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) {
539 #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