free_algebra/
monoid.rs

1//!
2//!Contains [MonoidalString] and the types and traits relevant to its system
3//!
4//!For more information see the struct-level docs
5//!
6
7use super::*;
8
9use std::ops::Index;
10use std::cmp::*;
11
12///
13///Creates free-arithmetic constructions based upon free-multiplication of letters of type `C`
14///that uses a [`Vec<C>`](Vec) internally
15///
16///# Basic Construction
17///
18///Given type parameters `C` and `M`, the construction goes as follows:
19/// * Internally, each instance contains a list of values of type `C`
20/// * By default, multiplication is given by concatenating the internal [`Vec`]'s  of each argument
21/// * Then, with the above as a base, the given type `M` can modify that operation by applying
22///   a multiplication rule to the internal list every time another `C` is appended to it
23///
24///With this system, using different `M` rules and `C` types, a number of variants can be defined:
25/// * [`FreeMonoid<C>`](FreeMonoid) is created by using the default multiplication with any `C`
26/// * [`FreeGroup<C>`](FreeGroup) is made by wrapping it in a [`FreeInv<C>`](FreeInv) to
27///  allow each `C` to be inverted and by and modifying `M` to make inverses cancel
28/// * [`FreePowMonoid<C,P>`](FreePowMonoid) is constructed by wrapping each `C` in a [`FreePow<C>`](FreePow)
29///  to raise each element to a symbolic power `P` and by having `M` combine any
30///  adjacent elements with equal base by adding their exponents
31///
32///# Other `impls`
33///
34///In addition to the basic multiplication traits, [MonoidalString] implements a number of other
35///notable traits depending on the type arguments:
36/// * [Div], [DivAssign], [Inv], etc. These apply whenever `M` implements
37/// * [Index] wraps the internal list's implementation
38///  [`InvMonoidRule<C>`](InvMonoidRule) to provide a way to invert `C` elements
39/// * [MulAssociative] and [MulCommutative] whenever `M` implements [AssociativeMonoidRule] or
40///  [CommutativeMonoidRule]
41/// * [PartialEq] with any type that implements [`Borrow<[C]>`](Borrow). This is in order to make
42///  it possible to test equality with other structures (like `Vec<C>` and `[C]`) that are lists
43///  of `C`'s
44/// * [PartialOrd] and [Ord] implement lexicographic ordering
45/// * [Extend], [FromIterator], and [Product] all are implemented by applying the multiplication
46///  rule to an [Iterator] of `C`'s.
47///
48///# A note on [IterMut]
49///
50///The method [MonoidalString.iter_mut()] *will* give an valid iterator over mutable references to each
51///element of the object, but it is of note that because of the nature of some of the [`MonoidRule`]'s,
52///the method will reallocate internal storage and iterate through *every* element,
53///even if dropped.
54///
55///The reason for this is that if it did not, it would be possible to modify a MonoidalString into
56///an invalid state. Hence, to mitigate this, the iterator must remultiply every element again as it
57///iterates over the references.
58///
59#[derive(Derivative)]
60#[derivative(Clone(clone_from="true"))]
61#[derivative(Default(bound=""))]
62#[derivative(Hash)]
63#[derivative(Debug="transparent")]
64pub struct MonoidalString<C,M:?Sized> {
65    #[derivative(Default(value="Vec::with_capacity(0)"))]
66    string: Vec<C>,
67
68    #[derivative(PartialEq="ignore", Hash="ignore")]
69    #[derivative(Debug="ignore")]
70    rule: PhantomData<M>
71}
72
73impl<C:Eq,M:?Sized> Eq for MonoidalString<C,M> {}
74impl<C:PartialEq,M:?Sized,V:Borrow<[C]>> PartialEq<V> for MonoidalString<C,M> {
75    fn eq(&self, rhs:&V) -> bool {Borrow::<[C]>::borrow(self) == Borrow::<[C]>::borrow(rhs)}
76    fn ne(&self, rhs:&V) -> bool {Borrow::<[C]>::borrow(self) != Borrow::<[C]>::borrow(rhs)}
77}
78
79impl<C:PartialOrd,M:?Sized> PartialOrd for MonoidalString<C,M> {
80    fn partial_cmp(&self, rhs:&Self) -> Option<Ordering> { self.string.partial_cmp(&rhs.string) }
81    fn lt(&self, rhs:&Self) -> bool { self.string.lt(&rhs.string) }
82    fn le(&self, rhs:&Self) -> bool { self.string.le(&rhs.string) }
83    fn gt(&self, rhs:&Self) -> bool { self.string.gt(&rhs.string) }
84    fn ge(&self, rhs:&Self) -> bool { self.string.ge(&rhs.string) }
85}
86
87impl<C:Ord,M:?Sized> Ord for MonoidalString<C,M> {
88    fn cmp(&self, rhs:&Self) -> Ordering { self.string.cmp(&rhs.string) }
89}
90
91///
92///Formats the [MonoidalString] as a sequence of factors separated by `*`'s
93///
94///# Examples
95///
96///```
97///use maths_traits::algebra::One;
98///use free_algebra::FreeMonoid;
99///
100///let x = FreeMonoid::one() * 'a' * 'b' * 'c';
101///assert_eq!(format!("{}", x), "a*b*c");
102///
103///```
104///
105///```
106///use maths_traits::algebra::*;
107///use free_algebra::FreeInv::*;
108///
109///let y = Id('a') * Inv('b') * Inv('a') * Id('c');
110///assert_eq!(format!("{}", y), "a*b⁻¹*a⁻¹*c");
111///```
112///
113///Note that if the "alternate" flag `#` is used, then the `*`'s will be dropped.
114///
115///```
116///use maths_traits::algebra::One;
117///use free_algebra::FreeMonoid;
118///
119///let x = FreeMonoid::one() * 'a' * 'b' * 'c';
120///assert_eq!(format!("{:#}", x), "abc");
121///
122///```
123///
124///```
125///use maths_traits::algebra::*;
126///use free_algebra::FreeInv::*;
127///
128///let y = Id('a') * Inv('b') * Inv('a') * Id('c');
129///assert_eq!(format!("{:#}", y), "ab⁻¹a⁻¹c");
130///```
131///
132impl<C:Display,M:?Sized> Display for MonoidalString<C,M> {
133    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {
134        if self.len()==0 {
135            write!(f, "{}", 1)
136        } else {
137            //print letters as a product
138            for i in 0..self.len() {
139                if i!=0 && !f.alternate() { write!(f, "*")? }
140                write!(f, "{}", self[i])?
141            }
142
143            //success
144            Ok(())
145        }
146    }
147}
148
149///Iterates over immutable references of the letters of a [MonoidalString]
150pub type Iter<'a,C> = std::slice::Iter<'a,C>;
151
152///Iterates over the letters of a [MonoidalString]
153pub type IntoIter<C> = <Vec<C> as IntoIterator>::IntoIter;
154
155///
156///Iterates over mutable references to the letters of a [MonoidalString]
157///
158///Note that this causes a reallocation of the internal [Vec] since it's possible that an
159///element mutation could create an illegal state if not reconstructed from the sums of the mutated
160///terms.
161///
162pub struct IterMut<'a, C, M:MonoidRule<C>+?Sized> {
163    dest_ref: &'a mut MonoidalString<C,M>,
164    next: Option<C>,
165    iter: IntoIter<C>
166}
167
168impl<'a,C,M:MonoidRule<C>+?Sized> FusedIterator for IterMut<'a,C,M> {}
169impl<'a,C,M:MonoidRule<C>+?Sized> ExactSizeIterator for IterMut<'a,C,M> {}
170impl<'a,C,M:MonoidRule<C>+?Sized> Iterator for IterMut<'a,C,M> {
171    type Item = &'a mut C;
172    fn next(&mut self) -> Option<&'a mut C> {
173        self.next.take().map(|c| *self.dest_ref *= c);
174        self.next = self.iter.next();
175
176        //we know that the given reference is lifetime 'a because in order for next to be dropped,
177        //either self must be borrowed mutably again or dropped, which cannot happen while the reference lives
178        self.next.as_mut().map(|c| unsafe {&mut *(c as *mut C)} )
179    }
180
181    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
182}
183
184impl<'a,C,M:MonoidRule<C>+?Sized> Drop for IterMut<'a,C,M> {
185    fn drop(&mut self) {
186        loop { if let None = self.next() {break;} }
187    }
188}
189
190impl<C,M:?Sized> From<C> for MonoidalString<C,M> {
191    #[inline] fn from(c:C) -> Self {MonoidalString{string:vec![c],rule:PhantomData}}
192}
193
194impl<C,M:?Sized> AsRef<[C]> for MonoidalString<C,M> { #[inline] fn as_ref(&self) -> &[C] {self.string.as_ref()} }
195impl<C,M:?Sized> Borrow<[C]> for MonoidalString<C,M> { #[inline] fn borrow(&self) -> &[C] {self.string.borrow()} }
196
197impl<C,M:?Sized,I> Index<I> for MonoidalString<C,M> where Vec<C>:Index<I> {
198    type Output = <Vec<C> as Index<I>>::Output;
199    #[inline] fn index(&self, i:I) -> &Self::Output {&self.string[i]}
200}
201
202impl<C,M:?Sized> IntoIterator for MonoidalString<C,M> {
203    type Item = C;
204    type IntoIter = IntoIter<C>;
205    #[inline] fn into_iter(self) -> IntoIter<C> { self.string.into_iter() }
206}
207
208impl<C,M:MonoidRule<C>+?Sized> Extend<C> for MonoidalString<C,M> {
209    fn extend<I:IntoIterator<Item=C>>(&mut self, iter:I) {
210        self.apply_fn(|string| M::apply_iter(string, iter.into_iter()))
211    }
212}
213
214impl<C,M:?Sized,T> FromIterator<T> for MonoidalString<C,M> where Self:Product<T> {
215    fn from_iter<I:IntoIterator<Item=T>>(iter:I) -> Self { iter.into_iter().product() }
216}
217
218impl<C,M:MonoidRule<C>+?Sized> Product<C> for MonoidalString<C,M> {
219    fn product<I:Iterator<Item=C>>(iter: I) -> Self {
220        let mut dest:Self = One::one();
221        dest.extend(iter);
222        dest
223    }
224}
225
226impl<C,M:MonoidRule<C>+?Sized> Product for MonoidalString<C,M> {
227    fn product<I:Iterator<Item=Self>>(iter: I) -> Self { iter.flatten().product() }
228}
229
230impl<C,M:?Sized> MonoidalString<C,M> {
231
232    ///
233    ///Returns the number of letters in this monoidal-string
234    ///
235    ///## Examples
236    ///```
237    ///use maths_traits::algebra::One;
238    ///use free_algebra::FreeMonoid;
239    ///
240    ///let x = FreeMonoid::one();
241    ///let y = x.clone() * 'a' * 'a';
242    ///
243    ///assert_eq!(x.len(), 0);
244    ///assert_eq!(y.len(), 2);
245    ///
246    ///```
247    ///
248    #[inline] pub fn len(&self) -> usize { self.string.len() }
249
250    ///
251    ///Produces an iterator over references to the letters in this element
252    ///
253    ///## Examples
254    ///```
255    ///use maths_traits::algebra::One;
256    ///use free_algebra::FreeMonoid;
257    ///
258    ///let x = FreeMonoid::one() * 'a' * 'b' * 'c';
259    ///let mut iter = x.iter();
260    ///
261    ///assert_eq!(iter.next(), Some(&'a'));
262    ///assert_eq!(iter.next(), Some(&'b'));
263    ///assert_eq!(iter.next(), Some(&'c'));
264    ///assert_eq!(iter.next(), None);
265    ///
266    ///```
267    ///
268    #[inline] pub fn iter(&self) -> Iter<C> { self.string.iter() }
269
270    ///
271    ///Produces an iterator over mutable references to the letters in this element
272    ///
273    ///Note that the potential for modification does mean that the element needs to be remultiplied
274    ///as letters are changed, so a potential reallocation of space may occur.
275    ///
276    ///## Examples
277    ///```
278    ///use free_algebra::{FreePow, FreePowMonoid};
279    ///
280    ///let x = FreePow('a',1) * FreePow('b',1) * FreePow('c',1);
281    ///let mut y = x.clone();
282    ///
283    ///for FreePow(c,p) in y.iter_mut() {
284    ///    *c = 'a';
285    ///}
286    ///
287    ///assert_eq!(x, [FreePow('a',1), FreePow('b',1), FreePow('c',1)]);
288    ///assert_eq!(y, [FreePow('a',3)]);
289    ///
290    ///```
291    ///
292    #[inline] pub fn iter_mut(&mut self) -> IterMut<C,M> where M:MonoidRule<C> {
293        let mut temp = Self { string: Vec::with_capacity(self.len()), rule:PhantomData };
294        ::std::mem::swap(self, &mut temp);
295        IterMut { dest_ref: self, next: None, iter: temp.into_iter() }
296    }
297
298    ///
299    ///Reverses the letters in this element and remultiplies
300    ///
301    ///## Examples
302    ///```
303    ///use maths_traits::algebra::One;
304    ///use free_algebra::FreeMonoid;
305    ///
306    ///let x = FreeMonoid::one() * 'a' * 'b' * 'c';
307    ///let y = x.clone().reverse();
308    ///
309    ///assert_eq!(x, ['a', 'b', 'c']);
310    ///assert_eq!(y, ['c', 'b', 'a']);
311    ///
312    ///```
313    pub fn reverse(self) -> Self where Self:Product<C> {
314        self.into_iter().rev().product()
315    }
316
317    ///
318    ///Computes the multiplicative commutator `[a,b] = a⁻¹b⁻¹ab`
319    ///
320    ///## Examples
321    ///```
322    ///use free_algebra::FreeGroup;
323    ///use free_algebra::FreeInv::*;
324    ///
325    ///let x:FreeGroup<_> = Id('a').into();
326    ///let y:FreeGroup<_> = Id('b').into();
327    ///
328    ///assert_eq!(x, [Id('a')]);
329    ///assert_eq!(y, [Id('b')]);
330    ///assert_eq!(x.commutator(y), [Inv('a'), Inv('b'), Id('a'), Id('b')]);
331    ///
332    ///```
333    ///
334    ///A property of significance for this product is that when the arguments commute, the
335    ///output is always `1`.
336    ///
337    ///```
338    ///use maths_traits::algebra::One;
339    ///use free_algebra::{FreePowMonoid, FreePow};
340    ///
341    ///let x:FreePowMonoid<_,_> = FreePow('a', 2).into();
342    ///let y:FreePowMonoid<_,_> = FreePow('a', -24).into();
343    ///
344    ///assert!(x.commutator(y).is_one());
345    ///
346    ///```
347    ///
348    pub fn commutator(self, rhs:Self) -> Self where Self:MulMonoid+Inv<Output=Self> {
349        self.clone().inv()*rhs.clone().inv()*self*rhs
350    }
351}
352
353///
354///Dictates a rule for how to multiply or add letters to a [MonoidalString]'s word
355///
356///The simplest possible version of this simply applies multiplication as simple concatenation,
357///but this trait is robust enough to support more complex operations such as for [FreeGroup]
358///
359pub trait MonoidRule<C> {
360    ///Applies the operation rule to the product of a word and a single letter
361    fn apply(word: Vec<C>, letter: C) -> Vec<C>;
362
363    ///
364    ///Applies the operation rule to the product of two words
365    ///
366    ///By default, this computes the result by individually applying the rule to each letter of the
367    ///second word to the first using [MonoidRule::apply]
368    ///
369    fn apply_many(word1: Vec<C>, word2: Vec<C>) -> Vec<C> {Self::apply_iter(word1, word2.into_iter())}
370
371    ///
372    ///Applies the operation rule to the product of a word and a sequence of letters
373    ///
374    ///By default, this computes the result by individually applying the rule to each letter in
375    ///sequence to the first using [MonoidRule::apply]
376    ///
377    fn apply_iter<I:Iterator<Item=C>>(mut word: Vec<C>, letters: I) -> Vec<C> {
378        word.reserve(letters.size_hint().0);
379        letters.fold(word, |s,c| Self::apply(s,c))
380    }
381
382}
383
384///A [MonoidRule] where each letter has a notion of an inverse
385pub trait InvMonoidRule<C>: MonoidRule<C> {
386    ///Inverts a letter `x` such that `x * x.invert() == 1`
387    fn invert(letter: C) -> C;
388}
389
390///A [MonoidRule] that is evaluation order independent
391#[marker] pub trait AssociativeMonoidRule<C>: MonoidRule<C> {}
392
393///A [MonoidRule] that is order independent
394#[marker] pub trait CommutativeMonoidRule<C>: MonoidRule<C> {}
395
396impl<C,M:AssociativeMonoidRule<C>+?Sized> MulAssociative for MonoidalString<C,M> {}
397impl<C,M:CommutativeMonoidRule<C>+?Sized> MulCommutative for MonoidalString<C,M> {}
398
399impl<C,M:?Sized> MonoidalString<C,M> {
400
401    ///Applies a move-semantic function by reference
402    fn apply_fn<F:FnOnce(Vec<C>)->Vec<C>>(&mut self, f:F) {
403        //swap out string with a dummy vec so we don't violate move rule
404        let mut temp = Vec::with_capacity(0);
405        ::std::mem::swap(&mut self.string, &mut temp);
406
407        //apply the monoid rule
408        self.string = f(temp);
409    }
410
411    ///An operation agnostic method for computing inverses
412    fn invert<R:InvMonoidRule<C>+?Sized>(self) -> Self {
413        Self {
414            string: R::apply_iter(Vec::with_capacity(0), self.string.into_iter().rev().map(|c| R::invert(c))),
415            rule: PhantomData
416        }
417    }
418}
419
420impl<C,M:MonoidRule<C>+?Sized> MulAssign<C> for MonoidalString<C,M> {
421    fn mul_assign(&mut self, rhs:C) {
422        self.apply_fn(|string| M::apply(string,rhs));
423    }
424}
425impl<C,M:InvMonoidRule<C>+?Sized> DivAssign<C> for MonoidalString<C,M> {
426    #[inline] fn div_assign(&mut self, rhs:C) { *self*=M::invert(rhs) }
427}
428
429impl<C,M:MonoidRule<C>+?Sized> MulAssign for MonoidalString<C,M> {
430    fn mul_assign(&mut self, rhs:Self) {
431        self.apply_fn(|string| M::apply_many(string,rhs.string));
432    }
433}
434impl<C,M:InvMonoidRule<C>+?Sized> DivAssign for MonoidalString<C,M> {
435    #[inline] fn div_assign(&mut self, rhs:Self) { *self*=rhs.inv() }
436}
437
438impl_arith!(impl<C,M> MulAssign<&C>.mul_assign for MonoidalString<C,M> where M:?Sized);
439impl_arith!(impl<C,M> DivAssign<&C>.div_assign for MonoidalString<C,M> where M:?Sized);
440
441impl_arith!(impl<C,M> MulAssign<&Self>.mul_assign for MonoidalString<C,M> where M:?Sized);
442impl_arith!(impl<C,M> DivAssign<&Self>.div_assign for MonoidalString<C,M> where M:?Sized);
443
444impl_arith!(impl<C,M> Mul.mul with MulAssign.mul_assign for MonoidalString<C,M> where M:?Sized);
445impl_arith!(impl<C,M> Div.div with DivAssign.div_assign for MonoidalString<C,M> where M:?Sized);
446
447impl<C,M:MonoidRule<C>+?Sized> One for MonoidalString<C,M> {
448    #[inline] fn one() -> Self { Default::default() }
449    #[inline] fn is_one(&self) -> bool { self.string.len()==0 }
450}
451
452impl<C,M:InvMonoidRule<C>+?Sized> Inv for MonoidalString<C,M> {
453    type Output = Self;
454    #[inline] fn inv(self) -> Self {self.invert::<M>()}
455}
456
457impl<'a,C,M:InvMonoidRule<C>+?Sized> Inv for &'a MonoidalString<C,M> where MonoidalString<C,M>:Clone {
458    type Output = MonoidalString<C,M>;
459    #[inline] fn inv(self) -> Self::Output {(*self).clone().inv()}
460}
461
462#[marker] #[doc(hidden)] pub trait PowMarker<T> {}
463impl<Z:IntegerSubset,C,M:InvMonoidRule<C>+?Sized> PowMarker<Z> for MonoidalString<C,M> {}
464impl<Z:Natural,C,M:MonoidRule<C>+?Sized> PowMarker<Z> for MonoidalString<C,M> {}
465
466impl<Z:IntegerSubset,C:Clone,M:MonoidRule<C>+?Sized> Pow<Z> for MonoidalString<C,M>
467where Self:PowMarker<Z> + MulAssociative
468{
469    type Output = Self;
470    default fn pow(self, p:Z) -> Self { repeated_squaring(self, p.as_unsigned()) }
471}
472
473impl<Z:IntegerSubset,C:Clone,M:InvMonoidRule<C>+?Sized> Pow<Z> for MonoidalString<C,M>
474where Self:PowMarker<Z> + MulAssociative
475{
476    fn pow(self, p:Z) -> Self { repeated_squaring_inv(self, p) }
477}