Skip to content

Commit

Permalink
more spans
Browse files Browse the repository at this point in the history
  • Loading branch information
lperron committed Dec 2, 2024
1 parent 0ad3c6c commit 927f5c9
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 11 deletions.
1 change: 1 addition & 0 deletions ortools/algorithms/python/set_cover.cc
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ PYBIND11_MODULE(set_cover, m) {
},
arg("subset"), arg("cost"))
.def("create_sparse_row_view", &SetCoverModel::CreateSparseRowView)
.def("sort_elements_in_subsets", &SetCoverModel::SortElementsInSubsets)
.def("compute_feasibility", &SetCoverModel::ComputeFeasibility)
.def(
"reserve_num_subsets",
Expand Down
1 change: 1 addition & 0 deletions ortools/algorithms/python/set_cover_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class SetCoverTest(absltest.TestCase):

def test_save_reload(self):
model = create_knights_cover_model(10, 10)
model.sort_elements_in_subsets()
proto = model.export_model_as_proto()
reloaded = set_cover.SetCoverModel()
reloaded.import_model_from_proto(proto)
Expand Down
2 changes: 1 addition & 1 deletion ortools/algorithms/set_cover_heuristics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ bool GreedySolutionGenerator::NextSolution() {
}

bool GreedySolutionGenerator::NextSolution(
const std::vector<SubsetIndex>& focus) {
absl::Span<const SubsetIndex> focus) {
return NextSolution(focus, inv_->model()->subset_costs());
}

Expand Down
2 changes: 1 addition & 1 deletion ortools/algorithms/set_cover_heuristics.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class GreedySolutionGenerator {

// Computes the next partial solution considering only the subsets whose
// indices are in focus.
bool NextSolution(const std::vector<SubsetIndex>& focus);
bool NextSolution(absl::Span<const SubsetIndex> focus);

// Same with a different set of costs.
bool NextSolution(absl::Span<const SubsetIndex> focus,
Expand Down
23 changes: 19 additions & 4 deletions ortools/algorithms/set_cover_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ void SetCoverModel::UpdateAllSubsetsList() {
}

void SetCoverModel::AddEmptySubset(Cost cost) {
elements_in_subsets_are_sorted_ = false;
subset_costs_.push_back(cost);
columns_.push_back(SparseColumn());
all_subsets_.push_back(SubsetIndex(num_subsets_));
Expand All @@ -194,6 +195,7 @@ void SetCoverModel::AddEmptySubset(Cost cost) {
}

void SetCoverModel::AddElementToLastSubset(BaseInt element) {
elements_in_subsets_are_sorted_ = false;
columns_.back().push_back(ElementIndex(element));
num_elements_ = std::max(num_elements_, element + 1);
// No need to update the list all_subsets_.
Expand All @@ -206,6 +208,7 @@ void SetCoverModel::AddElementToLastSubset(ElementIndex element) {
}

void SetCoverModel::SetSubsetCost(BaseInt subset, Cost cost) {
elements_in_subsets_are_sorted_ = false;
CHECK(std::isfinite(cost));
DCHECK_GE(subset, 0);
if (subset >= num_subsets()) {
Expand All @@ -223,6 +226,7 @@ void SetCoverModel::SetSubsetCost(SubsetIndex subset, Cost cost) {
}

void SetCoverModel::AddElementToSubset(BaseInt element, BaseInt subset) {
elements_in_subsets_are_sorted_ = false;
if (subset >= num_subsets()) {
num_subsets_ = subset + 1;
subset_costs_.resize(num_subsets_, 0.0);
Expand Down Expand Up @@ -264,6 +268,13 @@ void SetCoverModel::ReserveNumElementsInSubset(ElementIndex num_elements,
ReserveNumElementsInSubset(num_elements.value(), subset.value());
}

void SetCoverModel::SortElementsInSubsets() {
for (const SubsetIndex subset : SubsetRange()) {
std::sort(columns_[subset].begin(), columns_[subset].end());
}
elements_in_subsets_are_sorted_ = true;
}

void SetCoverModel::CreateSparseRowView() {
if (row_view_is_valid_) {
return;
Expand All @@ -287,6 +298,7 @@ void SetCoverModel::CreateSparseRowView() {
}
}
row_view_is_valid_ = true;
elements_in_subsets_are_sorted_ = true;
}

bool SetCoverModel::ComputeFeasibility() const {
Expand Down Expand Up @@ -319,13 +331,15 @@ bool SetCoverModel::ComputeFeasibility() const {
return true;
}

SetCoverProto SetCoverModel::ExportModelAsProto() {
SetCoverProto SetCoverModel::ExportModelAsProto() const {
CHECK(elements_in_subsets_are_sorted_);
SetCoverProto message;
for (const SubsetIndex subset : SubsetRange()) {
SetCoverProto::Subset* subset_proto = message.add_subset();
subset_proto->set_cost(subset_costs_[subset]);
std::sort(columns_[subset].begin(), columns_[subset].end());
for (const ElementIndex element : columns_[subset]) {
SparseColumn column = columns_[subset];
std::sort(column.begin(), column.end());
for (const ElementIndex element : column) {
subset_proto->add_element(element.value());
}
}
Expand Down Expand Up @@ -433,8 +447,9 @@ std::vector<T> ComputeDeciles(std::vector<T> values) {
const int kNumDeciles = 10;
std::vector<T> deciles;
deciles.reserve(kNumDeciles);
const float step = values.size() / kNumDeciles;
for (int i = 1; i <= kNumDeciles; ++i) {
const size_t point = values.size() * i / kNumDeciles - 1;
const size_t point = std::max<float>(0, i * step - 1);
std::nth_element(values.begin(), values.begin() + point, values.end());
deciles.push_back(values[point]);
}
Expand Down
21 changes: 16 additions & 5 deletions ortools/algorithms/set_cover_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class SetCoverModel {
num_subsets_(0),
num_nonzeros_(0),
row_view_is_valid_(false),
elements_in_subsets_are_sorted_(false),
subset_costs_(),
columns_(),
rows_(),
Expand Down Expand Up @@ -204,7 +205,12 @@ class SetCoverModel {
void AddElementToSubset(BaseInt element, BaseInt subset);
void AddElementToSubset(ElementIndex element, SubsetIndex subset);

// Creates the sparse ("dual") representation of the problem.
// Sorts the elements in each subset. Should be called before exporting the
// model to a proto.
void SortElementsInSubsets();

// Creates the sparse ("dual") representation of the problem. This also sorts
// the elements in each subset.
void CreateSparseRowView();

// Returns true if the problem is feasible, i.e. if the subsets cover all
Expand All @@ -220,10 +226,12 @@ class SetCoverModel {
void ReserveNumElementsInSubset(ElementIndex num_elements,
SubsetIndex subset);

// Returns the model as a SetCoverProto. The function is not const because
// the element indices in the columns need to be sorted for the representation
// as a protobuf to be canonical.
SetCoverProto ExportModelAsProto();
// Returns the model as a SetCoverProto. Note that the elements of each subset
// are sorted locally before being exported to the proto. This is done to
// ensure that the proto is deterministic. The function is const because it
// does not modify the model. Therefore, the model as exported by this
// function may be different from the initial model.
SetCoverProto ExportModelAsProto() const;

// Imports the model from a SetCoverProto.
void ImportModelFromProto(const SetCoverProto& message);
Expand Down Expand Up @@ -284,6 +292,9 @@ class SetCoverModel {
// True when the SparseRowView is up-to-date.
bool row_view_is_valid_;

// True when the elements in each subset are sorted.
bool elements_in_subsets_are_sorted_;

// Costs for each subset.

SubsetCostVector subset_costs_;
Expand Down
1 change: 1 addition & 0 deletions ortools/algorithms/set_cover_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class KnightsCover {

TEST(SetCoverProtoTest, SaveReload) {
SetCoverModel model = KnightsCover(10, 10).model();
model.SortElementsInSubsets();
SetCoverProto proto = model.ExportModelAsProto();
SetCoverModel reloaded;
reloaded.ImportModelFromProto(proto);
Expand Down

0 comments on commit 927f5c9

Please sign in to comment.