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