timely/progress/
frontier.rs

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