CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
init_rev.hpp
Go to the documentation of this file.
1 
2 # ifndef CPPAD_LOCAL_SUBGRAPH_INIT_REV_HPP
3 # define CPPAD_LOCAL_SUBGRAPH_INIT_REV_HPP
4 
5 /* --------------------------------------------------------------------------
6 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
7 
8 CppAD is distributed under multiple licenses. This distribution is under
9 the terms of the
10  Eclipse Public License Version 1.0.
11 
12 A copy of this license is included in the COPYING file of this distribution.
13 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
14 -------------------------------------------------------------------------- */
15 
17 
18 // BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE
19 namespace CppAD { namespace local { namespace subgraph {
20 /*!
21 \file init_rev.hpp
22 initialize for a reverse mode subgraph calculation
23 */
24 
25 // -----------------------------------------------------------------------
26 /*!
27 Initialize in_subgraph corresponding to a single dependent variable
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 (it must correspond to map_user_op_).
36 
37 \param select_domain
38 is a vector with, size equal to the number of independent variables
39 in the recording. It determines the selected independent variables.
40 
41 \par in_subgraph_
42 We use depend_yes (depend_no) for the value n_dep_ (n_dep_ + 1).
43 The important properties are that depend_yes < depend_no and
44 for a valid indpendent variable index i_ind < depend_yes.
45 The input size and elements of in_subgraph_ do not matter.
46 If in_subgraph_[i_op] == depend_yes (depend_no),
47 the result for this operator depends (does not depend)
48 on the selected independent variables.
49 Note that for user function call operators i_op,
50 in_subgraph[i_op] is depend_no except for the first UserOp in the
51 atomic function call sequence. For the first UserOp,
52 it is depend_yes (depend_no) if any of the results for the call sequence
53 depend (do not depend) on the selected independent variables.
54 Except for UserOP, only operators with NumRes(op) > 0 have in_subgraph_
55 value depend_yes;
56 e.g., comparision operators have in_subgraph_ value depend_no.
57 
58 \par select_domain_
59 This vector is is set equal to the select_domain argument.
60 
61 \par process_range_
62 This vector is to to size n_dep_ and its values are set to false
63 */
64 template <typename Base, typename BoolVector>
66  const player<Base>* play ,
67  const BoolVector& select_domain )
68 {
69  // check sizes
72  CPPAD_ASSERT_UNKNOWN( size_t( select_domain.size() ) == n_ind_ );
73 
74  // depend_yes and depend_no
75  addr_t depend_yes = addr_t( n_dep_ );
76  addr_t depend_no = addr_t( n_dep_ + 1 );
77 
78  // select_domain_
80  for(size_t j = 0; j < n_ind_; ++j)
81  select_domain_[j] = select_domain[j];
82 
83  // process_range_
85  for(size_t i = 0; i < n_dep_; ++i)
86  process_range_[i] = false;
87 
88  // set in_subgraph to have proper size
90 
91  // space used to return set of arguments that are variables
92  pod_vector<size_t> argument_variable;
93 
94  // temporary space used by get_argument_variable
95  pod_vector<bool> work;
96 
97 # ifndef NDEBUG
98  size_t count_independent = 0;
99 # endif
100  bool begin_atomic_call = false;
101  for(size_t i_op = 0; i_op < n_op_; ++i_op)
102  { OpCode op = play->GetOp(i_op);
103  //
104  // default value for this operator
105  in_subgraph_[i_op] = depend_no;
106  //
107  switch(op)
108  { case InvOp:
109  CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );
110  CPPAD_ASSERT_UNKNOWN( i_op > 0 );
111  { // get user index for this independent variable
112  size_t j = i_op - 1;
113  CPPAD_ASSERT_UNKNOWN( j < n_ind_ );
114  //
115  // set in_subgraph_[i_op]
116  if( select_domain[j] )
117  in_subgraph_[i_op] = depend_yes;
118  }
119 # ifndef NDEBUG
120  ++count_independent;
121 # endif
122  break;
123 
124  // only mark both first UserOp for each call as depending
125  // on the selected independent variables
126  case UserOp:
127  begin_atomic_call = not begin_atomic_call;
128  if( begin_atomic_call )
129  { get_argument_variable(play, i_op, argument_variable, work);
130  for(size_t j = 0; j < argument_variable.size(); ++j)
131  { size_t j_var = argument_variable[j];
132  size_t j_op = play->var2op(j_var);
133  j_op = map_user_op_[j_op];
134  CPPAD_ASSERT_UNKNOWN( j_op < i_op );
135  if( in_subgraph_[j_op] == depend_yes )
136  in_subgraph_[i_op] = depend_yes;
137  }
138  }
139  break;
140 
141  // skip UsrrvOp (gets mapped to first UserOp in this call)
142  case UsrrvOp:
143  CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 );
144  break;
145 
146  default:
147  // Except for UserOp, only include when NumRes(op) > 0.
148  if( NumRes(op) > 0 )
149  { get_argument_variable(play, i_op, argument_variable, work);
150  for(size_t j = 0; j < argument_variable.size(); ++j)
151  { size_t j_var = argument_variable[j];
152  size_t j_op = play->var2op(j_var);
153  j_op = map_user_op_[j_op];
154  CPPAD_ASSERT_UNKNOWN( j_op < i_op );
155  if( in_subgraph_[j_op] == depend_yes )
156  in_subgraph_[i_op] = depend_yes;
157  }
158  }
159  break;
160  }
161  }
163  count_independent == size_t(select_domain.size())
164  );
165  //
166  return;
167 }
168 
169 } } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE
170 
171 # 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
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
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
void init_rev(const player< Base > *play, const BoolVector &select_domain)
Initialize in_subgraph corresponding to a single dependent variable (and a selected set of independen...
Definition: init_rev.hpp:65
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
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
size_t num_op_rec(void) const
Fetch number of operators in the recording.
Definition: player.hpp:622
size_t n_ind_
number of independent variables for this function
Definition: info.hpp:31
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