algebraeon_groups/examples/
symmetric.rs

1use std::collections::HashMap;
2
3use itertools::Itertools;
4
5use crate::structure::Group;
6
7use super::c2::C2;
8
9#[derive(Debug, Clone)]
10pub struct Cycle<const N: usize> {
11    cyc: Vec<usize>,
12}
13
14impl<const N: usize> Cycle<N> {
15    pub fn new(cyc: Vec<usize>) -> Result<Self, &'static str> {
16        let mut present = [false; N];
17        for i in &cyc {
18            if present[*i] {
19                return Err("Duplicate element in cycle");
20            }
21            present[*i] = true;
22        }
23        Ok(Self { cyc })
24    }
25
26    pub fn len(&self) -> usize {
27        self.cyc.len()
28    }
29
30    pub fn is_empty(&self) -> bool {
31        self.cyc.is_empty()
32    }
33}
34
35impl<const N: usize> std::convert::From<Cycle<N>> for Permutation<N> {
36    fn from(cyc: Cycle<N>) -> Self {
37        let mut perm = [0; N];
38        for i in 0..N {
39            perm[i] = i;
40        }
41        let n = cyc.cyc.len();
42        for i in 0..n {
43            perm[cyc.cyc[i]] = cyc.cyc[(i + 1) % n];
44        }
45        Self { perm }
46    }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Hash)]
50pub struct Permutation<const N: usize> {
51    perm: [usize; N],
52}
53
54impl<const N: usize> TryFrom<super::super::permutation::Permutation> for Permutation<N> {
55    type Error = ();
56
57    fn try_from(value: super::super::permutation::Permutation) -> Result<Self, Self::Error> {
58        let n = value.n();
59        if N < n {
60            Err(())
61        } else {
62            let mut perm = [0; N];
63            for i in 0..N {
64                perm[i] = value.call(i);
65            }
66            Ok(Self { perm })
67        }
68    }
69}
70
71impl<const N: usize> Permutation<N> {
72    pub fn new(perm: [usize; N]) -> Result<Self, &'static str> {
73        //check that the numbers in forward are 0, 1, ..., n-1 in some order
74        let mut present = [false; N];
75        for i in &perm {
76            if *i >= N {
77                return Err("Permutation value out of range");
78            }
79            present[*i] = true;
80        }
81        for is_present in present {
82            if !is_present {
83                return Err("Not a valid permutation");
84            }
85        }
86
87        Ok(Self { perm })
88    }
89
90    pub fn new_from_cycles(cycles: Vec<Vec<usize>>) -> Result<Self, &'static str> {
91        let mut parsed_cycles = vec![];
92        for c in cycles {
93            parsed_cycles.push(Cycle::<N>::new(c)?);
94        }
95        Ok(Self::compose_list(
96            parsed_cycles
97                .into_iter()
98                .map(Into::<Permutation<N>>::into)
99                .collect(),
100        ))
101    }
102
103    pub fn call(&self, x: usize) -> Result<usize, &'static str> {
104        if x >= self.perm.len() {
105            return Err("argument too large");
106        }
107        Ok(self.perm[x])
108    }
109
110    pub fn sign(&self) -> C2 {
111        let mut s = C2::identity();
112        for i in 0..N {
113            for j in 0..i {
114                if (i < j) != (self.call(i) < self.call(j)) {
115                    s.compose_mut(&C2::Flip);
116                }
117            }
118        }
119        s
120    }
121
122    pub fn disjoint_cycles(&self) -> Vec<Cycle<N>> {
123        let mut missing: std::collections::HashSet<usize> = (0..N).collect();
124        let mut cycles = vec![];
125        while !missing.is_empty() {
126            let mut cycle = vec![];
127            let x = *missing.iter().min().unwrap();
128            let mut i = x;
129            loop {
130                cycle.push(i);
131                missing.remove(&i);
132                i = self.perm[i];
133                if i == x {
134                    break;
135                }
136            }
137            cycles.push(Cycle { cyc: cycle });
138        }
139        cycles
140    }
141
142    pub fn cycle_shape(&self) -> Vec<usize> {
143        let mut shape = self.disjoint_cycles().iter().map(Cycle::len).collect_vec();
144        shape.sort_unstable();
145        shape
146    }
147
148    pub fn all_permutations() -> impl Iterator<Item = Self> {
149        (0..N).permutations(N).map(|perm| Self {
150            perm: perm.try_into().unwrap(),
151        })
152    }
153
154    pub fn symmetric_composition_table() -> (
155        crate::composition_table::group::FiniteGroupMultiplicationTable,
156        Vec<Self>,
157        HashMap<Self, usize>,
158    ) {
159        Self::generated_finite_subgroup_table(Self::all_permutations().collect())
160    }
161
162    pub fn alternating_composition_table() -> (
163        crate::composition_table::group::FiniteGroupMultiplicationTable,
164        Vec<Self>,
165        HashMap<Self, usize>,
166    ) {
167        Self::generated_finite_subgroup_table(
168            Self::all_permutations()
169                .filter(|p| p.sign() == C2::Identity)
170                .collect(),
171        )
172    }
173}
174
175impl<const N: usize> std::fmt::Display for Permutation<N> {
176    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177        let mut cycles = self.disjoint_cycles();
178        cycles.retain(|cycle| cycle.len() != 1);
179
180        if cycles.is_empty() {
181            f.write_str("()")?;
182        }
183
184        let string = cycles
185            .iter()
186            .map(|cycle| {
187                "(".to_owned()
188                    + &cycle
189                        .cyc
190                        .iter()
191                        .map(std::string::ToString::to_string)
192                        .collect::<Vec<String>>()
193                        .join(" ")
194                    + ")"
195            })
196            .collect::<Vec<String>>()
197            .join(" ");
198
199        f.write_str(string.as_str())
200    }
201}
202
203impl<const N: usize> Group for Permutation<N> {
204    fn identity() -> Self {
205        let mut perm = [0; N];
206        for i in 0..N {
207            perm[i] = i;
208        }
209        Self { perm }
210    }
211
212    fn inverse(self) -> Self {
213        let mut inv_perm = [0; N];
214        for (i, j) in self.perm.into_iter().enumerate() {
215            inv_perm[j] = i;
216        }
217        Self { perm: inv_perm }
218    }
219
220    fn compose_refs(a: &Self, b: &Self) -> Self {
221        let mut comp_perm = [0; N];
222        for i in 0..N {
223            comp_perm[i] = a.perm[b.perm[i]];
224        }
225        Self { perm: comp_perm }
226    }
227
228    fn compose_mut(&mut self, other: &Self) {
229        *self = Self::compose_refs(self, other);
230    }
231}
232
233#[cfg(test)]
234mod tests {
235    use super::*;
236
237    #[test]
238    fn test_composition() {
239        let a = Permutation::new([0, 2, 1]).unwrap();
240        let b = Permutation::new([1, 2, 0]).unwrap();
241        let c = Permutation::new([2, 1, 0]).unwrap();
242
243        println!("a = {}", a);
244        println!("b = {}", b);
245        println!("ab = {}", Permutation::compose_refs(&a, &b));
246        println!("c = {}", c);
247
248        assert_eq!(Permutation::compose(a, b), c);
249    }
250
251    #[test]
252    fn test_sign() {
253        let a = Permutation::new([0, 2, 1]).unwrap();
254        let b = Permutation::new([1, 2, 0]).unwrap();
255        let c = Permutation::new([2, 1, 0]).unwrap();
256
257        println!("a = {}", a);
258        println!("b = {}", b);
259        println!("c = {}", c);
260
261        assert_eq!(a.sign(), C2::Flip);
262        assert_eq!(b.sign(), C2::Identity);
263        assert_eq!(c.sign(), C2::Flip);
264    }
265
266    #[test]
267    fn test_all_permutations() {
268        assert_eq!(Permutation::<0>::all_permutations().collect_vec().len(), 1);
269        assert_eq!(Permutation::<1>::all_permutations().collect_vec().len(), 1);
270        assert_eq!(Permutation::<2>::all_permutations().collect_vec().len(), 2);
271        assert_eq!(Permutation::<3>::all_permutations().collect_vec().len(), 6);
272        assert_eq!(Permutation::<4>::all_permutations().collect_vec().len(), 24);
273        assert_eq!(
274            Permutation::<5>::all_permutations().collect_vec().len(),
275            120
276        );
277    }
278}