CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_SPARSE_BINARY_OP_INCLUDED 00003 # define CPPAD_SPARSE_BINARY_OP_INCLUDED 00004 /* -------------------------------------------------------------------------- 00005 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-14 Bradley M. Bell 00006 00007 CppAD is distributed under multiple licenses. This distribution is under 00008 the terms of the 00009 Eclipse Public License Version 1.0. 00010 00011 A copy of this license is included in the COPYING file of this distribution. 00012 Please visit http://www.coin-or.org/CppAD/ for information on other licenses. 00013 -------------------------------------------------------------------------- */ 00014 00015 namespace CppAD { // BEGIN_CPPAD_NAMESPACE 00016 /*! 00017 \file sparse_binary_op.hpp 00018 Forward and reverse mode sparsity patterns for binary operators. 00019 */ 00020 00021 00022 /*! 00023 Forward mode Jacobian sparsity pattern for all binary operators. 00024 00025 The C++ source code corresponding to a binary operation has the form 00026 \verbatim 00027 z = fun(x, y) 00028 \endverbatim 00029 where fun is a C++ binary function and both x and y are variables, 00030 or it has the form 00031 \verbatim 00032 z = x op y 00033 \endverbatim 00034 where op is a C++ binary unary operator and both x and y are variables. 00035 00036 \tparam Vector_set 00037 is the type used for vectors of sets. It can be either 00038 \c sparse_pack, \c sparse_set, or \c sparse_list. 00039 00040 \param i_z 00041 variable index corresponding to the result for this operation; 00042 i.e., z. 00043 00044 \param arg 00045 \a arg[0] 00046 variable index corresponding to the left operand for this operator; 00047 i.e., x. 00048 \n 00049 \n arg[1] 00050 variable index corresponding to the right operand for this operator; 00051 i.e., y. 00052 00053 \param sparsity 00054 \b Input: 00055 The set with index \a arg[0] in \a sparsity 00056 is the sparsity bit pattern for x. 00057 This identifies which of the independent variables the variable x 00058 depends on. 00059 \n 00060 \n 00061 \b Input: 00062 The set with index \a arg[1] in \a sparsity 00063 is the sparsity bit pattern for y. 00064 This identifies which of the independent variables the variable y 00065 depends on. 00066 \n 00067 \n 00068 \b Output: 00069 The set with index \a i_z in \a sparsity 00070 is the sparsity bit pattern for z. 00071 This identifies which of the independent variables the variable z 00072 depends on. 00073 00074 \par Checked Assertions: 00075 \li \a arg[0] < \a i_z 00076 \li \a arg[1] < \a i_z 00077 */ 00078 00079 template <class Vector_set> 00080 inline void forward_sparse_jacobian_binary_op( 00081 size_t i_z , 00082 const addr_t* arg , 00083 Vector_set& sparsity ) 00084 { 00085 // check assumptions 00086 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00087 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00088 00089 sparsity.binary_union(i_z, arg[0], arg[1], sparsity); 00090 00091 return; 00092 } 00093 00094 /*! 00095 Reverse mode Jacobian sparsity pattern for all binary operators. 00096 00097 The C++ source code corresponding to a unary operation has the form 00098 \verbatim 00099 z = fun(x, y) 00100 \endverbatim 00101 where fun is a C++ unary function and x and y are variables, 00102 or it has the form 00103 \verbatim 00104 z = x op y 00105 \endverbatim 00106 where op is a C++ bianry operator and x and y are variables. 00107 00108 This routine is given the sparsity patterns 00109 for a function G(z, y, x, ... ) 00110 and it uses them to compute the sparsity patterns for 00111 \verbatim 00112 H( y, x, w , u , ... ) = G[ z(x,y) , y , x , w , u , ... ] 00113 \endverbatim 00114 00115 \tparam Vector_set 00116 is the type used for vectors of sets. It can be either 00117 \c sparse_pack, \c sparse_set, or \c sparse_list. 00118 00119 \param i_z 00120 variable index corresponding to the result for this operation; 00121 i.e., z. 00122 00123 \param arg 00124 \a arg[0] 00125 variable index corresponding to the left operand for this operator; 00126 i.e., x. 00127 00128 \n 00129 \n arg[1] 00130 variable index corresponding to the right operand for this operator; 00131 i.e., y. 00132 00133 \param sparsity 00134 The set with index \a i_z in \a sparsity 00135 is the sparsity pattern for z corresponding ot the function G. 00136 \n 00137 \n 00138 The set with index \a arg[0] in \a sparsity 00139 is the sparsity pattern for x. 00140 On input, it corresponds to the function G, 00141 and on output it corresponds to H. 00142 \n 00143 \n 00144 The set with index \a arg[1] in \a sparsity 00145 is the sparsity pattern for y. 00146 On input, it corresponds to the function G, 00147 and on output it corresponds to H. 00148 \n 00149 \n 00150 00151 \par Checked Assertions: 00152 \li \a arg[0] < \a i_z 00153 \li \a arg[1] < \a i_z 00154 */ 00155 template <class Vector_set> 00156 inline void reverse_sparse_jacobian_binary_op( 00157 size_t i_z , 00158 const addr_t* arg , 00159 Vector_set& sparsity ) 00160 { 00161 // check assumptions 00162 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00163 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00164 00165 sparsity.binary_union(arg[0], arg[0], i_z, sparsity); 00166 sparsity.binary_union(arg[1], arg[1], i_z, sparsity); 00167 00168 return; 00169 } 00170 00171 /*! 00172 Reverse mode Hessian sparsity pattern for add and subtract operators. 00173 00174 The C++ source code corresponding to a unary operation has the form 00175 \verbatim 00176 z = x op y 00177 \endverbatim 00178 where op is + or - and x, y are variables. 00179 00180 \copydetails reverse_sparse_hessian_binary_op 00181 */ 00182 template <class Vector_set> 00183 inline void reverse_sparse_hessian_addsub_op( 00184 size_t i_z , 00185 const addr_t* arg , 00186 bool* jac_reverse , 00187 Vector_set& for_jac_sparsity , 00188 Vector_set& rev_hes_sparsity ) 00189 { 00190 // check assumptions 00191 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00192 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00193 00194 rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity); 00195 rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity); 00196 00197 jac_reverse[arg[0]] |= jac_reverse[i_z]; 00198 jac_reverse[arg[1]] |= jac_reverse[i_z]; 00199 00200 return; 00201 } 00202 00203 /*! 00204 Reverse mode Hessian sparsity pattern for multiplication operator. 00205 00206 The C++ source code corresponding to a unary operation has the form 00207 \verbatim 00208 z = x * y 00209 \endverbatim 00210 where x and y are variables. 00211 00212 \copydetails reverse_sparse_hessian_binary_op 00213 */ 00214 template <class Vector_set> 00215 inline void reverse_sparse_hessian_mul_op( 00216 size_t i_z , 00217 const addr_t* arg , 00218 bool* jac_reverse , 00219 Vector_set& for_jac_sparsity , 00220 Vector_set& rev_hes_sparsity ) 00221 { 00222 // check assumptions 00223 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00224 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00225 00226 rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity); 00227 rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity); 00228 00229 if( jac_reverse[i_z] ) 00230 { rev_hes_sparsity.binary_union( 00231 arg[0], arg[0], arg[1], for_jac_sparsity); 00232 rev_hes_sparsity.binary_union( 00233 arg[1], arg[1], arg[0], for_jac_sparsity); 00234 } 00235 00236 jac_reverse[arg[0]] |= jac_reverse[i_z]; 00237 jac_reverse[arg[1]] |= jac_reverse[i_z]; 00238 return; 00239 } 00240 00241 /*! 00242 Reverse mode Hessian sparsity pattern for division operator. 00243 00244 The C++ source code corresponding to a unary operation has the form 00245 \verbatim 00246 z = x / y 00247 \endverbatim 00248 where x and y are variables. 00249 00250 \copydetails reverse_sparse_hessian_binary_op 00251 */ 00252 template <class Vector_set> 00253 inline void reverse_sparse_hessian_div_op( 00254 size_t i_z , 00255 const addr_t* arg , 00256 bool* jac_reverse , 00257 Vector_set& for_jac_sparsity , 00258 Vector_set& rev_hes_sparsity ) 00259 { 00260 // check assumptions 00261 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00262 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00263 00264 rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity); 00265 rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity); 00266 00267 if( jac_reverse[i_z] ) 00268 { rev_hes_sparsity.binary_union( 00269 arg[0], arg[0], arg[1], for_jac_sparsity); 00270 rev_hes_sparsity.binary_union( 00271 arg[1], arg[1], arg[0], for_jac_sparsity); 00272 rev_hes_sparsity.binary_union( 00273 arg[1], arg[1], arg[1], for_jac_sparsity); 00274 } 00275 00276 jac_reverse[arg[0]] |= jac_reverse[i_z]; 00277 jac_reverse[arg[1]] |= jac_reverse[i_z]; 00278 return; 00279 } 00280 00281 /*! 00282 Reverse mode Hessian sparsity pattern for power function. 00283 00284 The C++ source code corresponding to a unary operation has the form 00285 \verbatim 00286 z = pow(x, y) 00287 \endverbatim 00288 where x and y are variables. 00289 00290 \copydetails reverse_sparse_hessian_binary_op 00291 */ 00292 template <class Vector_set> 00293 inline void reverse_sparse_hessian_pow_op( 00294 size_t i_z , 00295 const addr_t* arg , 00296 bool* jac_reverse , 00297 Vector_set& for_jac_sparsity , 00298 Vector_set& rev_hes_sparsity ) 00299 { 00300 // check assumptions 00301 CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < i_z ); 00302 CPPAD_ASSERT_UNKNOWN( size_t(arg[1]) < i_z ); 00303 00304 rev_hes_sparsity.binary_union(arg[0], arg[0], i_z, rev_hes_sparsity); 00305 rev_hes_sparsity.binary_union(arg[1], arg[1], i_z, rev_hes_sparsity); 00306 00307 if( jac_reverse[i_z] ) 00308 { 00309 rev_hes_sparsity.binary_union( 00310 arg[0], arg[0], arg[0], for_jac_sparsity); 00311 rev_hes_sparsity.binary_union( 00312 arg[0], arg[0], arg[1], for_jac_sparsity); 00313 00314 rev_hes_sparsity.binary_union( 00315 arg[1], arg[1], arg[0], for_jac_sparsity); 00316 rev_hes_sparsity.binary_union( 00317 arg[1], arg[1], arg[1], for_jac_sparsity); 00318 } 00319 00320 // I cannot think of a case where this is necessary, but it including 00321 // it makes it like the other cases. 00322 jac_reverse[arg[0]] |= jac_reverse[i_z]; 00323 jac_reverse[arg[1]] |= jac_reverse[i_z]; 00324 return; 00325 } 00326 00327 } // END_CPPAD_NAMESPACE 00328 # endif