pcp/propagators/cmp/
x_less_y.rs

1// Copyright 2015 Pierre Talbot (IRCAM)
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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    // False:
74    // x:    |--|
75    // y: |--|
76    //
77    // True:
78    // x: |--|
79    // y:     |--|
80    //
81    // Unknown: Everything else.
82
83    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}