1#ifndef STAN_MATH_REV_FUNCTOR_FP_SOLVER_HPP
2#define STAN_MATH_REV_FUNCTOR_FP_SOLVER_HPP
14#include <sundials/sundials_context.h>
15#include <kinsol/kinsol.h>
16#include <sunmatrix/sunmatrix_dense.h>
17#include <sunlinsol/sunlinsol_dense.h>
18#include <nvector/nvector_serial.h>
44 const Eigen::VectorXd&
y_;
50 const std::vector<double>&
x_r_;
52 const std::vector<int>&
x_i_;
65 template <
typename T,
typename T_u,
typename T_f>
67 const Eigen::VectorXd& y,
const std::vector<double>& x_r,
68 const std::vector<int>& x_i, std::ostream* msgs,
69 const std::vector<T_u>& u_scale,
70 const std::vector<T_f>& f_scale)
84 for (
int i = 0; i <
N_; ++i) {
92 template <
typename T,
typename T_u,
typename T_f>
94 const Eigen::Matrix<stan::math::var, -1, 1>& y,
95 const std::vector<double>& x_r,
96 const std::vector<int>& x_i, std::ostream* msgs,
97 const std::vector<T_u>& u_scale,
98 const std::vector<T_f>& f_scale)
112 for (
int i = 0; i <
N_; ++i) {
120 N_VDestroy_Serial(
nv_x_);
129 Eigen::VectorXd x_eigen(Eigen::Map<Eigen::VectorXd>(NV_DATA_S(x), g->N_));
130 Eigen::Map<Eigen::VectorXd>(N_VGetArrayPointer(f), g->N_)
131 = g->f_(x_eigen, g->
y_, g->x_r_, g->x_i_, g->msgs_);
162 template <
typename F>
164 const Eigen::VectorXd& x,
const Eigen::Matrix<stan::math::var, -1, 1>& y,
170 auto g = [&env](
const Eigen::Matrix<
var, -1, 1>& par_) {
171 Eigen::Matrix<
var, -1, 1> x_(par_.head(env.
N_));
172 Eigen::Matrix<
var, -1, 1> y_(par_.tail(env.
M_));
176 Eigen::VectorXd theta(x.size() + y.size());
177 for (
int i = 0; i < env.
N_; ++i) {
180 for (
int i = 0; i < env.
M_; ++i) {
181 theta(i + env.
N_) = env.
y_(i);
183 Eigen::Matrix<double, -1, 1> fx;
184 Eigen::Matrix<double, -1, -1> J_theta;
186 Eigen::MatrixXd A(J_theta.block(0, 0, env.
N_, env.
N_));
187 Eigen::MatrixXd b(J_theta.block(0, env.
N_, env.
N_, env.
M_));
188 A = Eigen::MatrixXd::Identity(env.
N_, env.
N_) - A;
189 Eigen::MatrixXd Jxy = A.colPivHouseholderQr().solve(b);
190 std::vector<double> gradients(env.
M_);
191 Eigen::Matrix<
var, -1, 1> x_sol(env.
N_);
193 for (
int i = 0; i < env.
N_; ++i) {
194 gradients =
to_array_1d(Eigen::VectorXd(Jxy.row(i)));
220template <
typename fp_env_type,
typename fp_jac_type>
229template <
typename F,
typename fp_jac_type>
240 double f_tol,
int max_num_steps) {
242 void* mem = env.
mem_;
244 const int default_anderson_depth = 4;
245 int anderson_depth = std::min(N, default_anderson_depth);
253 "KINSol", max_num_steps);
255 for (
int i = 0; i < N; ++i) {
256 x(i) = NV_Ith_S(env.
nv_x_, i);
271 template <
typename T1>
272 Eigen::Matrix<double, -1, 1>
solve(
const Eigen::Matrix<T1, -1, 1>& x,
273 const Eigen::Matrix<double, -1, 1>& y,
277 kinsol_solve_fp(xd, env, f_tol, max_num_steps);
292 template <
typename T1>
294 const Eigen::Matrix<T1, -1, 1>& x,
295 const Eigen::Matrix<stan::math::var, -1, 1>& y,
301 Eigen::VectorXd xd(solve(x, Eigen::VectorXd(), env, f_tol, max_num_steps));
304 return jac_sol(xd, y, env);
364template <
typename F,
typename T1,
typename T2,
typename T_u,
typename T_f>
366 const F& f,
const Eigen::Matrix<T1, -1, 1>& x,
367 const Eigen::Matrix<T2, -1, 1>& y,
const std::vector<double>& x_r,
368 const std::vector<int>& x_i,
const std::vector<T_u>& u_scale,
369 const std::vector<T_f>& f_scale, std::ostream* msgs =
nullptr,
371 int max_num_steps = 200) {
377 "the vector of unknowns, x,", x);
382 return fp.solve(x, y, env, f_tol, max_num_steps);
#define CHECK_KINSOL_CALL(call)
auto to_array_1d(T_x &&x)
Returns input matrix reshaped into a vector.
int64_t size(const T &m)
Returns the size (number of the elements) of a matrix_cl or var_value<matrix_cl<T>>.
void jacobian(const F &f, const Eigen::Matrix< T, Eigen::Dynamic, 1 > &x, Eigen::Matrix< T, Eigen::Dynamic, 1 > &fx, Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &J)
void check_nonnegative(const char *function, const char *name, const T_y &y)
Check if y is non-negative.
void algebra_solver_check(const Eigen::Matrix< T1, Eigen::Dynamic, 1 > &x, const Eigen::Matrix< T2, Eigen::Dynamic, 1 > y, const std::vector< double > &dat, const std::vector< int > &dat_int, double function_tolerance, long int max_num_steps)
static constexpr double e()
Return the base of the natural logarithm.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Eigen::Matrix< T2, -1, 1 > algebra_solver_fp(const F &f, const Eigen::Matrix< T1, -1, 1 > &x, const Eigen::Matrix< T2, -1, 1 > &y, const std::vector< double > &x_r, const std::vector< int > &x_i, const std::vector< T_u > &u_scale, const std::vector< T_f > &f_scale, std::ostream *msgs=nullptr, double f_tol=1e-8, int max_num_steps=200)
Return a fixed pointer to the specified system of algebraic equations of form.
void check_matching_sizes(const char *function, const char *name1, const T_y1 &y1, const char *name2, const T_y2 &y2)
Check if two structures at the same size.
void kinsol_check(int flag, const char *func_name)
Throws an exception message when the functions in KINSOL fails.
var precomputed_gradients(Arith value, const VecVar &operands, const VecArith &gradients, const std::tuple< ContainerOperands... > &container_operands=std::tuple<>(), const std::tuple< ContainerGradients... > &container_gradients=std::tuple<>())
This function returns a var for an expression that has the specified value, vector of operands,...
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Eigen::Matrix< stan::math::var, -1, 1 > operator()(const Eigen::VectorXd &x, const Eigen::Matrix< stan::math::var, -1, 1 > &y, KinsolFixedPointEnv< F > &env)
Calculate Jacobian Jxy.
Calculate Jacobian Jxy(Jacobian of unknown x w.r.t.
Eigen::Matrix< stan::math::var, -1, 1 > solve(const Eigen::Matrix< T1, -1, 1 > &x, const Eigen::Matrix< stan::math::var, -1, 1 > &y, KinsolFixedPointEnv< F > &env, double f_tol, int max_num_steps)
Solve FP problem and calculate jacobian.
Eigen::Matrix< double, -1, 1 > solve(const Eigen::Matrix< T1, -1, 1 > &x, const Eigen::Matrix< double, -1, 1 > &y, KinsolFixedPointEnv< F > &env, double f_tol, int max_num_steps)
Solve data-only FP problem so no need to calculate jacobian.
void kinsol_solve_fp(Eigen::VectorXd &x, KinsolFixedPointEnv< F > &env, double f_tol, int max_num_steps)
Solve FP using KINSOL.
Fixed point solver for problem of form.
const std::vector< int > & x_i_
integer data
void * mem_
KINSOL memory block.
const std::vector< double > & x_r_
real data
std::ostream * msgs_
message stream
N_Vector nv_u_scal_
NVECTOR for scaling u.
N_Vector nv_x_
NVECTOR for unknowns.
KinsolFixedPointEnv(const F &f, const Eigen::Matrix< T, -1, 1 > &x, const Eigen::VectorXd &y, const std::vector< double > &x_r, const std::vector< int > &x_i, std::ostream *msgs, const std::vector< T_u > &u_scale, const std::vector< T_f > &f_scale)
Constructor when y is data.
static int kinsol_f_system(N_Vector x, N_Vector f, void *user_data)
Implements the user-defined function passed to KINSOL.
sundials::Context sundials_context_
Sundials context.
N_Vector nv_f_scal_
NVECTOR for scaling f.
const size_t N_
system size
const Eigen::VectorXd & y_
ref to val of params
const Eigen::VectorXd y_dummy
val of params for y_ to refer to when params are var type
KinsolFixedPointEnv(const F &f, const Eigen::Matrix< T, -1, 1 > &x, const Eigen::Matrix< stan::math::var, -1, 1 > &y, const std::vector< double > &x_r, const std::vector< int > &x_i, std::ostream *msgs, const std::vector< T_u > &u_scale, const std::vector< T_f > &f_scale)
Constructor when y is param.
KINSOL algebraic system data holder that handles construction & destruction of SUNDIALS data,...