CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
code_handler.hpp
1#ifndef CPPAD_CG_CODE_HANDLER_INCLUDED
2#define CPPAD_CG_CODE_HANDLER_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2012 Ciengis
6 *
7 * CppADCodeGen is distributed under multiple licenses:
8 *
9 * - Eclipse Public License Version 1.0 (EPL1), and
10 * - GNU General Public License Version 3 (GPL3).
11 *
12 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14 * ----------------------------------------------------------------------------
15 * Author: Joao Leal
16 */
17
18namespace CppAD {
19namespace cg {
20
27template<class Base>
29 friend class CodeHandlerVectorSync<Base>;
30public:
32 using SourceCodePath = std::vector<PathNode>;
33 using ScopePath = std::vector<ScopePathElement<Base> >;
35 using Arg = Argument<Base>;
36 using CGB = CG<Base>;
37 using ScopeIDType = unsigned short;
38protected:
39 struct LoopData; // forward declaration
40
41protected:
42 // counter used to determine visitation IDs for the operation tree
43 size_t _idVisit;
44 // counter used to generate variable IDs
45 size_t _idCount;
46 // counter used to generate array variable IDs
47 size_t _idArrayCount;
48 // counter used to generate sparse array variable IDs
49 size_t _idSparseArrayCount;
50 // counter used to generate IDs for atomic functions
51 size_t _idAtomicCount;
52 // the independent variables
53 std::vector<Node *> _independentVariables;
54 // the current dependent variables
55 ArrayView<CGB>* _dependents;
60 std::vector<Node*> _codeBlocks;
64 std::set<CodeHandlerVectorSync<Base>*> _managedVectors;
102 std::vector<Node*> _variableOrder;
106 std::vector<std::set<Node*>> _variableDependencies;
111 std::vector<std::vector<Node*> > _scopedVariableOrder;
115 LoopData _loops;
119 std::map<size_t, CGAbstractAtomicFun<Base>*> _atomicFunctions;
124 std::map<std::string, size_t> _atomicFunctionName2Index;
129 std::vector<std::string>* _atomicFunctionsOrder;
140 // a flag indicating if this handler was previously used to generate code
141 bool _used;
142 // a flag indicating whether or not to reuse the IDs of destroyed variables
143 bool _reuseIDs;
144 // scope color/index counter
145 ScopeIDType _scopeColorCount;
146 // the current scope color/index counter
147 ScopeIDType _currentScopeColor;
148 // all scopes
149 std::vector<ScopePath> _scopes;
150 // possible altered nodes due to scope conditionals (altered node <-> clone of original)
151 std::list<std::pair<Node*, Node* > > _alteredNodes;
152 // the language used for source code generation
153 Language<Base>* _lang;
154 // the lowest ID used for temporary variables
155 size_t _minTemporaryVarID;
161 //
162 bool _verbose;
175public:
176
177 CodeHandler(size_t varCount = 50);
178
179 CodeHandler(const CodeHandler&) = delete;
180
181 CodeHandler& operator=(const CodeHandler&) = delete;
182
186 inline virtual ~CodeHandler();
187
192 inline void setReuseVariableIDs(bool reuse);
193
198 inline bool isReuseVariableIDs() const;
199
206 template<class VectorCG>
207 inline void makeVariables(VectorCG& variables) {
208 for (size_t i = 0; i < variables.size(); i++) {
209 makeVariable(variables[i]);
210 }
211 }
212
219 inline void makeVariables(std::vector<AD<CGB> >& variables);
220
227 inline void makeVariable(AD<CGB>& variable);
228
235 inline void makeVariable(CGB& variable);
236
240 size_t getIndependentVariableSize() const;
241
245 size_t getIndependentVariableIndex(const Node& var) const;
246
254
255 inline size_t getMaximumVariableID() const;
256
257 inline bool isVerbose() const;
258
259 inline void setVerbose(bool verbose);
260
261 inline JobTimer* getJobTimer() const;
262
263 inline void setJobTimer(JobTimer* jobTimer);
264
271 inline bool isZeroDependents() const;
272
279 inline void setZeroDependents(bool zeroDependents);
280
281 inline size_t getOperationTreeVisitId() const;
282
283 inline void startNewOperationTreeVisit();
284
285 inline bool isVisited(const Node& node) const;
286
287 inline void markVisited(const Node& node);
288
296 inline std::string getAtomicFunctionName(size_t id) const;
297
304 inline const std::map<size_t, CGAbstractAtomicFun<Base>* >& getAtomicFunctions() const;
305
311 const std::vector<int>& getExternalFuncMaxForwardOrder() const;
312
318 const std::vector<int>& getExternalFuncMaxReverseOrder() const;
319
327 inline const std::string* getLoopName(size_t id) const;
328
329 inline const std::vector<ScopePath>& getScopes() const;
330
331 /**************************************************************************
332 * Graph management functions
333 *************************************************************************/
342 inline std::vector<SourceCodePath> findPaths(Node& root,
343 Node& target,
344 size_t max);
345
346 inline BidirGraph<Base> findPathGraph(Node& root,
347 Node& target) ;
348
349 inline BidirGraph<Base> findPathGraph(Node& root,
350 Node& target,
351 size_t& bifurcations,
352 size_t maxBifurcations = (std::numeric_limits<size_t>::max)());
353
354 /**************************************************************************
355 * Source code generation
356 *************************************************************************/
357
369 virtual void generateCode(std::ostream& out,
370 Language<Base>& lang,
371 CppAD::vector<CGB>& dependent,
373 const std::string& jobName = "source");
374
375 virtual void generateCode(std::ostream& out,
376 Language<Base>& lang,
377 std::vector<CGB>& dependent,
379 const std::string& jobName = "source");
380
381 virtual void generateCode(std::ostream& out,
382 Language<Base>& lang,
383 ArrayView<CGB>& dependent,
385 const std::string& jobName = "source");
386
399 virtual void generateCode(std::ostream& out,
400 Language<Base>& lang,
401 CppAD::vector<CGB>& dependent,
403 std::vector<std::string>& atomicFunctions,
404 const std::string& jobName = "source");
405
406 virtual void generateCode(std::ostream& out,
407 Language<Base>& lang,
408 std::vector<CGB>& dependent,
410 std::vector<std::string>& atomicFunctions,
411 const std::string& jobName = "source");
412
413 virtual void generateCode(std::ostream& out,
414 Language<Base>& lang,
415 ArrayView<CGB>& dependent,
417 std::vector<std::string>& atomicFunctions,
418 const std::string& jobName = "source");
419
420 size_t getTemporaryVariableCount() const;
421
422 size_t getTemporaryArraySize() const;
423
424 size_t getTemporarySparseArraySize() const;
425
426 /**************************************************************************
427 * Reusing handler and nodes
428 *************************************************************************/
429
434 virtual void reset();
435
440 inline void resetNodes();
441
442 /**************************************************************************
443 * access to managed memory
444 *************************************************************************/
445
449 inline Node* cloneNode(const Node& n);
450
451 inline Node* makeNode(CGOpCode op);
452
453 inline Node* makeNode(CGOpCode op,
454 const Arg& arg);
455
456 inline Node* makeNode(CGOpCode op,
457 std::vector<Arg>&& args);
458
459 inline Node* makeNode(CGOpCode op,
460 std::vector<size_t>&& info,
461 std::vector<Arg>&& args);
462
463 inline Node* makeNode(CGOpCode op,
464 const std::vector<size_t>& info,
465 const std::vector<Arg>& args);
466
467 inline LoopStartOperationNode<Base>* makeLoopStartNode(Node& indexDcl,
468 size_t iterationCount);
469
470 inline LoopStartOperationNode<Base>* makeLoopStartNode(Node& indexDcl,
471 IndexOperationNode<Base>& iterCount);
472
473 inline LoopEndOperationNode<Base>* makeLoopEndNode(LoopStartOperationNode<Base>& loopStart,
474 const std::vector<Arg >& endArgs);
475
476 inline PrintOperationNode<Base>* makePrintNode(const std::string& before,
477 const Arg& arg,
478 const std::string& after);
479
480 inline IndexOperationNode<Base>* makeIndexNode(Node& indexDcl);
481
482 inline IndexOperationNode<Base>* makeIndexNode(LoopStartOperationNode<Base>& loopStart);
483
484 inline IndexOperationNode<Base>* makeIndexNode(IndexAssignOperationNode<Base>& indexAssign);
485
486 inline IndexAssignOperationNode<Base>* makeIndexAssignNode(Node& index,
487 IndexPattern& indexPattern,
489
490 inline IndexAssignOperationNode<Base>* makeIndexAssignNode(Node& index,
491 IndexPattern& indexPattern,
494
495 inline Node* makeIndexDclrNode(const std::string& name);
496
505 inline size_t getManagedNodesCount() const;
506
510 inline const std::vector<Node *>& getManagedNodes() const;
511
519 inline void deleteManagedNodes(size_t start,
520 size_t end);
521
522 /**************************************************************************
523 * Value generation
524 *************************************************************************/
525 CGB createCG(const Arg& arg);
526
527 /**************************************************************************
528 * Loop management
529 *************************************************************************/
530
531 const std::map<size_t, LoopModel<Base>*>& getLoops() const;
532
533 inline LoopModel<Base>* getLoop(size_t loopId) const;
534
535 inline size_t addLoopDependentIndexPattern(IndexPattern& jacPattern);
536
537 inline void manageLoopDependentIndexPattern(const IndexPattern* pattern);
538
539 inline size_t addLoopIndependentIndexPattern(IndexPattern& pattern, size_t hint);
540
541 /***********************************************************************
542 * Index patterns
543 **********************************************************************/
544 static inline void findRandomIndexPatterns(IndexPattern* ip,
545 std::set<RandomIndexPattern*>& found);
546
547 /**************************************************************************
548 * Operation graph manipulation
549 *************************************************************************/
550
559 inline CGB solveFor(Node& expression,
560 Node& var);
561
562 inline bool isSolvable(Node& expression,
563 Node& var);
564
579 inline void substituteIndependent(const CGB& indep,
580 const CGB& dep,
581 bool removeFromIndeps = true);
582
583 inline void substituteIndependent(Node& indep,
584 Node& dep,
585 bool removeFromIndeps = true);
586
595 inline void undoSubstituteIndependent(Node& indep);
596
605 inline void removeIndependent(Node& indep);
606
615 inline bool manageOperationNodeMemory(Node* code);
616
617protected:
618
619 virtual Node* manageOperationNode(Node* code);
620
621 inline void addVector(CodeHandlerVectorSync<Base>* v);
622
623 inline void removeVector(CodeHandlerVectorSync<Base>* v);
624
625 virtual void markCodeBlockUsed(Node& code);
626
627 inline bool handleTemporaryVarInDiffScopes(Node& code,
628 size_t oldScope, size_t newScope);
629
630 inline void replaceWithConditionalTempVar(Node& tmp,
631 IndexOperationNode<Base>& iterationIndexOp,
632 const std::vector<size_t>& iterationRegions,
633 ScopeIDType oldScope,
634 ScopeIDType commonScopeColor);
635
636 inline void updateTemporaryVarInDiffScopes(Node& code);
637
638 inline void restoreTemporaryVar(Node& tmp);
639
640 inline void restoreTemporaryVar(Node* tmp,
641 Node* opClone);
642
643 inline void updateVarScopeUsage(Node* node,
644 ScopeIDType usageScope,
645 ScopeIDType oldUsageScope);
646
647 inline void addScopeToVarOrder(size_t scope,
648 size_t& e);
649
658 inline size_t findFirstDifferentScope(size_t color1,
659 size_t color2);
660
665 inline void optimizeIfs();
666
667 inline void replaceScope(Node* node,
668 ScopeIDType oldScope,
669 ScopeIDType newScope);
670
679 inline void breakCyclicDependency(Node* node,
680 size_t scope,
681 Node* endIf);
682
683 inline bool containedInScope(const Node& node,
684 ScopeIDType scope);
685
686 inline static bool containsArgument(const Node& node,
687 const Node& arg);
688
689 virtual void registerAtomicFunction(CGAbstractAtomicFun<Base>& atomic);
690
691 /***********************************************************************
692 *
693 **********************************************************************/
694 virtual void checkVariableCreation(Node& code);
695
696 inline void addToEvaluationQueue(Node& arg);
697
698 inline void reduceTemporaryVariables(ArrayView<CGB>& dependent);
699
705 inline void reorderOperations(ArrayView<CGB>& dependent);
706
707 inline void reorderOperation(Node& node);
708
716 inline size_t findLastTemporaryLocation(Node& node);
717
718 inline void repositionEvaluationQueue(size_t fromPos,
719 size_t toPos);
720
727 inline void determineLastTempVarUsage(Node& node);
728
732 inline void findVariableDependencies();
733
734 inline void findVariableDependencies(size_t i,
735 Node& node);
736
742 inline void dependentAdded2EvaluationQueue(Node& node);
743
744 inline void updateEvaluationQueueOrder(Node& node,
745 size_t newEvalOrder);
746
747 inline bool isIndependent(const Node& arg) const;
748
749 inline bool isTemporary(const Node& arg) const;
750
751 inline static bool isTemporaryArray(const Node& arg);
752
753 inline static bool isTemporarySparseArray(const Node& arg);
754
755 inline static Node* getOperationFromAlias(Node& alias);
756
757 inline size_t getEvaluationOrder(const Node& node) const;
758
759 inline void setEvaluationOrder(Node& node,
760 size_t order);
761
762 inline size_t getLastUsageEvaluationOrder(const Node& node) const;
763
764 inline void setLastUsageEvaluationOrder(const Node& node,
765 size_t last);
766
772 inline size_t getTotalUsageCount(const Node& node) const;
773
774 inline void setTotalUsageCount(const Node& node,
775 size_t cout);
776
777 inline void increaseTotalUsageCount(const Node& node);
778
779 inline void resetManagedNodes();
780
781 /**************************************************************************
782 * Graph management functions
783 *************************************************************************/
784
785 inline void findPaths(SourceCodePath& path2node,
786 Node& code,
787 std::vector<SourceCodePath>& found,
788 size_t max);
789
790 static inline std::vector<SourceCodePath> findPathsFromNode(const std::vector<SourceCodePath> nodePaths,
791 Node& node);
792
793 /**************************************************************************
794 * Operation graph manipulation
795 *************************************************************************/
805 inline CGB solveFor(const SourceCodePath& path);
806
823 inline CGB collectVariable(Node& expression,
824 const SourceCodePath& path1,
825 const SourceCodePath& path2,
826 size_t bifPos);
827
828 inline CGB collectVariableAddSub(const SourceCodePath& pathLeft,
829 const SourceCodePath& pathRight);
830
831 inline bool isCollectableVariableAddSub(const SourceCodePath& pathLeft,
832 const SourceCodePath& pathRight,
833 bool throwEx);
834
835 inline bool isSolvable(const SourceCodePath& path) const;
836
837 /**************************************************************************
838 * Loop related structure/methods
839 *************************************************************************/
840 struct LoopData {
841 // maps the loop ids of the loop atomic functions
842 std::map<size_t, LoopModel<Base>*> loopModels;
843 std::vector<LoopEndOperationNode<Base>*> endNodes;
844 // the used indexes
845 std::set<const Node*> indexes;
846 // the used random index patterns
847 std::set<RandomIndexPattern*> indexRandomPatterns;
848 //
849 std::vector<IndexPattern*> dependentIndexPatterns;
850 std::vector<const IndexPattern*> dependentIndexPatternManaged; // garbage collection
851 std::vector<IndexPattern*> independentIndexPatterns;
852 // variables used inside a loop which are assigned outside (for different loop depths)
853 std::vector<std::set<Node*> > outerVars;
854 // the current loop depth (-1 means no loop)
855 int depth;
856 // the evaluation order of the loop start for each loop depth
857 std::vector<size_t> startEvalOrder;
858
859 inline LoopData() :
860 depth(-1) {
861 }
862
863 inline void prepare4NewSourceGen();
864
865 inline void reset();
866
874 inline const std::string* getLoopName(size_t id) const;
875
876 inline void registerModel(LoopModel<Base>& loop);
877
878 inline LoopModel<Base>* getLoop(size_t loopId) const;
879
880 size_t addDependentIndexPattern(IndexPattern& jacPattern);
881
882 void manageDependentIndexPattern(const IndexPattern* pattern);
883
884 size_t addIndependentIndexPattern(IndexPattern& pattern, size_t hint);
885
886 void addLoopEndNode(Node& node);
887 };
888
889 /**************************************************************************
890 * friends
891 *************************************************************************/
892 friend class CG<Base>;
893 friend class CGAbstractAtomicFun<Base>;
894 friend class BaseAbstractAtomicFun<Base>;
895 friend class LoopModel<Base>;
896
897};
898
899} // END cg namespace
900} // END CppAD namespace
901
902#endif
void breakCyclicDependency(Node *node, size_t scope, Node *endIf)
void reorderOperation(Node &node)
std::string getAtomicFunctionName(size_t id) const
const std::vector< int > & getExternalFuncMaxReverseOrder() const
const std::string * getLoopName(size_t id) const
void removeIndependent(Node &indep)
Definition graph_mod.hpp:76
CodeHandlerVector< Base, size_t > _lastVisit
CodeHandlerVector< Base, size_t > _varId
size_t getIndependentVariableSize() const
bool isCollectableVariableAddSub(const SourceCodePath &pathLeft, const SourceCodePath &pathRight, bool throwEx)
virtual void markCodeBlockUsed(Node &code)
virtual void checkVariableCreation(Node &code)
size_t findLastTemporaryLocation(Node &node)
bool handleTemporaryVarInDiffScopes(Node &code, size_t oldScope, size_t newScope)
void determineLastTempVarUsage(Node &node)
std::vector< std::string > * _atomicFunctionsOrder
void makeVariables(VectorCG &variables)
size_t findFirstDifferentScope(size_t color1, size_t color2)
CodeHandlerVector< Base, size_t > _lastUsageOrder
void dependentAdded2EvaluationQueue(Node &node)
std::vector< int > _atomicFunctionsMaxReverse
const CodeHandlerVector< Base, size_t > & getVariablesIDs() const
void makeVariable(AD< CGB > &variable)
void reduceTemporaryVariables(ArrayView< CGB > &dependent)
void setZeroDependents(bool zeroDependents)
void substituteIndependent(const CGB &indep, const CGB &dep, bool removeFromIndeps=true)
Definition graph_mod.hpp:22
CodeHandlerVector< Base, size_t > _totalUseCount
std::vector< Node * > _variableOrder
CodeHandlerVector< Base, ScopeIDType > _scope
size_t getIndependentVariableIndex(const Node &var) const
std::vector< std::vector< Node * > > _scopedVariableOrder
IndexOperationNode< Base > * _auxIterationIndexOp
void restoreTemporaryVar(Node &tmp)
Node * cloneNode(const Node &n)
const std::vector< Node * > & getManagedNodes() const
virtual void generateCode(std::ostream &out, Language< Base > &lang, CppAD::vector< CGB > &dependent, VariableNameGenerator< Base > &nameGen, const std::string &jobName="source")
CGB solveFor(Node &expression, Node &var)
Definition solver.hpp:25
void deleteManagedNodes(size_t start, size_t end)
size_t getTotalUsageCount(const Node &node) const
std::vector< std::set< Node * > > _variableDependencies
void updateTemporaryVarInDiffScopes(Node &code)
std::vector< int > _atomicFunctionsMaxForward
std::vector< SourceCodePath > findPaths(Node &root, Node &target, size_t max)
CGB collectVariableAddSub(const SourceCodePath &pathLeft, const SourceCodePath &pathRight)
CodeHandlerVector< Base, size_t > _operationCount
std::map< size_t, CGAbstractAtomicFun< Base > * > _atomicFunctions
void setReuseVariableIDs(bool reuse)
void undoSubstituteIndependent(Node &indep)
Definition graph_mod.hpp:65
size_t getManagedNodesCount() const
CodeHandlerVector< Base, size_t > _evaluationOrder
const std::vector< int > & getExternalFuncMaxForwardOrder() const
std::vector< Node * > _codeBlocks
void replaceWithConditionalTempVar(Node &tmp, IndexOperationNode< Base > &iterationIndexOp, const std::vector< size_t > &iterationRegions, ScopeIDType oldScope, ScopeIDType commonScopeColor)
bool manageOperationNodeMemory(Node *code)
std::set< CodeHandlerVectorSync< Base > * > _managedVectors
std::map< std::string, size_t > _atomicFunctionName2Index
void reorderOperations(ArrayView< CGB > &dependent)
CGB collectVariable(Node &expression, const SourceCodePath &path1, const SourceCodePath &path2, size_t bifPos)
const std::map< size_t, CGAbstractAtomicFun< Base > * > & getAtomicFunctions() const
const std::string * getLoopName(size_t id) const