Automatic Differentiation
 
Loading...
Searching...
No Matches
solve_newton.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_REV_FUNCTOR_SOLVE_NEWTON_HPP
2#define STAN_MATH_REV_FUNCTOR_SOLVE_NEWTON_HPP
3
12#include <unsupported/Eigen/NonLinearOptimization>
13#include <iostream>
14#include <string>
15#include <vector>
16
17namespace stan {
18namespace math {
19
56template <typename F, typename T, typename... Args,
57 require_eigen_vector_t<T>* = nullptr,
58 require_all_st_arithmetic<Args...>* = nullptr>
59Eigen::VectorXd solve_newton_tol(const F& f, const T& x,
60 const double scaling_step_size,
61 const double function_tolerance,
62 const int64_t max_num_steps,
63 std::ostream* const msgs,
64 const Args&... args) {
65 const auto& x_ref = to_ref(value_of(x));
66
67 check_nonzero_size("solve_newton", "initial guess", x_ref);
68 check_finite("solve_newton", "initial guess", x_ref);
69 check_nonnegative("solve_newton", "scaling_step_size", scaling_step_size);
70 check_nonnegative("solve_newton", "function_tolerance", function_tolerance);
71 check_positive("solve_newton", "max_num_steps", max_num_steps);
72
73 return kinsol_solve(f, x_ref, scaling_step_size, function_tolerance,
74 max_num_steps, 1, 10, KIN_LINESEARCH, msgs, args...);
75}
76
135template <typename F, typename T, typename... T_Args,
136 require_eigen_vector_t<T>* = nullptr,
137 require_any_st_var<T_Args...>* = nullptr>
138Eigen::Matrix<var, Eigen::Dynamic, 1> solve_newton_tol(
139 const F& f, const T& x, const double scaling_step_size,
140 const double function_tolerance, const int64_t max_num_steps,
141 std::ostream* const msgs, const T_Args&... args) {
142 const auto& x_ref = to_ref(value_of(x));
143 auto arena_args_tuple = make_chainable_ptr(std::make_tuple(eval(args)...));
144 auto args_vals_tuple = math::apply(
145 [&](const auto&... args) {
146 return std::make_tuple(to_ref(value_of(args))...);
147 },
148 *arena_args_tuple);
149
150 check_nonzero_size("solve_newton", "initial guess", x_ref);
151 check_finite("solve_newton", "initial guess", x_ref);
152 check_nonnegative("solve_newton", "scaling_step_size", scaling_step_size);
153 check_nonnegative("solve_newton", "function_tolerance", function_tolerance);
154 check_positive("solve_newton", "max_num_steps", max_num_steps);
155
156 // Solve the system
157 Eigen::VectorXd theta_dbl = math::apply(
158 [&](const auto&... vals) {
159 return kinsol_solve(f, x_ref, scaling_step_size, function_tolerance,
160 max_num_steps, 1, 10, KIN_LINESEARCH, msgs,
161 vals...);
162 },
163 args_vals_tuple);
164
165 auto f_wrt_x = [&](const auto& x) {
166 return math::apply([&](const auto&... args) { return f(x, msgs, args...); },
167 args_vals_tuple);
168 };
169
170 Eigen::MatrixXd Jf_x;
171 Eigen::VectorXd f_x;
172
173 jacobian(f_wrt_x, theta_dbl, f_x, Jf_x);
174
175 using ret_type = Eigen::Matrix<var, Eigen::Dynamic, -1>;
176 arena_t<ret_type> ret = theta_dbl;
177 auto Jf_x_T_lu_ptr
178 = make_unsafe_chainable_ptr(Jf_x.transpose().partialPivLu()); // Lu
179
181 [f, ret, arena_args_tuple, Jf_x_T_lu_ptr, msgs]() mutable {
182 Eigen::VectorXd eta = -Jf_x_T_lu_ptr->solve(ret.adj().eval());
183
184 // Contract with Jacobian of f with respect to y using a nested reverse
185 // autodiff pass.
186 {
188
189 Eigen::VectorXd ret_val = ret.val();
190 auto x_nrad_ = math::apply(
191 [&ret_val, &f, msgs](const auto&... args) {
192 return eval(f(ret_val, msgs, args...));
193 },
194 *arena_args_tuple);
195 x_nrad_.adj() = eta;
196 grad();
197 }
198 });
199
200 return ret_type(ret);
201}
202
237template <typename F, typename T, typename... T_Args,
238 require_eigen_vector_t<T>* = nullptr>
239Eigen::Matrix<stan::return_type_t<T_Args...>, Eigen::Dynamic, 1> solve_newton(
240 const F& f, const T& x, std::ostream* const msgs, const T_Args&... args) {
241 double scaling_step_size = 1e-3;
242 double function_tolerance = 1e-6;
243 int64_t max_num_steps = 200;
244 const auto& args_ref_tuple = std::make_tuple(to_ref(args)...);
245 return math::apply(
246 [&](const auto&... args_refs) {
247 return solve_newton_tol(f, x, scaling_step_size, function_tolerance,
248 max_num_steps, msgs, args_refs...);
249 },
250 args_ref_tuple);
251}
252
293template <typename F, typename T1, typename T2,
295Eigen::Matrix<scalar_type_t<T2>, Eigen::Dynamic, 1> algebra_solver_newton(
296 const F& f, const T1& x, const T2& y, const std::vector<double>& dat,
297 const std::vector<int>& dat_int, std::ostream* const msgs = nullptr,
298 const double scaling_step_size = 1e-3,
299 const double function_tolerance = 1e-6,
300 const long int max_num_steps = 200) { // NOLINT(runtime/int)
301 return solve_newton_tol(algebra_solver_adapter<F>(f), x, scaling_step_size,
302 function_tolerance, max_num_steps, msgs, y, dat,
303 dat_int);
304}
305
306} // namespace math
307} // namespace stan
308
309#endif
A class following the RAII idiom to start and recover nested autodiff scopes.
require_all_t< std::is_arithmetic< scalar_type_t< std::decay_t< Types > > >... > require_all_st_arithmetic
Require all of the scalar types satisfy std::is_arithmetic.
require_t< is_eigen_vector< std::decay_t< T > > > require_eigen_vector_t
Require type satisfies is_eigen_vector.
require_all_t< is_eigen_vector< std::decay_t< Types > >... > require_all_eigen_vector_t
Require all of the types satisfy is_eigen_vector.
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
require_any_t< is_var< scalar_type_t< std::decay_t< Types > > >... > require_any_st_var
Require any of the scalar types satisfy is_var.
Definition is_var.hpp:131
Eigen::VectorXd solve_newton_tol(const F &f, const T &x, const double scaling_step_size, const double function_tolerance, const int64_t max_num_steps, std::ostream *const msgs, const Args &... args)
Return the solution to the specified system of algebraic equations given an initial guess,...
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)
Definition jacobian.hpp:11
void check_nonnegative(const char *function, const char *name, const T_y &y)
Check if y is non-negative.
static constexpr double e()
Return the base of the natural logarithm.
Definition constants.hpp:20
auto make_unsafe_chainable_ptr(T &&obj)
Store the given object in a chainable_object so it is destructed only when the chainable stack memory...
void reverse_pass_callback(F &&functor)
Puts a callback on the autodiff stack to be called in reverse pass.
T eval(T &&arg)
Inputs which have a plain_type equal to the own time are forwarded unmodified (for Eigen expressions ...
Definition eval.hpp:20
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
auto make_chainable_ptr(T &&obj)
Store the given object in a chainable_object so it is destructed only when the chainable stack memory...
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:17
Eigen::Matrix< scalar_type_t< T2 >, Eigen::Dynamic, 1 > algebra_solver_newton(const F &f, const T1 &x, const T2 &y, const std::vector< double > &dat, const std::vector< int > &dat_int, std::ostream *const msgs=nullptr, const double scaling_step_size=1e-3, const double function_tolerance=1e-6, const long int max_num_steps=200)
Return the solution to the specified system of algebraic equations given an initial guess,...
void check_finite(const char *function, const char *name, const T_y &y)
Return true if all values in y are finite.
var_value< double > var
Definition var.hpp:1187
void check_nonzero_size(const char *function, const char *name, const T_y &y)
Check if the specified matrix/vector is of non-zero size.
void check_positive(const char *function, const char *name, const T_y &y)
Check if y is positive.
Eigen::Matrix< stan::return_type_t< T_Args... >, Eigen::Dynamic, 1 > solve_newton(const F &f, const T &x, std::ostream *const msgs, const T_Args &... args)
Return the solution to the specified system of algebraic equations given an initial guess,...
static void grad()
Compute the gradient for all variables starting from the end of the AD tape.
Definition grad.hpp:26
constexpr decltype(auto) apply(F &&f, Tuple &&t, PreArgs &&... pre_args)
Definition apply.hpp:52
Eigen::VectorXd kinsol_solve(const F1 &f, const Eigen::VectorXd &x, const double scaling_step_tol, const double function_tolerance, const int64_t max_num_steps, const bool custom_jacobian, const int steps_eval_jacobian, const int global_line_search, std::ostream *const msgs, const Args &... args)
Return the solution to the specified algebraic system, given an initial guess.
typename internal::arena_type_impl< std::decay_t< T > >::type arena_t
Determines a type that can be used in place of T that does any dynamic allocations on the AD stack.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Adapt the non-variadic algebra_solver_newton and algebra_solver_powell arguemts to the variadic algeb...