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