linnet/
permutation.rs

1use std::{collections::BTreeMap, fmt, ops::Index};
2
3use crate::half_edge::{
4    involution::Hedge,
5    subgraph::{InternalSubGraph, SubGraph, SubGraphOps},
6    HedgeGraph, NodeIndex,
7};
8use ahash::AHashSet;
9use bitvec::vec::BitVec;
10use thiserror::Error;
11
12use crate::half_edge::involution::Flow;
13
14/// A permutation of `0..n`, with the ability to apply itself (or its inverse) to slices.
15///
16/// # Examples
17///
18/// ```
19/// use linnet::permutation::Permutation;
20///
21/// // Create a permutation that maps 0->2, 1->0, 2->1, 3->3
22/// let p = Permutation::from_map(vec![2, 0, 1, 3]);
23///
24/// // Apply the permutation to a slice
25/// let data = vec![10, 20, 30, 40];
26/// let permuted = p.apply_slice(&data);
27/// assert_eq!(permuted, vec![30, 10, 20, 40]);
28/// ```
29#[derive(Debug, Clone, PartialEq, Eq, Hash)]
30pub struct Permutation {
31    map: Vec<usize>,
32    inv: Vec<usize>,
33}
34
35/// Implement ordering comparisons for permutations based on their `map` field.
36impl PartialOrd for Permutation {
37    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
38        self.map.partial_cmp(&other.map)
39    }
40}
41
42impl Permutation {
43    // --------------------------------------------------------------------------------------------
44    // Basic Constructors and Accessors
45    // --------------------------------------------------------------------------------------------
46
47    /// Creates the identity permutation of length `n`.
48    ///
49    /// # Examples
50    ///
51    /// ```
52    /// # use linnet::permutation::Permutation;
53    /// let p = Permutation::id(4);
54    /// assert_eq!(p.apply_slice(&[10,20,30,40]), vec![10,20,30,40]);
55    /// ```
56    pub fn id(n: usize) -> Self {
57        Permutation {
58            map: (0..n).collect(),
59            inv: (0..n).collect(),
60        }
61    }
62
63    /// Creates a permutation from a mapping vector.
64    /// The `map` vector states where index `i` is sent: `map[i]` is the image of `i`.
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// # use linnet::permutation::Permutation;
70    /// let p = Permutation::from_map(vec![2, 0, 1]);
71    /// assert_eq!(p.apply_slice(&[10,20,30]), vec![30,10,20]);
72    /// ```
73    pub fn from_map(map: Vec<usize>) -> Self {
74        let mut inv = vec![0; map.len()];
75        for (i, &j) in map.iter().enumerate() {
76            inv[j] = i;
77        }
78        Permutation { map, inv }
79    }
80
81    /// Returns the internal mapping as a slice.
82    ///
83    /// # Examples
84    ///
85    /// ```
86    /// # use linnet::permutation::Permutation;
87    /// let p = Permutation::from_map(vec![2, 0, 1]);
88    /// assert_eq!(p.map(), &[2, 0, 1]);
89    /// ```
90    // -- ADDED
91    pub fn map(&self) -> &[usize] {
92        &self.map
93    }
94
95    /// Returns the inverse mapping as a slice.
96    ///
97    /// # Examples
98    ///
99    /// ```
100    /// # use linnet::permutation::Permutation;
101    /// let p = Permutation::from_map(vec![2, 0, 1]);
102    /// assert_eq!(p.inv(), &[1, 2, 0]);
103    /// ```
104    // -- ADDED
105    pub fn inv(&self) -> &[usize] {
106        &self.inv
107    }
108
109    // --------------------------------------------------------------------------------------------
110    // Basic Operations
111    // --------------------------------------------------------------------------------------------
112
113    /// Returns the inverse of the permutation.
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// # use linnet::permutation::Permutation;
119    /// let p = Permutation::from_map(vec![2, 0, 1]);
120    /// let inv = p.inverse();
121    /// assert_eq!(inv.apply_slice(&[10,20,30]), vec![20,30,10]);
122    /// ```
123    pub fn inverse(&self) -> Self {
124        Permutation {
125            map: self.inv.clone(),
126            inv: self.map.clone(),
127        }
128    }
129
130    /// Applies `self` to a slice, returning a new `Vec<T>` in permuted order.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// # use linnet::permutation::Permutation;
136    /// let p = Permutation::from_map(vec![2, 0, 1]);
137    /// let data = vec![10, 20, 30];
138    /// assert_eq!(p.apply_slice(&data), vec![30, 10, 20]);
139    /// ```
140    pub fn apply_slice<T: Clone, S>(&self, slice: S) -> Vec<T>
141    where
142        S: AsRef<[T]>,
143    {
144        let s = slice.as_ref();
145        self.map.iter().map(|&idx| s[idx].clone()).collect()
146    }
147
148    /// Applies the inverse of `self` to a slice, returning a new `Vec<T>` in permuted order.
149    ///
150    /// # Examples
151    ///
152    /// ```
153    /// # use linnet::permutation::Permutation;
154    /// let p = Permutation::from_map(vec![2, 0, 1]);
155    /// let data = vec![10, 20, 30];
156    /// assert_eq!(p.apply_slice_inv(&data), vec![20, 30, 10]);
157    /// ```
158    pub fn apply_slice_inv<T: Clone, S>(&self, slice: S) -> Vec<T>
159    where
160        S: AsRef<[T]>,
161    {
162        let s = slice.as_ref();
163        self.inv.iter().map(|&idx| s[idx].clone()).collect()
164    }
165
166    /// Applies `self` in-place to the provided slice by using transpositions
167    /// derived from the cycle decomposition.
168    ///
169    /// # Examples
170    ///
171    /// ```
172    /// # use linnet::permutation::Permutation;
173    /// let p = Permutation::from_map(vec![2, 0, 1]);
174    /// let mut data = vec![10, 20, 30];
175    /// p.apply_slice_in_place(&mut data);
176    /// assert_eq!(data, vec![20, 30, 10]);
177    /// ```
178    pub fn apply_slice_in_place<T: Clone, S>(&self, slice: &mut S)
179    where
180        S: AsMut<[T]>,
181    {
182        let transpositions = self.transpositions();
183        for (i, j) in transpositions.iter().rev() {
184            slice.as_mut().swap(*i, *j);
185        }
186    }
187
188    /// Applies the inverse of `self` in-place to the provided slice by using transpositions
189    /// derived from the cycle decomposition.
190    ///
191    /// # Examples
192    ///
193    /// ```
194    /// # use linnet::permutation::Permutation;
195    /// let p = Permutation::from_map(vec![2, 0, 1]);
196    /// let mut data = vec![10, 20, 30];
197    /// p.apply_slice_in_place_inv(&mut data);
198    /// assert_eq!(data, vec![30, 10, 20]);
199    /// ```
200    pub fn apply_slice_in_place_inv<T: Clone, S>(&self, slice: &mut S)
201    where
202        S: AsMut<[T]>,
203    {
204        let transpositions = self.transpositions();
205        for (i, j) in transpositions {
206            slice.as_mut().swap(i, j);
207        }
208    }
209
210    /// Composes `self` with another permutation `other`, returning a new permutation:
211    /// `(self ◦ other)(i) = self.map[other.map[i]]`.
212    pub fn compose(&self, other: &Self) -> Self {
213        let map = other.map.iter().map(|&i| self.map[i]).collect();
214        Self::from_map(map)
215    }
216
217    // --------------------------------------------------------------------------------------------
218    // Sorting Utilities
219    // --------------------------------------------------------------------------------------------
220
221    /// Given a slice of items that implement `Ord`, returns the permutation that sorts them
222    /// in ascending order.
223    ///
224    /// # Examples
225    ///
226    /// ```
227    /// # use linnet::permutation::Permutation;
228    /// let data = vec![30, 10, 20, 40];
229    /// let perm = Permutation::sort(&data);
230    /// // perm.map should be [1, 2, 0, 3]
231    /// assert_eq!(perm.apply_slice(&data), vec![10, 20, 30, 40]);
232    /// ```
233    pub fn sort<T, S>(slice: S) -> Permutation
234    where
235        T: Ord,
236        S: AsRef<[T]>,
237    {
238        let s = slice.as_ref();
239        let mut permutation: Vec<usize> = (0..s.len()).collect();
240        permutation.sort_by_key(|&i| &s[i]);
241        Self::from_map(permutation)
242    }
243
244    // --------------------------------------------------------------------------------------------
245    // Cycles and Transpositions
246    // --------------------------------------------------------------------------------------------
247
248    /// Returns the cycle decomposition of `self` as a `Vec` of cycles,
249    /// each cycle represented as a `Vec<usize>`.
250    /// Each cycle lists the indices of a single cycle, e.g. `[0, 2, 1]` means `0->2, 2->1, 1->0`.
251    ///
252    /// # Examples
253    ///
254    /// ```
255    /// # use linnet::permutation::Permutation;
256    /// let p = Permutation::from_map(vec![2, 0, 1, 3]);
257    /// let cycles = p.find_cycles();
258    /// // cycles might be [[0, 2, 1], [3]]
259    /// assert_eq!(cycles.len(), 2);
260    /// ```
261    pub fn find_cycles(&self) -> Vec<Vec<usize>> {
262        let mut visited = vec![false; self.map.len()];
263        let mut cycles = Vec::new();
264        for i in 0..self.map.len() {
265            if visited[i] {
266                continue;
267            }
268            let mut cycle = Vec::new();
269            let mut j = i;
270            while !visited[j] {
271                visited[j] = true;
272                cycle.push(j);
273                j = self.map[j];
274            }
275            if !cycle.is_empty() {
276                cycles.push(cycle);
277            }
278        }
279        cycles
280    }
281
282    /// Converts a single cycle to a list of transpositions that produce that cycle.
283    /// This is a helper method and typically not used directly.
284    ///
285    /// # Examples
286    ///
287    /// ```
288    /// # use linnet::permutation::Permutation;
289    /// let cycle = vec![0, 2, 1];
290    /// let transpositions = Permutation::cycle_to_transpositions(&cycle);
291    /// // cycle 0->2,2->1,1->0 can be built from swaps (0,1) and (0,2)
292    /// assert_eq!(transpositions, vec![(0, 1), (0, 2)]);
293    /// ```
294    pub fn cycle_to_transpositions(cycle: &[usize]) -> Vec<(usize, usize)> {
295        let mut transpositions = Vec::new();
296        for i in (1..cycle.len()).rev() {
297            transpositions.push((cycle[0], cycle[i]));
298        }
299        transpositions
300    }
301
302    /// Returns the list of transpositions for `self`, by decomposing it into cycles
303    /// and then converting each cycle to transpositions.
304    ///
305    /// # Examples
306    ///
307    /// ```
308    /// # use linnet::permutation::Permutation;
309    /// let p = Permutation::from_map(vec![2, 0, 1]);
310    /// let transpositions = p.transpositions();
311    /// assert_eq!(transpositions, vec![(0, 1), (0, 2)]);
312    /// ```
313    pub fn transpositions(&self) -> Vec<(usize, usize)> {
314        let cycles = self.find_cycles();
315        let mut transpositions = Vec::new();
316        for cycle in cycles {
317            transpositions.extend(Self::cycle_to_transpositions(&cycle));
318        }
319        transpositions
320    }
321
322    // --------------------------------------------------------------------------------------------
323    // Myrvold & Ruskey Ranking/Unranking
324    // --------------------------------------------------------------------------------------------
325
326    /// Computes the rank of the permutation in the Myrvold & Ruskey "Rank1" ordering.
327    ///
328    /// This is a recursive implementation. For permutations of size `n`, it removes
329    /// the position of `n-1` from the permutation, multiplies the result by `n`,
330    /// and adds the index of `n-1`.
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// # use linnet::permutation::Permutation;
336    /// let p = Permutation::from_map(vec![2, 1, 3, 0]);
337    /// assert_eq!(p.myrvold_ruskey_rank1(), 12);
338    /// ```
339    pub fn myrvold_ruskey_rank1(mut self) -> usize {
340        let n = self.map.len();
341        if self.map.len() == 1 {
342            return 0;
343        }
344
345        let s = self.map[n - 1];
346        self.map.swap_remove(self.inv[n - 1]);
347        self.inv.swap_remove(s);
348
349        s + n * self.myrvold_ruskey_rank1()
350    }
351
352    /// Unranks a permutation of size `n` from its Myrvold & Ruskey "Rank1" index.
353    ///
354    /// # Examples
355    ///
356    /// ```
357    /// # use linnet::permutation::Permutation;
358    /// let p = Permutation::myrvold_ruskey_unrank1(4, 12);
359    /// assert_eq!(p.map(), &[2, 1, 3, 0]);
360    /// ```
361    pub fn myrvold_ruskey_unrank1(n: usize, mut rank: usize) -> Self {
362        let mut p = (0..n).collect::<Vec<_>>();
363        for i in (1..=n).rev() {
364            let j = rank % i;
365            rank /= i;
366            p.swap(i - 1, j);
367        }
368        Permutation::from_map(p)
369    }
370
371    fn factorial(n: usize) -> usize {
372        (1..=n).product()
373    }
374
375    /// Computes the rank of the permutation in the Myrvold & Ruskey "Rank2" ordering.
376    ///
377    /// # Examples
378    ///
379    /// ```
380    /// # use linnet::permutation::Permutation;
381    /// let p = Permutation::from_map(vec![2, 1, 3, 0]);
382    /// // Suppose it has rank = R. We can test we get p back by unranking R.
383    /// let rank = p.clone().myrvold_ruskey_rank2();
384    /// let q = Permutation::myrvold_ruskey_unrank2(4, rank);
385    /// assert_eq!(q, p);
386    /// ```
387    pub fn myrvold_ruskey_rank2(mut self) -> usize {
388        let n = self.map.len();
389        if n == 1 {
390            return 0;
391        }
392        let s = self.map[n - 1];
393        self.map.swap_remove(self.inv[n - 1]);
394        self.inv.swap_remove(s);
395        s * Self::factorial(n - 1) + self.myrvold_ruskey_rank2()
396    }
397
398    /// Unranks a permutation of size `n` from its Myrvold & Ruskey "Rank2" index.
399    ///
400    /// # Examples
401    ///
402    /// ```
403    /// # use linnet::permutation::Permutation;
404    /// let p = Permutation::myrvold_ruskey_unrank2(4, 1);
405    /// assert_eq!(p.map(), &[2, 1, 3, 0]);
406    /// ```
407    pub fn myrvold_ruskey_unrank2(n: usize, mut rank: usize) -> Self {
408        let mut p = (0..n).collect::<Vec<_>>();
409        for i in (1..=n).rev() {
410            let s = rank / (Self::factorial(i - 1));
411            p.swap(i - 1, s);
412            rank %= Self::factorial(i - 1);
413        }
414        Permutation::from_map(p)
415    }
416
417    // --------------------------------------------------------------------------------------------
418    // Additional Suggested Methods
419    // --------------------------------------------------------------------------------------------
420
421    /// Checks if this permutation is the identity permutation (i.e., does nothing).
422    ///
423    /// # Examples
424    ///
425    /// ```
426    /// # use linnet::permutation::Permutation;
427    /// let p = Permutation::id(4);
428    /// assert!(p.is_identity());
429    ///
430    /// let q = Permutation::from_map(vec![1,0,2,3]);
431    /// assert!(!q.is_identity());
432    /// ```
433    // -- ADDED
434    pub fn is_identity(&self) -> bool {
435        self.map.iter().enumerate().all(|(i, &m)| i == m)
436    }
437
438    /// Returns the sign (+1 or -1) of the permutation,
439    /// indicating whether it is an even (+1) or odd (-1) permutation.
440    ///
441    /// # Examples
442    ///
443    /// ```
444    /// # use linnet::permutation::Permutation;
445    /// let p = Permutation::from_map(vec![1,0,3,2]);
446    /// assert_eq!(p.sign(), 1); // even
447    ///
448    /// let q = Permutation::from_map(vec![2,1,0]);
449    /// assert_eq!(q.sign(), -1); // odd
450    /// ```
451    // -- ADDED
452    pub fn sign(&self) -> i8 {
453        // Count inversions or use transpositions
454        let mut sign = 1i8;
455        for cycle in self.find_cycles() {
456            // Each cycle of length k contributes (k-1) to the total parity
457            let k = cycle.len();
458            if k > 1 && (k - 1) % 2 == 1 {
459                sign = -sign;
460            }
461        }
462        sign
463    }
464
465    /// Computes the k-th power of the permutation (composition with itself k times).
466    /// For k = 0, it returns the identity of the same size.
467    ///
468    /// # Examples
469    ///
470    /// ```
471    /// # use linnet::permutation::Permutation;
472    /// let p = Permutation::from_map(vec![1, 2, 0]);
473    /// // p^2 maps 0->p(1)=2, 1->p(2)=0, 2->p(0)=1 => [2,0,1]
474    /// let p2 = p.pow(2);
475    /// assert_eq!(p2.map(), &[2, 0, 1]);
476    /// ```
477    // -- ADDED
478    pub fn pow(&self, k: usize) -> Self {
479        if k == 0 {
480            return Permutation::id(self.map.len());
481        }
482        let mut result = Permutation::id(self.map.len());
483        let mut base = self.clone();
484        let mut exp = k;
485
486        while exp > 0 {
487            if exp % 2 == 1 {
488                result = result.compose(&base);
489            }
490            base = base.compose(&base);
491            exp /= 2;
492        }
493        result
494    }
495}
496
497/// Specifies the direction for reading cycle compositions
498#[derive(Debug, Copy, Clone, Eq, PartialEq)]
499pub enum CycleOrder {
500    /// Apply rightmost cycles first: (a b)(c d) applies (c d) then (a b)
501    LastFirst,
502    /// Apply leftmost cycles first: (a b)(c d) applies (a b) then (c d)
503    FirstFirst,
504}
505
506impl fmt::Display for Permutation {
507    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
508        // First show cycle notation
509        let cycles = self.find_cycles();
510        let mut first = true;
511        for cycle in cycles {
512            if cycle.len() > 1 {
513                // Only show non-trivial cycles
514                if !first {
515                    write!(f, " ")?;
516                }
517                write!(f, "(")?;
518                for (i, &x) in cycle.iter().enumerate() {
519                    if i > 0 {
520                        write!(f, " ")?;
521                    }
522                    write!(f, "{}", x)?;
523                }
524                write!(f, ")")?;
525                first = false;
526            }
527        }
528        if first {
529            // If no cycles were printed (identity permutation)
530            write!(f, "()")?;
531        }
532
533        // Then show one-line notation
534        write!(f, " [")?;
535        for (i, &x) in self.map.iter().enumerate() {
536            if i > 0 {
537                write!(f, " ")?;
538            }
539            write!(f, "{}", x)?;
540        }
541        write!(f, "]")
542    }
543}
544
545impl Permutation {
546    /// Creates a permutation from a set of disjoint cycles.
547    /// Each cycle should be a Vec<usize> representing indices in the cycle.
548    /// The cycles must be disjoint (no shared elements).
549    ///
550    /// # Examples
551    ///
552    /// ```
553    /// # use linnet::permutation::Permutation;
554    /// let cycles = vec![vec![0, 1, 2], vec![3, 4]];
555    /// let p = Permutation::from_disjoint_cycles(&cycles).unwrap();
556    /// assert_eq!(p.map(), &[1, 2, 0, 4, 3]);
557    ///
558    /// // Error if cycles are not disjoint
559    /// let invalid = vec![vec![0, 1], vec![1, 2]];
560    /// assert!(Permutation::from_disjoint_cycles(&invalid).is_err());
561    /// ```
562    pub fn from_disjoint_cycles(cycles: &[Vec<usize>]) -> Result<Self, String> {
563        // Find the size of the permutation (maximum index + 1)
564        let n = cycles
565            .iter()
566            .flat_map(|cycle| cycle.iter())
567            .max()
568            .map(|&max| max + 1)
569            .unwrap_or(0);
570
571        // Check for duplicates across cycles
572        let mut seen = vec![false; n];
573        for cycle in cycles {
574            for &idx in cycle {
575                if seen[idx] {
576                    return Err("Cycles are not disjoint".to_string());
577                }
578                seen[idx] = true;
579            }
580        }
581
582        // Create the permutation map
583        let mut map = (0..n).collect::<Vec<_>>();
584        for cycle in cycles {
585            if cycle.len() <= 1 {
586                continue;
587            }
588
589            // Map each element to the next element in the cycle
590            for i in 0..cycle.len() {
591                let from = cycle[i];
592                let to = cycle[(i + 1) % cycle.len()];
593                map[from] = to;
594            }
595        }
596
597        Ok(Permutation::from_map(map))
598    }
599    /// Creates a permutation from any set of cycles with specified reading order.
600    pub fn from_cycles_ordered(cycles: &[Vec<usize>], order: CycleOrder) -> Self {
601        // Find the size of the permutation
602        let n = cycles
603            .iter()
604            .flat_map(|cycle| cycle.iter())
605            .max()
606            .map(|&max| max + 1)
607            .unwrap_or(0);
608
609        // Start with identity permutation
610        let mut result = Permutation::id(n);
611
612        // Choose iteration order based on CycleOrder
613        let cycle_iter: Box<dyn Iterator<Item = &Vec<usize>>> = match order {
614            CycleOrder::LastFirst => Box::new(cycles.iter().rev()),
615            CycleOrder::FirstFirst => Box::new(cycles.iter()),
616        };
617
618        // Apply cycles in specified order
619        for cycle in cycle_iter {
620            if cycle.len() <= 1 {
621                continue;
622            }
623
624            // Create a single cycle permutation
625            let mut cycle_map = (0..n).collect::<Vec<_>>();
626            for i in 0..cycle.len() {
627                let from = cycle[i];
628                let to = cycle[(i + 1) % cycle.len()];
629                cycle_map[from] = to;
630            }
631            let cycle_perm = Permutation::from_map(cycle_map);
632            result = cycle_perm.compose(&result);
633        }
634
635        result
636    }
637
638    /// Creates a permutation from cycles using right-to-left reading order (default).
639    /// Equivalent to `from_cycles_ordered(cycles, CycleOrder::RightToLeft)`.
640    ///
641    /// # Examples
642    ///
643    /// ```
644    /// # use linnet::permutation::Permutation;
645    /// let cycles = vec![vec![0, 1, 2], vec![1, 2]];
646    /// let p = Permutation::from_cycles(&cycles);
647    /// assert_eq!(p.map(), &[1, 0, 2]);
648    /// ```
649    pub fn from_cycles(cycles: &[Vec<usize>]) -> Self {
650        Self::from_cycles_ordered(cycles, CycleOrder::LastFirst)
651    }
652
653    pub fn length(&self) -> usize {
654        self.map.len()
655    }
656
657    pub fn generate_all(generators: &[Permutation]) -> Result<Vec<Permutation>, PermutationError> {
658        let size = if let Some(generator) = generators.first() {
659            generator.length()
660        } else {
661            return Err(PermutationError::EmptyGenerators);
662        };
663        let mut all = AHashSet::new();
664        let mut stack = vec![Permutation::id(size)];
665        for g in generators {
666            if g.length() != size {
667                return Err(PermutationError::InvalidGeneratorLength);
668            }
669        }
670
671        while let Some(current) = stack.pop() {
672            for g in generators {
673                let next = current.compose(g);
674                if all.insert(next.clone()) {
675                    stack.push(next);
676                }
677            }
678        }
679
680        Ok(all.drain().collect())
681    }
682}
683
684#[derive(Error, Debug)]
685pub enum PermutationError {
686    #[error("Invalid generator length")]
687    InvalidGeneratorLength,
688
689    #[error("Empty generators")]
690    EmptyGenerators,
691}
692
693pub trait HedgeGraphExt {
694    fn hedges_between(&self, a: NodeIndex, b: NodeIndex) -> BitVec;
695
696    fn permute_subgraph<S: SubGraph>(&self, subgraph: &S, hedge_perm: &Permutation) -> BitVec;
697
698    fn orientation_ord(&self, hedge: Hedge) -> u8;
699}
700
701pub trait PermutationExt<Orderer: Ord = ()> {
702    // fn from_disjoint_cycles(cycles: &[Vec<usize>]) -> Result<Self, String>;
703    //
704    type Output;
705    type Edges;
706
707    fn permute_vertices(
708        &self,
709        perm: &Permutation,
710        ord: &impl Fn(&Self::Edges) -> Orderer,
711    ) -> Vec<Self::Output>;
712
713    fn sort_by(&self, hedge: Hedge, ord: &impl Fn(&Self::Edges) -> Orderer) -> impl Ord;
714
715    fn sort_by_perm(
716        &self,
717        hedge: Hedge,
718        perm: &Permutation,
719        ord: &impl Fn(&Self::Edges) -> Orderer,
720    ) -> impl Ord;
721}
722
723impl<E, V> HedgeGraphExt for HedgeGraph<E, V> {
724    fn hedges_between(&self, a: NodeIndex, b: NodeIndex) -> BitVec {
725        let a_ext =
726            InternalSubGraph::cleaned_filter_optimist(self.hairs_from_id(a).hairs.clone(), self)
727                .filter;
728        let b_ext =
729            InternalSubGraph::cleaned_filter_optimist(self.hairs_from_id(b).hairs.clone(), self)
730                .filter;
731        a_ext.intersection(&b_ext)
732    }
733
734    fn permute_subgraph<S: SubGraph>(&self, subgraph: &S, hedge_perm: &Permutation) -> BitVec {
735        let mut permuted_subgraph: BitVec = self.empty_subgraph();
736
737        for h in subgraph.included_iter() {
738            permuted_subgraph.set(hedge_perm[h.0], true);
739        }
740        permuted_subgraph
741    }
742
743    fn orientation_ord(&self, hedge: Hedge) -> u8 {
744        match self.superficial_hedge_orientation(hedge) {
745            Some(Flow::Sink) => 1,
746            Some(Flow::Source) => 2,
747            None => 0,
748        }
749    }
750}
751
752impl<E, V, O: Ord> PermutationExt<O> for HedgeGraph<E, V> {
753    type Output = Permutation;
754    type Edges = E;
755
756    fn permute_vertices(
757        &self,
758        perm: &Permutation,
759        ord: &impl Fn(&Self::Edges) -> O,
760    ) -> Vec<Self::Output> {
761        // fn generator_pair(shift: usize, n: usize, total_size: usize) -> [Permutation; 2] {
762        //     let mut map = (0..total_size).collect::<Vec<_>>();
763        //     for i in 0..n {
764        //         map[i + shift] = (i + 1) % n;
765        //     }
766        //     [
767        //         Permutation::from_map(map),
768        //         Permutation::from_cycles(&[vec![shift, shift + n - 1], vec![total_size]]),
769        //     ]
770        // }
771        //
772        fn generator_pair(n: usize) -> [Permutation; 2] {
773            let mut map = Vec::new();
774            for i in 0..n {
775                map.push((i + 1) % n)
776            }
777            [
778                Permutation::from_map(map),
779                Permutation::from_cycles(&[vec![0, n - 1]]),
780            ]
781        }
782        let transpositions = perm.map();
783        let mut perms = Vec::new();
784
785        let n = self.n_hedges();
786        let mut map = (0..n).collect::<Vec<_>>();
787
788        for (from, &to) in transpositions.iter().enumerate() {
789            let from_hairs = &self.hairs_from_id(NodeIndex(from)).hairs;
790            let mut from_hedges = from_hairs.included_iter().collect::<Vec<_>>();
791            let to_hairs = &self.hairs_from_id(NodeIndex(to)).hairs;
792            let mut to_hedges = to_hairs.included_iter().collect::<Vec<_>>();
793
794            let mut to = BTreeMap::new();
795
796            to_hedges.iter().for_each(|&hedge| {
797                to.entry(self.sort_by_perm(hedge, perm, ord))
798                    .or_insert_with(Vec::new)
799                    .push(hedge);
800            });
801            to_hedges = to
802                .values()
803                .flat_map(|values| {
804                    if values.len() > 1
805                        && self.node_id(self.inv(values[0])).0 <= self.node_id(values[0]).0
806                    //insure no double counting of inter-edge permutation
807                    {
808                        let gen_pair = generator_pair(values.len());
809
810                        let cycle = gen_pair[0].apply_slice(values);
811                        let trans = gen_pair[1].apply_slice(values);
812
813                        println!("{values:?}{cycle:?}{trans:?}");
814
815                        let mut cycle_map = (0..n).collect::<Vec<_>>();
816                        let mut trans_map = (0..n).collect::<Vec<_>>();
817                        for i in 0..values.len() {
818                            cycle_map[cycle[i].0] = values[i].0;
819                            trans_map[trans[i].0] = values[i].0;
820                        }
821
822                        perms.push(Permutation::from_map(cycle_map));
823                        perms.push(Permutation::from_map(trans_map));
824                    }
825                    values
826                })
827                .cloned()
828                .collect();
829
830            // let mut to = BTreeMap::new();
831
832            // to_hedges.iter().for_each(|&hedge| {
833            //     to.entry(self.sort_by(hedge, ord))
834            //         .or_insert_with(Vec::new)
835            //         .push(hedge);
836            // });
837
838            from_hedges.sort_by(|a, b| self.sort_by(*a, ord).cmp(&self.sort_by(*b, ord)));
839
840            // to_hedges.sort_by(|a, b| {
841            //     self.sort_by_perm(*a, perm, ord)
842            //         .cmp(&self.sort_by_perm(*b, perm, ord))
843            // });
844
845            // println!("from:{from_hedges:?}");
846
847            for (from_hedge, to_hedge) in from_hedges.iter().zip(to_hedges.iter()) {
848                // println!("{from_hedge}->{to_hedge}");
849                map[from_hedge.0] = to_hedge.0;
850            }
851        }
852        let mut maps = vec![];
853        let map = Permutation::from_map(map);
854        // println!("Map:{map}");
855        match Permutation::generate_all(&perms) {
856            Ok(a) => {
857                for p in a {
858                    println!("Permutation:{p}");
859                    println!("Composition:{}", map.compose(&p));
860                    maps.push(map.compose(&p));
861                }
862            }
863            Err(PermutationError::EmptyGenerators) => maps.push(map),
864            Err(e) => panic!("Error generating permutations: {}", e),
865        }
866        maps
867    }
868
869    fn sort_by(&self, hedge: Hedge, ord: &impl Fn(&Self::Edges) -> O) -> impl Ord {
870        (
871            self.involved_node_id(hedge)
872                .unwrap_or(self.node_id(hedge))
873                .0,
874            self.orientation_ord(hedge),
875            ord(self.get_edge_data(hedge)),
876        )
877    }
878
879    fn sort_by_perm(
880        &self,
881        hedge: Hedge,
882        perm: &Permutation,
883        ord: &impl Fn(&Self::Edges) -> O,
884    ) -> impl Ord {
885        (
886            perm.inv()[self
887                .involved_node_id(hedge)
888                .unwrap_or(self.node_id(hedge))
889                .0],
890            self.orientation_ord(hedge),
891            ord(self.get_edge_data(hedge)),
892        )
893    }
894}
895
896impl Index<usize> for Permutation {
897    type Output = usize;
898
899    fn index(&self, index: usize) -> &Self::Output {
900        &self.map()[index]
901    }
902}
903
904#[cfg(test)]
905mod tests {
906    use crate::half_edge::{builder::HedgeGraphBuilder, involution::Flow};
907
908    use super::*;
909
910    #[test]
911    fn test_from_disjoint_cycles() {
912        // Test disjoint cycles
913        let cycles = vec![vec![0, 3, 2], vec![1, 4]];
914        let p = Permutation::from_disjoint_cycles(&cycles).unwrap();
915        assert_eq!(p.map(), &[3, 4, 0, 2, 1]);
916
917        // Test single cycle
918        let cycles = vec![vec![0, 1, 2]];
919        let p = Permutation::from_disjoint_cycles(&cycles).unwrap();
920        assert_eq!(p.map(), &[1, 2, 0]);
921
922        // Test non-disjoint cycles
923        let cycles = vec![vec![0, 1], vec![1, 2]];
924        assert!(Permutation::from_disjoint_cycles(&cycles).is_err());
925
926        // Test empty cycles
927        let cycles: Vec<Vec<usize>> = vec![];
928        let p = Permutation::from_disjoint_cycles(&cycles).unwrap();
929        assert!(p.map().is_empty());
930
931        // Test single element cycles
932        let cycles = vec![vec![0]];
933        let p = Permutation::from_disjoint_cycles(&cycles).unwrap();
934        assert_eq!(p.map(), &[0]);
935    }
936
937    #[test]
938    fn test_from_cycles_ordered() {
939        let cycles = vec![vec![0, 1, 2], vec![1, 2]];
940
941        // Right to left: (0 1 2)(1 2)
942        // First (1 2): [0 2 1]
943        // Then (0 1 2): [1 0 2]
944        let p = Permutation::from_cycles_ordered(&cycles, CycleOrder::LastFirst);
945        assert_eq!(p.map(), &[1, 0, 2]);
946
947        // Left to right: (1 2)(0 1 2)
948        // First (0 1 2): [1 2 0]
949        // Then (1 2): [0 2 1]
950        let p = Permutation::from_cycles_ordered(&cycles, CycleOrder::FirstFirst);
951        assert_eq!(p.map(), &[2, 1, 0]);
952    }
953
954    #[test]
955    fn test_cycle_composition_both_orders() {
956        // Test (1 2)(0 1)
957        let cycles = vec![vec![1, 2], vec![0, 1]];
958
959        // Right to left: apply (0 1) then (1 2)
960        let p = Permutation::from_cycles_ordered(&cycles, CycleOrder::LastFirst);
961        assert_eq!(p.map(), &[2, 0, 1]);
962
963        // Left to right: apply (1 2) then (0 1)
964        let p = Permutation::from_cycles_ordered(&cycles, CycleOrder::FirstFirst);
965        assert_eq!(p.map(), &[1, 2, 0]);
966    }
967
968    #[test]
969    fn test_default_order() {
970        let cycles = vec![vec![0, 1, 2], vec![1, 2]];
971        let p1 = Permutation::from_cycles(&cycles);
972        let p2 = Permutation::from_cycles_ordered(&cycles, CycleOrder::LastFirst);
973        assert_eq!(p1, p2);
974    }
975
976    #[test]
977    fn test_disjoint_cycles_order_invariant() {
978        let cycles = vec![vec![0, 1], vec![2, 3]];
979        let p1 = Permutation::from_cycles_ordered(&cycles, CycleOrder::LastFirst);
980        let p2 = Permutation::from_cycles_ordered(&cycles, CycleOrder::FirstFirst);
981        // Order shouldn't matter for disjoint cycles
982        assert_eq!(p1, p2);
983    }
984
985    #[test]
986    fn test_from_cycles() {
987        // Test single cycle
988        let cycles = vec![vec![0, 1, 2]];
989        let p = Permutation::from_cycles(&cycles);
990        assert_eq!(p.map(), &[1, 2, 0]);
991
992        // Test overlapping cycles
993        let cycles = vec![vec![0, 1, 2], vec![1, 2]];
994        let p = Permutation::from_cycles(&cycles);
995        assert_eq!(p.map(), &[1, 0, 2]);
996
997        // Test multiple disjoint cycles
998        let cycles = vec![vec![0, 1], vec![2, 3]];
999        let p = Permutation::from_cycles(&cycles);
1000        assert_eq!(p.map(), &[1, 0, 3, 2]);
1001
1002        // Test composition order
1003        let cycles = vec![vec![0, 1], vec![1, 2]]; // (0 1)(1 2) = (0 1 2)
1004        let p = Permutation::from_cycles(&cycles);
1005        assert_eq!(p.map(), &[1, 2, 0]);
1006    }
1007
1008    #[test]
1009    fn test_cycle_composition_properties() {
1010        // Test that (0 1 2)(1 2) = (0 1)()
1011        let p = Permutation::from_cycles(&[vec![0, 1, 2], vec![1, 2]]);
1012        let q = Permutation::from_cycles(&[vec![1, 0], vec![2]]);
1013        assert_eq!(p, q);
1014
1015        // Test that (0 1)(1 2) = (0 1 2)
1016        let p = Permutation::from_cycles(&[vec![0, 1], vec![1, 2]]);
1017        let q = Permutation::from_cycles(&[vec![1, 2, 0]]);
1018        assert_eq!(p, q);
1019    }
1020
1021    #[test]
1022    fn test_myrvold_ruskey_rank1() {
1023        let p = Permutation::from_map(vec![2, 1, 3, 0]);
1024        assert_eq!(p.myrvold_ruskey_rank1(), 12);
1025        for i in 0..=23 {
1026            assert_eq!(
1027                i,
1028                Permutation::myrvold_ruskey_rank1(Permutation::myrvold_ruskey_unrank1(4, i))
1029            );
1030        }
1031    }
1032
1033    #[test]
1034    fn test_myrvold_ruskey_rank2() {
1035        let p = Permutation::myrvold_ruskey_unrank2(4, 1);
1036        assert_eq!(p.map, vec![2, 1, 3, 0]);
1037        for i in 0..=23 {
1038            assert_eq!(
1039                i,
1040                Permutation::myrvold_ruskey_rank2(Permutation::myrvold_ruskey_unrank2(4, i))
1041            );
1042        }
1043    }
1044
1045    #[test]
1046    fn test_apply_slice() {
1047        let p = Permutation::from_map(vec![2, 1, 3, 0]);
1048        let data = vec![10, 20, 30, 40];
1049        let permuted = p.apply_slice(&data);
1050        assert_eq!(permuted, vec![30, 20, 40, 10]);
1051    }
1052
1053    #[test]
1054    fn test_apply_slice_inv() {
1055        let p = Permutation::from_map(vec![2, 1, 3, 0]);
1056        let data = vec![10, 20, 30, 40];
1057        let permuted = p.apply_slice_inv(&data);
1058        assert_eq!(permuted, vec![40, 20, 10, 30]);
1059    }
1060
1061    #[test]
1062    fn test_find_cycles() {
1063        let p = Permutation::from_map(vec![2, 0, 1, 3]);
1064        let cycles = p.find_cycles();
1065        assert_eq!(cycles, vec![vec![0, 2, 1], vec![3]]);
1066    }
1067
1068    #[test]
1069    fn test_cycle_to_transpositions() {
1070        let cycle = vec![0, 2, 1];
1071        let transpositions = Permutation::cycle_to_transpositions(&cycle);
1072        assert_eq!(transpositions, vec![(0, 1), (0, 2)]);
1073    }
1074
1075    #[test]
1076    fn test_transpositions() {
1077        let p = Permutation::sort([2, 1, 0, 3]);
1078
1079        let transpositions = p.transpositions();
1080        println!("{:?}", transpositions.len());
1081
1082        let p = Permutation::from_map(vec![2, 0, 1, 3]);
1083        let transpositions = p.transpositions();
1084        assert_eq!(transpositions, vec![(0, 1), (0, 2)]);
1085    }
1086
1087    #[test]
1088    fn test_apply_slice_in_place() {
1089        let p = Permutation::from_map(vec![2, 0, 1, 3]);
1090        let mut data = vec![10, 20, 30, 40];
1091        p.apply_slice_in_place(&mut data);
1092        assert_eq!(data, vec![20, 30, 10, 40]);
1093    }
1094
1095    #[test]
1096    fn test_apply_slice_in_place_inv() {
1097        let p = Permutation::from_map(vec![2, 0, 1, 3]);
1098        let mut data = vec![10, 20, 30, 40];
1099        p.apply_slice_in_place_inv(&mut data);
1100        assert_eq!(data, vec![30, 10, 20, 40]);
1101    }
1102
1103    #[test]
1104    fn test_sort() {
1105        let data = vec![30, 10, 20, 40];
1106        let perm = Permutation::sort(&data);
1107        assert_eq!(perm.map, vec![1, 2, 0, 3]);
1108
1109        let sorted_data = perm.apply_slice(&data);
1110        assert_eq!(sorted_data, vec![10, 20, 30, 40]);
1111    }
1112
1113    #[test]
1114    fn test_sort_inverse() {
1115        let data = vec![30, 10, 20, 40];
1116        let perm = Permutation::sort(&data);
1117        let sorted_data = perm.apply_slice(&data);
1118        assert_eq!(sorted_data, vec![10, 20, 30, 40]);
1119
1120        let inv_perm = perm.inverse();
1121        let original_data = inv_perm.apply_slice(&sorted_data);
1122        assert_eq!(original_data, data);
1123    }
1124
1125    // -- ADDED TESTS
1126
1127    #[test]
1128    fn test_is_identity() {
1129        let p = Permutation::id(5);
1130        assert!(p.is_identity());
1131
1132        let q = Permutation::from_map(vec![1, 0, 2]);
1133        assert!(!q.is_identity());
1134    }
1135
1136    #[test]
1137    fn test_sign() {
1138        // Even permutation
1139        let p = Permutation::from_map(vec![1, 0, 3, 2]);
1140        assert_eq!(p.sign(), 1);
1141
1142        // Odd permutation
1143        let q = Permutation::from_map(vec![2, 1, 0]);
1144        assert_eq!(q.sign(), -1);
1145    }
1146
1147    #[test]
1148    fn test_pow() {
1149        let p = Permutation::from_map(vec![1, 2, 0]);
1150        // p^1 = p
1151        assert_eq!(p.pow(1), p);
1152
1153        // p^2 = 0->2,1->0,2->1 => [2,0,1]
1154        let p2 = p.pow(2);
1155        assert_eq!(p2.map(), &[2, 0, 1]);
1156
1157        // p^3 = identity
1158        let p3 = p.pow(3);
1159        assert_eq!(p3, Permutation::id(3));
1160    }
1161
1162    #[test]
1163    fn test_compose() {
1164        // p1: 0→1, 1→2, 2→0 (a cycle of length 3)
1165        let p1 = Permutation::from_map(vec![1, 2, 0]);
1166
1167        // p2: 0→2, 1→0, 2→1 (the inverse of p1)
1168        let p2 = Permutation::from_map(vec![2, 0, 1]);
1169
1170        // By definition in your code, compose(self, other) = x ↦ other(self(x)).
1171        //
1172        // So p2 ∘ p1 means apply p1 first, then p2. Since p2 is the inverse of p1,
1173        // their composition should be the identity permutation.
1174        let c1 = p1.compose(&p2);
1175        assert_eq!(c1, Permutation::id(3), "Expected p2 ∘ p1 = identity");
1176
1177        // Likewise, p1 ∘ p2 = identity
1178        let c2 = p2.compose(&p1);
1179        assert_eq!(c2, Permutation::id(3), "Expected p1 ∘ p2 = identity");
1180
1181        {
1182            let p1 = Permutation::from_map(vec![1, 0, 2]); // (0 1)
1183            let p2 = Permutation::from_map(vec![0, 2, 1]); // (1 2)
1184
1185            let c1 = p1.compose(&p2); // (0 1)(1 2) = (0 1 2)
1186            let c2 = p2.compose(&p1); // (1 2)(0 1) = (0 2 1)
1187
1188            assert_ne!(
1189                c1, c2,
1190                "Different order of composition should give different results"
1191            );
1192            assert_eq!(c1.map(), &[1, 2, 0]);
1193            assert_eq!(c2.map(), &[2, 0, 1]);
1194        }
1195
1196        // Test associativity: (a ∘ b) ∘ c = a ∘ (b ∘ c)
1197        {
1198            let p1 = Permutation::from_map(vec![1, 2, 0]);
1199            let p2 = Permutation::from_map(vec![2, 0, 1]);
1200            let p3 = Permutation::from_map(vec![0, 2, 1]);
1201
1202            let c1 = p1.compose(&p2).compose(&p3);
1203            let c2 = p1.compose(&p2.compose(&p3));
1204
1205            assert_eq!(c1, c2, "Composition should be associative");
1206        }
1207
1208        // Test composition of disjoint cycles
1209        {
1210            let p1 = Permutation::from_map(vec![1, 0, 2, 3]); // (0 1)
1211            let p2 = Permutation::from_map(vec![0, 1, 3, 2]); // (2 3)
1212
1213            let c = p1.compose(&p2);
1214            assert_eq!(
1215                c.map(),
1216                &[1, 0, 3, 2],
1217                "Disjoint cycles should compose independently"
1218            );
1219        }
1220
1221        // Test composition order with multiple elements
1222        {
1223            let p1 = Permutation::from_map(vec![1, 2, 3, 0]); // (0 1 2 3)
1224            let p2 = Permutation::from_map(vec![3, 2, 1, 0]); // (0 3)(1 2)
1225
1226            let c = p1.compose(&p2);
1227            assert_eq!(
1228                c.map(),
1229                &[0, 3, 2, 1],
1230                "Complex composition should work correctly"
1231            );
1232        }
1233    }
1234
1235    #[test]
1236    fn test_permute_graph() {
1237        let mut triangle = HedgeGraphBuilder::new();
1238
1239        let a = triangle.add_node(());
1240        let b = triangle.add_node(());
1241        let c = triangle.add_node(());
1242
1243        triangle.add_edge(a, b, (), false);
1244        triangle.add_edge(b, c, (), false);
1245        triangle.add_edge(c, a, (), false);
1246
1247        let graph = triangle.build();
1248        let perm = Permutation::from_cycles(&[vec![0, 2], vec![1]]); //permutes a and c
1249        let perm2 = Permutation::from_cycles(&[vec![0, 1, 2]]); //permutes a and c
1250
1251        let a_b_edge = graph.hedges_between(a, b);
1252        let b_c_edge = graph.hedges_between(b, c);
1253        let c_a_edge = graph.hedges_between(c, a);
1254
1255        let hedge_perm = graph.permute_vertices(&perm, &|_| ());
1256        let hedge_perm2 = graph.permute_vertices(&perm2, &|_| ());
1257        let permuted_b_c_edge = graph.permute_subgraph(&b_c_edge, &hedge_perm[0]);
1258        let permuted_b_c_edge2 = graph.permute_subgraph(&b_c_edge, &hedge_perm2[0]);
1259        let permuted_a_b_edge = graph.permute_subgraph(&a_b_edge, &hedge_perm[0]);
1260        let permuted_a_b_edge2 = graph.permute_subgraph(&a_b_edge, &hedge_perm2[0]);
1261        let permuted_c_a_edge = graph.permute_subgraph(&c_a_edge, &hedge_perm[0]);
1262        let permuted_c_a_edge2 = graph.permute_subgraph(&c_a_edge, &hedge_perm2[0]);
1263
1264        assert_eq!(hedge_perm.len(), 1);
1265
1266        println!(
1267            "//a-c\n{}\n//a-b\n{}\n//b-c\n{}",
1268            graph.dot(&c_a_edge),
1269            graph.dot(&a_b_edge),
1270            graph.dot(&b_c_edge)
1271        );
1272        println!(
1273            "//permuted a-b\n{}\n//permuted b-c\n{}\n//permuted c-a\n{}",
1274            graph.dot(&permuted_a_b_edge),
1275            graph.dot(&permuted_b_c_edge),
1276            graph.dot(&permuted_c_a_edge)
1277        );
1278        println!(
1279            "//permuted a-b\n{}\n//permuted b-c\n{}\n//permuted c-a\n{}",
1280            graph.dot(&permuted_a_b_edge2),
1281            graph.dot(&permuted_b_c_edge2),
1282            graph.dot(&permuted_c_a_edge2)
1283        );
1284
1285        assert_eq!(a_b_edge, permuted_b_c_edge);
1286        assert_eq!(b_c_edge, permuted_a_b_edge);
1287        assert_eq!(c_a_edge, permuted_c_a_edge);
1288
1289        // println!(
1290        //     "{}\n{}",
1291        //     graph.dot(&cleaned_subgraph),
1292        //     graph.dot(&permuted_subgraph)
1293        // )
1294        // let permuted_subgraph = hedgeperm.apply_slice(cleaned_subgraph.filter);
1295    }
1296
1297    #[test]
1298    fn test_permute_graph_double_edges() {
1299        let mut triangle = HedgeGraphBuilder::new();
1300
1301        let a = triangle.add_node(());
1302        let b = triangle.add_node(());
1303        let c = triangle.add_node(());
1304
1305        triangle.add_edge(a, b, (), false);
1306
1307        triangle.add_external_edge(a, (), false, Flow::Sink);
1308        triangle.add_edge(b, c, (), false);
1309        triangle.add_external_edge(c, (), false, Flow::Source);
1310        triangle.add_edge(c, a, (), false);
1311        triangle.add_edge(c, a, (), false);
1312        let graph = triangle.build();
1313        let perm = Permutation::from_cycles(&[vec![0, 2], vec![1]]); //permutes a and c
1314
1315        let a_b_edge = graph.hedges_between(a, b);
1316        let b_c_edge = graph.hedges_between(b, c);
1317        let c_a_edge = graph.hedges_between(c, a);
1318
1319        let hedge_perm = graph.permute_vertices(&perm, &|_| ());
1320        let permuted_b_c_edge = graph.permute_subgraph(&b_c_edge, &hedge_perm[0]);
1321        let permuted_a_b_edge = graph.permute_subgraph(&a_b_edge, &hedge_perm[0]);
1322        let permuted_c_a_edge = graph.permute_subgraph(&c_a_edge, &hedge_perm[0]);
1323
1324        assert_eq!(hedge_perm.len(), 2);
1325        assert_eq!(a_b_edge, permuted_b_c_edge);
1326        assert_eq!(b_c_edge, permuted_a_b_edge);
1327        assert_eq!(c_a_edge, permuted_c_a_edge);
1328
1329        println!(
1330            "//a-c\n{}\n//a-b\n{}\n//b-c\n{}",
1331            graph.dot(&c_a_edge),
1332            graph.dot(&a_b_edge),
1333            graph.dot(&b_c_edge)
1334        );
1335        println!(
1336            "//permuted a-b\n{}\n//permuted b-c\n{}\n//permuted c-a\n{}",
1337            graph.dot(&permuted_a_b_edge),
1338            graph.dot(&permuted_b_c_edge),
1339            graph.dot(&permuted_c_a_edge)
1340        );
1341        // let permuted_subgraph = hedgeperm.apply_slice(a.filter);
1342    }
1343
1344    #[test]
1345    fn test_permute_double_triangle() {
1346        let mut doubletriangle = HedgeGraphBuilder::new();
1347
1348        let a = doubletriangle.add_node(());
1349        let b = doubletriangle.add_node(());
1350        let c = doubletriangle.add_node(());
1351        let d = doubletriangle.add_node(());
1352
1353        doubletriangle.add_edge(a, b, (), false);
1354
1355        doubletriangle.add_edge(b, c, (), false);
1356        doubletriangle.add_edge(c, d, (), false);
1357        doubletriangle.add_edge(d, a, (), false);
1358        doubletriangle.add_edge(c, a, (), false);
1359        let graph = doubletriangle.build();
1360        let perm = Permutation::from_cycles(&[vec![0, 2], vec![3]]); //permutes a and c
1361
1362        let a_b_edge = graph.hedges_between(a, b);
1363        let b_c_edge = graph.hedges_between(b, c);
1364        let c_a_edge = graph.hedges_between(c, a);
1365
1366        let hedge_perm = graph.permute_vertices(&perm, &|_| ());
1367        let permuted_b_c_edge = graph.permute_subgraph(&b_c_edge, &hedge_perm[0]);
1368        let permuted_a_b_edge = graph.permute_subgraph(&a_b_edge, &hedge_perm[0]);
1369        let permuted_c_a_edge = graph.permute_subgraph(&c_a_edge, &hedge_perm[0]);
1370
1371        assert_eq!(hedge_perm.len(), 1);
1372        assert_eq!(a_b_edge, permuted_b_c_edge);
1373        assert_eq!(b_c_edge, permuted_a_b_edge);
1374        assert_eq!(c_a_edge, permuted_c_a_edge);
1375
1376        println!(
1377            "//a-c\n{}\n//a-b\n{}\n//b-c\n{}",
1378            graph.dot(&c_a_edge),
1379            graph.dot(&a_b_edge),
1380            graph.dot(&b_c_edge)
1381        );
1382        println!(
1383            "//permuted a-b\n{}\n//permuted b-c\n{}\n//permuted c-a\n{}",
1384            graph.dot(&permuted_a_b_edge),
1385            graph.dot(&permuted_b_c_edge),
1386            graph.dot(&permuted_c_a_edge)
1387        );
1388        // let permuted_subgraph = hedgeperm.apply_slice(a.filter);
1389    }
1390
1391    #[test]
1392    fn cyclic_doubled_triangle() {
1393        let mut doubledtriangle = HedgeGraphBuilder::new();
1394
1395        let a = doubledtriangle.add_node(());
1396        let b = doubledtriangle.add_node(());
1397        let c = doubledtriangle.add_node(());
1398
1399        doubledtriangle.add_edge(a, b, (), false);
1400        doubledtriangle.add_edge(a, b, (), false);
1401        doubledtriangle.add_edge(b, c, (), false);
1402        doubledtriangle.add_edge(b, c, (), false);
1403        doubledtriangle.add_edge(c, a, (), false);
1404        doubledtriangle.add_edge(c, a, (), false);
1405        let graph = doubledtriangle.build();
1406        let perm = Permutation::from_cycles(&[vec![0, 1, 2]]); //single cycle
1407
1408        let a_b_edge = graph.hedges_between(a, b);
1409        let b_c_edge = graph.hedges_between(b, c);
1410        let c_a_edge = graph.hedges_between(c, a);
1411
1412        let hedge_perm = graph.permute_vertices(&perm, &|_| ());
1413        let permuted_b_c_edge = graph.permute_subgraph(&b_c_edge, &hedge_perm[0]);
1414        let permuted_a_b_edge = graph.permute_subgraph(&a_b_edge, &hedge_perm[0]);
1415        let permuted_c_a_edge = graph.permute_subgraph(&c_a_edge, &hedge_perm[0]);
1416
1417        assert_eq!(hedge_perm.len(), 8); //2^3
1418
1419        println!(
1420            "//a-c\n{}\n//a-b\n{}\n//b-c\n{}",
1421            graph.dot(&c_a_edge),
1422            graph.dot(&a_b_edge),
1423            graph.dot(&b_c_edge)
1424        );
1425        println!(
1426            "//permuted a-b\n{}\n//permuted b-c\n{}\n//permuted c-a\n{}",
1427            graph.dot(&permuted_a_b_edge),
1428            graph.dot(&permuted_b_c_edge),
1429            graph.dot(&permuted_c_a_edge)
1430        );
1431        assert_eq!(a_b_edge, permuted_c_a_edge);
1432        assert_eq!(c_a_edge, permuted_b_c_edge);
1433        assert_eq!(b_c_edge, permuted_a_b_edge);
1434        // let permuted_subgraph = hedgeperm.apply_slice(a.filter);
1435    }
1436
1437    #[test]
1438    fn cycle_permutation() {
1439        let mut cycle = HedgeGraphBuilder::new();
1440
1441        let a = cycle.add_node(());
1442        let b = cycle.add_node(());
1443
1444        cycle.add_edge(a, b, (), false);
1445        cycle.add_edge(b, a, (), false);
1446
1447        let graph = cycle.build();
1448        let perm = Permutation::from_cycles(&[vec![0, 1]]); //permutes a and b
1449
1450        let h = Hedge(0);
1451        let mut h_sub: BitVec = graph.empty_subgraph();
1452        h_sub.set(h.0, true);
1453
1454        let hedge_perm = graph.permute_vertices(&perm, &|_| ());
1455        let permuted_h = graph.permute_subgraph(&h_sub, &hedge_perm[0]);
1456        println!("n perms{}", hedge_perm.len());
1457
1458        println!("//origninal:\n{}", graph.dot(&h_sub));
1459        println!("//permuted:\n{}", graph.dot(&permuted_h));
1460        // let permuted_subgraph = hedgeperm.apply_slice(a.filter);
1461    }
1462
1463    #[test]
1464    fn triple_loop_two_nodes() {
1465        let mut cycle = HedgeGraphBuilder::new();
1466
1467        let a = cycle.add_node(());
1468        let b = cycle.add_node(());
1469
1470        cycle.add_edge(a, b, (), false);
1471        cycle.add_edge(b, a, (), false);
1472        cycle.add_edge(b, a, (), false);
1473
1474        let graph = cycle.build();
1475        let perm = Permutation::from_cycles(&[vec![0, 1]]); //permutes a and b
1476
1477        let h = Hedge(0);
1478        let mut h_sub: BitVec = graph.empty_subgraph();
1479        h_sub.set(h.0, true);
1480
1481        let hedge_perm = graph.permute_vertices(&perm, &|_| ());
1482        let permuted_h = graph.permute_subgraph(&h_sub, &hedge_perm[0]);
1483        println!("n perms{}", hedge_perm.len());
1484
1485        println!("//origninal:\n{}", graph.dot(&h_sub));
1486        println!("//permuted:\n{}", graph.dot(&permuted_h));
1487        // let permuted_subgraph = hedgeperm.apply_slice(a.filter);
1488    }
1489
1490    #[test]
1491    fn generate_all() {
1492        fn generator_pair(n: usize) -> [Permutation; 2] {
1493            let mut map = Vec::new();
1494            for i in 0..n {
1495                map.push((i + 1) % n)
1496            }
1497            [
1498                Permutation::from_map(map),
1499                Permutation::from_cycles(&[vec![0, n - 1]]),
1500            ]
1501        }
1502
1503        let all_2 = Permutation::generate_all(&generator_pair(2)).unwrap();
1504
1505        let all_3 = Permutation::generate_all(&generator_pair(3)).unwrap();
1506        let all_4 = Permutation::generate_all(&generator_pair(4)).unwrap();
1507        assert_eq!(all_2.len(), 2);
1508        assert_eq!(all_3.len(), 6);
1509        assert_eq!(all_4.len(), 24);
1510    }
1511}