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 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 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}