CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
pantelides.hpp
1 #ifndef CPPAD_CG_PANTELIDES_INCLUDED
2 #define CPPAD_CG_PANTELIDES_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2012 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 #include <cppad/cg/dae_index_reduction/dae_structural_index_reduction.hpp>
20 #include <cppad/cg/dae_index_reduction/augment_path_depth_lookahead.hpp>
21 
22 namespace CppAD {
23 namespace cg {
24 
28 template<class Base>
30 protected:
32  using ADCG = CppAD::AD<CGBase>;
33 protected:
34  // avoids having to type this->graph_
36  // typical values used to avoid NaNs in the tape validation by CppAD
37  std::vector<Base> x_;
38  // whether or not reduceIndex() has been called
39  bool reduced_;
40  AugmentPathDepthLookahead<Base> defaultAugmentPath_;
41  AugmentPath<Base>* augmentPath_;
42 public:
43 
55  const std::vector<DaeVarInfo>& varInfo,
56  const std::vector<std::string>& eqName,
57  const std::vector<Base>& x) :
58  DaeStructuralIndexReduction<Base>(fun, varInfo, eqName),
59  x_(x),
60  reduced_(false),
61  augmentPath_(&defaultAugmentPath_) {
62 
63  }
64 
65  Pantelides(const Pantelides& p) = delete;
66 
67  Pantelides& operator=(const Pantelides& p) = delete;
68 
69  virtual ~Pantelides() = default;
70 
71  AugmentPath<Base>& getAugmentPath() const {
72  return *augmentPath_;
73  }
74 
75  void setAugmentPath(AugmentPath<Base>& a) const {
76  augmentPath_ = &a;
77  }
78 
79  inline std::unique_ptr<ADFun<CG<Base>>> reduceIndex(std::vector<DaeVarInfo>& newVarInfo,
80  std::vector<DaeEquationInfo>& equationInfo) override {
81  if (reduced_)
82  throw CGException("reduceIndex() can only be called once!");
83 
84  if (this->verbosity_ >= Verbosity::Low)
85  log() << "######## Pantelides method ########\n";
86 
87  augmentPath_->setLogger(*this);
88 
89  reduced_ = true;
90 
92 
93  if (this->verbosity_ >= Verbosity::Low) {
94  graph_.printResultInfo("Pantelides");
95 
96  log() << "Structural index: " << graph_.getStructuralIndex() << std::endl;
97  }
98 
99  std::unique_ptr<ADFun<CGBase>> reducedFun(graph_.generateNewModel(newVarInfo, equationInfo, x_));
100 
101  return reducedFun;
102  }
103 
104 protected:
106 
110  inline void detectSubset2Dif() {
111  auto& vnodes = graph_.variables();
112  auto& enodes = graph_.equations();
113 
114  Enode<Base>* ll;
115 
116  if (this->verbosity_ >= Verbosity::High)
117  graph_.printDot(this->log());
118 
119  size_t Ndash = enodes.size();
120  for (size_t k = 0; k < Ndash; k++) {
121  Enode<Base>* i = enodes[k];
122 
123  if (this->verbosity_ >= Verbosity::High)
124  log() << "Outer loop: equation k = " << *i << "\n";
125 
126  bool pathfound = false;
127  while (!pathfound) {
128 
133  for (Vnode<Base>* jj : vnodes) {
134  if (!jj->isDeleted() && jj->derivative() != nullptr) {
135  jj->deleteNode(log(), this->verbosity_);
136  }
137  }
138 
139  graph_.uncolorAll();
140 
141  pathfound = augmentPath_->augmentPath(*i);
142 
143  if (!pathfound) {
144  const size_t vsize = vnodes.size(); // the size might change
145  for (size_t l = 0; l < vsize; ++l) {
146  Vnode<Base>* jj = vnodes[l];
147  if (jj->isColored() && !jj->isDeleted()) {
148  // add new variable derivatives of colored variables
149  graph_.createDerivate(*jj);
150  }
151  }
152 
153  const size_t esize = enodes.size(); // the size might change
154  for (size_t l = 0; l < esize; l++) {
155  ll = enodes[l];
156  if (ll->isColored()) {
157  // add new derivative equations for colored equations and create edges
158  graph_.createDerivate(*ll);
159  }
160  }
161 
162  // structural check to avoid infinite recursion
163  for (size_t l = esize; l < enodes.size(); l++) {
164  ll = enodes[l];
165  const std::vector<Vnode<Base>*>& nvars = ll->originalVariables();
166  bool ok = false;
167  for (Vnode<Base>* js : nvars) {
168  if (js->equations().size() > 1) {
169  ok = true;
170  break;
171  }
172  }
173  if (!ok)
174  throw CGException("Invalid equation structure. The model appears to be over-defined.");
175  }
176 
177  for (Vnode<Base>* jj : vnodes) {
178  if (jj->isColored() && !jj->isDeleted()) {
179  Vnode<Base>* jDiff = jj->derivative();
180  jDiff->setAssignmentEquation(*jj->assignmentEquation()->derivative(), log(), this->verbosity_);
181  }
182  }
183 
184  i = i->derivative();
185 
186  if (this->verbosity_ >= Verbosity::High) {
187  log() << "Set current equation to (i=" << i->index() << ") " << *i << "\n";
188 
189  graph_.printDot(this->log());
190  }
191  }
192  }
193 
194  }
195 
196  }
197 
198 };
199 
200 } // END cg namespace
201 } // END CppAD namespace
202 
203 #endif
Vnode< Base > * derivative() const
std::unique_ptr< ADFun< CG< Base > > > reduceIndex(std::vector< DaeVarInfo > &newVarInfo, std::vector< DaeEquationInfo > &equationInfo) override
Definition: pantelides.hpp:79
Enode< Base > * derivative() const
virtual bool augmentPath(Enode< Base > &i)=0
Pantelides(ADFun< CG< Base > > &fun, const std::vector< DaeVarInfo > &varInfo, const std::vector< std::string > &eqName, const std::vector< Base > &x)
Definition: pantelides.hpp:54