use im::{ordmap, ordset, OrdMap, OrdSet};
use itertools::Itertools;
use std::{
borrow::Borrow,
collections::{BTreeMap, BTreeSet},
fmt::Debug,
ops::{Deref, DerefMut},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum JoinResult {
Unchanged,
Changed,
}
impl JoinResult {
pub fn combine(self, other: JoinResult) -> JoinResult {
use JoinResult::*;
match (self, other) {
(Unchanged, Unchanged) => Unchanged,
_ => Changed,
}
}
}
pub trait AbstractDomain {
fn join(&mut self, other: &Self) -> JoinResult;
}
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct SetDomain<E: Ord + Clone>(OrdSet<E>);
impl<E: Ord + Clone> Default for SetDomain<E> {
fn default() -> Self {
Self(OrdSet::default())
}
}
impl<E: Ord + Clone> From<OrdSet<E>> for SetDomain<E> {
fn from(ord_set: OrdSet<E>) -> Self {
Self(ord_set)
}
}
impl<E: Ord + Clone> AsRef<OrdSet<E>> for SetDomain<E> {
fn as_ref(&self) -> &OrdSet<E> {
&self.0
}
}
impl<E: Ord + Clone> Borrow<OrdSet<E>> for SetDomain<E> {
fn borrow(&self) -> &OrdSet<E> {
self.as_ref()
}
}
impl<E: Ord + Clone> Deref for SetDomain<E> {
type Target = OrdSet<E>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<E: Ord + Clone> DerefMut for SetDomain<E> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<E: Ord + Clone + Debug> Debug for SetDomain<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.0)
}
}
impl<E: Ord + Clone> std::iter::FromIterator<E> for SetDomain<E> {
fn from_iter<I: IntoIterator<Item = E>>(iter: I) -> Self {
let mut s = SetDomain::default();
for e in iter {
s.insert(e);
}
s
}
}
impl<E: Ord + Clone> std::iter::IntoIterator for SetDomain<E> {
type Item = E;
type IntoIter = im::ordset::ConsumingIter<E>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<E: Ord + Clone> AbstractDomain for SetDomain<E> {
fn join(&mut self, other: &Self) -> JoinResult {
let mut change = JoinResult::Unchanged;
for e in other.iter() {
if self.insert(e.clone()).is_none() {
change = JoinResult::Changed;
}
}
change
}
}
impl<E: Ord + Clone> From<BTreeSet<E>> for SetDomain<E> {
fn from(s: BTreeSet<E>) -> Self {
s.into_iter().collect()
}
}
impl<E: Ord + Clone> SetDomain<E> {
pub fn singleton(e: E) -> Self {
ordset!(e).into()
}
pub fn difference<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = &'a E> {
self.iter().filter(move |e| !other.contains(e))
}
pub fn is_disjoint(&self, other: &Self) -> bool {
self.iter().all(move |e| !other.contains(e))
}
}
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct MapDomain<K: Ord, V: AbstractDomain>(OrdMap<K, V>);
impl<K: Ord + Clone, V: AbstractDomain + Clone> Default for MapDomain<K, V> {
fn default() -> Self {
Self(OrdMap::default())
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> From<OrdMap<K, V>> for MapDomain<K, V> {
fn from(ord_map: OrdMap<K, V>) -> Self {
Self(ord_map)
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> AsRef<OrdMap<K, V>> for MapDomain<K, V> {
fn as_ref(&self) -> &OrdMap<K, V> {
&self.0
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> Borrow<OrdMap<K, V>> for MapDomain<K, V> {
fn borrow(&self) -> &OrdMap<K, V> {
self.as_ref()
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> Deref for MapDomain<K, V> {
type Target = OrdMap<K, V>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> DerefMut for MapDomain<K, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<K: Ord + Clone + Debug, V: AbstractDomain + Clone + Debug> Debug for MapDomain<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.0)
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> std::iter::FromIterator<(K, V)>
for MapDomain<K, V>
{
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
let mut s = MapDomain::default();
for (k, v) in iter {
s.insert(k, v);
}
s
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> std::iter::IntoIterator for MapDomain<K, V> {
type Item = (K, V);
type IntoIter = im::ordmap::ConsumingIter<(K, V)>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> AbstractDomain for MapDomain<K, V> {
fn join(&mut self, other: &Self) -> JoinResult {
let mut change = JoinResult::Unchanged;
for (k, v) in other.iter() {
change = change.combine(self.insert_join(k.clone(), v.clone()));
}
change
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> From<BTreeMap<K, V>> for MapDomain<K, V> {
fn from(m: BTreeMap<K, V>) -> Self {
m.into_iter().collect()
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone> MapDomain<K, V> {
pub fn singleton(k: K, v: V) -> MapDomain<K, V> {
(ordmap! {k => v}).into()
}
pub fn insert_join(&mut self, k: K, v: V) -> JoinResult {
let mut change = JoinResult::Unchanged;
self.0
.entry(k)
.and_modify(|old_v| {
change = old_v.join(&v);
})
.or_insert_with(|| {
change = JoinResult::Changed;
v
});
change
}
}
impl<K: Ord + Clone, V: AbstractDomain + Clone + PartialEq> MapDomain<K, V> {
pub fn update_values(&mut self, mut f: impl FnMut(&mut V)) {
let new_values = self
.iter()
.filter_map(|(k, v)| {
let mut v_new = v.clone();
f(&mut v_new);
if v != &v_new {
Some((k.clone(), v_new))
} else {
None
}
})
.collect_vec();
self.extend(new_values.into_iter());
}
}