1use kernel::*;
18use trilean::SKleene;
19use trilean::SKleene::*;
20use model::*;
21use propagation::Reactor;
22use propagation::Scheduler;
23use propagation::concept::*;
24use propagation::ops::*;
25use variable::ops::*;
26use gcollections::kind::*;
27use gcollections::ops::*;
28use std::ops::{Index, IndexMut};
29use bit_set::BitSet;
30
31#[derive(Debug)]
32pub struct Store<VStore, Event, Reactor, Scheduler>
33{
34 propagators: Vec<Box<dyn PropagatorConcept<VStore, Event> + 'static>>,
35 active: BitSet,
36 reactor: Reactor,
37 scheduler: Scheduler
38}
39
40impl<VStore, Event, R, S> Empty for Store<VStore, Event, R, S> where
41 Event: EventIndex,
42 R: Reactor,
43 S: Scheduler
44{
45 fn empty() -> Store<VStore, Event, R, S> {
46 Store {
47 propagators: vec![],
48 active: BitSet::new(),
49 reactor: Reactor::new(0,0),
50 scheduler: Scheduler::new(0)
51 }
52 }
53}
54
55impl<VStore, Event, R, S> Collection for Store<VStore, Event, R, S>
56{
57 type Item = Box<dyn PropagatorConcept<VStore, Event>>;
58}
59
60impl<VStore, Event, R, S> AssociativeCollection for Store<VStore, Event, R, S>
61{
62 type Location = usize;
63}
64
65impl<VStore, Event, R, S> Cardinality for Store<VStore, Event, R, S>
66{
67 type Size = usize;
68
69 fn size(&self) -> usize {
70 self.propagators.len()
71 }
72}
73
74impl<VStore, Event, R, S> Store<VStore, Event, R, S>
75{
76 fn display_constraints(&self, model: &Model, indexes: Vec<usize>, header: &str) {
77 let header_width = 15;
78 print!("{:>width$} ", header, width=header_width);
79 let mut idx = 0;
80 while idx < indexes.len() {
81 self.propagators[indexes[idx]].display(model);
82 if idx < indexes.len() - 1 {
83 print!(" /\\ \n{:>width$} ", "", width=header_width);
84 }
85 idx += 1;
86 }
87 println!();
88 }
89}
90
91impl<VStore, Event, R, S> DisplayStateful<(Model, VStore)> for Store<VStore, Event, R, S>
92{
93 fn display(&self, &(ref model, ref vstore): &(Model, VStore)) {
94 let mut subsumed = vec![];
95 let mut unknown = vec![];
96 let mut unsatisfiable = vec![];
97 for (i, p) in self.propagators.iter().enumerate() {
98 match p.is_subsumed(&vstore) {
99 False => unsatisfiable.push(i),
100 True => subsumed.push(i),
101 Unknown => unknown.push(i)
102 };
103 }
104 self.display_constraints(&model, unsatisfiable, "unsatisfiable:");
105 self.display_constraints(&model, subsumed, "subsumed:");
106 self.display_constraints(&model, unknown, "unknown:");
107 }
108}
109
110impl<VStore, Event, R, S> DisplayStateful<Model> for Store<VStore, Event, R, S>
111{
112 fn display(&self, model: &Model) {
113 let mut i = 0;
114 while i < self.propagators.len() {
115 self.propagators[i].display(model);
116 if i < self.propagators.len() - 1 {
117 print!(" /\\ ");
118 }
119 i += 1;
120 }
121 }
122}
123
124impl<VStore, Event, R, S> Store<VStore, Event, R, S> where
125 VStore: Cardinality<Size=usize> + DrainDelta<Event>,
126 Event: EventIndex,
127 R: Reactor + Cardinality<Size=usize>,
128 S: Scheduler
129{
130 fn prepare(&mut self, vstore: &VStore) {
131 self.init_reactor(vstore);
132 self.init_scheduler();
133 }
134
135 fn init_reactor(&mut self, vstore: &VStore) {
136 self.reactor = Reactor::new(vstore.size(), Event::size());
137 for p_idx in self.active.iter() {
138 let p_deps = self[p_idx].dependencies();
139 for (v, ev) in p_deps {
140 debug_assert!(v < vstore.size(),
141 "The propagator {:?} has a dependency to the variable {} which is not in the vstore (of size {}).\n\
142 Hint: you should not manually create `Identity` struct, if you do make sure they contain relevant index to the variable vstore.",
143 self[p_idx], v, vstore.size());
144 self.reactor.subscribe(v, ev, p_idx);
145 }
146 }
147 }
148
149 fn init_scheduler(&mut self) {
150 self.scheduler = Scheduler::new(self.propagators.len());
151 for p_idx in self.active.iter() {
152 self.scheduler.schedule(p_idx);
153 }
154 }
155
156 fn propagation_loop(&mut self, vstore: &mut VStore) -> bool {
157 let mut consistent = true;
158 while !self.scheduler.is_empty() && consistent {
159 while let Some(p_idx) = self.scheduler.pop() {
160 if !self.propagate_one(p_idx, vstore) {
161 consistent = false;
162 break;
163 }
164 self.react(vstore);
165 }
166 }
168 consistent
169 }
170
171 fn propagate_one(&mut self, p_idx: usize, vstore: &mut VStore) -> bool {
172 vstore.reset_changed();
173 let subsumed = self.propagator_consistency(p_idx, vstore);
174 match subsumed {
175 False => return false,
176 True => self.unlink_prop(p_idx),
177 Unknown => self.reschedule_prop(p_idx, vstore)
178 };
179 true
180 }
181
182 fn propagator_consistency(&mut self, p_idx: usize, vstore: &mut VStore) -> SKleene {
183 if self[p_idx].propagate(vstore) {
184 self[p_idx].is_subsumed(vstore)
185 } else {
186 False
187 }
188 }
189
190 fn reschedule_prop(&mut self, p_idx: usize, vstore: &mut VStore) {
191 if vstore.has_changed() {
192 self.scheduler.schedule(p_idx);
193 }
194 }
195
196 fn react(&mut self, vstore: &mut VStore) {
197 for (v, ev) in vstore.drain_delta() {
198 let reactions = self.reactor.react(v, ev);
199 for p in reactions.into_iter() {
200 self.scheduler.schedule(p);
201 }
202 }
203 }
204
205 fn unlink_prop(&mut self, p_idx: usize) {
206 self.active.remove(p_idx);
207 self.scheduler.unschedule(p_idx);
208 let deps = self[p_idx].dependencies();
209 for &(var, ev) in deps.iter() {
210 self.reactor.unsubscribe(var, ev, p_idx)
211 }
212 }
213}
214
215impl<VStore, Event, R, S> Index<usize> for Store<VStore, Event, R, S>
216{
217 type Output = Box<dyn PropagatorConcept<VStore, Event> + 'static>;
218 fn index<'a>(&'a self, index: usize) -> &'a Self::Output {
219 &self.propagators[index]
220 }
221}
222
223impl<VStore, Event, R, S> IndexMut<usize> for Store<VStore, Event, R, S>
224{
225 fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut Self::Output {
226 &mut self.propagators[index]
227 }
228}
229
230impl<VStore, Event, R, S> Alloc for Store<VStore, Event, R, S>
231{
232 fn alloc(&mut self, p: Self::Item) -> usize {
233 let idx = self.propagators.len();
234 self.propagators.push(p);
235 self.active.insert(idx);
236 idx
237 }
238}
239
240impl<VStore, Event, R, S> Subsumption<VStore> for Store<VStore, Event, R, S>
241{
242 fn is_subsumed(&self, vstore: &VStore) -> SKleene {
243 self.propagators.iter()
244 .fold(True, |x,p| x.and(p.is_subsumed(vstore)))
245 }
246}
247
248impl<VStore, Event, R, S> Consistency<VStore> for Store<VStore, Event, R, S> where
249 VStore: Cardinality<Size=usize> + DrainDelta<Event>,
250 Event: EventIndex,
251 R: Reactor + Cardinality<Size=usize>,
252 S: Scheduler
253{
254 fn consistency(&mut self, vstore: &mut VStore) -> SKleene {
255 self.prepare(vstore);
256 let consistent = self.propagation_loop(vstore);
257 if !consistent { False }
258 else if self.reactor.is_empty() { True }
259 else { Unknown }
260 }
261}
262
263impl<VStore, Event, R, S> Clone for Store<VStore, Event, R, S> where
264 Event: EventIndex,
265 R: Reactor,
266 S: Scheduler
267{
268 fn clone(&self) -> Self {
269 let mut cstore = Store::empty();
270 cstore.propagators = self.propagators.iter()
271 .map(|p| p.bclone())
272 .collect();
273 cstore.active = self.active.clone();
274 cstore
275 }
276}
277
278impl<VStore, Event, R, S> Freeze for Store<VStore, Event, R, S> where
279 Event: EventIndex,
280 R: Reactor + Clone,
281 S: Scheduler
282{
283 type FrozenState = FrozenStore<VStore, Event, R, S>;
284 fn freeze(self) -> Self::FrozenState
285 {
286 FrozenStore::new(self)
287 }
288}
289
290pub struct FrozenStore<VStore, Event, R, S> where
291 Event: EventIndex,
292 R: Reactor + Clone,
293 S: Scheduler
294{
295 cstore: Store<VStore, Event, R, S>
296}
297
298impl<VStore, Event, R, S> FrozenStore<VStore, Event, R, S> where
299 Event: EventIndex,
300 R: Reactor + Clone,
301 S: Scheduler
302{
303 fn new(cstore: Store<VStore, Event, R, S>) -> Self {
304 FrozenStore {
305 cstore: cstore
306 }
307 }
308}
309
310impl<VStore, Event, R, S> Snapshot for FrozenStore<VStore, Event, R, S> where
311 Event: EventIndex,
312 R: Reactor + Clone,
313 S: Scheduler
314{
315 type Label = (usize, BitSet);
316 type State = Store<VStore, Event, R, S>;
317
318 fn label(&mut self) -> Self::Label {
319 (self.cstore.propagators.len(), self.cstore.active.clone())
320 }
321
322 fn restore(mut self, label: Self::Label) -> Self::State {
323 self.cstore.propagators.truncate(label.0);
324 self.cstore.active = label.1;
325 self.cstore
326 }
327}
328
329