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