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