free_algebra/specifics/mod.rs
1use super::*;
2
3pub use self::free_monoid::*;
4pub use self::free_group::*;
5pub use self::free_pow::*;
6
7mod free_monoid;
8mod free_group;
9mod free_pow;
10
11///Multiplication of terms using a type's intrinsic [addition](Add) operation
12pub struct AddRule;
13///Multiplication of terms using a type's intrinsic [multiplication](Mul) operation
14pub struct MulRule;
15
16impl<R,T:Add<Output=T>+AddAssociative> AssociativeAlgebraRule<R,T> for AddRule {}
17impl<R,T:Add<Output=T>+AddCommutative> CommutativeAlgebraRule<R,T> for AddRule {}
18impl<R,T:Add<Output=T>> AlgebraRule<R,T> for AddRule {
19 fn apply(t1:T, t2:T) -> (Option<R>,T) { (None, t1+t2) }
20}
21impl<R,T:Add<Output=T>+Zero> UnitalAlgebraRule<R,T> for AddRule {
22 fn one() -> T { T::zero() }
23 fn is_one(t:&T) -> bool { t.is_zero() }
24}
25
26impl<R,T:Mul<Output=T>+MulAssociative> AssociativeAlgebraRule<R,T> for MulRule {}
27impl<R,T:Mul<Output=T>+MulCommutative> CommutativeAlgebraRule<R,T> for MulRule {}
28impl<R,T:Mul<Output=T>> AlgebraRule<R,T> for MulRule {
29 fn apply(t1:T, t2:T) -> (Option<R>,T) { (None, t1*t2) }
30}
31impl<R,T:Mul<Output=T>+One+PartialEq> UnitalAlgebraRule<R,T> for MulRule {
32 fn one() -> T { T::one() }
33 fn is_one(t:&T) -> bool { t.is_one() }
34}
35
36///
37///A [FreeModule] over some monoid, but with a multiplication between elements given using the monoid operation
38///
39///# Examples
40///```
41///use maths_traits::algebra::*;
42///use free_algebra::MonoidRing;
43///
44///#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
45///pub enum SplitComplexUnit { One, J }
46///
47///impl MulAssociative for SplitComplexUnit {}
48///impl MulCommutative for SplitComplexUnit {}
49///impl Mul for SplitComplexUnit {
50/// type Output = Self;
51/// fn mul(self, rhs:Self) -> Self {
52/// match self {
53/// One => rhs,
54/// J => match rhs {
55/// One => J,
56/// J => One,
57/// }
58/// }
59/// }
60///}
61///
62///impl maths_traits::algebra::One for SplitComplexUnit {
63/// fn one() -> Self { One }
64/// fn is_one(&self) -> bool { if let One=self { true } else { false } }
65///}
66///
67///use SplitComplexUnit::*;
68///type SplitComplex<R> = MonoidRing<R,SplitComplexUnit>;
69///
70///let x = SplitComplex::one() * 2.5 + SplitComplex::one() * (3.0, J);
71///let y = SplitComplex::one() * 4.0 + SplitComplex::one() * (2.0, J);
72///
73///assert_eq!([x[&One], x[&J]], [2.5, 3.0]);
74///assert_eq!([y[&One], y[&J]], [4.0, 2.0]);
75///
76///let z = x * y;
77///assert_eq!([z[&One], z[&J]], [16.0, 17.0]);
78///
79///```
80///
81pub type MonoidRing<R,M> = ModuleString<R,M,MulRule>;
82
83///
84///A [module](RingModule) over a ring constructed from free addition scalar-multiplication of elements of a set
85///
86///Concretely, given a set `T` and ring `R`, we construct the free-module of `T` over `R` as
87///the set of linear combination over elements in `T` where the scalars are in `R`. In practice,
88///though, this construction is effectively just polynomials with variables from `T` but without
89///multiplication.
90///
91///# Examples
92///```
93///use maths_traits::algebra::Zero;
94///use free_algebra::FreeModule;
95///
96///let p = FreeModule::zero() + (3.5, 'x') + (2.0, 'y') + (1.0, 'x');
97///let q = FreeModule::zero() - (1.5, 'x') + (2.0, 'y');
98///
99///assert_eq!([p[&'x'], p[&'y']], [4.5, 2.0]);
100///assert_eq!([q[&'x'], q[&'y']], [-1.5, 2.0]);
101///
102///let r = &p + &q;
103///let s = (p - q) * 0.5;
104///
105///assert_eq!([r[&'x'], r[&'y']], [3.0, 4.0]);
106///assert_eq!([s[&'x'], s.get(&'y')], [3.0, 0.0]);
107///
108///```
109///
110pub type FreeModule<R,T> = ModuleString<R,T,!>;
111
112///
113///A [module](RingModule) over a ring constructed from free multiplication and addition of elements of a set
114///
115///Concretely, this is a [MonoidRing] of the [FreeMonoid] over `T` with coeffients in `R`. However,
116///effectively, this just makes polynomials with elements of `T` as variables and coefficients in `R`,
117///but where multiplication isn't commutative.
118///
119///# Examples
120///```
121///use maths_traits::algebra::One;
122///use free_algebra::{FreeAlgebra, FreeMonoid};
123///
124///let one = FreeMonoid::one();
125///let x:FreeMonoid<_> = 'x'.into();
126///let y:FreeMonoid<_> = 'y'.into();
127///
128///let p = FreeAlgebra::<f32,_>::one() + &x;
129///let q = FreeAlgebra::<f32,_>::one() - &y;
130///
131///assert_eq!([p[&one], p[&x]], [1.0, 1.0]);
132///assert_eq!([q[&one], q[&y]], [1.0, -1.0]);
133///
134///let r = p * q;
135///assert_eq!([r[&one], r[&x], r[&y], r[&(x*y)]], [1.0, 1.0, -1.0, -1.0]);
136///
137///```
138///
139pub type FreeAlgebra<R,T> = MonoidRing<R,FreeMonoid<T>>;