diff --git a/ortools/algorithms/set_cover_ledger.cc b/ortools/algorithms/set_cover_ledger.cc index 9c5d71e0c4..20397af44e 100644 --- a/ortools/algorithms/set_cover_ledger.cc +++ b/ortools/algorithms/set_cover_ledger.cc @@ -134,13 +134,14 @@ SubsetToElementVector SetCoverLedger::ComputeMarginalImpacts( } Cost SetCoverLedger::ComputeCost(const SubsetBoolVector& c) const { + DCHECK_EQ(c.size(), model_->num_subsets()); Cost recomputed_cost = 0; const SubsetCostVector& subset_costs = model_->subset_costs(); - const SubsetIndex num_subsets(model_->num_subsets()); - for (SubsetIndex subset(0); subset < num_subsets; ++subset) { - if (c[subset]) { + for (SubsetIndex subset(0); bool b : c) { + if (b) { recomputed_cost += subset_costs[subset]; } + ++subset; } return recomputed_cost; } diff --git a/ortools/algorithms/set_cover_ledger.h b/ortools/algorithms/set_cover_ledger.h index e55e1a79f8..f582217f58 100644 --- a/ortools/algorithms/set_cover_ledger.h +++ b/ortools/algorithms/set_cover_ledger.h @@ -73,7 +73,11 @@ class SetCoverLedger { } // Returns the number of subsets covering each element. - SubsetIndex coverage(ElementIndex subset) const { return coverage_[subset]; } + SubsetIndex coverage(ElementIndex element) const { + return coverage_[element]; + } + + ElementToSubsetVector coverage() const { return coverage_; } // Returns whether subset can be removed from the solution. bool is_removable(SubsetIndex subset) const { return is_removable_[subset]; } diff --git a/ortools/algorithms/set_cover_model.h b/ortools/algorithms/set_cover_model.h index 24754076e9..e246980161 100644 --- a/ortools/algorithms/set_cover_model.h +++ b/ortools/algorithms/set_cover_model.h @@ -16,6 +16,7 @@ #include +#include "absl/log/check.h" #include "ortools/lp_data/lp_types.h" // For StrictITIVector. // Representation class for the weighted set-covering problem. @@ -57,6 +58,7 @@ DEFINE_STRONG_INDEX_TYPE(EntryIndex); // The return type for size() is a simple size_t and not an Index as in // StrictITIVector, which makes the code less elegant. using SubsetCostVector = glop::StrictITIVector; +using ElementCostVector = glop::StrictITIVector; using SparseColumn = glop::StrictITIVector; using SparseRow = glop::StrictITIVector; @@ -85,19 +87,30 @@ class SetCoverModel { // number of columns. SubsetIndex num_subsets() const { return columns_.size(); } - const SubsetCostVector& subset_costs() { return subset_costs_; } + const SubsetCostVector& subset_costs() const { return subset_costs_; } - const SparseColumnView& columns() { return columns_; } + Cost subset_costs(SubsetIndex subset) const { return subset_costs_[subset]; } - const SparseRowView& rows() { + const SparseColumnView& columns() const { return columns_; } + + const SparseColumn& columns(SubsetIndex subset) const { + return columns_[subset]; + } + + const SparseRowView& rows() const { DCHECK(row_view_is_valid_); return rows_; } + const SparseRow& rows(ElementIndex element) const { + DCHECK(row_view_is_valid_); + return rows_[element]; + } + // Returns true if rows_ and columns_ represent the same problem. bool row_view_is_valid() const { return row_view_is_valid_; } - // Returns the list of indices for the subsets in the model. + // Returns the list of indices for all the subsets in the model. std::vector all_subsets() const { return all_subsets_; } // Adds an empty subset with a cost to the problem. In matrix terms, this diff --git a/ortools/algorithms/set_cover_reader.cc b/ortools/algorithms/set_cover_reader.cc index ade77eb341..24b390563f 100644 --- a/ortools/algorithms/set_cover_reader.cc +++ b/ortools/algorithms/set_cover_reader.cc @@ -14,9 +14,9 @@ #include "ortools/algorithms/set_cover_reader.h" #include +#include #include -#include "absl/base/log_severity.h" #include "absl/log/check.h" #include "absl/strings/numbers.h" #include "absl/strings/string_view.h" @@ -36,8 +36,8 @@ class SetCoverReader { int64_t ParseNextInteger(); private: - size_t SkipBlanks(size_t pos); - size_t SkipNonBlanks(size_t pos); + size_t SkipBlanks(size_t pos) const; + size_t SkipNonBlanks(size_t pos) const; FileLineIterator line_iter_; absl::string_view line_; int start_pos_; @@ -52,22 +52,22 @@ SetCoverReader::SetCoverReader(File* file) line_ = *line_iter_; } -size_t SetCoverReader::SkipBlanks(size_t pos) { - size_t size = line_.size(); +size_t SetCoverReader::SkipBlanks(size_t pos) const { + const size_t size = line_.size(); for (; pos < size && std::isspace(line_[pos]); ++pos) { } return pos; } -size_t SetCoverReader::SkipNonBlanks(size_t pos) { - size_t size = line_.size(); +size_t SetCoverReader::SkipNonBlanks(size_t pos) const { + const size_t size = line_.size(); for (; pos < size && !std::isspace(line_[pos]); ++pos) { } return pos; } absl::string_view SetCoverReader::GetNextToken() { - size_t size = line_.size(); + const size_t size = line_.size(); start_pos_ = SkipBlanks(end_pos_); if (start_pos_ >= size) { ++line_iter_; @@ -95,20 +95,16 @@ SetCoverModel ReadBeasleySetCoverProblem(absl::string_view filename) { File* file(file::OpenOrDie(filename, "r", file::Defaults())); SetCoverReader reader(file); const ElementIndex num_rows(reader.ParseNextInteger()); - DVLOG(INFO) << "num_rows: " << num_rows; const int num_cols(reader.ParseNextInteger()); - DVLOG(INFO) << "num_cols: " << num_cols; model.ReserveNumSubsets(num_cols); for (int i = 0; i < num_cols; ++i) { const double cost(reader.ParseNextDouble()); - DVLOG(INFO) << "cost for column: " << i << ": " << cost; model.SetSubsetCost(i, cost); } for (int element(0); element < num_rows; ++element) { const EntryIndex row_size(reader.ParseNextInteger()); for (EntryIndex entry(0); entry < row_size; ++entry) { const int subset(reader.ParseNextInteger() - 1); - DVLOG(INFO) << "element: " << element << " in is subset: " << subset; model.AddElementToSubset(element, subset); } } @@ -121,20 +117,15 @@ SetCoverModel ReadRailSetCoverProblem(absl::string_view filename) { File* file(file::OpenOrDie(filename, "r", file::Defaults())); SetCoverReader reader(file); const ElementIndex num_rows(reader.ParseNextInteger()); - DVLOG(INFO) << "num_rows: " << num_rows; const int num_cols(reader.ParseNextInteger()); model.ReserveNumSubsets(num_cols); - DVLOG(INFO) << "num_cols: " << num_cols; for (int i(0); i < num_cols; ++i) { const double cost(reader.ParseNextDouble()); - DVLOG(INFO) << "cost for column: " << i << ": " << cost; model.SetSubsetCost(i, cost); const int column_size(reader.ParseNextInteger()); - DVLOG(INFO) << "column_size for column: " << i << ": " << column_size; model.ReserveNumElementsInSubset(i, column_size); for (EntryIndex entry(0); entry < column_size; ++entry) { const int element(reader.ParseNextInteger() - 1); - DVLOG(INFO) << "element: " << element << " in is subset: " << i; model.AddElementToSubset(element, i); } }