CppADCodeGen  2.3.0
A C++ Algorithmic Differentiation Package with Source Code Generation
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 
18 namespace CppAD {
19 namespace cg {
20 
27 template<class Base>
28 class CodeHandler {
29  friend class CodeHandlerVectorSync<Base>;
30 public:
32  using SourceCodePath = std::vector<PathNode>;
33  using ScopePath = std::vector<ScopePathElement<Base> >;
34  using Node = OperationNode<Base>;
35  using Arg = Argument<Base>;
36  using CGB = CG<Base>;
37  using ScopeIDType = unsigned short;
38 protected:
39  struct LoopData; // forward declaration
40 
41 protected:
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;
96  std::vector<Node*> _variableOrder;
100  std::vector<std::set<Node*>> _variableDependencies;
105  std::vector<std::vector<Node*> > _scopedVariableOrder;
109  LoopData _loops;
113  std::map<size_t, CGAbstractAtomicFun<Base>*> _atomicFunctions;
118  std::map<std::string, size_t> _atomicFunctionName2Index;
123  std::vector<std::string>* _atomicFunctionsOrder;
127  std::map<size_t, size_t> _atomicFunctionId2Index;
132  std::vector<int> _atomicFunctionsMaxForward;
137  std::vector<int> _atomicFunctionsMaxReverse;
138  // a flag indicating if this handler was previously used to generate code
139  bool _used;
140  // a flag indicating whether or not to reuse the IDs of destroyed variables
141  bool _reuseIDs;
142  // scope color/index counter
143  ScopeIDType _scopeColorCount;
144  // the current scope color/index counter
145  ScopeIDType _currentScopeColor;
146  // all scopes
147  std::vector<ScopePath> _scopes;
148  // possible altered nodes due to scope conditionals (altered node <-> clone of original)
149  std::list<std::pair<Node*, Node* > > _alteredNodes;
150  // the language used for source code generation
151  Language<Base>* _lang;
155  std::unique_ptr<LanguageGenerationData<Base> > _info;
156  // the lowest ID used for temporary variables
157  size_t _minTemporaryVarID;
163  //
164  bool _verbose;
177 public:
178 
179  CodeHandler(size_t varCount = 50);
180 
181  CodeHandler(const CodeHandler&) = delete;
182 
183  CodeHandler& operator=(const CodeHandler&) = delete;
184 
188  inline virtual ~CodeHandler();
189 
194  inline void setReuseVariableIDs(bool reuse);
195 
200  inline bool isReuseVariableIDs() const;
201 
208  template<class VectorCG>
209  inline void makeVariables(VectorCG& variables) {
210  for (size_t i = 0; i < variables.size(); i++) {
211  makeVariable(variables[i]);
212  }
213  }
214 
221  inline void makeVariables(std::vector<AD<CGB> >& variables);
222 
229  inline void makeVariable(AD<CGB>& variable);
230 
237  inline void makeVariable(CGB& variable);
238 
242  size_t getIndependentVariableSize() const;
243 
247  size_t getIndependentVariableIndex(const Node& var) const;
248 
255  inline const CodeHandlerVector<Base, size_t>& getVariablesIDs() const;
256 
257  inline size_t getMaximumVariableID() const;
258 
259  inline bool isVerbose() const;
260 
261  inline void setVerbose(bool verbose);
262 
263  inline JobTimer* getJobTimer() const;
264 
265  inline void setJobTimer(JobTimer* jobTimer);
266 
273  inline bool isZeroDependents() const;
274 
281  inline void setZeroDependents(bool zeroDependents);
282 
283  inline size_t getOperationTreeVisitId() const;
284 
285  inline void startNewOperationTreeVisit();
286 
287  inline bool isVisited(const Node& node) const;
288 
289  inline void markVisited(const Node& node);
290 
298  inline const std::string* getAtomicFunctionName(size_t id) const;
299 
306  inline const std::map<size_t, CGAbstractAtomicFun<Base>* >& getAtomicFunctions() const;
307 
313  const std::vector<int>& getExternalFuncMaxForwardOrder() const;
314 
320  const std::vector<int>& getExternalFuncMaxReverseOrder() const;
321 
329  inline const std::string* getLoopName(size_t id) const;
330 
331  inline const std::vector<ScopePath>& getScopes() const;
332 
333  /**************************************************************************
334  * Graph management functions
335  *************************************************************************/
344  inline std::vector<SourceCodePath> findPaths(Node& root,
345  Node& target,
346  size_t max);
347 
348  inline BidirGraph<Base> findPathGraph(Node& root,
349  Node& target) ;
350 
351  inline BidirGraph<Base> findPathGraph(Node& root,
352  Node& target,
353  size_t& bifurcations,
354  size_t maxBifurcations = std::numeric_limits<size_t>::max());
355 
356  /**************************************************************************
357  * Source code generation
358  *************************************************************************/
359 
371  virtual void generateCode(std::ostream& out,
372  Language<Base>& lang,
373  CppAD::vector<CGB>& dependent,
375  const std::string& jobName = "source");
376 
377  virtual void generateCode(std::ostream& out,
378  Language<Base>& lang,
379  std::vector<CGB>& dependent,
381  const std::string& jobName = "source");
382 
383  virtual void generateCode(std::ostream& out,
384  Language<Base>& lang,
385  ArrayView<CGB>& dependent,
387  const std::string& jobName = "source");
388 
401  virtual void generateCode(std::ostream& out,
402  Language<Base>& lang,
403  CppAD::vector<CGB>& dependent,
405  std::vector<std::string>& atomicFunctions,
406  const std::string& jobName = "source");
407 
408  virtual void generateCode(std::ostream& out,
409  Language<Base>& lang,
410  std::vector<CGB>& dependent,
412  std::vector<std::string>& atomicFunctions,
413  const std::string& jobName = "source");
414 
415  virtual void generateCode(std::ostream& out,
416  Language<Base>& lang,
417  ArrayView<CGB>& dependent,
419  std::vector<std::string>& atomicFunctions,
420  const std::string& jobName = "source");
421 
422  size_t getTemporaryVariableCount() const;
423 
424  size_t getTemporaryArraySize() const;
425 
426  size_t getTemporarySparseArraySize() const;
427 
428  /**************************************************************************
429  * Reusing handler and nodes
430  *************************************************************************/
431 
436  virtual void reset();
437 
442  inline void resetNodes();
443 
444  /**************************************************************************
445  * access to managed memory
446  *************************************************************************/
447 
451  inline Node* cloneNode(const Node& n);
452 
453  inline Node* makeNode(CGOpCode op);
454 
455  inline Node* makeNode(CGOpCode op,
456  const Arg& arg);
457 
458  inline Node* makeNode(CGOpCode op,
459  std::vector<Arg>&& args);
460 
461  inline Node* makeNode(CGOpCode op,
462  std::vector<size_t>&& info,
463  std::vector<Arg>&& args);
464 
465  inline Node* makeNode(CGOpCode op,
466  const std::vector<size_t>& info,
467  const std::vector<Arg>& args);
468 
469  inline LoopStartOperationNode<Base>* makeLoopStartNode(Node& indexDcl,
470  size_t iterationCount);
471 
472  inline LoopStartOperationNode<Base>* makeLoopStartNode(Node& indexDcl,
473  IndexOperationNode<Base>& iterCount);
474 
475  inline LoopEndOperationNode<Base>* makeLoopEndNode(LoopStartOperationNode<Base>& loopStart,
476  const std::vector<Arg >& endArgs);
477 
478  inline PrintOperationNode<Base>* makePrintNode(const std::string& before,
479  const Arg& arg,
480  const std::string& after);
481 
482  inline IndexOperationNode<Base>* makeIndexNode(Node& indexDcl);
483 
484  inline IndexOperationNode<Base>* makeIndexNode(LoopStartOperationNode<Base>& loopStart);
485 
486  inline IndexOperationNode<Base>* makeIndexNode(IndexAssignOperationNode<Base>& indexAssign);
487 
488  inline IndexAssignOperationNode<Base>* makeIndexAssignNode(Node& index,
489  IndexPattern& indexPattern,
490  IndexOperationNode<Base>& index1);
491 
492  inline IndexAssignOperationNode<Base>* makeIndexAssignNode(Node& index,
493  IndexPattern& indexPattern,
494  IndexOperationNode<Base>* index1,
495  IndexOperationNode<Base>* index2);
496 
497  inline Node* makeIndexDclrNode(const std::string& name);
498 
507  inline size_t getManagedNodesCount() const;
508 
512  inline const std::vector<Node *>& getManagedNodes() const;
513 
521  inline void deleteManagedNodes(size_t start,
522  size_t end);
523 
524  /**************************************************************************
525  * Value generation
526  *************************************************************************/
527  CGB createCG(const Arg& arg);
528 
529  /**************************************************************************
530  * Loop management
531  *************************************************************************/
532 
533  const std::map<size_t, LoopModel<Base>*>& getLoops() const;
534 
535  inline LoopModel<Base>* getLoop(size_t loopId) const;
536 
537  inline size_t addLoopDependentIndexPattern(IndexPattern& jacPattern);
538 
539  inline void manageLoopDependentIndexPattern(const IndexPattern* pattern);
540 
541  inline size_t addLoopIndependentIndexPattern(IndexPattern& pattern, size_t hint);
542 
543  /***********************************************************************
544  * Index patterns
545  **********************************************************************/
546  static inline void findRandomIndexPatterns(IndexPattern* ip,
547  std::set<RandomIndexPattern*>& found);
548 
549  /**************************************************************************
550  * Operation graph manipulation
551  *************************************************************************/
552 
561  inline CGB solveFor(Node& expression,
562  Node& var);
563 
564  inline bool isSolvable(Node& expression,
565  Node& var);
566 
581  inline void substituteIndependent(const CGB& indep,
582  const CGB& dep,
583  bool removeFromIndeps = true);
584 
585  inline void substituteIndependent(Node& indep,
586  Node& dep,
587  bool removeFromIndeps = true);
588 
597  inline void undoSubstituteIndependent(Node& indep);
598 
607  inline void removeIndependent(Node& indep);
608 
617  inline bool manageOperationNodeMemory(Node* code);
618 
619 protected:
620 
621  virtual Node* manageOperationNode(Node* code);
622 
623  inline void addVector(CodeHandlerVectorSync<Base>* v);
624 
625  inline void removeVector(CodeHandlerVectorSync<Base>* v);
626 
627  virtual void markCodeBlockUsed(Node& code);
628 
629  inline bool handleTemporaryVarInDiffScopes(Node& code,
630  size_t oldScope, size_t newScope);
631 
632  inline void replaceWithConditionalTempVar(Node& tmp,
633  IndexOperationNode<Base>& iterationIndexOp,
634  const std::vector<size_t>& iterationRegions,
635  ScopeIDType oldScope,
636  ScopeIDType commonScopeColor);
637 
638  inline void updateTemporaryVarInDiffScopes(Node& code);
639 
640  inline void restoreTemporaryVar(Node& tmp);
641 
642  inline void restoreTemporaryVar(Node* tmp,
643  Node* opClone);
644 
645  inline void updateVarScopeUsage(Node* node,
646  ScopeIDType usageScope,
647  ScopeIDType oldUsageScope);
648 
649  inline void addScopeToVarOrder(size_t scope,
650  size_t& e);
651 
660  inline size_t findFirstDifferentScope(size_t color1,
661  size_t color2);
662 
667  inline void optimizeIfs();
668 
669  inline void replaceScope(Node* node,
670  ScopeIDType oldScope,
671  ScopeIDType newScope);
672 
681  inline void breakCyclicDependency(Node* node,
682  size_t scope,
683  Node* endIf);
684 
685  inline bool containedInScope(const Node& node,
686  ScopeIDType scope);
687 
688  inline static bool containsArgument(const Node& node,
689  const Node& arg);
690 
691  virtual void registerAtomicFunction(CGAbstractAtomicFun<Base>& atomic);
692 
693  /***********************************************************************
694  *
695  **********************************************************************/
696  virtual void checkVariableCreation(Node& code);
697 
698  inline void addToEvaluationQueue(Node& arg);
699 
700  inline void reduceTemporaryVariables(ArrayView<CGB>& dependent);
701 
707  inline void reorderOperations(ArrayView<CGB>& dependent);
708 
709  inline void reorderOperation(Node& node);
710 
718  inline size_t findLastTemporaryLocation(Node& node);
719 
720  inline void repositionEvaluationQueue(size_t fromPos,
721  size_t toPos);
722 
729  inline void determineLastTempVarUsage(Node& node);
730 
734  inline void findVariableDependencies();
735 
736  inline void findVariableDependencies(size_t i,
737  Node& node);
738 
744  inline void dependentAdded2EvaluationQueue(Node& node);
745 
746  inline void updateEvaluationQueueOrder(Node& node,
747  size_t newEvalOrder);
748 
749  inline bool isIndependent(const Node& arg) const;
750 
751  inline bool isTemporary(const Node& arg) const;
752 
753  inline static bool isTemporaryArray(const Node& arg);
754 
755  inline static bool isTemporarySparseArray(const Node& arg);
756 
757  inline static Node* getOperationFromAlias(Node& alias);
758 
759  inline size_t getEvaluationOrder(const Node& node) const;
760 
761  inline void setEvaluationOrder(Node& node,
762  size_t order);
763 
764  inline size_t getLastUsageEvaluationOrder(const Node& node) const;
765 
766  inline void setLastUsageEvaluationOrder(const Node& node,
767  size_t last);
768 
774  inline size_t getTotalUsageCount(const Node& node) const;
775 
776  inline void setTotalUsageCount(const Node& node,
777  size_t cout);
778 
779  inline void increaseTotalUsageCount(const Node& node);
780 
781  inline void resetManagedNodes();
782 
783  /**************************************************************************
784  * Graph management functions
785  *************************************************************************/
786 
787  inline void findPaths(SourceCodePath& path2node,
788  Node& code,
789  std::vector<SourceCodePath>& found,
790  size_t max);
791 
792  static inline std::vector<SourceCodePath> findPathsFromNode(const std::vector<SourceCodePath> nodePaths,
793  Node& node);
794 
795  /**************************************************************************
796  * Operation graph manipulation
797  *************************************************************************/
807  inline CGB solveFor(const SourceCodePath& path);
808 
825  inline CGB collectVariable(Node& expression,
826  const SourceCodePath& path1,
827  const SourceCodePath& path2,
828  size_t bifPos);
829 
830  inline CGB collectVariableAddSub(const SourceCodePath& pathLeft,
831  const SourceCodePath& pathRight);
832 
833  inline bool isCollectableVariableAddSub(const SourceCodePath& pathLeft,
834  const SourceCodePath& pathRight,
835  bool throwEx);
836 
837  inline bool isSolvable(const SourceCodePath& path) const;
838 
839  /**************************************************************************
840  * Loop related structure/methods
841  *************************************************************************/
842  struct LoopData {
843  // maps the loop ids of the loop atomic functions
844  std::map<size_t, LoopModel<Base>*> loopModels;
845  std::vector<LoopEndOperationNode<Base>*> endNodes;
846  // the used indexes
847  std::set<const Node*> indexes;
848  // the used random index patterns
849  std::set<RandomIndexPattern*> indexRandomPatterns;
850  //
851  std::vector<IndexPattern*> dependentIndexPatterns;
852  std::vector<const IndexPattern*> dependentIndexPatternManaged; // garbage collection
853  std::vector<IndexPattern*> independentIndexPatterns;
854  // variables used inside a loop which are assigned outside (for different loop depths)
855  std::vector<std::set<Node*> > outerVars;
856  // the current loop depth (-1 means no loop)
857  int depth;
858  // the evaluation order of the loop start for each loop depth
859  std::vector<size_t> startEvalOrder;
860 
861  inline LoopData() :
862  depth(-1) {
863  }
864 
865  inline void prepare4NewSourceGen();
866 
867  inline void reset();
868 
876  inline const std::string* getLoopName(size_t id) const;
877 
878  inline void registerModel(LoopModel<Base>& loop);
879 
880  inline LoopModel<Base>* getLoop(size_t loopId) const;
881 
882  size_t addDependentIndexPattern(IndexPattern& jacPattern);
883 
884  void manageDependentIndexPattern(const IndexPattern* pattern);
885 
886  size_t addIndependentIndexPattern(IndexPattern& pattern, size_t hint);
887 
888  void addLoopEndNode(Node& node);
889  };
890 
891  /**************************************************************************
892  * friends
893  *************************************************************************/
894  friend class CG<Base>;
895  friend class CGAbstractAtomicFun<Base>;
896  friend class BaseAbstractAtomicFun<Base>;
897  friend class LoopModel<Base>;
898 
899 };
900 
901 } // END cg namespace
902 } // END CppAD namespace
903 
904 #endif
virtual void markCodeBlockUsed(Node &code)
const std::string * getLoopName(size_t id) const
std::vector< int > _atomicFunctionsMaxReverse
Node * cloneNode(const Node &n)
std::vector< SourceCodePath > findPaths(Node &root, Node &target, size_t max)
void substituteIndependent(const CGB &indep, const CGB &dep, bool removeFromIndeps=true)
Definition: graph_mod.hpp:22
void updateTemporaryVarInDiffScopes(Node &code)
std::vector< std::string > * _atomicFunctionsOrder
void reorderOperations(ArrayView< CGB > &dependent)
void deleteManagedNodes(size_t start, size_t end)
CodeHandlerVector< Base, size_t > _lastVisit
void dependentAdded2EvaluationQueue(Node &node)
std::set< CodeHandlerVectorSync< Base > * > _managedVectors
const CodeHandlerVector< Base, size_t > & getVariablesIDs() const
bool manageOperationNodeMemory(Node *code)
const std::vector< Node * > & getManagedNodes() const
CodeHandlerVector< Base, size_t > _evaluationOrder
const std::string * getAtomicFunctionName(size_t id) const
size_t findLastTemporaryLocation(Node &node)
std::vector< std::vector< Node * > > _scopedVariableOrder
bool isCollectableVariableAddSub(const SourceCodePath &pathLeft, const SourceCodePath &pathRight, bool throwEx)
std::map< std::string, size_t > _atomicFunctionName2Index
std::vector< int > _atomicFunctionsMaxForward
size_t findFirstDifferentScope(size_t color1, size_t color2)
CodeHandlerVector< Base, ScopeIDType > _scope
void determineLastTempVarUsage(Node &node)
size_t getIndependentVariableSize() const
CGB collectVariableAddSub(const SourceCodePath &pathLeft, const SourceCodePath &pathRight)
const std::string * getLoopName(size_t id) const
const std::vector< int > & getExternalFuncMaxForwardOrder() const
void removeIndependent(Node &indep)
Definition: graph_mod.hpp:76
std::unique_ptr< LanguageGenerationData< Base > > _info
void makeVariables(VectorCG &variables)
CGB solveFor(Node &expression, Node &var)
Definition: solver.hpp:25
bool handleTemporaryVarInDiffScopes(Node &code, size_t oldScope, size_t newScope)
const std::map< size_t, CGAbstractAtomicFun< Base > *> & getAtomicFunctions() const
void undoSubstituteIndependent(Node &indep)
Definition: graph_mod.hpp:65
void reorderOperation(Node &node)
void makeVariable(AD< CGB > &variable)
std::vector< Node * > _variableOrder
std::map< size_t, CGAbstractAtomicFun< Base > * > _atomicFunctions
CodeHandlerVector< Base, size_t > _totalUseCount
void replaceWithConditionalTempVar(Node &tmp, IndexOperationNode< Base > &iterationIndexOp, const std::vector< size_t > &iterationRegions, ScopeIDType oldScope, ScopeIDType commonScopeColor)
size_t getManagedNodesCount() const
size_t getIndependentVariableIndex(const Node &var) const
void reduceTemporaryVariables(ArrayView< CGB > &dependent)
void setZeroDependents(bool zeroDependents)
std::vector< std::set< Node * > > _variableDependencies
size_t getTotalUsageCount(const Node &node) const
virtual void checkVariableCreation(Node &code)
IndexOperationNode< Base > * _auxIterationIndexOp
void setReuseVariableIDs(bool reuse)
const std::vector< int > & getExternalFuncMaxReverseOrder() const
CGB collectVariable(Node &expression, const SourceCodePath &path1, const SourceCodePath &path2, size_t bifPos)
void restoreTemporaryVar(Node &tmp)
std::vector< Node * > _codeBlocks
virtual void generateCode(std::ostream &out, Language< Base > &lang, CppAD::vector< CGB > &dependent, VariableNameGenerator< Base > &nameGen, const std::string &jobName="source")
CodeHandlerVector< Base, size_t > _varId
void breakCyclicDependency(Node *node, size_t scope, Node *endIf)
CodeHandlerVector< Base, size_t > _lastUsageOrder