Skip to main content

inertia_algebra/structures/
grouplike.rs

1
2use crate::*;
3
4pub type Elem<T> = <T as Parent>::Element;
5pub type Par<T> = <T as Element>::Parent;
6
7pub trait Parent: Clone {
8    type Element: Element<Parent=Self>;
9}
10
11pub trait Element: Clone + PartialEq {
12    type Parent: Parent<Element=Self>;
13    
14    fn parent(&self) -> Self::Parent;
15}
16
17/// A magma is an algebraic structure which consists of a set equipped with a 
18/// binary operation, ∘, which must be closed.
19///
20/// # Closed binary operation
21///
22/// ~~~notrust
23/// a, b ∈ Self ⇒ a ∘ b ∈ Self
24/// ~~~
25pub trait AbstractMagma<O: Operator>: 
26    Parent<Element=<Self as AbstractMagma<O>>::Element> 
27{
28    type Element: AbstractMagmaElement<O, Parent=Self>;
29    fn is_abstract_magma(&self, _: O) -> bool { true }
30}
31
32pub trait AbstractMagmaElement<O: Operator>:
33    Element<Parent=<Self as AbstractMagmaElement<O>>::Parent>
34    + Operation<O>
35{
36    type Parent: AbstractMagma<O, Element=Self>;
37}
38
39impl<T, O: Operator> AbstractMagma<O> for T
40where
41    T: Parent,
42    Elem<T>: Operation<O>
43{
44    type Element = Elem<T>;
45}
46
47impl<T, O: Operator> AbstractMagmaElement<O> for T
48where
49    T: Element + Operation<O>
50{
51    type Parent = Par<T>;
52}
53
54/// A quasigroup is a magma which that has the **divisibility property** (or Latin 
55/// square property).
56/// *A set with a closed binary operation with the divisibility property.*
57///
58/// Divisibility is a weak form of right and left invertibility.
59///
60/// # Divisibility or Latin square property
61///
62/// ```notrust
63/// ∀ a, b ∈ Self, ∃! r, l ∈ Self such that l ∘ a = b and a ∘ r = b
64/// ```
65///
66/// The solution to these equations can be written as
67///
68/// ```notrust
69/// r = a \ b and l = b / a
70/// ```
71///
72/// where "\" and "/" are respectively the **left** and **right** division.
73pub trait AbstractQuasigroup<O: Operator>: 
74    AbstractMagma<O, Element=<Self as AbstractQuasigroup<O>>::Element>
75    + Divisible<O>
76{
77    type Element: AbstractQuasigroupElement<O, Parent=Self>;
78    fn is_abstract_quasigroup(&self, _: O) -> bool { true }
79}
80
81pub trait AbstractQuasigroupElement<O: Operator>:
82    AbstractMagmaElement<O, Parent=<Self as AbstractQuasigroupElement<O>>::Parent>
83    + TwoSidedInverse<O>
84{
85    type Parent: AbstractQuasigroup<O, Element=Self>;
86}
87
88impl<T, O: Operator> AbstractQuasigroup<O> for T
89where
90    T: AbstractMagma<O> + Divisible<O>,
91    Elem<T>: TwoSidedInverse<O>
92{
93    type Element = Elem<T>;
94}
95
96impl<T, O: Operator> AbstractQuasigroupElement<O> for T
97where
98    T: AbstractMagmaElement<O> + TwoSidedInverse<O>,
99    Par<T>: Divisible<O>
100{
101    type Parent = Par<T>;
102}
103
104/// A semigroup is a quasigroup that is **associative**.
105///
106/// *A semigroup is a set equipped with a closed associative binary operation and that has the divisibility property.*
107///
108/// # Associativity
109///
110/// ~~~notrust
111/// ∀ a, b, c ∈ Self, (a ∘ b) ∘ c = a ∘ (b ∘ c)
112/// ~~~
113pub trait AbstractSemigroup<O: Operator>: 
114    AbstractMagma<O, Element=<Self as AbstractSemigroup<O>>::Element> 
115    + Associative<O>
116{
117    type Element: AbstractSemigroupElement<O, Parent=Self>;
118    fn is_abstract_semigroup(&self, _: O) -> bool { true }
119}
120
121pub trait AbstractSemigroupElement<O: Operator>: 
122    AbstractMagmaElement<O, Parent=<Self as AbstractSemigroupElement<O>>::Parent>
123{
124    type Parent: AbstractSemigroup<O, Element=Self>;
125}
126
127impl<T, O: Operator> AbstractSemigroup<O> for T
128where
129    T: AbstractMagma<O> + Associative<O>,
130{
131    type Element = Elem<T>;
132}
133
134impl<T, O: Operator> AbstractSemigroupElement<O> for T
135where
136    T: AbstractMagmaElement<O>,
137    Par<T>: Associative<O>
138{
139    type Parent = Par<T>;
140}
141
142/// A loop is a quasigroup with an unique **identity element**, e.
143///
144/// *A set equipped with a closed binary operation possessing the divisibility property
145/// and a unique identity element.*
146///
147/// # Identity element
148///
149/// ~~~notrust
150/// ∃! e ∈ Self, ∀ a ∈ Self, ∃ r, l ∈ Self such that l ∘ a = a ∘ r = e.
151/// ~~~
152///
153/// The left inverse `r` and right inverse `l` are not required to be equal.
154///
155/// This property follows from
156///
157/// ~~~notrust
158/// ∀ a ∈ Self, ∃ e ∈ Self, such that e ∘ a = a ∘ e = a.
159/// ~~~
160pub trait AbstractLoop<O: Operator>: 
161    AbstractQuasigroup<O, Element=<Self as AbstractLoop<O>>::Element> 
162    + Identity<O> 
163{
164    type Element: AbstractLoopElement<O, Parent=Self>;
165    fn is_abstract_loop(&self, _: O) -> bool { true }
166}
167
168pub trait AbstractLoopElement<O: Operator>: 
169    AbstractQuasigroupElement<O, Parent=<Self as AbstractLoopElement<O>>::Parent>
170    + IsIdentity<O> 
171{
172    type Parent: AbstractLoop<O, Element=Self>;
173
174}
175
176impl<T, O: Operator> AbstractLoop<O> for T
177where
178    T: AbstractQuasigroup<O> + Identity<O>,
179    Elem<T>: IsIdentity<O>
180{
181    type Element = Elem<T>;
182}
183
184impl<T, O: Operator> AbstractLoopElement<O> for T
185where
186    T: AbstractQuasigroupElement<O> + IsIdentity<O>,
187    Par<T>: Identity<O>
188{
189    type Parent = Par<T>;
190}
191
192/// A monoid is a semigroup equipped with an identity element, e.
193///
194/// *A set equipped with a closed associative binary operation with the divisibility property and
195/// an identity element.*
196///
197/// # Identity element
198///
199/// ~~~notrust
200/// ∃ e ∈ Self, ∀ a ∈ Self, e ∘ a = a ∘ e = a
201/// ~~~
202pub trait AbstractMonoid<O: Operator>: 
203    AbstractSemigroup<O, Element=<Self as AbstractMonoid<O>>::Element> 
204    + Identity<O> 
205{
206    type Element: AbstractMonoidElement<O, Parent=Self>;
207    fn is_abstract_monoid(&self, _: O) -> bool { true }
208}
209
210pub trait AbstractMonoidElement<O: Operator>: 
211    AbstractSemigroupElement<O, Parent=<Self as AbstractMonoidElement<O>>::Parent> 
212    + IsIdentity<O> 
213{
214    type Parent: AbstractMonoid<O, Element=Self>;
215}
216
217impl<T, O: Operator> AbstractMonoid<O> for T
218where
219    T: AbstractSemigroup<O> + Identity<O>,
220    Elem<T>: IsIdentity<O>
221{
222    type Element = Elem<T>;
223}
224
225impl<T, O: Operator> AbstractMonoidElement<O> for T
226where
227    T: AbstractSemigroupElement<O> + IsIdentity<O>,
228    Par<T>: Identity<O>
229{
230    type Parent = Par<T>;
231}
232
233/// A group is a loop and a monoid  at the same time.
234///
235/// *A groups is a set with a closed associative binary operation with the divisibility property and an identity element.*
236pub trait AbstractGroup<O: Operator>: 
237    AbstractLoop<O, Element=<Self as AbstractGroup<O>>::Element> 
238    + Associative<O>
239{
240    type Element: AbstractGroupElement<O, Parent=Self>;
241    fn is_abstract_group(&self, _: O) -> bool { true }
242}
243
244pub trait AbstractGroupElement<O: Operator>: 
245    AbstractLoopElement<O, Parent=<Self as AbstractGroupElement<O>>::Parent> 
246{
247    type Parent: AbstractGroup<O, Element=Self>;
248}
249
250impl<T, O: Operator> AbstractGroup<O> for T
251where
252    T: AbstractLoop<O> + Associative<O>,
253{
254    type Element = Elem<T>;
255}
256
257impl<T, O: Operator> AbstractGroupElement<O> for T
258where
259    T: AbstractLoopElement<O>,
260    Par<T>: Associative<O>
261{
262    type Parent = Par<T>;
263}
264
265/// An Abelian group is a **commutative** group.
266///
267/// *An commutative group is a set with a closed commutative and associative binary operation with the divisibility property and an identity element.*
268///
269/// # Commutativity
270///
271/// ```notrust
272/// ∀ a, b ∈ Self, a ∘ b = b ∘ a
273/// ```
274pub trait AbstractGroupAbelian<O: Operator>: 
275    AbstractGroup<O, Element=<Self as AbstractGroupAbelian<O>>::Element> 
276    + Commutative<O>
277{
278    type Element: AbstractGroupAbelianElement<O, Parent=Self>;
279    fn is_abstract_group_abelian(&self, _: O) -> bool { true }
280}
281
282pub trait AbstractGroupAbelianElement<O: Operator>: 
283    AbstractGroupElement<O, Parent=<Self as AbstractGroupAbelianElement<O>>::Parent> 
284{
285    type Parent: AbstractGroupAbelian<O, Element=Self>;
286}
287
288impl<T, O: Operator> AbstractGroupAbelian<O> for T
289where
290    T: AbstractGroup<O> + Commutative<O>,
291{
292    type Element = Elem<T>;
293}
294
295impl<T, O: Operator> AbstractGroupAbelianElement<O> for T
296where
297    T: AbstractGroupElement<O>,
298    Par<T>: Commutative<O>
299{
300    type Parent = Par<T>;
301}