CppADCodeGen  HEAD
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;
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;
134  std::vector<int> _atomicFunctionsMaxForward;
139  std::vector<int> _atomicFunctionsMaxReverse;
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;
175 public:
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 
253  inline const CodeHandlerVector<Base, size_t>& getVariablesIDs() const;
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,
488  IndexOperationNode<Base>& index1);
489 
490  inline IndexAssignOperationNode<Base>* makeIndexAssignNode(Node& index,
491  IndexPattern& indexPattern,
492  IndexOperationNode<Base>* index1,
493  IndexOperationNode<Base>* index2);
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 
617 protected:
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
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
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
void makeVariables(VectorCG &variables)
CGB solveFor(Node &expression, Node &var)
Definition: solver.hpp:25
bool handleTemporaryVarInDiffScopes(Node &code, size_t oldScope, size_t newScope)
CodeHandlerVector< Base, size_t > _operationCount
const std::map< size_t, CGAbstractAtomicFun< Base > *> & getAtomicFunctions() const
void undoSubstituteIndependent(Node &indep)
Definition: graph_mod.hpp:65
void reorderOperation(Node &node)
std::string getAtomicFunctionName(size_t id) const
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