26 #include "rootfinder_impl.hpp"
27 #include "mx_node.hpp"
31 #include "global_options.hpp"
121 template<
typename XType>
127 rfp_in[
RFP_X]=i.second;
128 }
else if (i.first==
"p") {
129 rfp_in[
RFP_P]=i.second;
130 }
else if (i.first==
"g") {
131 rfp_out[
RFP_G]=i.second;
133 casadi_error(
"No such field: " + i.first);
139 Dict::const_iterator it = opts.find(
"oracle_options");
140 if (it!=opts.end()) {
142 oracle_options = it->second;
143 }
else if ((it=opts.find(
"verbose")) != opts.end()) {
145 oracle_options[
"verbose"] = it->second;
149 return Function(
"rfp", rfp_in, rfp_out, {
"x",
"p"}, {
"g"}, oracle_options);
156 casadi_error(
"Cannot create '" + name +
"' since " +
str(f.
get_free()) +
" are free.");
177 "User-defined linear solver class. Needed for sensitivities."}},
178 {
"linear_solver_options",
180 "Options to be passed to the linear solver."}},
183 "Constrain the unknowns. 0 (default): no constraint on ui, "
184 "1: ui >= 0.0, -1: ui <= 0.0, 2: ui > 0.0, -2: ui < 0.0."}},
187 "Index of the input that corresponds to the actual root-finding"}},
190 "Index of the output that corresponds to the actual root-finding"}},
191 {
"jacobian_function",
193 "Function object for calculating the Jacobian (autogenerated by default)"}},
200 Dict linear_solver_options;
201 std::string linear_solver =
"qr";
205 for (
auto&& op : opts) {
206 if (op.first==
"implicit_input") {
208 }
else if (op.first==
"implicit_output") {
210 }
else if (op.first==
"jacobian_function") {
212 }
else if (op.first==
"linear_solver_options") {
213 linear_solver_options = op.second;
214 }
else if (op.first==
"linear_solver") {
215 linear_solver = op.second.to_string();
216 }
else if (op.first==
"constraints") {
223 "Implicit input not in range");
225 "Implicit output not in range");
228 "Residual must be a dense vector");
231 "Unknown must be a dense vector");
251 "Rootfinder::init: singularity - the jacobian is structurally rank-deficient. "
258 casadi_assert(
u_c_.size()==
n_ ||
u_c_.empty(),
259 "Constraint vector if supplied, must be of length n, but got "
284 casadi_int* iw,
double* w,
void* mem)
const {
286 setup(mem, arg, res, iw, w);
289 int ret =
solve(mem);
292 casadi_error(
"rootfinder process failed. "
293 "Set 'error_on_fail' option to false to ignore this error.");
299 casadi_int*& iw,
double*& w)
const {
317 const std::vector<std::string>& inames,
318 const std::vector<std::string>& onames,
319 const Dict& opts)
const {
321 std::vector<MX> arg = mx_in(), res = mx_out();
322 std::vector<std::vector<MX>> fseed = fwd_seed<MX>(nfwd), fsens;
324 for (
auto&& e : fseed) e[iin_] =
MX::sym(e[iin_].name(), e[iin_].size());
325 ad_forward(arg, res, fseed, fsens,
false,
false);
328 arg.insert(arg.end(), res.begin(), res.end());
329 std::vector<MX> v(nfwd);
330 for (casadi_int i=0; i<n_in_; ++i) {
331 for (casadi_int d=0; d<nfwd; ++d) v[d] = fseed[d][i];
332 arg.push_back(horzcat(v));
335 for (casadi_int i=0; i<n_out_; ++i) {
336 for (casadi_int d=0; d<nfwd; ++d) v[d] = fsens[d][i];
337 res.push_back(ensure_stacked(horzcat(v), sparsity_out(i), nfwd));
341 options[
"allow_duplicate_io_names"] =
true;
343 return Function(name, arg, res, inames, onames, options);
348 const std::vector<std::string>& inames,
349 const std::vector<std::string>& onames,
350 const Dict& opts)
const {
352 std::vector<MX> arg = mx_in();
353 arg[iin_] =
MX::sym(arg[iin_].name() +
"_guess",
355 std::vector<MX> res = mx_out();
356 std::vector<std::vector<MX> > aseed = symbolicAdjSeed(nadj, res), asens;
357 ad_reverse(arg, res, aseed, asens,
false,
false);
360 arg.insert(arg.end(), res.begin(), res.end());
361 std::vector<MX> v(nadj);
362 for (casadi_int i=0; i<n_out_; ++i) {
363 for (casadi_int d=0; d<nadj; ++d) v[d] = aseed[d][i];
364 arg.push_back(horzcat(v));
367 for (casadi_int i=0; i<n_in_; ++i) {
368 for (casadi_int d=0; d<nadj; ++d) v[d] = asens[d][i];
369 res.push_back(ensure_stacked(horzcat(v), sparsity_in(i), nadj));
373 options[
"allow_duplicate_io_names"] =
true;
374 return Function(name, arg, res, inames, onames, options);
384 std::copy(arg, arg+
n_in_, arg1);
385 arg1[
iin_] =
nullptr;
387 std::fill_n(res1,
n_out_,
static_cast<bvec_t*
>(
nullptr));
392 std::fill_n(tmp2,
n_, 0);
399 std::copy(res, res+
n_out_, res1);
400 res1[
iout_] =
nullptr;
407 casadi_int* iw,
bvec_t* w,
void* mem)
const {
414 std::fill_n(res[
iout_],
n_, 0);
416 std::fill_n(tmp1,
n_, 0);
421 std::copy(res, res+
n_out_, res1);
422 res1[
iout_] =
nullptr;
424 std::copy(arg, arg+
n_in_, arg1);
427 if (
oracle_.
rev(arg1, res1, iw, w, 0))
return 1;
431 std::fill_n(tmp2,
n_, 0);
435 for (casadi_int i=0; i<
n_out_; ++i) res1[i] =
nullptr;
437 arg1[
iin_] =
nullptr;
438 if (
oracle_.
rev(arg1, res1, iw, w, 0))
return 1;
444 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
445 std::mutex Rootfinder::mutex_solvers_;
451 ad_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
452 const std::vector<std::vector<MX> >& fseed,
453 std::vector<std::vector<MX> >& fsens,
454 bool always_inline,
bool never_inline)
const {
456 casadi_int nfwd = fseed.size();
463 std::vector<MX> f_arg(arg);
465 std::vector<MX> f_res(res);
467 std::vector<std::vector<MX> > f_fseed(fseed);
468 for (casadi_int d=0; d<nfwd; ++d) {
472 always_inline, never_inline);
476 MX J = jac(f_arg).front();
479 std::vector<MX> rhs(nfwd);
480 for (casadi_int d=0; d<nfwd; ++d) rhs[d] = vec(fsens[d][
iout_]);
482 for (casadi_int d=0; d<nfwd; ++d) fsens[d][
iout_] = reshape(rhs[d],
size_in(
iin_));
486 for (casadi_int d=0; d<nfwd; ++d) f_fseed[d][
iin_] = fsens[d][
iout_];
488 always_inline, never_inline);
489 for (casadi_int d=0; d<nfwd; ++d) fsens[d][
iout_] = f_fseed[d][
iin_];
494 ad_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
495 const std::vector<std::vector<MX> >& aseed,
496 std::vector<std::vector<MX> >& asens,
497 bool always_inline,
bool never_inline)
const {
500 casadi_int nadj = aseed.size();
507 std::vector<MX> f_arg(arg);
510 MX J = jac(f_arg).front();
513 std::vector<MX> f_res(res);
515 std::vector<std::vector<MX> > f_aseed(nadj);
516 for (casadi_int d=0; d<nadj; ++d) {
517 f_aseed[d].resize(
n_out_);
518 for (casadi_int i=0; i<
n_out_; ++i) f_aseed[d][i] = i==
iout_ ? f_res[
iout_] : aseed[d][i];
522 std::vector<MX> rhs(nadj);
523 std::vector<std::vector<MX> > asens_aux;
526 for (casadi_int d=0; d<nadj; ++d) rhs[d] = vec(asens_aux[d][
iin_] + aseed[d][
iout_]);
528 for (casadi_int d=0; d<nadj; ++d) rhs[d] = vec(aseed[d][
iout_]);
533 for (casadi_int d=0; d<nadj; ++d) {
534 for (casadi_int i=0; i<
n_out_; ++i) {
536 f_aseed[d][i] = reshape(rhs[d],
size_out(i));
545 std::vector<MX> tmp(nadj);
546 for (casadi_int d=0; d<nadj; ++d) {
547 asens[d].resize(
n_in_);
555 for (casadi_int d=0; d<nadj; ++d) {
556 asens[d][
iin_] = tmp[d];
561 for (casadi_int d=0; d<nadj; ++d) {
562 for (casadi_int i=0; i<
n_in_; ++i)
if (i!=
iin_) asens[d][i] += asens_aux[d][i];
579 s.
pack(
"Rootfinder::n",
n_);
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
virtual void call_forward(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens, bool always_inline, bool never_inline) const
Forward mode AD, virtual functions overloaded in derived classes.
std::pair< casadi_int, casadi_int > size_in(casadi_int ind) const
Input/output dimensions.
virtual void call_reverse(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens, bool always_inline, bool never_inline) const
Reverse mode, virtual functions overloaded in derived classes.
size_t n_in_
Number of inputs and outputs.
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Input/output dimensions.
void serialize_type(SerializingStream &s) const override
Serialize type information.
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.
void setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
void alloc(const Function &f, bool persistent=false, int num_threads=1)
Ensure work vectors long enough to evaluate function.
static std::string string_from_UnifiedReturnStatus(UnifiedReturnStatus status)
casadi_int nnz_out() const
Get number of output nonzeros.
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
const std::vector< std::string > & name_in() const
Get input scheme.
const std::string & name() const
Name of the function.
static Function create(FunctionInternal *node)
Create from node.
int rev(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, int mem=0) const
Propagate sparsity backward.
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
casadi_int n_out() const
Get the number of function outputs.
casadi_int n_in() const
Get the number of function inputs.
std::vector< std::string > get_free() const
Get free variables as a string.
size_t sz_w() const
Get required length of w field.
bool has_free() const
Does the function have free variables.
casadi_int nnz_in() const
Get number of input nonzeros.
Function factory(const std::string &name, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const AuxOut &aux=AuxOut(), const Dict &opts=Dict()) const
const std::vector< std::string > & name_out() const
Get output scheme.
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
bool is_null() const
Is a null pointer?
virtual MX get_solve(const MX &r, bool tr, const Linsol &linear_solver) const
Solve a system of linear equations.
Base class for functions that perform calculation with an oracle.
void set_function(const Function &fcn, const std::string &fname, bool jit=false)
Function oracle_
Oracle: Used to generate other functions.
void init(const Dict &opts) override
int init_mem(void *mem) const override
Initalize memory block.
std::vector< std::string > get_function() const override
Get list of dependency functions.
static const Options options_
Options.
Dict get_stats(void *mem) const override
Get all statistics.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static bool has_plugin(const std::string &pname, bool verbose=false)
Check if a plugin is available or can be loaded.
static Rootfinder * instantiate(const std::string &fname, const std::string &pname, Problem problem)
void serialize_type(SerializingStream &s) const
Serialize type information.
static const Options & plugin_options(const std::string &pname)
Get the plugin options.
static Plugin & getPlugin(const std::string &pname)
Load and get the creator function.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static Plugin load_plugin(const std::string &pname, bool register_plugin=true, bool needs_lock=true)
Load a plugin dynamically.
Base class for FunctionInternal and LinsolInternal.
bool error_on_fail_
Throw an exception on failure?
virtual int solve(void *mem) const =0
int init_mem(void *mem) const override
Initalize memory block.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
casadi_int n_
Number of equations.
Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Generate a function that calculates nfwd forward derivatives.
~Rootfinder() override=0
Destructor.
Rootfinder(const std::string &name, const Function &oracle)
Constructor.
virtual void ad_reverse(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens, bool always_inline, bool never_inline) const
Create call to (cached) derivative function, reverse mode.
std::vector< casadi_int > u_c_
Constraints on decision variables.
Sparsity get_sparsity_out(casadi_int i) override
Sparsities of function inputs and outputs.
Dict get_stats(void *mem) const override
Get all statistics.
void serialize_type(SerializingStream &s) const override
Serialize type information.
static std::map< std::string, Plugin > solvers_
Collection of solvers.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
static const std::string infix_
Infix.
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate numerically.
virtual void ad_forward(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens, bool always_inline, bool never_inline) const
Create call to (cached) derivative function, forward mode.
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const override
Propagate sparsity forward.
casadi_int iin_
Indices of the input and output that correspond to the actual root-finding.
static const Options options_
Options.
Linsol linsol_
Linear solver.
Function get_reverse(casadi_int nadj, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Generate a function that calculates nadj adjoint derivatives.
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const override
Propagate sparsity backwards.
std::string get_name_in(casadi_int i) override
Names of function input and outputs.
static Function create_oracle(const std::map< std::string, XType > &d, const Dict &opts)
Convert dictionary to Problem.
void init(const Dict &opts) override
Initialize.
std::string get_name_out(casadi_int i) override
Names of function input and outputs.
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_column() const
Check if the pattern is a column vector (i.e. size2()==1)
void spsolve(bvec_t *X, bvec_t *B, bool tr) const
Propagate sparsity through a linear solve.
bool is_singular() const
Check whether the sparsity-pattern indicates structural singularity.
bool is_dense() const
Is dense?
std::string rootfinder_option_type(const std::string &name, const std::string &op)
Get type info for a particular option.
std::vector< std::string > rootfinder_in()
Get rootfinder input scheme.
casadi_int rootfinder_n_out()
Number of rootfinder outputs.
casadi_int rootfinder_n_in()
Number of rootfinder inputs.
void load_rootfinder(const std::string &name)
Explicitly load a plugin dynamically.
RootfinderInput
Input arguments of a rootfinder.
std::string rootfinder_option_info(const std::string &name, const std::string &op)
Get documentation for a particular option.
std::vector< std::string > rootfinder_options(const std::string &name)
Get all options for a plugin.
std::string doc_rootfinder(const std::string &name)
Get the documentation string for a plugin.
bool has_rootfinder(const std::string &name)
Check if a particular plugin is available.
std::vector< std::string > rootfinder_out()
Get rootfinder output scheme.
Function rootfinder(const std::string &name, const std::string &solver, const SXDict &rfp, const Dict &opts)
RootfinderOutput
Output arguments of a rootfinder.
@ ROOTFINDER_NUM_IN
Number of input arguments of a rootfinder.
@ ROOTFINDER_P
Parameters.
@ ROOTFINDER_X0
Initial guess for the solution.
@ ROOTFINDER_X
Solution to the system of equations.
@ ROOTFINDER_NUM_OUT
Number of output arguments of a rootfinder.
std::map< std::string, MX > MXDict
unsigned long long bvec_t
std::map< std::string, SX > SXDict
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
Options metadata for a class.
std::string type(const std::string &name) const
std::vector< std::string > all() const
std::string info(const std::string &name) const