CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
soares_secchi.hpp
1#ifndef CPPAD_CG_SOARES_SECCHI_HPP
2#define CPPAD_CG_SOARES_SECCHI_HPP
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2016 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#include <cppad/cg/dae_index_reduction/augment_path_depth_lookahead_a.hpp>
22
23namespace CppAD {
24namespace cg {
25
29template<class Base>
31protected:
33 using ADCG = CppAD::AD<CGBase>;
34protected:
35 // avoids having to type this->graph_
36 using DaeStructuralIndexReduction<Base>::graph_;
37 // typical values used to avoid NaNs in the tape validation by CppAD
38 std::vector<Base> x_;
43 std::set<Enode<Base>*> lastAddEq_;
44 // whether or not reduceIndex() has been called
45 bool reduced_;
46 //
47 AugmentPathDepthLookahead<Base> defaultAugmentPath_;
48 AugmentPathDepthLookaheadA<Base> defaultAugmentPathA_;
49 AugmentPath<Base>* augmentPath_;
50 AugmentPath<Base>* augmentPathA_;
51public:
52
64 const std::vector<DaeVarInfo>& varInfo,
65 const std::vector<std::string>& eqName,
66 const std::vector<Base>& x) :
67 DaeStructuralIndexReduction<Base>(fun, varInfo, eqName),
68 x_(x),
69 reduced_(false),
70 augmentPath_(&defaultAugmentPath_),
71 augmentPathA_(&defaultAugmentPathA_){
72
73 }
74
75 SoaresSecchi(const SoaresSecchi& p) = delete;
76
77 SoaresSecchi& operator=(const SoaresSecchi& p) = delete;
78
79 virtual ~SoaresSecchi() {
80 }
81
82 AugmentPath<Base>& getAugmentPath() const {
83 return *augmentPath_;
84 }
85
86 void setAugmentPath(AugmentPath<Base>& a) const {
87 augmentPath_ = &a;
88 }
89
95 inline void setPreserveNames(bool p) {
96 graph_.setPreserveNames(p);
97 }
98
104 inline bool isPreserveNames() const {
105 return graph_.isPreserveNames();
106 }
107
118 inline std::unique_ptr<ADFun<CG<Base>>> reduceIndex(std::vector<DaeVarInfo>& newVarInfo,
119 std::vector<DaeEquationInfo>& equationInfo) override {
120 if (reduced_)
121 throw CGException("reduceIndex() can only be called once!");
122
123 if (this->verbosity_ >= Verbosity::High)
124 log() << "######## Soares Secchi method ########\n";
125
126 augmentPath_->setLogger(*this);
127 augmentPathA_->setLogger(*this);
128
129 reduced_ = true;
130
131 // detects which equations have to be differentiated to get an ODE
132 detectSubset2Dif();
133
134 // we want an index 1 DAE (ignore the last equations added to the graph)
135 for(const Enode<Base>* i: lastAddEq_) {
136 graph_.remove(*i);
137 }
138
139 if (this->verbosity_ >= Verbosity::Low) {
140 graph_.printResultInfo("Soares Secchi");
141
142 log() << "Structural index: " << graph_.getStructuralIndex() << std::endl;
143 }
144
145 std::unique_ptr<ADFun<CGBase>> reducedFun(graph_.generateNewModel(newVarInfo, equationInfo, x_));
146
147 return reducedFun;
148 }
149
157 inline size_t getStructuralIndex() const {
158 return graph_.getStructuralIndex();
159 }
160
161protected:
162 using DaeStructuralIndexReduction<Base>::log;
163
167 inline void detectSubset2Dif() {
168 auto& vnodes = graph_.variables();
169 auto& enodes = graph_.equations();
170
171 std::set<Enode<Base>*> marked;
172 std::set<Enode<Base>*> lastMarked;
173
174 if (this->verbosity_ >= Verbosity::High)
175 graph_.printDot(this->log());
176
177 while (true) {
178 // augment the matching one by one
179 for (size_t k = 0; k < enodes.size(); k++) {
180 Enode<Base>* i = enodes[k];
181
182 if (this->verbosity_ >= Verbosity::High)
183 log() << "Outer loop: equation k = " << *i << "\n";
184
185 if (i->assignmentVariable() != nullptr) {
186 continue;
187 }
188
189 bool pathFound = augmentPathA_->augmentPath(*i);
190 if (!pathFound) {
191
192 for (Enode<Base>* ii: enodes) {
193 // mark colored equations to be differentiated
194 if (ii->isColored() && ii->derivative() == nullptr) {
195 marked.insert(ii);
196
197 // uncolor equations
198 ii->uncolor();
199 }
200 }
201
202 pathFound = augmentPath_->augmentPath(*i);
203 if (!pathFound) {
204 throw CGException("Singular system detected.");
205 }
206
207 for (auto* jj: vnodes)
208 jj->uncolor();
209
210 } else {
211 for (auto* ii: enodes)
212 ii->uncolor();
213 }
214 }
215
216 if (marked.empty())
217 break;
218
219 // diff all MARKED equations
220 for (Enode<Base>* i: marked) {
221 graph_.createDerivate(*i, false);
222 }
223
224 if (this->verbosity_ >= Verbosity::High)
225 graph_.printDot(this->log());
226
227 lastMarked.swap(marked);
228 marked.clear();
229 }
230
231 lastAddEq_.clear();
232 for (const Enode<Base>* i: lastMarked) {
233 lastAddEq_.insert(i->derivative());
234 }
235
236 }
237
238};
239
240} // END cg namespace
241} // END CppAD namespace
242
243#endif
virtual bool augmentPath(Enode< Base > &i)=0
Enode< Base > * derivative() const
SoaresSecchi(ADFun< CG< Base > > &fun, const std::vector< DaeVarInfo > &varInfo, const std::vector< std::string > &eqName, const std::vector< Base > &x)
std::unique_ptr< ADFun< CG< Base > > > reduceIndex(std::vector< DaeVarInfo > &newVarInfo, std::vector< DaeEquationInfo > &equationInfo) override
size_t getStructuralIndex() const
std::set< Enode< Base > * > lastAddEq_