1 #ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_HESS_INCLUDED 2 #define CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_HESS_INCLUDED 30 location(std::numeric_limits<size_t>::max()),
31 row(std::numeric_limits<size_t>::max()),
39 const std::vector<HessianElement>& positions,
52 const std::vector<size_t>& lowerHessCols,
53 const std::vector<size_t>& lowerHessOrder,
54 std::vector<std::set<size_t> >& noLoopEvalJacSparsity,
55 std::vector<std::set<size_t> >& noLoopEvalHessSparsity,
56 std::vector<std::map<
size_t, std::set<size_t> > >& noLoopEvalHessLocations,
62 size_t nonIndexdedEqSize = _funNoLoops !=
nullptr ? _funNoLoops->getOrigDependentIndexes().size() : 0;
68 l->evalJacobianSparsity();
69 l->evalHessianSparsity();
72 if (_funNoLoops !=
nullptr) {
73 _funNoLoops->evalJacobianSparsity();
74 _funNoLoops->evalHessianSparsity();
77 size_t m = _fun.Range();
78 size_t n = _fun.Domain();
80 size_t nnz = lowerHessRows.size();
82 noLoopEvalJacSparsity.resize(_funNoLoops !=
nullptr ? m : 0);
83 noLoopEvalHessSparsity.resize(_funNoLoops !=
nullptr ? n : 0);
84 noLoopEvalHessLocations.resize(noLoopEvalHessSparsity.size());
92 loopHessInfol.noLoopEvalHessTempsSparsity.resize(_funNoLoops !=
nullptr ? n : 0);
95 auto flipIndices = [&](
const std::vector<set<size_t> >& groupHess,
98 return useSymmetry && tape1 > tape2 && groupHess[tape2].find(tape1) != groupHess[tape2].end();
101 auto flipIndices2 = [&](
const std::vector<set<size_t> >& groupHess,
104 return useSymmetry && groupHess[tape2].find(tape1) != groupHess[tape2].end();
112 for (
size_t eh = 0; eh < nnz; eh++) {
113 size_t j1 = lowerHessRows[eh];
114 size_t j2 = lowerHessCols[eh];
115 size_t e = lowerHessOrder[eh];
117 if (_funNoLoops !=
nullptr) {
119 const std::vector<std::set<size_t> >& dydxx = _funNoLoops->getHessianOrigEqsSparsity();
120 if (dydxx.size() > 0) {
121 if (dydxx[j1].find(j2) != dydxx[j1].end()) {
125 noLoopEvalHessSparsity[j1].insert(j2);
126 noLoopEvalHessLocations[j1][j2].insert(e);
132 size_t nIter = loop->getIterationCount();
134 const std::vector<IterEquationGroup<Base> >& eqGroups = loop->getEquationsGroups();
135 const std::vector<set<size_t> >& loopJac = loop->getJacobianSparsity();
138 const std::vector<std::vector<LoopPosition> >& indexedIndepIndexes = loop->getIndexedIndepIndexes();
139 const std::vector<LoopPosition>& nonIndexedIndepIndexes = loop->getNonIndexedIndepIndexes();
140 const std::vector<LoopPosition>& temporaryIndependents = loop->getTemporaryIndependents();
142 size_t nIndexed = indexedIndepIndexes.size();
143 size_t nNonIndexed = nonIndexedIndepIndexes.size();
145 const LoopPosition* posJ1 = loop->getNonIndexedIndepIndexes(j1);
146 const LoopPosition* posJ2 = (j1 == j2) ? posJ1 : loop->getNonIndexedIndepIndexes(j2);
148 size_t nEqGroups = loopInfo.equationGroups.size();
150 for (
size_t g = 0; g < nEqGroups; g++) {
152 const std::vector<set<size_t> >& groupHess = group.getHessianSparsity();
160 for (
size_t iteration = 0; iteration < iter2tapeJJ.size(); iteration++) {
161 const set<pairss>& tapePairs = iter2tapeJJ[iteration];
163 for (
const pairss& itPairs : tapePairs) {
164 size_t tape1 = itPairs.first;
165 size_t tape2 = itPairs.second;
168 bool flip = flipIndices(groupHess, tape1, tape2);
170 tape = pairss(tape2, tape1);
175 std::vector<HessianElement>& positions = loopInfo.equationGroups[g].indexedIndexedPositions[tape];
176 positions.resize(nIter);
178 positions[iteration].location = e;
179 positions[iteration].row = j1;
180 positions[iteration].count++;
182 loopInfo.equationGroups[g].evalHessSparsity[tape.first].insert(tape.second);
192 if (posJ2 !=
nullptr) {
194 const std::vector<set<size_t> >& iter2tapeJ1OrigJ2 = group.getHessianIndexedNonIndexedTapeIndexes(j1, j2);
195 for (
size_t iteration = 0; iteration < iter2tapeJ1OrigJ2.size(); iteration++) {
196 const set<size_t>& tapeJ1s = iter2tapeJ1OrigJ2[iteration];
198 for (
size_t tapeJ1 : tapeJ1s) {
200 bool flip = flipIndices2(groupHess, tapeJ1, posJ2->tape);
202 std::vector<HessianElement>* positions;
204 positions = &loopInfo.equationGroups[g].nonIndexedIndexedPositions[pairss(posJ2->tape, tapeJ1)];
205 loopInfo.equationGroups[g].evalHessSparsity[posJ2->tape].insert(tapeJ1);
207 positions = &loopInfo.equationGroups[g].indexedNonIndexedPositions[pairss(tapeJ1, posJ2->tape)];
208 loopInfo.equationGroups[g].evalHessSparsity[tapeJ1].insert(posJ2->tape);
211 positions->resize(nIter);
212 (*positions)[iteration].location = e;
213 (*positions)[iteration].row = j1;
214 (*positions)[iteration].count++;
226 if (_funNoLoops !=
nullptr) {
227 map<size_t, set<size_t> > iter2tapeJ1 = loop->getIndexedTapeIndexes(j1);
228 for (
const auto& itIter : iter2tapeJ1) {
229 size_t iteration = itIter.first;
230 const set<size_t>& tapeJ1s = itIter.second;
231 const set<const IterEquationGroup<Base>*>& groups = loop->getIterationEquationsGroup()[iteration];
233 for (
size_t tapeJ1 : tapeJ1s) {
236 size_t g = group.
index;
238 const std::vector<set<size_t> >& groupHess = group.getHessianSparsity();
240 set<size_t>::const_iterator itz = groupHess[tapeJ1].lower_bound(nIndexed + nNonIndexed);
242 pairss pos(tapeJ1, j2);
246 for (; itz != groupHess[tapeJ1].end(); ++itz) {
248 size_t k = temporaryIndependents[tapeJ - nIndexed - nNonIndexed].original;
253 const set<size_t>& sparsity = _funNoLoops->getJacobianSparsity()[nonIndexdedEqSize + k];
254 if (sparsity.find(j2) != sparsity.end()) {
255 noLoopEvalJacSparsity[nonIndexdedEqSize + k].insert(j2);
257 size_t tapeK = loop->getTempIndepIndexes(k)->tape;
261 set<size_t>& evals = groupInfo.indexedTempEvals[pos];
264 groupInfo.evalHessSparsity[tapeJ1].insert(tapeK);
270 std::vector<HessianElement>& positions = groupInfo.indexedTempPositions[pos];
271 positions.resize(nIter);
273 positions[iteration].location = e;
274 positions[iteration].row = j1;
275 positions[iteration].count++;
290 if (posJ1 !=
nullptr) {
292 for (
size_t g = 0; g < nEqGroups; g++) {
295 const std::vector<set<size_t> >& iter2TapeJ2 = group.getHessianNonIndexedIndexedTapeIndexes(j1, j2);
296 for (
size_t iteration = 0; iteration < iter2TapeJ2.size(); iteration++) {
297 const set<size_t>& tapeJ2s = iter2TapeJ2[iteration];
299 for (
size_t tapeJ2 : tapeJ2s) {
300 std::vector<HessianElement>& positions = loopInfo.equationGroups[g].nonIndexedIndexedPositions[pairss(posJ1->tape, tapeJ2)];
301 positions.resize(nIter);
302 positions[iteration].location = e;
303 positions[iteration].row = j1;
304 positions[iteration].count++;
306 loopInfo.equationGroups[g].evalHessSparsity[posJ1->tape].insert(tapeJ2);
317 bool jInNonIndexed =
false;
320 if (posJ1 !=
nullptr && posJ2 !=
nullptr) {
321 for (
size_t g = 0; g < nEqGroups; g++) {
324 const set<pairss>& orig1orig2 = group.getHessianNonIndexedNonIndexedIndexes();
325 if (orig1orig2.find(orig) != orig1orig2.end()) {
326 jInNonIndexed =
true;
328 loopInfo.equationGroups[g].nonIndexedNonIndexedEvals.insert(orig);
329 loopInfo.equationGroups[g].evalHessSparsity[posJ1->tape].insert(posJ2->tape);
335 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
343 if (_funNoLoops !=
nullptr && posJ1 !=
nullptr) {
345 for (
size_t g = 0; g < nEqGroups; g++) {
348 const set<size_t>& hessRow = group.getHessianSparsity()[posJ1->tape];
349 set<size_t>::const_iterator itz = hessRow.lower_bound(nIndexed + nNonIndexed);
352 for (; itz != hessRow.end(); ++itz) {
354 size_t k = temporaryIndependents[tapeJ - nIndexed - nNonIndexed].original;
357 const set<size_t>& gJacRow = _funNoLoops->getJacobianSparsity()[nonIndexdedEqSize + k];
358 if (gJacRow.find(j2) != gJacRow.end()) {
359 noLoopEvalJacSparsity[nonIndexdedEqSize + k].insert(j2);
361 if (!jInNonIndexed) {
362 jInNonIndexed =
true;
363 CPPADCG_ASSERT_KNOWN(loopInfo.nonIndexedNonIndexedPosition.find(orig) == loopInfo.nonIndexedNonIndexedPosition.end(),
364 "Repeated hessian elements requested");
365 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
368 size_t tapeK = loop->getTempIndepIndexes(k)->tape;
369 loopInfo.equationGroups[g].nonIndexedTempEvals[orig].insert(k);
370 loopInfo.equationGroups[g].evalHessSparsity[posJ1->tape].insert(tapeK);
380 if (_funNoLoops !=
nullptr) {
381 const std::vector<set<size_t> >& gJac = _funNoLoops->getJacobianSparsity();
382 size_t nk = _funNoLoops->getTemporaryDependentCount();
383 size_t nOrigEq = _funNoLoops->getTapeDependentCount() - nk;
385 const std::vector<set<size_t> >& dzdxx = _funNoLoops->getHessianTempEqsSparsity();
387 std::vector<std::set<size_t> > usedTapeJ2(nEqGroups);
389 for (
size_t k1 = 0; k1 < nk; k1++) {
390 if (gJac[nOrigEq + k1].find(j1) == gJac[nOrigEq + k1].end()) {
394 const LoopPosition* posK1 = loop->getTempIndepIndexes(k1);
395 if (posK1 ==
nullptr) {
405 for (
size_t g = 0; g < nEqGroups; g++) {
407 const std::vector<set<size_t> >& groupHess = group.getHessianSparsity();
410 const map<size_t, set<size_t> >& tapeJ22Iter = group.getHessianTempIndexedTapeIndexes(k1, j2);
411 for (
const auto& ittj22iter : tapeJ22Iter) {
412 size_t tapeJ2 = ittj22iter.first;
413 const set<size_t>& iterations = ittj22iter.second;
415 bool used = usedTapeJ2[g].find(tapeJ2) != usedTapeJ2[g].end();
418 for (
size_t iteration : iterations) {
419 std::vector<HessianElement>* positions =
nullptr;
421 bool flip = flipIndices2(groupHess, posK1->tape, tapeJ2);
424 pairss pos(tapeJ2, j1);
425 positions = &groupHessInfo.indexedTempPositions[pos];
427 groupHessInfo.evalHessSparsity[tapeJ2].insert(posK1->tape);
430 pairss pos(j1, tapeJ2);
431 positions = &groupHessInfo.tempIndexedPositions[pos];
433 groupHessInfo.evalHessSparsity[posK1->tape].insert(tapeJ2);
436 if (positions !=
nullptr) {
437 positions->resize(nIter);
439 (*positions)[iteration].location = e;
440 (*positions)[iteration].row = j1;
441 (*positions)[iteration].count++;
442 usedTapeJ2[g].insert(tapeJ2);
447 set<size_t>& evals = groupHessInfo.indexedTempEvals[pairss(tapeJ2, j1)];
459 if (posJ2 !=
nullptr) {
460 const set<size_t>& hessRow = group.getHessianSparsity()[posK1->tape];
462 if (hessRow.find(j2) != hessRow.end()) {
463 if (!jInNonIndexed) {
464 jInNonIndexed =
true;
465 CPPADCG_ASSERT_KNOWN(loopInfo.nonIndexedNonIndexedPosition.find(orig) == loopInfo.nonIndexedNonIndexedPosition.end(),
466 "Repeated hessian elements requested");
467 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
470 groupHessInfo.tempNonIndexedEvals[orig].insert(k1);
471 groupHessInfo.evalHessSparsity[posK1->tape].insert(posJ2->tape);
482 const set<size_t>& hessRow = group.getHessianSparsity()[posK1->tape];
483 set<size_t>::const_iterator itTapeJ2 = hessRow.lower_bound(nIndexed + nNonIndexed);
484 for (; itTapeJ2 != hessRow.end(); ++itTapeJ2) {
485 size_t tapeK2 = *itTapeJ2;
486 size_t k2 = loop->getTemporaryIndependents()[tapeK2 - nIndexed - nNonIndexed].original;
488 const set<size_t>& jacZk2Row = gJac[nOrigEq + k2];
489 if (jacZk2Row.find(j2) != jacZk2Row.end()) {
491 if (!jInNonIndexed) {
492 jInNonIndexed =
true;
493 CPPADCG_ASSERT_KNOWN(loopInfo.nonIndexedNonIndexedPosition.find(orig) == loopInfo.nonIndexedNonIndexedPosition.end(),
494 "Repeated hessian elements requested");
495 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
498 groupHessInfo.tempTempEvals[orig][k1].insert(k2);
499 groupHessInfo.evalHessSparsity[posK1->tape].insert(tapeK2);
501 noLoopEvalJacSparsity[nOrigEq + k2].insert(j2);
507 noLoopEvalJacSparsity[nOrigEq + k1].insert(j1);
514 if (dzdxx[j1].find(j2) != dzdxx[j1].end()) {
516 for (
size_t i = 0; i < loopJac.size(); i++) {
517 const set<size_t>& fJacRow = loopJac[i];
519 if (fJacRow.find(posK1->tape) != fJacRow.end()) {
520 if (!jInNonIndexed) {
521 CPPADCG_ASSERT_KNOWN(loopInfo.nonIndexedNonIndexedPosition.find(orig) == loopInfo.nonIndexedNonIndexedPosition.end(),
522 "Repeated hessian elements requested");
524 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
525 jInNonIndexed =
true;
528 loopInfo.nonLoopNonIndexedNonIndexed[orig].insert(k1);
529 loopInfo.evalJacSparsity[i].insert(posK1->tape);
530 loopInfo.noLoopEvalHessTempsSparsity[j1].insert(j2);
542 inline void addContribution(std::vector<std::pair<
CG<Base>,
IndexPattern*> >& indexedLoopResults,
545 if (!val.first.isIdenticalZero()) {
546 if (indexedLoopResults.size() <= hessLE) {
547 if (indexedLoopResults.capacity() <= hessLE) {
548 indexedLoopResults.reserve(3 * hessLE / 2 + 1);
550 indexedLoopResults.resize(hessLE + 1);
552 indexedLoopResults[hessLE++] = val;
558 std::vector<CGBase>& x,
559 std::vector<CGBase>& w,
560 const std::vector<size_t>& lowerHessRows,
561 const std::vector<size_t>& lowerHessCols,
562 const std::vector<size_t>& lowerHessOrder,
563 const std::map<size_t, size_t>& duplicates) {
569 size_t nonIndexdedEqSize = _funNoLoops !=
nullptr ? _funNoLoops->getOrigDependentIndexes().size() : 0;
571 size_t maxLoc = _hessSparsity.rows.size();
572 std::vector<CGBase> hess(maxLoc);
574 std::vector<set<size_t> > noLoopEvalJacSparsity;
575 std::vector<set<size_t> > noLoopEvalHessSparsity;
576 std::vector<map<size_t, set<size_t> > > noLoopEvalHessLocations;
584 analyseSparseHessianWithLoops(lowerHessRows, lowerHessCols, lowerHessOrder,
585 noLoopEvalJacSparsity, noLoopEvalHessSparsity,
586 noLoopEvalHessLocations, loopHessInfo,
true);
597 std::vector<CGBase> tmpsAlias;
598 if (_funNoLoops !=
nullptr) {
601 tmpsAlias.resize(fun.Range() - nonIndexdedEqSize);
602 for (
size_t k = 0; k < tmpsAlias.size(); k++) {
604 tmpsAlias[k] =
CG<Base>(*handler.makeNode(CGOpCode::Alias));
612 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
619 info.loopStart = handler.makeLoopStartNode(*iterationIndexDcl, lModel.
getIterationCount());
621 info.iterationIndexOp = handler.makeIndexNode(*info.loopStart);
622 set<IndexOperationNode<Base>*> indexesOps;
623 indexesOps.insert(info.iterationIndexOp);
628 std::vector<CGBase> indexedIndeps = createIndexedIndependents(handler, lModel, *info.iterationIndexOp);
629 info.x = createLoopIndependentVector(handler, lModel, indexedIndeps, x, tmpsAlias);
631 info.w = createLoopDependentVector(handler, lModel, *info.iterationIndexOp);
640 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
645 _cache <<
"model (Jacobian + Hessian, loop " << lModel.
getLoopId() <<
")";
646 std::string jobName = _cache.str();
648 startingJob(
"'" + jobName +
"'", JobTimer::GRAPH);
660 map<size_t, map<size_t, CGBase> > dzDx;
662 if (_funNoLoops !=
nullptr) {
664 std::vector<CGBase> yNL(fun.Range());
669 startingJob(
"'model (Jacobian + Hessian, temporaries)'", JobTimer::GRAPH);
671 dzDx = _funNoLoops->calculateJacobianHessianUsedByLoops(handler,
672 loopHessInfo, x, yNL,
673 noLoopEvalJacSparsity,
678 for (
size_t i = 0; i < tmpsAlias.size(); i++)
679 tmpsAlias[i].getOperationNode()->getArguments().push_back(asArgument(yNL[nonIndexdedEqSize + i]));
681 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
690 _funNoLoops->calculateHessian4OrignalEquations(x, w,
691 noLoopEvalHessSparsity, noLoopEvalHessLocations,
698 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
704 size_t hessElSize = info.nonIndexedNonIndexedPosition.size();
705 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
707 hessElSize += infog.indexedIndexedPositions.size() +
708 infog.indexedTempPositions.size() +
709 infog.nonIndexedIndexedPositions.size();
715 std::vector<pair<CGBase, IndexPattern*> > indexedLoopResults(hessElSize);
721 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
728 for (
const auto& it : infog.indexedIndexedPositions) {
729 size_t tapeJ1 = it.first.first;
730 size_t tapeJ2 = it.first.second;
731 const std::vector<HessianElement>& positions = it.second;
733 addContribution(indexedLoopResults, hessLE,
734 createHessianContribution(handler, positions, infog.
hess[tapeJ1].at(tapeJ2),
735 *info.iterationIndexOp, info.ifElses));
742 for (
const auto& it : infog.indexedNonIndexedPositions) {
743 size_t tapeJ1 = it.first.first;
744 size_t tapeJ2 = it.first.second;
745 const std::vector<HessianElement>& positions = it.second;
747 addContribution(indexedLoopResults, hessLE,
748 createHessianContribution(handler, positions, infog.
hess[tapeJ1].at(tapeJ2),
749 *info.iterationIndexOp, info.ifElses));
755 if (!infog.indexedTempPositions.empty()) {
756 for (
const auto& itEval : infog.indexedTempEvals) {
757 size_t tapeJ1 = itEval.first.first;
758 size_t j2 = itEval.first.second;
759 const set<size_t>& ks = itEval.second;
761 const auto itPos = infog.indexedTempPositions.find(itEval.first);
762 if (itPos != infog.indexedTempPositions.end()) {
763 const std::vector<HessianElement>& positions = itPos->second;
766 for (
size_t k : ks) {
768 hessVal += infog.
hess[tapeJ1].at(tapeK) * dzDx[k][j2];
771 addContribution(indexedLoopResults, hessLE,
772 createHessianContribution(handler, positions, hessVal,
773 *info.iterationIndexOp, info.ifElses));
781 for (
const auto& it : infog.nonIndexedIndexedPositions) {
782 size_t tapeJ1 = it.first.first;
783 size_t tapeJ2 = it.first.second;
784 const std::vector<HessianElement>& positions = it.second;
786 addContribution(indexedLoopResults, hessLE,
787 createHessianContribution(handler, positions, infog.
hess[tapeJ1].at(tapeJ2),
788 *info.iterationIndexOp, info.ifElses));
799 if (!infog.tempIndexedPositions.empty()) {
800 for (
const auto& itEval : infog.indexedTempEvals) {
801 size_t tapeJ2 = itEval.first.first;
802 size_t j1 = itEval.first.second;
803 const set<size_t>& ks = itEval.second;
805 const auto itPos = infog.tempIndexedPositions.find(pairss(j1, tapeJ2));
806 if (itPos != infog.tempIndexedPositions.end()) {
807 const std::vector<HessianElement>& positions = itPos->second;
809 for (
size_t k : ks) {
811 hessVal += infog.
hess[tapeK].at(tapeJ2) * dzDx[k][j1];
814 addContribution(indexedLoopResults, hessLE,
815 createHessianContribution(handler, positions, hessVal,
816 *info.iterationIndexOp, info.ifElses));
826 for (
const auto& orig2PosIt : info.nonIndexedNonIndexedPosition) {
827 const pairss& orig = orig2PosIt.first;
828 size_t e = orig2PosIt.second;
830 size_t j1 = orig.first;
831 size_t j2 = orig.second;
837 handler.manageLoopDependentIndexPattern(pattern);
847 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
850 CGBase gHessVal = Base(0);
853 if (infog.nonIndexedNonIndexedEvals.find(orig) != infog.nonIndexedNonIndexedEvals.end()) {
854 gHessVal = infog.
hess[posJ1->tape].at(posJ2->tape);
860 const auto itNT = infog.nonIndexedTempEvals.find(orig);
861 if (itNT != infog.nonIndexedTempEvals.end()) {
862 const set<size_t>& ks = itNT->second;
864 for (
size_t k : ks) {
866 gHessVal += infog.
hess[posJ1->tape].at(tapeK) * dzDx[k][j2];
876 const auto itTN = infog.tempNonIndexedEvals.find(orig);
877 if (itTN != infog.tempNonIndexedEvals.end()) {
878 const set<size_t>& ks = itTN->second;
880 for (
size_t k1 : ks) {
882 gHessVal += infog.
hess[tapeK].at(posJ2->tape) * dzDx[k1][j1];
889 const auto itTT = infog.tempTempEvals.find(orig);
890 if (itTT != infog.tempTempEvals.end()) {
891 const map<size_t, set<size_t> >& k1k2 = itTT->second;
895 for (
const auto& itzz : k1k2) {
896 size_t k1 = itzz.first;
897 const set<size_t>& k2s = itzz.second;
901 for (
size_t k2 : k2s) {
904 tmp += infog.
hess[tapeK1].at(tapeK2) * dzDx[k2][j2];
907 sum += tmp * dzDx[k1][j1];
915 nIterations, gHessVal,
916 *info.iterationIndexOp, info.ifElses);
917 addContribution(indexedLoopResults, hessLE, make_pair(v, (
IndexPattern*)
nullptr));
927 const auto itTT2 = info.nonLoopNonIndexedNonIndexed.find(orig);
928 if (itTT2 != info.nonLoopNonIndexedNonIndexed.end()) {
929 hessVal += info.dzDxx.at(j1).at(j2);
933 addContribution(indexedLoopResults, hessLE, make_pair(hessVal, (
IndexPattern*) pattern));
936 indexedLoopResults.resize(hessLE);
941 size_t assignOrAdd = 1;
942 set<IndexOperationNode<Base>*> indexesOps;
943 indexesOps.insert(info.iterationIndexOp);
944 info.loopEnd = createLoopEnd(handler, *info.loopStart, indexedLoopResults, indexesOps, assignOrAdd);
946 for (
size_t e : lowerHessOrder) {
948 if (hess[e].isIdenticalZero()) {
949 hess[e] =
CG<Base>(*handler.makeNode(CGOpCode::DependentMultiAssign, *info.loopEnd));
951 }
else if (hess[e].getOperationNode() !=
nullptr && hess[e].getOperationNode()->getOperationType() == CGOpCode::DependentMultiAssign) {
952 hess[e].getOperationNode()->getArguments().push_back(*info.loopEnd);
955 hess[e] = handler.createCG(*handler.makeNode(CGOpCode::DependentMultiAssign,{asArgument(hess[e]), *info.loopEnd}));
960 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
961 info.equationGroups[g].hess.clear();
968 moveNonIndexedOutsideLoop(handler, *info.loopStart, *info.loopEnd);
975 for (
const auto& it2 : duplicates) {
976 if (hess[it2.second].isVariable())
977 hess[it2.first] =
CG<Base>(*handler.makeNode(CGOpCode::Alias, asArgument(hess[it2.second])));
979 hess[it2.first] = hess[it2.second].getValue();
989 const std::vector<HessianElement>& positions,
995 if (ddfdxdx.isIdenticalZero()) {
1000 map<size_t, map<size_t, size_t> > locations;
1001 for (
size_t iter = 0; iter < positions.size(); iter++) {
1002 size_t c = positions[iter].count;
1004 locations[c][iter] = positions[iter].location;
1008 map<size_t, CG<Base> > results;
1011 for (
const auto& countIt : locations) {
1012 size_t count = countIt.first;
1015 for (
size_t c = 1; c < count; c++)
1018 results[count] = val;
1021 if (results.size() == 1 && locations.begin()->second.size() == positions.size()) {
1026 handler.manageLoopDependentIndexPattern(pattern);
1028 return make_pair(results.begin()->second, pattern);
1036 map<size_t, IfBranchData<Base> > branches;
1039 for (
const auto& countIt : locations) {
1041 size_t count = countIt.first;
1043 branches[count] = branch;
1046 CG<Base> v = createConditionalContribution(handler,
1048 positions.size() - 1,
1061 template<
class Base>
1064 const std::set<size_t>& iterations,
1069 using namespace std;
1071 if (ddfdxdx.isIdenticalZero()) {
1075 CPPADCG_ASSERT_UNKNOWN(pattern.getLinearSlopeDy() == 0);
1077 if (iterations.size() == nIterations) {
1088 return createConditionalContribution(handler, pattern,
1089 iterations, nIterations - 1,
1090 ddfdxdx, iterationIndexOp,
1095 template<
class Base>
1098 const std::vector<std::vector<
CG<Base> > >& vw,
1100 const std::vector<std::set<size_t> >& jacSparsity,
1101 const std::vector<std::set<size_t> >& jacEvalSparsity,
1102 std::vector<std::map<
size_t,
CG<Base> > >& jac,
1103 const std::vector<std::set<size_t> >& hesSparsity,
1104 const std::vector<std::set<size_t> >& hesEvalSparsity,
1105 std::vector<std::map<
size_t, std::map<
size_t,
CG<Base> > > >& vhess,
1106 bool individualColoring) {
1107 using namespace std;
1111 size_t m = fun.Range();
1112 size_t n = fun.Domain();
1115 vhess.resize(vw.size());
1117 if (!individualColoring) {
1123 std::vector<size_t> jacRow, jacCol;
1124 generateSparsityIndexes(jacEvalSparsity, jacRow, jacCol);
1127 std::vector<CGB> jacFlat(jacRow.size());
1132 std::vector<size_t> hesRow, hesCol;
1133 generateSparsityIndexes(hesEvalSparsity, hesRow, hesCol);
1135 std::vector<std::vector<CGB> > vhessFlat(vw.size());
1136 for (
size_t l = 0; l < vw.size(); l++) {
1137 vhessFlat[l].resize(hesRow.size());
1140 std::vector<CG<Base> > xl;
1141 if (x.size() == 0) {
1149 sparseForJacHessian(fun, xl, vw,
1152 jacRow, jacCol, jacFlat,
1154 hesRow, hesCol, vhessFlat,
1158 for (
size_t el = 0; el < jacRow.size(); el++) {
1159 size_t i = jacRow[el];
1160 size_t j = jacCol[el];
1162 jac[i][j] = jacFlat[el];
1166 for (
size_t l = 0; l < vw.size(); l++) {
1167 std::vector<CGB>& hessFlat = vhessFlat[l];
1168 map<size_t, map<size_t, CGB> >& hess = vhess[l];
1170 for (
size_t el = 0; el < hesRow.size(); el++) {
1171 size_t j1 = hesRow[el];
1172 size_t j2 = hesCol[el];
1173 hess[j1][j2] = hessFlat[el];
1183 std::vector<set<size_t> > jacEvalSparsityT(n);
1184 addTransMatrixSparsity(jacEvalSparsity, jacEvalSparsityT);
1186 std::vector<CGB> tx1v(n);
1188 y = fun.Forward(0, x);
1190 for (
size_t j1 = 0; j1 < n; j1++) {
1191 if (jacEvalSparsityT[j1].empty() && hesEvalSparsity[j1].empty()) {
1196 std::vector<CGB> dy = fun.Forward(1, tx1v);
1197 CPPADCG_ASSERT_UNKNOWN(dy.size() == m);
1201 const set<size_t>& column = jacEvalSparsityT[j1];
1202 for (
size_t i : column) {
1206 const set<size_t>& hesRow = hesEvalSparsity[j1];
1208 if (!hesRow.empty()) {
1210 for (
size_t l = 0; l < vw.size(); l++) {
1212 std::vector<CGB> px = fun.Reverse(2, vw[l]);
1213 CPPADCG_ASSERT_UNKNOWN(px.size() == 2 * n);
1216 map<size_t, CGB>& hessRow = vhess[l][j1];
1217 for (
size_t j2 : hesRow) {
1218 hessRow[j2] = px[j2 * 2 + 1];
void evalLoopModelJacobianHessian(bool individualColoring)
std::map< size_t, std::map< size_t, CG< Base > > > hess
size_t index
iteration group index/ID
const std::vector< std::set< pairss > > & getHessianIndexedIndexedTapeIndexes(size_t origJ1, size_t origJ2) const
std::vector< std::map< size_t, CG< Base > > > dyiDzk
bool isContainsAtomics() const
static IndexPattern * detect(const VectorSizeT &x2y)
const LoopPosition * getTempIndepIndexes(size_t k) const
virtual std::vector< CGBase > prepareSparseHessianWithLoops(CodeHandler< Base > &handler, std::vector< CGBase > &indVars, std::vector< CGBase > &w, const std::vector< size_t > &lowerHessRows, const std::vector< size_t > &lowerHessCols, const std::vector< size_t > &lowerHessOrder, const std::map< size_t, size_t > &duplicates)
void analyseSparseHessianWithLoops(const std::vector< size_t > &lowerHessRows, const std::vector< size_t > &lowerHessCols, const std::vector< size_t > &lowerHessOrder, SparsitySetType &noLoopEvalJacSparsity, SparsitySetType &noLoopEvalHessSparsity, std::vector< std::map< size_t, std::set< size_t > > > &noLoopEvalHessLocations, std::map< LoopModel< Base > *, loops::HessianWithLoopsInfo< Base > > &loopHessInfo, bool useSymmetry)
const std::vector< LoopPosition > & getNonIndexedIndepIndexes() const
const size_t getIterationCount() const
const std::vector< IterEquationGroup< Base > > & getEquationsGroups() const
void setZeroDependents(bool zeroDependents)
std::set< size_t > iterations
iterations which only have these equations defined