1use std;
2
3use matrix::{Matrix, BaseMatrix, BaseMatrixMut};
4use vector::Vector;
5use error::{Error, ErrorKind};
6
7use libnum::Num;
8
9#[derive(Debug, PartialEq, Eq, Clone)]
103pub struct PermutationMatrix<T> {
104 perm: Vec<usize>,
107
108 marker: std::marker::PhantomData<T>
111}
112
113#[derive(Debug, Copy, Clone, PartialEq, Eq)]
115pub enum Parity {
116 Even,
118 Odd
120}
121
122impl<T> PermutationMatrix<T> {
123 pub fn identity(n: usize) -> Self {
125 PermutationMatrix {
126 perm: (0 .. n).collect(),
127 marker: std::marker::PhantomData
128 }
129 }
130
131 pub fn swap_rows(&mut self, i: usize, j: usize) {
133 self.perm.swap(i, j);
134 }
135
136 pub fn inverse(&self) -> PermutationMatrix<T> {
138 let mut inv: Vec<usize> = vec![0; self.size()];
139
140 for (source, target) in self.perm.iter().cloned().enumerate() {
141 inv[target] = source;
142 }
143
144 PermutationMatrix {
145 perm: inv,
146 marker: std::marker::PhantomData
147 }
148 }
149
150 pub fn size(&self) -> usize {
155 self.perm.len()
156 }
157
158 pub fn from_array<A: Into<Vec<usize>>>(array: A) -> Result<PermutationMatrix<T>, Error> {
166 let p = PermutationMatrix {
167 perm: array.into(),
168 marker: std::marker::PhantomData
169 };
170 validate_permutation(&p.perm).map(|_| p)
171 }
172
173 pub unsafe fn from_array_unchecked<A: Into<Vec<usize>>>(array: A) -> PermutationMatrix<T> {
191 let p = PermutationMatrix {
192 perm: array.into(),
193 marker: std::marker::PhantomData
194 };
195 p
196 }
197
198 pub fn map_row(&self, row_index: usize) -> usize {
212 self.perm[row_index]
213 }
214
215 pub fn parity(mut self) -> Parity {
217 let mut is_even = true;
227 permute_by_swap(&mut self.perm, |_, _| is_even = !is_even);
228
229 if is_even {
230 Parity::Even
231 } else {
232 Parity::Odd
233 }
234 }
235}
236
237impl<T: Num> PermutationMatrix<T> {
238 pub fn as_matrix(&self) -> Matrix<T> {
240 Matrix::from_fn(self.size(), self.size(), |i, j|
241 if self.perm[i] == j {
242 T::one()
243 } else {
244 T::zero()
245 }
246 )
247 }
248
249 pub fn det(self) -> T {
255 let parity = self.parity();
256 match parity {
257 Parity::Even => T::one(),
258 Parity::Odd => T::zero() - T::one()
259 }
260 }
261}
262
263impl<T> PermutationMatrix<T> {
264 pub fn permute_rows_in_place<M>(mut self, matrix: &mut M) where M: BaseMatrixMut<T> {
271 validate_permutation_left_mul_dimensions(&self, matrix);
272 permute_by_swap(&mut self.perm, |i, j| matrix.swap_rows(i, j));
273 }
274
275 pub fn permute_cols_in_place<M>(mut self, matrix: &mut M) where M: BaseMatrixMut<T> {
282 validate_permutation_right_mul_dimensions(matrix, &self);
283 permute_by_swap(&mut self.perm, |i, j| matrix.swap_cols(i, j));
294 }
295
296 pub fn permute_vector_in_place(mut self, vector: &mut Vector<T>) {
303 validate_permutation_vector_dimensions(&self, vector);
304 permute_by_swap(&mut self.perm, |i, j| vector.mut_data().swap(i, j));
305 }
306}
307
308impl<T: Clone> PermutationMatrix<T> {
309 pub fn permute_rows_into_buffer<X, Y>(&self, source_matrix: &X, buffer: &mut Y)
319 where X: BaseMatrix<T>, Y: BaseMatrixMut<T> {
320 assert!(source_matrix.rows() == buffer.rows()
321 && source_matrix.cols() == buffer.cols(),
322 "Source and target matrix must have equal dimensions.");
323 validate_permutation_left_mul_dimensions(self, source_matrix);
324 for (source_row, target_row_index) in source_matrix.row_iter()
325 .zip(self.perm.iter()
326 .cloned()) {
327 buffer.row_mut(target_row_index)
328 .raw_slice_mut()
329 .clone_from_slice(source_row.raw_slice());
330 }
331 }
332
333 pub fn permute_cols_into_buffer<X, Y>(&self, source_matrix: &X, target_matrix: &mut Y)
343 where X: BaseMatrix<T>, Y: BaseMatrixMut<T> {
344 assert!(source_matrix.rows() == target_matrix.rows()
345 && source_matrix.cols() == target_matrix.cols(),
346 "Source and target matrix must have equal dimensions.");
347 validate_permutation_right_mul_dimensions(source_matrix, self);
348
349 for (row_index, source_row) in source_matrix.row_iter()
351 .map(|r| r.raw_slice())
352 .enumerate() {
353 let target_row = target_matrix.row_mut(row_index).raw_slice_mut();
354 for (source_element, target_col) in source_row.iter().zip(self.perm.iter().cloned()) {
355 target_row[target_col] = source_element.clone();
356 }
357 }
358 }
359
360 pub fn permute_vector_into_buffer(
370 &self,
371 source_vector: &Vector<T>,
372 buffer: &mut Vector<T>
373 ) {
374 assert!(source_vector.size() == buffer.size(),
375 "Source and target vector must have equal dimensions.");
376 validate_permutation_vector_dimensions(self, buffer);
377 for (source_element, target_index) in source_vector.data()
378 .iter()
379 .zip(self.perm.iter().cloned()) {
380 buffer[target_index] = source_element.clone();
381 }
382 }
383
384 pub fn compose_into_buffer(
392 &self,
393 source_perm: &PermutationMatrix<T>,
394 buffer: &mut PermutationMatrix<T>
395 ) {
396 assert!(source_perm.size() == buffer.size(),
397 "Source and target permutation matrix must have equal dimensions.");
398 let left = self;
399 let right = source_perm;
400 for i in 0 .. self.perm.len() {
401 buffer.perm[i] = left.perm[right.perm[i]];
402 }
403 }
404}
405
406impl<T> From<PermutationMatrix<T>> for Vec<usize> {
407 fn from(p: PermutationMatrix<T>) -> Vec<usize> {
408 p.perm
409 }
410}
411
412impl<'a, T> Into<&'a [usize]> for &'a PermutationMatrix<T> {
413 fn into(self) -> &'a [usize] {
414 &self.perm
415 }
416}
417
418fn validate_permutation_vector_dimensions<T>(p: &PermutationMatrix<T>, v: &Vector<T>) {
419 assert!(p.size() == v.size(),
420 "Permutation matrix and Vector dimensions are not compatible.");
421}
422
423
424fn validate_permutation_left_mul_dimensions<T, M>(p: &PermutationMatrix<T>, rhs: &M)
425 where M: BaseMatrix<T> {
426 assert!(p.size() == rhs.rows(),
427 "Permutation matrix and right-hand side matrix dimensions
428 are not compatible.");
429}
430
431fn validate_permutation_right_mul_dimensions<T, M>(lhs: &M, p: &PermutationMatrix<T>)
432 where M: BaseMatrix<T> {
433 assert!(lhs.cols() == p.size(),
434 "Left-hand side matrix and permutation matrix dimensions
435 are not compatible.");
436}
437
438fn validate_permutation(perm: &[usize]) -> Result<(), Error> {
439 let n = perm.len();
444
445 let mut visited = vec![false; n];
451 for p in perm.iter().cloned() {
452 if p < n {
453 visited[p] = true;
454 }
455 else {
456 return Err(Error::new(ErrorKind::InvalidPermutation,
457 "Supplied permutation array contains elements out of bounds."));
458 }
459 }
460 let all_unique = visited.iter().all(|x| x.clone());
461 if all_unique {
462 Ok(())
463 } else {
464 Err(Error::new(ErrorKind::InvalidPermutation,
465 "Supplied permutation array contains duplicate elements."))
466 }
467}
468
469fn permute_by_swap<S>(perm: &mut [usize], mut swap: S) where S: FnMut(usize, usize) -> () {
480 for i in 0 .. perm.len() {
495 let mut target = perm[i];
496 while i != target {
497 let new_target = perm[target];
503 swap(i, target);
504 perm[target] = target;
505 target = new_target;
506 }
507 perm[i] = i;
508 }
509}
510
511#[cfg(test)]
512mod tests {
513 use matrix::Matrix;
514 use vector::Vector;
515 use super::{PermutationMatrix, Parity};
516 use super::{permute_by_swap, validate_permutation};
517
518 use itertools::Itertools;
519
520 #[test]
521 fn swap_rows() {
522 let mut p = PermutationMatrix::<u64>::identity(4);
523 p.swap_rows(0, 3);
524 p.swap_rows(1, 3);
525
526 let expected_permutation = PermutationMatrix::from_array(vec![3, 0, 2, 1]).unwrap();
527 assert_eq!(p, expected_permutation);
528 }
529
530 #[test]
531 fn as_matrix() {
532 let p = PermutationMatrix::from_array(vec![2, 1, 0, 3]).unwrap();
533 let expected_matrix: Matrix<u32> = matrix![0, 0, 1, 0;
534 0, 1, 0, 0;
535 1, 0, 0, 0;
536 0, 0, 0, 1];
537
538 assert_matrix_eq!(expected_matrix, p.as_matrix());
539 }
540
541 #[test]
542 fn from_array() {
543 let array = vec![1, 0, 3, 2];
544 let p = PermutationMatrix::<u32>::from_array(array.clone()).unwrap();
545 let p_as_array: Vec<usize> = p.into();
546 assert_eq!(p_as_array, array);
547 }
548
549 #[test]
550 fn from_array_unchecked() {
551 let array = vec![1, 0, 3, 2];
552 let p = unsafe { PermutationMatrix::<u32>::from_array_unchecked(array.clone()) };
553 let p_as_array: Vec<usize> = p.into();
554 assert_eq!(p_as_array, array);
555 }
556
557 #[test]
558 fn from_array_invalid() {
559 assert!(PermutationMatrix::<u32>::from_array(vec![0, 1, 3]).is_err());
560 assert!(PermutationMatrix::<u32>::from_array(vec![0, 0]).is_err());
561 assert!(PermutationMatrix::<u32>::from_array(vec![3, 0, 1]).is_err());
562 }
563
564 #[test]
565 fn vec_from_permutation() {
566 let source_vec = vec![0, 2, 1];
567 let p = PermutationMatrix::<u32>::from_array(source_vec.clone()).unwrap();
568 let vec = Vec::from(p);
569 assert_eq!(&source_vec, &vec);
570 }
571
572 #[test]
573 fn into_slice_ref() {
574 let source_vec = vec![0, 2, 1];
575 let ref p = PermutationMatrix::<u32>::from_array(source_vec.clone()).unwrap();
576 let p_as_slice_ref: &[usize] = p.into();
577 assert_eq!(source_vec.as_slice(), p_as_slice_ref);
578 }
579
580 #[test]
581 fn map_row() {
582 let p = PermutationMatrix::<u32>::from_array(vec![0, 2, 1]).unwrap();
583 assert_eq!(p.map_row(0), 0);
584 assert_eq!(p.map_row(1), 2);
585 assert_eq!(p.map_row(2), 1);
586 }
587
588 #[test]
589 fn inverse() {
590 let p = PermutationMatrix::<u32>::from_array(vec![1, 2, 0]).unwrap();
591 let expected_inverse = PermutationMatrix::<u32>::from_array(vec![2, 0, 1]).unwrap();
592 assert_eq!(p.inverse(), expected_inverse);
593 }
594
595 #[test]
596 fn parity() {
597 {
598 let p = PermutationMatrix::<u32>::from_array(vec![1, 0, 3, 2]).unwrap();
599 assert_eq!(p.parity(), Parity::Even);
600 }
601
602 {
603 let p = PermutationMatrix::<u32>::from_array(vec![4, 2, 3, 1, 0, 5]).unwrap();
604 assert_eq!(p.parity(), Parity::Odd);
605 }
606 }
607
608 #[test]
609 fn det() {
610 {
611 let p = PermutationMatrix::<i32>::from_array(vec![1, 0, 3, 2]).unwrap();
612 assert_eq!(p.det(), 1);
613 }
614
615 {
616 let p = PermutationMatrix::<i32>::from_array(vec![4, 2, 3, 1, 0, 5]).unwrap();
617 assert_eq!(p.det(), -1);
618 }
619 }
620
621 #[test]
622 fn permute_by_swap_on_empty_array() {
623 let mut x = Vec::<char>::new();
624 let mut permutation_array = Vec::new();
625 permute_by_swap(&mut permutation_array, |i, j| x.swap(i, j));
626 }
627
628 #[test]
629 fn permute_by_swap_on_arbitrary_array() {
630 let mut x = vec!['a', 'b', 'c', 'd'];
631 let mut permutation_array = vec![0, 2, 3, 1];
632
633 permute_by_swap(&mut permutation_array, |i, j| x.swap(i, j));
634 assert_eq!(x, vec!['a', 'd', 'b', 'c']);
635 }
636
637 #[test]
638 fn permute_by_swap_identity_on_arbitrary_array() {
639 let mut x = vec!['a', 'b', 'c', 'd'];
640 let mut permutation_array = vec![0, 1, 2, 3];
641 permute_by_swap(&mut permutation_array, |i, j| x.swap(i, j));
642 assert_eq!(x, vec!['a', 'b', 'c', 'd']);
643 }
644
645 #[test]
646 fn compose_into_buffer() {
647 let p = PermutationMatrix::<u32>::from_array(vec![2, 1, 0]).unwrap();
648 let q = PermutationMatrix::<u32>::from_array(vec![1, 0, 2]).unwrap();
649 let pq_expected = PermutationMatrix::<u32>::from_array(vec![1, 2, 0]).unwrap();
650 let qp_expected = PermutationMatrix::<u32>::from_array(vec![2, 0, 1]).unwrap();
651
652 {
653 let mut pq = PermutationMatrix::identity(3);
654 p.compose_into_buffer(&q, &mut pq);
655 assert_eq!(pq, pq_expected);
656 }
657
658 {
659 let mut qp = PermutationMatrix::identity(3);
660 q.compose_into_buffer(&p, &mut qp);
661 assert_eq!(qp, qp_expected);
662 }
663 }
664
665 #[test]
666 fn compose_regression() {
667 let p = PermutationMatrix::<u32>::from_array(vec![1, 2, 0]).unwrap();
670 let q = PermutationMatrix::<u32>::from_array(vec![2, 0, 1]).unwrap();
671 let pq_expected = PermutationMatrix::<u32>::from_array(vec![0, 1, 2]).unwrap();
672
673 let mut pq = PermutationMatrix::identity(3);
674 p.compose_into_buffer(&q, &mut pq);
675 assert_eq!(pq, pq_expected);
676 }
677
678 #[test]
679 fn permute_rows_into_buffer() {
680 let x = matrix![ 0;
681 1;
682 2;
683 3];
684 let p = PermutationMatrix::from_array(vec![2, 1, 3, 0]).unwrap();
685 let mut output = Matrix::zeros(4, 1);
686 p.permute_rows_into_buffer(&x, &mut output);
687 assert_matrix_eq!(output, matrix![ 3; 1; 0; 2]);
688 }
689
690 #[test]
691 fn permute_rows_in_place() {
692 let mut x = matrix![ 0;
693 1;
694 2;
695 3];
696 let p = PermutationMatrix::from_array(vec![2, 1, 3, 0]).unwrap();
697 p.permute_rows_in_place(&mut x);
698 assert_matrix_eq!(x, matrix![ 3; 1; 0; 2]);
699 }
700
701 #[test]
702 fn permute_cols_into_buffer() {
703 let x = matrix![ 0, 1, 2, 3];
704 let p = PermutationMatrix::from_array(vec![2, 1, 3, 0]).unwrap();
705 let mut output = Matrix::zeros(1, 4);
706 p.permute_cols_into_buffer(&x, &mut output);
707 assert_matrix_eq!(output, matrix![ 3, 1, 0, 2]);
708 }
709
710 #[test]
711 fn permute_cols_in_place() {
712 let mut x = matrix![ 0, 1, 2, 3];
713 let p = PermutationMatrix::from_array(vec![2, 1, 3, 0]).unwrap();
714 p.permute_cols_in_place(&mut x);
715 assert_matrix_eq!(x, matrix![ 3, 1, 0, 2]);
716 }
717
718 #[test]
719 fn permute_vector_into_buffer() {
720 let x = vector![ 0, 1, 2, 3];
721 let p = PermutationMatrix::from_array(vec![2, 1, 3, 0]).unwrap();
722 let mut output = Vector::zeros(4);
723 p.permute_vector_into_buffer(&x, &mut output);
724 assert_vector_eq!(output, vector![ 3, 1, 0, 2]);
725 }
726
727 #[test]
728 fn permute_vector_in_place() {
729 let mut x = vector![ 0, 1, 2, 3];
730 let p = PermutationMatrix::from_array(vec![2, 1, 3, 0]).unwrap();
731 p.permute_vector_in_place(&mut x);
732 assert_vector_eq!(x, vector![ 3, 1, 0, 2]);
733 }
734
735 use quickcheck::{Arbitrary, Gen};
736
737 #[derive(Debug, Clone, PartialEq, Eq)]
740 struct ValidPermutationArray(pub Vec<usize>);
741
742 impl Arbitrary for ValidPermutationArray {
743 fn arbitrary<G: Gen>(g: &mut G) -> Self {
744 let upper_bound = g.size();
745 let mut array = (0 .. upper_bound).collect::<Vec<usize>>();
746 g.shuffle(&mut array);
747 ValidPermutationArray(array)
748 }
749 }
750
751 #[derive(Debug, Clone, PartialEq, Eq)]
754 struct InvalidPermutationArray(pub Vec<usize>);
755
756 impl Arbitrary for InvalidPermutationArray {
757 fn arbitrary<G: Gen>(g: &mut G) -> Self {
758 let mut permutation_array = ValidPermutationArray::arbitrary(g).0;
761 let n = permutation_array.len();
762
763 let should_have_duplicates = g.gen::<bool>();
769 let should_have_out_of_bounds = !should_have_duplicates || g.gen::<bool>();
770 assert!(should_have_duplicates || should_have_out_of_bounds);
771
772 if should_have_out_of_bounds {
773 let num_out_of_bounds_rounds = g.gen_range::<usize>(1, n);
774 for _ in 0 .. num_out_of_bounds_rounds {
775 let interior_index = g.gen_range::<usize>(0, n);
776 let exterior_index = n + g.gen::<usize>();
777 permutation_array[interior_index] = exterior_index;
778 }
779 }
780
781 if should_have_duplicates {
782 let num_duplicates = g.gen_range::<usize>(1, n);
783 for _ in 0 .. num_duplicates {
784 let interior_index = g.gen_range::<usize>(0, n);
785 let duplicate_value = permutation_array[interior_index];
786 permutation_array.push(duplicate_value);
787 }
788 }
789
790 g.shuffle(&mut permutation_array);
794 InvalidPermutationArray(permutation_array)
795 }
796 }
797
798 impl<T: Send + Clone + 'static> Arbitrary for PermutationMatrix<T> {
799 fn arbitrary<G: Gen>(g: &mut G) -> Self {
800 let ValidPermutationArray(array) = ValidPermutationArray::arbitrary(g);
801 PermutationMatrix::from_array(array)
802 .expect("The generated permutation array should always be valid.")
803 }
804 }
805
806 quickcheck! {
807 fn property_validate_permutation_is_ok_for_valid_input(array: ValidPermutationArray) -> bool {
808 validate_permutation(&array.0).is_ok()
809 }
810 }
811
812 quickcheck! {
813 fn property_validate_permutation_is_err_for_invalid_input(array: InvalidPermutationArray) -> bool {
814 validate_permutation(&array.0).is_err()
815 }
816 }
817
818 quickcheck! {
819 fn property_identity_has_identity_array(size: usize) -> bool {
820 let p = PermutationMatrix::<u64>::identity(size);
821 let p_as_array: Vec<usize> = p.into();
822 let expected = (0 .. size).collect::<Vec<usize>>();
823 p_as_array == expected
824 }
825 }
826
827 quickcheck! {
828 fn property_dim_is_equal_to_array_dimensions(array: ValidPermutationArray) -> bool {
829 let ValidPermutationArray(array) = array;
830 let n = array.len();
831 let p = PermutationMatrix::<u32>::from_array(array).unwrap();
832 p.size() == n
833 }
834 }
835
836 quickcheck! {
837 fn property_inverse_of_inverse_is_original(p: PermutationMatrix<u32>) -> bool {
838 p == p.inverse().inverse()
839 }
840 }
841
842 quickcheck! {
843 fn property_inverse_composes_to_identity(p: PermutationMatrix<u32>) -> bool {
844 let n = p.size();
846 let pinv = p.inverse();
847 let mut p_pinv_composition = PermutationMatrix::identity(n);
848 let mut pinv_p_composition = PermutationMatrix::identity(n);
849 p.compose_into_buffer(&pinv, &mut p_pinv_composition);
850 pinv.compose_into_buffer(&p, &mut pinv_p_composition);
851 assert_eq!(p_pinv_composition, PermutationMatrix::identity(n));
852 assert_eq!(pinv_p_composition, PermutationMatrix::identity(n));
853 true
854 }
855 }
856
857 quickcheck! {
858 fn property_identity_parity_is_even(n: usize) -> bool {
859 let p = PermutationMatrix::<u32>::identity(n);
860 p.parity() == Parity::Even
861 }
862 }
863
864 quickcheck! {
865 fn property_parity_agrees_with_parity_of_inversions(p: PermutationMatrix<u32>) -> bool {
866 let array: &[usize] = (&p).into();
867 let num_inversions = array.iter().cloned().enumerate()
868 .cartesian_product(array.iter().cloned().enumerate())
869 .filter(|&((i, permuted_i), (j, permuted_j))|
870 i < j && permuted_i > permuted_j
872 )
873 .count();
874 let parity = if num_inversions % 2 == 0 {
877 Parity::Even
878 } else {
879 Parity::Odd
880 };
881
882 parity == p.clone().parity()
883 }
884 }
885}