use crate::finite_function::FiniteFunction;
use crate::lax::functor::*;
use crate::lax::var::*;
use crate::lax::*;
pub fn forget<
O: Clone + PartialEq + std::fmt::Debug,
A: Clone + PartialEq + HasVar + std::fmt::Debug,
>(
f: &OpenHypergraph<O, A>,
) -> OpenHypergraph<O, A> {
Forget.map_arrow(f)
}
pub fn forget_monogamous<
O: Clone + PartialEq + std::fmt::Debug,
A: Clone + PartialEq + HasVar + std::fmt::Debug,
>(
f: &OpenHypergraph<O, A>,
) -> OpenHypergraph<O, A> {
ForgetMonogamous.map_arrow(f)
}
#[derive(Clone)]
pub struct Forget;
impl<O: Clone + PartialEq, A: HasVar + Clone + PartialEq> Functor<O, A, O, A> for Forget {
fn map_object(&self, o: &O) -> impl ExactSizeIterator<Item = O> {
std::iter::once(o.clone())
}
fn map_operation(&self, a: &A, source: &[O], target: &[O]) -> OpenHypergraph<O, A> {
if *a == HasVar::var() && all_elements_equal(source, target) {
if source.is_empty() && target.is_empty() {
return OpenHypergraph::empty();
}
let label = {
if source.is_empty() {
target[0].clone()
} else {
source[0].clone()
}
};
let s = FiniteFunction::terminal(source.len());
let t = FiniteFunction::terminal(target.len());
return OpenHypergraph::<O, A>::spider(s, t, vec![label]).unwrap();
}
OpenHypergraph::singleton(a.clone(), source.to_vec(), target.to_vec())
}
fn map_arrow(&self, f: &OpenHypergraph<O, A>) -> OpenHypergraph<O, A> {
dyn_functor::define_map_arrow(self, f)
}
}
fn all_elements_equal<T: PartialEq>(a: &[T], b: &[T]) -> bool {
a.iter()
.chain(b.iter())
.all(|x| *x == *a.first().unwrap_or(x))
}
#[derive(Clone)]
struct ForgetMonogamous;
impl<O: Clone + PartialEq + std::fmt::Debug, A: HasVar + Clone + PartialEq + std::fmt::Debug>
Functor<O, A, O, A> for ForgetMonogamous
{
fn map_object(&self, o: &O) -> impl ExactSizeIterator<Item = O> {
std::iter::once(o.clone())
}
fn map_operation(&self, a: &A, source: &[O], target: &[O]) -> OpenHypergraph<O, A> {
if source.len() != 1 || target.len() != 1 {
return OpenHypergraph::singleton(a.clone(), source.to_vec(), target.to_vec());
}
if *a == HasVar::var() && all_elements_equal(source, target) {
if source.is_empty() && target.is_empty() {
return OpenHypergraph::empty();
}
let label = {
if source.is_empty() {
target[0].clone()
} else {
source[0].clone()
}
};
let s = FiniteFunction::terminal(source.len());
let t = FiniteFunction::terminal(target.len());
return OpenHypergraph::<O, A>::spider(s, t, vec![label]).unwrap();
}
OpenHypergraph::singleton(a.clone(), source.to_vec(), target.to_vec())
}
fn map_arrow(&self, f: &OpenHypergraph<O, A>) -> OpenHypergraph<O, A> {
dyn_functor::define_map_arrow(self, f)
}
}