22 #include "absl/status/status.h"
23 #include "absl/strings/str_format.h"
35 #include "CbcConfig.h"
36 #include "CbcMessage.hpp"
37 #include "CbcModel.hpp"
38 #include "CoinModel.hpp"
39 #include "OsiClpSolverInterface.hpp"
52 void Reset()
override;
61 num_threads_ = num_threads;
62 return absl::OkStatus();
74 bool IsLP()
const override {
return false; }
75 bool IsMIP()
const override {
return true; }
88 const MPVariable*
const variable,
double new_value,
89 double old_value)
override {
114 LOG(
FATAL) <<
"Basis status only available for continuous problems";
119 LOG(
FATAL) <<
"Basis status only available for continuous problems";
137 void ResetBestObjectiveBound();
142 void SetRelativeMipGap(
double value)
override;
143 void SetPrimalTolerance(
double value)
override;
144 void SetDualTolerance(
double value)
override;
145 void SetPresolveMode(
int value)
override;
146 void SetScalingMode(
int value)
override;
147 void SetLpAlgorithm(
int value)
override;
149 OsiClpSolverInterface osi_;
154 double relative_mip_gap_;
155 int num_threads_ = 1;
166 osi_.setStrParam(OsiProbName,
solver_->name_);
176 osi_.setStrParam(OsiProbName,
solver_->name_);
180 void CBCInterface::ResetBestObjectiveBound() {
191 osi_.setObjSense(maximize ? -1 : 1);
199 int MPSolverVarIndexToCbcVarIndex(
int var_index) {
return var_index + 1; }
205 osi_.setColBounds(MPSolverVarIndexToCbcVarIndex(var_index), lb, ub);
216 osi_.setInteger(MPSolverVarIndexToCbcVarIndex(var_index));
218 osi_.setContinuous(MPSolverVarIndexToCbcVarIndex(var_index));
228 osi_.setRowBounds(
index, lb, ub);
248 if (!
solver_->variables_.empty()) {
251 if (!
solver_->constraints_.empty()) {
266 if (
solver_->variables_.empty() &&
solver_->constraints_.empty()) {
281 build.addColumn(0,
nullptr,
nullptr, 1.0, 1.0,
283 const int nb_vars =
solver_->variables_.size();
284 for (
int i = 0; i < nb_vars; ++i) {
288 if (
var->name().empty()) {
289 build.addColumn(0,
nullptr,
nullptr,
var->lb(),
var->ub(), obj_coeff,
290 nullptr,
var->integer());
292 build.addColumn(0,
nullptr,
nullptr,
var->lb(),
var->ub(), obj_coeff,
293 var->name().c_str(),
var->integer());
298 int max_row_length = 0;
299 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
302 if (
ct->coefficients_.size() > max_row_length) {
303 max_row_length =
ct->coefficients_.size();
306 std::unique_ptr<int[]> indices(
new int[max_row_length]);
307 std::unique_ptr<double[]> coefs(
new double[max_row_length]);
309 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
311 const int size =
ct->coefficients_.size();
313 for (
const auto& entry :
ct->coefficients_) {
314 const int index = MPSolverVarIndexToCbcVarIndex(entry.first->index());
316 coefs[j] = entry.second;
319 if (
ct->name().empty()) {
320 build.addRow(size, indices.get(), coefs.get(),
ct->lb(),
ct->ub());
322 build.addRow(size, indices.get(), coefs.get(),
ct->lb(),
ct->ub(),
326 osi_.loadFromCoinModel(build);
342 VLOG(1) << absl::StrFormat(
"Model built in %.3f seconds.", timer.
Get());
344 ResetBestObjectiveBound();
347 CbcModel
model(osi_);
350 CoinMessageHandler message_handler;
351 model.passInMessageHandler(&message_handler);
353 message_handler.setLogLevel(0, 0);
354 message_handler.setLogLevel(1, 0);
355 message_handler.setLogLevel(2, 0);
356 message_handler.setLogLevel(3, 0);
358 message_handler.setLogLevel(0, 1);
359 message_handler.setLogLevel(1, 1);
360 message_handler.setLogLevel(2, 1);
361 message_handler.setLogLevel(3, 1);
376 SetParameters(param);
379 model.setTypePresolve(0);
382 model.setAllowableFractionGap(relative_mip_gap_);
386 ? callCbc(
"-solve ",
model)
387 : callCbc(absl::StrCat(
"-threads ", num_threads_,
" -solve "),
model);
388 const int kBadReturnStatus = 777;
389 CHECK_NE(kBadReturnStatus, return_status);
392 VLOG(1) << absl::StrFormat(
"Solved in %.3f seconds.", timer.
Get());
395 int tmp_status =
model.status();
397 VLOG(1) <<
"cbc result status: " << tmp_status;
410 switch (tmp_status) {
414 if (
model.isProvenOptimal()) {
416 }
else if (
model.isContinuousUnbounded()) {
418 }
else if (
model.isProvenInfeasible()) {
420 }
else if (
model.isAbandoned()) {
427 if (
model.bestSolution() !=
nullptr) {
443 const double*
const values =
model.bestSolution();
444 if (values !=
nullptr) {
446 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
448 const int var_index = MPSolverVarIndexToCbcVarIndex(
var->index());
449 const double val = values[var_index];
450 var->set_solution_value(val);
451 VLOG(3) <<
var->name() <<
"=" << val;
454 VLOG(1) <<
"No feasible solution found.";
458 iterations_ =
model.getIterationCount();
459 nodes_ =
model.getNodeCount();
493 void CBCInterface::SetRelativeMipGap(
double value) {
494 relative_mip_gap_ =
value;
497 void CBCInterface::SetPrimalTolerance(
double value) {
505 void CBCInterface::SetDualTolerance(
double value) {
513 void CBCInterface::SetPresolveMode(
int value) {
525 void CBCInterface::SetScalingMode(
int value) {
529 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
int64 nodes() const 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)
void SetVariableBounds(int var_index, double lb, double ub) override
bool IsLP() const override
bool IsMIP() const override
virtual void ExtractModel()
void SetOptimizationDirection(bool maximize) override
MPSolver::BasisStatus column_status(int variable_index) const override
int64 iterations() 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.
double time_limit_in_secs() const
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
static constexpr int64 kUnknownNumberOfNodes
static constexpr int64 kUnknownNumberOfIterations
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)
double best_objective_bound_
bool CheckSolutionIsSynchronized() const
void ResetExtractionInformation()
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...
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
MPSolverInterface * BuildCBCInterface(MPSolver *const solver)