open_hypergraphs/lax/var/
forget.rs1use crate::finite_function::FiniteFunction;
8use crate::lax::functor::*;
9use crate::lax::var::*;
10use crate::lax::*;
11
12pub fn forget<
14 O: Clone + PartialEq + std::fmt::Debug,
15 A: Clone + PartialEq + HasVar + std::fmt::Debug,
16>(
17 f: &OpenHypergraph<O, A>,
18) -> OpenHypergraph<O, A> {
19 Forget.map_arrow(f)
20}
21
22pub fn forget_monogamous<
24 O: Clone + PartialEq + std::fmt::Debug,
25 A: Clone + PartialEq + HasVar + std::fmt::Debug,
26>(
27 f: &OpenHypergraph<O, A>,
28) -> OpenHypergraph<O, A> {
29 ForgetMonogamous.map_arrow(f)
30}
31
32#[derive(Clone)]
46pub struct Forget;
47
48impl<O: Clone + PartialEq, A: HasVar + Clone + PartialEq> Functor<O, A, O, A> for Forget {
49 fn map_object(&self, o: &O) -> impl ExactSizeIterator<Item = O> {
51 std::iter::once(o.clone())
52 }
53
54 fn map_operation(&self, a: &A, source: &[O], target: &[O]) -> OpenHypergraph<O, A> {
55 if *a == HasVar::var() && all_elements_equal(source, target) {
57 if source.is_empty() && target.is_empty() {
59 return OpenHypergraph::empty();
60 }
61
62 let label = {
64 if source.is_empty() {
65 target[0].clone()
66 } else {
67 source[0].clone()
68 }
69 };
70
71 let s = FiniteFunction::terminal(source.len());
72 let t = FiniteFunction::terminal(target.len());
73
74 return OpenHypergraph::<O, A>::spider(s, t, vec![label]).unwrap();
75 }
76 OpenHypergraph::singleton(a.clone(), source.to_vec(), target.to_vec())
77 }
78
79 fn map_arrow(&self, f: &OpenHypergraph<O, A>) -> OpenHypergraph<O, A> {
80 dyn_functor::define_map_arrow(self, f)
81 }
82}
83
84fn all_elements_equal<T: PartialEq>(a: &[T], b: &[T]) -> bool {
86 a.iter()
87 .chain(b.iter())
88 .all(|x| *x == *a.first().unwrap_or(x))
89}
90
91#[derive(Clone)]
93struct ForgetMonogamous;
94
95impl<O: Clone + PartialEq + std::fmt::Debug, A: HasVar + Clone + PartialEq + std::fmt::Debug>
96 Functor<O, A, O, A> for ForgetMonogamous
97{
98 fn map_object(&self, o: &O) -> impl ExactSizeIterator<Item = O> {
100 std::iter::once(o.clone())
101 }
102
103 fn map_operation(&self, a: &A, source: &[O], target: &[O]) -> OpenHypergraph<O, A> {
104 if source.len() != 1 || target.len() != 1 {
105 return OpenHypergraph::singleton(a.clone(), source.to_vec(), target.to_vec());
106 }
107
108 if *a == HasVar::var() && all_elements_equal(source, target) {
110 if source.is_empty() && target.is_empty() {
112 return OpenHypergraph::empty();
113 }
114
115 let label = {
117 if source.is_empty() {
118 target[0].clone()
119 } else {
120 source[0].clone()
121 }
122 };
123
124 let s = FiniteFunction::terminal(source.len());
125 let t = FiniteFunction::terminal(target.len());
126
127 return OpenHypergraph::<O, A>::spider(s, t, vec![label]).unwrap();
128 }
129 OpenHypergraph::singleton(a.clone(), source.to_vec(), target.to_vec())
130 }
131
132 fn map_arrow(&self, f: &OpenHypergraph<O, A>) -> OpenHypergraph<O, A> {
133 dyn_functor::define_map_arrow(self, f)
134 }
135}