26 #include "knitro_interface.hpp"
27 #include "casadi/core/casadi_misc.hpp"
32 #ifdef CASADI_WITH_THREAD
33 #ifdef CASADI_WITH_THREAD_MINGW
34 #include <mingw.thread.h>
43 int CASADI_NLPSOL_KNITRO_EXPORT
46 plugin->name =
"knitro";
48 plugin->version = CASADI_VERSION;
72 "Options to be passed to KNITRO"}},
75 "Read options from file (solver specific)"}},
76 {
"detect_linear_constraints",
78 "Detect type of constraints"}},
81 "Type of constraint"}},
84 "List of complementary constraints on simple bounds. "
85 "Pair (i, j) encodes complementarity between the bounds on variable i and variable j."}}
92 bool detect_linear_constraints =
true;
93 std::vector< std::vector<casadi_int> > complem_variables;
97 for (
auto&& op : opts) {
98 if (op.first==
"knitro") {
100 }
else if (op.first==
"options_file") {
102 }
else if (op.first==
"contype") {
104 }
else if (op.first==
"detect_linear_constraints") {
105 detect_linear_constraints = op.second;
106 }
else if (op.first==
"complem_variables") {
107 complem_variables = op.second;
114 if (detect_linear_constraints) {
116 for (casadi_int i=0;i<
ng_;++i)
117 contype_[i] = nl_g[i] ? KN_CONTYPE_GENERAL : KN_CONTYPE_LINEAR;
124 comp_type_.resize(complem_variables.size(), KN_CCTYPE_VARVAR);
125 comp_i1_.reserve(complem_variables.size());
126 comp_i2_.reserve(complem_variables.size());
127 for (
auto && e : complem_variables) {
128 casadi_assert(e.size()==2,
"Complementary constraints must come in pairs.");
129 casadi_assert(e[0]>=0,
"Invalid variable index.");
130 casadi_assert(e[1]>=0,
"Invalid variable index.");
131 casadi_assert(e[0]<
nx_,
"Invalid variable index.");
132 casadi_assert(e[1]<
nx_,
"Invalid variable index.");
140 jacg_sp_ = gf_jg_fcn.sparsity_out(1);
142 {
"triu:hess:gamma:x:x"},
143 {{
"gamma", {
"f",
"g"}}});
147 #ifdef CASADI_WITH_THREAD
149 hc = std::thread::hardware_concurrency();
151 int processor_count = hc ? hc : 8;
153 int ms_numthreads = 1;
154 int findiff_numthreads = 1;
156 int mip_numthreads = 1;
157 for (
auto&& op :
opts_) {
158 if (op.first==
"ms_numthreads") {
159 ms_numthreads = op.second;
161 if (op.first==
"findiff_numthreads") {
162 findiff_numthreads = op.second;
164 if (op.first==
"numthreads") {
165 numthreads = op.second;
167 if (op.first==
"mip_numthreads") {
168 mip_numthreads = op.second;
172 findiff_numthreads, numthreads, mip_numthreads});
191 casadi_int*& iw,
double*& w)
const {
198 m->wlbx = w; w +=
nx_;
199 m->wubx = w; w +=
nx_;
200 m->wlbg = w; w +=
ng_;
201 m->wubg = w; w +=
ng_;
206 uout() << s << std::flush;
212 auto d_nlp = &m->
d_nlp;
216 casadi_assert_dev(m->kc==
nullptr);
217 status = KN_new(&m->kc);
218 casadi_assert_dev(m->kc!=
nullptr);
221 casadi_assert(status == 0,
"KN_set_puts_callback failed");
224 std::vector<int> Jcol, Jrow;
232 casadi_assert(status==0,
"KN_load_param_file failed");
237 std::vector<int> Hcol, Hrow;
241 status = KN_set_int_param_by_name(m->kc,
"hessopt", KN_HESSOPT_EXACT);
242 casadi_assert(status==0,
"KN_set_int_param failed");
244 status = KN_set_int_param_by_name(m->kc,
"hessopt", KN_HESSOPT_LBFGS);
245 casadi_assert(status==0,
"KN_set_int_param failed");
249 for (
auto&& op :
opts_) {
251 casadi_assert(KN_get_param_id(m->kc, op.first.c_str(), ¶m_id)==0,
252 "Unknown parameter '" + op.first +
"'.");
255 casadi_assert(!KN_get_param_type(m->kc, param_id, ¶m_type),
256 "Error when setting option '" + op.first +
"'.");
258 switch (param_type) {
259 case KN_PARAMTYPE_INTEGER:
260 casadi_assert(!KN_set_int_param(m->kc, param_id, op.second),
261 "Error when setting option '" + op.first +
"'.");
263 case KN_PARAMTYPE_FLOAT:
264 casadi_assert(!KN_set_double_param(m->kc, param_id, op.second),
265 "Error when setting option '" + op.first +
"'.");
267 case KN_PARAMTYPE_STRING:
269 std::string
str = op.second.to_string();
270 casadi_assert(!KN_set_char_param(m->kc, param_id,
str.c_str()),
271 "Error when setting option '" + op.first +
"'.");
275 casadi_error(
"Error when setting option '" + op.first +
"'.");
284 for (casadi_int i=0; i<
nx_; ++i)
if (isinf(m->wlbx[i])) m->wlbx[i] = -KN_INFINITY;
285 for (casadi_int i=0; i<
nx_; ++i)
if (isinf(m->wubx[i])) m->wubx[i] = KN_INFINITY;
286 for (casadi_int i=0; i<
ng_; ++i)
if (isinf(m->wlbg[i])) m->wlbg[i] = -KN_INFINITY;
287 for (casadi_int i=0; i<
ng_; ++i)
if (isinf(m->wubg[i])) m->wubg[i] = KN_INFINITY;
289 std::vector<int> xindex(
nx_);
290 std::vector<int> gindex(
ng_);
291 iota(begin(xindex), end(xindex), 0);
292 iota(begin(gindex), end(gindex), 0);
294 status = KN_add_vars(m->kc,
nx_,
get_ptr(xindex));
295 casadi_assert(status==0,
"KN_add_vars failed");
296 status = KN_set_obj_goal(m->kc, KN_OBJGOAL_MINIMIZE);
297 casadi_assert(status==0,
"KN_set_obj_goal failed");
298 status = KN_set_var_lobnds_all(m->kc, m->wlbx);
299 casadi_assert(status==0,
"KN_set_var_lobnds failed");
300 status = KN_set_var_upbnds_all(m->kc, m->wubx);
301 casadi_assert(status==0,
"KN_set_var_upbnds failed");
302 status = KN_add_cons(m->kc,
ng_,
get_ptr(gindex));
303 casadi_assert(status==0,
"KN_add_cons failed");
304 status = KN_set_con_lobnds_all(m->kc, m->wlbg);
305 casadi_assert(status==0,
"KN_set_con_lobnds failed");
306 status = KN_set_con_upbnds_all(m->kc, m->wubg);
307 casadi_assert(status==0,
"KN_set_con_upbnds failed");
308 status = KN_set_var_primal_init_values_all(m->kc, d_nlp->z);
309 casadi_assert(status==0,
"KN_set_var_primal_init_values failed");
312 std::vector<int> vtype;
315 vtype.push_back(e ? KN_VARTYPE_INTEGER : KN_VARTYPE_CONTINUOUS);
317 status = KN_set_var_types_all(m->kc,
get_ptr(vtype));
318 casadi_assert(status==0,
"KN_set_var_types failed");
322 status = KN_set_compcons(m->kc,
comp_i1_.size(),
324 casadi_assert(status==0,
"KN_set_compcons failed");
328 casadi_assert(status==0,
"KN_add_eval_callback failed");
330 status = KN_set_cb_grad(m->kc, m->cb,
nx_,
get_ptr(xindex),
332 casadi_assert(status==0,
"KN_set_cb_grad failed");
336 casadi_assert(status==0,
"KN_set_cb_hess failed");
339 status = KN_set_cb_user_params(m->kc, m->cb,
static_cast<void*
>(m));
340 casadi_assert(status==0,
"KN_set_cb_user_params failed");
343 status = KN_set_int_param_by_name(m->kc,
"numthreads", 1);
344 casadi_assert(status==0,
"KN_set_cb_user_params failed");
347 std::vector<double> lambda(
nx_+
ng_);
353 status = KN_solve(m->kc);
354 int statusKnitro =
static_cast<int>(status);
357 m->success = status==KN_RC_OPTIMAL_OR_SATISFACTORY ||
358 status==KN_RC_NEAR_OPT;
359 if (status==KN_RC_ITER_LIMIT_FEAS ||
360 status==KN_RC_TIME_LIMIT_FEAS ||
361 status==KN_RC_FEVAL_LIMIT_FEAS ||
362 status==KN_RC_ITER_LIMIT_INFEAS ||
363 status==KN_RC_TIME_LIMIT_INFEAS ||
364 status==KN_RC_FEVAL_LIMIT_INFEAS)
369 error = KN_get_solution(m->kc, &statusKnitro, &objSol, d_nlp->z,
get_ptr(lambda));
370 casadi_assert(error == 0,
"KN_get_solution failed");
375 d_nlp->objective = objSol;
379 m->arg[0] = d_nlp->z;
380 m->arg[1] = d_nlp->p;
382 m->res[1] = d_nlp->z +
nx_;
387 status = KN_free(&m->kc);
388 casadi_assert(status == 0,
"KN_free failed");
395 KN_eval_request_ptr
const evalRequest,
396 KN_eval_result_ptr
const evalResult,
397 void *
const userParams) {
399 int thread_id = evalRequest->threadID;
404 auto d_nlp = &m->d_nlp;
407 switch (evalRequest->type) {
412 obj = evalResult->obj;
415 ml->arg[1] = d_nlp->p;
418 if (m->self.calc_function(m,
"nlp_fg",
nullptr, thread_id))
return KN_RC_EVAL_ERR;
424 objGrad = evalResult->objGrad;
425 jac = evalResult->jac;
427 ml->arg[1] = d_nlp->p;
428 ml->res[0] = objGrad;
430 if (m->self.calc_function(m,
"nlp_gf_jg",
nullptr, thread_id))
return KN_RC_EVAL_ERR;
432 case KN_RC_EVALH_NO_F:
434 const double *lambda;
438 hess = evalResult->hess;
439 lambda = evalRequest->lambda;
440 sigma = *(evalRequest->sigma);
442 ml->arg[1] = d_nlp->p;
446 if (m->self.calc_function(m,
"nlp_hess_l",
nullptr, thread_id)) {
447 casadi_error(
"calc_hess_l failed");
451 casadi_error(
"KnitroInterface::callback: unknown method");
456 return KN_RC_USER_TERMINATION;
457 }
catch(std::exception& ex) {
458 uerr() <<
"KnitroInterface::callback caught exception: "
459 << ex.
what() << std::endl;
467 case KN_RC_OPTIMAL_OR_SATISFACTORY:
return "KN_RC_OPTIMAL_OR_SATISFACTORY";
468 case KN_RC_NEAR_OPT:
return "KN_RC_NEAR_OPT";
469 case KN_RC_FEAS_XTOL:
return "KN_RC_FEAS_XTOL";
470 case KN_RC_FEAS_NO_IMPROVE:
return "KN_RC_FEAS_NO_IMPROVE";
471 case KN_RC_FEAS_FTOL:
return "KN_RC_FEAS_FTOL";
472 case KN_RC_INFEASIBLE:
return "KN_RC_INFEASIBLE";
473 case KN_RC_INFEAS_XTOL:
return "KN_RC_INFEAS_XTOL";
474 case KN_RC_INFEAS_NO_IMPROVE:
return "KN_RC_INFEAS_NO_IMPROVE";
475 case KN_RC_INFEAS_MULTISTART:
return "KN_RC_INFEAS_MULTISTART";
476 case KN_RC_INFEAS_CON_BOUNDS:
return "KN_RC_INFEAS_CON_BOUNDS";
477 case KN_RC_INFEAS_VAR_BOUNDS:
return "KN_RC_INFEAS_VAR_BOUNDS";
478 case KN_RC_UNBOUNDED:
return "KN_RC_UNBOUNDED";
479 case KN_RC_ITER_LIMIT_FEAS:
return "KN_RC_ITER_LIMIT_FEAS";
480 case KN_RC_TIME_LIMIT_FEAS:
return "KN_RC_TIME_LIMIT_FEAS";
481 case KN_RC_FEVAL_LIMIT_FEAS:
return "KN_RC_FEVAL_LIMIT_FEAS";
482 case KN_RC_MIP_EXH_FEAS:
return "KN_RC_MIP_EXH_FEAS";
483 case KN_RC_MIP_TERM_FEAS:
return "KN_RC_MIP_TERM_FEAS";
484 case KN_RC_MIP_SOLVE_LIMIT_FEAS:
return "KN_RC_MIP_SOLVE_LIMIT_FEAS";
485 case KN_RC_MIP_NODE_LIMIT_FEAS:
return "KN_RC_MIP_NODE_LIMIT_FEAS";
486 case KN_RC_ITER_LIMIT_INFEAS:
return "KN_RC_ITER_LIMIT_INFEAS";
487 case KN_RC_TIME_LIMIT_INFEAS:
return "KN_RC_TIME_LIMIT_INFEAS";
488 case KN_RC_FEVAL_LIMIT_INFEAS:
return "KN_RC_FEVAL_LIMIT_INFEAS";
489 case KN_RC_MIP_EXH_INFEAS:
return "KN_RC_MIP_EXH_INFEAS";
490 case KN_RC_MIP_SOLVE_LIMIT_INFEAS:
return "KN_RC_MIP_SOLVE_LIMIT_INFEAS";
491 case KN_RC_MIP_NODE_LIMIT_INFEAS:
return "KN_RC_MIP_NODE_LIMIT_INFEAS";
492 case KN_RC_CALLBACK_ERR:
return "KN_RC_CALLBACK_ERR";
493 case KN_RC_LP_SOLVER_ERR:
return "KN_RC_LP_SOLVER_ERR";
494 case KN_RC_EVAL_ERR:
return "KN_RC_EVAL_ERR";
495 case KN_RC_OUT_OF_MEMORY:
return "KN_RC_OUT_OF_MEMORY";
496 case KN_RC_USER_TERMINATION:
return "KN_RC_USER_TERMINATION";
497 case KN_RC_OPEN_FILE_ERR:
return "KN_RC_OPEN_FILE_ERR";
498 case KN_RC_BAD_N_OR_F:
return "KN_RC_BAD_N_OR_F";
499 case KN_RC_BAD_CONSTRAINT:
return "KN_RC_BAD_CONSTRAINT";
500 case KN_RC_BAD_JACOBIAN:
return "KN_RC_BAD_JACOBIAN";
501 case KN_RC_BAD_HESSIAN:
return "KN_RC_BAD_HESSIAN";
502 case KN_RC_BAD_CON_INDEX:
return "KN_RC_BAD_CON_INDEX";
503 case KN_RC_BAD_JAC_INDEX:
return "KN_RC_BAD_JAC_INDEX";
504 case KN_RC_BAD_HESS_INDEX:
return "KN_RC_BAD_HESS_INDEX";
505 case KN_RC_BAD_CON_BOUNDS:
return "KN_RC_BAD_CON_BOUNDS";
506 case KN_RC_BAD_VAR_BOUNDS:
return "KN_RC_BAD_VAR_BOUNDS";
507 case KN_RC_ILLEGAL_CALL:
return "KN_RC_ILLEGAL_CALL";
508 case KN_RC_BAD_KCPTR:
return "KN_RC_BAD_KCPTR";
509 case KN_RC_NULL_POINTER:
return "KN_RC_NULL_POINTER";
510 case KN_RC_BAD_INIT_VALUE:
return "KN_RC_BAD_INIT_VALUE";
511 case KN_RC_BAD_PARAMINPUT:
return "KN_RC_BAD_PARAMINPUT";
512 case KN_RC_LINEAR_SOLVER_ERR:
return "KN_RC_LINEAR_SOLVER_ERR";
513 case KN_RC_DERIV_CHECK_FAILED:
return "KN_RC_DERIV_CHECK_FAILED";
514 case KN_RC_DERIV_CHECK_TERMINATE:
return "KN_RC_DERIV_CHECK_TERMINATE";
515 case KN_RC_INTERNAL_ERROR:
return "KN_RC_INTERNAL_ERROR";
529 int version = s.
version(
"KnitroInterface", 1, 2);
546 s.
version(
"KnitroInterface", 2);
const char * what() const override
Display error.
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_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
std::vector< bool > which_depends(const std::string &s_in, const std::vector< std::string > &s_out, casadi_int order=1, bool tr=false) const
Which variables enter with some order.
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
bool is_null() const
Is a null pointer?
'knitro' plugin for Nlpsol
std::vector< int > comp_i1_
static int callback(KN_context_ptr kc, CB_context_ptr cb, KN_eval_request_ptr const evalRequest, KN_eval_result_ptr const evalResult, void *const userParams)
static const std::string meta_doc
A documentation string.
Dict get_stats(void *mem) const override
Get all statistics.
static Nlpsol * creator(const std::string &name, const Function &nlp)
Create a new NLP Solver.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
std::string options_file_
std::vector< int > comp_type_
static const Options options_
Options.
static const char * return_codes(int flag)
void init(const Dict &opts) override
Initialize.
int init_mem(void *mem) const override
Initalize memory block.
std::vector< int > comp_i2_
~KnitroInterface() override
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
std::vector< int > contype_
int solve(void *mem) const override
KnitroInterface(const std::string &name, const Function &nlp)
NLP solver storage class.
Dict get_stats(void *mem) const override
Get all statistics.
static const Options options_
Options.
void init(const Dict &opts) override
Initialize.
casadi_int ng_
Number of constraints.
int init_mem(void *mem) const override
Initalize memory block.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
std::vector< bool > discrete_
Options.
casadi_int nx_
Number of variables.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Function oracle_
Oracle: Used to generate other functions.
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())
int calc_function(OracleMemory *m, const std::string &fcn, const double *const *arg=nullptr, int thread_id=0) const
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
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.
std::vector< casadi_int > get_col() const
Get the column for each non-zero entry.
casadi_int nnz() const
Get the number of (structural) non-zeros.
std::vector< casadi_int > get_row() const
Get the row for each non-zero entry.
int casadi_KN_puts(const char *const str, void *const userParams)
void assign_vector(const std::vector< S > &s, std::vector< D > &d)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
void CASADI_NLPSOL_KNITRO_EXPORT casadi_load_nlpsol_knitro()
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_NLPSOL_KNITRO_EXPORT casadi_register_nlpsol_knitro(Nlpsol::Plugin *plugin)
~KnitroMemory()
Destructor.
KnitroMemory(const KnitroInterface &self)
Constructor.
const char * return_status
casadi_nlpsol_data< double > d_nlp
Options metadata for a class.
std::vector< LocalOracleMemory * > thread_local_mem