use crate::progress::ChangeBatch;
use crate::order::PartialOrder;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
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 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 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))
}
#[inline]
pub fn dominates(&self, other: &Antichain<T>) -> bool {
other.elements().iter().all(|t2| self.elements().iter().any(|t1| t1.less_equal(t2)))
}
#[inline] pub fn elements(&self) -> &[T] { &self.elements[..] }
}
#[derive(Clone, Debug)]
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()
}
#[inline]
#[deprecated(since="0.8.0", note="`update_iter` now provides an iterator as output")]
pub fn update_iter_and<I, A>(&mut self, updates: I, mut action: A)
where
I: IntoIterator<Item = (T, i64)>,
A: FnMut(&T, i64)
{
self.update_iter(updates)
.for_each(|(time, diff)| action(&time, diff));
}
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(PartialEq, Eq)]
pub struct AntichainRef<'a, T: 'a+PartialOrder> {
frontier: &'a [T],
}
impl<'a, T: 'a+PartialOrder> AntichainRef<'a, T> {
pub fn new(frontier: &'a [T]) -> Self {
Self {
frontier,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.frontier.is_empty()
}
pub fn iter(&self) -> ::std::slice::Iter<T> {
self.frontier.iter()
}
#[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))
}
pub fn len(&self) -> usize {
self.frontier.len()
}
pub fn to_vec(&self) -> Vec<T> where T: Clone {
self.frontier.to_vec()
}
}
impl<'a, T: PartialOrder> ::std::ops::Deref for AntichainRef<'a, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.frontier
}
}
impl<'a, T: 'a+PartialOrder> ::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()
}
}