Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
sparse_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_SPARSE_PERMUTATION_H_
15#define OR_TOOLS_ALGORITHMS_SPARSE_PERMUTATION_H_
16
17#include <string>
18#include <vector>
19
20#include "absl/types/span.h"
22
23namespace operations_research {
24
25// A compact representation for permutations of {0..N-1} that displaces few
26// elements: it needs only O(K) memory for a permutation that displaces
27// K elements.
29 public:
30 explicit SparsePermutation(int size) : size_(size) {} // Identity.
31
32 // TODO(user): complete the reader API.
33 int Size() const { return size_; }
34 int NumCycles() const { return cycle_ends_.size(); }
35
36 // Returns the "support" of this permutation; that is, the set of elements
37 // displaced by it.
38 const std::vector<int>& Support() const { return cycles_; }
39
40 // The permutation has NumCycles() cycles numbered 0 .. NumCycles()-1.
41 // To iterate over cycle #i of the permutation, do this:
42 // for (const int e : permutation.Cycle(i)) { ...
43 struct Iterator;
44 Iterator Cycle(int i) const;
45
46 // This is useful for iterating over the pair {element, image}
47 // of a permutation:
48 //
49 // for (int c = 0; c < perm.NumCycles(); ++c) {
50 // int element = LastElementInCycle(c);
51 // for (int image : perm.Cycle(c)) {
52 // // The pair is (element, image).
53 // ...
54 // element = image;
55 // }
56 // }
57 //
58 // TODO(user): Provide a full iterator for this? Note that we have more
59 // information with the loop above. Not sure it is needed though.
60 int LastElementInCycle(int i) const;
61
62 // To add a cycle to the permutation, repeatedly call AddToCurrentCycle()
63 // with the cycle's orbit, then call CloseCurrentCycle();
64 // This shouldn't be called on trivial cycles (of length 1).
65 void AddToCurrentCycle(int x);
66 void CloseCurrentCycle();
67
68 // Removes the cycles with given indices from the permutation. This
69 // works in O(K) for a permutation displacing K elements.
70 void RemoveCycles(absl::Span<const int> cycle_indices);
71
72 // Output all non-identity cycles of the permutation, sorted
73 // lexicographically (each cycle is described starting by its smallest
74 // element; and all cycles are sorted lexicographically against each other).
75 // This isn't efficient; use for debugging only.
76 // Example: "(1 4 3) (5 9) (6 8 7)".
77 std::string DebugString() const;
78
79 private:
80 const int size_;
81 std::vector<int> cycles_;
82 std::vector<int> cycle_ends_;
83};
84
86 DCHECK_GE(x, 0);
87 DCHECK_LT(x, size_);
88 cycles_.push_back(x);
89}
90
92 if (cycle_ends_.empty()) {
93 DCHECK_GE(cycles_.size(), 2);
94 } else {
95 DCHECK_GE(cycles_.size(), cycle_ends_.back() + 2);
96 }
97 cycle_ends_.push_back(cycles_.size());
98}
99
101 // These typedefs allow this iterator to be used within testing::ElementsAre.
102 typedef int value_type;
103 typedef std::vector<int>::const_iterator const_iterator;
104
105 Iterator() = default;
106 Iterator(const std::vector<int>::const_iterator& b,
107 const std::vector<int>::const_iterator& e)
108 : begin_(b), end_(e) {}
109
110 std::vector<int>::const_iterator begin() const { return begin_; }
111 std::vector<int>::const_iterator end() const { return end_; }
112 const std::vector<int>::const_iterator begin_;
113 const std::vector<int>::const_iterator end_;
114
115 int size() const { return end_ - begin_; }
116};
117
119 DCHECK_GE(i, 0);
120 DCHECK_LT(i, NumCycles());
121 return Iterator(cycles_.begin() + (i == 0 ? 0 : cycle_ends_[i - 1]),
122 cycles_.begin() + cycle_ends_[i]);
123}
124
126 DCHECK_GE(i, 0);
127 DCHECK_LT(i, cycle_ends_.size());
128 DCHECK_GT(cycle_ends_[i], i == 0 ? 0 : cycle_ends_[i - 1]);
129 return cycles_[cycle_ends_[i] - 1];
130}
131
132} // namespace operations_research
133
134#endif // OR_TOOLS_ALGORITHMS_SPARSE_PERMUTATION_H_
IntegerValue size
void RemoveCycles(absl::Span< const int > cycle_indices)
const std::vector< int > & Support() const
int64_t b
Definition table.cc:45
In SWIG mode, we don't want anything besides these top-level includes.
const Variable x
Definition qp_tests.cc:127
std::vector< int >::const_iterator end() const
const std::vector< int >::const_iterator end_
const std::vector< int >::const_iterator begin_
std::vector< int >::const_iterator begin() const
std::vector< int >::const_iterator const_iterator
int value_type
These typedefs allow this iterator to be used within testing::ElementsAre.
Iterator(const std::vector< int >::const_iterator &b, const std::vector< int >::const_iterator &e)