Linear Algebra  master
Accessible implementations of linear algebra algorithms
PermutationMatrix.cpp
Go to the documentation of this file.
2 
3 #include <iomanip>
4 #include <iostream>
5 
7  size_t length, std::default_random_engine::result_type seed) {
8  // Create a random engine for shuffling
9  std::default_random_engine gen(seed);
10  // Start with the identity permutation (0, 1, 2, 3, ..., length-1)
11  Permutation permutation = identity_permutation(length);
12  // Then shuffle it randomly
13  std::random_shuffle(
14  permutation.begin(), permutation.end(), [&gen](size_t n) {
15  std::uniform_int_distribution<size_t> dist(0, n ? n - 1 : 0);
16  return dist(gen);
17  });
18  return permutation;
19 }
20 
23  Permutation permutation(length);
24  std::iota(permutation.begin(), permutation.end(), size_t(0));
25  return permutation;
26 }
27 
29  resize(permutation.size());
30  // Convert the permutation to a sequence of swaps.
31  //
32  // Sort the permuted sequence using selection sort, starting from the
33  // right, and record all swaps necessary to sort. This sequence of swaps
34  // will be used as the internal representation of the permutation
35  // matrix.
36  //
37  // TODO: Selection sort is O(n²), is there a better way?
38  for (size_t i = size(); i-- > 0;) {
39  // Boundaries of the sorted and unsorted sublists:
40  // | unsorted | sorted |
41  auto unsorted_begin = permutation.begin();
42  auto unsorted_end = permutation.begin() + i + 1; // one-past-end
43  // Find the element that comes at the i-th place in the sorted list:
44  auto next_element = std::find(unsorted_begin, unsorted_end, i);
45  // Ensure the number exists in the list. If it doesn't, the list
46  // didn't contain a valid permutation in the first place.
47  assert(next_element != unsorted_end && "Invalid permutation");
48  // Find the index of that element:
49  auto swap_idx = next_element - permutation.begin();
50  // Swap it with the current element, so the *next_element is in the
51  // correct place for a sorted list:
52  std::swap(permutation[i], *next_element);
53  // Record the swap:
54  (*this)(i) = swap_idx;
55  }
56 }
57 
58 // LCOV_EXCL_START
59 
60 void PermutationMatrix::print(std::ostream &os, uint8_t precision,
61  uint8_t width) const {
62  int backup_precision = os.precision();
63  precision = precision > 0 ? precision : backup_precision;
64  width = width > 0 ? width : precision + 9;
65  os.precision(precision);
66  Permutation permutation = to_permutation();
67  for (size_t i = 0; i < size(); ++i) {
68  os << std::setw(width) << permutation[i];
69  }
70  os.precision(backup_precision);
71 }
72 
73 std::ostream &operator<<(std::ostream &os, const PermutationMatrix &P) {
74  P.print(os);
75  return os;
76 }
77 
78 // LCOV_EXCL_STOP
std::ostream & operator<<(std::ostream &os, const HouseholderQR &qr)
Print the Q and R matrices of a HouseholderQR object.
Class that represents matrices that permute the rows or columns of other matrices.
size_t size() const
Get the size of the permutation matrix.
Permutation to_permutation() const
Convert a permutation matrix into a mathematical permutation.
void resize(size_t size)
Resize the permutation matrix.
void fill_from_permutation(Permutation permutation)
Create a permutation matrix from the given permutation.
storage_t Permutation
Type that represents a permutation (in the mathematical sense, a permutation of the integers 0 throug...
static Permutation identity_permutation(size_t length)
Return the identity permutation (0, 1, 2, 3, ..., length-1).
void print(std::ostream &os, uint8_t precision=0, uint8_t width=0) const
Print a permutation matrix.
static Permutation random_permutation(size_t length, std::default_random_engine::result_type seed=std::default_random_engine::default_seed)
Return a random permutation of the integers 0 through length-1.