OR-Tools  8.0
lp_data/permutation.h
Go to the documentation of this file.
1 // Copyright 2010-2018 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #ifndef OR_TOOLS_LP_DATA_PERMUTATION_H_
15 #define OR_TOOLS_LP_DATA_PERMUTATION_H_
16 
17 #include "absl/random/random.h"
20 
21 namespace operations_research {
22 namespace glop {
23 
24 // Permutation<IndexType> is a template class for storing and using
25 // row- and column- permutations, when instantiated with RowIndex and ColIndex
26 // respectively.
27 //
28 // By a row permutation we mean a permutation that maps the row 'i' of a matrix
29 // (or column vector) to the row 'permutation[i]' and in a similar fashion by a
30 // column permutation we mean a permutation that maps the column 'j' of a matrix
31 // (or row vector) to the column 'permutation[j]'.
32 //
33 // A permutation can be represented as a matrix P, but it gets a bit tricky
34 // here: P.x permutes the rows of x according to the permutation P but x^T.P
35 // permutes the columns of x^T (a row vector) using the INVERSE permutation.
36 // That is, to permute the columns of x^T using P, one has to compute
37 // x^T.P^{-1} but P^{-1} = P^T so the notation is consistent: If P.x permutes x,
38 // then (P.x)^T = x^T.P^T permutes x^T with the same permutation.
39 //
40 // So to be clear, if P and Q are permutation matrices, the matrix P.A.Q^{-1}
41 // is the image of A through the row permutation P and column permutation Q.
42 template <typename IndexType>
43 class Permutation {
44  public:
45  Permutation() : perm_() {}
46 
47  explicit Permutation(IndexType size) : perm_(size.value(), IndexType(0)) {}
48 
49  IndexType size() const { return IndexType(perm_.size()); }
50  bool empty() const { return perm_.empty(); }
51 
52  void clear() { perm_.clear(); }
53 
54  void resize(IndexType size, IndexType value) {
55  perm_.resize(size.value(), value);
56  }
57 
58  void assign(IndexType size, IndexType value) {
59  perm_.assign(size.value(), value);
60  }
61 
62  IndexType& operator[](IndexType i) { return perm_[i]; }
63 
64  const IndexType operator[](IndexType i) const { return perm_[i]; }
65 
66  // Populates the calling object with the inverse permutation of the parameter
67  // inverse.
68  void PopulateFromInverse(const Permutation& inverse);
69 
70  // Populates the calling object with the identity permutation.
72 
73  // Populates the calling object with a random permutation.
75 
76  // Returns true if the calling object contains a permutation, false otherwise.
77  bool Check() const;
78 
79  // Returns the signature of a permutation in O(n), where n is the permutation
80  // size.
81  // The signature of a permutation is the product of the signature of
82  // the cycles defining the permutation.
83  // The signature of an odd cycle is 1, while the signature of an even cycle
84  // is -1. (Remembering hint: the signature of a swap (a 2-cycle) is -1.)
85  int ComputeSignature() const;
86 
87  private:
89 
90  DISALLOW_COPY_AND_ASSIGN(Permutation);
91 };
92 
95 
96 // Applies the permutation perm to the vector b. Overwrites result to store
97 // the result.
98 // TODO(user): Try to restrict this method to using the same integer type in
99 // the permutation and for the vector indices, i.e.
100 // IndexType == ITIVectorType::IndexType. Some client code will need to be
101 // refactored.
102 template <typename IndexType, typename ITIVectorType>
104  const ITIVectorType& b, ITIVectorType* result);
105 
106 // Applies the inverse of perm to the vector b. Overwrites result to store
107 // the result.
108 template <typename IndexType, typename ITIVectorType>
110  const ITIVectorType& b, ITIVectorType* result);
111 
112 // Specialization of ApplyPermutation(): apply a column permutation to a
113 // row-indexed vector v.
114 template <typename RowIndexedVector>
116  const Permutation<ColIndex>& col_perm, RowIndexedVector* v) {
117  RowIndexedVector temp_v = *v;
118  ApplyPermutation(col_perm, temp_v, v);
119 }
120 
121 // --------------------------------------------------------
122 // Implementation
123 // --------------------------------------------------------
124 
125 template <typename IndexType>
127  const size_t size = inverse.perm_.size();
128  perm_.resize(size);
129  for (IndexType i(0); i < size; ++i) {
130  perm_[inverse[i]] = i;
131  }
132 }
133 
134 template <typename IndexType>
136  const size_t size = perm_.size();
137  perm_.resize(size, IndexType(0));
138  for (IndexType i(0); i < size; ++i) {
139  perm_[i] = i;
140  }
141 }
142 
143 template <typename IndexType>
145  PopulateFromIdentity();
146  std::shuffle(perm_.begin(), perm_.end());
147 }
148 
149 template <typename IndexType>
151  const size_t size = perm_.size();
152  gtl::ITIVector<IndexType, bool> visited(size, false);
153  for (IndexType i(0); i < size; ++i) {
154  if (perm_[i] < 0 || perm_[i] >= size) {
155  return false;
156  }
157  visited[perm_[i]] = true;
158  }
159  for (IndexType i(0); i < size; ++i) {
160  if (!visited[i]) {
161  return false;
162  }
163  }
164  return true;
165 }
166 
167 template <typename IndexType>
169  const size_t size = perm_.size();
170  gtl::ITIVector<IndexType, bool> visited(size);
171  DCHECK(Check());
172  int signature = 1;
173  for (IndexType i(0); i < size; ++i) {
174  if (!visited[i]) {
175  int cycle_size = 0;
176  IndexType j = i;
177  do {
178  j = perm_[j];
179  visited[j] = true;
180  ++cycle_size;
181  } while (j != i);
182  if ((cycle_size & 1) == 0) {
183  signature = -signature;
184  }
185  }
186  }
187  return signature;
188 }
189 
190 template <typename IndexType, typename ITIVectorType>
192  const ITIVectorType& b, ITIVectorType* result) {
193  RETURN_IF_NULL(result);
194  const IndexType size(perm.size());
195  if (size == 0) return;
196  DCHECK_EQ(size.value(), b.size().value());
197  result->resize(b.size(), /*whatever junk value*/ b.back());
198  for (IndexType i(0); i < size; ++i) {
199  const typename ITIVectorType::IndexType ith_index(i.value());
200  const typename ITIVectorType::IndexType permuted(perm[i].value());
201  (*result)[permuted] = b[ith_index];
202  }
203 }
204 
205 template <typename IndexType, typename ITIVectorType>
207  const ITIVectorType& b, ITIVectorType* result) {
208  RETURN_IF_NULL(result);
209  const IndexType size(perm.size().value());
210  if (size == 0) return;
211  DCHECK_EQ(size.value(), b.size().value());
212  result->resize(b.size(), /*whatever junk value*/ b.back());
213  for (IndexType i(0); i < size; ++i) {
214  const typename ITIVectorType::IndexType ith_index(i.value());
215  const typename ITIVectorType::IndexType permuted(perm[i].value());
216  (*result)[ith_index] = b[permuted];
217  }
218 }
219 
220 } // namespace glop
221 } // namespace operations_research
222 
223 #endif // OR_TOOLS_LP_DATA_PERMUTATION_H_
operations_research::glop::ApplyColumnPermutationToRowIndexedVector
void ApplyColumnPermutationToRowIndexedVector(const Permutation< ColIndex > &col_perm, RowIndexedVector *v)
Definition: lp_data/permutation.h:115
operations_research::glop::Permutation::empty
bool empty() const
Definition: lp_data/permutation.h:50
operations_research::glop::ApplyPermutation
void ApplyPermutation(const Permutation< IndexType > &perm, const ITIVectorType &b, ITIVectorType *result)
Definition: lp_data/permutation.h:191
operations_research::glop::Permutation::PopulateRandomly
void PopulateRandomly()
Definition: lp_data/permutation.h:144
gtl::ITIVector::clear
void clear()
Definition: int_type_indexed_vector.h:169
operations_research::glop::Permutation::assign
void assign(IndexType size, IndexType value)
Definition: lp_data/permutation.h:58
value
int64 value
Definition: demon_profiler.cc:43
operations_research::glop::Permutation::Permutation
Permutation()
Definition: lp_data/permutation.h:45
operations_research::glop::Permutation::Check
bool Check() const
Definition: lp_data/permutation.h:150
gtl::ITIVector::resize
void resize(size_type new_size)
Definition: int_type_indexed_vector.h:149
operations_research::glop::Permutation::Permutation
Permutation(IndexType size)
Definition: lp_data/permutation.h:47
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::glop::Permutation::operator[]
IndexType & operator[](IndexType i)
Definition: lp_data/permutation.h:62
gtl::ITIVector::size
size_type size() const
Definition: int_type_indexed_vector.h:146
gtl::ITIVector::empty
bool empty() const
Definition: int_type_indexed_vector.h:155
RETURN_IF_NULL
#define RETURN_IF_NULL(x)
Definition: return_macros.h:20
gtl::ITIVector::assign
void assign(size_type n, const value_type &val)
Definition: int_type_indexed_vector.h:130
operations_research::glop::RowPermutation
Permutation< RowIndex > RowPermutation
Definition: lp_data/permutation.h:93
operations_research::glop::Permutation::size
IndexType size() const
Definition: lp_data/permutation.h:49
operations_research::glop::ColumnPermutation
Permutation< ColIndex > ColumnPermutation
Definition: lp_data/permutation.h:94
operations_research::glop::Permutation::resize
void resize(IndexType size, IndexType value)
Definition: lp_data/permutation.h:54
return_macros.h
operations_research::glop::Permutation
Definition: lp_data/permutation.h:43
operations_research::glop::ApplyInversePermutation
void ApplyInversePermutation(const Permutation< IndexType > &perm, const ITIVectorType &b, ITIVectorType *result)
Definition: lp_data/permutation.h:206
b
int64 b
Definition: constraint_solver/table.cc:43
operations_research::glop::Permutation::PopulateFromInverse
void PopulateFromInverse(const Permutation &inverse)
Definition: lp_data/permutation.h:126
gtl::ITIVector< IndexType, IndexType >
operations_research::glop::Permutation::ComputeSignature
int ComputeSignature() const
Definition: lp_data/permutation.h:168
operations_research::glop::Permutation::PopulateFromIdentity
void PopulateFromIdentity()
Definition: lp_data/permutation.h:135
lp_types.h
operations_research::glop::Permutation::operator[]
const IndexType operator[](IndexType i) const
Definition: lp_data/permutation.h:64
operations_research::glop::Permutation::clear
void clear()
Definition: lp_data/permutation.h:52