CppADCodeGen  HEAD
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.atomic_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  bool ok = rev_sparse_jac(m, rt, st, x);
190  if (!ok)
191  throw CGException("False returned from rev_sparse_jac() in the atomic function \"", this->atomic_name(), "\".");
192 
193  for (size_t j = 0; j < n; j++) {
194  for (size_t i : st[j]) {
195  if (vx[j]) {
196  vy[i] = true;
197  }
198  }
199  }
200  }
201 
202  bool atomicForward(size_t q,
203  size_t p,
204  const CppAD::vector<Base>& tx,
205  CppAD::vector<Base>& ty) override {
206  CppAD::vector<bool> vx, vy;
207  return atomicFun_.forward(q, p, vx, vy, tx, ty);
208  }
209 
210  bool atomicReverse(size_t p,
211  const CppAD::vector<Base>& tx,
212  const CppAD::vector<Base>& ty,
214  const CppAD::vector<Base>& py) override {
215  return atomicFun_.reverse(p, tx, ty, px, py);
216  }
217 
218 private:
219  inline CppAD::vector<Base> sparsityIndeps(const CppAD::vector<CGB>& x) const {
220  CPPADCG_ASSERT_UNKNOWN(x.size() == xSparsity_.size());
221 
222  size_t n = x.size();
223  CppAD::vector<Base> out(n);
224  for (size_t i = 0; i < n; ++i) {
225  if (x[i].isValueDefined()) {
226  out[i] = x[i].getValue();
227  } else {
228  out = xSparsity_;
229  break;
230  }
231  }
232 
233  return out;
234  }
235 
236  inline static CppAD::vector<Base> values(ArrayView<const CppAD::AD<Base>> x) {
237  CppAD::vector<Base> out(x.size());
238  for (size_t i = 0; i < out.size(); ++i) {
239  out[i] = CppAD::Value(CppAD::Var2Par(x[i]));
240  }
241  return out;
242  }
243 
244  inline static CppAD::vector<Base> values(ArrayView<const Base> x) {
245  CppAD::vector<Base> out(x.size());
246  for (size_t i = 0; i < out.size(); ++i) {
247  out[i] = x[i];
248  }
249  return out;
250  }
251 };
252 
253 } // END cg namespace
254 } // END CppAD namespace
255 
256 #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:210
bool atomicForward(size_t q, size_t p, const CppAD::vector< Base > &tx, CppAD::vector< Base > &ty) override
Definition: atomic_fun.hpp:202
size_t size() const noexcept
Definition: array_view.hpp:202