Linear Algebra  arduino
Accessible implementations of linear algebra algorithms
PermutationMatrix.cpp
Go to the documentation of this file.
1 #ifndef ARDUINO
3 #else
5 #endif
6 
7 #ifndef NO_RANDOM_SUPPORT
9  size_t length, std::default_random_engine::result_type seed) {
10  // Create a random engine for shuffling
11  std::default_random_engine gen(seed);
12  // Start with the identity permutation (0, 1, 2, 3, ..., length-1)
13  Permutation permutation = identity_permutation(length);
14  // Then shuffle it randomly
15  std::random_shuffle(
16  permutation.begin(), permutation.end(), [&gen](size_t n) {
17  std::uniform_int_distribution<size_t> dist(0, n ? n - 1 : 0);
18  return dist(gen);
19  });
20  return permutation;
21 }
22 #endif
23 
26  Permutation permutation(length);
27  std::iota(permutation.begin(), permutation.end(), size_t(0));
28  return permutation;
29 }
30 
32  resize(permutation.size());
33  // Convert the permutation to a sequence of swaps.
34  //
35  // Sort the permuted sequence using selection sort, starting from the
36  // right, and record all swaps necessary to sort. This sequence of swaps
37  // will be used as the internal representation of the permutation
38  // matrix.
39  //
40  // TODO: Selection sort is O(n²), is there a better way?
41  for (size_t i = size(); i-- > 0;) {
42  // Boundaries of the sorted and unsorted sublists:
43  // | unsorted | sorted |
44  auto unsorted_begin = permutation.begin();
45  auto unsorted_end = permutation.begin() + i + 1; // one-past-end
46  // Find the element that comes at the i-th place in the sorted list:
47  auto next_element = std::find(unsorted_begin, unsorted_end, i);
48  // Ensure the number exists in the list. If it doesn't, the list
49  // didn't contain a valid permutation in the first place.
50  assert(next_element != unsorted_end && "Invalid permutation");
51  // Find the index of that element:
52  auto swap_idx = next_element - permutation.begin();
53  // Swap it with the current element, so the *next_element is in the
54  // correct place for a sorted list:
55  std::swap(permutation[i], *next_element);
56  // Record the swap:
57  (*this)(i) = swap_idx;
58  }
59 }
60 
61 #ifndef NO_IOSTREAM_SUPPORT
62 
63 #include <iomanip>
64 #include <iostream>
65 
66 // LCOV_EXCL_START
67 
68 void PermutationMatrix::print(std::ostream &os, uint8_t precision,
69  uint8_t width) const {
70  int backup_precision = os.precision();
71  precision = precision > 0 ? precision : backup_precision;
72  width = width > 0 ? width : precision + 9;
73  os.precision(precision);
74  Permutation permutation = to_permutation();
75  for (size_t i = 0; i < size(); ++i) {
76  os << std::setw(width) << permutation[i];
77  }
78  os.precision(backup_precision);
79 }
80 
81 std::ostream &operator<<(std::ostream &os, const PermutationMatrix &P) {
82  P.print(os);
83  return os;
84 }
85 
86 // LCOV_EXCL_STOP
87 
88 #endif
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.