CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
get_rev.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_SUBGRAPH_GET_REV_HPP
2 # define CPPAD_LOCAL_SUBGRAPH_GET_REV_HPP
3 /* --------------------------------------------------------------------------
4 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
5 
6 CppAD is distributed under multiple licenses. This distribution is under
7 the terms of the
8  Eclipse Public License Version 1.0.
9 
10 A copy of this license is included in the COPYING file of this distribution.
11 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
12 -------------------------------------------------------------------------- */
13 
17 
18 // BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE
19 namespace CppAD { namespace local { namespace subgraph {
20 /*!
21 \file get_rev.hpp
22 Get subgraph corresponding to a dependent variable.
23 */
24 
25 // ===========================================================================
26 /*!
27 Get the subgraph corresponding to a dependent variables
28 (and a selected set of independent variables).
29 
30 \tparam Base
31 this operation sequence was recording using AD<Base>.
32 
33 \param play
34 is the operation sequence corresponding to the ADFun<Base> function.
35 
36 \param dep_taddr
37 is the vector mapping user dependent variable indices
38 to the correpsonding variable in the recording.
39 
40 \param i_dep
41 is the user index for his dependent variable;
42 that i_dep < n_dep_.
43 
44 \param subgraph
45 the input size and contents of this vector do not matter.
46 Repeated calls with the same subgraph vector should reduce
47 the amount of memory allocation.
48 Upon return it contains the operator indices for the subgraph
49 corresponding to the dependent and the selected independent variables.
50 Only selected independent variable operators InvOp are included
51 in the subgraph.
52 Furthermore the operator indices in subgraph are unique; i.e.,
53 if i_op != j_op then subgraph[i_op] != subgraph[j_op].
54 
55 \par map_user_op_
56 This vector must be set.
57 
58 \par in_subgraph_
59 has size equal to the number of operators in play.
60 If in_subgraph[i_op] <= n_dep_,
61 the result for this operator depends on the selected independent variables.
62 In addition, upon input, there is no i_op such that in_subgraph[i_op] == i_dep.
63 Note that for user function call operators i_op,
64 \code
65  n_dep_ < in_subgraph[i_op]
66 \endcode
67 except for the first UserOp in the atomic function call sequence.
68 For the first UserOp,
69 \code
70  in_subgraph[i_op] <= n_dep_
71 \endcode
72 if any result for the user function call
73 depends on the selected independent variables.
74 Except for UserOP, only operators with NumRes(op) > 0 are included
75 in the dependency; e.g., comparision operators are not included.
76 Upon return, some of the i_op for which in_subgraph[i_op] <= n_dep_,
77 will be changed to in_subgraph[i_op] = i_dep.
78 
79 \par process_range_
80 The value process_range_[i_dep] is checked to make sure it is false.
81 It is then set to have value true.
82 */
83 template <typename Base>
85  const player<Base>* play ,
86  const vector<size_t>& dep_taddr ,
87  addr_t i_dep ,
88  pod_vector<addr_t>& subgraph )
89 { // check sizes
91 
92  // process_range_
93  CPPAD_ASSERT_UNKNOWN( process_range_[i_dep] == false );
94  process_range_[i_dep] = true;
95 
96  // special value; see init_rev_in_subgraph
97  addr_t depend_yes = addr_t( n_dep_ );
98 
99  // assumption on i_dep
100  CPPAD_ASSERT_UNKNOWN( i_dep < depend_yes );
101 
102  // start with an empty subgraph for this dependent variable
103  subgraph.resize(0);
104 
105  // tape index corresponding to this dependent variable
106  size_t i_var = dep_taddr[i_dep];
107 
108  // operator corresponding to this dependent variable
109  size_t i_op = play->var2op(i_var);
110  i_op = map_user_op_[i_op];
111 
112  // if this variable depends on the selected indepent variables
113  // process its subgraph
114  CPPAD_ASSERT_UNKNOWN( in_subgraph_[i_op] != i_dep )
115  if( in_subgraph_[i_op] <= depend_yes )
116  { subgraph.push_back( addr_t(i_op) );
117  in_subgraph_[i_op] = i_dep;
118  }
119 
120  // space used to return set of arguments that are variables
121  pod_vector<size_t> argument_variable;
122 
123  // temporary space used by get_argument_variable
124  pod_vector<bool> work;
125 
126  // scan all the operators in this subgraph
127  size_t sub_index = 0;
128  while(sub_index < subgraph.size() )
129  { // this operator connected to this dependent and selected independent
130  i_op = subgraph[sub_index];
131  CPPAD_ASSERT_UNKNOWN( in_subgraph_[i_op] == i_dep );
132  //
133  // There must be a result for this operator
134 # ifndef NDEBUG
135  OpCode op = play->GetOp(i_op);
136  CPPAD_ASSERT_UNKNOWN(op == UserOp || NumRes(op) > 0 );
137 # endif
138  //
139  // which variables are connected to this operator
140  get_argument_variable(play, i_op, argument_variable, work);
141  for(size_t j = 0; j < argument_variable.size(); ++j)
142  { // add the corresponding operators to the subgraph
143  size_t j_var = argument_variable[j];
144  size_t j_op = play->var2op(j_var);
145  j_op = map_user_op_[j_op];
146  bool add = in_subgraph_[j_op] <= depend_yes;
147  add &= in_subgraph_[j_op] != i_dep;
148  if( play->GetOp(j_op) == InvOp )
149  { CPPAD_ASSERT_UNKNOWN( j_op == j_var );
150  add &= select_domain_[j_var - 1];
151  }
152  if( add )
153  { subgraph.push_back( addr_t(j_op) );
154  in_subgraph_[j_op] = i_dep;
155  }
156  }
157  // we are done scaning this subgraph operator
158  ++sub_index;
159  }
160 }
161 
162 } } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE
163 
164 # endif
size_t n_op_
number of operatros in operation sequence
Definition: info.hpp:37
void resize(size_t n)
resize the vector (existing elements preserved when n &lt;= capacity_).
Definition: pod_vector.hpp:180
void push_back(const Type &e)
Add an element to theh back of this vector.
Definition: pod_vector.hpp:312
subgraph information attached to a operation sequence
CPPAD_TAPE_ADDR_TYPE addr_t
Definition: declare_ad.hpp:44
Class used to store and play back an operation sequence recording.
Definition: declare_ad.hpp:27
size_t NumRes(OpCode op)
Number of variables resulting from the specified operation.
Definition: op_code.hpp:281
File used to define pod_vector class.
void get_rev(const player< Base > *play, const vector< size_t > &dep_taddr, addr_t i_dep, pod_vector< addr_t > &subgraph)
Get the subgraph corresponding to a dependent variables (and a selected set of independent variables)...
Definition: get_rev.hpp:84
size_t n_dep_
number of dependent variables for this function
Definition: info.hpp:34
void get_argument_variable(const player< Base > *play, size_t i_op, pod_vector< size_t > &variable, pod_vector< bool > &work)
Determine the set of arguments, for an operator, that are variables.
pod_vector< bool > process_range_
flags which dependent variables have been processed since the previous init_rev
Definition: info.hpp:67
OpCode
Type used to distinguish different AD&lt; Base &gt; atomic operations.
Definition: op_code.hpp:49
pod_vector< addr_t > in_subgraph_
flags which operatiors are in subgraph (size zero or n_op_).
Definition: info.hpp:60
pod_vector< addr_t > map_user_op_
Mapping atomic call operators to UserOp that begins call sequence, other operators are not changed by...
Definition: info.hpp:52
size_t size(void) const
current number of elements in this vector.
Definition: pod_vector.hpp:79
Determine arguments that are variables.
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
size_t var2op(size_t var_index) const
fetch the operator corresponding to a primary variable
Definition: player.hpp:461
OpCode GetOp(size_t i) const
fetch an operator from the recording.
Definition: player.hpp:558
pod_vector< bool > select_domain_
flags which dependent variables are selected
Definition: info.hpp:63