pcp/propagators/
all_equal.rs

1// Copyright 2018 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 model::*;
18use logic::*;
19use propagators::cmp::x_eq_y::*;
20use propagation::events::*;
21use propagation::*;
22use gcollections::*;
23use concept::*;
24
25#[derive(Debug)]
26pub struct AllEqual<VStore>
27{
28  conj: Conjunction<VStore>,
29  vars: Vec<Var<VStore>>
30}
31
32impl<VStore> NotFormula<VStore> for AllEqual<VStore> where
33 VStore: Collection + 'static
34{
35  fn not(&self) -> Formula<VStore> {
36    self.conj.not()
37  }
38}
39
40impl<VStore, Domain, Bound> AllEqual<VStore> where
41  VStore: VStoreConcept<Item=Domain> + 'static,
42  Domain: IntDomain<Item=Bound> + 'static,
43  Bound: IntBound + 'static,
44{
45  /// Precondition: `vars.len() > 1`.
46  pub fn new(vars: Vec<Var<VStore>>) -> Self {
47    assert!(vars.len() > 0,
48      "Variable array in `AllEqual` must be non-empty.");
49    let mut props = vec![];
50    for i in 0..vars.len()-1 {
51      let i_eq_j = Box::new(XEqY::new(vars[i].bclone(), vars[i+1].bclone())) as Formula<VStore>;
52      props.push(i_eq_j);
53    }
54    AllEqual {
55      conj: Conjunction::new(props),
56      vars: vars
57    }
58  }
59}
60
61impl<VStore> Clone for AllEqual<VStore> where
62 VStore: Collection
63{
64  fn clone(&self) -> Self {
65    AllEqual {
66      conj: self.conj.clone(),
67      vars: self.vars.iter().map(|v| v.bclone()).collect()
68    }
69  }
70}
71
72impl<VStore> DisplayStateful<Model> for AllEqual<VStore>
73{
74  fn display(&self, model: &Model) {
75    model.display_global("all_equal", &self.vars);
76  }
77}
78
79impl<VStore> Subsumption<VStore> for AllEqual<VStore>
80{
81  fn is_subsumed(&self, vstore: &VStore) -> SKleene {
82    self.conj.is_subsumed(vstore)
83  }
84}
85
86impl<VStore> Propagator<VStore> for AllEqual<VStore>
87{
88  fn propagate(&mut self, vstore: &mut VStore) -> bool {
89    self.conj.propagate(vstore)
90  }
91}
92
93impl<VStore> PropagatorDependencies<FDEvent> for AllEqual<VStore>
94{
95  fn dependencies(&self) -> Vec<(usize, FDEvent)> {
96    self.vars.iter().flat_map(|v| v.dependencies(FDEvent::Inner)).collect()
97  }
98}
99
100#[cfg(test)]
101mod test {
102  use super::*;
103  use trilean::SKleene::*;
104  use propagation::events::FDEvent::*;
105  use interval::interval::*;
106  use propagators::test::*;
107
108  #[test]
109  fn all_equal_test() {
110    let zero = (0,0).to_interval();
111    let one = (1,1).to_interval();
112    let two = (2,2).to_interval();
113    let dom0_1 = (0,1).to_interval();
114    let dom0_2 = (0,2).to_interval();
115    let dom0_3 = (0,3).to_interval();
116
117    all_equal_test_one(1, vec![zero,one,two], False, False, vec![], false);
118    all_equal_test_one(2, vec![zero,zero,two], False, False, vec![], false);
119    all_equal_test_one(3, vec![zero,zero,zero], True, True, vec![], true);
120    all_equal_test_one(4, vec![zero,dom0_3,dom0_3], Unknown, True, vec![(1, Assignment),(2, Assignment)], true);
121    all_equal_test_one(5, vec![dom0_1,dom0_3,dom0_3], Unknown, Unknown, vec![(1, Bound),(2, Bound)], true);
122    all_equal_test_one(6, vec![zero,one,dom0_2], False, False, vec![], false);
123    all_equal_test_one(7, vec![dom0_1,one,dom0_1], Unknown, True, vec![(0, Assignment), (2, Assignment)], true);
124    all_equal_test_one(8, vec![dom0_3], True, True, vec![], true);
125    all_equal_test_one(9, vec![one], True, True, vec![], true);
126  }
127
128  fn all_equal_test_one(test_num: u32, doms: Vec<Interval<i32>>,
129    before: SKleene, after: SKleene,
130    delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool)
131  {
132    nary_propagator_test(test_num, AllEqual::new, doms, before, after, delta_expected, propagate_success);
133  }
134}