OR-Tools  9.6
dynamic_permutation.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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_ALGORITHMS_DYNAMIC_PERMUTATION_H_
15 #define OR_TOOLS_ALGORITHMS_DYNAMIC_PERMUTATION_H_
16 
17 #include <memory>
18 #include <set> // TODO(user): remove when no longer used.
19 #include <string>
20 #include <vector>
21 
22 #include "ortools/base/logging.h"
23 
24 namespace operations_research {
25 
26 class SparsePermutation;
27 
28 // Maintains a 'partial' permutation of [0..n-1] onto itself, with a dynamic
29 // API allowing it to be built incrementally, and allowing some backtracking.
30 // This is tuned for a specific usage by ./find_graph_symmetries.cc.
31 //
32 // RAM usage: as of 2014-04, this class needs less than:
33 // 32.125 * (n + 2 * support_size) bytes.
35  public:
36  // Upon construction, every element i in [0..n-1] maps to itself.
37  explicit DynamicPermutation(int n);
38 
39  int Size() const { return image_.size(); } // Return the original "n".
40 
41  // Declares a set of mappings for this permutation: src[i] will map to dst[i].
42  // Requirements that are DCHECKed:
43  // - "src" and "dst" must have the same size.
44  // - For all i, src[i] must not already be mapped to something.
45  // - For all i, dst[i] must not already be the image of something.
46  //
47  // Complexity: amortized O(src.size()).
48  void AddMappings(const std::vector<int>& src, const std::vector<int>& dst);
49 
50  // Undoes the last AddMappings() operation, and fills the "undone_mapping_src"
51  // vector with the src of that last operation. This works like an undo stack.
52  // For example, applying the sequence (Add, Add, Add, Undo, Add, Undo, Undo)
53  // has exactly the same effect as applying the first Add() alone.
54  // If you call this too may times (i.e. there is nothing left to undo), it is
55  // simply a no-op.
56  //
57  // Complexity: same as the AddMappings() operation being undone.
58  void UndoLastMappings(std::vector<int>* undone_mapping_src);
59 
60  // Makes the permutation back to the identity (i.e. like right after
61  // construction).
62  // Complexity: O(support size).
63  void Reset();
64 
65  int ImageOf(int i) const; // Complexity: one vector lookup.
66 
67  // Returns the union of all "src" ever given to AddMappings().
68  const std::vector<int>& AllMappingsSrc() const { return mapping_src_stack_; }
69 
70  // While the permutation is partially being built, the orbit of elements will
71  // either form unclosed paths, or closed cycles. In the former case,
72  // RootOf(i) returns the start of the path where i lies. If i is on a cycle,
73  // RootOf(i) will return some element of its cycle (meaning that if i maps to
74  // itself, RootOf(i) = i).
75  //
76  // Complexity: O(log(orbit size)) in average, assuming that the mappings are
77  // added in a random order. O(orbit size) in the worst case.
78  int RootOf(int i) const;
79 
80  // The exhaustive set of the 'loose end' of the incomplete cycles
81  // (e.g., paths) built so far.
82  // TODO(user): use a faster underlying container like SparseBitSet, and
83  // tweak this API accordingly.
84  const std::set<int>& LooseEnds() const { return loose_ends_; }
85 
86  // Creates a SparsePermutation representing the current permutation.
87  // Requirements: the permutation must only have cycles.
88  //
89  // Complexity: O(support size).
90  std::unique_ptr<SparsePermutation> CreateSparsePermutation() const;
91 
92  std::string DebugString() const;
93 
94  private:
95  std::vector<int> image_;
96  // ancestor_[i] isn't exactly RootOf(i): it might itself have an ancestor, and
97  // so on.
98  std::vector<int> ancestor_;
99 
100  // The concatenation of all "src" ever given to AddMappings(), and their
101  // sizes, to implement the undo stack. Note that "mapping_src_stack_" contains
102  // exactly the support of the permutation.
103  std::vector<int> mapping_src_stack_;
104  std::vector<int> mapping_src_size_stack_;
105 
106  // See the homonymous accessor, above.
107  std::set<int> loose_ends_;
108 
109  // Used transiently by CreateSparsePermutation(). Its resting state is:
110  // size=Size(), all elements are false.
111  mutable std::vector<bool> tmp_mask_;
112 };
113 
114 // Forced-inline for the speed.
115 inline int DynamicPermutation::ImageOf(int i) const {
116  DCHECK_GE(i, 0);
117  DCHECK_LT(i, Size());
118  return image_[i];
119 }
120 
121 // Forced-inline for the speed.
122 inline int DynamicPermutation::RootOf(int i) const {
123  DCHECK_GE(i, 0);
124  DCHECK_LT(i, Size());
125  while (true) {
126  const int j = ancestor_[i];
127  if (j == i) return i;
128  i = j;
129  }
130 }
131 
132 } // namespace operations_research
133 
134 #endif // OR_TOOLS_ALGORITHMS_DYNAMIC_PERMUTATION_H_
std::unique_ptr< SparsePermutation > CreateSparsePermutation() const
const std::set< int > & LooseEnds() const
const std::vector< int > & AllMappingsSrc() const
void UndoLastMappings(std::vector< int > *undone_mapping_src)
void AddMappings(const std::vector< int > &src, const std::vector< int > &dst)
Collection of objects used to extend the Constraint Solver library.