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}