Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
set_cover_mip.cc
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <cstdint>
17#include <limits>
18
19#include "absl/log/check.h"
20#include "absl/types/span.h"
26
27namespace operations_research {
28
29namespace {
30// Returns the vector a - b.
32 const ElementToIntVector& b) {
34 DCHECK_EQ(a.size(), b.size());
35 for (const ElementIndex i : a.index_range()) {
36 delta[i] = a[i] - b[i];
37 }
38 return delta;
39}
40} // namespace
41
42template <typename IndexType, typename ValueType>
44
45bool SetCoverMip::NextSolution(bool use_integers,
46 double time_limit_in_seconds) {
47 return NextSolution(inv_->model()->all_subsets(), use_integers,
48 time_limit_in_seconds);
49}
50
51bool SetCoverMip::NextSolution(absl::Span<const SubsetIndex> focus,
52 bool use_integers,
53 double time_limit_in_seconds) {
54 SetCoverModel* model = inv_->model();
55 const SubsetIndex num_subsets(model->num_subsets());
56 const ElementIndex num_elements(model->num_elements());
57 SubsetBoolVector choices = inv_->is_selected();
59 switch (mip_solver_) {
62 break;
64 if (use_integers) {
66 } else {
68 }
69 break;
71 if (!use_integers) {
72 LOG(INFO) << "Defaulting to integer variables with SAT";
73 use_integers = true;
74 }
76 break;
78 LOG(INFO) << "Defaulting to linear relaxation with GLOP";
79 use_integers = false;
81 break;
83 if (use_integers) {
84 LOG(INFO) << "Defaulting to linear relaxation with PDLP";
85 use_integers = false;
86 }
88 break;
89 default:
90 LOG(WARNING) << "Unknown solver value, defaulting to SCIP";
92 }
93 // We are using MPSolver, which is deprecated, because MathOpt does not
94 // provide an interface without using protobufs.
95 // We construct a restricted MIP, omitting all the parts of the problem
96 // that are already fixed in the invariant. The goal is to not spend time
97 // sending data, and having the MIP solver re-discover fixed variables.
98 MPSolver solver("set cover mip", problem_type);
99 solver.SuppressOutput();
100 MPObjective* const objective = solver.MutableObjective();
101 objective->SetMinimization();
102
103 StrictVector<ElementIndex, MPConstraint*> constraints(num_elements, nullptr);
104 StrictVector<SubsetIndex, MPVariable*> vars(num_subsets, nullptr);
105 ElementToIntVector coverage_outside_focus =
106 Subtract(inv_->coverage(), inv_->ComputeCoverageInFocus(focus));
107 for (const SubsetIndex subset : focus) {
108 vars[subset] = solver.MakeVar(0, 1, use_integers, "");
109 objective->SetCoefficient(vars[subset], model->subset_costs()[subset]);
110 for (const ElementIndex element : model->columns()[subset]) {
111 // The model should only contain elements that are not forcibly covered by
112 // subsets outside the focus.
113 if (coverage_outside_focus[element] == 0) continue;
114
115 if (constraints[element] == nullptr) {
116 constexpr double kInfinity = std::numeric_limits<double>::infinity();
117 constraints[element] = solver.MakeRowConstraint(1.0, kInfinity);
118 }
119 constraints[element]->SetCoefficient(vars[subset], 1);
120 }
121 }
122 // set_time_limit takes milliseconds as a unit.
123 solver.set_time_limit(static_cast<int64_t>(time_limit_in_seconds * 1000));
124
125 // Call the solver.
126 const MPSolver::ResultStatus solve_status = solver.Solve();
127 switch (solve_status) {
129 break;
131 break;
133 LOG(ERROR) << "Did not find solution. Problem is infeasible.";
134 break;
136 LOG(ERROR) << "Did not find solution. Problem is unbounded.";
137 break;
138 default:
139 LOG(ERROR) << "Solving resulted in an error.";
140 return false;
141 }
142 if (use_integers) {
143 for (const SubsetIndex subset : focus) {
144 choices[subset] = (vars[subset]->solution_value() > 0.9);
145 }
146 inv_->LoadSolution(choices);
147 } else {
148 lower_bound_ = solver.Objective().Value();
149 }
150 return true;
151}
152
153} // namespace operations_research
A class to express a linear objective.
void SetCoefficient(const MPVariable *var, double coeff)
void SetMinimization()
Sets the optimization direction to minimize.
MPVariable * MakeVar(double lb, double ub, bool integer, const std::string &name)
@ FEASIBLE
feasible, or stopped by limit.
@ INFEASIBLE
proven infeasible.
ResultStatus Solve()
Solves the problem using the default parameter values.
const MPObjective & Objective() const
@ SCIP_MIXED_INTEGER_PROGRAMMING
Recommended default value for MIP problems.
@ GUROBI_LINEAR_PROGRAMMING
Commercial software (need license).
MPObjective * MutableObjective()
Returns the mutable objective object.
void SuppressOutput()
Suppresses solver logging.
MPConstraint * MakeRowConstraint(double lb, double ub)
void set_time_limit(int64_t time_limit_milliseconds)
void LoadSolution(const SubsetBoolVector &solution)
Loads the solution and recomputes the data in the invariant.
const SubsetBoolVector & is_selected() const
Returns the subset assignment vector.
SetCoverModel * model() const
Returns the weighted set covering model to which the state applies.
const ElementToIntVector & coverage() const
Returns vector containing number of subsets covering each element.
ElementToIntVector ComputeCoverageInFocus(absl::Span< const SubsetIndex > focus) const
bool NextSolution(bool use_integers, double time_limit_in_seconds)
Main class for describing a weighted set-covering problem.
std::vector< SubsetIndex > all_subsets() const
Returns the list of indices for all the subsets in the model.
int64_t b
Definition table.cc:45
int64_t a
Definition table.cc:44
GRBmodel * model
MPSolver::OptimizationProblemType problem_type
In SWIG mode, we don't want anything besides these top-level includes.
util_intops::StrongVector< ElementIndex, BaseInt, IntAllocator > ElementToIntVector
int64_t delta
Definition resource.cc:1709