Automatic Differentiation
 
Loading...
Searching...
No Matches
precomputed_gradients.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_REV_CORE_PRECOMPUTED_GRADIENTS_HPP
2#define STAN_MATH_REV_CORE_PRECOMPUTED_GRADIENTS_HPP
3
9#include <algorithm>
10#include <vector>
11#include <tuple>
12
13namespace stan {
14namespace math {
15
27template <typename ContainerOperands = std::tuple<>,
28 typename ContainerGradients = std::tuple<>>
30 protected:
31 const size_t size_;
33 double* gradients_;
34 static_assert(std::tuple_size<ContainerOperands>::value
35 == std::tuple_size<ContainerGradients>::value,
36 "precomputed_gradients_vari: ContainerOperands and "
37 "ContainerGradients should have same size!");
38 static constexpr size_t N_containers
39 = std::tuple_size<ContainerOperands>::value;
40 ContainerOperands container_operands_;
41 ContainerGradients container_gradients_;
42
49 template <size_t... Is>
50 void check_sizes(std::index_sequence<Is...>) {
51 static_cast<void>(std::initializer_list<int>{
52 (check_matching_dims("precomputed_gradients_vari", "operands",
53 std::get<Is>(container_operands_), "gradients",
54 std::get<Is>(container_gradients_)),
55 0)...});
56 }
57
58 public:
74 template <typename... ContainerOps, typename... ContainerGrads>
76 double val, size_t size, vari** varis, double* gradients,
77 const std::tuple<ContainerOps...>& container_operands = std::tuple<>(),
78 const std::tuple<ContainerGrads...>& container_gradients = std::tuple<>())
79 : vari(val),
80 size_(size),
81 varis_(varis),
82 gradients_(gradients),
84 return std::make_tuple(to_arena(std::get<Is>(container_operands))...);
85 })),
86 container_gradients_(index_apply<N_containers>([&](auto... Is) {
87 return std::make_tuple(
88 to_arena(std::get<Is>(container_gradients))...);
89 })) {
90 check_sizes(std::make_index_sequence<N_containers>());
91 }
92
113 template <typename Arith, typename VecVar, typename VecArith,
114 typename... ContainerOps, typename... ContainerGrads,
115 require_all_vector_t<VecVar, VecArith>* = nullptr>
117 Arith val, const VecVar& vars, const VecArith& gradients,
118 const std::tuple<ContainerOps...>& container_operands = std::tuple<>(),
119 const std::tuple<ContainerGrads...>& container_gradients = std::tuple<>())
120 : vari(val),
121 size_(vars.size()),
122 varis_(ChainableStack::instance_->memalloc_.alloc_array<vari*>(
123 vars.size())),
124 gradients_(ChainableStack::instance_->memalloc_.alloc_array<double>(
125 vars.size())),
127 return std::make_tuple(to_arena(std::get<Is>(container_operands))...);
128 })),
129 container_gradients_(index_apply<N_containers>([&](auto... Is) {
130 return std::make_tuple(
131 to_arena(std::get<Is>(container_gradients))...);
132 })) {
133 check_consistent_sizes("precomputed_gradients_vari", "vars", vars,
134 "gradients", gradients);
135 check_sizes(std::make_index_sequence<N_containers>());
136 for (size_t i = 0; i < vars.size(); ++i) {
137 varis_[i] = vars[i].vi_;
138 }
139 std::copy(gradients.begin(), gradients.end(), gradients_);
140 }
141
146 void chain() {
147 for (size_t i = 0; i < size_; ++i) {
148 varis_[i]->adj_ += adj_ * gradients_[i];
149 }
150 index_apply<N_containers>([this](auto... Is) {
151 static_cast<void>(std::initializer_list<int>{
152 (this->chain_one(std::get<Is>(this->container_operands_),
153 std::get<Is>(this->container_gradients_)),
154 0)...});
155 });
156 }
157
158 private:
166 template <typename Op, typename Grad,
168 void chain_one(Op& op, const Grad& grad) {
169 op.vi_->adj_ = op.vi_->adj_ + this->adj_ * grad;
170 }
171
179 template <typename Op, typename OpAlloc, typename Grad, typename GradAlloc>
180 void chain_one(const std::vector<Op, OpAlloc>& op,
181 const std::vector<Grad, GradAlloc>& grad) {
182 for (int i = 0; i < op.size(); i++) {
183 chain_one(op[i], grad[i]);
184 }
185 }
186};
187
190
211template <typename Arith, typename VecVar, typename VecArith,
212 typename... ContainerOperands, typename... ContainerGradients>
214 Arith value, const VecVar& operands, const VecArith& gradients,
215 const std::tuple<ContainerOperands...>& container_operands = std::tuple<>(),
216 const std::tuple<ContainerGradients...>& container_gradients
217 = std::tuple<>()) {
219 std::tuple<arena_t<ContainerOperands>...>,
220 std::tuple<arena_t<ContainerGradients>...>>(
221 value, operands, gradients, container_operands, container_gradients)};
222}
223
224} // namespace math
225} // namespace stan
226#endif
void check_sizes(std::index_sequence< Is... >)
Checks that sizes of containers in container operands and container_gradients match.
void chain()
Implements the chain rule for this variable, using the prestored operands and gradient.
void chain_one(Op &op, const Grad &grad)
Implements the chain rule for one non-std::vector operand.
void chain_one(const std::vector< Op, OpAlloc > &op, const std::vector< Grad, GradAlloc > &grad)
Implements the chain rule for one std::vector operand.
precomputed_gradients_vari_template(Arith val, const VecVar &vars, const VecArith &gradients, const std::tuple< ContainerOps... > &container_operands=std::tuple<>(), const std::tuple< ContainerGrads... > &container_gradients=std::tuple<>())
Construct a precomputed vari with the specified value, operands, gradients and optionally container o...
precomputed_gradients_vari_template(double val, size_t size, vari **varis, double *gradients, const std::tuple< ContainerOps... > &container_operands=std::tuple<>(), const std::tuple< ContainerGrads... > &container_gradients=std::tuple<>())
Construct a precomputed vari with the specified value, operands, gradients and optionally container o...
A variable implementation taking a sequence of operands and partial derivatives with respect to the o...
require_all_not_t< is_std_vector< std::decay_t< Types > >... > require_all_not_std_vector_t
Require none of the types satisfy is_std_vector.
int64_t size(const T &m)
Returns the size (number of the elements) of a matrix_cl or var_value<matrix_cl<T>>.
Definition size.hpp:19
void check_matching_dims(const char *function, const char *name1, const T1 &y1, const char *name2, const T2 &y2)
Check if the two containers have the same dimensions.
arena_t< T > to_arena(const T &a)
Converts given argument into a type that either has any dynamic allocation on AD stack or schedules i...
Definition to_arena.hpp:25
void check_consistent_sizes(const char *)
Trivial no input case, this function is a no-op.
constexpr auto index_apply(F &&f)
Calls given callable with an index sequence.
static void grad()
Compute the gradient for all variables starting from the end of the AD tape.
Definition grad.hpp:26
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 ...
This struct always provides access to the autodiff stack using the singleton pattern.