23 #include "absl/status/status.h"
24 #include "absl/strings/str_format.h"
36 #include "CbcConfig.h"
37 #include "CbcMessage.hpp"
38 #include "CbcModel.hpp"
39 #include "CoinModel.hpp"
40 #include "OsiClpSolverInterface.hpp"
53 void Reset()
override;
62 num_threads_ = num_threads;
63 return absl::OkStatus();
75 bool IsLP()
const override {
return false; }
76 bool IsMIP()
const override {
return true; }
89 const MPVariable*
const variable,
double new_value,
90 double old_value)
override {
111 int64_t
nodes()
const override;
115 LOG(
FATAL) <<
"Basis status only available for continuous problems";
120 LOG(
FATAL) <<
"Basis status only available for continuous problems";
138 void ResetBestObjectiveBound();
143 void SetRelativeMipGap(
double value)
override;
144 void SetPrimalTolerance(
double value)
override;
145 void SetDualTolerance(
double value)
override;
146 void SetPresolveMode(
int value)
override;
147 void SetScalingMode(
int value)
override;
148 void SetLpAlgorithm(
int value)
override;
150 OsiClpSolverInterface osi_;
155 double relative_mip_gap_;
156 int num_threads_ = 1;
167 osi_.setStrParam(OsiProbName,
solver_->name_);
177 osi_.setStrParam(OsiProbName,
solver_->name_);
181 void CBCInterface::ResetBestObjectiveBound() {
192 osi_.setObjSense(maximize ? -1 : 1);
200 int MPSolverVarIndexToCbcVarIndex(
int var_index) {
return var_index + 1; }
206 osi_.setColBounds(MPSolverVarIndexToCbcVarIndex(var_index), lb, ub);
217 osi_.setInteger(MPSolverVarIndexToCbcVarIndex(var_index));
219 osi_.setContinuous(MPSolverVarIndexToCbcVarIndex(var_index));
229 osi_.setRowBounds(
index, lb, ub);
249 if (!
solver_->variables_.empty()) {
252 if (!
solver_->constraints_.empty()) {
267 if (
solver_->variables_.empty() &&
solver_->constraints_.empty()) {
282 build.addColumn(0,
nullptr,
nullptr, 1.0, 1.0,
284 const int nb_vars =
solver_->variables_.size();
285 for (
int i = 0; i < nb_vars; ++i) {
289 if (
var->name().empty()) {
290 build.addColumn(0,
nullptr,
nullptr,
var->lb(),
var->ub(), obj_coeff,
291 nullptr,
var->integer());
293 build.addColumn(0,
nullptr,
nullptr,
var->lb(),
var->ub(), obj_coeff,
294 var->name().c_str(),
var->integer());
299 int max_row_length = 0;
300 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
303 if (
ct->coefficients_.size() > max_row_length) {
304 max_row_length =
ct->coefficients_.size();
307 std::unique_ptr<int[]> indices(
new int[max_row_length]);
308 std::unique_ptr<double[]> coefs(
new double[max_row_length]);
310 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
312 const int size =
ct->coefficients_.size();
314 for (
const auto& entry :
ct->coefficients_) {
315 const int index = MPSolverVarIndexToCbcVarIndex(entry.first->index());
317 coefs[j] = entry.second;
320 if (
ct->name().empty()) {
321 build.addRow(size, indices.get(), coefs.get(),
ct->lb(),
ct->ub());
323 build.addRow(size, indices.get(), coefs.get(),
ct->lb(),
ct->ub(),
327 osi_.loadFromCoinModel(build);
343 VLOG(1) << absl::StrFormat(
"Model built in %.3f seconds.", timer.
Get());
345 ResetBestObjectiveBound();
348 CbcModel
model(osi_);
351 CoinMessageHandler message_handler;
352 model.passInMessageHandler(&message_handler);
354 message_handler.setLogLevel(0, 0);
355 message_handler.setLogLevel(1, 0);
356 message_handler.setLogLevel(2, 0);
357 message_handler.setLogLevel(3, 0);
359 message_handler.setLogLevel(0, 1);
360 message_handler.setLogLevel(1, 1);
361 message_handler.setLogLevel(2, 1);
362 message_handler.setLogLevel(3, 1);
377 SetParameters(param);
380 model.setTypePresolve(0);
383 model.setAllowableFractionGap(relative_mip_gap_);
387 ? callCbc(
"-solve ",
model)
388 : callCbc(absl::StrCat(
"-threads ", num_threads_,
" -solve "),
model);
389 const int kBadReturnStatus = 777;
390 CHECK_NE(kBadReturnStatus, return_status);
393 VLOG(1) << absl::StrFormat(
"Solved in %.3f seconds.", timer.
Get());
396 int tmp_status =
model.status();
398 VLOG(1) <<
"cbc result status: " << tmp_status;
411 switch (tmp_status) {
415 if (
model.isProvenOptimal()) {
417 }
else if (
model.isContinuousUnbounded()) {
419 }
else if (
model.isProvenInfeasible()) {
421 }
else if (
model.isAbandoned()) {
428 if (
model.bestSolution() !=
nullptr) {
444 const double*
const values =
model.bestSolution();
445 if (values !=
nullptr) {
447 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
449 const int var_index = MPSolverVarIndexToCbcVarIndex(
var->index());
450 const double val = values[var_index];
451 var->set_solution_value(val);
452 VLOG(3) <<
var->name() <<
"=" << val;
455 VLOG(1) <<
"No feasible solution found.";
459 iterations_ =
model.getIterationCount();
460 nodes_ =
model.getNodeCount();
494 void CBCInterface::SetRelativeMipGap(
double value) {
495 relative_mip_gap_ =
value;
498 void CBCInterface::SetPrimalTolerance(
double value) {
506 void CBCInterface::SetDualTolerance(
double value) {
514 void CBCInterface::SetPresolveMode(
int value) {
526 void CBCInterface::SetScalingMode(
int value) {
530 void CBCInterface::SetLpAlgorithm(
int value) {
#define CHECK_GE(val1, val2)
#define CHECK_NE(val1, val2)
#define VLOG(verboselevel)
void AddRowConstraint(MPConstraint *const ct) override
void * underlying_solver() override
void ExtractObjective() 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.
const MPObjective & Objective() const
Returns the objective object.
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
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)