Google OR-Tools: ortools/linear_solver/clp_interface.cc Source File
20#include "absl/base/attributes.h"
21#include "absl/strings/str_format.h"
50 void Reset() override;
53 void SetVariableBounds(int var_index, double lb, double ub) override;
63 double new_value, double old_value) override;
69 double coefficient) override;
79 int64_t nodes() const override;
89 bool IsLP() const override { return true; }
90 bool IsMIP() const override { return false; }
96 std::string SolverVersion() const override { return "Clp " CLP_VERSION; }
104 void CreateDummyVariableForEmptyConstraints();
113 void SetRelativeMipGap(double value) override;
114 void SetPrimalTolerance(double value) override;
115 void SetDualTolerance(double value) override;
116 void SetPresolveMode(int value) override;
117 void SetScalingMode(int value) override;
118 void SetLpAlgorithm(int value) override;
122 ClpSimplex::Status clp_basis_status) const;
124 std::unique_ptr<ClpSimplex> clp_;
132 : MPSolverInterface(solver), clp_(new ClpSimplex), options_(new ClpSolve) {
133 clp_->setStrParam(ClpProbName, solver_->name_);
140 clp_ = std::make_unique<ClpSimplex>();
141 clp_->setOptimizationDirection(maximize_ ? -1 : 1);
150int MPSolverVarIndexToClpVarIndex(int var_index) { return var_index + 1; }
186 double new_value, double old_value) {
194 clp_->modifyCoefficient(constraint->index(),
195 MPSolverVarIndexToClpVarIndex(variable->index()),
209 for (const auto& entry : constraint->coefficients_) {
211 clp_->modifyCoefficient(constraint->index(),
222 clp_->setObjectiveCoefficient(
223 MPSolverVarIndexToClpVarIndex(variable->index()), coefficient);
241 for (const auto& entry : solver_->objective_->coefficients_) {
242 const int mpsolver_var_index = entry.first->index();
247 clp_->setObjectiveCoefficient(
248 MPSolverVarIndexToClpVarIndex(mpsolver_var_index), 0.0);
263void CLPInterface::CreateDummyVariableForEmptyConstraints() {
269 std::string dummy = "dummy";
276 int total_num_vars = solver_->variables_.size();
280 clp_->resize(0, total_num_vars + 1);
281 CreateDummyVariableForEmptyConstraints();
282 for (int i = 0; i < total_num_vars; ++i) {
285 if (!var->name().empty()) {
286 std::string name = var->name();
287 clp_->setColumnName(MPSolverVarIndexToClpVarIndex(i), name);
289 clp_->setColumnBounds(MPSolverVarIndexToClpVarIndex(i), var->lb(),
290 var->ub());
303 double tmp_obj_coef = 0.0;
304 clp_->addColumn(0, nullptr, nullptr, var->lb(), var->ub(),
306 if (!var->name().empty()) {
307 std::string name = var->name();
308 clp_->setColumnName(MPSolverVarIndexToClpVarIndex(j), name);
314 const int ct_index = ct->index();
315 for (const auto& entry : ct->coefficients_) {
316 const int mpsolver_var_index = entry.first->index();
320 ct_index, MPSolverVarIndexToClpVarIndex(mpsolver_var_index),
331 int total_num_rows = solver_->constraints_.size();
339 if (ct->coefficients_.size() > max_row_length) {
340 max_row_length = ct->coefficients_.size();
344 max_row_length = std::max(1, max_row_length);
345 std::unique_ptr<int[]> indices(new int[max_row_length]);
346 std::unique_ptr<double[]> coefs(new double[max_row_length]);
352 int size = ct->coefficients_.size();
360 for (const auto& entry : ct->coefficients_) {
361 const int mpsolver_var_index = entry.first->index();
363 indices[j] = MPSolverVarIndexToClpVarIndex(mpsolver_var_index);
367 build_object.addRow(size, indices.get(), coefs.get(), ct->lb(), ct->ub());
370 clp_->addRows(build_object);
373 if (!ct->name().empty()) {
374 std::string name = ct->name();
375 clp_->setRowName(ct->index(), name);
384 for (const auto& entry : solver_->objective_->coefficients_) {
385 clp_->setObjectiveCoefficient(
386 MPSolverVarIndexToClpVarIndex(entry.first->index()), entry.second);
391 clp_->setObjectiveOffset(-solver_->Objective().offset());
406 CoinMessageHandler message_handler;
407 clp_->passInMessageHandler(&message_handler);
409 message_handler.setLogLevel(1, 0);
412 message_handler.setLogLevel(1, 1);
418 if (solver_->variables_.empty() && solver_->constraints_.empty()) {
426 VLOG(1) << absl::StrFormat("Model built in %.3f seconds.", timer.Get());
429 if (solver_->time_limit() != 0) {
430 VLOG(1) << "Setting time limit = " << solver_->time_limit() << " ms.";
431 clp_->setMaximumSeconds(solver_->time_limit_in_secs());
433 clp_->setMaximumSeconds(-1.0);
438 options_ = std::make_unique<ClpSolve>();
443 clp_->initialSolve(*options_);
444 VLOG(1) << absl::StrFormat("Solved in %.3f seconds.", timer.Get());
447 int tmp_status = clp_->status();
448 VLOG(1) << "clp result status: " << tmp_status;
450 case CLP_SIMPLEX_FINISHED:
453 case CLP_SIMPLEX_INFEASIBLE:
456 case CLP_SIMPLEX_UNBOUNDED:
472 const double* const values = clp_->getColSolution();
473 const double* const reduced_costs = clp_->getReducedCost();
474 for (int i = 0; i < solver_->variables_.size(); ++i) {
476 const int clp_var_index = MPSolverVarIndexToClpVarIndex(var->index());
477 const double val = values[clp_var_index];
479 VLOG(3) << var->name() << ": value = " << val;
480 double reduced_cost = reduced_costs[clp_var_index];
482 VLOG(4) << var->name() << ": reduced cost = " << reduced_cost;
484 const double* const dual_values = clp_->getRowPrice();
485 for (int i = 0; i < solver_->constraints_.size(); ++i) {
487 const int constraint_index = ct->index();
488 const double dual_value = dual_values[constraint_index];
490 VLOG(4) << "row " << ct->index() << " dual value = " << dual_value;
498 LOG(WARNING) << "Caught exception in Coin LP: " << e.message();
505 ClpSimplex::Status clp_basis_status) const {
506 switch (clp_basis_status) {
511 case ClpSimplex::atUpperBound:
513 case ClpSimplex::atLowerBound:
515 case ClpSimplex::superBasic:
520 LOG(FATAL) << "Unknown CLP basis status";
538 DCHECK_LE(0, constraint_index);
540 const ClpSimplex::Status clp_basis_status =
541 clp_->getRowStatus(constraint_index);
546 DCHECK_LE(0, variable_index);
548 const ClpSimplex::Status clp_basis_status =
549 clp_->getColumnStatus(MPSolverVarIndexToClpVarIndex(variable_index));
559void CLPInterface::ResetParameters() {
564void CLPInterface::SetRelativeMipGap(double value) {
565 LOG(WARNING) << "The relative MIP gap is only available "
566 << "for discrete problems.";
569void CLPInterface::SetPrimalTolerance(double value) {
570 clp_->setPrimalTolerance(value);
573void CLPInterface::SetDualTolerance(double value) {
574 clp_->setDualTolerance(value);
577void CLPInterface::SetPresolveMode(int value) {
580 options_->setPresolveType(ClpSolve::presolveOff);
584 options_->setPresolveType(ClpSolve::presolveOn);
593void CLPInterface::SetScalingMode(int value) {
597void CLPInterface::SetLpAlgorithm(int value) {
600 options_->setSolveType(ClpSolve::useDual);
604 options_->setSolveType(ClpSolve::usePrimal);
608 options_->setSolveType(ClpSolve::useBarrier);
621const void* const kRegisterCLP ABSL_ATTRIBUTE_UNUSED = [] {
Definition clp_interface.cc:35
int64_t iterations() const override
Definition clp_interface.cc:527
int64_t nodes() const override
Definition clp_interface.cc:532
~CLPInterface() override
Definition clp_interface.cc:137
MPSolver::BasisStatus row_status(int constraint_index) const override
Definition clp_interface.cc:537
CLPInterface(MPSolver *solver)
Definition clp_interface.cc:131
void ClearConstraint(MPConstraint *constraint) override
Definition clp_interface.cc:205
void ExtractNewConstraints() override
Definition clp_interface.cc:330
void SetVariableBounds(int var_index, double lb, double ub) override
Definition clp_interface.cc:159
void ClearObjective() override
Definition clp_interface.cc:238
MPSolver::BasisStatus column_status(int variable_index) const override
Definition clp_interface.cc:545
void AddRowConstraint(MPConstraint *ct) override
Definition clp_interface.cc:255
void SetObjectiveOffset(double offset) override
Definition clp_interface.cc:230
void * underlying_solver() override
Definition clp_interface.cc:98
void SetCoefficient(MPConstraint *constraint, const MPVariable *variable, double new_value, double old_value) override
Definition clp_interface.cc:184
void AddVariable(MPVariable *var) override
Definition clp_interface.cc:259
bool IsContinuous() const override
Definition clp_interface.cc:88
bool IsMIP() const override
Definition clp_interface.cc:90
bool IsLP() const override
Definition clp_interface.cc:89
std::string SolverVersion() const override
Definition clp_interface.cc:96
void SetConstraintBounds(int row_index, double lb, double ub) override
Definition clp_interface.cc:173
void SetOptimizationDirection(bool maximize) override
Definition clp_interface.cc:154
void SetVariableInteger(int var_index, bool integer) override
Definition clp_interface.cc:171
void ExtractNewVariables() override
Definition clp_interface.cc:274
void ExtractObjective() override
Definition clp_interface.cc:381
MPSolver::ResultStatus Solve(const MPSolverParameters ¶m) override
Definition clp_interface.cc:395
void SetObjectiveCoefficient(const MPVariable *variable, double coefficient) override
Definition clp_interface.cc:218
void Reset() override
Definition clp_interface.cc:139
void set_dual_value(double dual_value)
double lb() const
Returns the lower bound.
double ub() const
Returns the upper bound.
const std::string & name() const
Returns the name of the constraint.
int index() const
Returns the index of the constraint in the MPSolver::constraints_.
static MPSolverInterfaceFactoryRepository * GetInstance()
void Register(MPSolverInterfaceFactory factory, MPSolver::OptimizationProblemType problem_type, std::function< bool()> is_runtime_ready={})
void set_variable_as_extracted(int var_index, bool extracted)
bool CheckSolutionIsSynchronized() const
static constexpr int64_t kUnknownNumberOfIterations
friend class MPConstraint
void InvalidateSolutionSynchronization()
void set_constraint_as_extracted(int ct_index, bool extracted)
void ResetExtractionInformation()
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
int last_constraint_index_
static const int kDummyVariableIndex
virtual void SetUnsupportedIntegerParam(MPSolverParameters::IntegerParam param)
bool variable_is_extracted(int var_index) const
bool constraint_is_extracted(int ct_index) const
static constexpr int64_t kUnknownNumberOfNodes
MPSolverInterface(MPSolver *solver)
void SetCommonParameters(const MPSolverParameters ¶m)
MPSolver::ResultStatus result_status_
SynchronizationStatus sync_status_
static const double kDefaultDualTolerance
static const double kDefaultPrimalTolerance
@ PRESOLVE_OFF
Presolve is off.
@ PRESOLVE_ON
Presolve is on.
@ BARRIER
Barrier algorithm.
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
@ PRESOLVE
Advanced usage: presolve mode.
@ LP_ALGORITHM
Algorithm to solve linear programs.
@ SCALING
Advanced usage: enable or disable matrix scaling.
@ INCREMENTALITY_OFF
Start solve from scratch.
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
@ FEASIBLE
feasible, or stopped by limit.
@ INFEASIBLE
proven infeasible.
@ UNBOUNDED
proven unbounded.
@ ABNORMAL
abnormal, i.e., error of some kind.
The class for variables of a Mathematical Programming (MP) model.
double lb() const
Returns the lower bound.
double ub() const
Returns the upper bound.
const std::string & name() const
Returns the name of the variable.
void set_reduced_cost(double reduced_cost)
void set_solution_value(double value)
int index() const
Returns the index of the variable in the MPSolver::variables_.