1use kernel::*;
16use search::space::*;
17use search::search_tree_visitor::*;
18use concept::*;
19
20pub struct StopNode<C> {
21 child: C,
22 limit: usize,
23 nodes_explored: usize
24}
25
26impl<C> StopNode<C> {
27 pub fn new(limit: usize, child: C) -> StopNode<C> {
28 StopNode {
29 child: child,
30 limit: limit,
31 nodes_explored: 0
32 }
33 }
34}
35
36impl<VStore, CStore, R, C> SearchTreeVisitor<Space<VStore, CStore, R>> for StopNode<C> where
37 VStore: VStoreConcept,
38 CStore: IntCStore<VStore>,
39 C: SearchTreeVisitor<Space<VStore, CStore, R>>,
40 R: FreezeSpace<VStore, CStore> + Snapshot<State=Space<VStore, CStore, R>>
41{
42 fn start(&mut self, root: &Space<VStore, CStore, R>) {
43 self.child.start(root);
44 }
45
46 fn enter(&mut self, current: Space<VStore, CStore, R>)
47 -> (<Space<VStore, CStore, R> as Freeze>::FrozenState, Status<Space<VStore, CStore, R>>)
48 {
49 let (space, status) = self.child.enter(current);
50 self.nodes_explored += 1;
51 if self.nodes_explored >= self.limit {
53 (space, Status::EndOfSearch)
54 }
55 else {
56 (space, status)
57 }
58 }
59}
60
61#[cfg(test)]
62mod test {
63 use super::*;
64 use search::test::*;
65 use search::FDSpace;
66 use search::monitor::*;
67 use search::statistics::*;
68 use search::engine::one_solution::*;
69 use search::engine::all_solution::*;
70 use search::propagation::*;
71 use search::branching::binary_split::*;
72 use search::branching::brancher::*;
73 use search::branching::first_smallest_var::*;
74 use search::branching::middle_val::*;
75 use gcollections::VectorStack;
76 use gcollections::ops::*;
77
78 #[test]
79 fn test_stop() {
80 let n = 6;
81 let mut space = FDSpace::empty();
82 nqueens(n, &mut space);
83
84 let nodes_limit = 10;
85 let mut statistics = Statistics::new();
86 {
87 let mut search: AllSolution<OneSolution<_, VectorStack<_>, FDSpace>>
88 =
89 AllSolution::new(OneSolution::new(
90 Monitor::new(&mut statistics, StopNode::new(nodes_limit,
91 Propagation::new(Brancher::new(FirstSmallestVar, MiddleVal, BinarySplit))))));
92 search.start(&space);
93 let (_, status) = search.enter(space);
94 assert_eq!(status, Status::EndOfSearch);
95 }
96 assert_eq!(statistics.num_nodes, nodes_limit);
97 }
98}