22 #include "absl/strings/str_format.h"
23 #include "absl/strings/str_join.h"
29 uint64_t FprintOfInt32(
int i) {
36 DCHECK_GE(num_elements, 0);
37 element_.assign(num_elements, -1);
38 index_of_.assign(num_elements, -1);
39 for (
int i = 0; i < num_elements; ++i) {
43 part_of_.assign(num_elements, 0);
45 for (
int i = 0; i < num_elements; ++i) fprint ^= FprintOfInt32(i);
46 part_.push_back(Part(0, num_elements,
52 const std::vector<int>& initial_part_of_element) {
53 if (initial_part_of_element.empty())
return;
54 part_of_ = initial_part_of_element;
55 const int n = part_of_.size();
56 const int num_parts = 1 + *std::max_element(part_of_.begin(), part_of_.end());
57 DCHECK_EQ(0, *std::min_element(part_of_.begin(), part_of_.end()));
58 part_.resize(num_parts);
61 for (
int i = 0; i < n; ++i) part_[part_of_[i]].fprint ^= FprintOfInt32(i);
66 for (
int p = 0; p < num_parts; ++p) {
67 part_[p].end_index = 0;
68 part_[p].parent_part = p;
70 for (
const int p : part_of_) ++part_[p].end_index;
71 int sum_part_sizes = 0;
72 for (
int p = 0; p < num_parts; ++p) {
73 part_[p].start_index = sum_part_sizes;
74 sum_part_sizes += part_[p].end_index;
80 for (Part& part : part_) part.end_index = part.start_index;
81 element_.assign(n, -1);
82 index_of_.assign(n, -1);
83 for (
int element = 0; element < n; ++element) {
84 Part*
const part = &part_[part_of_[element]];
85 element_[part->end_index] = element;
86 index_of_[element] = part->end_index;
93 DCHECK_EQ(0, part_[0].start_index);
95 for (
int p = 1; p <
NumParts(); ++p) {
96 DCHECK_EQ(part_[p - 1].end_index, part_[p].start_index);
103 tmp_counter_of_part_.resize(
NumParts(), 0);
105 tmp_affected_parts_.clear();
106 for (
const int element : distinguished_subset) {
107 DCHECK_GE(element, 0);
109 const int part = part_of_[element];
110 const int num_distinguished_elements_in_part = ++tmp_counter_of_part_[part];
112 if (num_distinguished_elements_in_part == 1) {
114 tmp_affected_parts_.push_back(part);
117 const int old_index = index_of_[element];
118 const int new_index =
119 part_[part].end_index - num_distinguished_elements_in_part;
120 DCHECK_GE(new_index, old_index)
121 <<
"Duplicate element given to Refine(): " << element;
123 index_of_[element] = new_index;
124 index_of_[element_[new_index]] = old_index;
125 std::swap(element_[old_index], element_[new_index]);
131 std::sort(tmp_affected_parts_.begin(), tmp_affected_parts_.end());
135 for (
const int part : tmp_affected_parts_) {
136 const int start_index = part_[part].start_index;
137 const int end_index = part_[part].end_index;
138 const int split_index = end_index - tmp_counter_of_part_[part];
139 tmp_counter_of_part_[part] = 0;
140 DCHECK_GE(split_index, start_index);
141 DCHECK_LT(split_index, end_index);
144 if (split_index == start_index)
continue;
147 uint64_t new_fprint = 0;
148 for (
int i = split_index; i < end_index; ++i) {
149 new_fprint ^= FprintOfInt32(element_[i]);
155 part_[part].end_index = split_index;
156 part_[part].fprint ^= new_fprint;
157 part_.push_back(Part( split_index, end_index,
160 part_of_[element] = new_part;
166 DCHECK_GE(
NumParts(), original_num_parts);
167 DCHECK_GE(original_num_parts, 1);
168 while (
NumParts() > original_num_parts) {
169 const int part_index =
NumParts() - 1;
170 const Part& part = part_[part_index];
171 const int parent_part_index = part.parent_part;
172 DCHECK_LT(parent_part_index, part_index) <<
"UndoRefineUntilNumPartsEqual()"
174 "'original_num_parts' too low";
178 part_of_[element] = parent_part_index;
180 Part*
const parent_part = &part_[parent_part_index];
181 DCHECK_EQ(part.start_index, parent_part->end_index);
182 parent_part->end_index = part.end_index;
183 parent_part->fprint ^= part.fprint;
190 return absl::StrFormat(
"Unsupported sorting: %d", sorting);
192 std::vector<std::vector<int>> parts;
193 for (
int i = 0; i <
NumParts(); ++i) {
195 parts.emplace_back(iterable_part.
begin(), iterable_part.
end());
196 std::sort(parts.back().begin(), parts.back().end());
199 std::sort(parts.begin(), parts.end());
202 for (
const std::vector<int>& part : parts) {
203 if (!out.empty()) out +=
" | ";
204 out += absl::StrJoin(part,
" ");
210 DCHECK_GE(num_nodes, 0);
211 part_size_.assign(num_nodes, 1);
212 parent_.assign(num_nodes, -1);
213 for (
int i = 0; i < num_nodes; ++i) parent_[i] = i;
214 tmp_part_bit_.assign(num_nodes,
false);
224 if (root1 == root2)
return -1;
225 int s1 = part_size_[root1];
226 int s2 = part_size_[root2];
228 if (s1 < s2 || (s1 == s2 && root1 > root2)) {
235 part_size_[root1] += part_size_[root2];
236 SetParentAlongPathToRoot(node1, root1);
237 SetParentAlongPathToRoot(node2, root1);
244 const int root =
GetRoot(node);
245 SetParentAlongPathToRoot(node, root);
250 int num_nodes_kept = 0;
251 for (
const int node : *
nodes) {
255 (*nodes)[num_nodes_kept++] = node;
258 nodes->resize(num_nodes_kept);
262 for (
const int node : *
nodes) tmp_part_bit_[
GetRoot(node)] =
false;
266 std::vector<int>* node_equivalence_classes) {
267 node_equivalence_classes->assign(
NumNodes(), -1);
269 for (
int node = 0; node <
NumNodes(); ++node) {
271 if ((*node_equivalence_classes)[root] < 0) {
272 (*node_equivalence_classes)[root] = num_roots;
275 (*node_equivalence_classes)[node] = (*node_equivalence_classes)[root];
281 std::vector<std::vector<int>> sorted_parts(
NumNodes());
282 for (
int i = 0; i <
NumNodes(); ++i) {
285 for (std::vector<int>& part : sorted_parts)
286 std::sort(part.begin(), part.end());
287 std::sort(sorted_parts.begin(), sorted_parts.end());
291 for (
const std::vector<int>& part : sorted_parts) {
292 if (!out.empty()) out +=
" | ";
293 out += absl::StrJoin(part,
" ");
299 absl::Span<const int> distinguished_subset) {
302 temp_to_clean_.clear();
303 std::vector<int>& local_sizes = temp_data_by_part_;
304 local_sizes.resize(size_of_part_.size(), 0);
305 for (
const int element : distinguished_subset) {
306 const int part = part_of_[element];
307 if (local_sizes[part] == 0) temp_to_clean_.push_back(part);
313 for (
const int part : temp_to_clean_) {
314 if (local_sizes[part] == size_of_part_[part]) {
316 local_sizes[part] = 0;
320 const int new_part_index = size_of_part_.size();
321 size_of_part_[part] -= local_sizes[part];
322 size_of_part_.push_back(local_sizes[part]);
323 local_sizes[part] = new_part_index;
328 for (
const int element : distinguished_subset) {
329 const int new_part = local_sizes[part_of_[element]];
330 if (new_part != 0) part_of_[element] = new_part;
334 for (
const int part : temp_to_clean_) {
335 local_sizes[part] = 0;
340 std::vector<int>* buffer) {
341 const int num_elements = part_of_.size();
342 const int num_parts = size_of_part_.size();
343 buffer->resize(num_elements);
345 std::vector<absl::Span<const int>> result(num_parts);
346 if (result.empty())
return result;
349 std::vector<int>& starts = temp_data_by_part_;
350 starts.resize(num_parts, 0);
351 for (
int i = 1; i < num_parts; ++i) {
352 starts[i] = starts[i - 1] + size_of_part_[i - 1];
356 for (
int i = 0; i < num_parts; ++i) {
357 result[i] = absl::MakeSpan(&(*buffer)[starts[i]], size_of_part_[i]);
361 for (
int element = 0; element < num_elements; ++element) {
362 (*buffer)[starts[part_of_[element]]++] = element;
IterablePart ElementsInPart(int i) const
void Refine(const std::vector< int > &distinguished_subset)
void UndoRefineUntilNumPartsEqual(int original_num_parts)
DynamicPartition(int num_elements)
std::string DebugString(DebugStringSorting sorting) const
const int NumParts() const
void Reset(int num_nodes)
std::string DebugString()
int MergePartsOf(int node1, int node2)
int FillEquivalenceClasses(std::vector< int > *node_equivalence_classes)
void KeepOnlyOneNodePerPart(std::vector< int > *nodes)
int GetRootAndCompressPath(int node)
int GetRoot(int node) const
void Refine(absl::Span< const int > distinguished_subset)
std::vector< absl::Span< const int > > GetParts(std::vector< int > *buffer)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Collection of objects used to extend the Constraint Solver library.
uint64_t MurmurHash64(const char *buf, const size_t len)
std::vector< int >::const_iterator end() const
std::vector< int >::const_iterator begin() const