timely/progress/frontier.rs
1//! Tracks minimal sets of mutually incomparable elements of a partial order.
2
3use serde::{Deserialize, Serialize};
4use smallvec::SmallVec;
5
6use crate::progress::ChangeBatch;
7use crate::order::{PartialOrder, TotalOrder};
8
9/// A set of mutually incomparable elements.
10///
11/// An antichain is a set of partially ordered elements, each of which is incomparable to the others.
12/// This antichain implementation allows you to repeatedly introduce elements to the antichain, and
13/// which will evict larger elements to maintain the *minimal* antichain, those incomparable elements
14/// no greater than any other element.
15///
16/// Two antichains are equal if they contain the same set of elements, even if in different orders.
17/// This can make equality testing quadratic, though linear in the common case that the sequences
18/// are identical.
19#[derive(Debug, Serialize, Deserialize)]
20pub struct Antichain<T> {
21 elements: SmallVec<[T; 1]>
22}
23
24impl<T: PartialOrder> Antichain<T> {
25 /// Updates the `Antichain` if the element is not greater than or equal to some present element.
26 ///
27 /// Returns `true` if element is added to the set
28 ///
29 /// # Examples
30 ///
31 ///```
32 /// use timely::progress::frontier::Antichain;
33 ///
34 /// let mut frontier = Antichain::new();
35 /// assert!(frontier.insert(2));
36 /// assert!(!frontier.insert(3));
37 ///```
38 pub fn insert(&mut self, element: T) -> bool {
39 if !self.elements.iter().any(|x| x.less_equal(&element)) {
40 self.elements.retain(|x| !element.less_equal(x));
41 self.elements.push(element);
42 true
43 }
44 else {
45 false
46 }
47 }
48
49 /// Updates the `Antichain` if the element is not greater than or equal to some present element.
50 ///
51 /// Returns `true` if element is added to the set
52 ///
53 /// Accepts a reference to an element, which is cloned when inserting.
54 ///
55 /// # Examples
56 ///
57 ///```
58 /// use timely::progress::frontier::Antichain;
59 ///
60 /// let mut frontier = Antichain::new();
61 /// assert!(frontier.insert_ref(&2));
62 /// assert!(!frontier.insert(3));
63 ///```
64 pub fn insert_ref(&mut self, element: &T) -> bool where T: Clone {
65 if !self.elements.iter().any(|x| x.less_equal(element)) {
66 self.elements.retain(|x| !element.less_equal(x));
67 self.elements.push(element.clone());
68 true
69 }
70 else {
71 false
72 }
73 }
74
75 /// Updates the `Antichain` if the element is not greater than or equal to some present element.
76 /// If the antichain needs updating, it uses the `to_owned` closure to convert the element into
77 /// a `T`.
78 ///
79 /// Returns `true` if element is added to the set
80 ///
81 /// # Examples
82 ///
83 ///```
84 /// use timely::progress::frontier::Antichain;
85 ///
86 /// let mut frontier = Antichain::new();
87 /// assert!(frontier.insert_with(&2, |x| *x));
88 /// assert!(!frontier.insert(3));
89 ///```
90 pub fn insert_with<O: PartialOrder<T>, F: FnOnce(&O) -> T>(&mut self, element: &O, to_owned: F) -> bool where T: PartialOrder<O> {
91 if !self.elements.iter().any(|x| x.less_equal(element)) {
92 self.elements.retain(|x| !element.less_equal(x));
93 self.elements.push(to_owned(element));
94 true
95 }
96 else {
97 false
98 }
99 }
100
101 /// Reserves capacity for at least additional more elements to be inserted in the given `Antichain`
102 pub fn reserve(&mut self, additional: usize) {
103 self.elements.reserve(additional);
104 }
105
106 /// Performs a sequence of insertion and returns `true` iff any insertion does.
107 ///
108 /// # Examples
109 ///
110 ///```
111 /// use timely::progress::frontier::Antichain;
112 ///
113 /// let mut frontier = Antichain::new();
114 /// assert!(frontier.extend(Some(3)));
115 /// assert!(frontier.extend(vec![2, 5]));
116 /// assert!(!frontier.extend(vec![3, 4]));
117 ///```
118 pub fn extend<I: IntoIterator<Item=T>>(&mut self, iterator: I) -> bool {
119 let mut added = false;
120 for element in iterator {
121 added = self.insert(element) || added;
122 }
123 added
124 }
125
126 /// Returns `true` if any item in the antichain is strictly less than the argument.
127 ///
128 /// # Examples
129 ///
130 ///```
131 /// use timely::progress::frontier::Antichain;
132 ///
133 /// let mut frontier = Antichain::from_elem(2);
134 /// assert!(frontier.less_than(&3));
135 /// assert!(!frontier.less_than(&2));
136 /// assert!(!frontier.less_than(&1));
137 ///
138 /// frontier.clear();
139 /// assert!(!frontier.less_than(&3));
140 ///```
141 #[inline]
142 pub fn less_than(&self, time: &T) -> bool {
143 self.elements.iter().any(|x| x.less_than(time))
144 }
145
146 /// Returns `true` if any item in the antichain is less than or equal to the argument.
147 ///
148 /// # Examples
149 ///
150 ///```
151 /// use timely::progress::frontier::Antichain;
152 ///
153 /// let mut frontier = Antichain::from_elem(2);
154 /// assert!(frontier.less_equal(&3));
155 /// assert!(frontier.less_equal(&2));
156 /// assert!(!frontier.less_equal(&1));
157 ///
158 /// frontier.clear();
159 /// assert!(!frontier.less_equal(&3));
160 ///```
161 #[inline]
162 pub fn less_equal(&self, time: &T) -> bool {
163 self.elements.iter().any(|x| x.less_equal(time))
164 }
165
166 /// Returns `true` if every element of `other` is greater or equal to some element of `self`.
167 #[deprecated(since="0.12.0", note="please use `PartialOrder::less_equal` instead")]
168 #[inline]
169 pub fn dominates(&self, other: &Antichain<T>) -> bool {
170 <Self as PartialOrder>::less_equal(self, other)
171 }
172}
173
174impl<T: PartialOrder> std::iter::FromIterator<T> for Antichain<T> {
175 fn from_iter<I>(iterator: I) -> Self
176 where
177 I: IntoIterator<Item=T>
178 {
179 let mut result = Self::new();
180 result.extend(iterator);
181 result
182 }
183}
184
185impl<T> Antichain<T> {
186
187 /// Creates a new empty `Antichain`.
188 ///
189 /// # Examples
190 ///
191 ///```
192 /// use timely::progress::frontier::Antichain;
193 ///
194 /// let mut frontier = Antichain::<u32>::new();
195 ///```
196 pub fn new() -> Antichain<T> { Antichain { elements: SmallVec::new() } }
197
198 /// Creates a new empty `Antichain` with space for `capacity` elements.
199 ///
200 /// # Examples
201 ///
202 ///```
203 /// use timely::progress::frontier::Antichain;
204 ///
205 /// let mut frontier = Antichain::<u32>::with_capacity(10);
206 ///```
207 pub fn with_capacity(capacity: usize) -> Self {
208 Self {
209 elements: SmallVec::with_capacity(capacity),
210 }
211 }
212
213 /// Creates a new singleton `Antichain`.
214 ///
215 /// # Examples
216 ///
217 ///```
218 /// use timely::progress::frontier::Antichain;
219 ///
220 /// let mut frontier = Antichain::from_elem(2);
221 ///```
222 pub fn from_elem(element: T) -> Antichain<T> {
223 let mut elements = SmallVec::with_capacity(1);
224 elements.push(element);
225 Antichain { elements }
226 }
227
228 /// Clears the contents of the antichain.
229 ///
230 /// # Examples
231 ///
232 ///```
233 /// use timely::progress::frontier::Antichain;
234 ///
235 /// let mut frontier = Antichain::from_elem(2);
236 /// frontier.clear();
237 /// assert!(frontier.elements().is_empty());
238 ///```
239 pub fn clear(&mut self) { self.elements.clear() }
240
241 /// Drains the elements, leaving the allocation for reuse.
242 pub fn drain(&mut self) -> smallvec::Drain<'_, [T; 1]> { self.elements.drain(..) }
243
244 /// Sorts the elements so that comparisons between antichains can be made.
245 pub fn sort(&mut self) where T: Ord { self.elements.sort() }
246
247 /// Reveals the elements in the antichain.
248 ///
249 /// This method is redundant with `<Antichain<T> as Deref>`, but the method
250 /// is in such broad use that we probably don't want to deprecate it without
251 /// some time to fix all things.
252 ///
253 /// # Examples
254 ///
255 ///```
256 /// use timely::progress::frontier::Antichain;
257 ///
258 /// let mut frontier = Antichain::from_elem(2);
259 /// assert_eq!(frontier.elements(), &[2]);
260 ///```
261 #[inline] pub fn elements(&self) -> &[T] { &self[..] }
262
263 /// Reveals the elements in the antichain.
264 ///
265 /// # Examples
266 ///
267 ///```
268 /// use timely::progress::frontier::Antichain;
269 ///
270 /// let mut frontier = Antichain::from_elem(2);
271 /// assert_eq!(&*frontier.borrow(), &[2]);
272 ///```
273 #[inline] pub fn borrow(&self) -> AntichainRef<'_, T> { AntichainRef::new(&self.elements) }}
274
275impl<T: PartialEq> PartialEq for Antichain<T> {
276 fn eq(&self, other: &Self) -> bool {
277 // Lengths should be the same, with the option for fast acceptance if identical.
278 self.elements().len() == other.elements().len() &&
279 (
280 self.elements().iter().zip(other.elements().iter()).all(|(t1,t2)| t1 == t2) ||
281 self.elements().iter().all(|t1| other.elements().iter().any(|t2| t1.eq(t2)))
282 )
283 }
284}
285
286impl<T: Eq> Eq for Antichain<T> { }
287
288impl<T: PartialOrder> PartialOrder for Antichain<T> {
289 fn less_equal(&self, other: &Self) -> bool {
290 other.elements().iter().all(|t2| self.elements().iter().any(|t1| t1.less_equal(t2)))
291 }
292}
293
294impl<T: Clone> Clone for Antichain<T> {
295 fn clone(&self) -> Self {
296 Antichain { elements: self.elements.clone() }
297 }
298 fn clone_from(&mut self, source: &Self) {
299 self.elements.clone_from(&source.elements)
300 }
301}
302
303impl<T> Default for Antichain<T> {
304 fn default() -> Self {
305 Self::new()
306 }
307}
308
309impl<T: TotalOrder> TotalOrder for Antichain<T> { }
310
311impl<T: TotalOrder> Antichain<T> {
312 /// Convert to the at most one element the antichain contains.
313 pub fn into_option(mut self) -> Option<T> {
314 debug_assert!(self.len() <= 1);
315 self.elements.pop()
316 }
317 /// Return a reference to the at most one element the antichain contains.
318 pub fn as_option(&self) -> Option<&T> {
319 debug_assert!(self.len() <= 1);
320 self.elements.last()
321 }
322}
323
324impl<T: Ord+std::hash::Hash> std::hash::Hash for Antichain<T> {
325 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
326 let mut temp = self.elements.iter().collect::<Vec<_>>();
327 temp.sort();
328 for element in temp {
329 element.hash(state);
330 }
331 }
332}
333
334impl<T: PartialOrder> From<Vec<T>> for Antichain<T> {
335 fn from(vec: Vec<T>) -> Self {
336 // TODO: We could reuse `vec` with some care.
337 let mut temp = Antichain::new();
338 for elem in vec.into_iter() { temp.insert(elem); }
339 temp
340 }
341}
342
343impl<T> From<Antichain<T>> for SmallVec<[T; 1]> {
344 fn from(val: Antichain<T>) -> Self {
345 val.elements
346 }
347}
348
349impl<T> ::std::ops::Deref for Antichain<T> {
350 type Target = [T];
351 fn deref(&self) -> &Self::Target {
352 &self.elements
353 }
354}
355
356impl<T> ::std::iter::IntoIterator for Antichain<T> {
357 type Item = T;
358 type IntoIter = smallvec::IntoIter<[T; 1]>;
359 fn into_iter(self) -> Self::IntoIter {
360 self.elements.into_iter()
361 }
362}
363
364/// An antichain based on a multiset whose elements frequencies can be updated.
365///
366/// The `MutableAntichain` maintains frequencies for many elements of type `T`, and exposes the set
367/// of elements with positive count not greater than any other elements with positive count. The
368/// antichain may both advance and retreat; the changes do not all need to be to elements greater or
369/// equal to some elements of the frontier.
370///
371/// The type `T` must implement `PartialOrder` as well as `Ord`. The implementation of the `Ord` trait
372/// is used to efficiently organize the updates for cancellation, and to efficiently determine the lower
373/// bounds, and only needs to not contradict the `PartialOrder` implementation (that is, if `PartialOrder`
374/// orders two elements, then so does the `Ord` implementation).
375///
376/// The `MutableAntichain` implementation is done with the intent that updates to it are done in batches,
377/// and it is acceptable to rebuild the frontier from scratch when a batch of updates change it. This means
378/// that it can be expensive to maintain a large number of counts and change few elements near the frontier.
379#[derive(Clone, Debug, Serialize, Deserialize)]
380pub struct MutableAntichain<T> {
381 updates: ChangeBatch<T>,
382 frontier: Vec<T>,
383 changes: ChangeBatch<T>,
384}
385
386impl<T> MutableAntichain<T> {
387 /// Creates a new empty `MutableAntichain`.
388 ///
389 /// # Examples
390 ///
391 ///```
392 /// use timely::progress::frontier::MutableAntichain;
393 ///
394 /// let frontier = MutableAntichain::<usize>::new();
395 /// assert!(frontier.is_empty());
396 ///```
397 #[inline]
398 pub fn new() -> MutableAntichain<T> {
399 MutableAntichain {
400 updates: ChangeBatch::new(),
401 frontier: Vec::new(),
402 changes: ChangeBatch::new(),
403 }
404 }
405
406 /// Removes all elements.
407 ///
408 /// # Examples
409 ///
410 ///```
411 /// use timely::progress::frontier::MutableAntichain;
412 ///
413 /// let mut frontier = MutableAntichain::<usize>::new();
414 /// frontier.clear();
415 /// assert!(frontier.is_empty());
416 ///```
417 #[inline]
418 pub fn clear(&mut self) {
419 self.updates.clear();
420 self.frontier.clear();
421 self.changes.clear();
422 }
423
424 /// Reveals the minimal elements with positive count.
425 ///
426 /// # Examples
427 ///
428 ///```
429 /// use timely::progress::frontier::MutableAntichain;
430 ///
431 /// let mut frontier = MutableAntichain::<usize>::new();
432 /// assert!(frontier.frontier().len() == 0);
433 ///```
434 #[inline]
435 pub fn frontier(&self) -> AntichainRef<'_, T> {
436 AntichainRef::new(&self.frontier)
437 }
438
439 /// Creates a new singleton `MutableAntichain`.
440 ///
441 /// # Examples
442 ///
443 ///```
444 /// use timely::progress::frontier::{AntichainRef, MutableAntichain};
445 ///
446 /// let mut frontier = MutableAntichain::from_elem(0u64);
447 /// assert!(frontier.frontier() == AntichainRef::new(&[0u64]));
448 ///```
449 #[inline]
450 pub fn from_elem(bottom: T) -> MutableAntichain<T>
451 where
452 T: Ord+Clone,
453 {
454 MutableAntichain {
455 updates: ChangeBatch::new_from(bottom.clone(), 1),
456 frontier: vec![bottom],
457 changes: ChangeBatch::new(),
458 }
459 }
460
461 /// Returns `true` if there are no elements in the `MutableAntichain`.
462 ///
463 /// # Examples
464 ///
465 ///```
466 /// use timely::progress::frontier::MutableAntichain;
467 ///
468 /// let mut frontier = MutableAntichain::<usize>::new();
469 /// assert!(frontier.is_empty());
470 ///```
471 #[inline]
472 pub fn is_empty(&self) -> bool {
473 self.frontier.is_empty()
474 }
475
476 /// Returns `true` if any item in the `MutableAntichain` is strictly less than the argument.
477 ///
478 /// # Examples
479 ///
480 ///```
481 /// use timely::progress::frontier::MutableAntichain;
482 ///
483 /// let mut frontier = MutableAntichain::from_elem(1u64);
484 /// assert!(!frontier.less_than(&0));
485 /// assert!(!frontier.less_than(&1));
486 /// assert!(frontier.less_than(&2));
487 ///```
488 #[inline]
489 pub fn less_than<O>(&self, time: &O) -> bool
490 where
491 T: PartialOrder<O>,
492 {
493 self.frontier().less_than(time)
494 }
495
496 /// Returns `true` if any item in the `MutableAntichain` is less than or equal to the argument.
497 ///
498 /// # Examples
499 ///
500 ///```
501 /// use timely::progress::frontier::MutableAntichain;
502 ///
503 /// let mut frontier = MutableAntichain::from_elem(1u64);
504 /// assert!(!frontier.less_equal(&0));
505 /// assert!(frontier.less_equal(&1));
506 /// assert!(frontier.less_equal(&2));
507 ///```
508 #[inline]
509 pub fn less_equal<O>(&self, time: &O) -> bool
510 where
511 T: PartialOrder<O>,
512 {
513 self.frontier().less_equal(time)
514 }
515
516 /// Applies updates to the antichain and enumerates any changes.
517 ///
518 /// # Examples
519 ///
520 ///```
521 /// use timely::progress::frontier::{AntichainRef, MutableAntichain};
522 ///
523 /// let mut frontier = MutableAntichain::from_elem(1u64);
524 /// let changes =
525 /// frontier
526 /// .update_iter(vec![(1, -1), (2, 7)])
527 /// .collect::<Vec<_>>();
528 ///
529 /// assert!(frontier.frontier() == AntichainRef::new(&[2]));
530 /// assert!(changes == vec![(1, -1), (2, 1)]);
531 ///```
532 #[inline]
533 pub fn update_iter<I>(&mut self, updates: I) -> smallvec::Drain<'_, [(T, i64); 2]>
534 where
535 T: Clone + PartialOrder + Ord,
536 I: IntoIterator<Item = (T, i64)>,
537 {
538 // track whether a rebuild is needed.
539 let mut rebuild_required = false;
540 for (time, delta) in updates {
541 // If we do not yet require a rebuild, test whether we might require one
542 // and set the flag in that case.
543 if !rebuild_required {
544 rebuild_required = self.requires_rebuild(&time, delta);
545 }
546
547 self.updates.update(time, delta);
548 }
549
550 if rebuild_required {
551 self.rebuild()
552 }
553 self.changes.drain()
554 }
555
556 /// Tests whether applying `(time, delta)` will require a frontier rebuild.
557 ///
558 /// Factored out of [`Self::update_iter`] so it is generic only over `T` and not
559 /// the iterator type, deduplicating the inlined `frontier.iter().any(...)` bodies
560 /// across `update_iter` monomorphizations.
561 fn requires_rebuild(&self, time: &T, delta: i64) -> bool
562 where
563 T: PartialOrder,
564 {
565 if delta > 0 {
566 // Adding a count at or beyond the frontier cannot change it.
567 !self.frontier.iter().any(|f| f.less_equal(time))
568 }
569 else {
570 // Removing a count can only expose new frontier elements if it
571 // removes an existing frontier element. Zero changes do nothing.
572 delta < 0 && self.frontier.contains(time)
573 }
574 }
575
576 /// Rebuilds `self.frontier` from `self.updates`.
577 ///
578 /// This method is meant to be used for bulk updates to the frontier, and does more work than one might do
579 /// for single updates, but is meant to be an efficient way to process multiple updates together. This is
580 /// especially true when we want to apply very large numbers of updates.
581 fn rebuild(&mut self)
582 where
583 T: Clone + PartialOrder + Ord,
584 {
585 for time in self.frontier.drain(..) {
586 self.changes.update(time, -1);
587 }
588
589 // build new frontier using strictly positive times.
590 // as the times are sorted, we don't need to worry that we might displace frontier elements.
591 for time in self.updates.iter().filter(|x| x.1 > 0) {
592 if !self.frontier.iter().any(|f| f.less_equal(&time.0)) {
593 self.frontier.push(time.0.clone());
594 }
595 }
596
597 for time in self.frontier.iter() {
598 self.changes.update(time.clone(), 1);
599 }
600 }
601
602 /// Reports the count for a queried time.
603 pub fn count_for<O>(&self, query_time: &O) -> i64
604 where
605 T: PartialEq<O>,
606 {
607 self.updates
608 .unstable_internal_updates()
609 .iter()
610 .filter(|td| td.0.eq(query_time))
611 .map(|td| td.1)
612 .sum()
613 }
614
615 /// Reports the updates that form the frontier. Returns an iterator of timestamps and their frequency.
616 ///
617 /// Rebuilds the internal representation before revealing times and frequencies.
618 pub fn updates(&mut self) -> impl Iterator<Item=&(T, i64)>
619 where
620 T: Clone + PartialOrder + Ord,
621 {
622 self.rebuild();
623 self.updates.iter()
624 }
625}
626
627impl<T> Default for MutableAntichain<T> {
628 fn default() -> Self {
629 Self::new()
630 }
631}
632
633/// Extension trait for filtering time changes through antichains.
634pub trait MutableAntichainFilter<T: PartialOrder+Ord+Clone> {
635 /// Filters time changes through an antichain.
636 ///
637 /// # Examples
638 ///
639 /// ```
640 /// use timely::progress::frontier::{MutableAntichain, MutableAntichainFilter};
641 ///
642 /// let mut frontier = MutableAntichain::from_elem(1u64);
643 /// let changes =
644 /// vec![(1, -1), (2, 7)]
645 /// .filter_through(&mut frontier)
646 /// .collect::<Vec<_>>();
647 ///
648 /// assert!(changes == vec![(1, -1), (2, 1)]);
649 /// ```
650 fn filter_through(self, antichain: &mut MutableAntichain<T>) -> smallvec::Drain<'_, [(T,i64); 2]>;
651}
652
653impl<T: PartialOrder+Ord+Clone, I: IntoIterator<Item=(T,i64)>> MutableAntichainFilter<T> for I {
654 fn filter_through(self, antichain: &mut MutableAntichain<T>) -> smallvec::Drain<'_, [(T,i64); 2]> {
655 antichain.update_iter(self)
656 }
657}
658
659impl<T: PartialOrder+Ord+Clone> From<Antichain<T>> for MutableAntichain<T> {
660 fn from(antichain: Antichain<T>) -> Self {
661 let mut result = MutableAntichain::new();
662 result.update_iter(antichain.into_iter().map(|time| (time, 1)));
663 result
664 }
665}
666impl<'a, T: PartialOrder+Ord+Clone> From<AntichainRef<'a, T>> for MutableAntichain<T> {
667 fn from(antichain: AntichainRef<'a, T>) -> Self {
668 let mut result = MutableAntichain::new();
669 result.update_iter(antichain.into_iter().map(|time| (time.clone(), 1)));
670 result
671 }
672}
673
674impl<T> std::iter::FromIterator<(T, i64)> for MutableAntichain<T>
675where
676 T: Clone + PartialOrder + Ord,
677{
678 fn from_iter<I>(iterator: I) -> Self
679 where
680 I: IntoIterator<Item=(T, i64)>,
681 {
682 let mut result = Self::new();
683 result.update_iter(iterator);
684 result
685 }
686}
687
688/// A wrapper for elements of an antichain.
689#[derive(Debug)]
690pub struct AntichainRef<'a, T: 'a> {
691 /// Elements contained in the antichain.
692 frontier: &'a [T],
693}
694
695impl<'a, T: 'a> Clone for AntichainRef<'a, T> {
696 fn clone(&self) -> Self { *self }
697}
698
699impl<'a, T: 'a> Copy for AntichainRef<'a, T> { }
700
701impl<'a, T: 'a> AntichainRef<'a, T> {
702 /// Create a new `AntichainRef` from a reference to a slice of elements forming the frontier.
703 ///
704 /// This method does not check that this antichain has any particular properties, for example
705 /// that there are no elements strictly less than other elements.
706 pub fn new(frontier: &'a [T]) -> Self {
707 Self {
708 frontier,
709 }
710 }
711
712 /// Constructs an owned antichain from the antichain reference.
713 ///
714 /// # Examples
715 ///
716 ///```
717 /// use timely::progress::{Antichain, frontier::AntichainRef};
718 ///
719 /// let frontier = AntichainRef::new(&[1u64]);
720 /// assert_eq!(frontier.to_owned(), Antichain::from_elem(1u64));
721 ///```
722 pub fn to_owned(&self) -> Antichain<T> where T: Clone {
723 Antichain {
724 elements: self.frontier.into()
725 }
726 }
727}
728
729impl<T> AntichainRef<'_, T> {
730
731 /// Returns `true` if any item in the `AntichainRef` is strictly less than the argument.
732 ///
733 /// # Examples
734 ///
735 ///```
736 /// use timely::progress::frontier::AntichainRef;
737 ///
738 /// let frontier = AntichainRef::new(&[1u64]);
739 /// assert!(!frontier.less_than(&0));
740 /// assert!(!frontier.less_than(&1));
741 /// assert!(frontier.less_than(&2));
742 ///```
743 #[inline]
744 pub fn less_than<O>(&self, time: &O) -> bool where T: PartialOrder<O> {
745 self.iter().any(|x| x.less_than(time))
746 }
747
748 /// Returns `true` if any item in the `AntichainRef` is less than or equal to the argument.
749 #[inline]
750 ///
751 /// # Examples
752 ///
753 ///```
754 /// use timely::progress::frontier::AntichainRef;
755 ///
756 /// let frontier = AntichainRef::new(&[1u64]);
757 /// assert!(!frontier.less_equal(&0));
758 /// assert!(frontier.less_equal(&1));
759 /// assert!(frontier.less_equal(&2));
760 ///```
761 pub fn less_equal<O>(&self, time: &O) -> bool where T: PartialOrder<O> {
762 self.iter().any(|x| x.less_equal(time))
763 }
764}
765
766impl<T: PartialEq> PartialEq for AntichainRef<'_, T> {
767 fn eq(&self, other: &Self) -> bool {
768 // Lengths should be the same, with the option for fast acceptance if identical.
769 self.len() == other.len() &&
770 (
771 self.iter().zip(other.iter()).all(|(t1,t2)| t1 == t2) ||
772 self.iter().all(|t1| other.iter().any(|t2| t1.eq(t2)))
773 )
774 }
775}
776
777impl<T: Eq> Eq for AntichainRef<'_, T> { }
778
779impl<T: PartialOrder> PartialOrder for AntichainRef<'_, T> {
780 fn less_equal(&self, other: &Self) -> bool {
781 other.iter().all(|t2| self.iter().any(|t1| t1.less_equal(t2)))
782 }
783}
784
785impl<T: TotalOrder> TotalOrder for AntichainRef<'_, T> { }
786
787impl<T: TotalOrder> AntichainRef<'_, T> {
788 /// Return a reference to the at most one element the antichain contains.
789 pub fn as_option(&self) -> Option<&T> {
790 debug_assert!(self.len() <= 1);
791 self.frontier.last()
792 }
793}
794
795impl<T> ::std::ops::Deref for AntichainRef<'_, T> {
796 type Target = [T];
797 fn deref(&self) -> &Self::Target {
798 self.frontier
799 }
800}
801
802impl<'a, T: 'a> ::std::iter::IntoIterator for &'a AntichainRef<'a, T> {
803 type Item = &'a T;
804 type IntoIter = ::std::slice::Iter<'a, T>;
805 fn into_iter(self) -> Self::IntoIter {
806 self.iter()
807 }
808}
809
810#[cfg(test)]
811mod tests {
812 use std::collections::HashSet;
813
814 use super::*;
815
816 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
817 struct Elem(char, usize);
818
819 impl PartialOrder for Elem {
820 fn less_equal(&self, other: &Self) -> bool {
821 self.0 <= other.0 && self.1 <= other.1
822 }
823 }
824
825 #[test]
826 fn antichain_hash() {
827 let mut hashed = HashSet::new();
828 hashed.insert(Antichain::from(vec![Elem('a', 2), Elem('b', 1)]));
829
830 assert!(hashed.contains(&Antichain::from(vec![Elem('a', 2), Elem('b', 1)])));
831 assert!(hashed.contains(&Antichain::from(vec![Elem('b', 1), Elem('a', 2)])));
832
833 assert!(!hashed.contains(&Antichain::from(vec![Elem('a', 2)])));
834 assert!(!hashed.contains(&Antichain::from(vec![Elem('a', 1)])));
835 assert!(!hashed.contains(&Antichain::from(vec![Elem('b', 2)])));
836 assert!(!hashed.contains(&Antichain::from(vec![Elem('a', 1), Elem('b', 2)])));
837 assert!(!hashed.contains(&Antichain::from(vec![Elem('c', 3)])));
838 assert!(!hashed.contains(&Antichain::from(vec![])));
839 }
840
841 #[test]
842 fn mutable_compaction() {
843 let mut mutable = MutableAntichain::new();
844 mutable.update_iter(Some((7, 1)));
845 mutable.update_iter(Some((7, 1)));
846 mutable.update_iter(Some((7, 1)));
847 mutable.update_iter(Some((7, 1)));
848 mutable.update_iter(Some((7, 1)));
849 mutable.update_iter(Some((7, 1)));
850 mutable.update_iter(Some((8, 1)));
851 mutable.update_iter(Some((8, 1)));
852 mutable.update_iter(Some((8, 1)));
853 mutable.update_iter(Some((8, 1)));
854 mutable.update_iter(Some((8, 1)));
855 for _ in 0 .. 1000 {
856 mutable.update_iter(Some((9, 1)));
857 mutable.update_iter(Some((9, -1)));
858 }
859 assert!(mutable.updates.unstable_internal_updates().len() <= 32);
860 }
861
862 #[test]
863 fn mutable_matches_counted_set() {
864 // Include negative counts, zero changes, frontier retreat, and batches
865 // that remove and replace a frontier element before they are applied.
866 fn check<T: Clone + Ord + PartialOrder + std::fmt::Debug>(domain: Vec<T>) {
867 let mut counts = std::collections::BTreeMap::<T, i64>::new();
868 let mut mutable = MutableAntichain::new();
869 let mut seed = 1u64;
870 for _ in 0..2000 {
871 let before = mutable.frontier().to_vec();
872 let mut updates = Vec::new();
873 for _ in 0..1 + (seed as usize % 5) {
874 seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1);
875 let time = domain[((seed >> 32) as usize) % domain.len()].clone();
876 let diff = ((seed >> 48) % 5) as i64 - 2;
877 *counts.entry(time.clone()).or_default() += diff;
878 updates.push((time, diff));
879 }
880 let actual: Vec<_> = mutable.update_iter(updates).collect();
881 let expected: Antichain<_> = counts.iter()
882 .filter(|(_, count)| **count > 0)
883 .map(|(time, _)| time.clone())
884 .collect();
885 assert_eq!(mutable.frontier(), expected.borrow());
886
887 let mut changes = std::collections::BTreeMap::<T, i64>::new();
888 for time in before { *changes.entry(time).or_default() -= 1; }
889 for time in expected.elements() { *changes.entry(time.clone()).or_default() += 1; }
890 let expected_changes: Vec<_> = changes.into_iter().filter(|(_, d)| *d != 0).collect();
891 assert_eq!(actual, expected_changes);
892 for time in &domain {
893 assert_eq!(mutable.count_for(time), *counts.get(time).unwrap_or(&0));
894 }
895 }
896 }
897 check((0..16usize).collect());
898 check((0..4).flat_map(|outer| (0..4).map(move |inner|
899 crate::order::Product::new(outer, inner))).collect());
900 }
901}