1 #ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_REV2_INCLUDED 2 #define CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_REV2_INCLUDED 27 class HessianWithLoopsInfo;
44 const std::map<
size_t, std::map<
size_t,
CG<Base> > >& dzDx,
45 std::map<
size_t, std::set<size_t> >& jrow2CompressedLoc);
50 const std::vector<HessianElement>& positions,
54 std::map<
size_t, std::set<size_t> >& jrow2CompressedLoc);
66 size_t m = _fun.Range();
67 size_t n = _fun.Domain();
70 handler.setJobTimer(_jobTimer);
73 auto& indexJrowDcl = *handler.makeIndexDclrNode(
"jrow");
74 auto& indexLocalItDcl = *handler.makeIndexDclrNode(
"it");
75 auto& indexLocalItCountDcl = *handler.makeIndexDclrNode(
"itCount");
77 auto& jrowIndexOp = *handler.makeIndexNode(indexJrowDcl);
79 std::vector<OperationNode<Base>* > localNodes(5);
80 localNodes[0] = &indexJrowDcl;
81 localNodes[1] = &indexLocalItDcl;
82 localNodes[2] = &indexLocalItCountDcl;
83 localNodes[3] = &indexIterationDcl;
84 localNodes[4] = &jrowIndexOp;
87 std::vector<CGBase> x(n);
90 for (
size_t i = 0; i < n; i++) {
102 std::vector<CGBase> py(m);
105 for (
size_t i = 0; i < m; i++) {
106 py[i].setValue(Base(1.0));
110 size_t nonIndexdedEqSize = _funNoLoops !=
nullptr ? _funNoLoops->getOrigDependentIndexes().size() : 0;
113 for (
const auto& itJrow2jcols : elements) {
114 nnz += itJrow2jcols.second.size();
117 std::vector<size_t> hessRows(nnz);
118 std::vector<size_t> hessCols(nnz);
119 std::vector<size_t> hessOrder(nnz);
121 for (
const auto& itJrow2jcols : elements) {
122 size_t jrow = itJrow2jcols.first;
123 const std::vector<size_t>& jcols = itJrow2jcols.second;
125 for (
size_t e = 0; e < jcols.size(); e++) {
127 hessCols[ge] = jcols[e];
133 std::vector<set<size_t> > noLoopEvalJacSparsity;
134 std::vector<set<size_t> > noLoopEvalHessSparsity;
135 std::vector<map<size_t, set<size_t> > > noLoopEvalHessLocations;
138 analyseSparseHessianWithLoops(hessRows, hessCols, hessOrder,
139 noLoopEvalJacSparsity, noLoopEvalHessSparsity,
140 noLoopEvalHessLocations, loopHessInfo,
false);
149 std::vector<CGBase> tmpsAlias;
150 if (_funNoLoops !=
nullptr) {
153 tmpsAlias.resize(fun.Range() - nonIndexdedEqSize);
154 for (
size_t k = 0; k < tmpsAlias.size(); k++) {
156 tmpsAlias[k] =
CG<Base>(*handler.makeNode(CGOpCode::Alias));
164 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
168 info.iterationIndexOp = handler.makeIndexNode(indexIterationDcl);
169 set<IndexOperationNode<Base>*> indexesOps;
170 indexesOps.insert(info.iterationIndexOp);
175 std::vector<CGBase> indexedIndeps = createIndexedIndependents(handler, lModel, *info.iterationIndexOp);
176 info.x = createLoopIndependentVector(handler, lModel, indexedIndeps, x, tmpsAlias);
178 info.w = createLoopDependentVector(handler, lModel, *info.iterationIndexOp);
187 bool hasAtomics = isAtomicsUsed();
190 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
195 _cache <<
"model (Jacobian + Hessian, loop " << lModel.
getLoopId() <<
")";
196 std::string jobName = _cache.str();
198 startingJob(
"'" + jobName +
"'", JobTimer::GRAPH);
208 map<size_t, map<size_t, CGBase> > dzDx;
209 if (_funNoLoops !=
nullptr) {
211 std::vector<CGBase> yNL(fun.Range());
216 startingJob(
"'model (Jacobian + Hessian, temporaries)'", JobTimer::GRAPH);
218 dzDx = _funNoLoops->calculateJacobianHessianUsedByLoops(handler,
219 loopHessInfo, x, yNL,
220 noLoopEvalJacSparsity,
225 for (
size_t i = 0; i < tmpsAlias.size(); i++)
226 tmpsAlias[i].getOperationNode()->getArguments().push_back(asArgument(yNL[nonIndexdedEqSize + i]));
228 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
238 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
248 generateHessianRowGroups(lModel, info, n, loopGroups);
253 for (
size_t g = 0; g < loopGroups.size(); g++) {
261 map<size_t, set<size_t> > localIterCount2Jrows;
263 for (
const auto& itJrow2It : group.jRow2Iterations) {
264 size_t jrow = itJrow2It.first;
265 size_t itCount = itJrow2It.second.size();
266 localIterCount2Jrows[itCount].insert(jrow);
269 bool createsLoop = localIterCount2Jrows.size() != 1 ||
270 localIterCount2Jrows.begin()->first != 1;
278 map<size_t, map<size_t, size_t> > jrow2localIt2ModelIt;
280 for (
const auto& itJrow2It : group.jRow2Iterations) {
281 size_t jrow = itJrow2It.first;
283 map<size_t, size_t>& localIt2ModelIt = jrow2localIt2ModelIt[jrow];
285 for (
auto itIt = itJrow2It.second.begin(); itIt != itJrow2It.second.end(); ++itIt, localIt++) {
286 localIt2ModelIt[localIt] = *itIt;
296 if (itPattern.get() ==
nullptr) {
307 std::unique_ptr<IndexPattern> indexLocalItCountPattern;
310 map<size_t, size_t> jrow2litCount;
312 for (
const auto& itJrow2Its : group.jRow2Iterations) {
313 size_t jrow = itJrow2Its.first;
314 jrow2litCount[jrow] = itJrow2Its.second.size();
319 if (IndexPattern::isConstant(*indexLocalItCountPattern.get())) {
320 size_t itCount = group.jRow2Iterations.begin()->second.size();
321 loopStart = handler.makeLoopStartNode(indexLocalItDcl, itCount);
323 itCountAssignOp = handler.makeIndexAssignNode(indexLocalItCountDcl, *indexLocalItCountPattern.get(), jrowIndexOp);
324 localIterCountIndexOp = handler.makeIndexNode(*itCountAssignOp);
325 loopStart = handler.makeLoopStartNode(indexLocalItDcl, *localIterCountIndexOp);
328 localIterIndexOp = handler.makeIndexNode(*loopStart);
332 auto* iterationIndexPatternOp = handler.makeIndexAssignNode(indexIterationDcl, *itPattern.get(), &jrowIndexOp, localIterIndexOp);
333 info.iterationIndexOp->makeAssigmentDependent(*iterationIndexPatternOp);
335 map<size_t, set<size_t> > jrow2CompressedLoc;
336 std::vector<pair<CG<Base>,
IndexPattern*> > indexedLoopResults;
338 indexedLoopResults = generateReverseTwoGroupOps(handler, lModel, info,
343 _loopRev2Groups[&lModel][g] = jrow2CompressedLoc;
346 std::vector<CGBase> pxCustom;
351 size_t assignOrAdd = 1;
352 set<IndexOperationNode<Base>*> indexesOps;
353 indexesOps.insert(info.iterationIndexOp);
354 loopEnd = createLoopEnd(handler, *loopStart, indexedLoopResults, indexesOps, assignOrAdd);
359 moveNonIndexedOutsideLoop(handler, *loopStart, *loopEnd);
367 pxCustom[0] = handler.createCG(*handler.makeNode(CGOpCode::DependentRefRhs,{0},{*loopEnd}));
373 pxCustom.resize(indexedLoopResults.size());
374 for (
size_t i = 0; i < indexedLoopResults.size(); i++) {
375 const CGBase& val = indexedLoopResults[i].first;
378 pxCustom[i] = createLoopDependentFunctionResult(handler, i, val, ip, *info.iterationIndexOp);
384 langC.setFunctionIndexArgument(indexJrowDcl);
387 std::ostringstream code;
388 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"px"));
395 _cache <<
"model (reverse two, loop " << lModel.
getLoopId() <<
", group " << g <<
")";
396 string jobName = _cache.str();
397 handler.
generateCode(code, langC, pxCustom, nameGenRev2, _atomicFunctions, jobName);
400 generateFunctionNameLoopRev2(_cache, lModel, g);
401 std::string functionName = _cache.str();
403 std::string argsDcl = langC.generateFunctionArgumentsDcl();
406 _cache <<
"#include <stdlib.h>\n" 407 "#include <math.h>\n" 411 "void " << functionName <<
"(" << argsDcl <<
") {\n";
412 nameGenRev2.customFunctionVariableDeclarations(_cache);
413 _cache << langC.generateIndependentVariableDeclaration() <<
"\n";
414 _cache << langC.generateDependentVariableDeclaration() <<
"\n";
415 _cache << langC.generateTemporaryVariableDeclaration(
false,
false,
418 nameGenRev2.prepareCustomFunctionVariables(_cache);
421 _cache << code.str();
423 nameGenRev2.finalizeCustomFunctionVariables(_cache);
426 _sources[functionName +
".c"] = _cache.str();
432 if (g + 1 < loopGroups.size()) {
442 if (_funNoLoops !=
nullptr) {
448 std::vector<size_t> row, col;
449 generateSparsityIndexes(noLoopEvalHessSparsity, row, col);
451 if (row.size() > 0) {
452 const string jobName =
"model (reverse two, no loops)";
453 startingJob(
"'" + jobName +
"'", JobTimer::SOURCE_GENERATION);
457 handlerNL.setJobTimer(_jobTimer);
459 std::vector<CGBase> tx0(n);
462 for (
size_t i = 0; i < n; i++) {
463 tx0[i].setValue(_x[i]);
473 std::vector<CGBase> py(m);
476 std::vector<CGBase> pyNoLoop(_funNoLoops->getTapeDependentCount());
478 const std::vector<size_t>& origIndexes = _funNoLoops->getOrigDependentIndexes();
479 for (
size_t inl = 0; inl < origIndexes.size(); inl++) {
480 pyNoLoop[inl] = py[origIndexes[inl]];
482 pyNoLoop[inl].setValue(Base(1.0));
486 std::vector<CGBase> hessNoLoop(row.size());
488 CppAD::sparse_hessian_work work;
492 work.color_method =
"cppad.general";
493 fun.SparseHessian(tx0, pyNoLoop, _funNoLoops->getHessianOrigEqsSparsity(), row, col, hessNoLoop, work);
495 map<size_t, map<size_t, CGBase> > hess;
497 for (
size_t el = 0; el < row.size(); el++) {
500 const set<size_t>& locations = noLoopEvalHessLocations[j1][j2];
501 for (
size_t itE : locations) {
502 hess[j1][itE] = hessNoLoop[el];
503 _nonLoopRev2Elements[j1].insert(itE);
510 for (
const auto& it : hess) {
512 const map<size_t, CGBase>& cols = it.second;
515 _cache <<
"model (reverse two, no loops, indep " << j <<
")";
516 const string subJobName = _cache.str();
518 std::vector<CGBase> pxCustom(elements.at(j).size());
520 for (
const auto& it2 : cols) {
521 size_t e = it2.first;
522 pxCustom[e] = it2.second * tx1;
530 _cache << _name <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
"_noloop_indep" << j;
531 string functionName = _cache.str();
532 langC.setGenerateFunction(functionName);
534 std::ostringstream code;
535 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"px"));
538 handlerNL.
generateCode(code, langC, pxCustom, nameGenRev2, _atomicFunctions, subJobName);
549 string functionRev2 = _name +
"_" + FUNCTION_SPARSE_REVERSE_TWO;
550 _sources[functionRev2 +
".c"] = generateGlobalForRevWithLoopsFunctionSource(elements,
551 _loopRev2Groups, _nonLoopRev2Elements,
552 functionRev2, _name, _baseTypeName,
"indep",
553 generateFunctionNameLoopRev2);
558 generateSparsity1DSource2(_name +
"_" + FUNCTION_REVERSE_TWO_SPARSITY, elements);
559 _sources[_name +
"_" + FUNCTION_REVERSE_TWO_SPARSITY +
".c"] = _cache.str();
576 map<pairss, map<size_t, set<size_t> > > indexedIndexed2jrow2Iter;
577 map<pairss, map<size_t, set<size_t> > > indexedNonIndexed2jrow2Iter;
578 map<pairss, map<size_t, set<size_t> > > indexedTemp2jrow2Iter;
579 map<pairss, map<size_t, set<size_t> > > nonIndexedIndexed2jrow2Iter;
580 map<pairss, map<size_t, set<size_t> > > tempIndexed2jrow2Iter;
582 map<HessianTermContrib<Base>, set<size_t> > contrib2jrows = groupHessianRowsByContrib(info, n,
583 indexedIndexed2jrow2Iter,
584 indexedNonIndexed2jrow2Iter,
585 indexedTemp2jrow2Iter,
586 nonIndexedIndexed2jrow2Iter,
587 tempIndexed2jrow2Iter);
589 loopGroups.reserve(contrib2jrows.size() *2);
591 for (
const auto& itC : contrib2jrows) {
593 const set<size_t>& jrows = itC.second;
598 subgroupHessianRowsByContrib(info, c, jrows,
599 indexedIndexed2jrow2Iter,
600 indexedNonIndexed2jrow2Iter,
601 indexedTemp2jrow2Iter,
602 nonIndexedIndexed2jrow2Iter,
603 tempIndexed2jrow2Iter,
615 const std::map<
size_t, std::map<
size_t,
CG<Base> > >& dzDx,
616 std::map<
size_t, std::set<size_t> >& jrow2CompressedLoc) {
625 size_t hessElSize = group.size();
627 std::vector<pair<CGBase, IndexPattern*> > indexedLoopResults(hessElSize);
630 map<pairss, std::vector<HessianElement> >::const_iterator itPos;
635 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
642 for (
const pairss& it : group.indexedIndexed) {
643 size_t tapeJ1 = it.first;
644 size_t tapeJ2 = it.second;
646 itPos = infog.indexedIndexedPositions.find(it);
647 if (itPos != infog.indexedIndexedPositions.end()) {
648 const std::vector<HessianElement>& positions = itPos->second;
650 addContribution(indexedLoopResults, hessLE,
651 createReverseMode2Contribution(handler, group,
652 positions, infog.
hess.at(tapeJ1).at(tapeJ2), tx1,
654 jrow2CompressedLoc));
661 for (
const pairss& it : group.indexedNonIndexed) {
662 size_t tapeJ1 = it.first;
663 size_t tapeJ2 = it.second;
665 itPos = infog.indexedNonIndexedPositions.find(it);
666 if (itPos != infog.indexedNonIndexedPositions.end()) {
667 const std::vector<HessianElement>& positions = itPos->second;
669 addContribution(indexedLoopResults, hessLE,
670 createReverseMode2Contribution(handler, group,
671 positions, infog.
hess.at(tapeJ1).at(tapeJ2), tx1,
673 jrow2CompressedLoc));
680 for (
const pairss& it : group.indexedTemp) {
681 size_t tapeJ1 = it.first;
682 size_t j2 = it.second;
684 itPos = infog.indexedTempPositions.find(it);
685 if (itPos != infog.indexedTempPositions.end()) {
686 const std::vector<HessianElement>& positions = itPos->second;
687 const set<size_t>& ks = infog.indexedTempEvals.at(it);
690 for (
size_t k : ks) {
692 val += infog.
hess.at(tapeJ1).at(tapeK) * dzDx.at(k).at(j2);
695 addContribution(indexedLoopResults, hessLE,
696 createReverseMode2Contribution(handler, group,
699 jrow2CompressedLoc));
707 for (
const pairss& it : group.nonIndexedIndexed) {
708 size_t tapeJ1 = it.first;
709 size_t tapeJ2 = it.second;
711 itPos = infog.nonIndexedIndexedPositions.find(it);
712 if (itPos != infog.nonIndexedIndexedPositions.end()) {
713 const std::vector<HessianElement>& positions = itPos->second;
715 addContribution(indexedLoopResults, hessLE,
716 createReverseMode2Contribution(handler, group,
717 positions, infog.
hess.at(tapeJ1).at(tapeJ2), tx1,
719 jrow2CompressedLoc));
729 for (
const pairss& it : group.tempIndexed) {
730 size_t j1 = it.first;
731 size_t tapeJ2 = it.second;
733 itPos = infog.tempIndexedPositions.find(it);
734 if (itPos != infog.tempIndexedPositions.end()) {
735 const std::vector<HessianElement>& positions = itPos->second;
736 const set<size_t>& ks = infog.indexedTempEvals.at(pairss(tapeJ2, j1));
739 for (
size_t k : ks) {
741 val += infog.
hess.at(tapeK).at(tapeJ2) * dzDx.at(k).at(j1);
744 addContribution(indexedLoopResults, hessLE,
745 createReverseMode2Contribution(handler, group,
748 jrow2CompressedLoc));
756 for (
const pairss& orig : group.nonIndexedNonIndexed) {
757 size_t e = info.nonIndexedNonIndexedPosition.at(orig);
759 size_t j1 = orig.first;
760 size_t j2 = orig.second;
766 handler.manageLoopDependentIndexPattern(pattern);
776 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
778 set<size_t> iterations;
779 set_intersection(group.iterations.begin(), group.iterations.end(),
781 std::inserter(iterations, iterations.begin()));
783 CGBase gHessVal = Base(0);
786 if (infog.nonIndexedNonIndexedEvals.find(orig) != infog.nonIndexedNonIndexedEvals.end()) {
787 gHessVal = infog.
hess.at(posJ1->tape).at(posJ2->tape);
793 const auto itNT = infog.nonIndexedTempEvals.find(orig);
794 if (itNT != infog.nonIndexedTempEvals.end()) {
795 const set<size_t>& ks = itNT->second;
797 for (
size_t k : ks) {
799 gHessVal += infog.
hess.at(posJ1->tape).at(tapeK) * dzDx.at(k).at(j2);
809 const auto itTN = infog.tempNonIndexedEvals.find(orig);
810 if (itTN != infog.tempNonIndexedEvals.end()) {
811 const set<size_t>& ks = itTN->second;
813 for (
size_t k1 : ks) {
815 gHessVal += infog.
hess.at(tapeK).at(posJ2->tape) * dzDx.at(k1).at(j1);
822 const auto itTT = infog.tempTempEvals.find(orig);
823 if (itTT != infog.tempTempEvals.end()) {
824 const map<size_t, set<size_t> >& k1k2 = itTT->second;
828 for (
const auto& itzz : k1k2) {
829 size_t k1 = itzz.first;
830 const set<size_t>& k2s = itzz.second;
834 for (
size_t k2 : k2s) {
837 tmp += infog.
hess.at(tapeK1).at(tapeK2) * dzDx.at(k2).at(j2);
840 sum += tmp * dzDx.at(k1).at(j1);
846 if (iterations.size() != group.iterations.size()) {
847 CGBase v = createReverseMode2Contribution(handler, group,
848 *pattern, iterations,
850 *info.iterationIndexOp,
852 addContribution(indexedLoopResults, hessLE, make_pair(v, (
IndexPattern*)
nullptr));
853 jrow2CompressedLoc[j1].insert(e);
862 const auto itTT2 = info.nonLoopNonIndexedNonIndexed.find(orig);
863 if (itTT2 != info.nonLoopNonIndexedNonIndexed.end()) {
864 hessVal += info.dzDxx.at(j1).at(j2);
870 if (!hessVal.isIdenticalZero()) {
871 addContribution(indexedLoopResults, hessLE, make_pair(hessVal, (
IndexPattern*) pattern));
873 jrow2CompressedLoc[j1].insert(e);
877 indexedLoopResults.resize(hessLE);
879 return indexedLoopResults;
887 std::set<size_t> iterations;
893 const std::set<size_t>& iters) :
902 else if (l.jrow > r.jrow)
905 return compare(l.iterations, r.iterations) == -1;
914 std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedIndexed2jrow2Iter,
915 std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedNonIndexed2jrow2Iter,
916 std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedTemp2jrow2Iter,
917 std::map<pairss, std::map<
size_t, std::set<size_t> > >& nonIndexedIndexed2jrow2Iter,
918 std::map<pairss, std::map<
size_t, std::set<size_t> > >& tempIndexed2jrow2Iter) {
921 size_t nIterations = info.model->getIterationCount();
926 std::vector<HessianTermContrib<Base> > jrows(n);
928 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
932 for (
const auto& it : infog.indexedIndexedPositions) {
933 map<size_t, set<size_t> >& jrow2Iter = indexedIndexed2jrow2Iter[it.first];
934 const std::vector<HessianElement>& positions = it.second;
935 for (
size_t iter = 0; iter < nIterations; iter++) {
936 if (positions[iter].count > 0) {
937 jrows[positions[iter].row].indexedIndexed.insert(it.first);
938 jrow2Iter[positions[iter].row].insert(iter);
944 for (
const auto& it : infog.indexedNonIndexedPositions) {
945 map<size_t, set<size_t> >& jrow2Iter = indexedNonIndexed2jrow2Iter[it.first];
946 const std::vector<HessianElement>& positions = it.second;
947 for (
size_t iter = 0; iter < nIterations; iter++) {
948 if (positions[iter].count > 0) {
949 jrows[positions[iter].row].indexedNonIndexed.insert(it.first);
950 jrow2Iter[positions[iter].row].insert(iter);
956 for (
const auto& it : infog.indexedTempPositions) {
957 map<size_t, set<size_t> >& jrow2Iter = indexedTemp2jrow2Iter[it.first];
958 const std::vector<HessianElement>& positions = it.second;
959 for (
size_t iter = 0; iter < nIterations; iter++) {
960 if (positions[iter].count > 0) {
961 jrows[positions[iter].row].indexedTemp.insert(it.first);
962 jrow2Iter[positions[iter].row].insert(iter);
968 for (
const auto& it : infog.nonIndexedIndexedPositions) {
969 map<size_t, set<size_t> >& jrow2Iter = nonIndexedIndexed2jrow2Iter[it.first];
970 const std::vector<HessianElement>& positions = it.second;
971 for (
size_t iter = 0; iter < nIterations; iter++) {
972 if (positions[iter].count > 0) {
973 jrows[positions[iter].row].nonIndexedIndexed.insert(it.first);
974 jrow2Iter[positions[iter].row].insert(iter);
980 for (
const auto& it : infog.tempIndexedPositions) {
981 map<size_t, set<size_t> >& jrow2Iter = tempIndexed2jrow2Iter[it.first];
982 const std::vector<HessianElement>& positions = it.second;
983 for (
size_t iter = 0; iter < nIterations; iter++) {
984 if (positions[iter].count > 0) {
985 jrows[positions[iter].row].tempIndexed.insert(it.first);
986 jrow2Iter[positions[iter].row].insert(iter);
993 for (
const auto& orig2PosIt : info.nonIndexedNonIndexedPosition) {
994 size_t j1 = orig2PosIt.first.first;
995 jrows[j1].nonIndexedNonIndexed.insert(orig2PosIt.first);
1001 map<HessianTermContrib<Base>, set<size_t> > contrib2jrows;
1002 for (
size_t j = 0; j < n; j++) {
1003 if (!jrows[j].empty())
1004 contrib2jrows[jrows[j]].insert(j);
1007 return contrib2jrows;
1016 template<
class Base>
1019 const std::set<size_t>& jrows,
1020 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedIndexed2jrow2Iter,
1021 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedNonIndexed2jrow2Iter,
1022 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedTemp2jrow2Iter,
1023 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& nonIndexedIndexed2jrow2Iter,
1024 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& tempIndexed2jrow2Iter,
1026 using namespace std;
1028 map<Reverse2Jrow2Iter, HessianTermContrib<Base> > contribs;
1030 set<pairss>::const_iterator it;
1031 map<size_t, set<size_t> >::const_iterator itJrow2Iter;
1034 for (pairss pos : c.indexedIndexed) {
1035 map<size_t, set<size_t> > jrow2Iter = filterBykeys(indexedIndexed2jrow2Iter.at(pos), jrows);
1036 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1038 contribs[k].indexedIndexed.insert(pos);
1043 for (pairss pos : c.indexedNonIndexed) {
1044 map<size_t, set<size_t> > jrow2Iter = filterBykeys(indexedNonIndexed2jrow2Iter.at(pos), jrows);
1045 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1047 contribs[k].indexedNonIndexed.insert(pos);
1052 for (pairss pos : c.indexedTemp) {
1053 map<size_t, set<size_t> > jrow2Iter = filterBykeys(indexedTemp2jrow2Iter.at(pos), jrows);
1054 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1056 contribs[k].indexedTemp.insert(pos);
1061 for (pairss pos : c.nonIndexedIndexed) {
1062 map<size_t, set<size_t> > jrow2Iter = filterBykeys(nonIndexedIndexed2jrow2Iter.at(pos), jrows);
1063 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1065 contribs[k].nonIndexedIndexed.insert(pos);
1070 if (!c.nonIndexedNonIndexed.empty()) {
1071 set<size_t> allIters;
1072 size_t nIterations = info.model->getIterationCount();
1073 for (
size_t iter = 0; iter < nIterations; iter++)
1074 allIters.insert(allIters.end(), iter);
1076 for (pairss pos : c.nonIndexedNonIndexed) {
1078 contribs[k].nonIndexedNonIndexed.insert(pos);
1083 for (pairss pos : c.tempIndexed) {
1084 map<size_t, set<size_t> > jrow2Iter = filterBykeys(tempIndexed2jrow2Iter.at(pos), jrows);
1085 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1087 contribs[k].tempIndexed.insert(pos);
1096 for (
const auto& itK2C : contribs) {
1100 const auto its = c2subgroups.find(hc);
1101 if (its != c2subgroups.end()) {
1103 sg->jRow2Iterations[jrow2Iters.jrow] = jrow2Iters.iterations;
1104 sg->iterations.insert(jrow2Iters.iterations.begin(), jrow2Iters.iterations.end());
1107 subGroups.push_back(sg);
1108 c2subgroups[hc] = sg;
1113 template<
class Base>
1116 const std::vector<HessianElement>& positions,
1120 std::map<
size_t, std::set<size_t> >& jrow2CompressedLoc) {
1121 using namespace std;
1123 if (ddfdxdx.isIdenticalZero()) {
1130 std::map<size_t, size_t> iteration2pos;
1133 map<size_t, map<size_t, size_t> > locations;
1134 for (
size_t iter : group.iterations) {
1135 size_t c = positions[iter].count;
1137 locations[c][iter] = positions[iter].location;
1138 iteration2pos[iter] = positions[iter].location;
1139 jrow2CompressedLoc[positions[iter].row].insert(positions[iter].location);
1143 if (locations.empty()) {
1147 map<size_t, CG<Base> > results;
1150 for (
const auto& countIt : locations) {
1151 size_t count = countIt.first;
1154 for (
size_t c = 1; c < count; c++)
1157 results[count] = val * tx1;
1160 if (results.size() == 1 && locations.begin()->second.size() == group.iterations.size()) {
1165 handler.manageLoopDependentIndexPattern(pattern);
1167 return make_pair(results.begin()->second, pattern);
1175 map<size_t, IfBranchData<Base> > branches;
1178 for (
const auto& countIt : locations) {
1179 size_t count = countIt.first;
1181 branches[count] = branch;
1184 CG<Base> v = createConditionalContribution(handler,
1186 positions.size() - 1,
1187 group.iterations.size(),
1199 template<
class Base>
1203 const std::set<size_t>& iterations,
1207 using namespace std;
1209 if (ddfdxdx.isIdenticalZero()) {
1213 CPPADCG_ASSERT_UNKNOWN(pattern.getLinearSlopeDy() == 0);
1215 if (iterations.size() == group.iterations.size()) {
1225 return createConditionalContribution(handler, pattern,
1226 iterations, *group.iterations.rbegin(),
1227 ddfdxdx, iterationIndexOp,
1235 template<
class Base>
1239 std::set<pairss> indexedIndexed;
1241 std::set<pairss> indexedNonIndexed;
1243 std::set<pairss> indexedTemp;
1245 std::set<pairss> nonIndexedIndexed;
1247 std::set<pairss> nonIndexedNonIndexed;
1249 std::set<pairss> tempIndexed;
1253 inline bool empty()
const {
1254 return indexedIndexed.empty() && indexedNonIndexed.empty() && indexedTemp.empty() &&
1255 nonIndexedIndexed.empty() && nonIndexedNonIndexed.empty() &&
1256 tempIndexed.empty();
1259 inline size_t size()
const {
1260 return indexedIndexed.size() + indexedNonIndexed.size() + indexedTemp.size() +
1261 nonIndexedIndexed.size() + nonIndexedNonIndexed.size() +
1266 template<
class Base>
1268 int c = compare(l.indexedIndexed, r.indexedIndexed);
1269 if (c != 0)
return c == -1;
1270 c = compare(l.indexedNonIndexed, r.indexedNonIndexed);
1271 if (c != 0)
return c == -1;
1272 c = compare(l.indexedTemp, r.indexedTemp);
1273 if (c != 0)
return c == -1;
1274 c = compare(l.nonIndexedIndexed, r.nonIndexedIndexed);
1275 if (c != 0)
return c == -1;
1276 c = compare(l.nonIndexedNonIndexed, r.nonIndexedNonIndexed);
1277 if (c != 0)
return c == -1;
1278 c = compare(l.tempIndexed, r.tempIndexed);
1279 if (c != 0)
return c == -1;
1287 template<
class Base>
1291 std::map<size_t, std::set<size_t> > jRow2Iterations;
1293 std::set<size_t> iterations;
1295 std::vector<IfElseInfo<Base> > ifElses;
1301 iterations(jrow2Iters.iterations) {
1302 jRow2Iterations[jrow2Iters.jrow] = jrow2Iters.iterations;
1308 template<
class Base>
1312 generateFunctionNameLoopRev2(cache, _name, loop, g);
1315 template<
class Base>
1317 const std::string& modelName,
1320 cache << modelName <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
1321 "_loop" << loop.
getLoopId() <<
"_g" << g;
void evalLoopModelJacobianHessian(bool individualColoring)
std::map< size_t, std::map< size_t, CG< Base > > > hess
void setValue(const Base &val)
void setMaxOperationsPerAssignment(size_t maxOperationsPerAssignment)
static Plane2DIndexPattern * detectPlane2D(const std::map< size_t, std::map< size_t, size_t > > &x2y2z)
std::vector< std::map< size_t, CG< Base > > > dyiDzk
const std::vector< int > & getExternalFuncMaxForwardOrder() const
static IndexPattern * detect(const VectorSizeT &x2y)
void makeVariables(VectorCG &variables)
const LoopPosition * getTempIndepIndexes(size_t k) const
virtual void setMaxAssignmentsPerFunction(size_t maxAssignmentsPerFunction, std::map< std::string, std::string > *sources)
void makeVariable(AD< CGB > &variable)
virtual void setParameterPrecision(size_t p)
const std::vector< LoopPosition > & getNonIndexedIndepIndexes() const
virtual void prepareSparseReverseTwoWithLoops(const std::map< size_t, std::vector< size_t > > &elements)
const std::vector< IterEquationGroup< Base > > & getEquationsGroups() const
void setZeroDependents(bool zeroDependents)
const std::vector< int > & getExternalFuncMaxReverseOrder() const
virtual void generateCode(std::ostream &out, Language< Base > &lang, CppAD::vector< CGB > &dependent, VariableNameGenerator< Base > &nameGen, const std::string &jobName="source")
std::set< size_t > iterations
iterations which only have these equations defined