use crate::progress::ChangeBatch;
use crate::order::PartialOrder;
#[derive(Clone, Debug, Default, Abomonation, Serialize, Deserialize)]
pub struct Antichain<T> {
elements: Vec<T>
}
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 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> Antichain<T> {
pub fn new() -> Antichain<T> { Antichain { elements: Vec::new() } }
pub fn from_elem(element: T) -> Antichain<T> { Antichain { elements: vec![element] } }
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.elements[..] }
#[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: 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
}
}
#[derive(Clone, Debug, Abomonation, Serialize, Deserialize)]
pub struct MutableAntichain<T: PartialOrder+Ord> {
dirty: usize,
updates: Vec<(T, i64)>,
frontier: Vec<T>,
changes: ChangeBatch<T>,
}
impl<T: PartialOrder+Ord+Clone> MutableAntichain<T> {
#[inline]
pub fn new() -> MutableAntichain<T> {
MutableAntichain {
dirty: 0,
updates: Vec::new(),
frontier: Vec::new(),
changes: ChangeBatch::new(),
}
}
#[inline]
pub fn clear(&mut self) {
self.dirty = 0;
self.updates.clear();
self.frontier.clear();
self.changes.clear();
}
pub fn empty(&mut self) {
for index in 0 .. self.updates.len() { self.updates[index].1 = 0; }
self.dirty = self.updates.len();
}
#[inline]
pub fn frontier(&self) -> AntichainRef<T> {
debug_assert_eq!(self.dirty, 0);
AntichainRef::new(&self.frontier)
}
#[inline]
pub fn new_bottom(bottom: T) -> MutableAntichain<T> {
MutableAntichain {
dirty: 0,
updates: vec![(bottom.clone(), 1)],
frontier: vec![bottom],
changes: ChangeBatch::new(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
debug_assert_eq!(self.dirty, 0);
self.frontier.is_empty()
}
#[inline]
pub fn less_than(&self, time: &T) -> bool {
debug_assert_eq!(self.dirty, 0);
self.frontier().less_than(time)
}
#[inline]
pub fn less_equal(&self, time: &T) -> bool {
debug_assert_eq!(self.dirty, 0);
self.frontier().less_equal(time)
}
#[inline]
pub fn update_dirty(&mut self, time: T, delta: i64) {
self.updates.push((time, delta));
self.dirty += 1;
}
#[inline]
pub fn update_iter<'a, I>(&'a mut self, updates: I) -> ::std::vec::Drain<'a, (T, i64)>
where
I: IntoIterator<Item = (T, i64)>,
{
for (time, delta) in updates {
self.updates.push((time, delta));
self.dirty += 1;
}
let mut rebuild_required = false;
while self.dirty > 0 && !rebuild_required {
let time = &self.updates[self.updates.len() - self.dirty].0;
let delta = self.updates[self.updates.len() - self.dirty].1;
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 = rebuild_required || !(beyond_frontier || (delta < 0 && before_frontier));
self.dirty -= 1;
}
self.dirty = 0;
if rebuild_required {
self.rebuild()
}
self.changes.drain()
}
fn rebuild(&mut self) {
if !self.updates.is_empty() {
self.updates.sort_by(|x,y| x.0.cmp(&y.0));
for i in 0 .. self.updates.len() - 1 {
if self.updates[i].0 == self.updates[i+1].0 {
self.updates[i+1].1 += self.updates[i].1;
self.updates[i].1 = 0;
}
}
self.updates.retain(|x| x.1 != 0);
}
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(&self, query_time: &T) -> i64 {
self.updates
.iter()
.filter(|td| td.0.eq(query_time))
.map(|td| td.1)
.sum()
}
}
pub trait MutableAntichainFilter<T: PartialOrder+Ord+Clone> {
fn filter_through(self, antichain: &mut MutableAntichain<T>) -> ::std::vec::Drain<(T,i64)>;
}
impl<T: PartialOrder+Ord+Clone, I: IntoIterator<Item=(T,i64)>> MutableAntichainFilter<T> for I {
fn filter_through(self, antichain: &mut MutableAntichain<T>) -> ::std::vec::Drain<(T,i64)> {
antichain.update_iter(self.into_iter())
}
}
#[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 {
frontier: self.frontier.clone(),
}
}
}
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.to_vec()
}
}
}
impl<'a, T: 'a+PartialOrder> AntichainRef<'a, T> {
#[inline]
pub fn less_than(&self, time: &T) -> bool {
self.iter().any(|x| x.less_than(time))
}
#[inline]
pub fn less_equal(&self, time: &T) -> bool {
self.iter().any(|x| x.less_equal(time))
}
}
impl<'a, T: PartialEq> PartialEq for AntichainRef<'a, 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<'a, T: Eq> Eq for AntichainRef<'a, T> { }
impl<'a, T: PartialOrder> PartialOrder for AntichainRef<'a, T> {
fn less_equal(&self, other: &Self) -> bool {
other.iter().all(|t2| self.iter().any(|t1| t1.less_equal(t2)))
}
}
impl<'a, T> ::std::ops::Deref for AntichainRef<'a, 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()
}
}