1#ifndef CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_REV2_INCLUDED
2#define CPPAD_CG_MODEL_C_SOURCE_GEN_LOOPS_REV2_INCLUDED
27class HessianWithLoopsInfo;
30class HessianTermContrib;
39std::vector<std::pair<CG<Base>, IndexPattern*> > generateReverseTwoGroupOps(CodeHandler<Base>&
handler,
40 const LoopModel<Base>&
lModel,
41 const loops::HessianWithLoopsInfo<Base>&
info,
44 const std::map<
size_t, std::map<
size_t, CG<Base> > >&
dzDx,
48std::pair<CG<Base>, IndexPattern*> createReverseMode2Contribution(CodeHandler<Base>&
handler,
50 const std::vector<HessianElement>&
positions,
64 using namespace CppAD::cg::loops;
66 size_t m = _fun.Range();
67 size_t n = _fun.Domain();
71 handler.setZeroDependents(
false);
79 std::vector<OperationNode<Base>* >
localNodes(5);
87 std::vector<CGBase> x(
n);
90 for (
size_t i = 0;
i <
n;
i++) {
98 tx1.setValue(Base(1.0));
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;
125 for (
size_t e = 0;
e <
jcols.size();
e++) {
150 if (_funNoLoops !=
nullptr) {
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,
263 for (
const auto&
itJrow2It : group.jRow2Iterations) {
280 for (
const auto&
itJrow2It : group.jRow2Iterations) {
312 for (
const auto&
itJrow2Its : group.jRow2Iterations) {
320 size_t itCount = group.jRow2Iterations.begin()->second.size();
359 moveNonIndexedOutsideLoop(
handler, *loopStart, *loopEnd);
385 langC.setParameterPrecision(_parameterPrecision);
387 std::ostringstream
code;
388 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"px"));
395 _cache <<
"model (reverse two, loop " <<
lModel.getLoopId() <<
", group " <<
g <<
")";
400 generateFunctionNameLoopRev2(_cache,
lModel,
g);
403 std::string
argsDcl =
langC.generateFunctionArgumentsDcl();
406 _cache <<
"#include <stdlib.h>\n"
407 "#include <math.h>\n"
412 nameGenRev2.customFunctionVariableDeclarations(_cache);
413 _cache <<
langC.generateIndependentVariableDeclaration() <<
"\n";
414 _cache <<
langC.generateDependentVariableDeclaration() <<
"\n";
415 _cache <<
langC.generateTemporaryVariableDeclaration(
false,
false,
416 handler.getExternalFuncMaxForwardOrder(),
417 handler.getExternalFuncMaxReverseOrder()) <<
"\n";
418 nameGenRev2.prepareCustomFunctionVariables(_cache);
421 _cache <<
code.str();
423 nameGenRev2.finalizeCustomFunctionVariables(_cache);
442 if (_funNoLoops !=
nullptr) {
448 std::vector<size_t> row, col;
451 if (row.size() > 0) {
452 const string jobName =
"model (reverse two, no loops)";
453 startingJob(
"'" +
jobName +
"'", JobTimer::SOURCE_GENERATION);
459 std::vector<CGBase>
tx0(
n);
462 for (
size_t i = 0;
i <
n;
i++) {
463 tx0[
i].setValue(_x[
i]);
470 tx1.setValue(Base(1.0));
473 std::vector<CGBase>
py(m);
476 std::vector<CGBase>
pyNoLoop(_funNoLoops->getTapeDependentCount());
478 const std::vector<size_t>&
origIndexes = _funNoLoops->getOrigDependentIndexes();
492 work.color_method =
"cppad.general";
495 map<size_t, map<size_t, CGBase> > hess;
497 for (
size_t el = 0;
el < row.size();
el++) {
501 for (
size_t itE : locations) {
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 <<
")";
518 std::vector<CGBase>
pxCustom(elements.at(
j).size());
520 for (
const auto&
it2 : cols) {
521 size_t e =
it2.first;
526 langC.setMaxAssignmentsPerFunction(_maxAssignPerFunc, &_sources);
527 langC.setMaxOperationsPerAssignment(_maxOperationsPerAssignment);
528 langC.setParameterPrecision(_parameterPrecision);
530 _cache << _name <<
"_" << FUNCTION_SPARSE_REVERSE_TWO <<
"_noloop_indep" <<
j;
534 std::ostringstream
code;
535 std::unique_ptr<VariableNameGenerator<Base> > nameGen(createVariableNameGenerator(
"px"));
549 string functionRev2 = _name +
"_" + FUNCTION_SPARSE_REVERSE_TWO;
550 _sources[
functionRev2 +
".c"] = generateGlobalForRevWithLoopsFunctionSource(elements,
551 _loopRev2Groups, _nonLoopRev2Elements,
553 generateFunctionNameLoopRev2);
558 generateSparsity1DSource2(_name +
"_" + FUNCTION_REVERSE_TWO_SPARSITY, elements);
559 _sources[_name +
"_" + FUNCTION_REVERSE_TWO_SPARSITY +
".c"] = _cache.str();
571 using namespace CppAD::cg::loops;
582 map<HessianTermContrib<Base>, set<size_t> >
contrib2jrows = groupHessianRowsByContrib(
info,
n,
593 const set<size_t>&
jrows =
itC.second;
615 const std::map<
size_t, std::map<
size_t,
CG<Base> > >&
dzDx,
618 using namespace CppAD::cg::loops;
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) {
647 if (
itPos !=
infog.indexedIndexedPositions.end()) {
651 createReverseMode2Contribution(
handler, group,
661 for (
const pairss&
it : group.indexedNonIndexed) {
666 if (
itPos !=
infog.indexedNonIndexedPositions.end()) {
670 createReverseMode2Contribution(
handler, group,
680 for (
const pairss&
it : group.indexedTemp) {
682 size_t j2 =
it.second;
685 if (
itPos !=
infog.indexedTempPositions.end()) {
687 const set<size_t>&
ks =
infog.indexedTempEvals.at(
it);
689 CGBase
val = Base(0);
690 for (
size_t k :
ks) {
696 createReverseMode2Contribution(
handler, group,
707 for (
const pairss&
it : group.nonIndexedIndexed) {
712 if (
itPos !=
infog.nonIndexedIndexedPositions.end()) {
716 createReverseMode2Contribution(
handler, group,
729 for (
const pairss&
it : group.tempIndexed) {
730 size_t j1 =
it.first;
734 if (
itPos !=
infog.tempIndexedPositions.end()) {
738 CGBase
val = Base(0);
739 for (
size_t k :
ks) {
745 createReverseMode2Contribution(
handler, group,
756 for (
const pairss&
orig : group.nonIndexedNonIndexed) {
757 size_t e =
info.nonIndexedNonIndexedPosition.at(
orig);
766 handler.manageLoopDependentIndexPattern(pattern);
776 for (
size_t g = 0;
g <
info.equationGroups.size();
g++) {
778 set<size_t> iterations;
781 std::inserter(iterations, iterations.begin()));
786 if (
infog.nonIndexedNonIndexedEvals.find(
orig) !=
infog.nonIndexedNonIndexedEvals.end()) {
794 if (
itNT !=
infog.nonIndexedTempEvals.end()) {
795 const set<size_t>&
ks =
itNT->second;
797 for (
size_t k :
ks) {
810 if (
itTN !=
infog.tempNonIndexedEvals.end()) {
811 const set<size_t>&
ks =
itTN->second;
813 for (
size_t k1 :
ks) {
824 const map<size_t, set<size_t> >&
k1k2 =
itTT->second;
826 CGBase
sum = Base(0);
830 const set<size_t>&
k2s =
itzz.second;
833 CGBase
tmp = Base(0);
834 for (
size_t k2 :
k2s) {
846 if (iterations.size() != group.iterations.size()) {
847 CGBase v = createReverseMode2Contribution(
handler, group,
848 *pattern, iterations,
850 *
info.iterationIndexOp,
862 const auto itTT2 =
info.nonLoopNonIndexedNonIndexed.find(
orig);
863 if (
itTT2 !=
info.nonLoopNonIndexedNonIndexed.end()) {
870 if (!
hessVal.isIdenticalZero()) {
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;
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) {
934 const std::vector<HessianElement>&
positions =
it.second;
944 for (
const auto&
it :
infog.indexedNonIndexedPositions) {
946 const std::vector<HessianElement>&
positions =
it.second;
956 for (
const auto&
it :
infog.indexedTempPositions) {
958 const std::vector<HessianElement>&
positions =
it.second;
968 for (
const auto&
it :
infog.nonIndexedIndexedPositions) {
970 const std::vector<HessianElement>&
positions =
it.second;
980 for (
const auto&
it :
infog.tempIndexedPositions) {
982 const std::vector<HessianElement>&
positions =
it.second;
993 for (
const auto&
orig2PosIt :
info.nonIndexedNonIndexedPosition) {
1002 for (
size_t j = 0;
j <
n;
j++) {
1019 const std::set<size_t>&
jrows,
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) {
1043 for (pairss
pos :
c.indexedNonIndexed) {
1052 for (pairss
pos :
c.indexedTemp) {
1061 for (pairss
pos :
c.nonIndexedIndexed) {
1070 if (!
c.nonIndexedNonIndexed.empty()) {
1076 for (pairss
pos :
c.nonIndexedNonIndexed) {
1083 for (pairss
pos :
c.tempIndexed) {
1116 const std::vector<HessianElement>&
positions,
1121 using namespace std;
1123 if (
ddfdxdx.isIdenticalZero()) {
1133 map<size_t, map<size_t, size_t> > locations;
1134 for (
size_t iter : group.iterations) {
1143 if (locations.empty()) {
1147 map<size_t, CG<Base> >
results;
1150 for (
const auto&
countIt : locations) {
1154 for (
size_t c = 1;
c < count;
c++)
1160 if (
results.size() == 1 && locations.begin()->second.size() == group.iterations.size()) {
1165 handler.manageLoopDependentIndexPattern(pattern);
1175 map<size_t, IfBranchData<Base> >
branches;
1178 for (
const auto&
countIt : locations) {
1187 group.iterations.size(),
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(),
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() +
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;
1291 std::map<size_t, std::set<size_t> > jRow2Iterations;
1293 std::set<size_t> iterations;
1295 std::vector<IfElseInfo<Base> > ifElses;
1312 generateFunctionNameLoopRev2(
cache, _name,
loop,
g);
1321 "_loop" <<
loop.getLoopId() <<
"_g" <<
g;
static IndexPattern * detect(const VectorSizeT &x2y)
virtual void prepareSparseReverseTwoWithLoops(const std::map< size_t, std::vector< size_t > > &elements)
static Plane2DIndexPattern * detectPlane2D(const std::map< size_t, std::map< size_t, size_t > > &x2y2z)
std::map< size_t, std::map< size_t, CG< Base > > > hess
std::vector< std::map< size_t, CG< Base > > > dyiDzk
bool GreaterThanZero(const cg::CG< Base > &x)