Skip to content

Commit 240b86f

Browse files
committed
sync set cover
1 parent d04d379 commit 240b86f

7 files changed

+137
-81
lines changed

Diff for: ortools/algorithms/BUILD.bazel

+9-2
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,14 @@ cc_test(
120120
"//ortools/base:dump_vars",
121121
"//ortools/base:gmock_main",
122122
"//ortools/base:mathutil",
123+
"//ortools/base:timer",
123124
"@com_google_absl//absl/algorithm:container",
124125
"@com_google_absl//absl/log",
126+
"@com_google_absl//absl/log:check",
125127
"@com_google_absl//absl/random",
126128
"@com_google_absl//absl/random:bit_gen_ref",
127129
"@com_google_absl//absl/random:distributions",
130+
"@com_google_absl//absl/time",
128131
"@com_google_absl//absl/types:span",
129132
"@com_google_benchmark//:benchmark",
130133
],
@@ -286,6 +289,7 @@ cc_library(
286289
srcs = ["set_cover_model.cc"],
287290
hdrs = ["set_cover_model.h"],
288291
deps = [
292+
":radix_sort",
289293
":set_cover_cc_proto",
290294
"//ortools/base:intops",
291295
"//ortools/base:strong_vector",
@@ -296,6 +300,7 @@ cc_library(
296300
"@com_google_absl//absl/random:distributions",
297301
"@com_google_absl//absl/strings",
298302
"@com_google_absl//absl/strings:str_format",
303+
"@com_google_absl//absl/types:span",
299304
],
300305
)
301306

@@ -495,17 +500,19 @@ cc_library(
495500
":dynamic_partition",
496501
":dynamic_permutation",
497502
":sparse_permutation",
498-
"//ortools/base:dump_vars",
499503
"//ortools/base:murmur",
500504
"//ortools/graph",
501505
"//ortools/graph:iterators",
502506
"//ortools/graph:util",
503507
"//ortools/util:stats",
504508
"//ortools/util:time_limit",
505509
"@com_google_absl//absl/algorithm:container",
510+
"@com_google_absl//absl/base:log_severity",
511+
"@com_google_absl//absl/container:flat_hash_map",
506512
"@com_google_absl//absl/container:flat_hash_set",
507513
"@com_google_absl//absl/flags:flag",
508-
"@com_google_absl//absl/memory",
514+
"@com_google_absl//absl/log",
515+
"@com_google_absl//absl/log:check",
509516
"@com_google_absl//absl/numeric:int128",
510517
"@com_google_absl//absl/status",
511518
"@com_google_absl//absl/strings",

Diff for: ortools/algorithms/find_graph_symmetries.cc

+18-5
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,21 @@
1414
#include "ortools/algorithms/find_graph_symmetries.h"
1515

1616
#include <algorithm>
17+
#include <cmath>
1718
#include <cstdint>
18-
#include <limits>
1919
#include <memory>
2020
#include <numeric>
2121
#include <string>
2222
#include <utility>
2323
#include <vector>
2424

2525
#include "absl/algorithm/container.h"
26+
#include "absl/base/log_severity.h"
27+
#include "absl/container/flat_hash_map.h"
2628
#include "absl/container/flat_hash_set.h"
2729
#include "absl/flags/flag.h"
28-
#include "absl/memory/memory.h"
30+
#include "absl/log/check.h"
31+
#include "absl/numeric/int128.h"
2932
#include "absl/status/status.h"
3033
#include "absl/strings/str_format.h"
3134
#include "absl/strings/str_join.h"
@@ -36,6 +39,8 @@
3639
#include "ortools/algorithms/dynamic_partition.h"
3740
#include "ortools/algorithms/dynamic_permutation.h"
3841
#include "ortools/algorithms/sparse_permutation.h"
42+
#include "ortools/base/logging.h"
43+
#include "ortools/graph/graph.h"
3944
#include "ortools/graph/iterators.h"
4045
#include "ortools/graph/util.h"
4146

@@ -699,9 +704,17 @@ GraphSymmetryFinder::FindOneSuitablePermutation(
699704
// DCHECKs() and statistics.
700705
ScopedTimeDistributionUpdater search_time_updater(&stats_.search_time);
701706
DCHECK_EQ("", tmp_dynamic_permutation_.DebugString());
702-
DCHECK_EQ(
703-
base_partition->DebugString(/*sort_parts_lexicographically=*/false),
704-
image_partition->DebugString(/*sort_parts_lexicographically=*/false));
707+
DCHECK_EQ(base_partition->NumParts(), image_partition->NumParts());
708+
if (DEBUG_MODE) {
709+
for (int i = 0; i < base_partition->NumParts(); ++i) {
710+
DCHECK_EQ(base_partition->FprintOfPart(i),
711+
image_partition->FprintOfPart(i))
712+
<< base_partition->DebugString(/*sort_parts_lexicographically=*/false)
713+
<< " "
714+
<< image_partition->DebugString(
715+
/*sort_parts_lexicographically=*/false);
716+
}
717+
}
705718
DCHECK(search_states_.empty());
706719

707720
// These will be used during the search. See their usage.

Diff for: ortools/algorithms/set_cover.proto

+5
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,21 @@ message SetCoverSolutionResponse {
4444
enum Status {
4545
// Undefined.
4646
UNDEFINED = 0;
47+
4748
// The solver found the proven optimal solution.
4849
OPTIMAL = 1;
50+
4951
// The solver had enough time to find some solution that satisfied all
5052
// constraints, but it did not reach the optimal.
5153
FEASIBLE = 2;
54+
5255
// The model does not have any solution.
5356
INFEASIBLE = 3;
57+
5458
// The model is invalid.
5559
INVALID = 4;
5660
}
61+
5762
// For future use. TODO(user): Implement.
5863
optional Status status = 1;
5964

Diff for: ortools/algorithms/set_cover_heuristics.cc

+8-9
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,9 @@ void IncreasingCountingSort(uint32_t radix, int shift, std::vector<Key>& keys,
289289
const auto num_keys = keys.size();
290290
// In this order for stability.
291291
for (int64_t i = num_keys - 1; i >= 0; --i) {
292-
Counter& c = counts[Bucket(keys[i], shift, radix)];
293-
scratch_keys[c - 1] = keys[i];
294-
scratch_payloads[c - 1] = payloads[i];
295-
--c;
292+
Counter c = --counts[Bucket(keys[i], shift, radix)];
293+
scratch_keys[c] = keys[i];
294+
scratch_payloads[c] = payloads[i];
296295
}
297296
std::swap(keys, scratch_keys);
298297
std::swap(payloads, scratch_payloads);
@@ -301,14 +300,14 @@ void IncreasingCountingSort(uint32_t radix, int shift, std::vector<Key>& keys,
301300

302301
template <typename Key, typename Payload>
303302
void RadixSort(int radix_log, std::vector<Key>& keys,
304-
std::vector<Payload>& payloads, Key min_key, Key max_key) {
303+
std::vector<Payload>& payloads, Key /*min_key*/, Key max_key) {
305304
// range_log is the number of bits necessary to represent the max_key
306305
// We could as well use max_key - min_key, but it is more expensive to
307306
// compute.
308307
const int range_log = internal::NumBitsToRepresent(max_key);
309308
DCHECK_EQ(internal::NumBitsToRepresent(0), 0);
310309
DCHECK_LE(internal::NumBitsToRepresent(std::numeric_limits<Key>::max()),
311-
sizeof(Key) * CHAR_BIT);
310+
std::numeric_limits<Key>::digits);
312311
const int radix = 1 << radix_log; // By definition.
313312
std::vector<uint32_t> counters(radix, 0);
314313
std::vector<Key> scratch_keys(keys.size());
@@ -330,7 +329,7 @@ std::vector<ElementIndex> GetUncoveredElementsSortedByDegree(
330329
keys.reserve(num_elements);
331330
const SparseRowView& rows = inv->model()->rows();
332331
BaseInt max_degree = 0;
333-
for (ElementIndex element : inv->model()->ElementRange()) {
332+
for (const ElementIndex element : inv->model()->ElementRange()) {
334333
// Already covered elements should not be considered.
335334
if (inv->coverage()[element] != 0) continue;
336335
degree_sorted_elements.push_back(element);
@@ -729,8 +728,8 @@ bool GuidedLocalSearch::NextSolution(int num_iterations) {
729728
}
730729

731730
Cost GuidedLocalSearch::ComputeDelta(SubsetIndex subset) const {
732-
float delta = (penalization_factor_ * penalties_[subset] +
733-
inv_->model()->subset_costs()[subset]);
731+
const float delta = (penalization_factor_ * penalties_[subset] +
732+
inv_->model()->subset_costs()[subset]);
734733
if (inv_->is_selected()[subset] && inv_->ComputeIsRedundant(subset)) {
735734
return delta;
736735
} else if (!inv_->is_selected()[subset]) {

Diff for: ortools/algorithms/set_cover_model.cc

+14-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include "absl/random/distributions.h"
3030
#include "absl/random/random.h"
3131
#include "absl/strings/str_format.h"
32+
#include "absl/types/span.h"
33+
#include "ortools/algorithms/radix_sort.h"
3234
#include "ortools/algorithms/set_cover.pb.h"
3335
#include "ortools/base/logging.h"
3436

@@ -322,7 +324,9 @@ void SetCoverModel::ReserveNumElementsInSubset(ElementIndex num_elements,
322324

323325
void SetCoverModel::SortElementsInSubsets() {
324326
for (const SubsetIndex subset : SubsetRange()) {
325-
std::sort(columns_[subset].begin(), columns_[subset].end());
327+
// std::sort(columns_[subset].begin(), columns_[subset].end());
328+
BaseInt* data = reinterpret_cast<BaseInt*>(columns_[subset].data());
329+
RadixSort(absl::MakeSpan(data, columns_[subset].size()));
326330
}
327331
elements_in_subsets_are_sorted_ = true;
328332
}
@@ -336,7 +340,10 @@ void SetCoverModel::CreateSparseRowView() {
336340
for (const SubsetIndex subset : SubsetRange()) {
337341
// Sort the columns. It's not super-critical to improve performance here
338342
// as this needs to be done only once.
339-
std::sort(columns_[subset].begin(), columns_[subset].end());
343+
// std::sort(columns_[subset].begin(), columns_[subset].end());
344+
BaseInt* data = reinterpret_cast<BaseInt*>(columns_[subset].data());
345+
RadixSort(absl::MakeSpan(data, columns_[subset].size()));
346+
340347
for (const ElementIndex element : columns_[subset]) {
341348
++row_sizes[element];
342349
}
@@ -346,7 +353,7 @@ void SetCoverModel::CreateSparseRowView() {
346353
}
347354
for (const SubsetIndex subset : SubsetRange()) {
348355
for (const ElementIndex element : columns_[subset]) {
349-
rows_[element].push_back(subset);
356+
rows_[element].emplace_back(subset);
350357
}
351358
}
352359
row_view_is_valid_ = true;
@@ -392,8 +399,10 @@ SetCoverProto SetCoverModel::ExportModelAsProto() const {
392399
100.0 * subset.value() / num_subsets());
393400
SetCoverProto::Subset* subset_proto = message.add_subset();
394401
subset_proto->set_cost(subset_costs_[subset]);
395-
SparseColumn column = columns_[subset];
396-
std::sort(column.begin(), column.end());
402+
SparseColumn column = columns_[subset]; // Copy is intentional.
403+
// std::sort(column.begin(), column.end());
404+
BaseInt* data = reinterpret_cast<BaseInt*>(column.data());
405+
RadixSort(absl::MakeSpan(data, column.size()));
397406
for (const ElementIndex element : column) {
398407
subset_proto->add_element(element.value());
399408
}

0 commit comments

Comments
 (0)