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}