26 #include "madnlp_interface.hpp"
28 #include "casadi/core/casadi_misc.hpp"
29 #include "../../core/global_options.hpp"
30 #include "../../core/casadi_interrupt.hpp"
31 #include "../../core/convexify.hpp"
41 #include <madnlp_runtime_str.h>
46 int CASADI_NLPSOL_MADNLP_EXPORT
49 plugin->name =
"madnlp";
51 plugin->version = CASADI_VERSION;
75 "Number of variables"}},
78 "Number of constraints"}},
81 "Options to be passed to madnlp"}},
82 {
"convexify_strategy",
84 "NONE|regularize|eigen-reflect|eigen-clip. "
85 "Strategy to convexify the Lagrange Hessian before passing it to the solver."}},
88 "When using a convexification strategy, make sure that "
89 "the smallest eigenvalue is at least this (default: 1e-7)."}},
95 casadi_int ncol = sp[1];
96 const casadi_int* colind = sp+2;
97 const casadi_int* row = colind+ncol+1;
99 for (casadi_int cc=0; cc<ncol; ++cc) {
100 for (casadi_int el=colind[cc]; el<colind[cc+1]; ++el) {
101 *coord_i++ = row[el]+1;
113 casadi_int struct_cnt=0;
116 std::string convexify_strategy =
"none";
117 double convexify_margin = 1e-7;
118 casadi_int max_iter_eig = 200;
125 for (
auto&& op : opts) {
126 if (op.first==
"convexify_strategy") {
127 convexify_strategy = op.second.to_string();
128 }
else if (op.first==
"convexify_margin") {
129 convexify_margin = op.second;
130 }
else if (op.first==
"max_iter") {
131 max_iter_eig = op.second;
132 }
else if (op.first==
"madnlp") {
139 auto hessian_approximation =
opts_.find(
"hessian_approximation");
140 if (hessian_approximation!=
opts_.end()) {
160 {
"tril:hess:gamma:x:x"}, {{
"gamma", {
"f",
"g"}}});
165 if (convexify_strategy!=
"none") {
168 opts[
"strategy"] = convexify_strategy;
169 opts[
"margin"] = convexify_margin;
170 opts[
"max_iter_eig"] = max_iter_eig;
195 std::vector<char*> _argv = {};
198 std::set<std::string> comp_values = {
"no",
"yes",
"min",
"max"};
200 auto comp =
opts_.find(
"compile");
201 if (comp!=
opts_.end()) {
202 std::string comp_value = comp->second;
203 if (comp_values.find(comp_value) != comp_values.end()) {
204 s =
"--compile=" + comp_value;
205 const int comp_l = s.length();
206 char* option_comp =
new char[comp_l + 1];
207 strcpy(option_comp, s.c_str());
208 _argv.push_back(option_comp);
210 std::cout <<
"Invalid value (" << comp_value <<
")for option 'compile'" << std::endl;
211 std::cout <<
"Available values are: ";
212 for (
auto v: comp_values) std::cout << v <<
" "; std::cout << std::endl;
216 auto trace_opt =
opts_.find(
"trace_compile");
217 if (trace_opt!=
opts_.end() &&
bool(trace_opt->second)) {
218 std::string trace_compile_output =
"stderr";
219 auto _trace_out_opt =
opts_.find(
"trace_compile_output");
220 if (_trace_out_opt!=
opts_.end())
221 trace_compile_output = (std::string) _trace_out_opt->second;
222 s =
"--trace-compile=" + trace_compile_output;
223 const int trace_l = s.length();
224 char* option_trace =
new char[trace_l + 1];
225 strcpy(option_trace, s.c_str());
226 _argv.push_back(option_trace);
229 int argc = _argv.size();
230 char** argv =
reinterpret_cast<char**
>(_argv.data());
233 init_julia(argc, argv);
234 std::cout <<
"Init julia runtime with options: "<< std::endl ;
235 for (
auto s: _argv) std::cout << s << std::endl;
244 madnlp_init_mem(&m->d);
251 madnlp_free_mem(&m->d);
257 casadi_int*& iw,
double*& w)
const {
264 m->d.
nlp = &m->d_nlp;
266 casadi_madnlp_init(&m->d, &arg, &res, &iw, &w);
268 m->d.nlp->oracle->m =
static_cast<void*
>(m);
276 casadi_madnlp_presolve(&m->d);
278 for (
const auto& kv :
opts_) {
279 switch (madnlp_c_option_type(kv.first.c_str())) {
281 madnlp_c_set_option_double(m->d.solver, kv.first.c_str(), kv.second);
284 madnlp_c_set_option_int(m->d.solver, kv.first.c_str(), kv.second.to_int());
287 madnlp_c_set_option_bool(m->d.solver, kv.first.c_str(), kv.second.to_bool());
291 std::string s = kv.second.to_string();
292 madnlp_c_set_option_string(m->d.solver, kv.first.c_str(), s.c_str());
296 casadi_error(
"Madnlp option not supported: " + kv.first);
298 casadi_error(
"Unknown option type.");
302 int ret = casadi_madnlp_solve(&m->d);
305 m->success = m->d.success;
314 stats[
"iter_count"] = m->
d.
stats.iter;
316 madnlp[
"dual_feas"] = m->d.stats.dual_feas;
317 madnlp[
"primal_feas"] = m->d.stats.primal_feas;
318 madnlp[
"status"] = m->d.stats.status;
319 stats[
"madnlp"] = madnlp;
342 casadi_madnlp_setup(&p_);
346 g <<
"madnlp_init_mem(&" +
codegen_mem(g) +
");\n";
352 g <<
"madnlp_free_mem(&" +
codegen_mem(g) +
");\n";
379 g.
local(
"d",
"struct casadi_madnlp_data*");
381 g.
local(
"p",
"struct casadi_madnlp_prob");
384 g <<
"casadi_madnlp_init(d, &arg, &res, &iw, &w);\n";
385 g <<
"casadi_oracle_init(d->nlp->oracle, &arg, &res, &iw, &w);\n";
386 g <<
"casadi_madnlp_presolve(d);\n";
388 for (
const auto& kv :
opts_) {
389 switch (madnlp_c_option_type(kv.first.c_str())) {
391 g <<
"madnlp_c_set_option_double(d->solver, \"" + kv.first +
"\", "
392 +
str(kv.second) +
");\n";
395 g <<
"madnlp_c_set_option_int(d->solver, \"" + kv.first +
"\", "
396 +
str(kv.second.to_int()) +
");\n";
399 g <<
"madnlp_c_set_option_bool(d->solver, \"" + kv.first +
"\", "
400 +
str(
static_cast<int>(kv.second.to_bool())) +
");\n";
404 std::string s = kv.second.to_string();
405 g <<
"madnlp_c_set_option_string(d->solver, \"" + kv.first +
"\", \""
410 casadi_error(
"Madnlp option not supported: " + kv.first);
412 casadi_error(
"Unknown option type.");
417 g <<
"casadi_madnlp_solve(d);\n";
422 g <<
"return d->unified_return_status;\n";
430 casadi_error(
"Empty sparsity pattern not supported in MADNLP C interface");
432 g <<
"d->nlp = &d_nlp;\n";
433 g <<
"d->prob = &p;\n";
434 g <<
"p.nlp = &p_nlp;\n";
446 g <<
"p.sp_h = 0;\n";
449 g <<
"casadi_madnlp_setup(&p);\n";
453 s.
version(
"MadnlpInterface", 1);
460 s.
unpack(
"MadnlpInterface::nzj_i", nzj_i_);
461 s.
unpack(
"MadnlpInterface::nzj_j", nzj_j_);
462 s.
unpack(
"MadnlpInterface::nzh_i", nzh_i_);
463 s.
unpack(
"MadnlpInterface::nzh_j", nzh_j_);
470 s.
version(
"MadnlpInterface", 1);
478 s.
pack(
"MadnlpInterface::nzj_i", nzj_i_);
479 s.
pack(
"MadnlpInterface::nzj_j", nzj_j_);
480 s.
pack(
"MadnlpInterface::nzh_i", nzh_i_);
481 s.
pack(
"MadnlpInterface::nzh_j", nzh_j_);
Helper class for C code generation.
std::string add_dependency(const Function &f)
Add a function dependency.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
void setup_callback(const std::string &s, const Function &f)
Setup a callback.
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 <....
std::string sparsity(const Sparsity &sp, bool canonical=true)
std::stringstream auxiliaries
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
static Sparsity setup(ConvexifyData &d, const Sparsity &H, const Dict &opts=Dict(), bool inplace=true)
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.
static bool julia_initialized
static const Options options_
Options.
MadnlpInterface(const std::string &name, const Function &nlp)
void codegen_init_mem(CodeGenerator &g) const override
Codegen alloc_mem.
Dict get_stats(void *mem) const override
Get all statistics.
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
void init(const Dict &opts) override
Initialize.
void codegen_free_mem(CodeGenerator &g) const override
Codegen free_mem.
static Nlpsol * creator(const std::string &name, const Function &nlp)
Create a new NLP Solver.
int init_mem(void *mem) const override
Initalize memory block.
bool convexify_
convexify?
void free_mem(void *mem) const override
Free memory block.
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.
~MadnlpInterface() override
static const std::string meta_doc
A documentation string.
bool exact_hessian_
Exact Hessian?
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
Dict opts_
All MADNLP options.
void codegen_body(CodeGenerator &g) const override
Generate code for the function body.
ConvexifyData convexify_data_
Data for convexification.
int solve(void *mem) const override
NLP solver storage class.
void codegen_body_exit(CodeGenerator &g) const override
Generate code for the function body.
Dict get_stats(void *mem) const override
Get all statistics.
static const Options options_
Options.
void codegen_body_enter(CodeGenerator &g) const override
Generate code for the function body.
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
void init(const Dict &opts) override
Initialize.
int init_mem(void *mem) const override
Initalize memory block.
casadi_nlpsol_prob< double > p_nlp_
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.
Function create_function(const Function &oracle, const std::string &fname, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const Function::AuxOut &aux=Function::AuxOut(), const Dict &opts=Dict())
std::vector< std::string > get_function() const override
Get list of dependency functions.
bool has_function(const std::string &fname) const override
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 size1() const
Get the number of rows.
bool is_tril(bool strictly=false) const
Is lower triangular?
casadi_int nnz() const
Get the number of (structural) non-zeros.
void CASADI_NLPSOL_MADNLP_EXPORT casadi_load_nlpsol_madnlp()
void casadi_madnlp_sparsity(const casadi_int *sp, madnlp_int *coord_i, madnlp_int *coord_j)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
int CASADI_NLPSOL_MADNLP_EXPORT casadi_register_nlpsol_madnlp(Nlpsol::Plugin *plugin)
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
casadi_madnlp_data< double > d
Options metadata for a class.
struct MadnlpCStats stats
OracleCallback nlp_hess_l
const casadi_nlpsol_prob< T1 > * nlp
OracleCallback nlp_grad_f