CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
bipartite_nodes.hpp
1 #ifndef CPPAD_CG_BIPARTITE_NODES_INCLUDED
2 #define CPPAD_CG_BIPARTITE_NODES_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2012 Ciengis
6  *
7  * CppADCodeGen is distributed under multiple licenses:
8  *
9  * - Eclipse Public License Version 1.0 (EPL1), and
10  * - GNU General Public License Version 3 (GPL3).
11  *
12  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14  * ----------------------------------------------------------------------------
15  * Author: Joao Leal
16  */
17 
18 #include <assert.h>
19 #include <algorithm>
20 #include <iostream>
21 #include <sstream>
22 #include <vector>
23 
24 namespace CppAD {
25 namespace cg {
26 
30 template<class Base>
31 class BiPGraphNode {
32 protected:
33  size_t index_; // location of node
34  bool colored_; // node visited
35 public:
36 
37  inline BiPGraphNode(size_t index) :
38  index_(index),
39  colored_(false) {
40  }
41 
42  inline void color(std::ostream& out = std::cout,
43  Verbosity verbosity = Verbosity::None) {
44  colored_ = true;
45 
46  if (verbosity >= Verbosity::High)
47  out << " Colored " << nodeType() << " " << name() << "\n";
48  }
49 
50  inline void uncolor() {
51  colored_ = false;
52  }
53 
54  inline bool isColored() const {
55  return colored_;
56  }
57 
58  inline size_t index() const {
59  return index_;
60  }
61 
62  inline void setIndex(size_t index) {
63  index_ = index;
64  }
65 
66  virtual const std::string& name() const = 0;
67 
68  virtual std::string nodeType() = 0;
69 
70  inline virtual ~BiPGraphNode() {
71  }
72 };
73 
74 template<class Base>
75 class Vnode; // forward declaration
76 
80 template<class Base>
81 class Enode : public BiPGraphNode<Base> {
82 protected:
83  static const std::string TYPE;
88  std::vector<Vnode<Base>*> vnodes_orig_;
93  std::vector<Vnode<Base>*> vnodes_;
106  Vnode<Base>* assign_;
110  std::string name_;
111 public:
112 
113  inline Enode(size_t index,
114  const std::string& name = "") :
115  BiPGraphNode<Base>(index),
116  differentiation_(nullptr),
117  differentiationOf_(nullptr),
118  assign_(nullptr),
119  name_(name.empty()? ("Eq" + std::to_string(index)) : name) {
120  }
121 
122  inline Enode(size_t index,
123  Enode<Base>* differentiationOf) :
124  BiPGraphNode<Base>(index),
125  differentiation_(nullptr),
126  differentiationOf_(differentiationOf),
127  assign_(nullptr),
128  name_("Diff(" + differentiationOf->name() + ")") {
129  differentiationOf_->setDerivative(this);
130  }
131 
132  inline virtual ~Enode() {
133  }
134 
135  inline const std::vector<Vnode<Base>*>& variables() const {
136  return vnodes_;
137  }
138 
139  inline const std::vector<Vnode<Base>*>& originalVariables() const {
140  return vnodes_orig_;
141  }
142 
143  inline void addVariable(Vnode<Base>* j) {
144  if (std::find(vnodes_orig_.begin(), vnodes_orig_.end(), j) == vnodes_orig_.end()) {
145  vnodes_orig_.push_back(j);
146  if (!j->isDeleted()) {
147  vnodes_.push_back(j);
148  j->addEquation(this);
149  }
150  }
151  }
152 
153  inline Vnode<Base>* assignmentVariable() const {
154  return assign_;
155  }
156 
157  inline void setAssigmentVariable(Vnode<Base>& j) {
158  assign_ = &j;
159  }
160 
165  inline Enode<Base>* derivative() const {
166  return differentiation_;
167  }
168 
169  inline Enode<Base>* derivativeOf() const {
170  return differentiationOf_;
171  }
172 
173  inline Enode<Base>* originalEquation() {
174  if (differentiationOf_ == nullptr) {
175  return this;
176  } else {
177  return differentiationOf_->originalEquation();
178  }
179  }
180 
181  inline void deleteNode(Vnode<Base>* j) {
182  auto it = std::find(vnodes_.begin(), vnodes_.end(), j);
183  if (it != vnodes_.end())
184  vnodes_.erase(it);
185  }
186 
187  inline void setDerivative(Enode<Base>* difEq) {
188  differentiation_ = difEq;
189  }
190 
191  virtual const std::string& name() const {
192  return name_;
193  }
194 
195  virtual std::string nodeType() {
196  return TYPE;
197  }
198 };
199 
200 template<class Base>
201 inline std::ostream& operator <<(std::ostream& os, const Enode<Base>& i) {
202  if (i.derivativeOf() != nullptr) {
203  os << "Diff(" << *i.derivativeOf() << ")";
204  } else {
205  os << "Equation " << i.name() << " (" << i.index() << ")";
206  }
207 
208  return os;
209 }
210 
211 template<class Base>
212 const std::string Enode<Base>::TYPE = "Equation";
213 
217 template<class Base>
218 class Vnode : public BiPGraphNode<Base> {
219 protected:
220  static const std::string TYPE;
224  bool deleted_;
233  std::vector<Enode<Base>*> enodes_;
237  Enode<Base>* assign_;
250  size_t tapeIndex_;
254  std::string name_;
255 
256 public:
257 
258  inline Vnode(size_t index,
259  int tapeIndex,
260  const std::string& name) :
261  BiPGraphNode<Base>(index),
262  deleted_(false),
263  parameter_(false),
264  assign_(nullptr),
265  derivative_(nullptr),
266  antiDerivative_(nullptr),
267  tapeIndex_(tapeIndex),
268  name_(name) {
269 
270  }
271 
272  inline Vnode(size_t index,
273  size_t tapeIndex,
274  Vnode<Base>* derivativeOf,
275  const std::string& name = "") :
276  BiPGraphNode<Base>(index),
277  deleted_(false),
278  parameter_(false),
279  assign_(nullptr),
280  derivative_(nullptr),
281  antiDerivative_(derivativeOf),
282  tapeIndex_(tapeIndex),
283  name_(name.empty() ? "d" + derivativeOf->name() + "dt" : name) {
284  CPPADCG_ASSERT_UNKNOWN(antiDerivative_ != nullptr);
285 
286  antiDerivative_->setDerivative(this);
287  }
288 
289  inline virtual ~Vnode() {
290  }
291 
292  inline virtual const std::string& name() const {
293  return name_;
294  }
295 
296  inline size_t tapeIndex() const {
297  return tapeIndex_;
298  }
299 
300  inline void setTapeIndex(size_t tapeIndex) {
301  tapeIndex_ = tapeIndex;
302  }
303 
304  inline std::vector<Enode<Base>*>& equations() {
305  return enodes_;
306  }
307 
308  inline const std::vector<Enode<Base>*>& equations() const {
309  return enodes_;
310  }
311 
315  inline Vnode<Base>* derivative() const {
316  return derivative_;
317  }
318 
322  inline Vnode<Base>* antiDerivative() const {
323  return antiDerivative_;
324  }
325 
326  inline Vnode<Base>* originalVariable() {
327  if (antiDerivative_ == nullptr) {
328  return this;
329  } else {
330  return antiDerivative_->originalVariable();
331  }
332  }
333 
334  inline Vnode<Base>* originalVariable(size_t origVarSize) {
335  if (antiDerivative_ == nullptr || this->index_ < origVarSize) {
336  return this;
337  } else {
338  return antiDerivative_->originalVariable();
339  }
340  }
341 
342  inline bool isDeleted() const {
343  return deleted_;
344  }
345 
346  inline void makeParameter(std::ostream& out = std::cout,
347  Verbosity verbosity = Verbosity::None) {
348  parameter_ = true;
349  deleteNode(out, verbosity);
350  }
351 
352  inline bool isParameter() const {
353  return parameter_;
354  }
355 
356  inline void deleteNode(std::ostream& out = std::cout,
357  Verbosity verbosity = Verbosity::None) {
358  if (verbosity >= Verbosity::High)
359  out << "Deleting " << *this << "\n";
360 
361  deleted_ = true;
362  for (Enode<Base>* i : enodes_) {
363  i->deleteNode(this);
364  }
365  enodes_.clear();
366  }
367 
368  inline Enode<Base>* assignmentEquation() const {
369  return assign_;
370  }
371 
372  inline void setAssignmentEquation(Enode<Base>& i,
373  std::ostream& out = std::cout,
374  Verbosity verbosity = Verbosity::None) {
375  if (verbosity >= Verbosity::High)
376  out << " Assigning " << *this << " to " << i << "\n";
377 
378  assign_ = &i;
379  i.setAssigmentVariable(*this);
380  }
381 
382  virtual std::string nodeType() {
383  return TYPE;
384  }
385 
386  inline void setDerivative(Vnode<Base>* div) {
387  derivative_ = div;
388  }
389 
390  unsigned int order() const {
391  if (antiDerivative_ == nullptr) {
392  return 0u;
393  } else {
394  return antiDerivative_->order() + 1u;
395  }
396  }
397 
398 protected:
399 
400  inline void addEquation(Enode<Base>* i) {
401  if (!deleted_) {
402  CPPADCG_ASSERT_UNKNOWN(std::find(enodes_.begin(), enodes_.end(), i) == enodes_.end());
403  enodes_.push_back(i);
404  }
405  }
406 
407  friend class Enode<Base>;
408 };
409 
410 template<class Base>
411 inline std::ostream& operator <<(std::ostream& os, const Vnode<Base>& j) {
412  if (j.antiDerivative() != nullptr) {
413  os << "Diff(" << *j.antiDerivative() << ")";
414  } else {
415  os << "Variable " << j.name();
416  }
417  return os;
418 }
419 
420 template<class Base>
421 const std::string Vnode<Base>::TYPE = "Variable";
422 
423 } // END cg namespace
424 } // END CppAD namespace
425 
426 #endif
Enode< Base > * differentiationOf_
Vnode< Base > * derivative_
Vnode< Base > * derivative() const
Enode< Base > * differentiation_
STL namespace.
Vnode< Base > *const antiDerivative_
std::vector< Enode< Base > * > enodes_
Enode< Base > * derivative() const
std::vector< Vnode< Base > * > vnodes_orig_
Vnode< Base > * antiDerivative() const
std::vector< Vnode< Base > * > vnodes_