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;
526 langC.setMaxAssigmentsPerFunction(_maxAssignPerFunc, &_sources);
529 _cache << _name <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
"_noloop_indep" << j;
530 string functionName = _cache.str();
531 langC.setGenerateFunction(functionName);
533 std::ostringstream code;
534 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"px"));
537 handlerNL.
generateCode(code, langC, pxCustom, nameGenRev2, _atomicFunctions, subJobName);
548 string functionRev2 = _name +
"_" + FUNCTION_SPARSE_REVERSE_TWO;
549 _sources[functionRev2 +
".c"] = generateGlobalForRevWithLoopsFunctionSource(elements,
550 _loopRev2Groups, _nonLoopRev2Elements,
551 functionRev2, _name, _baseTypeName,
"indep",
552 generateFunctionNameLoopRev2);
557 generateSparsity1DSource2(_name +
"_" + FUNCTION_REVERSE_TWO_SPARSITY, elements);
558 _sources[_name +
"_" + FUNCTION_REVERSE_TWO_SPARSITY +
".c"] = _cache.str();
575 map<pairss, map<size_t, set<size_t> > > indexedIndexed2jrow2Iter;
576 map<pairss, map<size_t, set<size_t> > > indexedNonIndexed2jrow2Iter;
577 map<pairss, map<size_t, set<size_t> > > indexedTemp2jrow2Iter;
578 map<pairss, map<size_t, set<size_t> > > nonIndexedIndexed2jrow2Iter;
579 map<pairss, map<size_t, set<size_t> > > tempIndexed2jrow2Iter;
581 map<HessianTermContrib<Base>, set<size_t> > contrib2jrows = groupHessianRowsByContrib(info, n,
582 indexedIndexed2jrow2Iter,
583 indexedNonIndexed2jrow2Iter,
584 indexedTemp2jrow2Iter,
585 nonIndexedIndexed2jrow2Iter,
586 tempIndexed2jrow2Iter);
588 loopGroups.reserve(contrib2jrows.size() *2);
590 for (
const auto& itC : contrib2jrows) {
592 const set<size_t>& jrows = itC.second;
597 subgroupHessianRowsByContrib(info, c, jrows,
598 indexedIndexed2jrow2Iter,
599 indexedNonIndexed2jrow2Iter,
600 indexedTemp2jrow2Iter,
601 nonIndexedIndexed2jrow2Iter,
602 tempIndexed2jrow2Iter,
614 const std::map<
size_t, std::map<
size_t,
CG<Base> > >& dzDx,
615 std::map<
size_t, std::set<size_t> >& jrow2CompressedLoc) {
624 size_t hessElSize = group.size();
626 std::vector<pair<CGBase, IndexPattern*> > indexedLoopResults(hessElSize);
629 map<pairss, std::vector<HessianElement> >::const_iterator itPos;
634 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
641 for (
const pairss& it : group.indexedIndexed) {
642 size_t tapeJ1 = it.first;
643 size_t tapeJ2 = it.second;
645 itPos = infog.indexedIndexedPositions.find(it);
646 if (itPos != infog.indexedIndexedPositions.end()) {
647 const std::vector<HessianElement>& positions = itPos->second;
649 addContribution(indexedLoopResults, hessLE,
650 createReverseMode2Contribution(handler, group,
651 positions, infog.
hess.at(tapeJ1).at(tapeJ2), tx1,
653 jrow2CompressedLoc));
660 for (
const pairss& it : group.indexedNonIndexed) {
661 size_t tapeJ1 = it.first;
662 size_t tapeJ2 = it.second;
664 itPos = infog.indexedNonIndexedPositions.find(it);
665 if (itPos != infog.indexedNonIndexedPositions.end()) {
666 const std::vector<HessianElement>& positions = itPos->second;
668 addContribution(indexedLoopResults, hessLE,
669 createReverseMode2Contribution(handler, group,
670 positions, infog.
hess.at(tapeJ1).at(tapeJ2), tx1,
672 jrow2CompressedLoc));
679 for (
const pairss& it : group.indexedTemp) {
680 size_t tapeJ1 = it.first;
681 size_t j2 = it.second;
683 itPos = infog.indexedTempPositions.find(it);
684 if (itPos != infog.indexedTempPositions.end()) {
685 const std::vector<HessianElement>& positions = itPos->second;
686 const set<size_t>& ks = infog.indexedTempEvals.at(it);
689 for (
size_t k : ks) {
691 val += infog.
hess.at(tapeJ1).at(tapeK) * dzDx.at(k).at(j2);
694 addContribution(indexedLoopResults, hessLE,
695 createReverseMode2Contribution(handler, group,
698 jrow2CompressedLoc));
706 for (
const pairss& it : group.nonIndexedIndexed) {
707 size_t tapeJ1 = it.first;
708 size_t tapeJ2 = it.second;
710 itPos = infog.nonIndexedIndexedPositions.find(it);
711 if (itPos != infog.nonIndexedIndexedPositions.end()) {
712 const std::vector<HessianElement>& positions = itPos->second;
714 addContribution(indexedLoopResults, hessLE,
715 createReverseMode2Contribution(handler, group,
716 positions, infog.
hess.at(tapeJ1).at(tapeJ2), tx1,
718 jrow2CompressedLoc));
728 for (
const pairss& it : group.tempIndexed) {
729 size_t j1 = it.first;
730 size_t tapeJ2 = it.second;
732 itPos = infog.tempIndexedPositions.find(it);
733 if (itPos != infog.tempIndexedPositions.end()) {
734 const std::vector<HessianElement>& positions = itPos->second;
735 const set<size_t>& ks = infog.indexedTempEvals.at(pairss(tapeJ2, j1));
738 for (
size_t k : ks) {
740 val += infog.
hess.at(tapeK).at(tapeJ2) * dzDx.at(k).at(j1);
743 addContribution(indexedLoopResults, hessLE,
744 createReverseMode2Contribution(handler, group,
747 jrow2CompressedLoc));
755 for (
const pairss& orig : group.nonIndexedNonIndexed) {
756 size_t e = info.nonIndexedNonIndexedPosition.at(orig);
758 size_t j1 = orig.first;
759 size_t j2 = orig.second;
765 handler.manageLoopDependentIndexPattern(pattern);
775 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
777 set<size_t> iterations;
778 set_intersection(group.iterations.begin(), group.iterations.end(),
780 std::inserter(iterations, iterations.begin()));
782 CGBase gHessVal = Base(0);
785 if (infog.nonIndexedNonIndexedEvals.find(orig) != infog.nonIndexedNonIndexedEvals.end()) {
786 gHessVal = infog.
hess.at(posJ1->tape).at(posJ2->tape);
792 const auto itNT = infog.nonIndexedTempEvals.find(orig);
793 if (itNT != infog.nonIndexedTempEvals.end()) {
794 const set<size_t>& ks = itNT->second;
796 for (
size_t k : ks) {
798 gHessVal += infog.
hess.at(posJ1->tape).at(tapeK) * dzDx.at(k).at(j2);
808 const auto itTN = infog.tempNonIndexedEvals.find(orig);
809 if (itTN != infog.tempNonIndexedEvals.end()) {
810 const set<size_t>& ks = itTN->second;
812 for (
size_t k1 : ks) {
814 gHessVal += infog.
hess.at(tapeK).at(posJ2->tape) * dzDx.at(k1).at(j1);
821 const auto itTT = infog.tempTempEvals.find(orig);
822 if (itTT != infog.tempTempEvals.end()) {
823 const map<size_t, set<size_t> >& k1k2 = itTT->second;
827 for (
const auto& itzz : k1k2) {
828 size_t k1 = itzz.first;
829 const set<size_t>& k2s = itzz.second;
833 for (
size_t k2 : k2s) {
836 tmp += infog.
hess.at(tapeK1).at(tapeK2) * dzDx.at(k2).at(j2);
839 sum += tmp * dzDx.at(k1).at(j1);
845 if (iterations.size() != group.iterations.size()) {
846 CGBase v = createReverseMode2Contribution(handler, group,
847 *pattern, iterations,
849 *info.iterationIndexOp,
851 addContribution(indexedLoopResults, hessLE, make_pair(v, (
IndexPattern*)
nullptr));
852 jrow2CompressedLoc[j1].insert(e);
861 const auto itTT2 = info.nonLoopNonIndexedNonIndexed.find(orig);
862 if (itTT2 != info.nonLoopNonIndexedNonIndexed.end()) {
863 hessVal += info.dzDxx.at(j1).at(j2);
869 if (!hessVal.isIdenticalZero()) {
870 addContribution(indexedLoopResults, hessLE, make_pair(hessVal, (
IndexPattern*) pattern));
872 jrow2CompressedLoc[j1].insert(e);
876 indexedLoopResults.resize(hessLE);
878 return indexedLoopResults;
886 std::set<size_t> iterations;
892 const std::set<size_t>& iters) :
901 else if (l.jrow > r.jrow)
904 return compare(l.iterations, r.iterations) == -1;
913 std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedIndexed2jrow2Iter,
914 std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedNonIndexed2jrow2Iter,
915 std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedTemp2jrow2Iter,
916 std::map<pairss, std::map<
size_t, std::set<size_t> > >& nonIndexedIndexed2jrow2Iter,
917 std::map<pairss, std::map<
size_t, std::set<size_t> > >& tempIndexed2jrow2Iter) {
920 size_t nIterations = info.model->getIterationCount();
925 std::vector<HessianTermContrib<Base> > jrows(n);
927 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
931 for (
const auto& it : infog.indexedIndexedPositions) {
932 map<size_t, set<size_t> >& jrow2Iter = indexedIndexed2jrow2Iter[it.first];
933 const std::vector<HessianElement>& positions = it.second;
934 for (
size_t iter = 0; iter < nIterations; iter++) {
935 if (positions[iter].count > 0) {
936 jrows[positions[iter].row].indexedIndexed.insert(it.first);
937 jrow2Iter[positions[iter].row].insert(iter);
943 for (
const auto& it : infog.indexedNonIndexedPositions) {
944 map<size_t, set<size_t> >& jrow2Iter = indexedNonIndexed2jrow2Iter[it.first];
945 const std::vector<HessianElement>& positions = it.second;
946 for (
size_t iter = 0; iter < nIterations; iter++) {
947 if (positions[iter].count > 0) {
948 jrows[positions[iter].row].indexedNonIndexed.insert(it.first);
949 jrow2Iter[positions[iter].row].insert(iter);
955 for (
const auto& it : infog.indexedTempPositions) {
956 map<size_t, set<size_t> >& jrow2Iter = indexedTemp2jrow2Iter[it.first];
957 const std::vector<HessianElement>& positions = it.second;
958 for (
size_t iter = 0; iter < nIterations; iter++) {
959 if (positions[iter].count > 0) {
960 jrows[positions[iter].row].indexedTemp.insert(it.first);
961 jrow2Iter[positions[iter].row].insert(iter);
967 for (
const auto& it : infog.nonIndexedIndexedPositions) {
968 map<size_t, set<size_t> >& jrow2Iter = nonIndexedIndexed2jrow2Iter[it.first];
969 const std::vector<HessianElement>& positions = it.second;
970 for (
size_t iter = 0; iter < nIterations; iter++) {
971 if (positions[iter].count > 0) {
972 jrows[positions[iter].row].nonIndexedIndexed.insert(it.first);
973 jrow2Iter[positions[iter].row].insert(iter);
979 for (
const auto& it : infog.tempIndexedPositions) {
980 map<size_t, set<size_t> >& jrow2Iter = tempIndexed2jrow2Iter[it.first];
981 const std::vector<HessianElement>& positions = it.second;
982 for (
size_t iter = 0; iter < nIterations; iter++) {
983 if (positions[iter].count > 0) {
984 jrows[positions[iter].row].tempIndexed.insert(it.first);
985 jrow2Iter[positions[iter].row].insert(iter);
992 for (
const auto& orig2PosIt : info.nonIndexedNonIndexedPosition) {
993 size_t j1 = orig2PosIt.first.first;
994 jrows[j1].nonIndexedNonIndexed.insert(orig2PosIt.first);
1000 map<HessianTermContrib<Base>, set<size_t> > contrib2jrows;
1001 for (
size_t j = 0; j < n; j++) {
1002 if (!jrows[j].empty())
1003 contrib2jrows[jrows[j]].insert(j);
1006 return contrib2jrows;
1015 template<
class Base>
1018 const std::set<size_t>& jrows,
1019 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedIndexed2jrow2Iter,
1020 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedNonIndexed2jrow2Iter,
1021 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& indexedTemp2jrow2Iter,
1022 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& nonIndexedIndexed2jrow2Iter,
1023 const std::map<pairss, std::map<
size_t, std::set<size_t> > >& tempIndexed2jrow2Iter,
1025 using namespace std;
1027 map<Reverse2Jrow2Iter, HessianTermContrib<Base> > contribs;
1029 set<pairss>::const_iterator it;
1030 map<size_t, set<size_t> >::const_iterator itJrow2Iter;
1033 for (pairss pos : c.indexedIndexed) {
1034 map<size_t, set<size_t> > jrow2Iter = filterBykeys(indexedIndexed2jrow2Iter.at(pos), jrows);
1035 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1037 contribs[k].indexedIndexed.insert(pos);
1042 for (pairss pos : c.indexedNonIndexed) {
1043 map<size_t, set<size_t> > jrow2Iter = filterBykeys(indexedNonIndexed2jrow2Iter.at(pos), jrows);
1044 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1046 contribs[k].indexedNonIndexed.insert(pos);
1051 for (pairss pos : c.indexedTemp) {
1052 map<size_t, set<size_t> > jrow2Iter = filterBykeys(indexedTemp2jrow2Iter.at(pos), jrows);
1053 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1055 contribs[k].indexedTemp.insert(pos);
1060 for (pairss pos : c.nonIndexedIndexed) {
1061 map<size_t, set<size_t> > jrow2Iter = filterBykeys(nonIndexedIndexed2jrow2Iter.at(pos), jrows);
1062 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1064 contribs[k].nonIndexedIndexed.insert(pos);
1069 if (!c.nonIndexedNonIndexed.empty()) {
1070 set<size_t> allIters;
1071 size_t nIterations = info.model->getIterationCount();
1072 for (
size_t iter = 0; iter < nIterations; iter++)
1073 allIters.insert(allIters.end(), iter);
1075 for (pairss pos : c.nonIndexedNonIndexed) {
1077 contribs[k].nonIndexedNonIndexed.insert(pos);
1082 for (pairss pos : c.tempIndexed) {
1083 map<size_t, set<size_t> > jrow2Iter = filterBykeys(tempIndexed2jrow2Iter.at(pos), jrows);
1084 for (itJrow2Iter = jrow2Iter.begin(); itJrow2Iter != jrow2Iter.end(); ++itJrow2Iter) {
1086 contribs[k].tempIndexed.insert(pos);
1095 for (
const auto& itK2C : contribs) {
1099 const auto its = c2subgroups.find(hc);
1100 if (its != c2subgroups.end()) {
1102 sg->jRow2Iterations[jrow2Iters.jrow] = jrow2Iters.iterations;
1103 sg->iterations.insert(jrow2Iters.iterations.begin(), jrow2Iters.iterations.end());
1106 subGroups.push_back(sg);
1107 c2subgroups[hc] = sg;
1112 template<
class Base>
1115 const std::vector<HessianElement>& positions,
1119 std::map<
size_t, std::set<size_t> >& jrow2CompressedLoc) {
1120 using namespace std;
1122 if (ddfdxdx.isIdenticalZero()) {
1129 std::map<size_t, size_t> iteration2pos;
1132 map<size_t, map<size_t, size_t> > locations;
1133 for (
size_t iter : group.iterations) {
1134 size_t c = positions[iter].count;
1136 locations[c][iter] = positions[iter].location;
1137 iteration2pos[iter] = positions[iter].location;
1138 jrow2CompressedLoc[positions[iter].row].insert(positions[iter].location);
1142 if (locations.empty()) {
1146 map<size_t, CG<Base> > results;
1149 for (
const auto& countIt : locations) {
1150 size_t count = countIt.first;
1153 for (
size_t c = 1; c < count; c++)
1156 results[count] = val * tx1;
1159 if (results.size() == 1 && locations.begin()->second.size() == group.iterations.size()) {
1164 handler.manageLoopDependentIndexPattern(pattern);
1166 return make_pair(results.begin()->second, pattern);
1174 map<size_t, IfBranchData<Base> > branches;
1177 for (
const auto& countIt : locations) {
1178 size_t count = countIt.first;
1180 branches[count] = branch;
1183 CG<Base> v = createConditionalContribution(handler,
1185 positions.size() - 1,
1186 group.iterations.size(),
1198 template<
class Base>
1202 const std::set<size_t>& iterations,
1206 using namespace std;
1208 if (ddfdxdx.isIdenticalZero()) {
1212 CPPADCG_ASSERT_UNKNOWN(pattern.getLinearSlopeDy() == 0);
1214 if (iterations.size() == group.iterations.size()) {
1224 return createConditionalContribution(handler, pattern,
1225 iterations, *group.iterations.rbegin(),
1226 ddfdxdx, iterationIndexOp,
1234 template<
class Base>
1238 std::set<pairss> indexedIndexed;
1240 std::set<pairss> indexedNonIndexed;
1242 std::set<pairss> indexedTemp;
1244 std::set<pairss> nonIndexedIndexed;
1246 std::set<pairss> nonIndexedNonIndexed;
1248 std::set<pairss> tempIndexed;
1252 inline bool empty()
const {
1253 return indexedIndexed.empty() && indexedNonIndexed.empty() && indexedTemp.empty() &&
1254 nonIndexedIndexed.empty() && nonIndexedNonIndexed.empty() &&
1255 tempIndexed.empty();
1258 inline size_t size()
const {
1259 return indexedIndexed.size() + indexedNonIndexed.size() + indexedTemp.size() +
1260 nonIndexedIndexed.size() + nonIndexedNonIndexed.size() +
1265 template<
class Base>
1267 int c = compare(l.indexedIndexed, r.indexedIndexed);
1268 if (c != 0)
return c == -1;
1269 c = compare(l.indexedNonIndexed, r.indexedNonIndexed);
1270 if (c != 0)
return c == -1;
1271 c = compare(l.indexedTemp, r.indexedTemp);
1272 if (c != 0)
return c == -1;
1273 c = compare(l.nonIndexedIndexed, r.nonIndexedIndexed);
1274 if (c != 0)
return c == -1;
1275 c = compare(l.nonIndexedNonIndexed, r.nonIndexedNonIndexed);
1276 if (c != 0)
return c == -1;
1277 c = compare(l.tempIndexed, r.tempIndexed);
1278 if (c != 0)
return c == -1;
1286 template<
class Base>
1290 std::map<size_t, std::set<size_t> > jRow2Iterations;
1292 std::set<size_t> iterations;
1294 std::vector<IfElseInfo<Base> > ifElses;
1300 iterations(jrow2Iters.iterations) {
1301 jRow2Iterations[jrow2Iters.jrow] = jrow2Iters.iterations;
1307 template<
class Base>
1311 generateFunctionNameLoopRev2(cache, _name, loop, g);
1314 template<
class Base>
1316 const std::string& modelName,
1319 cache << modelName <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
1320 "_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)
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
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