pcp/propagators/cmp/
x_neq_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 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}