CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
sparsity.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_SUBGRAPH_SPARSITY_HPP
2 # define CPPAD_LOCAL_SUBGRAPH_SPARSITY_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 
18 
19 // BEGIN_CPPAD_LOCAL_SUBGRAPH_NAMESPACE
20 namespace CppAD { namespace local { namespace subgraph {
21 /*!
22 \file sparsity.hpp
23 Compute dependency sparsity pattern using subgraph technique.
24 */
25 // ===========================================================================
26 /*!
27 Compute dependency sparsity pattern for an ADFun<Base> function.
28 
29 \tparam Base
30 the operation sequence was recorded using AD<Base>.
31 
32 \tparam BoolVector
33 a simple vector class with elements of type bool.
34 
35 \param play
36 is the operation sequence corresponding to the ADFun<Base> function.
37 
38 \param sub_info
39 is the subgraph information for this ADFun object.
40 
41 \param dep_taddr
42 mapping from user dependent variable index to variable index in play
43 (must have size sub_info.n_dep()).
44 
45 \param select_domain
46 only the selected independent variables will be included in the sparsity
47 pattern (must have size sub_info.n_ind()).
48 
49 \param select_range
50 only the selected dependent variables will be included in the sparsity pattern
51 (must have size sub_info.n_dep()).
52 
53 \param row_out
54 The input size and elements of row_out do not matter.
55 We use number of non-zeros (nnz) to denote the number of elements
56 in row_out. For k = 0 , ... , nnz-1, row_out[k] is the row index
57 of the k-th no-zero element of the dependency sparsitiy pattern for
58 the function corresponding to the recording.
59 \code
60  0 <= row_out[k] < dep_taddr.size()
61  select_range[ row_out[k] ] == true
62 \endcode
63 
64 \param col_out
65 The input size and elements of col_out do not matter.
66 Upon return is has the same size as row_out; i.e., nnz.
67 For k = 0 , ... , nnz-1, col_out[k] is the column index
68 of the k-th no-zero element of the dependency sparsitiy pattern for
69 the function corresponding to the recording.
70 \code
71  0 <= col_out[k] < sub_info.n_ind()
72  select_domain[ col_out[k] ] == true
73 \endcode
74 
75 \par UserOp
76 All of the inputs and outputs for an atomic function call are considered
77 to be connected.
78 2DO: It would be good to use the sparsity patters for atomic function calls
79 to to make the sparsity pattern more efficient.
80 */
81 
82 template <typename Base, typename BoolVector>
84  const player<Base>* play ,
85  subgraph_info& sub_info ,
86  const vector<size_t>& dep_taddr ,
87  const BoolVector& select_domain ,
88  const BoolVector& select_range ,
89  pod_vector<size_t>& row_out ,
90  pod_vector<size_t>& col_out )
91 {
92  // check dimension assumptions
94  dep_taddr.size() == sub_info.n_dep()
95  );
97  size_t(select_domain.size()) == sub_info.n_ind()
98  );
100  size_t(select_range.size()) == sub_info.n_dep()
101  );
102 
103  // number of dependent variables
104  size_t n_dep = dep_taddr.size();
105  CPPAD_ASSERT_UNKNOWN( size_t(select_range.size()) == n_dep );
106 
107  // start with an empty sparsity pattern
108  row_out.resize(0);
109  col_out.resize(0);
110 
111  // map_user_op
112  if( sub_info.map_user_op().size() == 0 )
113  sub_info.set_map_user_op(play);
114  else
115  { CPPAD_ASSERT_UNKNOWN( sub_info.check_map_user_op(play) );
116  }
118  sub_info.map_user_op().size() == play->num_op_rec()
119  );
120 
121  // subgraph of operators that are are connected to one of the selected
122  // dependent variables and depend on the selected independent variables
123  pod_vector<addr_t> subgraph;
124 
125  // initialize a reverse mode subgraph calculation
126  sub_info.init_rev(play, select_domain);
128  sub_info.in_subgraph().size() == play->num_op_rec()
129  );
130  //
131 # ifndef NDEBUG
132  addr_t depend_yes = addr_t( n_dep );
133 # endif
134 
135  // for each of the selected dependent variables
136 # ifndef NDEBUG
137  addr_t depend_no = addr_t( n_dep + 1 );
138 # endif
139  CPPAD_ASSERT_UNKNOWN( depend_yes < depend_no );
142  for(size_t i_dep = 0; i_dep < n_dep; ++i_dep) if( select_range[i_dep] )
143  { CPPAD_ASSERT_UNKNOWN( i_dep < size_t( depend_yes ) );
144  //
145  // subgraph of operators connected to i_dep
146  sub_info.get_rev(
147  play, dep_taddr, addr_t(i_dep), subgraph
148  );
149  //
150  for(size_t k = 0; k < subgraph.size(); k++)
151  { size_t i_op = subgraph[k];
152  //
153  // operator corresponding to this index
154  OpCode op = play->GetOp(i_op);
155  //
156  // This version of the subgraph only has first UserOp
157  // for each atomic functionc all.
158  CPPAD_ASSERT_UNKNOWN( NumRes(op) > 0 || op == UserOp );
159  //
160  // independent variable entries correspond to sparsity pattern
161  if( op == InvOp )
162  { CPPAD_ASSERT_NARG_NRES(op, 0, 1);
163  // i_var is equal i_op becasue BeginOp and InvOp have 1 result
164  size_t i_var = i_op; // tape index for this variable
165  size_t i_ind = i_var - 1; // user index for this variable
166  CPPAD_ASSERT_UNKNOWN( play->var2op(i_var) == i_op );
167  CPPAD_ASSERT_UNKNOWN( select_domain[i_ind] );
168  //
169  // put this pair in the sparsity pattern
170  row_out.push_back(i_dep);
171  col_out.push_back(i_ind);
172  }
173  }
174  }
175 }
176 
177 } } } // END_CPPAD_LOCAL_SUBGRAPH_NAMESPACE
178 
179 # endif
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
const pod_vector< addr_t > & map_user_op(void) const
map user atomic function calls to first operator in the call
Definition: info.hpp:94
include entire function call in a subgraph
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 set_map_user_op(const player< Base > *play)
set the value of map_user_op for this operation sequence
Definition: info.hpp:264
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
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
size_t size(void) const
number of elements currently in this vector.
Definition: vector.hpp:387
OpCode
Type used to distinguish different AD&lt; Base &gt; atomic operations.
Definition: op_code.hpp:49
size_t n_dep(void) const
number of dependent variables
Definition: info.hpp:78
size_t size(void) const
current number of elements in this vector.
Definition: pod_vector.hpp:79
Determine arguments that are variables.
pod_vector< addr_t > & in_subgraph(void)
flag which operators that are in the subgraph
Definition: info.hpp:155
#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
#define CPPAD_ASSERT_NARG_NRES(op, n_arg, n_res)
Check that operator op has the specified number of of arguments and results.
size_t n_ind(void) const
number of independent variables
Definition: info.hpp:74
void subgraph_sparsity(const player< Base > *play, subgraph_info &sub_info, const vector< size_t > &dep_taddr, const BoolVector &select_domain, const BoolVector &select_range, pod_vector< size_t > &row_out, pod_vector< size_t > &col_out)
Compute dependency sparsity pattern for an ADFun&lt;Base&gt; function.
Definition: sparsity.hpp:83
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
class for maintaining subgraph information attached to on ADFun object.
Definition: info.hpp:25
bool check_map_user_op(const player< Base > *play) const
check that the value of map_user_op is OK for this operation sequence
Definition: info.hpp:126