Skip to content

Commit

Permalink
sync set cover
Browse files Browse the repository at this point in the history
  • Loading branch information
lperron committed Jan 27, 2025
1 parent d04d379 commit 240b86f
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 81 deletions.
11 changes: 9 additions & 2 deletions ortools/algorithms/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,14 @@ cc_test(
"//ortools/base:dump_vars",
"//ortools/base:gmock_main",
"//ortools/base:mathutil",
"//ortools/base:timer",
"@com_google_absl//absl/algorithm:container",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/random",
"@com_google_absl//absl/random:bit_gen_ref",
"@com_google_absl//absl/random:distributions",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
"@com_google_benchmark//:benchmark",
],
Expand Down Expand Up @@ -286,6 +289,7 @@ cc_library(
srcs = ["set_cover_model.cc"],
hdrs = ["set_cover_model.h"],
deps = [
":radix_sort",
":set_cover_cc_proto",
"//ortools/base:intops",
"//ortools/base:strong_vector",
Expand All @@ -296,6 +300,7 @@ cc_library(
"@com_google_absl//absl/random:distributions",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/types:span",
],
)

Expand Down Expand Up @@ -495,17 +500,19 @@ cc_library(
":dynamic_partition",
":dynamic_permutation",
":sparse_permutation",
"//ortools/base:dump_vars",
"//ortools/base:murmur",
"//ortools/graph",
"//ortools/graph:iterators",
"//ortools/graph:util",
"//ortools/util:stats",
"//ortools/util:time_limit",
"@com_google_absl//absl/algorithm:container",
"@com_google_absl//absl/base:log_severity",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/numeric:int128",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
Expand Down
23 changes: 18 additions & 5 deletions ortools/algorithms/find_graph_symmetries.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@
#include "ortools/algorithms/find_graph_symmetries.h"

#include <algorithm>
#include <cmath>
#include <cstdint>
#include <limits>
#include <memory>
#include <numeric>
#include <string>
#include <utility>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/base/log_severity.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/flags/flag.h"
#include "absl/memory/memory.h"
#include "absl/log/check.h"
#include "absl/numeric/int128.h"
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
Expand All @@ -36,6 +39,8 @@
#include "ortools/algorithms/dynamic_partition.h"
#include "ortools/algorithms/dynamic_permutation.h"
#include "ortools/algorithms/sparse_permutation.h"
#include "ortools/base/logging.h"
#include "ortools/graph/graph.h"
#include "ortools/graph/iterators.h"
#include "ortools/graph/util.h"

Expand Down Expand Up @@ -699,9 +704,17 @@ GraphSymmetryFinder::FindOneSuitablePermutation(
// DCHECKs() and statistics.
ScopedTimeDistributionUpdater search_time_updater(&stats_.search_time);
DCHECK_EQ("", tmp_dynamic_permutation_.DebugString());
DCHECK_EQ(
base_partition->DebugString(/*sort_parts_lexicographically=*/false),
image_partition->DebugString(/*sort_parts_lexicographically=*/false));
DCHECK_EQ(base_partition->NumParts(), image_partition->NumParts());
if (DEBUG_MODE) {
for (int i = 0; i < base_partition->NumParts(); ++i) {
DCHECK_EQ(base_partition->FprintOfPart(i),
image_partition->FprintOfPart(i))
<< base_partition->DebugString(/*sort_parts_lexicographically=*/false)
<< " "
<< image_partition->DebugString(
/*sort_parts_lexicographically=*/false);
}
}
DCHECK(search_states_.empty());

// These will be used during the search. See their usage.
Expand Down
5 changes: 5 additions & 0 deletions ortools/algorithms/set_cover.proto
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,21 @@ message SetCoverSolutionResponse {
enum Status {
// Undefined.
UNDEFINED = 0;

// The solver found the proven optimal solution.
OPTIMAL = 1;

// The solver had enough time to find some solution that satisfied all
// constraints, but it did not reach the optimal.
FEASIBLE = 2;

// The model does not have any solution.
INFEASIBLE = 3;

// The model is invalid.
INVALID = 4;
}

// For future use. TODO(user): Implement.
optional Status status = 1;

Expand Down
17 changes: 8 additions & 9 deletions ortools/algorithms/set_cover_heuristics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,9 @@ void IncreasingCountingSort(uint32_t radix, int shift, std::vector<Key>& keys,
const auto num_keys = keys.size();
// In this order for stability.
for (int64_t i = num_keys - 1; i >= 0; --i) {
Counter& c = counts[Bucket(keys[i], shift, radix)];
scratch_keys[c - 1] = keys[i];
scratch_payloads[c - 1] = payloads[i];
--c;
Counter c = --counts[Bucket(keys[i], shift, radix)];
scratch_keys[c] = keys[i];
scratch_payloads[c] = payloads[i];
}
std::swap(keys, scratch_keys);
std::swap(payloads, scratch_payloads);
Expand All @@ -301,14 +300,14 @@ void IncreasingCountingSort(uint32_t radix, int shift, std::vector<Key>& keys,

template <typename Key, typename Payload>
void RadixSort(int radix_log, std::vector<Key>& keys,
std::vector<Payload>& payloads, Key min_key, Key max_key) {
std::vector<Payload>& payloads, Key /*min_key*/, Key max_key) {
// range_log is the number of bits necessary to represent the max_key
// We could as well use max_key - min_key, but it is more expensive to
// compute.
const int range_log = internal::NumBitsToRepresent(max_key);
DCHECK_EQ(internal::NumBitsToRepresent(0), 0);
DCHECK_LE(internal::NumBitsToRepresent(std::numeric_limits<Key>::max()),
sizeof(Key) * CHAR_BIT);
std::numeric_limits<Key>::digits);
const int radix = 1 << radix_log; // By definition.
std::vector<uint32_t> counters(radix, 0);
std::vector<Key> scratch_keys(keys.size());
Expand All @@ -330,7 +329,7 @@ std::vector<ElementIndex> GetUncoveredElementsSortedByDegree(
keys.reserve(num_elements);
const SparseRowView& rows = inv->model()->rows();
BaseInt max_degree = 0;
for (ElementIndex element : inv->model()->ElementRange()) {
for (const ElementIndex element : inv->model()->ElementRange()) {
// Already covered elements should not be considered.
if (inv->coverage()[element] != 0) continue;
degree_sorted_elements.push_back(element);
Expand Down Expand Up @@ -729,8 +728,8 @@ bool GuidedLocalSearch::NextSolution(int num_iterations) {
}

Cost GuidedLocalSearch::ComputeDelta(SubsetIndex subset) const {
float delta = (penalization_factor_ * penalties_[subset] +
inv_->model()->subset_costs()[subset]);
const float delta = (penalization_factor_ * penalties_[subset] +
inv_->model()->subset_costs()[subset]);
if (inv_->is_selected()[subset] && inv_->ComputeIsRedundant(subset)) {
return delta;
} else if (!inv_->is_selected()[subset]) {
Expand Down
19 changes: 14 additions & 5 deletions ortools/algorithms/set_cover_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include "absl/random/distributions.h"
#include "absl/random/random.h"
#include "absl/strings/str_format.h"
#include "absl/types/span.h"
#include "ortools/algorithms/radix_sort.h"
#include "ortools/algorithms/set_cover.pb.h"
#include "ortools/base/logging.h"

Expand Down Expand Up @@ -322,7 +324,9 @@ void SetCoverModel::ReserveNumElementsInSubset(ElementIndex num_elements,

void SetCoverModel::SortElementsInSubsets() {
for (const SubsetIndex subset : SubsetRange()) {
std::sort(columns_[subset].begin(), columns_[subset].end());
// std::sort(columns_[subset].begin(), columns_[subset].end());
BaseInt* data = reinterpret_cast<BaseInt*>(columns_[subset].data());
RadixSort(absl::MakeSpan(data, columns_[subset].size()));
}
elements_in_subsets_are_sorted_ = true;
}
Expand All @@ -336,7 +340,10 @@ void SetCoverModel::CreateSparseRowView() {
for (const SubsetIndex subset : SubsetRange()) {
// Sort the columns. It's not super-critical to improve performance here
// as this needs to be done only once.
std::sort(columns_[subset].begin(), columns_[subset].end());
// std::sort(columns_[subset].begin(), columns_[subset].end());
BaseInt* data = reinterpret_cast<BaseInt*>(columns_[subset].data());
RadixSort(absl::MakeSpan(data, columns_[subset].size()));

for (const ElementIndex element : columns_[subset]) {
++row_sizes[element];
}
Expand All @@ -346,7 +353,7 @@ void SetCoverModel::CreateSparseRowView() {
}
for (const SubsetIndex subset : SubsetRange()) {
for (const ElementIndex element : columns_[subset]) {
rows_[element].push_back(subset);
rows_[element].emplace_back(subset);
}
}
row_view_is_valid_ = true;
Expand Down Expand Up @@ -392,8 +399,10 @@ SetCoverProto SetCoverModel::ExportModelAsProto() const {
100.0 * subset.value() / num_subsets());
SetCoverProto::Subset* subset_proto = message.add_subset();
subset_proto->set_cost(subset_costs_[subset]);
SparseColumn column = columns_[subset];
std::sort(column.begin(), column.end());
SparseColumn column = columns_[subset]; // Copy is intentional.
// std::sort(column.begin(), column.end());
BaseInt* data = reinterpret_cast<BaseInt*>(column.data());
RadixSort(absl::MakeSpan(data, column.size()));
for (const ElementIndex element : column) {
subset_proto->add_element(element.value());
}
Expand Down
Loading

0 comments on commit 240b86f

Please sign in to comment.