algebraeon_sets/structure/
morphism.rs1use itertools::Itertools;
2
3use super::*;
4use std::fmt::Debug;
5use std::marker::PhantomData;
6
7pub trait Morphism<Domain: Structure, Range: Structure>: Debug + Clone {
8 fn domain(&self) -> &Domain;
9 fn range(&self) -> &Range;
10}
11
12pub trait Function<Domain: SetStructure, Range: SetStructure>: Morphism<Domain, Range> {
13 fn image(&self, x: &Domain::Set) -> Range::Set;
14}
15
16pub trait InjectiveFunction<Domain: SetStructure, Range: SetStructure>:
17 Function<Domain, Range>
18{
19 fn try_preimage(&self, x: &Range::Set) -> Option<Domain::Set>;
20}
21
22pub trait BijectiveFunction<Domain: SetStructure, Range: SetStructure>:
23 InjectiveFunction<Domain, Range>
24{
25 fn preimage(&self, x: &Range::Set) -> Domain::Set {
26 self.try_preimage(x).unwrap()
27 }
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct IdentityMorphism<X: Structure> {
33 x: X,
34}
35
36impl<X: Structure> IdentityMorphism<X> {
37 pub fn new(x: X) -> Self {
38 Self { x }
39 }
40}
41
42impl<X: Structure> Morphism<X, X> for IdentityMorphism<X> {
43 fn domain(&self) -> &X {
44 &self.x
45 }
46
47 fn range(&self) -> &X {
48 &self.x
49 }
50}
51
52impl<X: SetStructure> Function<X, X> for IdentityMorphism<X> {
53 fn image(&self, x: &X::Set) -> X::Set {
54 x.clone()
55 }
56}
57
58impl<X: SetStructure> InjectiveFunction<X, X> for IdentityMorphism<X> {
59 fn try_preimage(&self, x: &X::Set) -> Option<X::Set> {
60 Some(x.clone())
61 }
62}
63
64impl<X: SetStructure> BijectiveFunction<X, X> for IdentityMorphism<X> {}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct CompositionMorphism<
69 A: Structure,
70 B: Structure,
71 C: Structure,
72 AB: Morphism<A, B>,
73 BC: Morphism<B, C>,
74> {
75 a: PhantomData<A>,
76 b: PhantomData<B>,
77 c: PhantomData<C>,
78 a_to_b: AB,
80 b_to_c: BC,
81}
82
83impl<A: Structure, B: Structure, C: Structure, AB: Morphism<A, B>, BC: Morphism<B, C>>
84 CompositionMorphism<A, B, C, AB, BC>
85{
86 pub fn new(a_to_b: AB, b_to_c: BC) -> Self {
87 assert_eq!(a_to_b.range(), b_to_c.domain());
88 Self {
89 a: PhantomData,
90 b: PhantomData,
91 c: PhantomData,
92 a_to_b,
93 b_to_c,
94 }
95 }
96
97 pub fn a(&self) -> &A {
98 self.a_to_b.domain()
99 }
100
101 pub fn b(&self) -> &B {
102 let b = self.a_to_b.range();
103 debug_assert_eq!(b, self.b_to_c.domain());
104 b
105 }
106
107 pub fn c(&self) -> &C {
108 self.b_to_c.range()
109 }
110
111 pub fn a_to_b(&self) -> &AB {
112 &self.a_to_b
113 }
114
115 pub fn b_to_c(&self) -> &BC {
116 &self.b_to_c
117 }
118}
119
120impl<A: Structure, B: Structure, C: Structure, AB: Morphism<A, B>, BC: Morphism<B, C>>
121 Morphism<A, C> for CompositionMorphism<A, B, C, AB, BC>
122{
123 fn domain(&self) -> &A {
124 self.a()
125 }
126
127 fn range(&self) -> &C {
128 self.c()
129 }
130}
131
132impl<A: SetStructure, B: SetStructure, C: SetStructure, AB: Function<A, B>, BC: Function<B, C>>
133 Function<A, C> for CompositionMorphism<A, B, C, AB, BC>
134{
135 fn image(&self, x: &A::Set) -> C::Set {
136 self.b_to_c.image(&self.a_to_b.image(x))
137 }
138}
139
140impl<
141 A: SetStructure,
142 B: SetStructure,
143 C: SetStructure,
144 AB: InjectiveFunction<A, B>,
145 BC: InjectiveFunction<B, C>,
146> InjectiveFunction<A, C> for CompositionMorphism<A, B, C, AB, BC>
147{
148 fn try_preimage(&self, x: &C::Set) -> Option<A::Set> {
149 self.a_to_b.try_preimage(&self.b_to_c.try_preimage(x)?)
150 }
151}
152
153impl<
154 A: SetStructure,
155 B: SetStructure,
156 C: SetStructure,
157 AB: BijectiveFunction<A, B>,
158 BC: BijectiveFunction<B, C>,
159> BijectiveFunction<A, C> for CompositionMorphism<A, B, C, AB, BC>
160{
161 fn preimage(&self, x: &C::Set) -> A::Set {
162 self.a_to_b.preimage(&self.b_to_c.preimage(x))
163 }
164}
165
166pub trait MorphismsStructure<Domain: Structure, Range: Structure>: SetStructure
167where
168 Self::Set: Morphism<Domain, Range>,
169{
170}
171
172#[derive(Debug, Clone, PartialEq, Eq)]
174pub struct Functions<Domain: SetStructure, Range: SetStructure> {
175 domain: Domain,
176 range: Range,
177}
178
179impl<Domain: SetStructure, Range: SetStructure> Functions<Domain, Range> {
180 pub fn new(domain: Domain, range: Range) -> Self {
181 Self { domain, range }
182 }
183}
184
185impl<Domain: SetStructure, Range: SetStructure> Structure for Functions<Domain, Range> {}
186
187impl<Domain: FiniteSetStructure, Range: EqStructure> SetStructure for Functions<Domain, Range> {
188 type Set = Vec<Range::Set>;
189
190 fn is_element(&self, x: &Self::Set) -> bool {
191 x.len() == self.domain.size() && x.iter().all(|y| self.range.is_element(y))
192 }
193}
194
195impl<Domain: FiniteSetStructure, Range: EqStructure + FiniteSetStructure> CountableSetStructure
196 for Functions<Domain, Range>
197{
198 fn generate_all_elements(&self) -> impl Iterator<Item = Self::Set> {
199 (0..self.domain.size())
200 .map(|_| self.range.list_all_elements())
201 .multi_cartesian_product()
202 }
203}
204
205impl<Domain: FiniteSetStructure, Range: EqStructure + FiniteSetStructure> FiniteSetStructure
206 for Functions<Domain, Range>
207{
208}