1pub type Tuple = Vec<usize>;
5pub trait SkipIterator {
12 fn next(&mut self) -> Option<(Tuple, Vec<usize>)>;
14 fn skip(&mut self, min: Tuple);
17 fn arity(&self) -> usize;
19 fn len(&self) -> usize;
21}
22
23#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash)]
25pub struct Field {
26 pub clause: usize,
29 pub field: usize,
31}
32
33#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash)]
35pub enum Restrict {
36 Const(usize),
38 Unify(usize),
41}
42
43impl Restrict {
44 fn check(&self, candidate: &mut Vec<usize>, val: usize, order: &[usize]) -> bool {
47 match *self {
48 Restrict::Const(v) => v == val,
49 Restrict::Unify(var) => if order[var] < candidate.len() {
50 candidate[order[var]] == val
51 } else if order[var] == candidate.len() {
52 candidate.push(val);
53 true
54 } else {
55 panic!("Out of order variable numbering")
56 },
57 }
58 }
59 fn min(&self, candidate: &Vec<usize>, order: &[usize]) -> usize {
62 match *self {
63 Restrict::Const(v) => v,
64 Restrict::Unify(var) => {
65 let var_xlat = order[var];
66 if var_xlat < candidate.len() {
67 candidate[var_xlat]
68 } else {
69 0
70 }
71 }
72 }
73 }
74}
75
76pub struct Join<'a> {
78 order: Vec<usize>,
80 var_old_to_new: Vec<usize>,
82 indices: Vec<&'a mut SkipIterator>,
83 restricts: &'a Vec<Vec<Option<Restrict>>>,
84 candidate: Vec<usize>,
86 candidate_len: Vec<usize>,
88 fids: Vec<Vec<usize>>,
90}
91
92fn min_possible(
93 candidate: &Vec<usize>,
94 restricts: &Vec<Option<Restrict>>,
95 order: &[usize],
96) -> Vec<usize> {
97 let mut out = Vec::new();
98 for mr in restricts.iter() {
99 match *mr {
100 None => out.push(0),
101 Some(ref r) => out.push(r.min(candidate, order)),
102 }
103 }
104 out
105}
106
107fn reorder_indices(indices: &Vec<&mut SkipIterator>) -> Vec<usize> {
110 let mut lens: Vec<(usize, usize)> = indices.iter().map(|x| x.len()).enumerate().collect();
111 lens.sort_by_key(|x| x.1);
112 lens.into_iter().map(|x| x.0).collect()
113}
114
115fn reorder_vars(order: &[usize], restricts: &[Vec<Option<Restrict>>]) -> Vec<usize> {
117 let max_var_len: usize = restricts
118 .iter()
119 .flat_map(|pred| pred.iter().flat_map(|mr| mr.iter()))
120 .filter_map(|r| if let Restrict::Unify(var) = *r {
121 Some(var)
122 } else {
123 None
124 })
125 .max()
126 .map(|x| x + 1)
128 .unwrap_or(0);
130 let mut new_to_old = Vec::new();
131 let mut old_to_new = vec![0; max_var_len];
132 for idx in order {
133 for mr in &restricts[*idx] {
134 if let Some(Restrict::Unify(var)) = *mr {
135 if !new_to_old.contains(&var) {
136 old_to_new[var] = new_to_old.len();
137 new_to_old.push(var);
138 }
139 }
140 }
141 }
142 old_to_new
143}
144
145impl<'a> Join<'a> {
146 pub fn new(
157 indices: Vec<&'a mut SkipIterator>,
158 restricts: &'a Vec<Vec<Option<Restrict>>>,
159 ) -> Self {
160 let order = reorder_indices(&indices);
161 let var_old_to_new = reorder_vars(&order, restricts);
162 let mut join = Join {
163 order: order,
164 var_old_to_new: var_old_to_new,
165 indices: indices,
166 restricts: restricts,
167 candidate: Vec::new(),
168 candidate_len: Vec::new(),
169 fids: Vec::new(),
170 };
171 join.right();
173 join
174 }
175
176 fn left(&mut self) {
178 self.fids.pop();
179 self.fids.pop();
180 self.candidate.truncate(self.candidate_len.pop().unwrap());
181 self.candidate.truncate(self.candidate_len.pop().unwrap());
182 }
183
184 fn right(&mut self) {
187 let n = self.order[self.candidate_len.len()];
188 self.indices[n].skip(min_possible(
189 &self.candidate,
190 &self.restricts[n],
191 &self.var_old_to_new,
192 ));
193 }
194}
195impl<'a> Iterator for Join<'a> {
196 type Item = (Tuple, Vec<Vec<usize>>);
197 fn next(&mut self) -> Option<Self::Item> {
198 'states: loop {
205 let n = self.order[self.candidate_len.len()];
206 self.candidate_len.push(self.candidate.len());
207 match self.indices[n].next() {
208 Some((tup, fid)) => {
209 self.fids.push(fid);
210 for (f, v) in tup.iter().enumerate() {
211 if let Some(r) = self.restricts[n][f] {
212 if !r.check(&mut self.candidate, *v, &self.var_old_to_new) {
213 if n == self.order[0] {
214 self.candidate.truncate(self.candidate_len.pop().unwrap());
215 self.fids.pop();
216 return None;
217 }
218 if f == 0 {
219 self.left();
220 } else {
221 let mut min = min_possible(
222 &self.candidate,
223 &self.restricts[n],
224 &self.var_old_to_new,
225 );
226 if min[f] <= tup[f] {
227 if f != 0 {
229 min[f - 1] += 1;
230 } else {
231 self.left();
234 continue 'states;
235 }
236 }
237 self.indices[n].skip(min);
238 self.candidate.truncate(self.candidate_len.pop().unwrap());
239 self.fids.pop();
240 }
241 continue 'states;
242 }
243 }
244 }
245
246 if self.candidate_len.len() == self.indices.len() {
247 let mut out = Vec::new();
249 for idx in &self.var_old_to_new {
250 out.push(self.candidate[*idx])
251 }
252 let mut fids = self.fids.clone();
253 for (new, old) in self.order.iter().enumerate() {
254 fids[*old] = self.fids[new].clone();
255 }
256 self.candidate.truncate(self.candidate_len.pop().unwrap());
257 self.fids.pop();
258
259 return Some((out, fids));
260 }
261 self.right();
263 }
264 None => {
265 if n == self.order[0] {
266 self.candidate.truncate(self.candidate_len.pop().unwrap());
267 return None;
268 }
269 self.fids.push(vec![]);
271 self.left();
272 }
273 }
274 }
275 }
276}
277
278#[cfg(test)]
279mod test {
280 pub struct TrivialIterator {
285 payload: Vec<Vec<usize>>,
286 loc: usize,
287 }
288
289 impl TrivialIterator {
290 pub fn new(mut payload: Vec<Vec<usize>>) -> Self {
292 payload.sort();
293 payload.dedup();
294 TrivialIterator {
295 payload: payload,
296 loc: 0,
297 }
298 }
299 }
300
301 impl SkipIterator for TrivialIterator {
302 fn next(&mut self) -> Option<(Tuple, Vec<usize>)> {
303 if self.loc < self.payload.len() {
304 self.loc += 1;
305 Some((self.payload[self.loc - 1].clone(), vec![self.loc - 1]))
306 } else {
307 None
308 }
309 }
310 fn skip(&mut self, min: Tuple) {
311 self.loc = 0;
312 while (self.payload.len() > self.loc) && (self.payload[self.loc] < min) {
313 self.loc = self.loc + 1;
314 }
315 }
316 fn arity(&self) -> usize {
317 self.payload[0].len()
318 }
319 fn len(&self) -> usize {
320 self.payload.len()
321 }
322 }
323 use super::*;
324
325 #[test]
326 fn simple_join() {
327 use self::Restrict::*;
328 let mut p = TrivialIterator::new(vec![vec![0, 2, 3], vec![3, 2, 5], vec![4, 4, 4]]);
329 let mut q = TrivialIterator::new(vec![vec![1, 3], vec![2, 7], vec![3, 4], vec![8, 2]]);
330 let restricts = vec![
331 vec![Some(Unify(0)), Some(Unify(1)), None],
332 vec![Some(Unify(1)), Some(Const(7))],
333 ];
334 let its: Vec<&mut SkipIterator> = vec![&mut p, &mut q];
335 let mut join = Join::new(its, &restricts);
336 assert_eq!(join.next().map(|x| x.0), Some(vec![0, 2]));
337 assert_eq!(join.next().map(|x| x.0), Some(vec![3, 2]));
338 assert_eq!(join.next().map(|x| x.0), None);
339 assert_eq!(join.next().map(|x| x.0), None);
340 }
341
342 #[test]
343 fn reorder_vars_flip() {
344 use self::Restrict::*;
345 let order = &[0, 1];
346 let order_flip = &[1, 0];
347 let restrict_flip = vec![
348 vec![Some(Unify(0)), Some(Unify(1))],
349 vec![Some(Unify(1)), Some(Unify(0))],
350 ];
351 assert_eq!(&reorder_vars(order, &restrict_flip), &[0, 1]);
352 assert_eq!(&reorder_vars(order_flip, &restrict_flip), &[1, 0]);
353 }
354
355 #[test]
358 fn reorder_real() {
359 use self::Restrict::*;
360 let mut p = TrivialIterator::new(vec![vec![16, 16], vec![18, 18], vec![26, 26]]);
361 let mut q = TrivialIterator::new(vec![vec![16, 88], vec![18, 89]]);
362 let restricts = vec![
363 vec![Some(Unify(0)), Some(Unify(1))],
364 vec![Some(Unify(1)), Some(Unify(2))],
365 ];
366 let its: Vec<&mut SkipIterator> = vec![&mut p, &mut q];
367 let join = Join::new(its, &restricts);
368 assert_eq!(join.collect::<Vec<_>>().len(), 2)
369 }
370
371 #[test]
373 fn reorder_real2() {
374 use self::Restrict::*;
375 let mut p = TrivialIterator::new(vec![vec![16, 16], vec![16, 88]]);
376
377 let mut q = TrivialIterator::new(vec![vec![88, 15]]);
378 let restricts = vec![
379 vec![Some(Unify(0)), Some(Unify(1))],
380 vec![Some(Unify(1)), Some(Unify(2))],
381 ];
382 let its: Vec<&mut SkipIterator> = vec![&mut p, &mut q];
383 let join = Join::new(its, &restricts);
384 assert_eq!(join.collect::<Vec<_>>().len(), 1)
385 }
386}