1 #ifndef CPPAD_CG_LOOP_MODEL_INCLUDED 2 #define CPPAD_CG_LOOP_MODEL_INCLUDED 30 using Arg = Argument<Base>;
31 using pairss = std::pair<size_t, size_t>;
33 static const std::string ITERATION_INDEX_NAME;
35 static const std::set<size_t> EMPTYSET;
41 ADFun<CGB>*
const fun_;
45 const bool containsAtoms_;
49 const size_t iterationCount_;
57 std::vector<std::vector<LoopPosition> > dependentIndexes_;
61 std::vector<std::vector<LoopPosition> > indexedIndepIndexes_;
65 std::vector<LoopPosition> nonIndexedIndepIndexes_;
70 std::vector<LoopPosition> temporaryIndependents_;
75 std::map<size_t, LoopIndexedPosition> depOrigIndexes_;
79 std::vector<IterEquationGroup<Base> > equationGroups_;
80 std::vector<std::set<const IterEquationGroup<Base>*> > iteration2eqGroups_;
84 std::vector<std::map<size_t, std::set<size_t> > > iteration2orig2indexedIndepIndexes_;
88 std::map<size_t, LoopPosition*> orig2nonIndexedIndepIndexes_;
92 std::map<size_t, LoopPosition*> orig2tempIndepIndexes_;
96 std::vector<IndexPattern*> indepIndexPatterns_;
100 std::vector<IndexPattern*> depIndexPatterns_;
104 std::vector<std::set<size_t> > jacTapeSparsity_;
109 std::vector<std::set<size_t> > hessTapeSparsity_;
127 size_t iterationCount,
128 const std::vector<std::vector<size_t> >& dependentOrigIndexes,
129 const std::vector<std::vector<size_t> >& indexedIndepOrigIndexes,
130 const std::vector<size_t>& nonIndexedIndepOrigIndexes,
131 const std::vector<size_t>& temporaryIndependents) :
132 loopId_(createNewLoopId()),
134 containsAtoms_(containsAtoms),
135 iterationCount_(iterationCount),
136 m_(dependentOrigIndexes.size()),
139 nonIndexedIndepIndexes_(nonIndexedIndepOrigIndexes.size()),
140 temporaryIndependents_(temporaryIndependents.size()),
141 iteration2orig2indexedIndepIndexes_(iterationCount),
143 hessSparsity_(false) {
144 CPPADCG_ASSERT_KNOWN(fun !=
nullptr,
"fun cannot be null");
149 for (
size_t i = 0; i < m_; i++) {
150 for (
size_t it = 0; it < iterationCount_; it++) {
151 size_t orig = dependentOrigIndexes[i][it];
153 if (orig != (std::numeric_limits<size_t>::max)())
155 dependentIndexes_[i][it].original,
165 size_t lm = dependentIndexes_.size();
167 for (
size_t i = 0; i < lm; i++) {
168 std::set<size_t> iterations;
169 for (
size_t it = 0; it < iterationCount_; it++) {
170 if (dependentIndexes_[i][it].original != (std::numeric_limits<size_t>::max)()) {
171 iterations.insert(it);
174 iterations2equations[iterations].insert(i);
177 equationGroups_.resize(iterations2equations.size());
178 iteration2eqGroups_.resize(iterationCount_);
182 for (itEqeIt = iterations2equations.begin(); itEqeIt != iterations2equations.end(); ++itEqeIt, g++) {
183 const std::set<size_t>& iterations = itEqeIt->first;
187 group.
tapeI = itEqeIt->second;
192 for (
size_t itIt : iterations) {
193 iteration2eqGroups_[itIt].insert(&group);
200 size_t nIndexed = indexedIndepOrigIndexes.size();
203 for (
size_t it = 0; it < iterationCount_; it++) {
204 for (
size_t j = 0; j < nIndexed; j++) {
205 size_t orig = indexedIndepOrigIndexes[j][it];
207 if (orig != (std::numeric_limits<size_t>::max)())
208 iteration2orig2indexedIndepIndexes_[it][orig].insert(j);
213 size_t nNonIndexed = nonIndexedIndepOrigIndexes.size();
214 for (
size_t j = 0; j < nNonIndexed; j++) {
215 size_t orig = nonIndexedIndepOrigIndexes[j];
216 nonIndexedIndepIndexes_[j] =
LoopPosition(nIndexed + j, orig);
217 orig2nonIndexedIndepIndexes_[orig] = &nonIndexedIndepIndexes_[j];
221 for (
size_t j = 0; j < temporaryIndependents.size(); j++) {
222 size_t k = temporaryIndependents[j];
223 temporaryIndependents_[j] =
LoopPosition(nIndexed + nNonIndexed + j, k);
224 orig2tempIndepIndexes_[k] = &temporaryIndependents_[j];
246 return containsAtoms_;
255 return iterationCount_;
285 return fun_->Domain();
292 return dependentIndexes_;
299 return equationGroups_;
302 inline const std::vector<std::set<const IterEquationGroup<Base>*> >& getIterationEquationsGroup()
const {
303 return iteration2eqGroups_;
310 return indexedIndepIndexes_;
317 return nonIndexedIndepIndexes_;
325 return temporaryIndependents_;
335 return depOrigIndexes_.at(origI);
338 inline const std::map<size_t, LoopIndexedPosition>& getOriginalDependentIndexes()
const {
339 return depOrigIndexes_;
346 std::map<size_t, LoopPosition*>::const_iterator it = orig2nonIndexedIndepIndexes_.find(origJ);
347 if (it != orig2nonIndexedIndepIndexes_.end()) {
358 std::map<size_t, LoopPosition*>::const_iterator it = orig2tempIndepIndexes_.find(k);
359 if (it != orig2tempIndepIndexes_.end()) {
375 CPPADCG_ASSERT_UNKNOWN(iteration < iteration2orig2indexedIndepIndexes_.size());
377 const std::map<size_t, std::set<size_t> >& itOrigs = iteration2orig2indexedIndepIndexes_[iteration];
378 std::map<size_t, std::set<size_t> >::const_iterator it = itOrigs.find(origJ);
379 if (it != itOrigs.end()) {
394 std::map<size_t, std::set<size_t> > iter2TapeJs;
396 for (
size_t iter = 0; iter < iterationCount_; iter++) {
397 const std::map<size_t, std::set<size_t> >& itOrigs = iteration2orig2indexedIndepIndexes_[iter];
398 std::map<size_t, std::set<size_t> >::const_iterator it = itOrigs.find(origJ);
399 if (it != itOrigs.end()) {
400 iter2TapeJs[iter] = it->second;
407 inline void detectIndexPatterns() {
408 if (indepIndexPatterns_.size() > 0)
411 indepIndexPatterns_.resize(indexedIndepIndexes_.size());
412 for (
size_t j = 0; j < indepIndexPatterns_.size(); j++) {
413 std::map<size_t, size_t> indexes;
414 for (
size_t it = 0; it < iterationCount_; it++) {
415 size_t orig = indexedIndepIndexes_[j][it].original;
416 if (orig != (std::numeric_limits<size_t>::max)())
422 depIndexPatterns_.resize(dependentIndexes_.size());
423 for (
size_t j = 0; j < depIndexPatterns_.size(); j++) {
424 std::map<size_t, size_t> indexes;
425 for (
size_t it = 0; it < iterationCount_; it++) {
426 size_t e = dependentIndexes_[j][it].original;
427 if (e != (std::numeric_limits<size_t>::max)())
435 inline const std::vector<IndexPattern*>& getDependentIndexPatterns()
const {
436 return depIndexPatterns_;
439 inline const std::vector<IndexPattern*>& getIndependentIndexPatterns()
const {
440 return indepIndexPatterns_;
443 inline bool isTemporary(
size_t tapeJ)
const {
444 size_t nIndexed = indexedIndepIndexes_.size();
445 size_t nNonIndexed = nonIndexedIndepIndexes_.size();
447 return nIndexed + nNonIndexed <= tapeJ;
450 inline bool isIndexedIndependent(
size_t tapeJ)
const {
451 return tapeJ < indexedIndepIndexes_.size();
454 inline void evalJacobianSparsity() {
456 jacTapeSparsity_ = jacobianSparsitySet<std::vector<std::set<size_t> >,
CGB>(*fun_);
461 inline const std::vector<std::set<size_t> >& getJacobianSparsity()
const {
462 return jacTapeSparsity_;
465 inline void evalHessianSparsity() {
466 if (!hessSparsity_) {
467 size_t n = fun_->Domain();
468 hessTapeSparsity_.resize(n);
470 for (
size_t g = 0; g < equationGroups_.size(); g++) {
471 equationGroups_[g].evalHessianSparsity();
472 const std::vector<std::set<size_t> >& ghess = equationGroups_[g].getHessianSparsity();
473 for (
size_t j = 0; j < n; j++) {
474 hessTapeSparsity_[j].insert(ghess[j].begin(), ghess[j].end());
478 hessSparsity_ =
true;
482 inline const std::vector<std::set<size_t> >& getHessianSparsity()
const {
483 return hessTapeSparsity_;
488 for (
size_t i = 0; i < indepIndexPatterns_.size(); i++) {
489 delete indepIndexPatterns_[i];
491 for (
size_t i = 0; i < depIndexPatterns_.size(); i++) {
492 delete depIndexPatterns_[i];
496 static inline void printOriginalVariableIndexes(std::ostringstream& ss,
497 const std::vector<LoopPosition>& indexes) {
498 for (
size_t iter = 0; iter < indexes.size(); iter++) {
499 if (iter > 0) ss <<
", ";
500 ss << indexes[iter].original;
506 static size_t createNewLoopId() {
507 CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
508 static size_t count = 0;
const std::set< size_t > & getIndexedTapeIndexes(size_t iteration, size_t origJ) const
std::map< size_t, std::set< size_t > > getIndexedTapeIndexes(size_t origJ) const
const LoopPosition * getNonIndexedIndepIndexes(size_t origJ) const
const std::vector< LoopPosition > & getTemporaryIndependents() const
size_t index
iteration group index/ID
size_t getTapeDependentCount() const
LoopModel(ADFun< CGB > *fun, bool containsAtoms, size_t iterationCount, const std::vector< std::vector< size_t > > &dependentOrigIndexes, const std::vector< std::vector< size_t > > &indexedIndepOrigIndexes, const std::vector< size_t > &nonIndexedIndepOrigIndexes, const std::vector< size_t > &temporaryIndependents)
const LoopIndexedPosition & getTapeDependentIndex(size_t origI) const
ADFun< CGB > & getTape() const
bool isContainsAtomics() const
static IndexPattern * detect(const VectorSizeT &x2y)
const LoopPosition * getTempIndepIndexes(size_t k) const
const std::vector< LoopPosition > & getNonIndexedIndepIndexes() const
const size_t getIterationCount() const
const std::vector< IterEquationGroup< Base > > & getEquationsGroups() const
const std::vector< std::vector< LoopPosition > > & getDependentIndexes() const
const std::vector< std::vector< LoopPosition > > & getIndexedIndepIndexes() const
std::set< size_t > tapeI
equations indexes in tape of the loop model
size_t getTapeIndependentCount() const
std::set< size_t > iterations
iterations which only have these equations defined