1use kernel::*;
16use search::branching::*;
17use search::branching::branch::*;
18use search::space::*;
19use term::*;
20use propagators::cmp::*;
21use concept::*;
22
23pub struct BinarySplit;
24
25impl<VStore, CStore, R, Domain, Bound> Distributor<Space<VStore, CStore, R>, Bound> for BinarySplit where
26 VStore: VStoreConcept<Item=Domain, Location=Identity<Domain>, Output=Domain> + 'static,
27 CStore: IntCStore<VStore>,
28 Domain: IntDomain<Item=Bound> + 'static,
29 Bound: IntBound + Copy + 'static,
30 R: FreezeSpace<VStore, CStore> + Snapshot<State=Space<VStore, CStore, R>>
31{
32 fn distribute(&mut self, space: Space<VStore, CStore, R>, var_idx: usize, val: Bound) ->
33 (<Space<VStore, CStore, R> as Freeze>::FrozenState, Vec<Branch<Space<VStore, CStore, R>>>)
34 {
35 Branch::distribute(space,
37 vec![
38 Box::new(move |space: &mut Space<VStore, CStore, R>| {
39 let x = Box::new(Identity::<Domain>::new(var_idx)) as Var<VStore>;
40 let v = Box::new(Constant::new(val)) as Var<VStore>;
41 let x_less_v = x_leq_y::<_,_,Bound>(x.bclone(), v.bclone());
42 space.cstore.alloc(Box::new(x_less_v));
43 }),
44 Box::new(move |space: &mut Space<VStore, CStore, R>| {
45 let x = Box::new(Identity::<Domain>::new(var_idx)) as Var<VStore>;
46 let v = Box::new(Constant::new(val)) as Var<VStore>;
47 let x_geq_v = x_greater_y(x, v);
48 space.cstore.alloc(Box::new(x_geq_v));
49 })
50 ]
51 )
52 }
53}
54
55#[cfg(test)]
56pub mod test {
57 use super::*;
58 use search::branching::Distributor;
59 use search::branching::MiddleVal;
60 use term::ops::*;
61 use trilean::SKleene::*;
62 use search::*;
63 use interval::interval_set::*;
64 use interval::ops::Range;
65 use gcollections::ops::*;
66
67 type Domain = IntervalSet<i32>;
68
69 pub fn test_distributor<D, Val>(mut distributor: D, mut val_selection: Val, distribution_index: usize,
70 root: Vec<(i32, i32)>, children: Vec<(i32, i32)>) where
71 Val: ValSelection<Domain>,
72 D: Distributor<FDSpace, i32>
73 {
74 let mut space = FDSpace::empty();
75
76 for (l,u) in root {
77 space.vstore.alloc(IntervalSet::new(l,u));
78 }
79
80 let x = Identity::<Domain>::new(distribution_index);
81 let d = x.read(&space.vstore);
82 let b = val_selection.select(d);
83
84 let (mut immutable_state, branches) = distributor.distribute(space, distribution_index, b);
85
86 assert_eq!(branches.len(), children.len());
87
88 for (branch, (l,u)) in branches.into_iter().zip(children.into_iter()) {
89 space = branch.commit(immutable_state);
90 assert_eq!(space.consistency(), True);
91 let split_dom = x.read(&space.vstore);
92 assert_eq!(split_dom, IntervalSet::new(l,u));
93 immutable_state = space.freeze();
94 }
95 }
96
97 #[test]
98 fn binary_split_distribution() {
99 let vars = vec![(1,10),(2,4),(1,2)];
100 test_distributor(BinarySplit, MiddleVal, 0,
101 vars.clone(),
102 vec![(1,5),(6,10)]
103 );
104 test_distributor(BinarySplit, MiddleVal, 1,
105 vars.clone(),
106 vec![(2,3),(4,4)]
107 );
108 test_distributor(BinarySplit, MiddleVal, 2,
109 vars.clone(),
110 vec![(1,1),(2,2)]
111 );
112 }
113
114 #[test]
115 #[should_panic]
116 fn binary_split_impossible_distribution() {
117 test_distributor(BinarySplit, MiddleVal, 0,
118 vec![(1,1)],
119 vec![]
120 );
121 }
122
123 #[test]
124 #[should_panic]
125 fn binary_split_impossible_distribution_2() {
126 test_distributor(BinarySplit, MiddleVal, 2,
127 vec![(1,5),(2,4),(4,4)],
128 vec![]
129 );
130 }
131}