23 #include "absl/base/attributes.h" 24 #include "absl/status/status.h" 25 #include "absl/strings/str_format.h" 37 #include "CbcConfig.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_);
182 void CBCInterface::ResetBestObjectiveBound() {
193 osi_.setObjSense(maximize ? -1 : 1);
201 int 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();
495 void CBCInterface::SetRelativeMipGap(
double value) {
496 relative_mip_gap_ =
value;
499 void CBCInterface::SetPrimalTolerance(
double value) {
507 void CBCInterface::SetDualTolerance(
double value) {
515 void CBCInterface::SetPresolveMode(
int value) {
527 void CBCInterface::SetScalingMode(
int value) {
531 void CBCInterface::SetLpAlgorithm(
int value) {
540 #endif // #if defined(USE_CBC) ResultStatus
The status of solving the problem.
MPVariable * LookupVariableOrNull(const std::string &var_name) const
Looks up a variable by name, and returns nullptr if it does not exist.
void set_variable_as_extracted(int var_index, bool extracted)
static const double kDefaultPrimalTolerance
Advanced usage: incrementality from one solve to the next.
void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value) override
void SetVariableInteger(int var_index, bool integer) override
#define CHECK_GE(val1, val2)
double best_objective_bound_
void set_constraint_as_extracted(int ct_index, bool extracted)
SynchronizationStatus sync_status_
#define VLOG(verboselevel)
const MPObjective & Objective() const
Returns the objective object.
MPSolver::BasisStatus row_status(int constraint_index) const override
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
Advanced usage: presolve mode.
void ExtractNewVariables() override
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
void SetOptimizationDirection(bool maximize) override
MPSolver::ResultStatus result_status_
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
void SetConstraintBounds(int row_index, double lb, double ub) override
The class for variables of a Mathematical Programming (MP) model.
bool IsMIP() const override
MPSolver::ResultStatus Solve(const MPSolverParameters ¶m) override
void SetObjectiveOffset(double value) override
MPSolverInterface * BuildCBCInterface(MPSolver *const solver)
MPConstraint * LookupConstraintOrNull(const std::string &constraint_name) const
Looks up a constraint by name, and returns nullptr if it does not exist.
virtual void ExtractModel()
bool IsLP() const override
void AddVariable(MPVariable *const var) override
void SetCommonParameters(const MPSolverParameters ¶m)
int64_t time_limit() const
static constexpr int64_t kUnknownNumberOfIterations
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
The class for constraints of a Mathematical Programming (MP) model.
feasible, or stopped by limit.
static const double kDefaultDualTolerance
void * underlying_solver() override
double GetCoefficient(const MPVariable *const var) const
Gets the coefficient of a given variable in the objective.
void SetMIPParameters(const MPSolverParameters ¶m)
void InvalidateSolutionSynchronization()
Advanced usage: tolerance for primal feasibility of basic solutions.
void ExtractNewConstraints() override
Advanced usage: enable or disable matrix scaling.
bool CheckSolutionIsSynchronized() const
void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient) override
static constexpr int64_t kUnknownNumberOfNodes
Advanced usage: tolerance for dual feasibility of basic solutions.
CBCInterface(MPSolver *const solver)
int64_t nodes() const override
void AddRowConstraint(MPConstraint *const ct) override
This mathematical programming (MP) solver class is the main class though which users build and solve ...
Collection of objects used to extend the Constraint Solver library.
std::string SolverVersion() const override
abnormal, i.e., error of some kind.
Start solve from scratch.
absl::Status SetNumThreads(int num_threads) override
This class stores parameter settings for LP and MIP solvers.
void ClearObjective() override
void ClearConstraint(MPConstraint *const constraint) override
Algorithm to solve linear programs.
MPSolver::BasisStatus column_status(int variable_index) const override
void ResetExtractionInformation()
void SetUnsupportedDoubleParam(MPSolverParameters::DoubleParam param)
void ExtractObjective() override
bool IsContinuous() const override
double offset() const
Gets the constant term in the objective.
int64_t iterations() const override
#define CHECK_NE(val1, val2)
double time_limit_in_secs() const
void SetVariableBounds(int var_index, double lb, double ub) override