pcp/propagators/
mod.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
15//! Propagators are implementations of constraints, a single constraint can be realized by different propagators.
16//!
17//! We keep the propagator implementations generic over domains implementing specific operations (e.g. intersection or union). Propagators are also implemented to work on variable views, you can always obtain a view from a variable by using the `Identity` view.
18
19pub mod cmp;
20pub mod distinct;
21pub mod cumulative;
22pub mod all_equal;
23
24pub use propagators::cmp::*;
25pub use propagators::distinct::*;
26pub use propagators::all_equal::*;
27
28#[cfg(test)]
29pub mod test
30{
31  use trilean::SKleene;
32  use propagation::*;
33  use gcollections::ops::*;
34  use concept::*;
35  use variable::VStoreFD;
36  use propagation::events::*;
37  use interval::interval::*;
38  use variable::store::test::consume_delta;
39
40  // fn error_msg<T: Debug, VStore>(test_num: u32, msg: &str,
41  //   prop: &Formula<VStore>, before: &T, after: &T) -> String
42  // {
43  //   format!("Test {}: {}\n\
44  //            \tPropagator {:?}\n\
45  //            \tBefore: {:?}\n\
46  //            \tAfter: {:?}",
47  //            test_num, msg, prop, before, after)
48  // }
49
50  // fn status_inclusion(s1: SKleene, s2: SKleene) -> bool {
51  //   match s1 {
52  //     True => s2 == True,
53  //     False => s2 == False,
54  //     Unknown => true
55  //   }
56  // }
57
58  // /// contracting: p(d) ⊆ d for any domain d
59  // fn contracting<VStore>(test_num: u32, vstore: &mut VStore, mut propagator: Formula<VStore>) where
60  //  VStore: VStoreConcept + Clone + Subset
61  // {
62  //   let d1 = vstore.clone();
63  //   let d1_status = propagator.is_subsumed(vstore);
64  //   let prop_status = propagator.propagate(vstore);
65  //   let d2_status = propagator.is_subsumed(vstore);
66  //   let err1 = error_msg(test_num, "Propagator is not contracting.", &propagator, &d1, &vstore);
67  //   assert!(vstore.is_subset(&d1), err1);
68  //   let err2 = error_msg(test_num, "Propagator status is not monotonic.", &propagator, &d1_status, &d2_status);
69  //   assert!(status_inclusion(d1_status, d2_status), err2);
70  //   if prop_status == false {
71  //     let err3 = error_msg(test_num, "Propagator is not monotonic: the propagation failed but the status is not `False`.",
72  //       &propagator, &d1_status, &d2_status);
73  //     assert!(d2_status == False, err3);
74  //   }
75  // }
76
77  // /// A propagator p is idempotent if and only if for all domains d, p(p(d)) = p(d).
78  // fn idempotent<VStore>(test_num: u32, vstore: &mut VStore, mut propagator: Formula<VStore>) where
79  //  VStore: VStoreConcept + Clone + Eq
80  // {
81  //   let prop_status = propagator.propagate(vstore);
82  //   let d1 = vstore.clone();
83  //   let d1_status = propagator.is_subsumed(vstore);
84  //   let prop_status2 = propagator.propagate(vstore);
85  //   let d2_status = propagator.is_subsumed(vstore);
86  //   let err1 = error_msg(test_num, "Propagator is not idempotent.", &propagator, &d1, &vstore);
87  //   assert!(d1 == vstore.clone() && prop_status == prop_status2 && d1_status == d2_status, err1);
88  // }
89
90  // // /// It is monotonic if and only if for any two domains d1 and d2, d1 ⊆ d2 implies p(d1) ⊆ p(d2).
91  // // fn monotonic<VStore>(test_num: u32, vstore1: &mut VStore, vstore2: &mut VStore,
92  // //   mut propagator: Formula<VStore>) where
93  // //  VStore: VStoreConcept + Clone
94  // // {}
95
96  // // /// sound: for any domain d ∈ Dom and any assignment a ∈ Asn, if {a} ⊆ d, then p({a}) ⊆ p(d)
97  // // fn sound<VStore>(test_num: u32, assignment: &mut VStore, vstore: &mut VStore,
98  // //   mut propagator: Formula<VStore>) where
99  // //  VStore: VStoreConcept + Clone
100  // // {}
101
102  // pub fn test_properties<VStore>(test_num: u32, vstore: &mut VStore, mut propagator: Formula<VStore>) where
103  //  VStore: VStoreConcept + Clone
104  // {
105  //   contracting(test_num, &mut vstore.clone(), propagator.bclone());
106  //   idempotent(test_num, &mut vstore.clone(), propagator.bclone());
107  // }
108
109  pub type FDVar = Var<VStoreFD>;
110
111  pub fn test_propagation<P>(test_num: u32, mut prop: P, vstore: &mut VStoreFD,
112    before: SKleene, after: SKleene,
113    delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool) where
114   P: PropagatorConcept<VStoreFD, FDEvent>
115  {
116    // test_properties(test_num, vstore, prop.bclone());
117    println!("Test number {}", test_num);
118    assert_eq!(prop.is_subsumed(vstore), before);
119    assert_eq!(prop.propagate(vstore), propagate_success);
120    if propagate_success {
121      consume_delta(vstore, delta_expected);
122    }
123    assert_eq!(prop.is_subsumed(vstore), after);
124  }
125
126  pub fn binary_propagator_test<P, FnProp>(test_num: u32, make_prop: FnProp, x: Interval<i32>, y: Interval<i32>,
127    before: SKleene, after: SKleene,
128    delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool) where
129   P: PropagatorConcept<VStoreFD, FDEvent>,
130   FnProp: FnOnce(FDVar, FDVar) -> P
131  {
132    let mut vstore = VStoreFD::empty();
133    let x = Box::new(vstore.alloc(x)) as Var<VStoreFD>;
134    let y = Box::new(vstore.alloc(y)) as Var<VStoreFD>;
135    let propagator = make_prop(x, y);
136    test_propagation(test_num, propagator, &mut vstore, before, after, delta_expected, propagate_success);
137  }
138
139  pub fn trinary_propagator_test<P, FnProp>(test_num: u32, make_prop: FnProp,
140    x: Interval<i32>, y: Interval<i32>, z: Interval<i32>,
141    before: SKleene, after: SKleene,
142    delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool) where
143   P: PropagatorConcept<VStoreFD, FDEvent>,
144   FnProp: FnOnce(FDVar, FDVar, FDVar) -> P
145  {
146    let mut vstore = VStoreFD::empty();
147    let x = Box::new(vstore.alloc(x)) as Var<VStoreFD>;
148    let y = Box::new(vstore.alloc(y)) as Var<VStoreFD>;
149    let z = Box::new(vstore.alloc(z)) as Var<VStoreFD>;
150    let propagator = make_prop(x, y, z);
151    test_propagation(test_num, propagator, &mut vstore, before, after, delta_expected, propagate_success);
152  }
153
154  pub fn nary_propagator_test<P, FnProp>(test_num: u32, make_prop: FnProp, doms: Vec<Interval<i32>>,
155    before: SKleene, after: SKleene,
156    delta_expected: Vec<(usize, FDEvent)>, propagate_success: bool) where
157   P: PropagatorConcept<VStoreFD, FDEvent>,
158   FnProp: FnOnce(Vec<FDVar>) -> P
159  {
160    let mut vstore = VStoreFD::empty();
161    let vars = doms.into_iter()
162      .map(|d| Box::new(vstore.alloc(d)) as Var<VStoreFD>)
163      .collect();
164    let propagator = make_prop(vars);
165    test_propagation(test_num, propagator, &mut vstore, before, after, delta_expected, propagate_success);
166  }
167}