Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
glop_interface.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
14#if defined(USE_GLOP)
15
16#include <atomic>
17#include <cstdint>
18#include <memory>
19#include <string>
20#include <utility>
21#include <vector>
22
23#include "absl/base/attributes.h"
24#include "absl/log/check.h"
27#include "ortools/glop/parameters.pb.h"
36namespace operations_research {
37
38namespace {} // Anonymous namespace
39
41 public:
42 explicit GLOPInterface(MPSolver* solver);
43 ~GLOPInterface() override;
44
45 // ----- Solve -----
46 MPSolver::ResultStatus Solve(const MPSolverParameters& param) override;
47 bool InterruptSolve() override;
48
49 // ----- Directly solve proto is supported ---
50 bool SupportsDirectlySolveProto(std::atomic<bool>* interrupt) const override {
51 return true;
52 }
54 std::atomic<bool>* interrupt) override {
55 return GlopSolveProto(std::move(request), interrupt);
56 }
57
58 // ----- Model modifications and extraction -----
59 void Reset() override;
60 void SetOptimizationDirection(bool maximize) override;
61 void SetVariableBounds(int index, double lb, double ub) override;
62 void SetVariableInteger(int index, bool integer) override;
63 void SetConstraintBounds(int index, double lb, double ub) override;
64 void AddRowConstraint(MPConstraint* ct) override;
65 void AddVariable(MPVariable* var) override;
66 void SetCoefficient(MPConstraint* constraint, const MPVariable* variable,
67 double new_value, double old_value) override;
68 void ClearConstraint(MPConstraint* constraint) override;
69 void SetObjectiveCoefficient(const MPVariable* variable,
70 double coefficient) override;
71 void SetObjectiveOffset(double value) override;
72 void ClearObjective() override;
73
74 // ------ Query statistics on the solution and the solve ------
75 int64_t iterations() const override;
76 int64_t nodes() const override;
78 MPSolver::BasisStatus column_status(int variable_index) const override;
79
80 // ----- Misc -----
81 bool IsContinuous() const override;
82 bool IsLP() const override;
83 bool IsMIP() const override;
84
85 std::string SolverVersion() const override;
86 void* underlying_solver() override;
87
88 void ExtractNewVariables() override;
89 void ExtractNewConstraints() override;
90 void ExtractObjective() override;
91
93 const std::vector<MPSolver::BasisStatus>& variable_statuses,
94 const std::vector<MPSolver::BasisStatus>& constraint_statuses) override;
95
96 void SetParameters(const MPSolverParameters& param) override;
97 void SetRelativeMipGap(double value) override;
98 void SetPrimalTolerance(double value) override;
99 void SetDualTolerance(double value) override;
100 void SetPresolveMode(int value) override;
101 void SetScalingMode(int value) override;
102 void SetLpAlgorithm(int value) override;
104 const std::string& parameters) override;
105
106 private:
107 void NonIncrementalChange();
108
109 glop::LinearProgram linear_program_;
110 glop::LPSolver lp_solver_;
111 std::vector<MPSolver::BasisStatus> column_status_;
112 std::vector<MPSolver::BasisStatus> row_status_;
113 glop::GlopParameters parameters_;
114 std::atomic<bool> interrupt_solver_;
115};
116
118 : MPSolverInterface(solver),
119 linear_program_(),
120 lp_solver_(),
121 column_status_(),
122 row_status_(),
123 parameters_(),
124 interrupt_solver_(false) {}
125
127
129 // Re-extract the problem from scratch. We don't support modifying the
130 // LinearProgram in sync with changes done in the MPSolver.
132 linear_program_.Clear();
133 interrupt_solver_ = false;
134 ExtractModel();
135 SetParameters(param);
136
137 linear_program_.SetMaximizationProblem(maximize_);
138 linear_program_.CleanUp();
139
140 // Time limit.
141 if (solver_->time_limit()) {
142 VLOG(1) << "Setting time limit = " << solver_->time_limit() << " ms.";
143 parameters_.set_max_time_in_seconds(
144 static_cast<double>(solver_->time_limit()) / 1000.0);
145 }
146
148 solver_->solver_specific_parameter_string_);
149 lp_solver_.SetParameters(parameters_);
150 std::unique_ptr<TimeLimit> time_limit =
152 time_limit->RegisterExternalBooleanAsLimit(&interrupt_solver_);
154 lp_solver_.SolveWithTimeLimit(linear_program_, time_limit.get());
155
156 // The solution must be marked as synchronized even when no solution exists.
159 objective_value_ = lp_solver_.GetObjectiveValue();
160
161 const int num_vars = solver_->variables_.size();
162 column_status_.resize(num_vars, MPSolver::FREE);
163 for (int var_id = 0; var_id < num_vars; ++var_id) {
164 MPVariable* const var = solver_->variables_[var_id];
165 const glop::ColIndex lp_solver_var_id(var->index());
166
167 const glop::Fractional solution_value =
168 lp_solver_.variable_values()[lp_solver_var_id];
169 var->set_solution_value(static_cast<double>(solution_value));
170
171 const glop::Fractional reduced_cost =
172 lp_solver_.reduced_costs()[lp_solver_var_id];
173 var->set_reduced_cost(static_cast<double>(reduced_cost));
174
175 const glop::VariableStatus variable_status =
176 lp_solver_.variable_statuses()[lp_solver_var_id];
177 column_status_.at(var_id) = GlopToMPSolverVariableStatus(variable_status);
178 }
179
180 const int num_constraints = solver_->constraints_.size();
181 row_status_.resize(num_constraints, MPSolver::FREE);
182 for (int ct_id = 0; ct_id < num_constraints; ++ct_id) {
183 MPConstraint* const ct = solver_->constraints_[ct_id];
184 const glop::RowIndex lp_solver_ct_id(ct->index());
185
186 const glop::Fractional dual_value =
187 lp_solver_.dual_values()[lp_solver_ct_id];
188 ct->set_dual_value(static_cast<double>(dual_value));
189
190 const glop::ConstraintStatus constraint_status =
191 lp_solver_.constraint_statuses()[lp_solver_ct_id];
192 row_status_.at(ct_id) = GlopToMPSolverConstraintStatus(constraint_status);
193 }
194
195 return result_status_;
196}
197
199 interrupt_solver_ = true;
200 return true;
201}
202
204 // Ignore any incremental info for the next solve. Note that the parameters
205 // will not be reset as we re-read them on each Solve().
206 lp_solver_.Clear();
207}
208
210 NonIncrementalChange();
211}
212
213void GLOPInterface::SetVariableBounds(int index, double lb, double ub) {
214 NonIncrementalChange();
215}
216
218 LOG(WARNING) << "Glop doesn't deal with integer variables.";
219}
220
221void GLOPInterface::SetConstraintBounds(int index, double lb, double ub) {
222 NonIncrementalChange();
223}
224
226 NonIncrementalChange();
227}
228
230 NonIncrementalChange();
231}
232
234 const MPVariable* const variable,
235 double new_value, double old_value) {
236 NonIncrementalChange();
237}
238
240 NonIncrementalChange();
241}
242
244 double coefficient) {
245 NonIncrementalChange();
246}
247
248void GLOPInterface::SetObjectiveOffset(double value) { NonIncrementalChange(); }
249
250void GLOPInterface::ClearObjective() { NonIncrementalChange(); }
251
253 return lp_solver_.GetNumberOfSimplexIterations();
254}
255
256int64_t GLOPInterface::nodes() const {
257 LOG(DFATAL) << "Number of nodes only available for discrete problems";
259}
260
264
266 return column_status_[variable_index];
267}
268
269bool GLOPInterface::IsContinuous() const { return true; }
270
271bool GLOPInterface::IsLP() const { return true; }
272
273bool GLOPInterface::IsMIP() const { return false; }
274
275std::string GLOPInterface::SolverVersion() const {
277}
278
279void* GLOPInterface::underlying_solver() { return &lp_solver_; }
280
282 DCHECK_EQ(0, last_variable_index_);
283 DCHECK_EQ(0, last_constraint_index_);
284
285 const glop::ColIndex num_cols(solver_->variables_.size());
286 for (glop::ColIndex col(last_variable_index_); col < num_cols; ++col) {
287 MPVariable* const var = solver_->variables_[col.value()];
288 const glop::ColIndex new_col = linear_program_.CreateNewVariable();
289 DCHECK_EQ(new_col, col);
290 set_variable_as_extracted(col.value(), true);
291 linear_program_.SetVariableBounds(col, var->lb(), var->ub());
292 }
293}
294
296 DCHECK_EQ(0, last_constraint_index_);
297
298 const glop::RowIndex num_rows(solver_->constraints_.size());
299 for (glop::RowIndex row(0); row < num_rows; ++row) {
300 MPConstraint* const ct = solver_->constraints_[row.value()];
301 set_constraint_as_extracted(row.value(), true);
302
303 const double lb = ct->lb();
304 const double ub = ct->ub();
305 const glop::RowIndex new_row = linear_program_.CreateNewConstraint();
306 DCHECK_EQ(new_row, row);
307 linear_program_.SetConstraintBounds(row, lb, ub);
308
309 for (const auto& entry : ct->coefficients_) {
310 const int var_index = entry.first->index();
312 const glop::ColIndex col(var_index);
313 const double coeff = entry.second;
314 linear_program_.SetCoefficient(row, col, coeff);
315 }
316 }
317}
318
320 linear_program_.SetObjectiveOffset(solver_->Objective().offset());
321 for (const auto& entry : solver_->objective_->coefficients_) {
322 const int var_index = entry.first->index();
323 const glop::ColIndex col(var_index);
324 const double coeff = entry.second;
325 linear_program_.SetObjectiveCoefficient(col, coeff);
326 }
327}
328
330 const std::vector<MPSolver::BasisStatus>& variable_statuses,
331 const std::vector<MPSolver::BasisStatus>& constraint_statuses) {
332 glop::VariableStatusRow glop_variable_statuses;
333 glop::ConstraintStatusColumn glop_constraint_statuses;
334 for (const MPSolver::BasisStatus& status : variable_statuses) {
335 glop_variable_statuses.push_back(MPSolverToGlopVariableStatus(status));
336 }
337 for (const MPSolver::BasisStatus& status : constraint_statuses) {
338 glop_constraint_statuses.push_back(MPSolverToGlopConstraintStatus(status));
339 }
340 lp_solver_.SetInitialBasis(glop_variable_statuses, glop_constraint_statuses);
341}
342
344 parameters_.Clear();
345 parameters_.set_log_search_progress(!quiet_);
346 SetCommonParameters(param);
348}
349
356
358 // TODO(user): Modify parameters_ with the correct value.
359 // The problem is that this is set by default by the wrapper to 1e-7 and for
360 // now we want to use higher default tolerances in Glop.
363 value);
364 }
365}
366
368 // TODO(user): Modify parameters_ with the correct value.
369 // The problem is that this is set by default by the wrapper to 1e-7 and for
370 // now we want to use higher default tolerances in Glop.
373 }
374}
375
377 switch (value) {
379 parameters_.set_use_preprocessing(false);
380 break;
382 parameters_.set_use_preprocessing(true);
383 break;
384 default:
387 }
388 }
389}
390
392 switch (value) {
394 parameters_.set_use_scaling(false);
395 break;
397 parameters_.set_use_scaling(true);
398 break;
399 default:
402 }
403 }
404}
405
407 switch (value) {
409 parameters_.set_use_dual_simplex(true);
410 break;
412 parameters_.set_use_dual_simplex(false);
413 break;
414 default:
417 value);
418 }
419 }
420}
421
423 const std::string& parameters) {
424 // NOTE(user): Android build uses protocol buffers in lite mode, and
425 // parsing data from text format is not supported there. To allow solver
426 // specific parameters from string on Android, we first need to switch to
427 // non-lite version of protocol buffers.
429 lp_solver_.SetParameters(parameters_);
430 return true;
431 }
432 return false;
433}
434
435void GLOPInterface::NonIncrementalChange() {
436 // The current implementation is not incremental.
438}
439
440// Register GLOP in the global linear solver factory.
442 return new GLOPInterface(solver);
443}
444
445} // namespace operations_research
446#endif // #if defined(USE_GLOP)
void SetParameters(const MPSolverParameters &param) override
Sets all parameters in the underlying solver.
void SetRelativeMipGap(double value) override
Sets each parameter in the underlying solver.
void ExtractNewConstraints() override
Extracts the constraints that have not been extracted yet.
void SetCoefficient(MPConstraint *constraint, const MPVariable *variable, double new_value, double old_value) override
Changes a coefficient in a constraint.
bool IsMIP() const override
Returns true if the problem is discrete and linear.
void ExtractNewVariables() override
Extracts the variables that have not been extracted yet.
bool IsContinuous() const override
--— Misc --—
void SetVariableInteger(int index, bool integer) override
Modifies integrality of an extracted variable.
bool SetSolverSpecificParametersAsString(const std::string &parameters) override
MPSolutionResponse DirectlySolveProto(LazyMutableCopy< MPModelRequest > request, std::atomic< bool > *interrupt) override
void SetObjectiveOffset(double value) override
Changes the constant term in the linear objective.
void Reset() override
--— Model modifications and extraction --—
void ClearConstraint(MPConstraint *constraint) override
Clears a constraint from all its terms.
void SetPrimalTolerance(double value) override
void * underlying_solver() override
Returns the underlying solver.
void AddRowConstraint(MPConstraint *ct) override
Adds a linear constraint.
void ExtractObjective() override
Extracts the objective.
void SetObjectiveCoefficient(const MPVariable *variable, double coefficient) override
Changes a coefficient in the linear objective.
MPSolver::ResultStatus Solve(const MPSolverParameters &param) override
--— Solve --—
void ClearObjective() override
Clears the objective from all its terms.
MPSolver::BasisStatus row_status(int constraint_index) const override
Returns the basis status of a row.
int64_t iterations() const override
---— Query statistics on the solution and the solve ---—
MPSolver::BasisStatus column_status(int variable_index) const override
Returns the basis status of a constraint.
void SetConstraintBounds(int index, double lb, double ub) override
Modify bounds of an extracted variable.
bool IsLP() const override
Returns true if the problem is continuous and linear.
void SetOptimizationDirection(bool maximize) override
Sets the optimization direction (min/max).
void SetDualTolerance(double value) override
void SetStartingLpBasis(const std::vector< MPSolver::BasisStatus > &variable_statuses, const std::vector< MPSolver::BasisStatus > &constraint_statuses) override
See MPSolver::SetStartingLpBasis().
void SetVariableBounds(int index, double lb, double ub) override
Modifies bounds of an extracted variable.
std::string SolverVersion() const override
Returns a string describing the underlying solver and its version.
void SetPresolveMode(int value) override
void AddVariable(MPVariable *var) override
Add a variable.
void SetScalingMode(int value) override
Sets the scaling mode.
void SetLpAlgorithm(int value) override
bool SupportsDirectlySolveProto(std::atomic< bool > *interrupt) const override
--— Directly solve proto is supported —
double offset() const
Gets the constant term in the objective.
void set_variable_as_extracted(int var_index, bool extracted)
void set_constraint_as_extracted(int ct_index, bool extracted)
void ResetExtractionInformation()
Resets the extraction information.
int last_variable_index_
Index in MPSolver::constraints_ of last variable extracted.
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
Sets a supported integer parameter to an unsupported value.
int last_constraint_index_
Index in MPSolver::variables_ of last constraint extracted.
bool variable_is_extracted(int var_index) const
static constexpr int64_t kUnknownNumberOfNodes
void ExtractModel()
Extracts model stored in MPSolver.
double objective_value_
The value of the objective function.
void SetDoubleParamToUnsupportedValue(MPSolverParameters::DoubleParam param, double value)
Sets a supported double parameter to an unsupported value.
bool maximize_
Optimization direction.
bool quiet_
Boolean indicator for the verbosity of the solver output.
void SetCommonParameters(const MPSolverParameters &param)
Sets parameters common to LP and MIP in the underlying solver.
SynchronizationStatus sync_status_
Indicates whether the model and the solution are synchronized.
@ DUAL_TOLERANCE
Advanced usage: tolerance for dual feasibility of basic solutions.
@ RELATIVE_MIP_GAP
Limit for relative MIP gap.
@ PRESOLVE
Advanced usage: presolve mode.
@ LP_ALGORITHM
Algorithm to solve linear programs.
@ SCALING
Advanced usage: enable or disable matrix scaling.
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
const MPObjective & Objective() const
bool SetSolverSpecificParametersAsString(const std::string &parameters)
The class for variables of a Mathematical Programming (MP) model.
static std::unique_ptr< TimeLimit > FromParameters(const Parameters &parameters)
Definition time_limit.h:140
A full-fledged linear programming solver.
Definition lp_solver.h:31
const GlopParameters & GetParameters() const
Definition lp_solver.cc:138
static std::string GlopVersion()
Returns a string that describes the version of the solver.
Definition lp_solver.cc:122
const DenseRow & reduced_costs() const
Definition lp_solver.h:110
void SetInitialBasis(const VariableStatusRow &variable_statuses, const ConstraintStatusColumn &constraint_statuses)
Definition lp_solver.cc:280
int GetNumberOfSimplexIterations() const
Returns the number of simplex iterations used by the last Solve().
Definition lp_solver.cc:543
Fractional GetObjectiveValue() const
Returns the objective value of the solution with its offset and scaling.
Definition lp_solver.cc:527
const ConstraintStatusColumn & constraint_statuses() const
Definition lp_solver.h:125
const VariableStatusRow & variable_statuses() const
Definition lp_solver.h:111
const DenseRow & variable_values() const
Accessors to information related to variables.
Definition lp_solver.h:109
ABSL_MUST_USE_RESULT ProblemStatus SolveWithTimeLimit(const LinearProgram &lp, TimeLimit *time_limit)
Definition lp_solver.cc:150
const DenseColumn & dual_values() const
Definition lp_solver.h:121
void SetParameters(const GlopParameters &parameters)
Definition lp_solver.cc:126
void Clear()
Clears, i.e. reset the object to its initial value.
Definition lp_data.cc:143
void SetObjectiveOffset(Fractional objective_offset)
Definition lp_data.cc:340
void SetObjectiveCoefficient(ColIndex col, Fractional value)
Definition lp_data.cc:335
void SetVariableBounds(ColIndex col, Fractional lower_bound, Fractional upper_bound)
Definition lp_data.cc:258
void SetConstraintBounds(RowIndex row, Fractional lower_bound, Fractional upper_bound)
Definition lp_data.cc:318
void SetCoefficient(RowIndex row, ColIndex col, Fractional value)
Defines the coefficient for col / row.
Definition lp_data.cc:326
void SetMaximizationProblem(bool maximize)
Definition lp_data.cc:352
void push_back(const value_type &val)
SatParameters parameters
const Constraint * ct
int64_t value
IntVar * var
absl::Status status
Definition g_gurobi.cc:44
int constraint_index
time_limit
Definition solve.cc:22
int index
ColIndex col
Definition markowitz.cc:187
RowIndex row
Definition markowitz.cc:186
ProblemStatus
Different statuses for a given problem.
Definition lp_types.h:107
In SWIG mode, we don't want anything besides these top-level includes.
MPSolver::ResultStatus GlopToMPSolverResultStatus(glop::ProblemStatus s)
Definition glop_utils.cc:18
glop::VariableStatus MPSolverToGlopVariableStatus(MPSolver::BasisStatus s)
Definition glop_utils.cc:74
glop::ConstraintStatus MPSolverToGlopConstraintStatus(MPSolver::BasisStatus s)
MPSolutionResponse GlopSolveProto(LazyMutableCopy< MPModelRequest > request, std::atomic< bool > *interrupt_solve, std::function< void(const std::string &)> logging_callback)
bool ProtobufTextFormatMergeFromString(absl::string_view proto_text_string, ProtoType *proto)
Definition proto_utils.h:66
MPSolver::BasisStatus GlopToMPSolverConstraintStatus(glop::ConstraintStatus s)
Definition glop_utils.cc:91
MPSolver::BasisStatus GlopToMPSolverVariableStatus(glop::VariableStatus s)
Definition glop_utils.cc:57
MPSolverInterface * BuildGLOPInterface(MPSolver *const solver)
Register GLOP in the global linear solver factory.
int64_t coefficient
int var_index
Definition search.cc:3268