23#include "absl/base/attributes.h"
24#include "absl/status/status.h"
25#include "absl/strings/str_format.h"
38#include "CbcMessage.hpp"
39#include "CbcModel.hpp"
40#include "CoinModel.hpp"
41#include "OsiClpSolverInterface.hpp"
54 void Reset()
override;
63 num_threads_ = num_threads;
64 return absl::OkStatus();
76 bool IsLP()
const override {
return false; }
77 bool IsMIP()
const override {
return true; }
90 const MPVariable*
const variable,
double new_value,
91 double old_value)
override {
112 int64_t
nodes()
const override;
116 LOG(
FATAL) <<
"Basis status only available for continuous problems";
121 LOG(
FATAL) <<
"Basis status only available for continuous problems";
139 void ResetBestObjectiveBound();
144 void SetRelativeMipGap(
double value)
override;
145 void SetPrimalTolerance(
double value)
override;
146 void SetDualTolerance(
double value)
override;
147 void SetPresolveMode(
int value)
override;
148 void SetScalingMode(
int value)
override;
149 void SetLpAlgorithm(
int value)
override;
151 OsiClpSolverInterface osi_;
156 double relative_mip_gap_;
157 int num_threads_ = 1;
168 osi_.setStrParam(OsiProbName,
solver_->name_);
178 osi_.setStrParam(OsiProbName,
solver_->name_);
182void CBCInterface::ResetBestObjectiveBound() {
193 osi_.setObjSense(maximize ? -1 : 1);
201int MPSolverVarIndexToCbcVarIndex(
int var_index) {
return var_index + 1; }
207 osi_.setColBounds(MPSolverVarIndexToCbcVarIndex(var_index), lb, ub);
218 osi_.setInteger(MPSolverVarIndexToCbcVarIndex(var_index));
220 osi_.setContinuous(MPSolverVarIndexToCbcVarIndex(var_index));
230 osi_.setRowBounds(
index, lb, ub);
250 if (!
solver_->variables_.empty()) {
253 if (!
solver_->constraints_.empty()) {
268 if (
solver_->variables_.empty() &&
solver_->constraints_.empty()) {
283 build.addColumn(0,
nullptr,
nullptr, 1.0, 1.0,
285 const int nb_vars =
solver_->variables_.size();
286 for (
int i = 0; i < nb_vars; ++i) {
290 if (
var->name().empty()) {
291 build.addColumn(0,
nullptr,
nullptr,
var->lb(),
var->ub(), obj_coeff,
292 nullptr,
var->integer());
294 build.addColumn(0,
nullptr,
nullptr,
var->lb(),
var->ub(), obj_coeff,
295 var->name().c_str(),
var->integer());
300 int max_row_length = 0;
301 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
304 if (
ct->coefficients_.size() > max_row_length) {
305 max_row_length =
ct->coefficients_.size();
308 std::unique_ptr<int[]> indices(
new int[max_row_length]);
309 std::unique_ptr<double[]> coefs(
new double[max_row_length]);
311 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
313 const int size =
ct->coefficients_.size();
315 for (
const auto& entry :
ct->coefficients_) {
316 const int index = MPSolverVarIndexToCbcVarIndex(entry.first->index());
318 coefs[j] = entry.second;
321 if (
ct->name().empty()) {
322 build.addRow(size, indices.get(), coefs.get(),
ct->lb(),
ct->ub());
324 build.addRow(size, indices.get(), coefs.get(),
ct->lb(),
ct->ub(),
328 osi_.loadFromCoinModel(build);
344 VLOG(1) << absl::StrFormat(
"Model built in %.3f seconds.", timer.
Get());
346 ResetBestObjectiveBound();
349 CbcModel
model(osi_);
352 CoinMessageHandler message_handler;
353 model.passInMessageHandler(&message_handler);
355 message_handler.setLogLevel(0, 0);
356 message_handler.setLogLevel(1, 0);
357 message_handler.setLogLevel(2, 0);
358 message_handler.setLogLevel(3, 0);
360 message_handler.setLogLevel(0, 1);
361 message_handler.setLogLevel(1, 1);
362 message_handler.setLogLevel(2, 1);
363 message_handler.setLogLevel(3, 1);
378 SetParameters(param);
381 model.setTypePresolve(0);
384 model.setAllowableFractionGap(relative_mip_gap_);
388 ? callCbc(
"-solve ",
model)
389 : callCbc(absl::StrCat(
"-threads ", num_threads_,
" -solve "),
model);
390 const int kBadReturnStatus = 777;
391 CHECK_NE(kBadReturnStatus, return_status);
394 VLOG(1) << absl::StrFormat(
"Solved in %.3f seconds.", timer.
Get());
397 int tmp_status =
model.status();
399 VLOG(1) <<
"cbc result status: " << tmp_status;
412 switch (tmp_status) {
416 if (
model.isProvenOptimal()) {
418 }
else if (
model.isContinuousUnbounded()) {
420 }
else if (
model.isProvenInfeasible()) {
422 }
else if (
model.isAbandoned()) {
429 if (
model.bestSolution() !=
nullptr) {
445 const double*
const values =
model.bestSolution();
446 if (values !=
nullptr) {
448 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
450 const int var_index = MPSolverVarIndexToCbcVarIndex(
var->index());
451 const double val = values[var_index];
452 var->set_solution_value(val);
453 VLOG(3) <<
var->name() <<
"=" << val;
456 VLOG(1) <<
"No feasible solution found.";
460 iterations_ =
model.getIterationCount();
461 nodes_ =
model.getNodeCount();
495void CBCInterface::SetRelativeMipGap(
double value) {
496 relative_mip_gap_ =
value;
499void CBCInterface::SetPrimalTolerance(
double value) {
507void CBCInterface::SetDualTolerance(
double value) {
515void CBCInterface::SetPresolveMode(
int value) {
527void CBCInterface::SetScalingMode(
int value) {
531void CBCInterface::SetLpAlgorithm(
int value) {
#define CHECK_GE(val1, val2)
#define CHECK_NE(val1, val2)
#define VLOG(verboselevel)
void AddRowConstraint(MPConstraint *const ct) override
void ExtractObjective() override
void * underlying_solver() override
bool IsContinuous() const override
void SetConstraintBounds(int row_index, double lb, double ub) override
MPSolver::ResultStatus Solve(const MPSolverParameters ¶m) override
void ClearConstraint(MPConstraint *const constraint) override
void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient) override
void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value) override
MPSolver::BasisStatus row_status(int constraint_index) const override
void SetVariableInteger(int var_index, bool integer) override
void SetObjectiveOffset(double value) override
void ExtractNewConstraints() override
std::string SolverVersion() const override
absl::Status SetNumThreads(int num_threads) override
void AddVariable(MPVariable *const var) override
void ExtractNewVariables() override
CBCInterface(MPSolver *const solver)
int64_t nodes() const override
void SetVariableBounds(int var_index, double lb, double ub) override
bool IsLP() const override
bool IsMIP() const override
int64_t iterations() const override
virtual void ExtractModel()
void SetOptimizationDirection(bool maximize) override
MPSolver::BasisStatus column_status(int variable_index) const override
void ClearObjective() override
The class for constraints of a Mathematical Programming (MP) model.
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable in the objective.
double offset() const
Gets the constant term in the objective.
This mathematical programming (MP) solver class is the main class though which users build and solve ...
MPVariable * LookupVariableOrNull(const std::string &var_name) const
Looks up a variable by name, and returns nullptr if it does not exist.
ResultStatus
The status of solving the problem.
@ 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.
MPConstraint * LookupConstraintOrNull(const std::string &constraint_name) const
Looks up a constraint by name, and returns nullptr if it does not exist.
int64_t time_limit() const
const MPObjective & Objective() const
Returns the objective object.
double time_limit_in_secs() const
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
void SetUnsupportedDoubleParam(MPSolverParameters::DoubleParam param)
void set_constraint_as_extracted(int ct_index, bool extracted)
MPSolver::ResultStatus result_status_
void InvalidateSolutionSynchronization()
void SetMIPParameters(const MPSolverParameters ¶m)
static constexpr int64_t kUnknownNumberOfNodes
double best_objective_bound_
bool CheckSolutionIsSynchronized() const
void ResetExtractionInformation()
static constexpr int64_t kUnknownNumberOfIterations
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
void set_variable_as_extracted(int var_index, bool extracted)
void SetCommonParameters(const MPSolverParameters ¶m)
SynchronizationStatus sync_status_
This class stores parameter settings for LP and MIP solvers.
@ INCREMENTALITY_OFF
Start solve from scratch.
@ DUAL_TOLERANCE
Advanced usage: tolerance for dual feasibility of basic solutions.
@ PRIMAL_TOLERANCE
Advanced usage: tolerance for primal feasibility of basic solutions.
static const double kDefaultDualTolerance
@ LP_ALGORITHM
Algorithm to solve linear programs.
@ SCALING
Advanced usage: enable or disable matrix scaling.
@ PRESOLVE
Advanced usage: presolve mode.
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
@ PRESOLVE_ON
Presolve is on.
static const double kDefaultPrimalTolerance
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
The class for variables of a Mathematical Programming (MP) model.
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
Collection of objects used to extend the Constraint Solver library.
MPSolverInterface * BuildCBCInterface(MPSolver *const solver)