competitive/algebra/
magma.rs

1//! algebraic traits
2
3/// binary operaion: $T \circ T \to T$
4pub trait Magma {
5    /// type of operands: $T$
6    type T: Clone;
7
8    /// binary operaion: $\circ$
9    fn operate(x: &Self::T, y: &Self::T) -> Self::T;
10
11    fn reverse_operate(x: &Self::T, y: &Self::T) -> Self::T {
12        Self::operate(y, x)
13    }
14
15    fn operate_assign(x: &mut Self::T, y: &Self::T) {
16        *x = Self::operate(x, y);
17    }
18}
19
20/// $\forall a,\forall b,\forall c \in T, (a \circ b) \circ c = a \circ (b \circ c)$
21pub trait Associative: Magma {
22    #[cfg(test)]
23    fn check_associative(a: &Self::T, b: &Self::T, c: &Self::T) -> bool
24    where
25        Self::T: PartialEq,
26    {
27        ({
28            let ab_c = Self::operate(&Self::operate(a, b), c);
29            let a_bc = Self::operate(a, &Self::operate(b, c));
30            ab_c == a_bc
31        }) && ({
32            let ab_c = Self::reverse_operate(c, &Self::reverse_operate(b, a));
33            let a_bc = Self::reverse_operate(&Self::reverse_operate(c, b), a);
34            ab_c == a_bc
35        }) && ({
36            let mut ab_c = a.clone();
37            Self::operate_assign(&mut ab_c, b);
38            Self::operate_assign(&mut ab_c, c);
39            let mut bc = b.clone();
40            Self::operate_assign(&mut bc, c);
41            let mut a_bc = a.clone();
42            Self::operate_assign(&mut a_bc, &bc);
43            ab_c == a_bc
44        })
45    }
46}
47
48/// associative binary operation
49pub trait SemiGroup: Magma + Associative {}
50
51impl<S> SemiGroup for S where S: Magma + Associative {}
52
53/// $\exists e \in T, \forall a \in T, e \circ a = a \circ e = e$
54pub trait Unital: Magma {
55    /// identity element: $e$
56    fn unit() -> Self::T;
57
58    fn is_unit(x: &Self::T) -> bool
59    where
60        Self::T: PartialEq,
61    {
62        x == &Self::unit()
63    }
64
65    fn set_unit(x: &mut Self::T) {
66        *x = Self::unit();
67    }
68
69    #[cfg(test)]
70    fn check_unital(x: &Self::T) -> bool
71    where
72        Self::T: PartialEq,
73    {
74        let u = Self::unit();
75        let xu = Self::operate(x, &u);
76        let ux = Self::operate(&u, x);
77        let mut any = x.clone();
78        Self::set_unit(&mut any);
79        xu == *x && ux == *x && Self::is_unit(&u) && Self::is_unit(&any)
80    }
81}
82
83pub trait ExpBits {
84    type Iter: Iterator<Item = bool>;
85    fn bits(self) -> Self::Iter;
86}
87
88pub trait SignedExpBits {
89    type T: ExpBits;
90
91    fn neg_and_bits(self) -> (bool, Self::T);
92}
93
94pub struct Bits<T> {
95    n: T,
96}
97
98macro_rules! impl_exp_bits_for_uint {
99    ($($t:ty)*) => {
100        $(
101            impl Iterator for Bits<$t> {
102                type Item = bool;
103                fn next(&mut self) -> Option<bool> {
104                    if self.n == 0 {
105                        None
106                    } else {
107                        let bit = (self.n & 1) == 1;
108                        self.n >>= 1;
109                        Some(bit)
110                    }
111                }
112            }
113            impl ExpBits for $t {
114                type Iter = Bits<$t>;
115                fn bits(self) -> Self::Iter {
116                    Bits { n: self }
117                }
118            }
119            impl SignedExpBits for $t {
120                type T = $t;
121                fn neg_and_bits(self) -> (bool, Self::T) {
122                    (false, self)
123                }
124            }
125        )*
126    };
127}
128impl_exp_bits_for_uint!(u8 u16 u32 u64 u128 usize);
129
130macro_rules! impl_signed_exp_bits_for_sint {
131    ($($s:ty, $u:ty;)*) => {
132        $(
133            impl SignedExpBits for $s {
134                type T = $u;
135                fn neg_and_bits(self) -> (bool, Self::T) {
136                    (self < 0, self.unsigned_abs())
137                }
138            }
139        )*
140    };
141}
142impl_signed_exp_bits_for_sint!(i8, u8; i16, u16; i32, u32; i64, u64; i128, u128; isize, usize;);
143
144/// associative binary operation and an identity element
145pub trait Monoid: SemiGroup + Unital {
146    /// binary exponentiation: $x^n = x\circ\ddots\circ x$
147    fn pow<E>(mut x: Self::T, exp: E) -> Self::T
148    where
149        E: ExpBits,
150    {
151        let mut res = Self::unit();
152        for bit in exp.bits() {
153            if bit {
154                res = Self::operate(&res, &x);
155            }
156            x = Self::operate(&x, &x);
157        }
158        res
159    }
160
161    fn fold<I>(iter: I) -> Self::T
162    where
163        I: IntoIterator<Item = Self::T>,
164    {
165        let mut iter = iter.into_iter();
166        if let Some(item) = iter.next() {
167            iter.fold(item, |acc, x| Self::operate(&acc, &x))
168        } else {
169            Self::unit()
170        }
171    }
172}
173
174impl<M> Monoid for M where M: SemiGroup + Unital {}
175
176/// $\exists e \in T, \forall a \in T, \exists b,c \in T, b \circ a = a \circ c = e$
177pub trait Invertible: Magma + Unital {
178    /// $a$ where $a \circ x = e$
179    fn inverse(x: &Self::T) -> Self::T;
180
181    fn rinv_operate(x: &Self::T, y: &Self::T) -> Self::T {
182        Self::operate(x, &Self::inverse(y))
183    }
184
185    fn rinv_operate_assign(x: &mut Self::T, y: &Self::T) {
186        *x = Self::rinv_operate(x, y);
187    }
188
189    #[cfg(test)]
190    fn check_invertible(x: &Self::T) -> bool
191    where
192        Self::T: PartialEq,
193    {
194        let i = Self::inverse(x);
195        ({
196            let xi = Self::operate(x, &i);
197            let ix = Self::operate(&i, x);
198            Self::is_unit(&xi) && Self::is_unit(&ix)
199        }) && ({
200            let ii = Self::inverse(&i);
201            ii == *x
202        }) && ({
203            let mut xi = x.clone();
204            Self::operate_assign(&mut xi, &i);
205            let mut ix = i.clone();
206            Self::operate_assign(&mut ix, x);
207            Self::is_unit(&xi) && Self::is_unit(&ix)
208        }) && ({
209            let mut xi = x.clone();
210            Self::rinv_operate_assign(&mut xi, x);
211            let mut ix = i.clone();
212            Self::rinv_operate_assign(&mut ix, &i);
213            Self::is_unit(&xi) && Self::is_unit(&ix)
214        })
215    }
216}
217
218/// associative binary operation and an identity element and inverse elements
219pub trait Group: Monoid + Invertible {
220    fn signed_pow<E>(x: Self::T, exp: E) -> Self::T
221    where
222        E: SignedExpBits,
223    {
224        let (neg, exp) = E::neg_and_bits(exp);
225        let res = Self::pow(x, exp);
226        if neg { Self::inverse(&res) } else { res }
227    }
228}
229
230impl<G> Group for G where G: Monoid + Invertible {}
231
232/// $\forall a,\forall b \in T, a \circ b = b \circ a$
233pub trait Commutative: Magma {
234    #[cfg(test)]
235    fn check_commutative(a: &Self::T, b: &Self::T) -> bool
236    where
237        Self::T: PartialEq,
238    {
239        Self::operate(a, b) == Self::operate(b, a)
240    }
241}
242
243/// commutative monoid
244pub trait AbelianMonoid: Monoid + Commutative {}
245
246impl<M> AbelianMonoid for M where M: Monoid + Commutative {}
247
248/// commutative group
249pub trait AbelianGroup: Group + Commutative {}
250
251impl<G> AbelianGroup for G where G: Group + Commutative {}
252
253/// $\forall a \in T, a \circ a = a$
254pub trait Idempotent: Magma {
255    #[cfg(test)]
256    fn check_idempotent(a: &Self::T) -> bool
257    where
258        Self::T: PartialEq,
259    {
260        Self::operate(a, a) == *a
261    }
262}
263
264/// idempotent monoid
265pub trait IdempotentMonoid: Monoid + Idempotent {}
266
267impl<M> IdempotentMonoid for M where M: Monoid + Idempotent {}
268
269#[macro_export]
270macro_rules! monoid_fold {
271    ($m:ty) => { <$m as Unital>::unit() };
272    ($m:ty,) => { <$m as Unital>::unit() };
273    ($m:ty, $f:expr) => { $f };
274    ($m:ty, $f:expr, $($ff:expr),*) => { <$m as Magma>::operate(&($f), &monoid_fold!($m, $($ff),*)) };
275}
276
277#[macro_export]
278macro_rules! define_monoid {
279    ($Name:ident, $t:ty, |$x:ident, $y:ident| $op:expr, $unit:expr) => {
280        struct $Name;
281        impl Magma for $Name {
282            type T = $t;
283            fn operate($x: &Self::T, $y: &Self::T) -> Self::T {
284                $op
285            }
286        }
287        impl Unital for $Name {
288            fn unit() -> Self::T {
289                $unit
290            }
291        }
292        impl Associative for $Name {}
293    };
294}
295
296#[cfg(test)]
297mod tests {
298    use super::*;
299    use crate::algebra::operations::{AdditiveOperation, MaxOperation};
300
301    #[test]
302    fn test_monoid_pow() {
303        assert_eq!(AdditiveOperation::pow(2, 0u32), 0);
304        assert_eq!(AdditiveOperation::pow(2, 1u32), 2);
305        assert_eq!(AdditiveOperation::pow(2, 3u32), 6);
306        assert_eq!(AdditiveOperation::pow(2, 4usize), 8);
307    }
308
309    #[test]
310    fn test_monoid_fold() {
311        assert_eq!(monoid_fold!(MaxOperation<u32>,), 0);
312        assert_eq!(monoid_fold!(MaxOperation<u32>, 1), 1);
313        assert_eq!(monoid_fold!(MaxOperation<u32>, 1, 2), 2);
314        assert_eq!(monoid_fold!(MaxOperation<u32>, 0, 1, 5, 2), 5);
315    }
316}