25 #include "clp_interface.hpp"
30 int CASADI_CONIC_CLP_EXPORT
35 plugin->version = CASADI_VERSION;
48 const std::map<std::string, Sparsity>& st)
56 "Options to be passed to CLP. "
57 "A first set of options can be found in ClpParameters.hpp. eg. 'PrimalTolerance'. "
58 "There are other options in additions. "
59 "'AutomaticScaling' (bool) is recognised. "
60 "'initial_solve' (default off) activates the use of Clp's initialSolve. "
61 "'initial_solve_options' takes a dictionary with following keys (see ClpSolve.hpp): "
62 " SolveType (string), PresolveType (string), "
63 " NumberPasses, SpecialOptions (intvectorvector), IndependentOptions (intvectorvector)."
73 return "primal infeasible";
75 return "dual infeasible";
77 return "stopped on iterations or time";
79 return "stopped due to errors";
81 return "stopped by event handler";
87 std::map<std::string, ClpIntParam> ClpInterface::param_map_int = {
88 {
"MaxNumIteration", ClpMaxNumIteration},
89 {
"MaxNumIterationHotStart", ClpMaxNumIterationHotStart},
90 {
"NameDiscipline", ClpMaxNumIteration},
93 std::map<std::string, ClpDblParam> ClpInterface::param_map_double = {
94 {
"DualObjectiveLimit", ClpDualObjectiveLimit},
95 {
"PrimalObjectiveLimit", ClpPrimalObjectiveLimit},
96 {
"DualTolerance", ClpDualTolerance},
97 {
"PrimalTolerance", ClpPrimalTolerance},
98 {
"ObjOffset", ClpObjOffset},
99 {
"MaxSeconds", ClpMaxSeconds},
100 {
"MaxWallSeconds", ClpMaxWallSeconds},
101 {
"PresolveTolerance", ClpPresolveTolerance}
104 std::map<std::string, ClpSolve::SolveType> ClpInterface::param_map_solvetype = {
105 {
"useDual", ClpSolve::useDual},
106 {
"usePrimal", ClpSolve::usePrimal},
107 {
"usePrimalorSprint", ClpSolve::usePrimal},
108 {
"useBarrier", ClpSolve::useBarrier},
109 {
"useBarrierNoCross", ClpSolve::useBarrierNoCross},
110 {
"automatic", ClpSolve::automatic},
111 {
"tryDantzigWolfe", ClpSolve::tryDantzigWolfe},
112 {
"tryBenders", ClpSolve::tryBenders},
115 std::map<std::string, ClpSolve::PresolveType> ClpInterface::param_map_presolvetype = {
116 {
"presolveOn", ClpSolve::presolveOn},
117 {
"presolveOff", ClpSolve::presolveOff},
118 {
"presolveNumber", ClpSolve::presolveNumber},
119 {
"presolveNumberCost", ClpSolve::presolveNumberCost}
128 return "primal infeasible because dual limit reached OR (probably primal"
129 " infeasible but can't prove it - main status was 4)";
131 return "scaled problem optimal - unscaled problem has primal infeasibilities";
133 return "scaled problem optimal - unscaled problem has dual infeasibilities";
135 return "scaled problem optimal - unscaled problem has primal and dual infeasibilities";
137 return "giving up in primal with flagged variables";
139 return "failed due to empty problem check";
141 return "postSolve says not optimal";
143 return "failed due to bad element check";
145 return "status was 3 and stopped on time";
147 return "status was 3 but stopped as primal feasibles";
148 case ClpEventHandler::Event::endOfIteration:
149 return "endOfIteration";
150 case ClpEventHandler::Event::endOfFactorization:
151 return "endOfFactorization";
152 case ClpEventHandler::Event::endOfValuesPass:
153 return "endOfValuesPass";
154 case ClpEventHandler::Event::node:
156 case ClpEventHandler::Event::treeStatus:
158 case ClpEventHandler::Event::solution:
160 case ClpEventHandler::Event::theta:
162 case ClpEventHandler::Event::pivotRow:
164 case ClpEventHandler::Event::presolveStart:
165 return "presolveStart";
166 case ClpEventHandler::Event::presolveSize:
167 return "presolveSize";
168 case ClpEventHandler::Event::presolveInfeasible:
169 return "presolveInfeasible";
170 case ClpEventHandler::Event::presolveBeforeSolve:
171 return "presolveBeforeSolve";
172 case ClpEventHandler::Event::presolveAfterFirstSolve:
173 return "presolveAfterFirstSolve";
174 case ClpEventHandler::Event::presolveAfterSolve:
175 return "presolveAfterSolve";
176 case ClpEventHandler::Event::presolveEnd:
177 return "presolveEnd";
178 case ClpEventHandler::Event::goodFactorization:
179 return "goodFactorization";
180 case ClpEventHandler::Event::complicatedPivotIn:
181 return "complicatedPivotIn";
182 case ClpEventHandler::Event::noCandidateInPrimal:
183 return "noCandidateInPrimal";
184 case ClpEventHandler::Event::looksEndInPrimal:
185 return "looksEndInPrimal";
186 case ClpEventHandler::Event::endInPrimal:
187 return "endInPrimal";
188 case ClpEventHandler::Event::beforeStatusOfProblemInPrimal:
189 return "beforeStatusOfProblemInPrimal";
190 case ClpEventHandler::Event::startOfStatusOfProblemInPrimal:
191 return "startOfStatusOfProblemInPrimal";
192 case ClpEventHandler::Event::complicatedPivotOut:
193 return "complicatedPivotOut";
194 case ClpEventHandler::Event::noCandidateInDual:
195 return "noCandidateInDual";
196 case ClpEventHandler::Event::looksEndInDual:
197 return "looksEndInDual";
198 case ClpEventHandler::Event::endInDual:
200 case ClpEventHandler::Event::beforeStatusOfProblemInDual:
201 return "beforeStatusOfProblemInDual";
202 case ClpEventHandler::Event::startOfStatusOfProblemInDual:
203 return "startOfStatusOfProblemInDual";
204 case ClpEventHandler::Event::startOfIterationInDual:
205 return "startOfIterationInDual";
206 case ClpEventHandler::Event::updateDualsInDual:
207 return "updateDualsInDual";
208 case ClpEventHandler::Event::endOfCreateRim:
209 return "endOfCreateRim";
210 case ClpEventHandler::Event::slightlyInfeasible:
211 return "slightlyInfeasible";
212 case ClpEventHandler::Event::modifyMatrixInMiniPresolve:
213 return "modifyMatrixInMiniPresolve";
214 case ClpEventHandler::Event::moreMiniPresolve:
215 return "moreMiniPresolve";
216 case ClpEventHandler::Event::modifyMatrixInMiniPostsolve:
217 return "modifyMatrixInMiniPostsolve";
218 case ClpEventHandler::Event::startOfCrossover:
219 return "startOfCrossover";
220 case ClpEventHandler::Event::noTheta:
227 class CasadiHandler :
public CoinMessageHandler {
229 virtual int print() ;
232 int CasadiHandler::print() {
233 uout() << messageBuffer() << std::endl;
242 casadi_assert(
H_.
nnz()==0,
"Not an LP");
245 for (
auto&& op : opts) {
246 if (op.first==
"clp") {
267 m->add_stat(
"solver");
268 m->add_stat(
"postprocessing");
270 m->colind.resize(
A_.
size2()+1);
271 m->row.resize(
A_.
nnz());
277 solve(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
282 m->secondary_return_status = -1;
285 m->fstats.at(
"preprocessing").tic();
288 double* g=w; w +=
nx_;
290 double* lbx=w; w +=
nx_;
292 double* ubx=w; w +=
nx_;
294 double* lba=w; w +=
na_;
296 double* uba=w; w +=
na_;
309 bool initial_solve =
false;
310 Dict initial_solve_options;
313 for (
auto&& op :
opts_) {
315 auto it = param_map_double.find(op.first);
316 if (it!=param_map_double.end()) {
317 casadi_assert(model.setDblParam(it->second, op.second.to_double()),
318 "Error setting option '" + op.first +
"'.");
322 auto it2 = param_map_int.find(op.first);
323 if (it2!=param_map_int.end()) {
324 casadi_assert(model.setIntParam(it2->second, op.second.to_int()),
325 "Error setting option '" + op.first +
"'.");
326 }
else if (op.first==
"AutomaticScaling") {
327 model.setAutomaticScaling(op.second.to_bool());
328 }
else if (op.first==
"initial_solve") {
329 initial_solve = op.second.to_bool();
330 }
else if (op.first==
"initial_solve_options") {
331 initial_solve_options = op.second.to_dict();
333 casadi_error(
"Unknown option '" + op.first +
"'.");
338 lbx, ubx, g, lba, uba,
nullptr);
341 model.passInMessageHandler(&ch);
343 m->fstats.at(
"preprocessing").toc();
344 m->fstats.at(
"solver").tic();
348 int numberPasses = -1;
349 ClpSolve::SolveType solveType = ClpSolve::automatic;
350 ClpSolve::PresolveType presolveType = ClpSolve::presolveOn;
351 std::vector< std::vector<int> > specialOptions;
352 std::vector< std::vector<int> > independentOptions;
354 for (
auto&& op : initial_solve_options) {
355 if (op.first==
"SolveType") {
356 auto it = param_map_solvetype.find(op.second.to_string());
357 casadi_assert(it!=param_map_solvetype.end(),
358 "SolveType ' " + op.second.to_string() +
"' not recognised.");
359 solveType = it->second;
360 }
else if (op.first==
"PresolveType") {
361 auto it = param_map_presolvetype.find(op.second);
362 casadi_assert(it!=param_map_presolvetype.end(),
363 "PresolveType ' " + op.second.to_string() +
"' not recognised.");
364 presolveType = it->second;
365 }
else if (op.first==
"NumberPasses") {
366 numberPasses = op.second.to_int();
367 }
else if (op.first==
"SpecialOptions") {
368 specialOptions =
to_int(op.second.to_int_vector_vector());
369 }
else if (op.first==
"IndependentOptions") {
370 independentOptions =
to_int(op.second.to_int_vector_vector());
372 casadi_error(
"Option not recognised: '" + op.first +
"'");
375 solvectl.setSolveType(solveType);
376 solvectl.setPresolveType(presolveType, numberPasses);
379 for (
auto const& v : specialOptions) {
381 solvectl.setSpecialOption(v[0], v[1]);
382 }
else if (v.size()==3) {
383 solvectl.setSpecialOption(v[0], v[1], v[2]);
385 casadi_error(
"SpecialOptions entries must be of length 2 or 3.");
389 for (
auto const& v : independentOptions) {
391 solvectl.setIndependentOption(v[0], v[1]);
393 casadi_error(
"SpecialOptions entries must be of length 2.");
396 model.initialSolve(solvectl);
402 m->fstats.at(
"solver").toc();
403 m->fstats.at(
"postprocessing").tic();
406 double* x = model.primalColumnSolution();
410 double* minus_lam_x = model.dualColumnSolution();
417 double* minus_lam_a = model.dualRowSolution();
424 double f = model.rawObjectiveValue();
427 m->fstats.at(
"postprocessing").toc();
428 m->return_status = model.status();
429 m->d_qp.success = m->return_status==0;
430 m->secondary_return_status = model.secondaryStatus();
ClpInterface(const std::string &name, const std::map< std::string, Sparsity > &st)
Constructor using sparsity patterns.
int solve(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Solve the QP.
static Conic * creator(const std::string &name, const std::map< std::string, Sparsity > &st)
Create a new QP Solver.
~ClpInterface() override
Destructor.
void init(const Dict &opts) override
Initialize.
int init_mem(void *mem) const override
Initalize memory block.
static const std::string meta_doc
A documentation string.
Dict opts_
All CLP options.
static const Options options_
Options.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Dict get_stats(void *mem) const override
Get all statistics.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static const Options options_
Options.
casadi_int nx_
Number of decision variables.
int init_mem(void *mem) const override
Initalize memory block.
casadi_int na_
The number of constraints (counting both equality and inequality) == A.size1()
Sparsity H_
Problem structure.
void init(const Dict &opts) override
Initialize.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Dict get_stats(void *mem) const override
Get all statistics.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
casadi_int nnz_in() const
Number of input/output nonzeros.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
bool verbose_
Verbose printout.
void clear_mem()
Clear all memory (called from destructor)
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
casadi_int size1() const
Get the number of rows.
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
void copy_vector(const std::vector< S > &s, std::vector< D > &d)
@ CONIC_UBA
dense, (nc x 1)
@ CONIC_A
The matrix A: sparse, (nc x n) - product with x must be dense.
@ CONIC_G
The vector g: dense, (n x 1)
@ CONIC_LBA
dense, (nc x 1)
@ CONIC_UBX
dense, (n x 1)
@ CONIC_LBX
dense, (n x 1)
int to_int(casadi_int rhs)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
const char * return_status_string(Bonmin::TMINLP::SolverReturn status)
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void CASADI_CONIC_CLP_EXPORT casadi_load_conic_clp()
void casadi_scal(casadi_int n, T1 alpha, T1 *x)
SCAL: x <- alpha*x.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
std::string return_secondary_status_string(int status)
int CASADI_CONIC_CLP_EXPORT casadi_register_conic_clp(Conic::Plugin *plugin)
@ CONIC_X
The primal solution.
@ CONIC_LAM_A
The dual solution corresponding to linear bounds.
@ CONIC_COST
The optimal cost.
@ CONIC_LAM_X
The dual solution corresponding to simple bounds.
Options metadata for a class.
void add_stat(const std::string &s)