CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
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 
19 namespace CppAD {
20 namespace cg {
21 
22 template<class Base>
23 inline 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 
55 template<class Base>
56 inline void LanguageDot<Base>::printRandomIndexPatternDeclaration(std::ostringstream& os,
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 auto& 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 
92 template<class Base>
93 void 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 
105 template<class Base>
106 void 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 
137 template<class Base>
138 inline void LanguageDot<Base>::indexPattern2String(std::ostream& os,
139  const IndexPattern& ip,
140  const OperationNode<Base>& index) {
141  indexPattern2String(os, ip,{&index});
142 }
143 
144 template<class Base>
145 inline 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 
224 template<class Base>
225 inline 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
const std::string * getName() const
void printRandomIndexPatternDeclaration(std::ostringstream &os, const std::set< RandomIndexPattern *> &randomPatterns)