use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use crate::progress::ChangeBatch;
use crate::order::{PartialOrder, TotalOrder};
#[derive(Debug, Serialize, Deserialize)]
pub struct Antichain<T> {
elements: SmallVec<[T; 1]>
}
impl<T: PartialOrder> Antichain<T> {
pub fn insert(&mut self, element: T) -> bool {
if !self.elements.iter().any(|x| x.less_equal(&element)) {
self.elements.retain(|x| !element.less_equal(x));
self.elements.push(element);
true
}
else {
false
}
}
pub fn insert_ref(&mut self, element: &T) -> bool where T: Clone {
if !self.elements.iter().any(|x| x.less_equal(element)) {
self.elements.retain(|x| !element.less_equal(x));
self.elements.push(element.clone());
true
}
else {
false
}
}
pub fn insert_with<O: PartialOrder<T>, F: FnOnce(&O) -> T>(&mut self, element: &O, to_owned: F) -> bool where T: PartialOrder<O> {
if !self.elements.iter().any(|x| x.less_equal(element)) {
self.elements.retain(|x| !element.less_equal(x));
self.elements.push(to_owned(element));
true
}
else {
false
}
}
pub fn reserve(&mut self, additional: usize) {
self.elements.reserve(additional);
}
pub fn extend<I: IntoIterator<Item=T>>(&mut self, iterator: I) -> bool {
let mut added = false;
for element in iterator {
added = self.insert(element) || added;
}
added
}
#[inline]
pub fn less_than(&self, time: &T) -> bool {
self.elements.iter().any(|x| x.less_than(time))
}
#[inline]
pub fn less_equal(&self, time: &T) -> bool {
self.elements.iter().any(|x| x.less_equal(time))
}
#[deprecated(since="0.12.0", note="please use `PartialOrder::less_equal` instead")]
#[inline]
pub fn dominates(&self, other: &Antichain<T>) -> bool {
<Self as PartialOrder>::less_equal(self, other)
}
}
impl<T: PartialOrder> std::iter::FromIterator<T> for Antichain<T> {
fn from_iter<I>(iterator: I) -> Self
where
I: IntoIterator<Item=T>
{
let mut result = Self::new();
result.extend(iterator);
result
}
}
impl<T> Antichain<T> {
pub fn new() -> Antichain<T> { Antichain { elements: SmallVec::new() } }
pub fn with_capacity(capacity: usize) -> Self {
Self {
elements: SmallVec::with_capacity(capacity),
}
}
pub fn from_elem(element: T) -> Antichain<T> {
let mut elements = SmallVec::with_capacity(1);
elements.push(element);
Antichain { elements }
}
pub fn clear(&mut self) { self.elements.clear() }
pub fn sort(&mut self) where T: Ord { self.elements.sort() }
#[inline] pub fn elements(&self) -> &[T] { &self[..] }
#[inline] pub fn borrow(&self) -> AntichainRef<'_, T> { AntichainRef::new(&self.elements) }}
impl<T: PartialEq> PartialEq for Antichain<T> {
fn eq(&self, other: &Self) -> bool {
self.elements().len() == other.elements().len() &&
(
self.elements().iter().zip(other.elements().iter()).all(|(t1,t2)| t1 == t2) ||
self.elements().iter().all(|t1| other.elements().iter().any(|t2| t1.eq(t2)))
)
}
}
impl<T: Eq> Eq for Antichain<T> { }
impl<T: PartialOrder> PartialOrder for Antichain<T> {
fn less_equal(&self, other: &Self) -> bool {
other.elements().iter().all(|t2| self.elements().iter().any(|t1| t1.less_equal(t2)))
}
}
impl<T: Clone> Clone for Antichain<T> {
fn clone(&self) -> Self {
Antichain { elements: self.elements.clone() }
}
fn clone_from(&mut self, source: &Self) {
self.elements.clone_from(&source.elements)
}
}
impl<T> Default for Antichain<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: TotalOrder> TotalOrder for Antichain<T> { }
impl<T: TotalOrder> Antichain<T> {
pub fn into_option(mut self) -> Option<T> {
debug_assert!(self.len() <= 1);
self.elements.pop()
}
pub fn as_option(&self) -> Option<&T> {
debug_assert!(self.len() <= 1);
self.elements.last()
}
}
impl<T: Ord+std::hash::Hash> std::hash::Hash for Antichain<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let mut temp = self.elements.iter().collect::<Vec<_>>();
temp.sort();
for element in temp {
element.hash(state);
}
}
}
impl<T: PartialOrder> From<Vec<T>> for Antichain<T> {
fn from(vec: Vec<T>) -> Self {
let mut temp = Antichain::new();
for elem in vec.into_iter() { temp.insert(elem); }
temp
}
}
impl<T> From<Antichain<T>> for SmallVec<[T; 1]> {
fn from(val: Antichain<T>) -> Self {
val.elements
}
}
impl<T> ::std::ops::Deref for Antichain<T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.elements
}
}
impl<T> ::std::iter::IntoIterator for Antichain<T> {
type Item = T;
type IntoIter = smallvec::IntoIter<[T; 1]>;
fn into_iter(self) -> Self::IntoIter {
self.elements.into_iter()
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MutableAntichain<T> {
updates: ChangeBatch<T>,
frontier: Vec<T>,
changes: ChangeBatch<T>,
}
impl<T> MutableAntichain<T> {
#[inline]
pub fn new() -> MutableAntichain<T> {
MutableAntichain {
updates: ChangeBatch::new(),
frontier: Vec::new(),
changes: ChangeBatch::new(),
}
}
#[inline]
pub fn clear(&mut self) {
self.updates.clear();
self.frontier.clear();
self.changes.clear();
}
#[inline]
pub fn frontier(&self) -> AntichainRef<'_, T> {
AntichainRef::new(&self.frontier)
}
#[inline]
pub fn from_elem(bottom: T) -> MutableAntichain<T>
where
T: Ord+Clone,
{
MutableAntichain {
updates: ChangeBatch::new_from(bottom.clone(), 1),
frontier: vec![bottom],
changes: ChangeBatch::new(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.frontier.is_empty()
}
#[inline]
pub fn less_than<O>(&self, time: &O) -> bool
where
T: PartialOrder<O>,
{
self.frontier().less_than(time)
}
#[inline]
pub fn less_equal<O>(&self, time: &O) -> bool
where
T: PartialOrder<O>,
{
self.frontier().less_equal(time)
}
#[inline]
pub fn update_iter<I>(&mut self, updates: I) -> smallvec::Drain<'_, [(T, i64); 2]>
where
T: Clone + PartialOrder + Ord,
I: IntoIterator<Item = (T, i64)>,
{
let updates = updates.into_iter();
let mut rebuild_required = false;
for (time, delta) in updates {
if !rebuild_required {
let beyond_frontier = self.frontier.iter().any(|f| f.less_than(&time));
let before_frontier = !self.frontier.iter().any(|f| f.less_equal(&time));
rebuild_required = !(beyond_frontier || (delta < 0 && before_frontier));
}
self.updates.update(time, delta);
}
if rebuild_required {
self.rebuild()
}
self.changes.drain()
}
fn rebuild(&mut self)
where
T: Clone + PartialOrder + Ord,
{
for time in self.frontier.drain(..) {
self.changes.update(time, -1);
}
for time in self.updates.iter().filter(|x| x.1 > 0) {
if !self.frontier.iter().any(|f| f.less_equal(&time.0)) {
self.frontier.push(time.0.clone());
}
}
for time in self.frontier.iter() {
self.changes.update(time.clone(), 1);
}
}
pub fn count_for<O>(&self, query_time: &O) -> i64
where
T: PartialEq<O>,
{
self.updates
.unstable_internal_updates()
.iter()
.filter(|td| td.0.eq(query_time))
.map(|td| td.1)
.sum()
}
pub fn updates(&mut self) -> impl Iterator<Item=&(T, i64)>
where
T: Clone + PartialOrder + Ord,
{
self.rebuild();
self.updates.iter()
}
}
impl<T> Default for MutableAntichain<T> {
fn default() -> Self {
Self::new()
}
}
pub trait MutableAntichainFilter<T: PartialOrder+Ord+Clone> {
fn filter_through(self, antichain: &mut MutableAntichain<T>) -> smallvec::Drain<'_, [(T,i64); 2]>;
}
impl<T: PartialOrder+Ord+Clone, I: IntoIterator<Item=(T,i64)>> MutableAntichainFilter<T> for I {
fn filter_through(self, antichain: &mut MutableAntichain<T>) -> smallvec::Drain<'_, [(T,i64); 2]> {
antichain.update_iter(self)
}
}
impl<T: PartialOrder+Ord+Clone> From<Antichain<T>> for MutableAntichain<T> {
fn from(antichain: Antichain<T>) -> Self {
let mut result = MutableAntichain::new();
result.update_iter(antichain.into_iter().map(|time| (time, 1)));
result
}
}
impl<'a, T: PartialOrder+Ord+Clone> From<AntichainRef<'a, T>> for MutableAntichain<T> {
fn from(antichain: AntichainRef<'a, T>) -> Self {
let mut result = MutableAntichain::new();
result.update_iter(antichain.into_iter().map(|time| (time.clone(), 1)));
result
}
}
impl<T> std::iter::FromIterator<(T, i64)> for MutableAntichain<T>
where
T: Clone + PartialOrder + Ord,
{
fn from_iter<I>(iterator: I) -> Self
where
I: IntoIterator<Item=(T, i64)>,
{
let mut result = Self::new();
result.update_iter(iterator);
result
}
}
#[derive(Debug)]
pub struct AntichainRef<'a, T: 'a> {
frontier: &'a [T],
}
impl<'a, T: 'a> Clone for AntichainRef<'a, T> {
fn clone(&self) -> Self { *self }
}
impl<'a, T: 'a> Copy for AntichainRef<'a, T> { }
impl<'a, T: 'a> AntichainRef<'a, T> {
pub fn new(frontier: &'a [T]) -> Self {
Self {
frontier,
}
}
pub fn to_owned(&self) -> Antichain<T> where T: Clone {
Antichain {
elements: self.frontier.into()
}
}
}
impl<T> AntichainRef<'_, T> {
#[inline]
pub fn less_than<O>(&self, time: &O) -> bool where T: PartialOrder<O> {
self.iter().any(|x| x.less_than(time))
}
#[inline]
pub fn less_equal<O>(&self, time: &O) -> bool where T: PartialOrder<O> {
self.iter().any(|x| x.less_equal(time))
}
}
impl<T: PartialEq> PartialEq for AntichainRef<'_, T> {
fn eq(&self, other: &Self) -> bool {
self.len() == other.len() &&
(
self.iter().zip(other.iter()).all(|(t1,t2)| t1 == t2) ||
self.iter().all(|t1| other.iter().any(|t2| t1.eq(t2)))
)
}
}
impl<T: Eq> Eq for AntichainRef<'_, T> { }
impl<T: PartialOrder> PartialOrder for AntichainRef<'_, T> {
fn less_equal(&self, other: &Self) -> bool {
other.iter().all(|t2| self.iter().any(|t1| t1.less_equal(t2)))
}
}
impl<T: TotalOrder> TotalOrder for AntichainRef<'_, T> { }
impl<T: TotalOrder> AntichainRef<'_, T> {
pub fn as_option(&self) -> Option<&T> {
debug_assert!(self.len() <= 1);
self.frontier.last()
}
}
impl<T> ::std::ops::Deref for AntichainRef<'_, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.frontier
}
}
impl<'a, T: 'a> ::std::iter::IntoIterator for &'a AntichainRef<'a, T> {
type Item = &'a T;
type IntoIter = ::std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use super::*;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
struct Elem(char, usize);
impl PartialOrder for Elem {
fn less_equal(&self, other: &Self) -> bool {
self.0 <= other.0 && self.1 <= other.1
}
}
#[test]
fn antichain_hash() {
let mut hashed = HashSet::new();
hashed.insert(Antichain::from(vec![Elem('a', 2), Elem('b', 1)]));
assert!(hashed.contains(&Antichain::from(vec![Elem('a', 2), Elem('b', 1)])));
assert!(hashed.contains(&Antichain::from(vec![Elem('b', 1), Elem('a', 2)])));
assert!(!hashed.contains(&Antichain::from(vec![Elem('a', 2)])));
assert!(!hashed.contains(&Antichain::from(vec![Elem('a', 1)])));
assert!(!hashed.contains(&Antichain::from(vec![Elem('b', 2)])));
assert!(!hashed.contains(&Antichain::from(vec![Elem('a', 1), Elem('b', 2)])));
assert!(!hashed.contains(&Antichain::from(vec![Elem('c', 3)])));
assert!(!hashed.contains(&Antichain::from(vec![])));
}
#[test]
fn mutable_compaction() {
let mut mutable = MutableAntichain::new();
mutable.update_iter(Some((7, 1)));
mutable.update_iter(Some((7, 1)));
mutable.update_iter(Some((7, 1)));
mutable.update_iter(Some((7, 1)));
mutable.update_iter(Some((7, 1)));
mutable.update_iter(Some((7, 1)));
mutable.update_iter(Some((8, 1)));
mutable.update_iter(Some((8, 1)));
mutable.update_iter(Some((8, 1)));
mutable.update_iter(Some((8, 1)));
mutable.update_iter(Some((8, 1)));
for _ in 0 .. 1000 {
mutable.update_iter(Some((9, 1)));
mutable.update_iter(Some((9, -1)));
}
assert!(mutable.updates.unstable_internal_updates().len() <= 32);
}
}