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