use crate::combinatorics::*;
use crate::iterators::*;
use canonical_form::Canonize;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::cmp;
use std::collections::BTreeSet;
use std::fmt;
use std::fmt::{Debug, Display};
use std::marker::PhantomData;
pub trait Flag
where
Self: Canonize + Debug + Display + Serialize + DeserializeOwned,
{
fn induce(&self, set: &[usize]) -> Self;
fn all_flags(n: usize) -> Vec<Self>;
fn superflags(&self) -> Vec<Self>;
const NAME: &'static str;
const HEREDITARY: bool = true;
fn generate_next(previous: &[Self]) -> Vec<Self> {
let mut res: BTreeSet<Self> = BTreeSet::new();
for g in previous {
for h in g.superflags() {
let _ = res.insert(h.canonical());
}
}
res.into_iter().collect()
}
fn generate(n: usize) -> Vec<Self> {
if n == 0 {
Self::all_flags(0)
} else {
Self::generate_next(&Self::generate(n - 1))
}
}
fn generate_typed_up(type_flag: &Self, g_vec: &[Self]) -> Vec<Self> {
assert!(g_vec.len() != 0);
let n = g_vec[0].size();
let k = type_flag.size();
assert!(k <= n);
let mut res: BTreeSet<Self> = BTreeSet::new();
for g in g_vec {
let mut iter = Choose::new(n, k);
while let Some(pre_selection) = iter.next() {
if &g.induce(pre_selection).canonical() == type_flag {
let mut iter2 = Injection::permutation(k);
while let Some(select2) = iter2.next() {
let selection = &compose(pre_selection, select2);
let h = g.induce(selection);
if &h == type_flag {
let p = invert(&permutation_of_injection(n, selection));
let _ = res.insert(g.apply_morphism(&p).canonical_typed(k));
}
}
}
}
}
res.into_iter().collect()
}
fn generate_typed(type_flag: &Self, size: usize) -> Vec<Self> {
Self::generate_typed_up(type_flag, &Self::generate(size))
}
fn select_type(&self, eta: &[usize]) -> Self {
let type_selector = invert(&permutation_of_injection(self.size(), eta));
self.apply_morphism(&type_selector)
}
}
pub struct SubClass<F, A> {
pub content: F,
phantom: PhantomData<A>,
}
impl<F, A> From<F> for SubClass<F, A> {
#[inline]
fn from(x: F) -> Self {
Self {
content: x,
phantom: PhantomData,
}
}
}
impl<F: Flag, A> Clone for SubClass<F, A> {
#[inline]
fn clone(&self) -> Self {
self.content.clone().into()
}
}
impl<F: Flag, A> Serialize for SubClass<F, A> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.content.serialize(serializer)
}
}
impl<'de, F: Flag, A> Deserialize<'de> for SubClass<F, A> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
F::deserialize(deserializer).map(Into::into)
}
}
impl<F: Flag, A> Display for SubClass<F, A> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.content, f)
}
}
impl<F: Flag, A> Debug for SubClass<F, A> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.content, f)
}
}
impl<F: Flag, A> PartialEq for SubClass<F, A> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.content.eq(&other.content)
}
}
impl<F: Flag, A> Eq for SubClass<F, A> {}
impl<F: Flag, A> PartialOrd for SubClass<F, A> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<F: Flag, A> Ord for SubClass<F, A> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.content.cmp(&other.content)
}
}
pub trait SubFlag<F>
where
F: Flag,
Self: Sized,
{
fn is_in_subclass(flag: &F) -> bool;
const SUBCLASS_NAME: &'static str;
const HEREDITARY: bool = true;
}
impl<F, A> Canonize for SubClass<F, A>
where
F: Flag,
{
#[inline]
fn size(&self) -> usize {
self.content.size()
}
fn invariant_neighborhood(&self, v: usize) -> Vec<Vec<usize>> {
self.content.invariant_neighborhood(v)
}
fn apply_morphism(&self, p: &[usize]) -> Self {
self.content.apply_morphism(p).into()
}
}
impl<F, A> Flag for SubClass<F, A>
where
A: SubFlag<F>,
F: Flag,
{
const NAME: &'static str = A::SUBCLASS_NAME;
const HEREDITARY: bool = A::HEREDITARY;
fn superflags(&self) -> Vec<Self> {
let mut res = Vec::new();
for flag in self.content.superflags().into_iter() {
if A::is_in_subclass(&flag) {
res.push(flag.into())
}
}
res
}
fn induce(&self, p: &[usize]) -> Self {
self.content.induce(p).into()
}
fn all_flags(n: usize) -> Vec<Self> {
F::all_flags(n).into_iter().map(Into::into).collect()
}
}