1use kernel::*;
16use trilean::SKleene;
17use model::*;
18use logic::*;
19use propagators::cmp::x_eq_y::*;
20use propagation::events::*;
21use propagation::*;
22use gcollections::*;
23use concept::*;
24
25#[derive(Debug)]
26pub struct AllEqual<VStore>
27{
28 conj: Conjunction<VStore>,
29 vars: Vec<Var<VStore>>
30}
31
32impl<VStore> NotFormula<VStore> for AllEqual<VStore> where
33 VStore: Collection + 'static
34{
35 fn not(&self) -> Formula<VStore> {
36 self.conj.not()
37 }
38}
39
40impl<VStore, Domain, Bound> AllEqual<VStore> where
41 VStore: VStoreConcept<Item=Domain> + 'static,
42 Domain: IntDomain<Item=Bound> + 'static,
43 Bound: IntBound + 'static,
44{
45 pub fn new(vars: Vec<Var<VStore>>) -> Self {
47 assert!(vars.len() > 0,
48 "Variable array in `AllEqual` must be non-empty.");
49 let mut props = vec![];
50 for i in 0..vars.len()-1 {
51 let i_eq_j = Box::new(XEqY::new(vars[i].bclone(), vars[i+1].bclone())) as Formula<VStore>;
52 props.push(i_eq_j);
53 }
54 AllEqual {
55 conj: Conjunction::new(props),
56 vars: vars
57 }
58 }
59}
60
61impl<VStore> Clone for AllEqual<VStore> where
62 VStore: Collection
63{
64 fn clone(&self) -> Self {
65 AllEqual {
66 conj: self.conj.clone(),
67 vars: self.vars.iter().map(|v| v.bclone()).collect()
68 }
69 }
70}
71
72impl<VStore> DisplayStateful<Model> for AllEqual<VStore>
73{
74 fn display(&self, model: &Model) {
75 model.display_global("all_equal", &self.vars);
76 }
77}
78
79impl<VStore> Subsumption<VStore> for AllEqual<VStore>
80{
81 fn is_subsumed(&self, vstore: &VStore) -> SKleene {
82 self.conj.is_subsumed(vstore)
83 }
84}
85
86impl<VStore> Propagator<VStore> for AllEqual<VStore>
87{
88 fn propagate(&mut self, vstore: &mut VStore) -> bool {
89 self.conj.propagate(vstore)
90 }
91}
92
93impl<VStore> PropagatorDependencies<FDEvent> for AllEqual<VStore>
94{
95 fn dependencies(&self) -> Vec<(usize, FDEvent)> {
96 self.vars.iter().flat_map(|v| v.dependencies(FDEvent::Inner)).collect()
97 }
98}
99
100#[cfg(test)]
101mod test {
102 use super::*;
103 use trilean::SKleene::*;
104 use propagation::events::FDEvent::*;
105 use interval::interval::*;
106 use propagators::test::*;
107
108 #[test]
109 fn all_equal_test() {
110 let zero = (0,0).to_interval();
111 let one = (1,1).to_interval();
112 let two = (2,2).to_interval();
113 let dom0_1 = (0,1).to_interval();
114 let dom0_2 = (0,2).to_interval();
115 let dom0_3 = (0,3).to_interval();
116
117 all_equal_test_one(1, vec![zero,one,two], False, False, vec![], false);
118 all_equal_test_one(2, vec![zero,zero,two], False, False, vec![], false);
119 all_equal_test_one(3, vec![zero,zero,zero], True, True, vec![], true);
120 all_equal_test_one(4, vec![zero,dom0_3,dom0_3], Unknown, True, vec![(1, Assignment),(2, Assignment)], true);
121 all_equal_test_one(5, vec![dom0_1,dom0_3,dom0_3], Unknown, Unknown, vec![(1, Bound),(2, Bound)], true);
122 all_equal_test_one(6, vec![zero,one,dom0_2], False, False, vec![], false);
123 all_equal_test_one(7, vec![dom0_1,one,dom0_1], Unknown, True, vec![(0, Assignment), (2, Assignment)], true);
124 all_equal_test_one(8, vec![dom0_3], True, True, vec![], true);
125 all_equal_test_one(9, vec![one], True, True, vec![], true);
126 }
127
128 fn all_equal_test_one(test_num: u32, doms: Vec<Interval<i32>>,
129 before: SKleene, after: SKleene,
130 delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool)
131 {
132 nary_propagator_test(test_num, AllEqual::new, doms, before, after, delta_expected, propagate_success);
133 }
134}