CppADCodeGen  2.3.0
A C++ Algorithmic Differentiation Package with Source Code Generation
util.hpp
1 #ifndef CPPAD_CG_UTIL_INCLUDED
2 #define CPPAD_CG_UTIL_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2012 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 VectorBool, class Base>
22 void zeroOrderDependency(ADFun<Base>& fun,
23  const VectorBool& vx,
24  VectorBool& vy) {
25  size_t m = fun.Range();
26  CPPADCG_ASSERT_KNOWN(vx.size() >= fun.Domain(), "Invalid vx size");
27  CPPADCG_ASSERT_KNOWN(vy.size() >= m, "Invalid vy size");
28 
29  using VectorSet = std::vector<std::set<size_t> >;
30 
31  const VectorSet jacSparsity = jacobianSparsitySet<VectorSet, Base>(fun);
32 
33  for (size_t i = 0; i < m; i++) {
34  for (size_t j : jacSparsity[i]) {
35  if (vx[j]) {
36  vy[i] = true;
37  break;
38  }
39  }
40  }
41 }
42 
43 template<class VectorSet>
44 inline bool isIdentityPattern(const VectorSet& pattern,
45  size_t mRows) {
46  CPPADCG_ASSERT_UNKNOWN(pattern.size() >= mRows);
47 
48  for (size_t i = 0; i < mRows; i++) {
49  if (pattern[i].size() != 1 || *pattern[i].begin() != i) {
50  return false;
51  }
52  }
53  return true;
54 }
55 
56 template<class VectorSet>
57 inline VectorSet transposePattern(const VectorSet& pattern,
58  size_t mRows,
59  size_t nCols) {
60  CPPADCG_ASSERT_UNKNOWN(pattern.size() >= mRows);
61 
62  VectorSet transpose(nCols);
63  for (size_t i = 0; i < mRows; i++) {
64  for (size_t it : pattern[i]) {
65  transpose[it].insert(i);
66  }
67  }
68  return transpose;
69 }
70 
80 template<class VectorSet, class VectorSet2>
81 inline void addTransMatrixSparsity(const VectorSet& a,
82  size_t mRows,
83  VectorSet2& result) {
84  CPPADCG_ASSERT_UNKNOWN(a.size() >= mRows);
85 
86  for (size_t i = 0; i < mRows; i++) {
87  for (size_t j : a[i]) {
88  result[j].insert(i);
89  }
90  }
91 }
92 
101 template<class VectorSet, class VectorSet2>
102 inline void addTransMatrixSparsity(const VectorSet& a,
103  VectorSet2& result) {
104  addTransMatrixSparsity<VectorSet, VectorSet2>(a, a.size(), result);
105 }
106 
115 template<class VectorSet, class VectorSet2>
116 inline void addMatrixSparsity(const VectorSet& a,
117  size_t mRows,
118  VectorSet2& result) {
119  CPPADCG_ASSERT_UNKNOWN(result.size() >= mRows);
120  CPPADCG_ASSERT_UNKNOWN(a.size() <= mRows);
121 
122  for (size_t i = 0; i < mRows; i++) {
123  if (result[i].empty()) {
124  result[i] = a[i];
125  } else {
126  result[i].insert(a[i].begin(), a[i].end());
127  }
128  }
129 }
130 
138 template<class VectorSet, class VectorSet2>
139 inline void addMatrixSparsity(const VectorSet& a,
140  VectorSet2& result) {
141  CPPADCG_ASSERT_UNKNOWN(result.size() == a.size());
142 
143  addMatrixSparsity<VectorSet, VectorSet2>(a, a.size(), result);
144 }
145 
155 template<class VectorSet, class VectorSet2>
156 inline void multMatrixMatrixSparsity(const VectorSet& a,
157  const VectorSet2& b,
158  CppAD::vector<std::set<size_t> >& result,
159  size_t q) {
160  multMatrixMatrixSparsity(a, b, result, a.size(), b.size(), q);
161 }
162 
176 template<class VectorSet, class VectorSet2>
177 inline void multMatrixMatrixSparsity(const VectorSet& a,
178  const VectorSet2& b,
179  CppAD::vector<std::set<size_t> >& result,
180  size_t m,
181  size_t n,
182  size_t q) {
183  CPPADCG_ASSERT_UNKNOWN(a.size() >= m);
184  CPPADCG_ASSERT_UNKNOWN(b.size() >= n);
185  CPPADCG_ASSERT_UNKNOWN(result.size() >= m);
186 
187  //check if b is identity
188  if (n == q) {
189  if (isIdentityPattern(b, n)) {
190  addMatrixSparsity(a, m, result); // R += A
191  return;
192  }
193  }
194 
195  VectorSet2 bt = transposePattern(b, n, q);
196 
197  for (size_t jj = 0; jj < q; jj++) { //loop columns of b
198  const std::set<size_t>& colB = bt[jj];
199  if (colB.size() > 0) {
200  for (size_t i = 0; i < m; i++) {
201  const std::set<size_t>& rowA = a[i];
202  for (size_t rowb : colB) {
203  if (rowA.find(rowb) != rowA.end()) {
204  result[i].insert(jj);
205  break;
206  }
207  }
208  }
209  }
210  }
211 }
212 
226 template<class VectorSet, class VectorSet2>
227 inline void multMatrixTransMatrixSparsity(const VectorSet& a,
228  const VectorSet2& b,
229  CppAD::vector<std::set<size_t> >& result,
230  size_t m,
231  size_t n,
232  size_t q) {
233  CPPADCG_ASSERT_UNKNOWN(a.size() >= m);
234  CPPADCG_ASSERT_UNKNOWN(b.size() >= m);
235  CPPADCG_ASSERT_UNKNOWN(result.size() >= n);
236 
237  //check if B is empty
238  bool empty = true;
239  for (size_t i = 0; i < m; i++) {
240  if (b[i].size() > 0) {
241  empty = false;
242  break;
243  }
244  }
245  if (empty) {
246  return; //nothing to do: R += 0
247  }
248 
249  //check if A is identity
250  if (m == n && isIdentityPattern(a, m)) {
251  addMatrixSparsity(b, n, result); // R += B
252  return;
253  }
254 
255  //check if B is identity
256  if (m == q && isIdentityPattern(b, m)) {
257  addTransMatrixSparsity(a, m, result); // R += A^T
258  return;
259  }
260 
261  VectorSet at = transposePattern(a, m, n);
262  VectorSet2 bt = transposePattern(b, m, q);
263 
264  for (size_t jj = 0; jj < q; jj++) { //loop columns of b
265  const std::set<size_t>& colB = bt[jj];
266  if (colB.size() > 0) {
267  for (size_t i = 0; i < n; i++) {
268  const std::set<size_t>& rowAt = at[i];
269  if (rowAt.size() > 0) {
270  for (size_t rowb : colB) {
271  if (rowAt.find(rowb) != rowAt.end()) {
272  result[i].insert(jj);
273  break;
274  }
275  }
276  }
277  }
278  }
279  }
280 
281 }
282 
295 template<class VectorSet, class VectorSet2>
296 inline void multMatrixMatrixSparsityTrans(const VectorSet& aT,
297  const VectorSet2& b,
298  CppAD::vector<std::set<size_t> >& rT,
299  size_t m,
300  size_t n,
301  size_t q) {
302  CPPADCG_ASSERT_UNKNOWN(aT.size() >= m);
303  CPPADCG_ASSERT_UNKNOWN(b.size() >= m);
304 
305  //check if b is empty
306  bool empty = true;
307  for (size_t i = 0; i < m; i++) {
308  if (b[i].size() > 0) {
309  empty = false;
310  break;
311  }
312  }
313  if (empty) {
314  return; //nothing to do: R^T += 0
315  }
316 
317  //check if a is identity
318  if (m == q && isIdentityPattern(aT, m)) {
319  addTransMatrixSparsity(b, m, rT); // R^T += B^T
320  return;
321  }
322 
323  VectorSet a = transposePattern(aT, m, q);
324  VectorSet2 bT = transposePattern(b, m, n);
325 
326  for (size_t jj = 0; jj < n; jj++) { //loop columns of b
327  for (size_t i = 0; i < q; i++) {
328  for (size_t it : a[i]) {
329  if (bT[jj].find(it) != bT[jj].end()) {
330  rT[jj].insert(i);
331  break;
332  }
333  }
334  }
335  }
336 }
337 
338 template<class VectorBool>
339 void printSparsityPattern(const VectorBool& sparsity,
340  const std::string& name,
341  size_t m, size_t n) {
342  size_t width = std::ceil(std::log10((m > n) ? m : n));
343  if (!name.empty()) {
344  std::cout << name << " sparsity:\n";
345  }
346  for (size_t i = 0; i < m; i++) {
347  std::cout << " " << std::setw(width) << i << ": ";
348  for (size_t j = 0; j < n; j++) {
349  if (sparsity[i * n + j]) {
350  std::cout << std::setw(width) << j << " ";
351  } else {
352  std::cout << std::setw(width) << " " << " ";
353  }
354  }
355  std::cout << "\n";
356  }
357  std::cout << std::endl;
358 }
359 
360 template<class VectorSet>
361 void printSparsityPattern(const VectorSet& sparsity,
362  const std::string& name,
363  bool printLocationByRow = false) {
364  size_t maxDim = sparsity.size();
365  size_t nnz = 0;
366  for (size_t i = 0; i < sparsity.size(); i++) {
367  if (sparsity[i].size() > 0 && *sparsity[i].rbegin() > maxDim) {
368  maxDim = *sparsity[i].rbegin();
369  }
370  nnz += sparsity[i].size();
371  }
372 
373  size_t width = std::ceil(std::log10(maxDim));
374  size_t width2;
375  size_t width3 = width;
376  if (printLocationByRow) {
377  width2 = std::ceil(std::log10(nnz));
378  width3 += width2 + 1;
379  }
380  if (!name.empty()) {
381  std::cout << name << " sparsity:\n";
382  }
383 
384  size_t e = 0;
385  for (size_t i = 0; i < sparsity.size(); i++) {
386  std::cout << " " << std::setw(width) << i << ": ";
387  long last = -1;
388  for (size_t j : sparsity[i]) {
389  if (j != 0 && long(j) != last + 1) {
390  std::cout << std::setw((j - last - 1) * (width3 + 1)) << " ";
391  }
392  if (printLocationByRow)
393  std::cout << std::setw(width2) << e << ":";
394  std::cout << std::setw(width) << j << " ";
395  last = j;
396  e++;
397  }
398  std::cout << "\n";
399  }
400  std::cout << std::endl;
401 }
402 
403 template<class VectorSize>
404 void printSparsityPattern(const VectorSize& row,
405  const VectorSize& col,
406  const std::string& name,
407  size_t m) {
408  std::vector<std::set<size_t> > sparsity(m);
409  generateSparsitySet(row, col, sparsity);
410  printSparsityPattern(sparsity, name);
411 }
412 
413 inline bool intersects(const std::set<size_t>& a,
414  const std::set<size_t>& b) {
415  if (a.empty() || b.empty()) {
416  return false;
417  } else if (*a.rbegin() < *b.begin() ||
418  *a.begin() > *b.rbegin()) {
419  return false;
420  }
421 
422  if (a.size() < b.size()) {
423  for (size_t ita : a) {
424  if (b.find(ita) != b.end()) {
425  return true;
426  }
427  }
428  } else {
429  for (size_t itb : b) {
430  if (a.find(itb) != a.end()) {
431  return true;
432  }
433  }
434  }
435 
436  return false;
437 }
438 
445 template<class Base>
446 inline CodeHandler<Base>* findHandler(const std::vector<CG<Base> >& ty) {
447  for (size_t i = 0; i < ty.size(); i++) {
448  if (ty[i].getCodeHandler() != nullptr) {
449  return ty[i].getCodeHandler();
450  }
451  }
452  return nullptr;
453 }
454 
455 template<class Base>
456 inline CodeHandler<Base>* findHandler(const CppAD::vector<CG<Base> >& ty) {
457  for (size_t i = 0; i < ty.size(); i++) {
458  if (ty[i].getCodeHandler() != nullptr) {
459  return ty[i].getCodeHandler();
460  }
461  }
462  return nullptr;
463 }
464 
465 template<class Base>
466 inline CodeHandler<Base>* findHandler(CppAD::cg::ArrayView<const CG<Base> > ty) {
467  for (size_t i = 0; i < ty.size(); i++) {
468  if (ty[i].getCodeHandler() != nullptr) {
469  return ty[i].getCodeHandler();
470  }
471  }
472  return nullptr;
473 }
474 
475 template<class Base>
476 inline Argument<Base> asArgument(const CG<Base>& tx) {
477  if (tx.isParameter()) {
478  return Argument<Base>(tx.getValue());
479  } else {
480  return Argument<Base>(*tx.getOperationNode());
481  }
482 }
483 
484 template<class Base>
485 inline std::vector<Argument<Base> > asArguments(const std::vector<CG<Base> >& tx) {
486  std::vector<Argument<Base> > arguments(tx.size());
487  for (size_t i = 0; i < arguments.size(); i++) {
488  arguments[i] = asArgument(tx[i]);
489  }
490  return arguments;
491 }
492 
493 template<class Base>
494 inline std::vector<Argument<Base> > asArguments(const CppAD::vector<CG<Base> >& tx) {
495  std::vector<Argument<Base> > arguments(tx.size());
496  for (size_t i = 0; i < arguments.size(); i++) {
497  arguments[i] = asArgument(tx[i]);
498  }
499  return arguments;
500 }
501 
502 /***************************************************************************
503  * map related
504  **************************************************************************/
505 
512 template<class Key, class Value>
513 void mapKeys(const std::map<Key, Value>& map, std::set<Key>& keys) {
514  for (const auto& p : map) {
515  keys.insert(keys.end(), p.first);
516  }
517 }
518 
525 template<class Key, class Value>
526 void mapKeys(const std::map<Key, Value>& map, std::vector<Key>& keys) {
527  keys.resize(map.size());
528 
529  size_t i = 0;
530  typename std::map<Key, Value>::const_iterator it;
531  for (it = map.begin(); it != map.end(); ++it, i++) {
532  keys[i] = it->first;
533  }
534 }
535 
543 template<class Key, class Value>
544 bool compareMapKeys(const std::map<Key, Value>& map, const std::set<Key>& keys) {
545  if (map.size() != keys.size())
546  return false;
547 
548  typename std::map<Key, Value>::const_iterator itm = map.begin();
549  typename std::set<Key>::const_iterator itk = keys.begin();
550  for (; itm != map.end(); ++itm, ++itk) {
551  if (itm->first != *itk)
552  return false;
553  }
554 
555  return true;
556 }
557 
565 template<class Key, class Value>
566 inline std::map<Key, Value> filterBykeys(const std::map<Key, Value>& m,
567  const std::set<Key>& keys) {
568  std::map<Key, Value> filtered;
569 
570  typename std::map<Key, Value>::const_iterator itM;
571 
572  for (const Key& k : keys) {
573  itM = m.find(k);
574  if (itM != m.end()) {
575  filtered[itM->first] = itM->second;
576  }
577  }
578  return filtered;
579 }
580 
590 template<class T>
591 inline int compare(const std::set<T>& s1, const std::set<T>& s2) {
592  if (s1.size() < s2.size()) {
593  return -1;
594  } else if (s1.size() > s2.size()) {
595  return 1;
596  } else {
597  typename std::set<T>::const_iterator it1, it2;
598  for (it1 = s1.begin(), it2 = s2.begin(); it1 != s1.end(); ++it1, ++it2) {
599  if (*it1 < *it2) {
600  return -1;
601  } else if (*it1 > *it2) {
602  return 1;
603  }
604  }
605  return 0;
606  }
607 }
608 
609 template<class T>
611 
612  bool operator() (const std::set<T>& lhs, const std::set<T>& rhs) const {
613  return compare(lhs, rhs) == -1;
614  }
615 };
616 
617 /***************************************************************************
618  * Generic functions for printing stl containers
619  **************************************************************************/
620 template<class Base>
621 inline void print(const Base& v) {
622  std::cout << v;
623 }
624 
625 template<class Key, class Value>
626 inline void print(const std::map<Key, Value>& m) {
627  for (const std::pair<Key, Value>& p : m) {
628  std::cout << p.first << " : ";
629  print(p.second);
630  std::cout << std::endl;
631  }
632 }
633 
634 template<class Base>
635 inline void print(const std::set<Base>& s) {
636  std::cout << "[";
637 
638  for (auto itj = s.begin(); itj != s.end(); ++itj) {
639  if (itj != s.begin()) std::cout << " ";
640  print(*itj);
641  }
642  std::cout << "]";
643  std::cout.flush();
644 }
645 
646 template<class Base>
647 inline void print(const std::set<Base*>& s) {
648  std::cout << "[";
649 
650  for (const auto itj = s.begin(); itj != s.end(); ++itj) {
651  if (itj != s.begin()) std::cout << " ";
652  Base* v = *itj;
653  if (v == nullptr) std::cout << "NULL";
654  else print(*v);
655  }
656  std::cout << "]";
657  std::cout.flush();
658 }
659 
660 template<class Base>
661 inline void print(const std::vector<Base>& v) {
662  std::cout << "[";
663 
664  for (size_t i = 0; i < v.size(); i++) {
665  if (i != 0) std::cout << " ";
666  print(v[i]);
667  }
668  std::cout << "]";
669  std::cout.flush();
670 }
671 
672 /***************************************************************************
673  * print
674  **************************************************************************/
686 template<class Base>
687 inline CG<Base> makePrintValue(const std::string& before,
688  const CG<Base>& x,
689  const std::string& after = "") {
690  std::cout << before << x << after;
691 
692  if (x.getOperationNode() != nullptr) {
693  auto* handler = x.getCodeHandler();
694  CG<Base> out(*handler->makePrintNode(before, *x.getOperationNode(), after));
695  if (x.isValueDefined())
696  out.setValue(x.getValue());
697  return out;
698  } else {
699  return x;
700  }
701 }
702 
703 /***************************************************************************
704  * String related utilities
705  **************************************************************************/
706 
714 inline void replaceString(std::string& text,
715  const std::string& toReplace,
716  const std::string& replacement) {
717  size_t pos = 0;
718  while ((pos = text.find(toReplace, pos)) != std::string::npos) {
719  text.replace(pos, toReplace.length(), replacement);
720  pos += replacement.length();
721  }
722 }
723 
724 inline std::vector<std::string> explode(const std::string& text,
725  const std::string& delimiter) {
726  std::vector<std::string> matches;
727 
728  const size_t dlen = delimiter.length();
729  if (dlen == 0)
730  return matches;
731 
732  size_t pos = 0;
733  size_t start = 0;
734  while (true) {
735  pos = text.find(delimiter, start);
736  if (pos == std::string::npos) {
737  break;
738  }
739  matches.push_back(text.substr(start, pos - start));
740  start = pos + dlen;
741  }
742 
743  if (start < text.length()) {
744  matches.push_back(text.substr(start, text.length() - start));
745  }
746 
747  return matches;
748 }
749 
750 inline std::string implode(const std::vector<std::string>& text,
751  const std::string& delimiter) {
752  if (text.empty()) {
753  return "";
754  } else if (text.size() == 1) {
755  return text[0];
756  } else {
757  std::string out;
758  size_t n = 0;
759  for (const auto& s: text)
760  n += s.size();
761  out.reserve(n + (text.size() - 1) * delimiter.size());
762  out = text[0];
763  for (size_t i = 1; i < text.size(); ++i) {
764  out += delimiter;
765  out += text[i];
766  }
767  return out;
768  }
769 }
770 
771 } // END cg namespace
772 } // END CppAD namespace
773 
774 #endif
const Base & getValue() const
Definition: variable.hpp:45
void setValue(const Base &val)
Definition: variable.hpp:54
bool isValueDefined() const
Definition: variable.hpp:40
CodeHandler< Base > * getCodeHandler() const
Definition: variable.hpp:22