1 #ifndef CPPAD_CG_LOOP_INCLUDED
2 #define CPPAD_CG_LOOP_INCLUDED
25 const std::vector<const OperationNode<Base>*> order;
35 std::map<size_t, IndependentOrder<Base>*> arg2Order;
54 using IndexValue = std::pair<size_t, CG<Base> >;
74 std::unique_ptr<CodeHandlerVector<Base, size_t>> varId_;
78 std::unique_ptr<CodeHandlerVector<Base, bool>> varIndexed_;
82 size_t iterationCount_;
90 std::vector<EquationGroup<Base> > eqGroups_;
94 std::map<EquationPattern<Base>*,
size_t> equationOrder_;
99 std::vector<std::set<size_t> > iterationDependents_;
103 std::map<size_t, size_t> dep2Iteration_;
107 size_t nIndependents_;
115 std::map<const OperationNode<Base>*, IndexValue> independentsIndexed_;
119 std::map<const OperationNode<Base>*, IndexValue> independentsNonIndexed_;
123 std::map<const OperationNode<Base>*, IndexValue> independentsTemp_;
127 std::map<size_t, OperationNode<Base>*> clonesTemporary_;
145 std::map<const OperationNode<Base>*, std::vector<IndependentOrder<Base>*> > firstIndep2orders_;
154 std::forward_list<OperationArgumentsIndepOrder<Base>*> arg2IndepOrder_;
162 handlerOrig_(eq.depRef.getCodeHandler()),
163 varId_(handlerOrig_ != nullptr ? new
CodeHandlerVector<Base, size_t>(*handlerOrig_): nullptr),
164 varIndexed_(handlerOrig_ != nullptr ? new
CodeHandlerVector<Base, bool>(*handlerOrig_): nullptr),
173 eqGroups_[0].equations.insert(&eq);
175 if(varId_ !=
nullptr)
176 varId_->adjustSize();
184 eqGroups_[0].equations.insert(&eq);
187 inline void setLinkedDependents(
const std::set<std::set<size_t>*>& newLoopRelations) {
188 CPPADCG_ASSERT_UNKNOWN(eqGroups_.size() == 1);
190 eqGroups_[0].linkedDependents.clear();
191 eqGroups_[0].linkedDependents.reserve(newLoopRelations.size());
193 for (std::set<size_t>* it : newLoopRelations)
194 eqGroups_[0].linkedDependents.push_back(*it);
197 inline void addLinkedEquationsByNonIndexed(EquationPattern<Base>* eq1,
198 EquationPattern<Base>* eq2) {
199 eqGroups_[0].addLinkedEquationsByNonIndexed(eq1, eq2);
202 inline size_t getLinkedEquationsByNonIndexedCount()
const {
203 return eqGroups_[0].getLinkedEquationsByNonIndexedCount();
210 return iterationCount_;
213 const std::vector<std::set<size_t> >& getIterationDependents()
const {
214 return iterationDependents_;
217 inline LoopModel<Base>* getModel()
const {
221 inline LoopModel<Base>* releaseLoopModel() {
222 LoopModel<Base>* loopAtomic = loopModel_;
223 loopModel_ =
nullptr;
235 CPPADCG_ASSERT_UNKNOWN(iterationCount_ == other.iterationCount_)
241 CPPADCG_ASSERT_UNKNOWN(eqGroups_.size() == 1)
242 CPPADCG_ASSERT_UNKNOWN(other.eqGroups_.size() == 1)
248 CPPADCG_ASSERT_UNKNOWN(equationOrder_.empty())
249 CPPADCG_ASSERT_UNKNOWN(iterationDependents_.empty())
251 g.linkedEquationsByNonIndexed.insert(og.linkedEquationsByNonIndexed.begin(), og.linkedEquationsByNonIndexed.end());
253 g.linkedEquationsByNonIndexed.erase(itNIndexed);
256 for (
size_t e = 0; e < nonIndexedLoopRelations.size(); e++) {
257 g.addLinkedEquationsByNonIndexed(nonIndexedLoopRelations[e].first, nonIndexedLoopRelations[e].second);
263 eqGroups_.insert(eqGroups_.end(), other.eqGroups_.begin(), other.eqGroups_.end());
272 for (
const auto& it : other.equationOrder_) {
273 equationOrder_[it.first] = it.second + nEq;
276 CPPADCG_ASSERT_UNKNOWN(iterationDependents_.size() == other.iterationDependents_.size())
277 for (
size_t iter = 0; iter < iterationDependents_.size(); iter++) {
278 iterationDependents_[iter].insert(other.iterationDependents_[iter].begin(), other.iterationDependents_[iter].end());
284 const std::vector<
CG<Base> >& independents,
288 CPPADCG_ASSERT_UNKNOWN(dep2Iteration_.empty())
289 for (
size_t iter = 0; iter < iterationCount_; iter++) {
290 const std::set<size_t>& deps = iterationDependents_[iter];
292 for (
size_t d : deps) {
293 dep2Iteration_[d] = iter;
297 if(varIndexed_ !=
nullptr) {
298 varIndexed_->adjustSize();
299 varIndexed_->fill(
false);
305 for (
size_t g = 0; g < eqGroups_.size(); g++) {
306 eqGroups_[g].findReferenceIteration();
307 #ifdef CPPADCG_PRINT_DEBUG
308 std::cout <<
"reference iteration=" << eqGroups_[g].refIteration <<
"\n";
309 print(eqGroups_[g].iterationDependents);
310 std::cout << std::endl;
312 typename std::set<EquationPattern<Base>*>::const_iterator iteq;
313 for (iteq = eqGroups_[g].
equations.begin(); iteq != eqGroups_[g].equations.end(); ++iteq) {
314 std::cout <<
"eq dependents=";
315 print((*iteq)->dependents);
316 std::cout << std::endl;
322 for (
size_t g = 0; g < eqGroups_.size(); g++) {
325 CPPADCG_ASSERT_UNKNOWN(refItDep.size() == group.
equations.size())
327 for (
size_t dep : refItDep) {
331 for (
size_t dep : refItDep) {
335 std::set<const OperationNode<Base>*> indexedOperations;
337 eq->findIndexedPath(dep, dependents, *varIndexed_, indexedOperations);
338 if (dep == eq->depRefIndex) {
343 CPPADCG_ASSERT_UNKNOWN(itop2a.first !=
nullptr)
344 addOperationArguments2Loop(itop2a.first, itop2a.second);
353 CPPADCG_ASSERT_UNKNOWN(opLoopRef !=
nullptr)
356 addOperationArguments2Loop(opLoopRef, eq->
indexedOpIndep.op2Arguments.at(opEqRef));
368 generateIndependentLoopIndexes();
370 if(varId_ !=
nullptr)
373 createLoopTapeNModel(dependents, independents, dep2Equation, origTemp2Index);
378 if(varId_ !=
nullptr)
385 iterationDependents_.clear();
386 equationOrder_.clear();
392 map<EquationPattern<Base>*, set<size_t> > depsInEq;
395 depsInEq[eq] = eq->dependents;
396 nMaxIt = std::max<size_t>(nMaxIt, eq->dependents.size());
399 iterationDependents_.reserve(nMaxIt + 2 *
equations.size());
401 for (
size_t g = 0; g < eqGroups_.size(); g++) {
403 const set<EquationPattern<Base>*>& eqs = group.
equations;
407 relatedEqIterationDeps.reserve(iterationDependents_.size());
411 size_t eqo_size = equationOrder_.size();
412 equationOrder_[eq] = eqo_size;
416 set<size_t> dependents;
418 dependents.insert(eq->dependents.begin(), eq->dependents.end());
421 map<size_t, map<EquationPattern<Base>*, set<size_t> > > nIndexedGroupPos2Eq2deps;
424 map<EquationPattern<Base>*, std::vector<size_t> > freeDependents;
426 freeDependents[eq].assign(eq->dependents.begin(), eq->dependents.end());
429 DependentIndexSorter depSorter(group, freeDependents, dep2Equation);
431 auto itDep = dependents.begin();
433 while (itDep != dependents.end()) {
437 if (iterationDependents_.size() <= i)
438 iterationDependents_.resize(i + 1);
439 set<size_t>& itDepi = iterationDependents_[i];
441 if (relatedEqIterationDeps.size() <= i)
442 relatedEqIterationDeps.resize(i + 1);
443 set<size_t>& ritDepi = relatedEqIterationDeps[i];
448 auto bestDep = depSorter.findBestDependentForIteration(dep, eq);
452 long pos = group.findIndexedLinkedDependent(dep);
455 for (
size_t dep2 : linkedDependents[pos]) {
456 if (dep2 == *itDep) itDep++;
458 ritDepi.insert(dep2);
459 dependents.erase(dep2);
462 std::vector<size_t>& eq2FreeDep = freeDependents[eq2];
463 typename std::vector<size_t>::const_iterator itFreeDep2;
464 itFreeDep2 = std::find(eq2FreeDep.cbegin(), eq2FreeDep.cend(), dep2);
465 CPPADCG_ASSERT_UNKNOWN(itFreeDep2 != eq2FreeDep.cend())
467 eq2FreeDep.erase(itFreeDep2);
473 long posN = group.findNonIndexedLinkedRel(eq);
476 dependents.erase(dep);
477 nIndexedGroupPos2Eq2deps[posN][eq].insert(dep);
482 std::vector<size_t>& eqFreeDep = freeDependents[eq];
483 auto itFreeDep = find(eqFreeDep.begin(), eqFreeDep.end(), dep);
484 CPPADCG_ASSERT_UNKNOWN(itFreeDep != eqFreeDep.end())
486 eqFreeDep.erase(itFreeDep);
497 if (!nIndexedGroupPos2Eq2deps.empty()) {
499 map<EquationPattern<Base>*, set<size_t> > eqIterations;
500 for (
size_t i = 0; i < relatedEqIterationDeps.size(); i++) {
501 const set<size_t>& deps = relatedEqIterationDeps[i];
502 for (
size_t dep : deps) {
503 eqIterations[dep2Equation.at(dep)].insert(i);
507 for (
auto& itPos2Eq2Dep : nIndexedGroupPos2Eq2deps) {
508 size_t posN = itPos2Eq2Dep.first;
510 std::vector<size_t> deps;
511 deps.reserve(itPos2Eq2Dep.second.size());
513 set<size_t> usedIterations;
517 const set<size_t>& iters = eqIterations[itRel];
518 usedIterations.insert(iters.begin(), iters.end());
526 for (
auto& itEq2Dep : itPos2Eq2Dep.second) {
527 if (!itEq2Dep.second.empty()) {
528 deps.push_back(*itEq2Dep.second.begin());
529 itEq2Dep.second.erase(itEq2Dep.second.begin());
539 set<size_t>::const_iterator itIter;
540 for (itIter = usedIterations.begin(); itIter != usedIterations.end();) {
543 if (itIter != usedIterations.end()) {
555 usedIterations.insert(i);
557 if (iterationDependents_.size() <= i)
558 iterationDependents_.resize(i + 1);
559 set<size_t>& itDepi = iterationDependents_[i];
561 if (relatedEqIterationDeps.size() <= i)
562 relatedEqIterationDeps.resize(i + 1);
563 set<size_t>& ritDepi = relatedEqIterationDeps[i];
564 itDepi.insert(deps.begin(), deps.end());
565 ritDepi.insert(deps.begin(), deps.end());
577 iterationCount_ = std::max<size_t>(iterationCount_, iterationDependents_.size());
586 for (
const auto& itf : firstIndep2orders_) {
610 CPPADCG_ASSERT_UNKNOWN(!dep2Iteration_.empty());
621 size_t dep = itDepIndep.first;
622 size_t iter = dep2Iteration_.at(dep);
629 void generateIndependentLoopIndexes() {
630 CPPADCG_ASSERT_UNKNOWN(iterationCount_ > 0);
634 const OperationNode<Base>* operation = it.first;
635 const OperationIndexedIndependents<Base>& opInd = it.second;
637 auto* arg2orderPos =
new OperationArgumentsIndepOrder<Base>();
638 op2Arg2IndepOrder_[operation] = arg2orderPos;
640 arg2IndepOrder_.push_front(arg2orderPos);
643 size_t aSize = opInd.arg2Independents.size();
644 for (
size_t argumentIndex = 0; argumentIndex < aSize; argumentIndex++) {
645 const std::map<size_t, const OperationNode<Base>*>& dep2Indep = opInd.arg2Independents[argumentIndex];
646 if (dep2Indep.empty())
649 std::vector<const OperationNode<Base>*> order(iterationCount_);
654 CPPADCG_ASSERT_UNKNOWN(dep2Indep.size() > 0 && dep2Indep.size() <= iterationCount_)
655 for (
const auto& itDep2Indep : dep2Indep) {
656 size_t iterationIndex = itDep2Indep.first;
657 const OperationNode<Base>* indep = itDep2Indep.second;
659 order[iterationIndex] = indep;
665 std::vector<IndependentOrder<Base>*>& availableOrders = firstIndep2orders_[order[0]];
666 IndependentOrder<Base>* match =
nullptr;
668 long a_size = availableOrders.size();
669 for (
long o = 0; o < a_size; o++) {
670 IndependentOrder<Base>* orderO = availableOrders[o];
672 for (
size_t iterationIndex = 0; iterationIndex < iterationCount_; iterationIndex++) {
673 if (orderO->order[iterationIndex] != order[iterationIndex]) {
684 if (match !=
nullptr) {
686 arg2orderPos->arg2Order[argumentIndex] = match;
689 auto* iOrder =
new IndependentOrder<Base>(order);
690 availableOrders.push_back(iOrder);
691 arg2orderPos->arg2Order[argumentIndex] = iOrder;
707 void createLoopTapeNModel(
const std::vector<CG<Base> >& dependents,
708 const std::vector<CG<Base> >& independents,
709 const std::map<
size_t, EquationPattern<Base>*>& dep2Equation,
710 std::map<OperationNode<Base>*,
size_t>& origTemp2Index) {
711 using CGB = CG<Base>;
712 using ADCGB = AD<CGB>;
713 CPPADCG_ASSERT_UNKNOWN(independents.size() > 0)
714 CPPADCG_ASSERT_UNKNOWN(independents[0].getCodeHandler() !=
nullptr)
715 CodeHandler<Base>& origHandler = *independents[0].getCodeHandler();
723 CPPADCG_ASSERT_UNKNOWN(equationOrder_.size() ==
equations.size())
727 for (
size_t g = 0; g < eqGroups_.size(); g++) {
728 const EquationGroup<Base>& group = eqGroups_[g];
729 const std::set<size_t>& iterationDependents = group.iterationDependents[group.refIteration];
731 for (
size_t depIndex : iterationDependents) {
732 EquationPattern<Base>* eq = dep2Equation.at(depIndex);
733 OperationNode<Base>* node = dependents[depIndex].getOperationNode();
735 Argument<Base> aClone;
737 if (node !=
nullptr) {
738 if (node->getOperationType() == CGOpCode::Inv) {
739 aClone = createIndependentClone(
nullptr, 0, *node);
741 aClone = makeGraphClones(*eq, *node);
744 aClone = dependents[depIndex].getValue();
747 size_t i = equationOrder_.at(eq);
748 deps[i] = CGB(aClone);
756 CPPADCG_ASSERT_UNKNOWN(indexedIndep2clone_.size() == independentsIndexed_.size());
758 std::vector<const OperationNode<Base>*> indexedCloneOrder;
759 indexedCloneOrder.reserve(indexedIndep2clone_.size());
761 std::map<const OperationNode<Base>*,
const IndependentOrder<Base>*> clone2indexedIndep;
762 for (
const auto& it : indexedIndep2clone_) {
763 clone2indexedIndep[it.second] = it.first;
764 indexedCloneOrder.push_back(it.second);
767 struct IndexedIndepSorter indexedSorter(clone2indexedIndep);
768 std::sort(indexedCloneOrder.begin(), indexedCloneOrder.end(), indexedSorter);
771 std::map<size_t, const OperationNode<Base>*> nonIndexedCloneOrder;
774 std::map<const OperationNode<Base>*,
const OperationNode<Base>*> clones2ConstIndep;
776 for (
auto itc = orig2ConstIndepClone_.begin(); itc != orig2ConstIndepClone_.end(); ++itc, s++) {
777 const OperationNode<Base>* orig = itc->first;
778 OperationNode<Base>* clone = itc->second;
780 size_t j = orig->getInfo()[0];
781 clones2ConstIndep[clone] = orig;
782 nonIndexedCloneOrder[j] = clone;
785 size_t nIndexed = indexedCloneOrder.size();
786 size_t nNonIndexed = nonIndexedCloneOrder.size();
787 size_t nTmpIndexed = independentsTemp_.size();
790 size_t nIndep = independentsIndexed_.size() +
791 independentsNonIndexed_.size() +
792 independentsTemp_.size();
793 std::vector<ADCGB> loopIndeps(nIndep);
795 typename std::map<const OperationNode<Base>*, IndexValue>::const_iterator itt;
796 typename std::map<size_t, const OperationNode<Base>*>::const_iterator origJ2CloneIt;
799 loopIndeps.resize(1);
800 loopIndeps[0] = Base(0);
807 for (
size_t j = 0; j < nIndexed; j++) {
808 const IndexValue& iv = independentsIndexed_.at(indexedCloneOrder[j]);
809 loopIndeps[j] = iv.second;
813 for (origJ2CloneIt = nonIndexedCloneOrder.begin(); origJ2CloneIt != nonIndexedCloneOrder.end(); ++origJ2CloneIt, s++) {
814 const IndexValue& iv = independentsNonIndexed_.at(origJ2CloneIt->second);
815 loopIndeps[nIndexed + s] = iv.second;
819 for (itt = independentsTemp_.begin(); itt != independentsTemp_.end(); ++itt, s++) {
820 const IndexValue& iv = itt->second;
821 loopIndeps[nIndexed + nNonIndexed + s] = iv.second;
828 CppAD::Independent(loopIndeps);
833 std::vector<ADCGB> localIndeps(nIndep);
835 for (
size_t j = 0; j < nIndexed; j++) {
836 const IndexValue& iv = independentsIndexed_.at(indexedCloneOrder[j]);
837 size_t localIndex = iv.first;
838 localIndeps[localIndex] = loopIndeps[j];
842 for (origJ2CloneIt = nonIndexedCloneOrder.begin(); origJ2CloneIt != nonIndexedCloneOrder.end(); ++origJ2CloneIt, s++) {
843 size_t localIndex = independentsNonIndexed_.at(origJ2CloneIt->second).first;
844 localIndeps[localIndex] = loopIndeps[nIndexed + s];
848 for (itt = independentsTemp_.begin(); itt != independentsTemp_.end(); ++itt, s++) {
849 size_t localIndex = itt->second.first;
850 localIndeps[localIndex] = loopIndeps[nIndexed + nNonIndexed + s];
857 Evaluator<Base, CGB> evaluator1stIt(handler_);
860 const std::map<size_t, CGAbstractAtomicFun<Base>* >& atomicsOrig = origHandler.getAtomicFunctions();
861 std::map<size_t, atomic_base<CGB>* > atomics;
862 atomics.insert(atomicsOrig.begin(), atomicsOrig.end());
863 evaluator1stIt.addAtomicFunctions(atomics);
865 std::vector<ADCGB> newDeps = evaluator1stIt.evaluate(localIndeps, deps);
867 bool containsAtoms = evaluator1stIt.getNumberOfEvaluatedAtomics() > 0;
869 std::unique_ptr<ADFun<CGB> >funIndexed(
new ADFun<CGB>());
870 funIndexed->Dependent(newDeps);
875 std::vector<std::vector<size_t> > dependentOrigIndexes(
equations.size(), std::vector<size_t> (iterationCount_, (std::numeric_limits<size_t>::max)()));
876 for (
size_t it = 0; it < iterationCount_; it++) {
877 const std::set<size_t>& itDeps = iterationDependents_[it];
878 for (
size_t origDep : itDeps) {
879 EquationPattern<Base>* eq = dep2Equation.at(origDep);
880 size_t i = equationOrder_.at(eq);
881 dependentOrigIndexes[i][it] = origDep;
886 std::vector<std::vector<size_t> > indexedIndependents(nIndexed, std::vector<size_t>(iterationCount_));
887 for (
size_t j = 0; j < indexedCloneOrder.size(); j++) {
888 const IndependentOrder<Base>* origOrder = clone2indexedIndep.at(indexedCloneOrder[j]);
889 for (
size_t it = 0; it < iterationCount_; it++) {
890 const OperationNode<Base>* indep = origOrder->order[it];
892 if (indep !=
nullptr) {
893 index = indep->getInfo()[0];
895 index = (std::numeric_limits<size_t>::max)();
897 indexedIndependents[j][it] = index;
901 std::vector<size_t> temporaryIndependents(nTmpIndexed);
904 for (itt = independentsTemp_.begin(); itt != independentsTemp_.end(); ++itt, j++) {
905 const OperationNode<Base>* tmpClone = itt->first;
906 OperationNode<Base>* origTmpNode = temporaryClone2Orig_.at(tmpClone);
912 typename std::map<OperationNode<Base>*,
size_t>::const_iterator itz = origTemp2Index.find(origTmpNode);
913 if (itz == origTemp2Index.end()) {
914 k = origTemp2Index.size();
915 origTemp2Index[origTmpNode] = k;
920 temporaryIndependents[j] = k;
923 std::vector<size_t> nonIndexedIndependents(orig2ConstIndepClone_.size());
925 for (origJ2CloneIt = nonIndexedCloneOrder.begin(); origJ2CloneIt != nonIndexedCloneOrder.end(); ++origJ2CloneIt, s++) {
926 nonIndexedIndependents[s] = origJ2CloneIt->first;
929 loopModel_ =
new LoopModel<Base>(funIndexed.release(),
932 dependentOrigIndexes,
934 nonIndexedIndependents,
935 temporaryIndependents);
937 loopModel_->detectIndexPatterns();
940 inline Argument<Base> makeGraphClones(
const EquationPattern<Base>& eq,
941 OperationNode<Base>& node) {
943 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::Inv)
945 size_t id = (*varId_)[node];
949 return Argument<Base>(*clonesTemporary_.at(
id));
955 (*varId_)[node] = id;
957 if ((*varIndexed_)[node] || node.getOperationType() == CGOpCode::ArrayCreation) {
962 const std::vector<Argument<Base> >& args = node.getArguments();
963 size_t arg_size = args.size();
964 std::vector<Argument<Base> > cloneArgs(arg_size);
966 for (
size_t a = 0; a < arg_size; a++) {
967 OperationNode<Base>* argOp = args[a].getOperation();
968 if (argOp ==
nullptr) {
970 cloneArgs[a] = *args[a].getParameter();
973 if (argOp->getOperationType() == CGOpCode::Inv) {
974 cloneArgs[a] = createIndependentClone(&node, a, *argOp);
976 cloneArgs[a] = makeGraphClones(eq, *argOp);
981 OperationNode<Base>* cloneOp = handler_.makeNode(node.getOperationType(),
985 clonesTemporary_[id] = cloneOp;
986 return Argument<Base>(*cloneOp);
993 return makeTemporaryVarClone(node);
997 inline OperationNode<Base>& createIndependentClone(OperationNode<Base>* operation,
998 size_t argumentIndex,
999 OperationNode<Base>& independent) {
1002 typename std::map<const OperationNode<Base>*, OperationIndexedIndependents<Base> >::const_iterator it =
indexedOpIndep.op2Arguments.find(operation);
1004 const OperationIndexedIndependents<Base>& yyy = it->second;
1006 if (!yyy.arg2Independents[argumentIndex].empty()) {
1008 return getIndexedIndependentClone(operation, argumentIndex);
1013 return getNonIndexedIndependentClone(independent);
1016 OperationNode<Base>& getIndexedIndependentClone(
const OperationNode<Base>* operation,
1018 CPPADCG_ASSERT_UNKNOWN(operation ==
nullptr || operation->getArguments().size() > argIndex)
1019 CPPADCG_ASSERT_UNKNOWN(operation ==
nullptr || operation->getArguments()[argIndex].getOperation() !=
nullptr)
1020 CPPADCG_ASSERT_UNKNOWN(operation ==
nullptr || operation->getArguments()[argIndex].getOperation()->getOperationType() == CGOpCode::Inv)
1022 OperationArgumentsIndepOrder<Base>* args2Order = op2Arg2IndepOrder_.at(operation);
1023 IndependentOrder<Base>* indepOrder = args2Order->arg2Order.at(argIndex);
1025 typename std::map<const IndependentOrder<Base>*, OperationNode<Base>*>::const_iterator it;
1026 it = indexedIndep2clone_.find(indepOrder);
1027 if (it != indexedIndep2clone_.end()) {
1032 independentsIndexed_[newIndep.getOperationNode()] = IndexValue(nIndependents_, newIndep);
1035 OperationNode<Base>* clone = newIndep.getOperationNode();
1036 indexedIndep2clone_[indepOrder] = clone;
1041 OperationNode<Base>& getNonIndexedIndependentClone(
const OperationNode<Base>& node) {
1042 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() == CGOpCode::Inv)
1044 typename std::map<const OperationNode<Base>*, OperationNode<Base>*>::iterator it;
1045 it = orig2ConstIndepClone_.find(&node);
1046 if (it != orig2ConstIndepClone_.end()) {
1052 independentsNonIndexed_[newIndep.getOperationNode()] = IndexValue(nIndependents_, newIndep);
1055 OperationNode<Base>* clone = newIndep.getOperationNode();
1056 orig2ConstIndepClone_[&node] = clone;
1066 OperationNode<Base>& makeTemporaryVarClone(OperationNode<Base>& node) {
1067 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::Inv)
1068 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::ArrayCreation)
1069 CPPADCG_ASSERT_UNKNOWN(node.getOperationType() != CGOpCode::SparseArrayCreation)
1073 OperationNode<Base>* cloneOp = newIndep.getOperationNode();
1075 temporaryClone2Orig_[cloneOp] = &node;
1076 independentsTemp_[cloneOp] = IndexValue(nIndependents_, newIndep);
1079 size_t id = idCounter_++;
1080 clonesTemporary_[id] = cloneOp;
1081 (*varId_)[node] = id;
1089 class DependentIndexSorter {
1091 const EquationGroup<Base>& group;
1092 const std::map<EquationPattern<Base>*, std::vector<size_t> >& freeDependents;
1093 const std::map<size_t, EquationPattern<Base>*>& dep2Equation;
1094 std::set<EquationPattern<Base>*> visitedEq;
1097 inline DependentIndexSorter(
const EquationGroup<Base>& g,
1098 const std::map<EquationPattern<Base>*, std::vector<size_t> >& f,
1099 const std::map<
size_t, EquationPattern<Base>*>& d2e) :
1113 inline std::pair<size_t, EquationPattern<Base>*> findBestDependentForIteration(
size_t dep, EquationPattern<Base>* eq) {
1115 return findBestDependent(dep, eq);
1120 inline size_t findRelativeFreeDependentInEq(EquationPattern<Base>* eq,
size_t dep) {
1122 const std::vector<size_t>& eqFreeDep = freeDependents.at(eq);
1123 for (
size_t depRelPos = 0; depRelPos < eqFreeDep.size(); depRelPos++) {
1124 if (eqFreeDep[depRelPos] == dep)
1129 return eqFreeDep.size();
1139 inline std::pair<size_t, EquationPattern<Base>*> findBestDependent(
size_t dep, EquationPattern<Base>* eq) {
1140 visitedEq.insert(eq);
1142 auto best = std::make_pair(dep, eq);
1145 long pos = group.findIndexedLinkedDependent(dep);
1147 size_t depRelPos = findRelativeFreeDependentInEq(eq, dep);
1151 for (
size_t dep2 : group.linkedDependents[pos]) {
1152 EquationPattern<Base>* eq2 = dep2Equation.at(dep2);
1153 if (visitedEq.find(eq2) != visitedEq.end())
continue;
1155 size_t dep2RelPos = findRelativeFreeDependentInEq(eq2, dep2);
1156 if (dep2RelPos > depRelPos) {
1159 best = std::make_pair(dep2, eq2);
1160 depRelPos = dep2RelPos;
1164 if (best.first != dep) {
1165 size_t bestDep = *freeDependents.at(best.second).begin();
1166 return findBestDependent(bestDep, best.second);
1179 struct IndexedIndepSorter {
1180 const std::map<const OperationNode<Base>*,
const IndependentOrder<Base>*>& clone2indexedIndep;
1182 IndexedIndepSorter(
const std::map<
const OperationNode<Base>*,
const IndependentOrder<Base>*>& clone2indexedIndep_) :
1183 clone2indexedIndep(clone2indexedIndep_) {
1186 bool operator()(
const OperationNode<Base>* node1,
1187 const OperationNode<Base>* node2) {
1188 const IndependentOrder<Base>* indepOrder1 = clone2indexedIndep.at(node1);
1189 const IndependentOrder<Base>* indepOrder2 = clone2indexedIndep.at(node2);
1190 CPPADCG_ASSERT_UNKNOWN(indepOrder1->order.size() == indepOrder2->order.size())
1192 size_t size = indepOrder1->order.size();
1193 for (
size_t j = 0; j < size; j++) {
1194 const OperationNode<Base>* indep1 = indepOrder1->order[j];
1195 const OperationNode<Base>* indep2 = indepOrder2->order[j];
1197 if (indep1 ==
nullptr) {
1198 if (indep2 ==
nullptr) {
1202 }
else if (indep2 ==
nullptr) {
1206 size_t index1 = indep1->getInfo()[0];
1207 size_t index2 = indep2->getInfo()[0];
1208 if (index1 < index2)
1210 else if (index1 > index2)
1214 CPPADCG_ASSERT_UNKNOWN(
false)
void makeVariable(AD< CGB > &variable)
std::vector< std::set< size_t > > linkedDependents
std::set< EquationPattern< Base > * > equations
std::vector< std::set< EquationPattern< Base > * > > linkedEquationsByNonIndexedRel
std::vector< std::set< size_t > > iterationDependents
IndexedIndependent< Base > indexedOpIndep
std::map< size_t, std::map< const OperationNode< Base > *, OperationNode< Base > * > > operationEO2Reference
void createLoopModel(const std::vector< CG< Base > > &dependents, const std::vector< CG< Base > > &independents, const std::map< size_t, EquationPattern< Base > * > &dep2Equation, std::map< OperationNode< Base > *, size_t > &origTemp2Index)
void merge(Loop< Base > &other, const std::set< EquationPattern< Base > * > &indexedLoopRelations, const std::vector< std::pair< EquationPattern< Base > *, EquationPattern< Base > * > > &nonIndexedLoopRelations)
size_t getIterationCount() const
std::set< EquationPattern< Base > * > equations
void generateDependentLoopIndexes(const std::map< size_t, EquationPattern< Base > * > &dep2Equation)
IndexedIndependent< Base > indexedOpIndep
void mergeEqGroups(Loop< Base > &other)
std::vector< MapDep2Indep_type > arg2Independents