pcp/propagators/cmp/
x_eq_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::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    // False:
74    // |--|
75    //     |--|
76    //
77    // True:
78    // |-|
79    // |-|
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() && 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}