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}