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}