1use kernel::*;
16use trilean::SKleene;
17use trilean::SKleene::*;
18use model::*;
19use logic::*;
20use propagators::{x_geq_y};
21use propagation::*;
22use propagation::events::*;
23use gcollections::ops::*;
24use gcollections::*;
25use concept::*;
26
27#[derive(Debug)]
28pub struct XLessY<VStore>
29{
30 x: Var<VStore>,
31 y: Var<VStore>
32}
33
34impl<VStore> XLessY<VStore> {
35 pub fn new(x: Var<VStore>, y: Var<VStore>) -> XLessY<VStore> {
36 XLessY { x: x, y: y }
37 }
38}
39
40impl<VStore> Clone for XLessY<VStore> where
41 VStore: Collection
42{
43 fn clone(&self) -> Self {
44 XLessY::new(self.x.bclone(), self.y.bclone())
45 }
46}
47
48impl<VStore> DisplayStateful<Model> for XLessY<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 XLessY<VStore> where
58 VStore: VStoreConcept<Item=Domain> + 'static,
59 Domain: Collection<Item=Bound> + IntDomain,
60 Bound: IntBound
61{
62 fn not(&self) -> Formula<VStore> {
63 Box::new(x_geq_y(self.x.bclone(), self.y.bclone()))
64 }
65}
66
67impl<VStore, Dom, Bound> Subsumption<VStore> for XLessY<VStore> where
68 VStore: Collection<Item=Dom>,
69 Dom: Bounded<Item=Bound>,
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() {
87 False
88 }
89 else if x.upper() < y.lower() {
90 True
91 }
92 else {
93 Unknown
94 }
95 }
96}
97
98impl<VStore, Dom, Bound> Propagator<VStore> for XLessY<VStore> where
99 VStore: Collection<Item=Dom>,
100 Dom: Bounded<Item=Bound> + StrictShrinkLeft + StrictShrinkRight,
101 Bound: PartialOrd
102{
103 fn propagate(&mut self, store: &mut VStore) -> bool {
104 let x = self.x.read(store);
105 let y = self.y.read(store);
106 self.x.update(store, x.strict_shrink_right(y.upper())) &&
107 self.y.update(store, y.strict_shrink_left(x.lower()))
108 }
109}
110
111impl<VStore> PropagatorDependencies<FDEvent> for XLessY<VStore>
112{
113 fn dependencies(&self) -> Vec<(usize, FDEvent)> {
114 let mut deps = self.x.dependencies(FDEvent::Bound);
115 deps.append(&mut self.y.dependencies(FDEvent::Bound));
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_less_y_test() {
129 let dom0_10 = (0,10).to_interval();
130 let dom10_20 = (10,20).to_interval();
131 let dom10_11 = (10,11).to_interval();
132 let dom5_15 = (5,15).to_interval();
133 let dom11_20 = (11,20).to_interval();
134 let dom1_1 = (1,1).to_interval();
135
136 x_less_y_test_one(1, dom0_10, dom0_10, Unknown, Unknown, vec![(0, Bound), (1, Bound)], true);
137 x_less_y_test_one(2, dom0_10, dom10_20, Unknown, Unknown, vec![], true);
138 x_less_y_test_one(3, dom10_11, dom10_11, Unknown, True, vec![(0, Assignment), (1, Assignment)], true);
139 x_less_y_test_one(4, dom5_15, dom10_20, Unknown, Unknown, vec![], true);
140 x_less_y_test_one(5, dom5_15, dom0_10, Unknown, Unknown, vec![(0, Bound), (1, Bound)], true);
141 x_less_y_test_one(6, dom0_10, dom11_20, True, True, vec![], true);
142 x_less_y_test_one(7, dom11_20, dom0_10, False, False, vec![], false);
143 x_less_y_test_one(8, dom1_1, dom0_10, Unknown, True, vec![(1, Bound)], true);
144 }
145
146 fn x_less_y_test_one(test_num: u32, x: Interval<i32>, y: Interval<i32>,
147 before: SKleene, after: SKleene,
148 delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool)
149 {
150 binary_propagator_test(test_num, XLessY::new, x, y, before, after, delta_expected, propagate_success);
151 }
152}