use std::collections::BTreeMap;
use std::fmt;
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Unification<T> {
parents: Vec<T>,
sizes: Vec<u32>,
}
impl<T: Copy + PartialEq + From<u32> + Into<u32>> Unification<T> {
pub fn new() -> Self {
Unification {
parents: Vec::new(),
sizes: Vec::new(),
}
}
pub fn root(&mut self, mut el: T) -> T {
let mut parent = self.parents[el.into() as usize];
while el != parent {
self.parents[el.into() as usize] = self.parents[parent.into() as usize];
el = parent;
parent = self.parents[parent.into() as usize];
}
el
}
pub fn root_const(&self, mut el: T) -> T {
let mut parent = self.parents[el.into() as usize];
while el != parent {
el = parent;
parent = self.parents[el.into() as usize];
}
el
}
pub fn union_roots_into(&mut self, lhs: T, rhs: T) {
assert!(lhs == self.root(lhs));
assert!(rhs == self.root(rhs));
self.parents[lhs.into() as usize] = rhs;
}
pub fn increase_size_to(&mut self, new_size: usize) {
assert!(new_size >= self.len());
assert!((u32::MAX as usize) > new_size);
for i in self.len()..new_size {
self.parents.push(T::from(i as u32));
}
}
pub fn len(&self) -> usize {
self.parents.len()
}
}
impl<T: Copy + PartialEq + From<u32> + Into<u32> + PartialOrd + Ord> Unification<T> {
pub fn classes(&self) -> BTreeMap<T, Vec<T>> {
let mut result = BTreeMap::new();
for p in 0..self.parents.len() {
let p = T::from(p as u32);
let root = self.root_const(p);
if !result.contains_key(&root) {
result.insert(root, Vec::new());
}
let class_els = result.get_mut(&root).unwrap();
if p != root {
class_els.push(p);
}
}
result
}
}
impl<T: Copy + PartialEq + From<u32> + Into<u32> + PartialOrd + Ord + fmt::Display> Unification<T> {}