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;
144 it=opts.find(
"verbose");
145 if (it != opts.end()) {
147 oracle_options[
"verbose"] = it->second;
152 return Function(
"rfp", rfp_in, rfp_out, {
"x",
"p"}, {
"g"}, oracle_options);
159 casadi_error(
"Cannot create '" + name +
"' since " +
str(f.
get_free()) +
" are free.");
180 "User-defined linear solver class. Needed for sensitivities."}},
181 {
"linear_solver_options",
183 "Options to be passed to the linear solver."}},
186 "Constrain the unknowns. 0 (default): no constraint on ui, "
187 "1: ui >= 0.0, -1: ui <= 0.0, 2: ui > 0.0, -2: ui < 0.0."}},
190 "Index of the input that corresponds to the actual root-finding"}},
193 "Index of the output that corresponds to the actual root-finding"}},
194 {
"jacobian_function",
196 "Function object for calculating the Jacobian (autogenerated by default)"}},
203 Dict linear_solver_options;
204 std::string linear_solver =
"qr";
208 for (
auto&& op : opts) {
209 if (op.first==
"implicit_input") {
211 }
else if (op.first==
"implicit_output") {
213 }
else if (op.first==
"jacobian_function") {
215 }
else if (op.first==
"linear_solver_options") {
216 linear_solver_options = op.second;
217 }
else if (op.first==
"linear_solver") {
218 linear_solver = op.second.to_string();
219 }
else if (op.first==
"constraints") {
226 "Implicit input not in range");
228 "Implicit output not in range");
231 "Residual must be a dense vector");
234 "Unknown must be a dense vector");
254 "Rootfinder::init: singularity - the jacobian is structurally rank-deficient. "
261 casadi_assert(
u_c_.size()==
n_ ||
u_c_.empty(),
262 "Constraint vector if supplied, must be of length n, but got "
287 casadi_int* iw,
double* w,
void* mem)
const {
289 setup(mem, arg, res, iw, w);
292 int ret =
solve(mem);
295 casadi_error(
"rootfinder process failed. "
296 "Set 'error_on_fail' option to false to ignore this error.");
302 casadi_int*& iw,
double*& w)
const {
320 const std::vector<std::string>& inames,
321 const std::vector<std::string>& onames,
322 const Dict& opts)
const {
324 std::vector<MX> arg = mx_in(), res = mx_out();
325 std::vector<std::vector<MX>> fseed = fwd_seed<MX>(nfwd), fsens;
327 for (
auto&& e : fseed) e[iin_] =
MX::sym(e[iin_].name(), e[iin_].size());
328 ad_forward(arg, res, fseed, fsens,
false,
false);
331 arg.insert(arg.end(), res.begin(), res.end());
332 std::vector<MX> v(nfwd);
333 for (casadi_int i=0; i<n_in_; ++i) {
334 for (casadi_int d=0; d<nfwd; ++d) v[d] = fseed[d][i];
335 arg.push_back(horzcat(v));
338 for (casadi_int i=0; i<n_out_; ++i) {
339 for (casadi_int d=0; d<nfwd; ++d) v[d] = fsens[d][i];
340 res.push_back(ensure_stacked(horzcat(v), sparsity_out(i), nfwd));
344 options[
"allow_duplicate_io_names"] =
true;
346 return Function(name, arg, res, inames, onames, options);
351 const std::vector<std::string>& inames,
352 const std::vector<std::string>& onames,
353 const Dict& opts)
const {
355 std::vector<MX> arg = mx_in();
356 arg[iin_] =
MX::sym(arg[iin_].name() +
"_guess",
358 std::vector<MX> res = mx_out();
359 std::vector<std::vector<MX> > aseed = symbolicAdjSeed(nadj, res), asens;
360 ad_reverse(arg, res, aseed, asens,
false,
false);
363 arg.insert(arg.end(), res.begin(), res.end());
364 std::vector<MX> v(nadj);
365 for (casadi_int i=0; i<n_out_; ++i) {
366 for (casadi_int d=0; d<nadj; ++d) v[d] = aseed[d][i];
367 arg.push_back(horzcat(v));
370 for (casadi_int i=0; i<n_in_; ++i) {
371 for (casadi_int d=0; d<nadj; ++d) v[d] = asens[d][i];
372 res.push_back(ensure_stacked(horzcat(v), sparsity_in(i), nadj));
376 options[
"allow_duplicate_io_names"] =
true;
377 return Function(name, arg, res, inames, onames, options);
387 std::copy(arg, arg+
n_in_, arg1);
388 arg1[
iin_] =
nullptr;
390 std::fill_n(res1,
n_out_,
static_cast<bvec_t*
>(
nullptr));
395 std::fill_n(tmp2,
n_, 0);
402 std::copy(res, res+
n_out_, res1);
403 res1[
iout_] =
nullptr;
410 casadi_int* iw,
bvec_t* w,
void* mem)
const {
417 std::fill_n(res[
iout_],
n_, 0);
419 std::fill_n(tmp1,
n_, 0);
424 std::copy(res, res+
n_out_, res1);
425 res1[
iout_] =
nullptr;
427 std::copy(arg, arg+
n_in_, arg1);
430 if (
oracle_.
rev(arg1, res1, iw, w, 0))
return 1;
434 std::fill_n(tmp2,
n_, 0);
438 for (casadi_int i=0; i<
n_out_; ++i) res1[i] =
nullptr;
440 arg1[
iin_] =
nullptr;
441 if (
oracle_.
rev(arg1, res1, iw, w, 0))
return 1;
447 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
448 std::mutex Rootfinder::mutex_solvers_;
454 ad_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
455 const std::vector<std::vector<MX> >& fseed,
456 std::vector<std::vector<MX> >& fsens,
457 bool always_inline,
bool never_inline)
const {
459 casadi_int nfwd = fseed.size();
466 std::vector<MX> f_arg(arg);
468 std::vector<MX> f_res(res);
470 std::vector<std::vector<MX> > f_fseed(fseed);
471 for (casadi_int d=0; d<nfwd; ++d) {
475 always_inline, never_inline);
479 MX J = jac(f_arg).front();
482 std::vector<MX> rhs(nfwd);
483 for (casadi_int d=0; d<nfwd; ++d) rhs[d] = vec(fsens[d][
iout_]);
485 for (casadi_int d=0; d<nfwd; ++d) fsens[d][
iout_] = reshape(rhs[d],
size_in(
iin_));
489 for (casadi_int d=0; d<nfwd; ++d) f_fseed[d][
iin_] = fsens[d][
iout_];
491 always_inline, never_inline);
492 for (casadi_int d=0; d<nfwd; ++d) fsens[d][
iout_] = f_fseed[d][
iin_];
497 ad_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
498 const std::vector<std::vector<MX> >& aseed,
499 std::vector<std::vector<MX> >& asens,
500 bool always_inline,
bool never_inline)
const {
503 casadi_int nadj = aseed.size();
510 std::vector<MX> f_arg(arg);
513 MX J = jac(f_arg).front();
516 std::vector<MX> f_res(res);
518 std::vector<std::vector<MX> > f_aseed(nadj);
519 for (casadi_int d=0; d<nadj; ++d) {
520 f_aseed[d].resize(
n_out_);
521 for (casadi_int i=0; i<
n_out_; ++i) f_aseed[d][i] = i==
iout_ ? f_res[
iout_] : aseed[d][i];
525 std::vector<MX> rhs(nadj);
526 std::vector<std::vector<MX> > asens_aux;
529 for (casadi_int d=0; d<nadj; ++d) rhs[d] = vec(asens_aux[d][
iin_] + aseed[d][
iout_]);
531 for (casadi_int d=0; d<nadj; ++d) rhs[d] = vec(aseed[d][
iout_]);
536 for (casadi_int d=0; d<nadj; ++d) {
537 for (casadi_int i=0; i<
n_out_; ++i) {
539 f_aseed[d][i] = reshape(rhs[d],
size_out(i));
548 std::vector<MX> tmp(nadj);
549 for (casadi_int d=0; d<nadj; ++d) {
550 asens[d].resize(
n_in_);
558 for (casadi_int d=0; d<nadj; ++d) {
559 asens[d][
iin_] = tmp[d];
564 for (casadi_int d=0; d<nadj; ++d) {
565 for (casadi_int i=0; i<
n_in_; ++i)
if (i!=
iin_) asens[d][i] += asens_aux[d][i];
582 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