1 #ifndef CPPAD_CG_UTIL_INCLUDED 2 #define CPPAD_CG_UTIL_INCLUDED 21 template<
class VectorBool,
class Base>
22 void zeroOrderDependency(ADFun<Base>& fun,
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");
29 using VectorSet = std::vector<std::set<size_t> >;
31 const VectorSet jacSparsity = jacobianSparsitySet<VectorSet, Base>(fun);
33 for (
size_t i = 0; i < m; i++) {
34 for (
size_t j : jacSparsity[i]) {
43 template<
class VectorSet>
44 inline bool isIdentityPattern(
const VectorSet& pattern,
46 CPPADCG_ASSERT_UNKNOWN(pattern.size() >= mRows);
48 for (
size_t i = 0; i < mRows; i++) {
49 if (pattern[i].size() != 1 || *pattern[i].begin() != i) {
56 template<
class VectorSet>
57 inline VectorSet transposePattern(
const VectorSet& pattern,
60 CPPADCG_ASSERT_UNKNOWN(pattern.size() >= mRows);
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);
80 template<
class VectorSet,
class VectorSet2>
81 inline void addTransMatrixSparsity(
const VectorSet& a,
84 CPPADCG_ASSERT_UNKNOWN(a.size() >= mRows);
86 for (
size_t i = 0; i < mRows; i++) {
87 for (
size_t j : a[i]) {
101 template<
class VectorSet,
class VectorSet2>
102 inline void addTransMatrixSparsity(
const VectorSet& a,
103 VectorSet2& result) {
104 addTransMatrixSparsity<VectorSet, VectorSet2>(a, a.size(), result);
115 template<
class VectorSet,
class VectorSet2>
116 inline void addMatrixSparsity(
const VectorSet& a,
118 VectorSet2& result) {
119 CPPADCG_ASSERT_UNKNOWN(result.size() >= mRows);
120 CPPADCG_ASSERT_UNKNOWN(a.size() <= mRows);
122 for (
size_t i = 0; i < mRows; i++) {
123 if (result[i].empty()) {
126 result[i].insert(a[i].begin(), a[i].end());
138 template<
class VectorSet,
class VectorSet2>
139 inline void addMatrixSparsity(
const VectorSet& a,
140 VectorSet2& result) {
141 CPPADCG_ASSERT_UNKNOWN(result.size() == a.size());
143 addMatrixSparsity<VectorSet, VectorSet2>(a, a.size(), result);
155 template<
class VectorSet,
class VectorSet2>
156 inline void multMatrixMatrixSparsity(
const VectorSet& a,
160 multMatrixMatrixSparsity(a, b, result, a.size(), b.size(), q);
176 template<
class VectorSet,
class VectorSet2>
177 inline void multMatrixMatrixSparsity(
const VectorSet& a,
183 CPPADCG_ASSERT_UNKNOWN(a.size() >= m);
184 CPPADCG_ASSERT_UNKNOWN(b.size() >= n);
185 CPPADCG_ASSERT_UNKNOWN(result.size() >= m);
189 if (isIdentityPattern(b, n)) {
190 addMatrixSparsity(a, m, result);
195 VectorSet2 bt = transposePattern(b, n, q);
197 for (
size_t jj = 0; jj < q; jj++) {
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);
226 template<
class VectorSet,
class VectorSet2>
227 inline void multMatrixTransMatrixSparsity(
const VectorSet& a,
233 CPPADCG_ASSERT_UNKNOWN(a.size() >= m);
234 CPPADCG_ASSERT_UNKNOWN(b.size() >= m);
235 CPPADCG_ASSERT_UNKNOWN(result.size() >= n);
239 for (
size_t i = 0; i < m; i++) {
240 if (b[i].size() > 0) {
250 if (m == n && isIdentityPattern(a, m)) {
251 addMatrixSparsity(b, n, result);
256 if (m == q && isIdentityPattern(b, m)) {
257 addTransMatrixSparsity(a, m, result);
261 VectorSet at = transposePattern(a, m, n);
262 VectorSet2 bt = transposePattern(b, m, q);
264 for (
size_t jj = 0; jj < q; jj++) {
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);
295 template<
class VectorSet,
class VectorSet2>
296 inline void multMatrixMatrixSparsityTrans(
const VectorSet& aT,
302 CPPADCG_ASSERT_UNKNOWN(aT.size() >= m);
303 CPPADCG_ASSERT_UNKNOWN(b.size() >= m);
307 for (
size_t i = 0; i < m; i++) {
308 if (b[i].size() > 0) {
318 if (m == q && isIdentityPattern(aT, m)) {
319 addTransMatrixSparsity(b, m, rT);
323 VectorSet a = transposePattern(aT, m, q);
324 VectorSet2 bT = transposePattern(b, m, n);
326 for (
size_t jj = 0; jj < n; jj++) {
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()) {
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));
344 std::cout << name <<
" sparsity:\n";
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 <<
" ";
352 std::cout << std::setw(width) <<
" " <<
" ";
357 std::cout << std::endl;
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();
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();
370 nnz += sparsity[i].size();
373 size_t width = std::ceil(std::log10(maxDim));
375 size_t width3 = width;
376 if (printLocationByRow) {
377 width2 = std::ceil(std::log10(nnz));
378 width3 += width2 + 1;
381 std::cout << name <<
" sparsity:\n";
385 for (
size_t i = 0; i < sparsity.size(); i++) {
386 std::cout <<
" " << std::setw(width) << i <<
": ";
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)) <<
" ";
392 if (printLocationByRow)
393 std::cout << std::setw(width2) << e <<
":";
394 std::cout << std::setw(width) << j <<
" ";
400 std::cout << std::endl;
403 template<
class VectorSize>
404 void printSparsityPattern(
const VectorSize& row,
405 const VectorSize& col,
406 const std::string& name,
408 std::vector<std::set<size_t> > sparsity(m);
409 generateSparsitySet(row, col, sparsity);
410 printSparsityPattern(sparsity, name);
413 inline bool intersects(
const std::set<size_t>& a,
414 const std::set<size_t>& b) {
415 if (a.empty() || b.empty()) {
417 }
else if (*a.rbegin() < *b.begin() ||
418 *a.begin() > *b.rbegin()) {
422 if (a.size() < b.size()) {
423 for (
size_t ita : a) {
424 if (b.find(ita) != b.end()) {
429 for (
size_t itb : b) {
430 if (a.find(itb) != a.end()) {
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();
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();
467 for (
size_t i = 0; i < ty.size(); i++) {
468 if (ty[i].getCodeHandler() !=
nullptr) {
469 return ty[i].getCodeHandler();
476 inline Argument<Base> asArgument(
const CG<Base>& tx) {
477 if (tx.isParameter()) {
478 return Argument<Base>(tx.getValue());
480 return Argument<Base>(*tx.getOperationNode());
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]);
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]);
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);
525 template<
class Key,
class Value>
526 void mapKeys(
const std::map<Key, Value>& map, std::vector<Key>& keys) {
527 keys.resize(map.size());
530 typename std::map<Key, Value>::const_iterator it;
531 for (it = map.begin(); it != map.end(); ++it, i++) {
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())
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)
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;
570 typename std::map<Key, Value>::const_iterator itM;
572 for (
const Key& k : keys) {
574 if (itM != m.end()) {
575 filtered[itM->first] = itM->second;
591 inline int compare(
const std::set<T>& s1,
const std::set<T>& s2) {
592 if (s1.size() < s2.size()) {
594 }
else if (s1.size() > s2.size()) {
597 typename std::set<T>::const_iterator it1, it2;
598 for (it1 = s1.begin(), it2 = s2.begin(); it1 != s1.end(); ++it1, ++it2) {
601 }
else if (*it1 > *it2) {
612 bool operator() (
const std::set<T>& lhs,
const std::set<T>& rhs)
const {
613 return compare(lhs, rhs) == -1;
621 inline void print(
const Base& v) {
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 <<
" : ";
630 std::cout << std::endl;
635 inline void print(
const std::set<Base>& s) {
638 for (
auto itj = s.begin(); itj != s.end(); ++itj) {
639 if (itj != s.begin()) std::cout <<
" ";
647 inline void print(
const std::set<Base*>& s) {
650 for (
const auto itj = s.begin(); itj != s.end(); ++itj) {
651 if (itj != s.begin()) std::cout <<
" ";
653 if (v ==
nullptr) std::cout <<
"NULL";
661 inline void print(
const std::vector<Base>& v) {
664 for (
size_t i = 0; i < v.size(); i++) {
665 if (i != 0) std::cout <<
" ";
687 inline CG<Base> makePrintValue(
const std::string& before,
689 const std::string& after =
"") {
690 std::cout << before << x << after;
692 if (x.getOperationNode() !=
nullptr) {
694 CG<Base> out(*handler->makePrintNode(before, *x.getOperationNode(), after));
714 inline void replaceString(std::string& text,
715 const std::string& toReplace,
716 const std::string& replacement) {
718 while ((pos = text.find(toReplace, pos)) != std::string::npos) {
719 text.replace(pos, toReplace.length(), replacement);
720 pos += replacement.length();
724 inline std::vector<std::string> explode(
const std::string& text,
725 const std::string& delimiter) {
726 std::vector<std::string> matches;
728 const size_t dlen = delimiter.length();
735 pos = text.find(delimiter, start);
736 if (pos == std::string::npos) {
739 matches.push_back(text.substr(start, pos - start));
743 if (start < text.length()) {
744 matches.push_back(text.substr(start, text.length() - start));
750 inline std::string implode(
const std::vector<std::string>& text,
751 const std::string& delimiter) {
754 }
else if (text.size() == 1) {
759 for (
const auto& s: text)
761 out.reserve(n + (text.size() - 1) * delimiter.size());
763 for (
size_t i = 1; i < text.size(); ++i) {
const Base & getValue() const
void setValue(const Base &val)
bool isValueDefined() const
CodeHandler< Base > * getCodeHandler() const