Google OR-Tools: ortools/linear_solver/cbc_interface.cc Source File
21#include "absl/base/attributes.h"
22#include "absl/status/status.h"
23#include "absl/strings/str_format.h"
34#include "OsiClpSolverInterface.hpp"
47 void Reset() override;
69 bool IsLP() const override { return false; }
70 bool IsMIP() const override { return true; }
73 void SetVariableBounds(int var_index, double lb, double ub) override;
105 int64_t nodes() const override;
122 std::string SolverVersion() const override { return "Cbc " CBC_VERSION; }
127 void* underlying_solver() override { return reinterpret_cast<void*>(&osi_); }
132 void ResetBestObjectiveBound();
137 void SetRelativeMipGap(double value) override;
138 void SetPrimalTolerance(double value) override;
139 void SetDualTolerance(double value) override;
140 void SetPresolveMode(int value) override;
141 void SetScalingMode(int value) override;
142 void SetLpAlgorithm(int value) override;
161 osi_.setStrParam(OsiProbName, solver_->name_);
175void CBCInterface::ResetBestObjectiveBound() {
194int MPSolverVarIndexToCbcVarIndex(int var_index) { return var_index + 1; }
211 osi_.setInteger(MPSolverVarIndexToCbcVarIndex(var_index));
213 osi_.setContinuous(MPSolverVarIndexToCbcVarIndex(var_index));
243 if (!solver_->variables_.empty()) {
244 solver_->LookupVariableOrNull(solver_->variables_[0]->name());
246 if (!solver_->constraints_.empty()) {
247 solver_->LookupConstraintOrNull(solver_->constraints_[0]->name());
261 if (solver_->variables_.empty() && solver_->constraints_.empty()) {
276 build.addColumn(0, nullptr, nullptr, 1.0, 1.0,
277 solver_->Objective().offset(), "dummy", false);
278 const int nb_vars = solver_->variables_.size();
279 for (int i = 0; i < nb_vars; ++i) {
282 const double obj_coeff = solver_->Objective().GetCoefficient(var);
283 if (var->name().empty()) {
284 build.addColumn(0, nullptr, nullptr, var->lb(), var->ub(), obj_coeff,
285 nullptr, var->integer());
287 build.addColumn(0, nullptr, nullptr, var->lb(), var->ub(), obj_coeff,
294 for (int i = 0; i < solver_->constraints_.size(); ++i) {
297 if (ct->coefficients_.size() > max_row_length) {
298 max_row_length = ct->coefficients_.size();
301 std::unique_ptr<int[]> indices(new int[max_row_length]);
302 std::unique_ptr<double[]> coefs(new double[max_row_length]);
304 for (int i = 0; i < solver_->constraints_.size(); ++i) {
306 const int size = ct->coefficients_.size();
308 for (const auto& entry : ct->coefficients_) {
309 const int index = MPSolverVarIndexToCbcVarIndex(entry.first->index());
314 if (ct->name().empty()) {
315 build.addRow(size, indices.get(), coefs.get(), ct->lb(), ct->ub());
317 build.addRow(size, indices.get(), coefs.get(), ct->lb(), ct->ub(),
318 ct->name().c_str());
321 osi_.loadFromCoinModel(build);
334 osi_.setObjSense(maximize_ ? -1 : 1);
337 VLOG(1) << absl::StrFormat("Model built in %.3f seconds.", timer.Get());
339 ResetBestObjectiveBound();
345 CoinMessageHandler message_handler;
346 model.passInMessageHandler(&message_handler);
348 message_handler.setLogLevel(0, 0);
349 message_handler.setLogLevel(1, 0);
350 message_handler.setLogLevel(2, 0);
351 message_handler.setLogLevel(3, 0);
353 message_handler.setLogLevel(0, 1);
354 message_handler.setLogLevel(1, 1);
355 message_handler.setLogLevel(2, 1);
356 message_handler.setLogLevel(3, 1);
360 if (solver_->time_limit() != 0) {
361 VLOG(1) << "Setting time limit = " << solver_->time_limit() << " ms.";
362 model.setMaximumSeconds(solver_->time_limit_in_secs());
377 model.setAllowableFractionGap(relative_mip_gap_);
381 ? callCbc("-solve ", model)
382 : callCbc(absl::StrCat("-threads ", num_threads_, " -solve "), model);
383 const int kBadReturnStatus = 777;
384 CHECK_NE(kBadReturnStatus, return_status);
387 VLOG(1) << absl::StrFormat("Solved in %.3f seconds.", timer.Get());
390 int tmp_status = model.status();
392 VLOG(1) << "cbc result status: " << tmp_status;
409 if (model.isProvenOptimal()) {
411 } else if (model.isContinuousUnbounded()) {
413 } else if (model.isProvenInfeasible()) {
415 } else if (model.isAbandoned()) {
422 if (model.bestSolution() != nullptr) {
438 const double* const values = model.bestSolution();
441 for (int i = 0; i < solver_->variables_.size(); ++i) {
443 const int var_index = MPSolverVarIndexToCbcVarIndex(var->index());
444 const double val = values[var_index];
446 VLOG(3) << var->name() << "=" << val;
449 VLOG(1) << "No feasible solution found.";
453 iterations_ = model.getIterationCount();
488void CBCInterface::SetRelativeMipGap(double value) {
489 relative_mip_gap_ = value;
492void CBCInterface::SetPrimalTolerance(double value) {
500void CBCInterface::SetDualTolerance(double value) {
508void CBCInterface::SetPresolveMode(int value) {
520void CBCInterface::SetScalingMode(int value) {
524void CBCInterface::SetLpAlgorithm(int value) {
531const void* const kRegisterCBC ABSL_ATTRIBUTE_UNUSED = [] {
Definition cbc_interface.cc:40
void SetConstraintBounds(int row_index, double lb, double ub) override
Definition cbc_interface.cc:220
MPSolver::BasisStatus row_status(int constraint_index) const override
Definition cbc_interface.cc:108
void AddRowConstraint(MPConstraint *ct) override
Definition cbc_interface.cc:229
void ClearObjective() override
Definition cbc_interface.cc:100
void ClearConstraint(MPConstraint *const constraint) override
Definition cbc_interface.cc:88
CBCInterface(MPSolver *solver)
Definition cbc_interface.cc:156
void ExtractNewConstraints() override
Definition cbc_interface.cc:119
void SetVariableBounds(int var_index, double lb, double ub) override
Definition cbc_interface.cc:197
void ExtractNewVariables() override
Definition cbc_interface.cc:118
absl::Status SetNumThreads(int num_threads) override
Definition cbc_interface.cc:54
int64_t nodes() const override
Definition cbc_interface.cc:470
void ExtractObjective() override
Definition cbc_interface.cc:120
void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient) override
Definition cbc_interface.cc:93
void SetOptimizationDirection(bool maximize) override
Definition cbc_interface.cc:183
MPSolver::ResultStatus Solve(const MPSolverParameters ¶m) override
Definition cbc_interface.cc:239
void AddVariable(MPVariable *var) override
Definition cbc_interface.cc:233
MPSolver::BasisStatus column_status(int variable_index) const override
Definition cbc_interface.cc:113
bool IsLP() const override
Definition cbc_interface.cc:69
void Reset() override
Definition cbc_interface.cc:168
int64_t iterations() const override
Definition cbc_interface.cc:465
bool IsMIP() const override
Definition cbc_interface.cc:70
void SetVariableInteger(int var_index, bool integer) override
Definition cbc_interface.cc:206
~CBCInterface() override
Definition cbc_interface.cc:165
std::string SolverVersion() const override
Definition cbc_interface.cc:122
void SetObjectiveOffset(double value) override
Definition cbc_interface.cc:98
bool IsContinuous() const override
Definition cbc_interface.cc:68
void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value) override
Definition cbc_interface.cc:82
virtual void ExtractModel()
Definition cbc_interface.cc:65
void * underlying_solver() override
Definition cbc_interface.cc:127
double lb() const
Returns the lower bound.
double ub() const
Returns the upper bound.
const std::string & name() const
Returns the name of the constraint.
static MPSolverInterfaceFactoryRepository * GetInstance()
void Register(MPSolverInterfaceFactory factory, MPSolver::OptimizationProblemType problem_type, std::function< bool()> is_runtime_ready={})
void set_variable_as_extracted(int var_index, bool extracted)
bool CheckSolutionIsSynchronized() const
static constexpr int64_t kUnknownNumberOfIterations
friend class MPConstraint
void InvalidateSolutionSynchronization()
void set_constraint_as_extracted(int ct_index, bool extracted)
void ResetExtractionInformation()
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
void SetUnsupportedDoubleParam(MPSolverParameters::DoubleParam param)
static constexpr int64_t kUnknownNumberOfNodes
double best_objective_bound_
void SetMIPParameters(const MPSolverParameters ¶m)
MPSolverInterface(MPSolver *solver)
void SetCommonParameters(const MPSolverParameters ¶m)
MPSolver::ResultStatus result_status_
SynchronizationStatus sync_status_
static const double kDefaultDualTolerance
static const double kDefaultPrimalTolerance
@ DUAL_TOLERANCE
Advanced usage: tolerance for dual feasibility of basic solutions.
@ PRESOLVE_ON
Presolve is on.
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
@ PRESOLVE
Advanced usage: presolve mode.
@ LP_ALGORITHM
Algorithm to solve linear programs.
@ SCALING
Advanced usage: enable or disable matrix scaling.
@ INCREMENTALITY_OFF
Start solve from scratch.
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
@ FEASIBLE
feasible, or stopped by limit.
@ NOT_SOLVED
not been solved yet.
@ INFEASIBLE
proven infeasible.
@ UNBOUNDED
proven unbounded.
@ ABNORMAL
abnormal, i.e., error of some kind.
@ CBC_MIXED_INTEGER_PROGRAMMING
The class for variables of a Mathematical Programming (MP) model.
bool integer() const
Returns the integrality requirement of the variable.
double lb() const
Returns the lower bound.
double ub() const
Returns the upper bound.
const std::string & name() const
Returns the name of the variable.
void set_solution_value(double value)
int index() const
Returns the index of the variable in the MPSolver::variables_.