22 #include "absl/base/attributes.h" 23 #include "absl/memory/memory.h" 24 #include "absl/strings/match.h" 25 #include "absl/strings/str_format.h" 33 #if defined(USE_CLP) || defined(USE_CBC) 37 #include "ClpConfig.h" 38 #include "ClpMessage.hpp" 39 #include "ClpSimplex.hpp" 40 #include "CoinBuild.hpp" 59 void Reset()
override;
72 const MPVariable*
const variable,
double new_value,
73 double old_value)
override;
89 int64_t
nodes()
const override;
99 bool IsLP()
const override {
return true; }
100 bool IsMIP()
const override {
return false; }
109 return reinterpret_cast<void*>(clp_.get());
114 void CreateDummyVariableForEmptyConstraints();
121 void ResetParameters();
123 void SetRelativeMipGap(
double value)
override;
124 void SetPrimalTolerance(
double value)
override;
125 void SetDualTolerance(
double value)
override;
126 void SetPresolveMode(
int value)
override;
127 void SetScalingMode(
int value)
override;
128 void SetLpAlgorithm(
int value)
override;
132 ClpSimplex::Status clp_basis_status)
const;
134 std::unique_ptr<ClpSimplex> clp_;
135 std::unique_ptr<ClpSolve> options_;
143 clp_->setStrParam(ClpProbName,
solver_->name_);
144 clp_->setOptimizationDirection(1);
150 clp_ = absl::make_unique<ClpSimplex>();
151 clp_->setOptimizationDirection(
maximize_ ? -1 : 1);
160 int MPSolverVarIndexToClpVarIndex(
int var_index) {
return var_index + 1; }
166 clp_->setOptimizationDirection(maximize ? -1 : 1);
174 clp_->setColumnBounds(MPSolverVarIndexToClpVarIndex(var_index), lb, ub);
188 clp_->setRowBounds(
index, lb, ub);
196 double new_value,
double old_value) {
204 clp_->modifyCoefficient(constraint->
index(),
205 MPSolverVarIndexToClpVarIndex(variable->
index()),
219 for (
const auto& entry : constraint->coefficients_) {
221 clp_->modifyCoefficient(constraint->
index(),
222 MPSolverVarIndexToClpVarIndex(entry.first->index()),
232 clp_->setObjectiveCoefficient(
244 clp_->setObjectiveOffset(-offset);
251 for (
const auto& entry :
solver_->objective_->coefficients_) {
252 const int mpsolver_var_index = entry.first->index();
257 clp_->setObjectiveCoefficient(
258 MPSolverVarIndexToClpVarIndex(mpsolver_var_index), 0.0);
262 clp_->setObjectiveOffset(0.0);
273 void CLPInterface::CreateDummyVariableForEmptyConstraints() {
279 std::string dummy =
"dummy";
286 int total_num_vars =
solver_->variables_.size();
290 clp_->resize(0, total_num_vars + 1);
291 CreateDummyVariableForEmptyConstraints();
292 for (
int i = 0; i < total_num_vars; ++i) {
295 if (!
var->name().empty()) {
296 std::string
name =
var->name();
297 clp_->setColumnName(MPSolverVarIndexToClpVarIndex(i),
name);
299 clp_->setColumnBounds(MPSolverVarIndexToClpVarIndex(i),
var->lb(),
313 double tmp_obj_coef = 0.0;
314 clp_->addColumn(0,
nullptr,
nullptr,
var->lb(),
var->ub(),
316 if (!
var->name().empty()) {
317 std::string
name =
var->name();
318 clp_->setColumnName(MPSolverVarIndexToClpVarIndex(j),
name);
324 const int ct_index =
ct->index();
325 for (
const auto& entry :
ct->coefficients_) {
326 const int mpsolver_var_index = entry.first->index();
329 clp_->modifyCoefficient(
330 ct_index, MPSolverVarIndexToClpVarIndex(mpsolver_var_index),
341 int total_num_rows =
solver_->constraints_.size();
344 int max_row_length = 0;
349 if (
ct->coefficients_.size() > max_row_length) {
350 max_row_length =
ct->coefficients_.size();
354 max_row_length =
std::max(1, max_row_length);
355 std::unique_ptr<int[]> indices(
new int[max_row_length]);
356 std::unique_ptr<double[]> coefs(
new double[max_row_length]);
357 CoinBuild build_object;
362 int size =
ct->coefficients_.size();
370 for (
const auto& entry :
ct->coefficients_) {
371 const int mpsolver_var_index = entry.first->index();
373 indices[j] = MPSolverVarIndexToClpVarIndex(mpsolver_var_index);
374 coefs[j] = entry.second;
377 build_object.addRow(size, indices.get(), coefs.get(),
ct->lb(),
ct->ub());
380 clp_->addRows(build_object);
383 if (!
ct->name().empty()) {
384 std::string
name =
ct->name();
385 clp_->setRowName(
ct->index(),
name);
394 for (
const auto& entry :
solver_->objective_->coefficients_) {
395 clp_->setObjectiveCoefficient(
396 MPSolverVarIndexToClpVarIndex(entry.first->index()), entry.second);
416 CoinMessageHandler message_handler;
417 clp_->passInMessageHandler(&message_handler);
419 message_handler.setLogLevel(1, 0);
420 clp_->setLogLevel(0);
422 message_handler.setLogLevel(1, 1);
423 clp_->setLogLevel(1);
428 if (
solver_->variables_.empty() &&
solver_->constraints_.empty()) {
436 VLOG(1) << absl::StrFormat(
"Model built in %.3f seconds.", timer.
Get());
443 clp_->setMaximumSeconds(-1.0);
448 options_ = absl::make_unique<ClpSolve>();
449 SetParameters(param);
453 clp_->initialSolve(*options_);
454 VLOG(1) << absl::StrFormat(
"Solved in %.3f seconds.", timer.
Get());
457 int tmp_status = clp_->status();
458 VLOG(1) <<
"clp result status: " << tmp_status;
459 switch (tmp_status) {
460 case CLP_SIMPLEX_FINISHED:
463 case CLP_SIMPLEX_INFEASIBLE:
466 case CLP_SIMPLEX_UNBOUNDED:
469 case CLP_SIMPLEX_STOPPED:
482 const double*
const values = clp_->getColSolution();
483 const double*
const reduced_costs = clp_->getReducedCost();
484 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
486 const int clp_var_index = MPSolverVarIndexToClpVarIndex(
var->index());
487 const double val = values[clp_var_index];
488 var->set_solution_value(val);
489 VLOG(3) <<
var->name() <<
": value = " << val;
490 double reduced_cost = reduced_costs[clp_var_index];
491 var->set_reduced_cost(reduced_cost);
492 VLOG(4) <<
var->name() <<
": reduced cost = " << reduced_cost;
494 const double*
const dual_values = clp_->getRowPrice();
495 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
497 const int constraint_index =
ct->index();
498 const double dual_value = dual_values[constraint_index];
499 ct->set_dual_value(dual_value);
500 VLOG(4) <<
"row " <<
ct->index() <<
" dual value = " << dual_value;
507 }
catch (CoinError& e) {
508 LOG(
WARNING) <<
"Caught exception in Coin LP: " << e.message();
515 ClpSimplex::Status clp_basis_status)
const {
516 switch (clp_basis_status) {
517 case ClpSimplex::isFree:
519 case ClpSimplex::basic:
521 case ClpSimplex::atUpperBound:
523 case ClpSimplex::atLowerBound:
525 case ClpSimplex::superBasic:
527 case ClpSimplex::isFixed:
530 LOG(
FATAL) <<
"Unknown CLP basis status";
539 return clp_->getIterationCount();
543 LOG(DFATAL) <<
"Number of nodes only available for discrete problems";
550 const ClpSimplex::Status clp_basis_status =
551 clp_->getRowStatus(constraint_index);
552 return TransformCLPBasisStatus(clp_basis_status);
558 const ClpSimplex::Status clp_basis_status =
559 clp_->getColumnStatus(MPSolverVarIndexToClpVarIndex(variable_index));
560 return TransformCLPBasisStatus(clp_basis_status);
569 void CLPInterface::ResetParameters() {
574 void CLPInterface::SetRelativeMipGap(
double value) {
575 LOG(
WARNING) <<
"The relative MIP gap is only available " 576 <<
"for discrete problems.";
579 void CLPInterface::SetPrimalTolerance(
double value) {
580 clp_->setPrimalTolerance(
value);
583 void CLPInterface::SetDualTolerance(
double value) {
584 clp_->setDualTolerance(
value);
587 void CLPInterface::SetPresolveMode(
int value) {
590 options_->setPresolveType(ClpSolve::presolveOff);
594 options_->setPresolveType(ClpSolve::presolveOn);
603 void CLPInterface::SetScalingMode(
int value) {
607 void CLPInterface::SetLpAlgorithm(
int value) {
610 options_->setSolveType(ClpSolve::useDual);
614 options_->setSolveType(ClpSolve::usePrimal);
618 options_->setSolveType(ClpSolve::useBarrier);
633 #endif // #if defined(USE_CBC) || defined(USE_CLP) ResultStatus
The status of solving the problem.
void set_variable_as_extracted(int var_index, bool extracted)
static const double kDefaultPrimalTolerance
void * underlying_solver() override
Advanced usage: incrementality from one solve to the next.
MPSolver::ResultStatus Solve(const MPSolverParameters ¶m) override
void SetCoefficient(MPConstraint *const constraint, const MPVariable *const variable, double new_value, double old_value) override
void SetOptimizationDirection(bool maximize) override
void set_constraint_as_extracted(int ct_index, bool extracted)
SynchronizationStatus sync_status_
void SetVariableInteger(int var_index, bool integer) override
#define VLOG(verboselevel)
const MPObjective & Objective() const
Returns the objective object.
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
void ExtractNewVariables() override
bool IsMIP() const override
void SetVariableBounds(int var_index, double lb, double ub) override
Advanced usage: presolve mode.
#define DCHECK_GT(val1, val2)
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
MPSolver::ResultStatus result_status_
void ExtractObjective() override
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
void SetObjectiveCoefficient(const MPVariable *const variable, double coefficient) override
The class for variables of a Mathematical Programming (MP) model.
std::string SolverVersion() const override
void AddRowConstraint(MPConstraint *const ct) override
CLPInterface(MPSolver *const solver)
#define DCHECK_NE(val1, val2)
static const int kDummyVariableIndex
void AddVariable(MPVariable *const var) override
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
void SetCommonParameters(const MPSolverParameters ¶m)
int64_t time_limit() const
static constexpr int64_t kUnknownNumberOfIterations
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
void ClearObjective() override
The class for constraints of a Mathematical Programming (MP) model.
feasible, or stopped by limit.
void ClearConstraint(MPConstraint *const constraint) override
static const double kDefaultDualTolerance
bool constraint_is_extracted(int ct_index) const
void InvalidateSolutionSynchronization()
int index() const
Returns the index of the constraint in the MPSolver::constraints_.
int64_t iterations() const override
#define DCHECK(condition)
int last_constraint_index_
int index() const
Returns the index of the variable in the MPSolver::variables_.
Advanced usage: enable or disable matrix scaling.
bool CheckSolutionIsSynchronized() const
void ExtractNewConstraints() override
static constexpr int64_t kUnknownNumberOfNodes
int64_t nodes() const override
#define DCHECK_LE(val1, val2)
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.
MPSolverInterface * BuildCLPInterface(MPSolver *const solver)
abnormal, i.e., error of some kind.
Start solve from scratch.
This class stores parameter settings for LP and MIP solvers.
bool IsContinuous() const override
MPSolver::BasisStatus row_status(int constraint_index) const override
Algorithm to solve linear programs.
void ResetExtractionInformation()
MPSolver::BasisStatus column_status(int variable_index) const override
double offset() const
Gets the constant term in the objective.
bool IsLP() const override
double time_limit_in_secs() const
void SetObjectiveOffset(double offset) override
bool variable_is_extracted(int var_index) const
#define DCHECK_LT(val1, val2)
void SetConstraintBounds(int row_index, double lb, double ub) override