CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
language_dot_index_patterns.hpp
1#ifndef CPPAD_CG_LANGUAGE_DOT_INDEX_PATTERNS_INCLUDED
2#define CPPAD_CG_LANGUAGE_DOT_INDEX_PATTERNS_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2016 Ciengis
6 * Copyright (C) 2020 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
19namespace CppAD {
20namespace cg {
21
22template<class Base>
23inline void LanguageDot<Base>::generateNames4RandomIndexPatterns(const std::set<RandomIndexPattern*>& randomPatterns) {
24 std::ostringstream os;
25
26 std::set<std::string> usedNames;
27
28 // save existing names so that they are not to overridden
29 // (independent variable names might have already used them)
30 for (RandomIndexPattern* ip : randomPatterns) {
31 if (!ip->getName().empty()) {
32 usedNames.insert(ip->getName());
33 }
34 }
35
36 // create new names for the index pattern arrays without a name
37 size_t c = 0;
38 for (RandomIndexPattern* ip : randomPatterns) {
39 if (ip->getName().empty()) {
40 // new name required
41 std::string name;
42 do {
43 os << _C_STATIC_INDEX_ARRAY << c;
44 name = os.str();
45 os.str("");
46 c++;
47 } while (usedNames.find(name) != usedNames.end());
48
49 ip->setName(name);
50 }
51 }
52
53}
54
55template<class Base>
57 const std::set<RandomIndexPattern*>& randomPatterns) {
58 if (randomPatterns.empty())
59 return;
60
61 _code << "subgraph index {" << _endline;
62 _code << " rank=same" << _endline;
63 for (RandomIndexPattern* ip : randomPatterns) {
64 os << "idx_" << ip->getName() << "[label=\"";
65 if (ip->getType() == IndexPatternType::Random1D) {
69 Random1DIndexPattern* ip1 = static_cast<Random1DIndexPattern*> (ip);
70 const std::map<size_t, size_t>& x2y = ip1->getValues();
71
72 std::vector<size_t> y(x2y.rbegin()->first + 1);
73 for (const std::pair<size_t, size_t>& p : x2y)
74 y[p.first] = p.second;
75
76 printStaticIndexArray(os, ip->getName(), y);
77 } else {
78 CPPADCG_ASSERT_UNKNOWN(ip->getType() == IndexPatternType::Random2D);
82 Random2DIndexPattern* ip2 = static_cast<Random2DIndexPattern*> (ip);
83 printStaticIndexMatrix(os, ip->getName(), ip2->getValues());
84 }
85
86 os << "\"]";
87 os << _endline;
88 }
89 _code << "}" << _endline;
90}
91
92template<class Base>
93void LanguageDot<Base>::printStaticIndexArray(std::ostringstream& os,
94 const std::string& name,
95 const std::vector<size_t>& values) {
96 os << name << " = [";
97 for (size_t i = 0; i < values.size(); i++) {
98 if (i > 0)
99 os << ",";
100 os << values[i];
101 }
102 os << "]";
103}
104
105template<class Base>
106void LanguageDot<Base>::printStaticIndexMatrix(std::ostringstream& os,
107 const std::string& name,
108 const std::map<size_t, std::map<size_t, size_t> >& values) {
109 std::map<size_t, std::map<size_t, size_t> >::const_iterator it;
110 std::map<size_t, size_t>::const_iterator ity2z;
111
112 os << name << "= [";
113 for (it = values.begin(); it != values.end(); ++it) {
114 if (it != values.begin())
115 os << it->first << ",\\n";
116 os << it->first << ":[";
117 size_t y = 0;
118 for (ity2z = it->second.begin(); ity2z != it->second.end(); ++ity2z) {
119 if (ity2z->first != y) {
120 while (ity2z->first != y) {
121 if (y > 0) os << ", ";
122 os << "0";
123 y++;
124 }
125 }
126
127 if (y > 0) os << ", ";
128 os << ity2z->second;
129
130 y++;
131 }
132 os << "]";
133 }
134 os << "]";
135}
136
137template<class Base>
138inline void LanguageDot<Base>::indexPattern2String(std::ostream& os,
139 const IndexPattern& ip,
140 const OperationNode<Base>& index) {
141 indexPattern2String(os, ip,{&index});
142}
143
144template<class Base>
145inline void LanguageDot<Base>::indexPattern2String(std::ostream& os,
146 const IndexPattern& ip,
147 const std::vector<const OperationNode<Base>*>& indexes) {
148 std::stringstream ss;
149 switch (ip.getType()) {
150 case IndexPatternType::Linear: // y = x * a + b
151 {
152 CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes")
153 const auto& lip = static_cast<const LinearIndexPattern&> (ip);
154 linearIndexPattern2String(os, lip, *indexes[0]);
155 return;
156 }
157 case IndexPatternType::Sectioned:
158 {
159 CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes")
160 const auto* lip = static_cast<const SectionedIndexPattern*> (&ip);
161 const std::map<size_t, IndexPattern*>& sections = lip->getLinearSections();
162 size_t sSize = sections.size();
163 CPPADCG_ASSERT_UNKNOWN(sSize > 1);
164
165 std::map<size_t, IndexPattern*>::const_iterator its = sections.begin();
166 for (size_t s = 0; s < sSize - 1; s++) {
167 const IndexPattern* lp = its->second;
168 ++its;
169 size_t xStart = its->first;
170
171 os << (*indexes[0]->getName()) << " < " << xStart << ")? ";
172 indexPattern2String(os, *lp, *indexes[0]);
173 os << ": ";
174 }
175 indexPattern2String(os, *its->second, *indexes[0]);
176
177 return;
178 }
179
180 case IndexPatternType::Plane2D: // y = f(x) + f(z)
181 {
182 CPPADCG_ASSERT_KNOWN(indexes.size() >= 1, "Invalid number of indexes")
183 const auto& pip = static_cast<const Plane2DIndexPattern&> (ip);
184 bool useParens = pip.getPattern1() != nullptr && pip.getPattern2() != nullptr;
185
186 if (useParens) os << "(";
187
188 if (pip.getPattern1() != nullptr)
189 indexPattern2String(os, *pip.getPattern1(), *indexes[0]);
190
191 if (useParens) os << ") + (";
192
193 if (pip.getPattern2() != nullptr)
194 indexPattern2String(os, *pip.getPattern2(), *indexes.back());
195
196 if (useParens) os << ")";
197
198 return;
199 }
200 case IndexPatternType::Random1D:
201 {
202 CPPADCG_ASSERT_KNOWN(indexes.size() == 1, "Invalid number of indexes")
203 const auto& rip = static_cast<const Random1DIndexPattern&> (ip);
204 CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array")
205 os << rip.getName() << "[" << (*indexes[0]->getName()) << "]";
206 return;
207 }
208 case IndexPatternType::Random2D:
209 {
210 CPPADCG_ASSERT_KNOWN(indexes.size() == 2, "Invalid number of indexes")
211 const auto& rip = static_cast<const Random2DIndexPattern&> (ip);
212 CPPADCG_ASSERT_KNOWN(!rip.getName().empty(), "Invalid name for array")
213 os << rip.getName() <<
214 "[" << (*indexes[0]->getName()) << "]"
215 "[" << (*indexes[1]->getName()) << "]";
216 return;
217 }
218 default:
219 CPPADCG_ASSERT_UNKNOWN(false); // should never reach this
220 return;
221 }
222}
223
224template<class Base>
225inline void LanguageDot<Base>::linearIndexPattern2String(std::ostream& os,
226 const LinearIndexPattern& lip,
227 const OperationNode<Base>& index) {
228 long dy = lip.getLinearSlopeDy();
229 long dx = lip.getLinearSlopeDx();
230 long b = lip.getLinearConstantTerm();
231 long xOffset = lip.getXOffset();
232
233 if (dy != 0) {
234 if (xOffset != 0) {
235 os << "(";
236 }
237 os << (*index.getName());
238 if (xOffset != 0) {
239 os << " -" << xOffset << ")";
240 }
241
242 if (dx != 1) {
243 os << "/" << dx;
244 }
245 if (dy != 1) {
246 os << "×" << dy;
247 }
248 } else if (b == 0) {
249 os << "0"; // when dy == 0 and b == 0
250 }
251
252 if (b != 0) {
253 if (dy != 0)
254 os << "+";
255 os << b;
256 }
257
258}
259
260} // END cg namespace
261} // END CppAD namespace
262
263#endif
void printRandomIndexPatternDeclaration(std::ostringstream &os, const std::set< RandomIndexPattern * > &randomPatterns)