CppADCodeGen  2.3.0
A C++ Algorithmic Differentiation Package with Source Code Generation
atomic_fun.hpp
1 #ifndef CPPAD_CG_ATOMIC_FUN_INCLUDED
2 #define CPPAD_CG_ATOMIC_FUN_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2013 Ciengis
6  * Copyright (C) 2018 Joao Leal
7  *
8  * CppADCodeGen is distributed under multiple licenses:
9  *
10  * - Eclipse Public License Version 1.0 (EPL1), and
11  * - GNU General Public License Version 3 (GPL3).
12  *
13  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
14  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
15  * ----------------------------------------------------------------------------
16  * Author: Joao Leal
17  */
18 
19 namespace CppAD {
20 namespace cg {
21 
27 template <class Base>
28 class CGAtomicFun : public CGAbstractAtomicFun<Base> {
29 protected:
30  using CGB = CG<Base>;
31 protected:
32  atomic_base<Base>& atomicFun_;
33  const CppAD::vector<Base> xSparsity_; // independent vector used to determine sparsity patterns
34 public:
35 
50  CGAtomicFun(atomic_base<Base>& atomicFun,
51  const CppAD::vector<Base>& xSparsity,
52  bool standAlone = false) :
53  CGAbstractAtomicFun<Base>(atomicFun.afun_name(), standAlone),
54  atomicFun_(atomicFun),
55  xSparsity_(xSparsity) {
56  }
57 
58  CGAtomicFun(atomic_base<Base>& atomicFun,
59  ArrayView<const Base> xSparsity,
60  bool standAlone = false) :
61  CGAtomicFun(atomicFun, values(xSparsity), standAlone) {
62  }
63 
64  CGAtomicFun(atomic_base<Base>& atomicFun,
65  ArrayView<const CppAD::AD<Base>> xSparsity,
66  bool standAlone = false) :
67  CGAtomicFun(atomicFun, values(xSparsity), standAlone) {
68  }
69 
70  virtual ~CGAtomicFun() = default;
71 
72  template <class ADVector>
73  void operator()(const ADVector& ax,
74  ADVector& ay,
75  size_t id = 0) {
76  this->CGAbstractAtomicFun<Base>::operator()(ax, ay, id);
77  }
78 
79  bool for_sparse_jac(size_t q,
80  const CppAD::vector<std::set<size_t> >& r,
81  CppAD::vector<std::set<size_t> >& s,
82  const CppAD::vector<CGB>& x) override {
83  return atomicFun_.for_sparse_jac(q, r, s, sparsityIndeps(x));
84  }
85 
86  bool for_sparse_jac(size_t q,
87  const CppAD::vector<std::set<size_t> >& r,
88  CppAD::vector<std::set<size_t> >& s) override {
89  return atomicFun_.for_sparse_jac(q, r, s);
90  }
91 
92  bool for_sparse_jac(size_t q,
93  const CppAD::vector<bool>& r,
95  const CppAD::vector<CGB>& x) override {
96  return atomicFun_.for_sparse_jac(q, r, s, sparsityIndeps(x));
97  }
98 
99  bool for_sparse_jac(size_t q,
100  const CppAD::vector<bool>& r,
101  CppAD::vector<bool>& s) override {
102  return atomicFun_.for_sparse_jac(q, r, s);
103  }
104 
105  bool rev_sparse_jac(size_t q,
106  const CppAD::vector<std::set<size_t> >& rt,
107  CppAD::vector<std::set<size_t> >& st,
108  const CppAD::vector<CGB>& x) override {
109  return atomicFun_.rev_sparse_jac(q, rt, st, sparsityIndeps(x));
110  }
111 
112  bool rev_sparse_jac(size_t q,
113  const CppAD::vector<std::set<size_t> >& rt,
114  CppAD::vector<std::set<size_t> >& st) override {
115  return atomicFun_.rev_sparse_jac(q, rt, st);
116  }
117 
118  bool rev_sparse_jac(size_t q,
119  const CppAD::vector<bool>& rt,
121  const CppAD::vector<CGB>& x) override {
122  return atomicFun_.rev_sparse_jac(q, rt, st, sparsityIndeps(x));
123  }
124 
125  bool rev_sparse_jac(size_t q,
126  const CppAD::vector<bool>& rt,
127  CppAD::vector<bool>& st) override {
128  return atomicFun_.rev_sparse_jac(q, rt, st);
129  }
130 
131  bool rev_sparse_hes(const CppAD::vector<bool>& vx,
132  const CppAD::vector<bool>& s,
134  size_t q,
135  const CppAD::vector<std::set<size_t> >& r,
136  const CppAD::vector<std::set<size_t> >& u,
137  CppAD::vector<std::set<size_t> >& v,
138  const CppAD::vector<CGB>& x) override {
139  return atomicFun_.rev_sparse_hes(vx, s, t, q, r, u, v, sparsityIndeps(x));
140  }
141 
142  bool rev_sparse_hes(const CppAD::vector<bool>& vx,
143  const CppAD::vector<bool>& s,
145  size_t q,
146  const CppAD::vector<std::set<size_t> >& r,
147  const CppAD::vector<std::set<size_t> >& u,
148  CppAD::vector<std::set<size_t> >& v) override {
149  return atomicFun_.rev_sparse_hes(vx, s, t, q, r, u, v);
150  }
151 
152  bool rev_sparse_hes(const CppAD::vector<bool>& vx,
153  const CppAD::vector<bool>& s,
155  size_t q,
156  const CppAD::vector<bool>& r,
157  const CppAD::vector<bool>& u,
159  const CppAD::vector<CGB>& x) override {
160  return atomicFun_.rev_sparse_hes(vx, s, t, q, r, u, v, sparsityIndeps(x));
161  }
162 
163  bool rev_sparse_hes(const CppAD::vector<bool>& vx,
164  const CppAD::vector<bool>& s,
166  size_t q,
167  const CppAD::vector<bool>& r,
168  const CppAD::vector<bool>& u,
169  CppAD::vector<bool>& v) override {
170  return atomicFun_.rev_sparse_hes(vx, s, t, q, r, u, v);
171  }
172 
173 protected:
174 
175  void zeroOrderDependency(const CppAD::vector<bool>& vx,
177  const CppAD::vector<CGB>& x) override {
178  using CppAD::vector;
179 
180  size_t m = vy.size();
181  size_t n = vx.size();
182 
183  vector<std::set<size_t> > rt(m);
184  for (size_t j = 0; j < m; j++) {
185  rt[j].insert(j);
186  }
187  vector<std::set<size_t> > st(n);
188 
189  rev_sparse_jac(m, rt, st, x);
190 
191  for (size_t j = 0; j < n; j++) {
192  for (size_t i : st[j]) {
193  if (vx[j]) {
194  vy[i] = true;
195  }
196  }
197  }
198  }
199 
200  bool atomicForward(size_t q,
201  size_t p,
202  const CppAD::vector<Base>& tx,
203  CppAD::vector<Base>& ty) override {
204  CppAD::vector<bool> vx, vy;
205  return atomicFun_.forward(q, p, vx, vy, tx, ty);
206  }
207 
208  bool atomicReverse(size_t p,
209  const CppAD::vector<Base>& tx,
210  const CppAD::vector<Base>& ty,
212  const CppAD::vector<Base>& py) override {
213  return atomicFun_.reverse(p, tx, ty, px, py);
214  }
215 
216 private:
217  inline CppAD::vector<Base> sparsityIndeps(const CppAD::vector<CGB>& x) const {
218  CPPADCG_ASSERT_UNKNOWN(x.size() == xSparsity_.size());
219 
220  size_t n = x.size();
221  CppAD::vector<Base> out(n);
222  for (size_t i = 0; i < n; ++i) {
223  if (x[i].isValueDefined()) {
224  out[i] = x[i].getValue();
225  } else {
226  out = xSparsity_;
227  break;
228  }
229  }
230 
231  return out;
232  }
233 
234  inline static CppAD::vector<Base> values(ArrayView<const CppAD::AD<Base>> x) {
235  CppAD::vector<Base> out(x.size());
236  for (size_t i = 0; i < out.size(); ++i) {
237  out[i] = CppAD::Value(CppAD::Var2Par(x[i]));
238  }
239  return out;
240  }
241 
242  inline static CppAD::vector<Base> values(ArrayView<const Base> x) {
243  CppAD::vector<Base> out(x.size());
244  for (size_t i = 0; i < out.size(); ++i) {
245  out[i] = x[i];
246  }
247  return out;
248  }
249 };
250 
251 } // END cg namespace
252 } // END CppAD namespace
253 
254 #endif
CGAtomicFun(atomic_base< Base > &atomicFun, const CppAD::vector< Base > &xSparsity, bool standAlone=false)
Definition: atomic_fun.hpp:50
bool atomicReverse(size_t p, const CppAD::vector< Base > &tx, const CppAD::vector< Base > &ty, CppAD::vector< Base > &px, const CppAD::vector< Base > &py) override
Definition: atomic_fun.hpp:208
bool atomicForward(size_t q, size_t p, const CppAD::vector< Base > &tx, CppAD::vector< Base > &ty) override
Definition: atomic_fun.hpp:200
size_t size() const noexcept
Definition: array_view.hpp:202