math/iter/
common_refinement_zip.rs

1//! If part of the iterators outputs are disjoint increasing integer intervals,
2//! then the iterators can be zipped together and the iteration can proceeds at
3//! the granularity of the common refinements of all the integer intervals.
4
5use crate::{
6    interval::{traits::Interval, IntInterval},
7    set::traits::Intersect,
8};
9use num::{Integer, Num, ToPrimitive};
10use std::{
11    collections::BTreeSet,
12    marker::{PhantomData, Sized},
13};
14
15pub trait CommonRefinementZip<B, X, P, V>
16where
17    B: Copy + Num + Ord,
18    Self: Iterator<Item = X> + Sized,
19    P: Clone + Interval<B> + for<'b> Intersect<&'b P, Option<P>>, {
20    fn get_interval_value_extractor(
21        &self,
22    ) -> Box<dyn Fn(<Self as Iterator>::Item) -> (P, V)>;
23
24    fn common_refinement_zip(
25        mut self,
26        mut other: Self,
27    ) -> CommonRefinementZipped<B, Self, X, P, V> {
28        let extractor = self.get_interval_value_extractor();
29        let mut intervals = Vec::new();
30        let mut values = Vec::new();
31        match self.next() {
32            None => {
33                intervals.push(None);
34                values.push(None);
35            }
36            Some(x) => {
37                let (interval, value) = extractor(x);
38                intervals.push(Some(interval));
39                values.push(Some(value));
40            }
41        }
42        match other.next() {
43            None => {
44                intervals.push(None);
45                values.push(None);
46            }
47            Some(x) => {
48                let (interval, value) = extractor(x);
49                intervals.push(Some(interval));
50                values.push(Some(value));
51            }
52        }
53        CommonRefinementZipped {
54            iters: vec![self, other],
55            intervals,
56            values,
57            extractor,
58            phantom: PhantomData,
59        }
60    }
61
62    fn into_common_refinement_zipped(
63        mut self,
64    ) -> CommonRefinementZipped<B, Self, X, P, V> {
65        let extractor = self.get_interval_value_extractor();
66        let mut intervals = Vec::new();
67        let mut values = Vec::new();
68        match self.next() {
69            None => {
70                intervals.push(None);
71                values.push(None);
72            }
73            Some(x) => {
74                let (interval, value) = extractor(x);
75                intervals.push(Some(interval));
76                values.push(Some(value));
77            }
78        }
79        CommonRefinementZipped {
80            iters: vec![self],
81            intervals,
82            values,
83            extractor,
84            phantom: PhantomData,
85        }
86    }
87}
88
89/// # Example
90/// ```
91/// use math::{
92///     interval::{traits::Interval, IntInterval},
93///     iter::CommonRefinementZip,
94/// };
95/// use std::collections::BTreeMap;
96///
97/// let m1: BTreeMap<IntInterval<usize>, i32> =
98///     vec![(IntInterval::new(0, 5), 5), (IntInterval::new(8, 10), 2)]
99///         .into_iter()
100///         .collect();
101///
102/// let m2: BTreeMap<IntInterval<usize>, i32> =
103///     vec![(IntInterval::new(2, 4), 8), (IntInterval::new(12, 13), 9)]
104///         .into_iter()
105///         .collect();
106///
107/// let mut iter = m1.iter().common_refinement_zip(m2.iter());
108/// assert_eq!(
109///     Some((IntInterval::new(0, 1), vec![Some(5), None])),
110///     iter.next()
111/// );
112/// assert_eq!(
113///     Some((IntInterval::new(2, 4), vec![Some(5), Some(8)])),
114///     iter.next()
115/// );
116/// assert_eq!(
117///     Some((IntInterval::new(5, 5), vec![Some(5), None])),
118///     iter.next()
119/// );
120/// assert_eq!(
121///     Some((IntInterval::new(8, 10), vec![Some(2), None])),
122///     iter.next()
123/// );
124/// assert_eq!(
125///     Some((IntInterval::new(12, 13), vec![None, Some(9)])),
126///     iter.next()
127/// );
128/// assert_eq!(None, iter.next());
129/// ```
130impl<'a, V, B: Integer + Copy + ToPrimitive>
131    CommonRefinementZip<B, (&'a IntInterval<B>, &'a V), IntInterval<B>, V>
132    for std::collections::btree_map::Iter<'a, IntInterval<B>, V>
133where
134    B: 'a,
135    V: 'a + Clone,
136{
137    fn get_interval_value_extractor(
138        &self,
139    ) -> Box<dyn Fn(<Self as Iterator>::Item) -> (IntInterval<B>, V)> {
140        Box::new(|item| ((*item.0).clone(), (*item.1).clone()))
141    }
142}
143
144impl<'a, V, B: Integer + Copy + ToPrimitive>
145    CommonRefinementZip<B, (IntInterval<B>, V), IntInterval<B>, V>
146    for std::collections::btree_map::IntoIter<IntInterval<B>, V>
147where
148    B: 'a,
149{
150    fn get_interval_value_extractor(
151        &self,
152    ) -> Box<dyn Fn(<Self as Iterator>::Item) -> (IntInterval<B>, V)> {
153        Box::new(|item| (item.0, item.1))
154    }
155}
156
157/// # Iterator Algorithm Description
158/// Given a list of iterators, a list of the current minimum interval for each
159/// iterator will be maintained together with their associated values. Then, at
160/// each pass the smallest minimum common refinement of the current intervals is
161/// subtracted from each interval. A list of values will be returned along with
162/// the common refinement. Each value will be the value associated with the
163/// iterated interval if the common refinement has a non-empty intersection with
164/// the corresponding interval, and `None` otherwise.
165///
166/// If an interval becomes empty after the subtraction, the corresponding
167/// iterator will be called to replace the interval with the next interval,
168/// together with the associated values.
169///
170/// # Fields
171/// * `iters`: the list of zipped iterators.
172/// * `intervals`: the intervals assocaited with each iterator for the current
173///   pass.
174/// * `values`: the values associated with each iterator for the current pass.
175/// * `extractor`: a function that extracts a tuple of (interval, value) from
176///   each of the items yielded from the iterators.
177pub struct CommonRefinementZipped<B, I, X, P, V>
178where
179    B: Copy + Num + Ord,
180    I: Iterator<Item = X> + Sized,
181    P: Clone + Interval<B> + for<'b> Intersect<&'b P, Option<P>>, {
182    iters: Vec<I>,
183    intervals: Vec<Option<P>>,
184    values: Vec<Option<V>>,
185    extractor: Box<dyn Fn(X) -> (P, V)>,
186    phantom: PhantomData<B>,
187}
188
189impl<B, I, X, P, V> Iterator for CommonRefinementZipped<B, I, X, P, V>
190where
191    B: Copy + Num + Ord,
192    I: Iterator<Item = X> + Sized,
193    P: Clone + Interval<B> + for<'b> Intersect<&'b P, Option<P>>,
194    V: Clone,
195{
196    type Item = (P, Vec<Option<V>>);
197
198    fn next(&mut self) -> Option<Self::Item> {
199        let starts: BTreeSet<B> = self
200            .intervals
201            .iter()
202            .filter_map(|i| i.clone().and_then(|i| Some(i.get_start())))
203            .collect();
204
205        let ends: BTreeSet<B> = self
206            .intervals
207            .iter()
208            .filter_map(|i| i.clone().and_then(|i| Some(i.get_end())))
209            .collect();
210
211        let mut starts_iter = starts.iter();
212        let min_start = match starts_iter.next() {
213            // if all intervals are empty, it means that all the iterators have
214            // been exhausted
215            None => return None,
216            Some(&a) => a,
217        };
218        let second_min_start = starts_iter.next();
219        let min_end = *ends.iter().next().unwrap();
220
221        let min_refinement = match second_min_start {
222            Some(&second_min_start) => {
223                if second_min_start <= min_end {
224                    P::from_boundaries(min_start, second_min_start - B::one())
225                } else {
226                    P::from_boundaries(min_start, min_end)
227                }
228            }
229            None => P::from_boundaries(min_start, min_end),
230        };
231
232        let mut refinement_values = Vec::new();
233        for ((interval, iter), v) in self
234            .intervals
235            .iter_mut()
236            .zip(self.iters.iter_mut())
237            .zip(self.values.iter_mut())
238        {
239            match interval {
240                Some(i) => {
241                    if i.has_non_empty_intersection_with(&min_refinement) {
242                        refinement_values.push((*v).clone());
243
244                        // subtract the min_refinement from the interval
245                        // min_start <= i.get_start() <= min_end <= i.get_end()
246                        let remainder = P::from_boundaries(
247                            min_refinement.get_end() + B::one(),
248                            i.get_end(),
249                        );
250                        if remainder.is_empty() {
251                            match iter.next() {
252                                None => {
253                                    *interval = None;
254                                    *v = None;
255                                }
256                                Some(x) => {
257                                    let (new_interval, new_val) =
258                                        (self.extractor)(x);
259                                    *interval = Some(new_interval);
260                                    *v = Some(new_val);
261                                }
262                            }
263                        } else {
264                            *interval = Some(remainder);
265                        }
266                    } else {
267                        refinement_values.push(None);
268                    }
269                }
270                None => {
271                    refinement_values.push(None);
272                }
273            }
274        }
275        Some((min_refinement, refinement_values))
276    }
277}
278
279impl<B, I, X, P, V> CommonRefinementZipped<B, I, X, P, V>
280where
281    B: Copy + Num + Ord,
282    I: Iterator<Item = X> + Sized,
283    P: Clone + Interval<B> + for<'b> Intersect<&'b P, Option<P>>,
284{
285    /// ```
286    /// use math::{
287    ///     interval::{traits::Interval, IntInterval},
288    ///     iter::CommonRefinementZip,
289    /// };
290    /// use std::collections::BTreeMap;
291    ///
292    /// let m1: BTreeMap<IntInterval<usize>, i32> =
293    ///     vec![(IntInterval::new(0, 10), 5), (IntInterval::new(16, 17), 21)]
294    ///         .into_iter()
295    ///         .collect();
296    ///
297    /// let m2: BTreeMap<IntInterval<usize>, i32> =
298    ///     vec![(IntInterval::new(2, 3), 8), (IntInterval::new(12, 20), 9)]
299    ///         .into_iter()
300    ///         .collect();
301    ///
302    /// let m3: BTreeMap<IntInterval<usize>, i32> = vec![
303    ///     (IntInterval::new(2, 4), 7),
304    ///     (IntInterval::new(9, 10), -1),
305    ///     (IntInterval::new(15, 20), 0),
306    /// ]
307    /// .into_iter()
308    /// .collect();
309    ///
310    /// let mut iter = m1
311    ///     .iter()
312    ///     .common_refinement_zip(m2.iter())
313    ///     .common_refinement_flat_zip(m3.iter());
314    ///
315    /// assert_eq!(
316    ///     Some((IntInterval::new(0, 1), vec![Some(5), None, None])),
317    ///     iter.next()
318    /// );
319    /// assert_eq!(
320    ///     Some((IntInterval::new(2, 3), vec![Some(5), Some(8), Some(7)])),
321    ///     iter.next()
322    /// );
323    /// assert_eq!(
324    ///     Some((IntInterval::new(4, 4), vec![Some(5), None, Some(7)])),
325    ///     iter.next()
326    /// );
327    /// assert_eq!(
328    ///     Some((IntInterval::new(5, 8), vec![Some(5), None, None])),
329    ///     iter.next()
330    /// );
331    /// assert_eq!(
332    ///     Some((IntInterval::new(9, 10), vec![Some(5), None, Some(-1)])),
333    ///     iter.next()
334    /// );
335    /// assert_eq!(
336    ///     Some((IntInterval::new(12, 14), vec![None, Some(9), None])),
337    ///     iter.next()
338    /// );
339    /// assert_eq!(
340    ///     Some((IntInterval::new(15, 15), vec![None, Some(9), Some(0)])),
341    ///     iter.next()
342    /// );
343    /// assert_eq!(
344    ///     Some((IntInterval::new(16, 17), vec![Some(21), Some(9), Some(0)])),
345    ///     iter.next()
346    /// );
347    /// assert_eq!(
348    ///     Some((IntInterval::new(18, 20), vec![None, Some(9), Some(0)])),
349    ///     iter.next()
350    /// );
351    /// assert_eq!(None, iter.next());
352    /// ```
353    pub fn common_refinement_flat_zip(
354        mut self,
355        mut other: I,
356    ) -> CommonRefinementZipped<B, I, X, P, V>
357    where
358        I: Iterator<Item = X> + Sized, {
359        match other.next() {
360            None => {
361                self.intervals.push(None);
362                self.values.push(None);
363            }
364            Some(x) => {
365                let (i, v) = (self.extractor)(x);
366                self.intervals.push(Some(i.clone()));
367                self.values.push(Some(v));
368            }
369        }
370        self.iters.push(other);
371        CommonRefinementZipped {
372            iters: self.iters,
373            intervals: self.intervals,
374            values: self.values,
375            extractor: self.extractor,
376            phantom: PhantomData,
377        }
378    }
379}