use std::collections::BTreeMap;
mod coloring;
pub mod set;
mod tree;
pub use coloring::{Coloring, ReversibleColoring};
pub use set::Map;
pub use set::Set;
pub trait Normalize: Sized {
type Elements: Set;
type Color: Ord;
type Cache;
type Morphed: Ord;
fn initialize_cache(&self) -> Self::Cache;
fn elements(&self) -> &Self::Elements;
fn initial_coloring(&self) -> <Self::Elements as Set>::Map<Self::Color>;
fn refine_coloring(
&self,
_cache: &mut Self::Cache,
_coloring: &mut ReversibleColoring<Self::Elements>,
) {
}
fn apply_morphism<F>(&self, morphism: F) -> Self::Morphed
where
F: Fn(&<Self::Elements as Set>::Item) -> usize;
fn normal_form(&self) -> Self::Morphed
where
<Self::Elements as Set>::Map<usize>: Clone,
{
self.normalize().0
}
fn canonical_permutation(&self) -> <Self::Elements as Set>::Map<usize>
where
<Self::Elements as Set>::Map<usize>: Clone,
{
self.normalize().1
}
fn normalize(&self) -> (Self::Morphed, <Self::Elements as Set>::Map<usize>)
where
<Self::Elements as Set>::Map<usize>: Clone,
{
use std::collections::btree_map::Entry;
let mut cache = self.initialize_cache();
let elements = self.elements();
let initial_coloring = self.initial_coloring();
let mut node = Some(
tree::Node::root(ReversibleColoring::from_coloring(
elements,
Coloring::from_map(elements, &initial_coloring),
))
.into_first_child_leaf(|coloring| self.refine_coloring(&mut cache, coloring)),
);
pub struct Automorphism<T: Normalize> {
path: Vec<<T::Elements as Set>::Item>,
permutation: <T::Elements as Set>::Map<usize>,
}
let mut automorphisms: BTreeMap<Self::Morphed, Automorphism<Self>> = BTreeMap::new();
while let Some(mut n) = node {
debug_assert!(n.coloring().is_discrete());
let permutation = n.coloring().as_permutation().unwrap();
let morphed = self.apply_morphism(|i| *permutation.get(i).unwrap());
match automorphisms.entry(morphed) {
Entry::Occupied(entry) => {
let len = n.path().len();
let prefix_len = longest_common_prefix_len(n.path(), &entry.get().path);
n.restore(len - prefix_len - 1); }
Entry::Vacant(entry) => {
entry.insert(Automorphism {
path: n.path().clone(),
permutation: permutation.clone(),
});
}
}
node = n.into_next_leaf(|coloring| self.refine_coloring(&mut cache, coloring));
}
let (normal_form, data) = automorphisms.into_iter().next().unwrap();
(normal_form, data.permutation)
}
}
fn longest_common_prefix_len<T: PartialEq>(a: &[T], b: &[T]) -> usize {
let mut n = 0;
for (a, b) in a.iter().zip(b) {
if a == b {
n += 1
} else {
break;
}
}
n
}