poset/
antichain_iterator.rs1use crate::PartialOrderBehaviour;
2
3pub struct AntichainIterator<'a, 'b, T, F>
5where
6 F: PartialOrderBehaviour<Element = T>,
7{
8 vectors: Vec<Vec<&'a T>>,
9 indices: Vec<Option<usize>>,
10 finished: bool,
11 p_ord: &'b F,
12}
13
14impl<'a, 'b, T, F> AntichainIterator<'a, 'b, T, F>
15where
16 T: Clone,
17 F: PartialOrderBehaviour<Element = T>,
18{
19 pub fn new(vectors: Vec<Vec<&'a T>>, p_ord: &'b F) -> Self {
21 AntichainIterator {
22 indices: vec![None; vectors.len()],
23 vectors,
24 finished: false,
25 p_ord,
26 }
27 }
28
29 fn is_incomparable(&self, combination: &[&T]) -> bool {
30 for (i, item1) in combination.iter().enumerate() {
31 for item2 in combination.iter().skip(i + 1) {
32 if self.p_ord.cp(item1, item2) {
33 return false;
34 }
35 }
36 }
37 true
38 }
39
40 fn advance_indices(&mut self) -> bool {
41 for i in (0..self.indices.len()).rev() {
42 #[allow(clippy::match_on_vec_items)]
43 match self.indices[i] {
44 None => {
45 if !self.vectors[i].is_empty() {
46 self.indices[i] = Some(0);
47 return true;
48 }
49 }
50 Some(idx) if idx + 1 < self.vectors[i].len() => {
51 self.indices[i] = Some(idx + 1);
52 return true;
53 }
54 _ => {
55 self.indices[i] = None;
56 }
57 }
58 }
59 false
60 }
61}
62
63impl<'a, 'b, T, F> Iterator for AntichainIterator<'a, 'b, T, F>
64where
65 T: Clone,
66 F: PartialOrderBehaviour<Element = T>,
67{
68 type Item = Vec<T>;
69
70 fn next(&mut self) -> Option<Self::Item> {
71 while !self.finished {
72 let combination: Vec<&T> = self
73 .indices
74 .iter()
75 .enumerate()
76 .filter_map(|(i, &idx)| idx.and_then(|idx| self.vectors[i].get(idx)))
77 .copied()
78 .collect();
79
80 if !self.advance_indices() {
81 self.finished = true;
82 }
83
84 if self.is_incomparable(&combination) {
85 return Some(combination.into_iter().cloned().collect());
86 }
87 }
88
89 None
90 }
91}