25 #include "mosek_interface.hpp"
26 #include "casadi/core/nlp_tools.hpp"
27 #include "casadi/core/casadi_misc.hpp"
29 #include <mosek_runtime_str.h>
37 int CASADI_CONIC_MOSEK_EXPORT
40 plugin->name =
"mosek";
42 plugin->version = CASADI_VERSION;
47 int ret = mosek_adaptor_load(buffer,
sizeof(buffer));
49 casadi_warning(
"Failed to load Mosek adaptor: " + std::string(buffer) +
".");
63 const std::map<std::string, Sparsity>& st)
71 "Options to be passed to MOSEK. Each entry's key is the MOSEK "
72 "parameter name (e.g. \"MSK_IPAR_LOG\", \"MSK_DPAR_INTPNT_QO_TOL_REL_GAP\"); "
73 "the value's type must match the parameter's type "
74 "(int parameters take int, dpar take double, spar take string)."
84 for (
auto&& op : opts) {
85 if (op.first==
"mosek") {
93 if (has_socp_) build_socp_config();
109 colinda_.resize(
A_.
size2() + 1);
110 rowa_.resize(
A_.
nnz());
118 qobj_nz_idx_.clear();
120 const casadi_int* Hr =
H_.
row();
121 for (casadi_int j = 0; j <
H_.
size2(); ++j) {
122 for (casadi_int k = Hc[j]; k < Hc[j + 1]; ++k) {
123 casadi_int i = Hr[k];
125 qobj_row_.push_back(
static_cast<int>(i));
126 qobj_col_.push_back(
static_cast<int>(j));
127 qobj_nz_idx_.push_back(
static_cast<int>(k));
137 bool any_discrete =
false;
138 for (
bool d :
discrete_)
if (d) { any_discrete =
true;
break; }
140 coltype_.assign(
nx_,
'C');
141 for (casadi_int i = 0; i <
nx_; ++i) {
154 p_.
nquad =
static_cast<int>(qobj_row_.size());
157 p_.
socp = has_socp_ ? &socp_ :
nullptr;
159 casadi_mosek_setup(&p_);
166 const std::string& local_name,
const std::vector<int>& v) {
168 g <<
"p." << prob_field <<
" = 0;\n";
170 g.
constant_copy(local_name, vector_static_cast<casadi_int>(v),
"int");
171 g <<
"p." << prob_field <<
" = " << local_name <<
";\n";
176 g <<
"p.qp = &p_qp;\n";
183 g <<
"p.nquad = " << qobj_row_.size() <<
";\n";
185 if (coltype_.empty()) {
186 g <<
"p.coltype = 0;\n";
188 g <<
"p.coltype = " << g.
constant(coltype_) <<
";\n";
192 g.
local(
"socp_p",
"struct casadi_socp_prob");
193 g <<
"socp_p.n_blocks = " << socp_.
n_blocks <<
";\n";
194 g <<
"socp_p.n_lifted = " << socp_.
n_lifted <<
";\n";
195 g <<
"socp_p.nx = " << socp_.
nx <<
";\n";
196 g <<
"socp_p.r = " << g.
constant(socp_r_) <<
";\n";
197 g <<
"socp_p.mq_colind = " << g.
constant(socp_mq_colind_) <<
";\n";
198 g <<
"socp_p.mq_row = " << g.
constant(socp_mq_row_) <<
";\n";
199 g <<
"socp_p.mq_data = " << g.
constant(socp_mq_data_) <<
";\n";
200 g <<
"socp_p.map_P = " << g.
constant(socp_map_P_) <<
";\n";
201 g <<
"casadi_socp_setup(&socp_p);\n";
202 g <<
"p.socp = &socp_p;\n";
204 g <<
"p.socp = 0;\n";
207 g <<
"casadi_mosek_setup(&p);\n";
211 g <<
"casadi_mosek_init_mem(&" +
codegen_mem(g) +
");\n";
216 g <<
"casadi_mosek_free_mem(&" +
codegen_mem(g) +
");\n";
228 g.
local(
"d",
"struct casadi_mosek_data*");
230 g.
local(
"p",
"struct casadi_mosek_prob");
233 g <<
"d->prob = &p;\n";
234 g <<
"d->qp = &d_qp;\n";
235 g <<
"casadi_mosek_set_work(d, &arg, &res, &iw, &w);\n";
238 g <<
"d->socp.q = arg[" <<
CONIC_Q <<
"];\n";
239 g <<
"d->socp.p = arg[" <<
CONIC_P <<
"];\n";
246 for (
auto&& op :
opts_) {
247 if (op.second.is_double()) {
248 g <<
"MSK_putnadouparam(d->task, " << g.
constant(op.first) <<
", "
249 << op.second.to_double() <<
");\n";
250 }
else if (op.second.is_int() || op.second.is_bool()) {
251 g <<
"MSK_putnaintparam(d->task, " << g.
constant(op.first) <<
", "
252 <<
static_cast<int>(op.second.to_int()) <<
");\n";
253 }
else if (op.second.is_string()) {
254 g <<
"MSK_putnastrparam(d->task, " << g.
constant(op.first) <<
", "
255 << g.
constant(op.second.to_string()) <<
");\n";
257 casadi_error(
"Unsupported option type for '" + op.first +
"'.");
261 g <<
"casadi_mosek_solve(d, arg, res, iw, w);\n";
263 g <<
"if (!d_qp.success) {\n";
265 g <<
" return -1000;\n";
267 g <<
" return -1;\n";
273 void MosekInterface::build_socp_config() {
278 casadi_int n_eq = sm.map_Q.size2();
279 socp_mq_colind_.assign(sm.map_Q.colind(), sm.map_Q.colind() + n_eq + 1);
280 socp_mq_row_.assign(sm.map_Q.row(), sm.map_Q.row() + sm.map_Q.nnz());
281 socp_mq_data_.assign(sm.map_Q.ptr(), sm.map_Q.ptr() + sm.map_Q.nnz());
282 socp_map_P_ = sm.map_P;
284 socp_.
n_blocks =
static_cast<casadi_int
>(sm.r.size() - 1);
292 casadi_socp_setup(&socp_);
302 if (casadi_mosek_init_mem(&m->d)) {
303 casadi_error(
"MOSEK: MSK_makeenv()/MSK_maketask() failed. "
304 "Check that the MOSEK license is reachable "
305 "(MOSEKLM_LICENSE_FILE or $HOME/mosek/mosek.lic).");
308 MSK_linkfunctotaskstream(m->d.task, MSK_STREAM_LOG,
nullptr,
mosek_stream_cb);
311 m->add_stat(
"preprocessing");
312 m->add_stat(
"solver");
313 m->add_stat(
"postprocessing");
320 casadi_mosek_free_mem(&m->d);
326 casadi_int*& iw,
double*& w)
const {
335 casadi_mosek_set_work(&m->d, &arg, &res, &iw, &w);
348 for (
auto&& op :
opts_) {
349 MSKrescodee rc = MSK_RES_OK;
350 if (op.second.is_double()) {
351 rc = MSK_putnadouparam(m->d.task, op.first.c_str(), op.second.to_double());
352 }
else if (op.second.is_int() || op.second.is_bool()) {
353 rc = MSK_putnaintparam(m->d.task, op.first.c_str(),
354 static_cast<int>(op.second.to_int()));
355 }
else if (op.second.is_string()) {
356 rc = MSK_putnastrparam(m->d.task, op.first.c_str(),
357 op.second.to_string().c_str());
359 casadi_error(
"MOSEK: unsupported value type for parameter '"
362 casadi_assert(rc == MSK_RES_OK,
363 "MOSEK: failed to set parameter '" + op.first +
"' (rc=" +
str(rc) +
").");
368 solve(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
371 m->
fstats.at(
"solver").tic();
372 int rc = casadi_mosek_solve(&m->d, arg, res, iw, w);
373 m->fstats.at(
"solver").toc();
386 stats[
"prob_status"] = m->d.prob_status;
387 stats[
"sol_status"] = m->d.sol_status;
388 stats[
"objective"] = m->d.obj_val;
393 s.
version(
"MosekInterface", 1);
396 if (has_socp_) build_socp_config();
404 s.
version(
"MosekInterface", 1);
Helper class for C code generation.
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
void init_local(const std::string &name, const std::string &def)
Specify the default value for a local variable.
std::string sanitize_source(const std::string &src, const std::vector< std::string > &inst, bool add_shorthand=true)
Sanitize source files for codegen.
void add_include(const std::string &new_include, bool relative_path=false, const std::string &use_ifdef=std::string())
Add an include file optionally using a relative path "..." instead of an absolute path <....
void constant_copy(const std::string &var_name, const std::vector< casadi_int > &v, const std::string &type="casadi_int")
Represent an array constant; adding it when new.
std::stringstream auxiliaries
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
static const Options options_
Options.
casadi_int nx_
Number of decision variables.
int init_mem(void *mem) const override
Initalize memory block.
Sparsity H_
Problem structure.
void init(const Dict &opts) override
Initialize.
std::vector< bool > discrete_
Options.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Dict get_stats(void *mem) const override
Get all statistics.
casadi_qp_prob< double > p_qp_
void qp_codegen_body(CodeGenerator &g) const
Generate code for the function body.
void sdp_to_socp_init(SDPToSOCPMem &mem) const
SDP to SOCP conversion initialization.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
void alloc_res(size_t sz_res, bool persistent=false)
Ensure required length of res field.
void alloc_arg(size_t sz_arg, bool persistent=false)
Ensure required length of arg field.
std::string codegen_mem(CodeGenerator &g, const std::string &index="mem") const
Get thread-local memory object.
size_t sz_res() const
Get required length of res field.
size_t sz_w() const
Get required length of w field.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
size_t sz_arg() const
Get required length of arg field.
size_t sz_iw() const
Get required length of iw field.
bool is_null() const
Is a null pointer?
void codegen_body(CodeGenerator &g) const override
Generate code for the function body.
void init(const Dict &opts) override
Initialize.
Dict get_stats(void *mem) const override
Get all statistics.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
void codegen_free_mem(CodeGenerator &g) const override
Codegen for free_mem.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
void free_mem(void *mem) const override
Free memory block.
int init_mem(void *mem) const override
Initalize memory block.
int solve(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Solve the QP.
void codegen_init_mem(CodeGenerator &g) const override
Codegen init for init_mem.
static const std::string meta_doc
A documentation string.
~MosekInterface() override
Destructor.
Dict opts_
All Mosek parameters (by name -> value)
MosekInterface(const std::string &name, const std::map< std::string, Sparsity > &st)
Constructor using sparsity patterns.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static Conic * creator(const std::string &name, const std::map< std::string, Sparsity > &st)
Create a new QP Solver.
static const Options options_
Options.
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
bool error_on_fail_
Throw an exception on failure?
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 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_Q
The matrix Q: sparse symmetric, (np^2 x n)
@ CONIC_P
The matrix P: sparse symmetric, (np x np)
static void mosek_stream_cb(void *, const char *s)
static void codegen_int_field(CodeGenerator &g, const std::string &prob_field, const std::string &local_name, const std::vector< int > &v)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
int CASADI_CONIC_MOSEK_EXPORT casadi_register_conic_mosek(Conic::Plugin *plugin)
void CASADI_CONIC_MOSEK_EXPORT casadi_load_conic_mosek()
casadi_mosek_data< double > d
Options metadata for a class.
std::map< std::string, FStats > fstats
const casadi_socp_prob< T1 > * socp
const casadi_qp_prob< T1 > * qp
const casadi_int * mq_colind
const casadi_int * mq_row
const casadi_int * mq_data