1use trilean::SKleene;
16use kernel::*;
17use model::*;
18use logic::*;
19use propagators::XEqY;
20use propagation::*;
21use propagation::events::*;
22use gcollections::ops::*;
23use gcollections::*;
24use concept::*;
25
26#[derive(Debug)]
27pub struct XNeqY<VStore>
28{
29 x: Var<VStore>,
30 y: Var<VStore>
31}
32
33impl<VStore> XNeqY<VStore> {
34 pub fn new(x: Var<VStore>, y: Var<VStore>) -> Self {
35 XNeqY { x: x, y: y }
36 }
37}
38
39impl<VStore> Clone for XNeqY<VStore> where
40 VStore: Collection
41{
42 fn clone(&self) -> Self {
43 XNeqY::new(self.x.bclone(), self.y.bclone())
44 }
45}
46
47impl<VStore> DisplayStateful<Model> for XNeqY<VStore>
48{
49 fn display(&self, model: &Model) {
50 self.x.display(model);
51 print!(" != ");
52 self.y.display(model);
53 }
54}
55
56impl<VStore, Domain, Bound> NotFormula<VStore> for XNeqY<VStore> where
57 VStore: VStoreConcept<Item=Domain> + 'static,
58 Domain: IntDomain<Item=Bound> + 'static,
59 Bound: IntBound + 'static,
60{
61 fn not(&self) -> Formula<VStore> {
62 Box::new(XEqY::new(self.x.bclone(), self.y.bclone()))
63 }
64}
65
66impl<VStore> Subsumption<VStore> for XNeqY<VStore> where
67 VStore: Collection,
68 XEqY<VStore>: Subsumption<VStore>
69{
70 fn is_subsumed(&self, store: &VStore) -> SKleene {
71 !XEqY::new(self.x.bclone(), self.y.bclone()).is_subsumed(store)
72 }
73}
74
75impl<VStore, Dom, Bound> Propagator<VStore> for XNeqY<VStore> where
76 VStore: Collection<Item=Dom>,
77 Dom: Bounded<Item=Bound> + Cardinality + Difference<Bound, Output=Dom>,
78 Bound: PartialOrd
79{
80 fn propagate(&mut self, store: &mut VStore) -> bool {
81 let x = self.x.read(store);
82 let y = self.y.read(store);
83
84 if x.is_singleton() {
85 self.y.update(store, y.difference(&x.lower()))
86 }
87 else if y.is_singleton() {
88 self.x.update(store, x.difference(&y.lower()))
89 }
90 else {
91 true
92 }
93 }
94}
95
96impl<VStore> PropagatorDependencies<FDEvent> for XNeqY<VStore> where
97 VStore: Collection,
98 XEqY<VStore>: PropagatorDependencies<FDEvent>
99{
100 fn dependencies(&self) -> Vec<(usize, FDEvent)> {
101 XEqY::new(self.x.bclone(), self.y.bclone()).dependencies()
102 }
103}
104
105#[cfg(test)]
106mod test {
107 use super::*;
108 use trilean::SKleene::*;
109 use propagation::events::FDEvent::*;
110 use interval::interval::*;
111 use propagators::test::*;
112
113 #[test]
114 fn x_neq_y_test() {
115 let dom0_10 = (0,10).to_interval();
116 let dom10_20 = (10,20).to_interval();
117 let dom5_15 = (5,15).to_interval();
118 let dom11_20 = (11,20).to_interval();
119 let one = (1,1).to_interval();
120 let zero = (0,0).to_interval();
121 let ten = (10,10).to_interval();
122
123 x_neq_y_test_one(1, dom0_10, dom0_10, Unknown, Unknown, vec![], true);
124 x_neq_y_test_one(2, dom0_10, dom10_20, Unknown, Unknown, vec![], true);
125 x_neq_y_test_one(3, dom5_15, dom10_20, Unknown, Unknown, vec![], true);
126 x_neq_y_test_one(4, dom0_10, dom11_20, True, True, vec![], true);
127 x_neq_y_test_one(5, one, dom0_10, Unknown, Unknown, vec![], true);
128 x_neq_y_test_one(6, zero, dom0_10, Unknown, True, vec![(1, Bound)], true);
129 x_neq_y_test_one(7, ten, dom0_10, Unknown, True, vec![(1, Bound)], true);
130 x_neq_y_test_one(8, one, one, False, False, vec![], false);
131 x_neq_y_test_one(9, zero, one, True, True, vec![], true);
132 }
133
134 fn x_neq_y_test_one(test_num: u32, x: Interval<i32>, y: Interval<i32>,
135 before: SKleene, after: SKleene,
136 delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool)
137 {
138 binary_propagator_test(test_num, XNeqY::new, x, y, before, after, delta_expected, propagate_success);
139 }
140}