1 #ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_HESS_INCLUDED 2 #define CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_HESS_INCLUDED 31 location((std::numeric_limits<size_t>::max)()),
32 row((std::numeric_limits<size_t>::max)()),
40 const std::vector<HessianElement>& positions,
53 const std::vector<size_t>& lowerHessCols,
54 const std::vector<size_t>& lowerHessOrder,
55 std::vector<std::set<size_t> >& noLoopEvalJacSparsity,
56 std::vector<std::set<size_t> >& noLoopEvalHessSparsity,
57 std::vector<std::map<
size_t, std::set<size_t> > >& noLoopEvalHessLocations,
63 size_t nonIndexdedEqSize = _funNoLoops !=
nullptr ? _funNoLoops->getOrigDependentIndexes().size() : 0;
69 l->evalJacobianSparsity();
70 l->evalHessianSparsity();
73 if (_funNoLoops !=
nullptr) {
74 _funNoLoops->evalJacobianSparsity();
75 _funNoLoops->evalHessianSparsity();
78 size_t m = _fun.Range();
79 size_t n = _fun.Domain();
81 size_t nnz = lowerHessRows.size();
83 noLoopEvalJacSparsity.resize(_funNoLoops !=
nullptr ? m : 0);
84 noLoopEvalHessSparsity.resize(_funNoLoops !=
nullptr ? n : 0);
85 noLoopEvalHessLocations.resize(noLoopEvalHessSparsity.size());
93 loopHessInfol.noLoopEvalHessTempsSparsity.resize(_funNoLoops !=
nullptr ? n : 0);
96 auto flipIndices = [&](
const std::vector<set<size_t> >& groupHess,
99 return useSymmetry && tape1 > tape2 && groupHess[tape2].find(tape1) != groupHess[tape2].end();
102 auto flipIndices2 = [&](
const std::vector<set<size_t> >& groupHess,
105 return useSymmetry && groupHess[tape2].find(tape1) != groupHess[tape2].end();
113 for (
size_t eh = 0; eh < nnz; eh++) {
114 size_t j1 = lowerHessRows[eh];
115 size_t j2 = lowerHessCols[eh];
116 size_t e = lowerHessOrder[eh];
118 if (_funNoLoops !=
nullptr) {
120 const std::vector<std::set<size_t> >& dydxx = _funNoLoops->getHessianOrigEqsSparsity();
121 if (!dydxx.empty()) {
122 if (dydxx[j1].find(j2) != dydxx[j1].end()) {
126 noLoopEvalHessSparsity[j1].insert(j2);
127 noLoopEvalHessLocations[j1][j2].insert(e);
133 size_t nIter = loop->getIterationCount();
135 const std::vector<IterEquationGroup<Base> >& eqGroups = loop->getEquationsGroups();
136 const std::vector<set<size_t> >& loopJac = loop->getJacobianSparsity();
139 const std::vector<std::vector<LoopPosition> >& indexedIndepIndexes = loop->getIndexedIndepIndexes();
140 const std::vector<LoopPosition>& nonIndexedIndepIndexes = loop->getNonIndexedIndepIndexes();
141 const std::vector<LoopPosition>& temporaryIndependents = loop->getTemporaryIndependents();
143 size_t nIndexed = indexedIndepIndexes.size();
144 size_t nNonIndexed = nonIndexedIndepIndexes.size();
146 const LoopPosition* posJ1 = loop->getNonIndexedIndepIndexes(j1);
147 const LoopPosition* posJ2 = (j1 == j2) ? posJ1 : loop->getNonIndexedIndepIndexes(j2);
149 size_t nEqGroups = loopInfo.equationGroups.size();
151 for (
size_t g = 0; g < nEqGroups; g++) {
153 const std::vector<set<size_t> >& groupHess = group.getHessianSparsity();
161 for (
size_t iteration = 0; iteration < iter2tapeJJ.size(); iteration++) {
162 const set<pairss>& tapePairs = iter2tapeJJ[iteration];
164 for (
const pairss& itPairs : tapePairs) {
165 size_t tape1 = itPairs.first;
166 size_t tape2 = itPairs.second;
169 bool flip = flipIndices(groupHess, tape1, tape2);
171 tape = pairss(tape2, tape1);
176 std::vector<HessianElement>& positions = loopInfo.equationGroups[g].indexedIndexedPositions[tape];
177 positions.resize(nIter);
179 positions[iteration].location = e;
180 positions[iteration].row = j1;
181 positions[iteration].count++;
183 loopInfo.equationGroups[g].evalHessSparsity[tape.first].insert(tape.second);
193 if (posJ2 !=
nullptr) {
195 const std::vector<set<size_t> >& iter2tapeJ1OrigJ2 = group.getHessianIndexedNonIndexedTapeIndexes(j1, j2);
196 for (
size_t iteration = 0; iteration < iter2tapeJ1OrigJ2.size(); iteration++) {
197 const set<size_t>& tapeJ1s = iter2tapeJ1OrigJ2[iteration];
199 for (
size_t tapeJ1 : tapeJ1s) {
201 bool flip = flipIndices2(groupHess, tapeJ1, posJ2->tape);
203 std::vector<HessianElement>* positions;
205 positions = &loopInfo.equationGroups[g].nonIndexedIndexedPositions[pairss(posJ2->tape, tapeJ1)];
206 loopInfo.equationGroups[g].evalHessSparsity[posJ2->tape].insert(tapeJ1);
208 positions = &loopInfo.equationGroups[g].indexedNonIndexedPositions[pairss(tapeJ1, posJ2->tape)];
209 loopInfo.equationGroups[g].evalHessSparsity[tapeJ1].insert(posJ2->tape);
212 positions->resize(nIter);
213 (*positions)[iteration].location = e;
214 (*positions)[iteration].row = j1;
215 (*positions)[iteration].count++;
227 if (_funNoLoops !=
nullptr) {
228 map<size_t, set<size_t> > iter2tapeJ1 = loop->getIndexedTapeIndexes(j1);
229 for (
const auto& itIter : iter2tapeJ1) {
230 size_t iteration = itIter.first;
231 const set<size_t>& tapeJ1s = itIter.second;
232 const set<const IterEquationGroup<Base>*>& groups = loop->getIterationEquationsGroup()[iteration];
234 for (
size_t tapeJ1 : tapeJ1s) {
237 size_t g = group.
index;
239 const std::vector<set<size_t> >& groupHess = group.getHessianSparsity();
241 auto itz = groupHess[tapeJ1].lower_bound(nIndexed + nNonIndexed);
243 pairss pos(tapeJ1, j2);
247 for (; itz != groupHess[tapeJ1].end(); ++itz) {
249 size_t k = temporaryIndependents[tapeJ - nIndexed - nNonIndexed].original;
254 const set<size_t>& sparsity = _funNoLoops->getJacobianSparsity()[nonIndexdedEqSize + k];
255 if (sparsity.find(j2) != sparsity.end()) {
256 noLoopEvalJacSparsity[nonIndexdedEqSize + k].insert(j2);
258 size_t tapeK = loop->getTempIndepIndexes(k)->tape;
262 set<size_t>& evals = groupInfo.indexedTempEvals[pos];
265 groupInfo.evalHessSparsity[tapeJ1].insert(tapeK);
271 std::vector<HessianElement>& positions = groupInfo.indexedTempPositions[pos];
272 positions.resize(nIter);
274 positions[iteration].location = e;
275 positions[iteration].row = j1;
276 positions[iteration].count++;
291 if (posJ1 !=
nullptr) {
293 for (
size_t g = 0; g < nEqGroups; g++) {
296 const std::vector<set<size_t> >& iter2TapeJ2 = group.getHessianNonIndexedIndexedTapeIndexes(j1, j2);
297 for (
size_t iteration = 0; iteration < iter2TapeJ2.size(); iteration++) {
298 const set<size_t>& tapeJ2s = iter2TapeJ2[iteration];
300 for (
size_t tapeJ2 : tapeJ2s) {
301 std::vector<HessianElement>& positions = loopInfo.equationGroups[g].nonIndexedIndexedPositions[pairss(posJ1->tape, tapeJ2)];
302 positions.resize(nIter);
303 positions[iteration].location = e;
304 positions[iteration].row = j1;
305 positions[iteration].count++;
307 loopInfo.equationGroups[g].evalHessSparsity[posJ1->tape].insert(tapeJ2);
318 bool jInNonIndexed =
false;
321 if (posJ1 !=
nullptr && posJ2 !=
nullptr) {
322 for (
size_t g = 0; g < nEqGroups; g++) {
325 const set<pairss>& orig1orig2 = group.getHessianNonIndexedNonIndexedIndexes();
326 if (orig1orig2.find(orig) != orig1orig2.end()) {
327 jInNonIndexed =
true;
329 loopInfo.equationGroups[g].nonIndexedNonIndexedEvals.insert(orig);
330 loopInfo.equationGroups[g].evalHessSparsity[posJ1->tape].insert(posJ2->tape);
336 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
344 if (_funNoLoops !=
nullptr && posJ1 !=
nullptr) {
346 for (
size_t g = 0; g < nEqGroups; g++) {
349 const set<size_t>& hessRow = group.getHessianSparsity()[posJ1->tape];
350 auto itz = hessRow.lower_bound(nIndexed + nNonIndexed);
353 for (; itz != hessRow.end(); ++itz) {
355 size_t k = temporaryIndependents[tapeJ - nIndexed - nNonIndexed].original;
358 const set<size_t>& gJacRow = _funNoLoops->getJacobianSparsity()[nonIndexdedEqSize + k];
359 if (gJacRow.find(j2) != gJacRow.end()) {
360 noLoopEvalJacSparsity[nonIndexdedEqSize + k].insert(j2);
362 if (!jInNonIndexed) {
363 jInNonIndexed =
true;
364 CPPADCG_ASSERT_KNOWN(loopInfo.nonIndexedNonIndexedPosition.find(orig) == loopInfo.nonIndexedNonIndexedPosition.end(),
365 "Repeated hessian elements requested")
366 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
369 size_t tapeK = loop->getTempIndepIndexes(k)->tape;
370 loopInfo.equationGroups[g].nonIndexedTempEvals[orig].insert(k);
371 loopInfo.equationGroups[g].evalHessSparsity[posJ1->tape].insert(tapeK);
381 if (_funNoLoops !=
nullptr) {
382 const std::vector<set<size_t> >& gJac = _funNoLoops->getJacobianSparsity();
383 size_t nk = _funNoLoops->getTemporaryDependentCount();
384 size_t nOrigEq = _funNoLoops->getTapeDependentCount() - nk;
386 const std::vector<set<size_t> >& dzdxx = _funNoLoops->getHessianTempEqsSparsity();
388 std::vector<std::set<size_t> > usedTapeJ2(nEqGroups);
390 for (
size_t k1 = 0; k1 < nk; k1++) {
391 if (gJac[nOrigEq + k1].find(j1) == gJac[nOrigEq + k1].end()) {
395 const LoopPosition* posK1 = loop->getTempIndepIndexes(k1);
396 if (posK1 ==
nullptr) {
406 for (
size_t g = 0; g < nEqGroups; g++) {
408 const std::vector<set<size_t> >& groupHess = group.getHessianSparsity();
411 const map<size_t, set<size_t> >& tapeJ22Iter = group.getHessianTempIndexedTapeIndexes(k1, j2);
412 for (
const auto& ittj22iter : tapeJ22Iter) {
413 size_t tapeJ2 = ittj22iter.first;
414 const set<size_t>& iterations = ittj22iter.second;
416 bool used = usedTapeJ2[g].find(tapeJ2) != usedTapeJ2[g].end();
419 for (
size_t iteration : iterations) {
420 std::vector<HessianElement>* positions =
nullptr;
422 bool flip = flipIndices2(groupHess, posK1->tape, tapeJ2);
425 pairss pos(tapeJ2, j1);
426 positions = &groupHessInfo.indexedTempPositions[pos];
428 groupHessInfo.evalHessSparsity[tapeJ2].insert(posK1->tape);
431 pairss pos(j1, tapeJ2);
432 positions = &groupHessInfo.tempIndexedPositions[pos];
434 groupHessInfo.evalHessSparsity[posK1->tape].insert(tapeJ2);
437 if (positions !=
nullptr) {
438 positions->resize(nIter);
440 (*positions)[iteration].location = e;
441 (*positions)[iteration].row = j1;
442 (*positions)[iteration].count++;
443 usedTapeJ2[g].insert(tapeJ2);
448 set<size_t>& evals = groupHessInfo.indexedTempEvals[pairss(tapeJ2, j1)];
460 if (posJ2 !=
nullptr) {
461 const set<size_t>& hessRow = group.getHessianSparsity()[posK1->tape];
463 if (hessRow.find(j2) != hessRow.end()) {
464 if (!jInNonIndexed) {
465 jInNonIndexed =
true;
466 CPPADCG_ASSERT_KNOWN(loopInfo.nonIndexedNonIndexedPosition.find(orig) == loopInfo.nonIndexedNonIndexedPosition.end(),
467 "Repeated hessian elements requested")
468 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
471 groupHessInfo.tempNonIndexedEvals[orig].insert(k1);
472 groupHessInfo.evalHessSparsity[posK1->tape].insert(posJ2->tape);
483 const set<size_t>& hessRow = group.getHessianSparsity()[posK1->tape];
484 auto itTapeJ2 = hessRow.lower_bound(nIndexed + nNonIndexed);
485 for (; itTapeJ2 != hessRow.end(); ++itTapeJ2) {
486 size_t tapeK2 = *itTapeJ2;
487 size_t k2 = loop->getTemporaryIndependents()[tapeK2 - nIndexed - nNonIndexed].original;
489 const set<size_t>& jacZk2Row = gJac[nOrigEq + k2];
490 if (jacZk2Row.find(j2) != jacZk2Row.end()) {
492 if (!jInNonIndexed) {
493 jInNonIndexed =
true;
494 CPPADCG_ASSERT_KNOWN(loopInfo.nonIndexedNonIndexedPosition.find(orig) == loopInfo.nonIndexedNonIndexedPosition.end(),
495 "Repeated hessian elements requested")
496 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
499 groupHessInfo.tempTempEvals[orig][k1].insert(k2);
500 groupHessInfo.evalHessSparsity[posK1->tape].insert(tapeK2);
502 noLoopEvalJacSparsity[nOrigEq + k2].insert(j2);
508 noLoopEvalJacSparsity[nOrigEq + k1].insert(j1);
515 if (dzdxx[j1].find(j2) != dzdxx[j1].end()) {
517 for (
size_t i = 0; i < loopJac.size(); i++) {
518 const set<size_t>& fJacRow = loopJac[i];
520 if (fJacRow.find(posK1->tape) != fJacRow.end()) {
521 if (!jInNonIndexed) {
522 CPPADCG_ASSERT_KNOWN(loopInfo.nonIndexedNonIndexedPosition.find(orig) == loopInfo.nonIndexedNonIndexedPosition.end(),
523 "Repeated hessian elements requested")
525 loopInfo.nonIndexedNonIndexedPosition[orig] = e;
526 jInNonIndexed =
true;
529 loopInfo.nonLoopNonIndexedNonIndexed[orig].insert(k1);
530 loopInfo.evalJacSparsity[i].insert(posK1->tape);
531 loopInfo.noLoopEvalHessTempsSparsity[j1].insert(j2);
543 inline void addContribution(std::vector<std::pair<
CG<Base>,
IndexPattern*> >& indexedLoopResults,
546 if (!val.first.isIdenticalZero()) {
547 if (indexedLoopResults.size() <= hessLE) {
548 if (indexedLoopResults.capacity() <= hessLE) {
549 indexedLoopResults.reserve(3 * hessLE / 2 + 1);
551 indexedLoopResults.resize(hessLE + 1);
553 indexedLoopResults[hessLE++] = val;
559 std::vector<CGBase>& x,
560 std::vector<CGBase>& w,
561 const std::vector<size_t>& lowerHessRows,
562 const std::vector<size_t>& lowerHessCols,
563 const std::vector<size_t>& lowerHessOrder,
564 const std::map<size_t, size_t>& duplicates) {
570 size_t nonIndexdedEqSize = _funNoLoops !=
nullptr ? _funNoLoops->getOrigDependentIndexes().size() : 0;
572 size_t maxLoc = _hessSparsity.rows.size();
573 std::vector<CGBase> hess(maxLoc);
575 std::vector<set<size_t> > noLoopEvalJacSparsity;
576 std::vector<set<size_t> > noLoopEvalHessSparsity;
577 std::vector<map<size_t, set<size_t> > > noLoopEvalHessLocations;
585 analyseSparseHessianWithLoops(lowerHessRows, lowerHessCols, lowerHessOrder,
586 noLoopEvalJacSparsity, noLoopEvalHessSparsity,
587 noLoopEvalHessLocations, loopHessInfo,
true);
598 std::vector<CGBase> tmpsAlias;
599 if (_funNoLoops !=
nullptr) {
602 tmpsAlias.resize(fun.Range() - nonIndexdedEqSize);
603 for (
size_t k = 0; k < tmpsAlias.size(); k++) {
605 tmpsAlias[k] =
CG<Base>(*handler.makeNode(CGOpCode::Alias));
613 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
620 info.loopStart = handler.makeLoopStartNode(*iterationIndexDcl, lModel.
getIterationCount());
622 info.iterationIndexOp = handler.makeIndexNode(*info.loopStart);
623 set<IndexOperationNode<Base>*> indexesOps;
624 indexesOps.insert(info.iterationIndexOp);
629 std::vector<CGBase> indexedIndeps = createIndexedIndependents(handler, lModel, *info.iterationIndexOp);
630 info.x = createLoopIndependentVector(handler, lModel, indexedIndeps, x, tmpsAlias);
632 info.w = createLoopDependentVector(handler, lModel, *info.iterationIndexOp);
641 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
646 _cache <<
"model (Jacobian + Hessian, loop " << lModel.
getLoopId() <<
")";
647 std::string jobName = _cache.str();
649 startingJob(
"'" + jobName +
"'", JobTimer::GRAPH);
661 map<size_t, map<size_t, CGBase> > dzDx;
663 if (_funNoLoops !=
nullptr) {
665 std::vector<CGBase> yNL(fun.Range());
670 startingJob(
"'model (Jacobian + Hessian, temporaries)'", JobTimer::GRAPH);
672 dzDx = _funNoLoops->calculateJacobianHessianUsedByLoops(handler,
673 loopHessInfo, x, yNL,
674 noLoopEvalJacSparsity,
679 for (
size_t i = 0; i < tmpsAlias.size(); i++)
680 tmpsAlias[i].getOperationNode()->getArguments().push_back(asArgument(yNL[nonIndexdedEqSize + i]));
682 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
691 _funNoLoops->calculateHessian4OrignalEquations(x, w,
692 noLoopEvalHessSparsity, noLoopEvalHessLocations,
699 for (itLoop2Info = loopHessInfo.begin(); itLoop2Info != loopHessInfo.end(); ++itLoop2Info) {
705 size_t hessElSize = info.nonIndexedNonIndexedPosition.size();
706 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
708 hessElSize += infog.indexedIndexedPositions.size() +
709 infog.indexedTempPositions.size() +
710 infog.nonIndexedIndexedPositions.size();
716 std::vector<pair<CGBase, IndexPattern*> > indexedLoopResults(hessElSize);
722 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
729 for (
const auto& it : infog.indexedIndexedPositions) {
730 size_t tapeJ1 = it.first.first;
731 size_t tapeJ2 = it.first.second;
732 const std::vector<HessianElement>& positions = it.second;
734 addContribution(indexedLoopResults, hessLE,
735 createHessianContribution(handler, positions, infog.
hess[tapeJ1].at(tapeJ2),
736 *info.iterationIndexOp, info.ifElses));
743 for (
const auto& it : infog.indexedNonIndexedPositions) {
744 size_t tapeJ1 = it.first.first;
745 size_t tapeJ2 = it.first.second;
746 const std::vector<HessianElement>& positions = it.second;
748 addContribution(indexedLoopResults, hessLE,
749 createHessianContribution(handler, positions, infog.
hess[tapeJ1].at(tapeJ2),
750 *info.iterationIndexOp, info.ifElses));
756 if (!infog.indexedTempPositions.empty()) {
757 for (
const auto& itEval : infog.indexedTempEvals) {
758 size_t tapeJ1 = itEval.first.first;
759 size_t j2 = itEval.first.second;
760 const set<size_t>& ks = itEval.second;
762 const auto itPos = infog.indexedTempPositions.find(itEval.first);
763 if (itPos != infog.indexedTempPositions.end()) {
764 const std::vector<HessianElement>& positions = itPos->second;
767 for (
size_t k : ks) {
769 hessVal += infog.
hess[tapeJ1].at(tapeK) * dzDx[k][j2];
772 addContribution(indexedLoopResults, hessLE,
773 createHessianContribution(handler, positions, hessVal,
774 *info.iterationIndexOp, info.ifElses));
782 for (
const auto& it : infog.nonIndexedIndexedPositions) {
783 size_t tapeJ1 = it.first.first;
784 size_t tapeJ2 = it.first.second;
785 const std::vector<HessianElement>& positions = it.second;
787 addContribution(indexedLoopResults, hessLE,
788 createHessianContribution(handler, positions, infog.
hess[tapeJ1].at(tapeJ2),
789 *info.iterationIndexOp, info.ifElses));
800 if (!infog.tempIndexedPositions.empty()) {
801 for (
const auto& itEval : infog.indexedTempEvals) {
802 size_t tapeJ2 = itEval.first.first;
803 size_t j1 = itEval.first.second;
804 const set<size_t>& ks = itEval.second;
806 const auto itPos = infog.tempIndexedPositions.find(pairss(j1, tapeJ2));
807 if (itPos != infog.tempIndexedPositions.end()) {
808 const std::vector<HessianElement>& positions = itPos->second;
810 for (
size_t k : ks) {
812 hessVal += infog.
hess[tapeK].at(tapeJ2) * dzDx[k][j1];
815 addContribution(indexedLoopResults, hessLE,
816 createHessianContribution(handler, positions, hessVal,
817 *info.iterationIndexOp, info.ifElses));
827 for (
const auto& orig2PosIt : info.nonIndexedNonIndexedPosition) {
828 const pairss& orig = orig2PosIt.first;
829 size_t e = orig2PosIt.second;
831 size_t j1 = orig.first;
832 size_t j2 = orig.second;
838 handler.manageLoopDependentIndexPattern(pattern);
848 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
851 CGBase gHessVal = Base(0);
854 if (infog.nonIndexedNonIndexedEvals.find(orig) != infog.nonIndexedNonIndexedEvals.end()) {
855 gHessVal = infog.
hess[posJ1->tape].at(posJ2->tape);
861 const auto itNT = infog.nonIndexedTempEvals.find(orig);
862 if (itNT != infog.nonIndexedTempEvals.end()) {
863 const set<size_t>& ks = itNT->second;
865 for (
size_t k : ks) {
867 gHessVal += infog.
hess[posJ1->tape].at(tapeK) * dzDx[k][j2];
877 const auto itTN = infog.tempNonIndexedEvals.find(orig);
878 if (itTN != infog.tempNonIndexedEvals.end()) {
879 const set<size_t>& ks = itTN->second;
881 for (
size_t k1 : ks) {
883 gHessVal += infog.
hess[tapeK].at(posJ2->tape) * dzDx[k1][j1];
890 const auto itTT = infog.tempTempEvals.find(orig);
891 if (itTT != infog.tempTempEvals.end()) {
892 const map<size_t, set<size_t> >& k1k2 = itTT->second;
896 for (
const auto& itzz : k1k2) {
897 size_t k1 = itzz.first;
898 const set<size_t>& k2s = itzz.second;
902 for (
size_t k2 : k2s) {
905 tmp += infog.
hess[tapeK1].at(tapeK2) * dzDx[k2][j2];
908 sum += tmp * dzDx[k1][j1];
916 nIterations, gHessVal,
917 *info.iterationIndexOp, info.ifElses);
918 addContribution(indexedLoopResults, hessLE, make_pair(v, (
IndexPattern*)
nullptr));
928 const auto itTT2 = info.nonLoopNonIndexedNonIndexed.find(orig);
929 if (itTT2 != info.nonLoopNonIndexedNonIndexed.end()) {
930 hessVal += info.dzDxx.at(j1).at(j2);
934 addContribution(indexedLoopResults, hessLE, make_pair(hessVal, (
IndexPattern*) pattern));
937 indexedLoopResults.resize(hessLE);
942 size_t assignOrAdd = 1;
943 set<IndexOperationNode<Base>*> indexesOps;
944 indexesOps.insert(info.iterationIndexOp);
945 info.loopEnd = createLoopEnd(handler, *info.loopStart, indexedLoopResults, indexesOps, assignOrAdd);
947 for (
size_t e : lowerHessOrder) {
949 if (hess[e].isIdenticalZero()) {
950 hess[e] =
CG<Base>(*handler.makeNode(CGOpCode::DependentMultiAssign, *info.loopEnd));
952 }
else if (hess[e].getOperationNode() !=
nullptr && hess[e].getOperationNode()->getOperationType() == CGOpCode::DependentMultiAssign) {
953 hess[e].getOperationNode()->getArguments().push_back(*info.loopEnd);
956 hess[e] = handler.createCG(*handler.makeNode(CGOpCode::DependentMultiAssign,{asArgument(hess[e]), *info.loopEnd}));
961 for (
size_t g = 0; g < info.equationGroups.size(); g++) {
962 info.equationGroups[g].hess.clear();
969 moveNonIndexedOutsideLoop(handler, *info.loopStart, *info.loopEnd);
976 for (
const auto& it2 : duplicates) {
977 if (hess[it2.second].isVariable())
978 hess[it2.first] =
CG<Base>(*handler.makeNode(CGOpCode::Alias, asArgument(hess[it2.second])));
980 hess[it2.first] = hess[it2.second].getValue();
990 const std::vector<HessianElement>& positions,
996 if (ddfdxdx.isIdenticalZero()) {
1001 map<size_t, map<size_t, size_t> > locations;
1002 for (
size_t iter = 0; iter < positions.size(); iter++) {
1003 size_t c = positions[iter].count;
1005 locations[c][iter] = positions[iter].location;
1009 map<size_t, CG<Base> > results;
1012 for (
const auto& countIt : locations) {
1013 size_t count = countIt.first;
1016 for (
size_t c = 1; c < count; c++)
1019 results[count] = val;
1022 if (results.size() == 1 && locations.begin()->second.size() == positions.size()) {
1027 handler.manageLoopDependentIndexPattern(pattern);
1029 return make_pair(results.begin()->second, pattern);
1037 map<size_t, IfBranchData<Base> > branches;
1040 for (
const auto& countIt : locations) {
1042 size_t count = countIt.first;
1044 branches[count] = branch;
1047 CG<Base> v = createConditionalContribution(handler,
1049 positions.size() - 1,
1062 template<
class Base>
1065 const std::set<size_t>& iterations,
1070 using namespace std;
1072 if (ddfdxdx.isIdenticalZero()) {
1076 CPPADCG_ASSERT_UNKNOWN(pattern.getLinearSlopeDy() == 0)
1078 if (iterations.size() == nIterations) {
1089 return createConditionalContribution(handler, pattern,
1090 iterations, nIterations - 1,
1091 ddfdxdx, iterationIndexOp,
1096 template<
class Base>
1099 const std::vector<std::vector<
CG<Base> > >& vw,
1101 const std::vector<std::set<size_t> >& jacSparsity,
1102 const std::vector<std::set<size_t> >& jacEvalSparsity,
1103 std::vector<std::map<
size_t,
CG<Base> > >& jac,
1104 const std::vector<std::set<size_t> >& hesSparsity,
1105 const std::vector<std::set<size_t> >& hesEvalSparsity,
1106 std::vector<std::map<
size_t, std::map<
size_t,
CG<Base> > > >& vhess,
1107 bool individualColoring) {
1108 using namespace std;
1112 size_t m = fun.Range();
1113 size_t n = fun.Domain();
1116 vhess.resize(vw.size());
1118 if (!individualColoring) {
1124 std::vector<size_t> jacRow, jacCol;
1125 generateSparsityIndexes(jacEvalSparsity, jacRow, jacCol);
1128 std::vector<CGB> jacFlat(jacRow.size());
1133 std::vector<size_t> hesRow, hesCol;
1134 generateSparsityIndexes(hesEvalSparsity, hesRow, hesCol);
1136 std::vector<std::vector<CGB> > vhessFlat(vw.size());
1137 for (
size_t l = 0; l < vw.size(); l++) {
1138 vhessFlat[l].resize(hesRow.size());
1141 std::vector<CG<Base> > xl;
1142 if (x.size() == 0) {
1150 sparseForJacHessian(fun, xl, vw,
1153 jacRow, jacCol, jacFlat,
1155 hesRow, hesCol, vhessFlat,
1159 for (
size_t el = 0; el < jacRow.size(); el++) {
1160 size_t i = jacRow[el];
1161 size_t j = jacCol[el];
1163 jac[i][j] = jacFlat[el];
1167 for (
size_t l = 0; l < vw.size(); l++) {
1168 std::vector<CGB>& hessFlat = vhessFlat[l];
1169 map<size_t, map<size_t, CGB> >& hess = vhess[l];
1171 for (
size_t el = 0; el < hesRow.size(); el++) {
1172 size_t j1 = hesRow[el];
1173 size_t j2 = hesCol[el];
1174 hess[j1][j2] = hessFlat[el];
1184 std::vector<set<size_t> > jacEvalSparsityT(n);
1185 addTransMatrixSparsity(jacEvalSparsity, jacEvalSparsityT);
1187 std::vector<CGB> tx1v(n);
1189 y = fun.Forward(0, x);
1191 for (
size_t j1 = 0; j1 < n; j1++) {
1192 if (jacEvalSparsityT[j1].empty() && hesEvalSparsity[j1].empty()) {
1197 std::vector<CGB> dy = fun.Forward(1, tx1v);
1198 CPPADCG_ASSERT_UNKNOWN(dy.size() == m)
1202 const set<size_t>& column = jacEvalSparsityT[j1];
1203 for (
size_t i : column) {
1207 const set<size_t>& hesRow = hesEvalSparsity[j1];
1209 if (!hesRow.empty()) {
1211 for (
size_t l = 0; l < vw.size(); l++) {
1213 std::vector<CGB> px = fun.Reverse(2, vw[l]);
1214 CPPADCG_ASSERT_UNKNOWN(px.size() == 2 * n)
1217 map<size_t, CGB>& hessRow = vhess[l][j1];
1218 for (
size_t j2 : hesRow) {
1219 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