CppAD: A C++ Algorithmic Differentiation Package 20110419
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_REV_HES_SWEEP_INCLUDED 00003 # define CPPAD_REV_HES_SWEEP_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-11 Bradley M. Bell 00007 00008 CppAD is distributed under multiple licenses. This distribution is under 00009 the terms of the 00010 Common Public License Version 1.0. 00011 00012 A copy of this license is included in the COPYING file of this distribution. 00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses. 00014 -------------------------------------------------------------------------- */ 00015 00016 CPPAD_BEGIN_NAMESPACE 00017 /*! 00018 \file rev_hes_sweep.hpp 00019 Compute Reverse mode Hessian sparsity patterns. 00020 */ 00021 00022 /*! 00023 \def CPPAD_REV_HES_SWEEP_TRACE 00024 This value is either zero or one. 00025 Zero is the normal operational value. 00026 If it is one, a trace of every rev_hes_sweep computation is printed. 00027 */ 00028 # define CPPAD_REV_HES_SWEEP_TRACE 0 00029 00030 /*! 00031 Given the forward Jacobian sparsity pattern for all the variables, 00032 and the reverse Jacobian sparsity pattern for the dependent variables, 00033 RevHesSweep computes the Hessian sparsity pattern for all the independent 00034 variables. 00035 00036 \tparam Base 00037 base type for the operator; i.e., this operation sequence was recorded 00038 using AD< \a Base > and computations by this routine are done using type 00039 \a Base. 00040 00041 \tparam Vector_set 00042 is the type used for vectors of sets. It can be either 00043 \c sparse_pack or \c sparse_set. 00044 00045 \param n 00046 is the number of independent variables on the tape. 00047 00048 \param numvar 00049 is the total number of variables on the tape; i.e., 00050 \a play->num_rec_var(). 00051 This is also the number of rows in the entire sparsity pattern 00052 \a rev_hes_sparse. 00053 00054 \param play 00055 The information stored in \a play 00056 is a recording of the operations corresponding to a function 00057 \f[ 00058 F : {\bf R}^n \rightarrow {\bf R}^m 00059 \f] 00060 where \f$ n \f$ is the number of independent variables 00061 and \f$ m \f$ is the number of dependent variables. 00062 The object \a play is effectly constant. 00063 It is not declared const because while playing back the tape 00064 the object \a play holds information about the currentl location 00065 with in the tape and this changes during playback. 00066 00067 \param for_jac_sparse 00068 For i = 0 , ... , \a numvar - 1, 00069 (for all the variables on the tape), 00070 the forward Jacobian sparsity pattern for the variable with index i 00071 corresponds to the set with index i in \a for_jac_sparse. 00072 00073 \param RevJac 00074 \b Input: 00075 For i = 0, ... , \a numvar - 1 00076 the if the variable with index i on the tape is an dependent variable and 00077 included in the Hessian, \a RevJac[ i ] is equal to true, 00078 otherwise it is equal to false. 00079 \n 00080 \n 00081 \b Output: The values in \a RevJac upon return are not specified; i.e., 00082 it is used for temporary work space. 00083 00084 \param rev_hes_sparse 00085 The reverse Hessian sparsity pattern for the variable with index i 00086 corresponds to the set with index i in \a rev_hes_sparse. 00087 \n 00088 \n 00089 \b Input: For i = 0 , ... , \a numvar - 1 00090 the reverse Hessian sparsity pattern for the variable with index i is empty. 00091 \n 00092 \n 00093 \b Output: For j = 1 , ... , \a n, 00094 the reverse Hessian sparsity pattern for the independent dependent variable 00095 with index (j-1) is given by the set with index j 00096 in \a rev_hes_sparse. 00097 The values in the rest of \a rev_hes_sparse are not specified; i.e., 00098 they are used for temporary work space. 00099 */ 00100 00101 template <class Base, class Vector_set> 00102 void RevHesSweep( 00103 size_t n, 00104 size_t numvar, 00105 player<Base> *play, 00106 Vector_set& for_jac_sparse, // should be const 00107 bool* RevJac, 00108 Vector_set& rev_hes_sparse 00109 ) 00110 { 00111 OpCode op; 00112 size_t i_op; 00113 size_t i_var; 00114 00115 const size_t *arg = 0; 00116 00117 // length of the parameter vector (used by CppAD assert macros) 00118 const size_t num_par = play->num_rec_par(); 00119 00120 size_t i, j, k; 00121 00122 // check numvar argument 00123 CPPAD_ASSERT_UNKNOWN( play->num_rec_var() == numvar ); 00124 CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); 00125 CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.n_set() == numvar ); 00126 CPPAD_ASSERT_UNKNOWN( numvar > 0 ); 00127 00128 // upper limit exclusive for set elements 00129 size_t limit = rev_hes_sparse.end(); 00130 CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit ); 00131 00132 // check number of sets match 00133 CPPAD_ASSERT_UNKNOWN( 00134 for_jac_sparse.n_set() == rev_hes_sparse.n_set() 00135 ); 00136 00137 // vecad_sparsity contains a sparsity pattern for each VecAD object. 00138 // vecad_ind maps a VecAD index (beginning of the VecAD object) 00139 // to the index for the corresponding set in vecad_sparsity. 00140 size_t num_vecad_ind = play->num_rec_vecad_ind(); 00141 size_t num_vecad_vec = play->num_rec_vecad_vec(); 00142 Vector_set vecad_sparse; 00143 vecad_sparse.resize(num_vecad_vec, limit); 00144 size_t* vecad_ind = CPPAD_NULL; 00145 bool* vecad_jac = CPPAD_NULL; 00146 if( num_vecad_vec > 0 ) 00147 { size_t length; 00148 vecad_ind = CPPAD_TRACK_NEW_VEC(num_vecad_ind, vecad_ind); 00149 vecad_jac = CPPAD_TRACK_NEW_VEC(num_vecad_vec, vecad_jac); 00150 j = 0; 00151 for(i = 0; i < num_vecad_vec; i++) 00152 { // length of this VecAD 00153 length = play->GetVecInd(j); 00154 // set vecad_ind to proper index for this VecAD 00155 vecad_ind[j] = i; 00156 // make all other values for this vector invalid 00157 for(k = 1; k <= length; k++) 00158 vecad_ind[j+k] = num_vecad_vec; 00159 // start of next VecAD 00160 j += length + 1; 00161 // initialize this vector's reverse jacobian value 00162 vecad_jac[i] = false; 00163 } 00164 CPPAD_ASSERT_UNKNOWN( j == play->num_rec_vecad_ind() ); 00165 } 00166 00167 // work space used by UserOp. 00168 typedef std::set<size_t> size_set; 00169 const size_t user_q = limit; // maximum element plus one 00170 size_set::iterator set_itr; // iterator for a standard set 00171 size_set::iterator set_end; // end of iterator sequence 00172 vector<size_t> user_ix; // variable indices for argument vector x 00173 vector< size_set > user_r; // forward Jacobian sparsity pattern for x 00174 vector<bool> user_s; // reverse Jacobian sparsity for y 00175 vector<bool> user_t; // reverse Jacobian sparsity for x 00176 vector< size_set > user_u; // reverse Hessian sparsity for y 00177 vector< size_set > user_v; // reverse Hessian sparsity for x 00178 size_t user_index = 0; // indentifier for this user_atomic operation 00179 size_t user_id = 0; // user identifier for this call to operator 00180 size_t user_i = 0; // index in result vector 00181 size_t user_j = 0; // index in argument vector 00182 size_t user_m = 0; // size of result vector 00183 size_t user_n = 0; // size of arugment vector 00184 // next expected operator in a UserOp sequence 00185 enum { user_start, user_arg, user_ret, user_end } user_state = user_end; 00186 00187 00188 // Initialize 00189 play->start_reverse(op, arg, i_op, i_var); 00190 CPPAD_ASSERT_UNKNOWN( op == EndOp ); 00191 # if CPPAD_REV_HES_SWEEP_TRACE 00192 std::cout << std::endl; 00193 CppAD::vectorBool zf_value(limit); 00194 CppAD::vectorBool zh_value(limit); 00195 # endif 00196 while(op != BeginOp) 00197 { 00198 // next op 00199 play->next_reverse(op, arg, i_op, i_var); 00200 # ifndef NDEBUG 00201 if( i_op <= n ) 00202 { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); 00203 } 00204 else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); 00205 # endif 00206 00207 // rest of information depends on the case 00208 switch( op ) 00209 { 00210 case AbsOp: 00211 CPPAD_ASSERT_NARG_NRES(op, 1, 1) 00212 reverse_sparse_hessian_linear_unary_op( 00213 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00214 ); 00215 break; 00216 // ------------------------------------------------- 00217 00218 case AddvvOp: 00219 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00220 reverse_sparse_hessian_addsub_op( 00221 i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse 00222 ); 00223 break; 00224 // ------------------------------------------------- 00225 00226 case AddpvOp: 00227 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00228 reverse_sparse_hessian_linear_unary_op( 00229 i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse 00230 ); 00231 break; 00232 // ------------------------------------------------- 00233 00234 case AcosOp: 00235 // acos(x) and sqrt(1 - x * x) are computed in pairs 00236 // but i_var + 1 should only be used here 00237 CPPAD_ASSERT_NARG_NRES(op, 1, 2) 00238 reverse_sparse_hessian_nonlinear_unary_op( 00239 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00240 ); 00241 break; 00242 // ------------------------------------------------- 00243 00244 case AsinOp: 00245 // asin(x) and sqrt(1 - x * x) are computed in pairs 00246 // but i_var + 1 should only be used here 00247 CPPAD_ASSERT_NARG_NRES(op, 1, 2) 00248 reverse_sparse_hessian_nonlinear_unary_op( 00249 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00250 ); 00251 break; 00252 // ------------------------------------------------- 00253 00254 case AtanOp: 00255 // atan(x) and 1 + x * x must be computed in pairs 00256 // but i_var + 1 should only be used here 00257 CPPAD_ASSERT_NARG_NRES(op, 1, 2) 00258 reverse_sparse_hessian_nonlinear_unary_op( 00259 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00260 ); 00261 break; 00262 // ------------------------------------------------- 00263 00264 case BeginOp: 00265 CPPAD_ASSERT_NARG_NRES(op, 0, 1) 00266 break; 00267 // ------------------------------------------------- 00268 00269 case CSumOp: 00270 // CSumOp has a variable number of arguments and 00271 // next_reverse thinks it one has one argument. 00272 // We must inform next_reverse of this special case. 00273 play->reverse_csum(op, arg, i_op, i_var); 00274 reverse_sparse_hessian_csum_op( 00275 i_var, arg, RevJac, rev_hes_sparse 00276 ); 00277 break; 00278 // ------------------------------------------------- 00279 00280 case CExpOp: 00281 reverse_sparse_hessian_cond_op( 00282 i_var, arg, num_par, RevJac, rev_hes_sparse 00283 ); 00284 break; 00285 // --------------------------------------------------- 00286 00287 case ComOp: 00288 CPPAD_ASSERT_NARG_NRES(op, 4, 0) 00289 CPPAD_ASSERT_UNKNOWN( arg[1] > 1 ); 00290 break; 00291 // -------------------------------------------------- 00292 00293 case CosOp: 00294 // cosine and sine must come in pairs 00295 // but i_var should only be used here 00296 CPPAD_ASSERT_NARG_NRES(op, 1, 2) 00297 reverse_sparse_hessian_nonlinear_unary_op( 00298 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00299 ); 00300 break; 00301 // --------------------------------------------------- 00302 00303 case CoshOp: 00304 // hyperbolic cosine and sine must come in pairs 00305 // but i_var should only be used here 00306 CPPAD_ASSERT_NARG_NRES(op, 1, 2) 00307 reverse_sparse_hessian_nonlinear_unary_op( 00308 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00309 ); 00310 break; 00311 // ------------------------------------------------- 00312 00313 case DisOp: 00314 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00315 00316 break; 00317 // ------------------------------------------------- 00318 00319 case DivvvOp: 00320 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00321 reverse_sparse_hessian_div_op( 00322 i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse 00323 ); 00324 break; 00325 // ------------------------------------------------- 00326 00327 case DivpvOp: 00328 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00329 reverse_sparse_hessian_nonlinear_unary_op( 00330 i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse 00331 ); 00332 break; 00333 // ------------------------------------------------- 00334 00335 case DivvpOp: 00336 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00337 reverse_sparse_hessian_linear_unary_op( 00338 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00339 ); 00340 break; 00341 // ------------------------------------------------- 00342 00343 case ExpOp: 00344 CPPAD_ASSERT_NARG_NRES(op, 1, 1) 00345 reverse_sparse_hessian_nonlinear_unary_op( 00346 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00347 ); 00348 break; 00349 // ------------------------------------------------- 00350 00351 case InvOp: 00352 CPPAD_ASSERT_NARG_NRES(op, 0, 1) 00353 // Z is already defined 00354 break; 00355 // ------------------------------------------------- 00356 00357 case LdpOp: 00358 reverse_sparse_hessian_load_op( 00359 op, 00360 i_var, 00361 arg, 00362 num_vecad_ind, 00363 vecad_ind, 00364 rev_hes_sparse, 00365 vecad_sparse, 00366 RevJac, 00367 vecad_jac 00368 ); 00369 break; 00370 // ------------------------------------------------- 00371 00372 case LdvOp: 00373 reverse_sparse_hessian_load_op( 00374 op, 00375 i_var, 00376 arg, 00377 num_vecad_ind, 00378 vecad_ind, 00379 rev_hes_sparse, 00380 vecad_sparse, 00381 RevJac, 00382 vecad_jac 00383 ); 00384 break; 00385 // ------------------------------------------------- 00386 00387 case LogOp: 00388 CPPAD_ASSERT_NARG_NRES(op, 1, 1) 00389 reverse_sparse_hessian_nonlinear_unary_op( 00390 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00391 ); 00392 break; 00393 // ------------------------------------------------- 00394 00395 case MulvvOp: 00396 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00397 reverse_sparse_hessian_mul_op( 00398 i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse 00399 ); 00400 break; 00401 // ------------------------------------------------- 00402 00403 case MulpvOp: 00404 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00405 reverse_sparse_hessian_linear_unary_op( 00406 i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse 00407 ); 00408 break; 00409 // ------------------------------------------------- 00410 00411 case ParOp: 00412 CPPAD_ASSERT_NARG_NRES(op, 1, 1) 00413 00414 break; 00415 // ------------------------------------------------- 00416 00417 case PowpvOp: 00418 CPPAD_ASSERT_NARG_NRES(op, 2, 3) 00419 reverse_sparse_hessian_nonlinear_unary_op( 00420 i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse 00421 ); 00422 break; 00423 // ------------------------------------------------- 00424 00425 case PowvpOp: 00426 CPPAD_ASSERT_NARG_NRES(op, 2, 3) 00427 reverse_sparse_hessian_nonlinear_unary_op( 00428 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00429 ); 00430 break; 00431 // ------------------------------------------------- 00432 00433 case PowvvOp: 00434 CPPAD_ASSERT_NARG_NRES(op, 2, 3) 00435 reverse_sparse_hessian_pow_op( 00436 i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse 00437 ); 00438 break; 00439 // ------------------------------------------------- 00440 00441 case PripOp: 00442 CPPAD_ASSERT_NARG_NRES(op, 2, 0); 00443 break; 00444 // ------------------------------------------------- 00445 00446 case PrivOp: 00447 CPPAD_ASSERT_NARG_NRES(op, 2, 0); 00448 break; 00449 // ------------------------------------------------- 00450 00451 case SinOp: 00452 // sine and cosine must come in pairs 00453 // but i_var should only be used here 00454 CPPAD_ASSERT_NARG_NRES(op, 1, 2) 00455 reverse_sparse_hessian_nonlinear_unary_op( 00456 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00457 ); 00458 break; 00459 // ------------------------------------------------- 00460 00461 case SinhOp: 00462 // sine and cosine must come in pairs 00463 // but i_var should only be used here 00464 CPPAD_ASSERT_NARG_NRES(op, 1, 2) 00465 reverse_sparse_hessian_nonlinear_unary_op( 00466 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00467 ); 00468 break; 00469 // ------------------------------------------------- 00470 00471 case SqrtOp: 00472 CPPAD_ASSERT_NARG_NRES(op, 1, 1) 00473 reverse_sparse_hessian_nonlinear_unary_op( 00474 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00475 ); 00476 break; 00477 // ------------------------------------------------- 00478 00479 case StppOp: 00480 // sparsity cannot propagate through a parameter 00481 CPPAD_ASSERT_NARG_NRES(op, 3, 0) 00482 break; 00483 // ------------------------------------------------- 00484 00485 case StpvOp: 00486 reverse_sparse_hessian_store_op( 00487 op, 00488 arg, 00489 num_vecad_ind, 00490 vecad_ind, 00491 rev_hes_sparse, 00492 vecad_sparse, 00493 RevJac, 00494 vecad_jac 00495 ); 00496 break; 00497 // ------------------------------------------------- 00498 00499 case StvpOp: 00500 // sparsity cannot propagate through a parameter 00501 CPPAD_ASSERT_NARG_NRES(op, 3, 0) 00502 break; 00503 // ------------------------------------------------- 00504 00505 case StvvOp: 00506 reverse_sparse_hessian_store_op( 00507 op, 00508 arg, 00509 num_vecad_ind, 00510 vecad_ind, 00511 rev_hes_sparse, 00512 vecad_sparse, 00513 RevJac, 00514 vecad_jac 00515 ); 00516 break; 00517 // ------------------------------------------------- 00518 00519 case SubvvOp: 00520 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00521 reverse_sparse_hessian_addsub_op( 00522 i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse 00523 ); 00524 break; 00525 // ------------------------------------------------- 00526 00527 case SubpvOp: 00528 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00529 reverse_sparse_hessian_linear_unary_op( 00530 i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse 00531 ); 00532 break; 00533 // ------------------------------------------------- 00534 00535 case SubvpOp: 00536 CPPAD_ASSERT_NARG_NRES(op, 2, 1) 00537 reverse_sparse_hessian_linear_unary_op( 00538 i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse 00539 ); 00540 break; 00541 // ------------------------------------------------- 00542 00543 case UserOp: 00544 // start or end an atomic operation sequence 00545 CPPAD_ASSERT_UNKNOWN( NumRes( UserOp ) == 0 ); 00546 CPPAD_ASSERT_UNKNOWN( NumArg( UserOp ) == 4 ); 00547 if( user_state == user_end ) 00548 { user_index = arg[0]; 00549 user_id = arg[1]; 00550 user_n = arg[2]; 00551 user_m = arg[3]; 00552 if(user_ix.size() < user_n) 00553 { user_ix.resize(user_n); 00554 user_r.resize(user_n); 00555 user_t.resize(user_n); 00556 user_v.resize(user_n); 00557 } 00558 if(user_s.size() < user_m) 00559 { user_s.resize(user_m); 00560 user_u.resize(user_m); 00561 } 00562 user_j = user_n; 00563 user_i = user_m; 00564 user_state = user_ret; 00565 } 00566 else 00567 { CPPAD_ASSERT_UNKNOWN( user_state == user_start ); 00568 CPPAD_ASSERT_UNKNOWN( user_index == arg[0] ); 00569 CPPAD_ASSERT_UNKNOWN( user_id == arg[1] ); 00570 CPPAD_ASSERT_UNKNOWN( user_n == arg[2] ); 00571 CPPAD_ASSERT_UNKNOWN( user_m == arg[3] ); 00572 user_state = user_end; 00573 00574 // call users function for this operation 00575 user_atomic<Base>::rev_hes_sparse(user_index, user_id, 00576 user_n, user_m, 00577 user_q, user_r, user_s, user_t, user_u, user_v 00578 ); 00579 for(j = 0; j < user_n; j++) if( user_ix[j] > 0 ) 00580 { size_t i_x = user_ix[j]; 00581 RevJac[i_x] = user_t[j]; 00582 set_itr = user_v[j].begin(); 00583 set_end = user_v[j].end(); 00584 while( set_itr != set_end ) 00585 rev_hes_sparse.add_element(i_x, *set_itr++); 00586 } 00587 } 00588 break; 00589 00590 case UsrapOp: 00591 // parameter argument in an atomic operation sequence 00592 CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); 00593 CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); 00594 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00595 CPPAD_ASSERT_UNKNOWN( arg[0] < num_par ); 00596 --user_j; 00597 user_ix[user_j] = 0; 00598 user_r[user_j].clear(); 00599 if( user_j == 0 ) 00600 user_state = user_start; 00601 break; 00602 00603 case UsravOp: 00604 // variable argument in an atomic operation sequence 00605 CPPAD_ASSERT_UNKNOWN( user_state == user_arg ); 00606 CPPAD_ASSERT_UNKNOWN( 0 < user_j && user_j <= user_n ); 00607 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00608 CPPAD_ASSERT_UNKNOWN( arg[0] <= i_var ); 00609 CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); 00610 --user_j; 00611 user_ix[user_j] = arg[0]; 00612 user_r[user_j].clear(); 00613 for_jac_sparse.begin(arg[0]); 00614 i = for_jac_sparse.next_element(); 00615 while( i < user_q ) 00616 { user_r[user_j].insert(i); 00617 i = for_jac_sparse.next_element(); 00618 } 00619 if( user_j == 0 ) 00620 user_state = user_start; 00621 break; 00622 00623 case UsrrpOp: 00624 // parameter result in an atomic operation sequence 00625 CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); 00626 CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); 00627 CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); 00628 CPPAD_ASSERT_UNKNOWN( arg[0] < num_par ); 00629 --user_i; 00630 user_s[user_i] = false; 00631 user_u[user_i].clear(); 00632 if( user_i == 0 ) 00633 user_state = user_arg; 00634 break; 00635 00636 case UsrrvOp: 00637 // variable result in an atomic operation sequence 00638 CPPAD_ASSERT_UNKNOWN( user_state == user_ret ); 00639 CPPAD_ASSERT_UNKNOWN( 0 < user_i && user_i <= user_m ); 00640 --user_i; 00641 user_s[user_i] = RevJac[i_var]; 00642 user_u[user_i].clear(); 00643 rev_hes_sparse.begin(i_var); 00644 i = rev_hes_sparse.next_element(); 00645 while( i < user_q ) 00646 { user_u[user_i].insert(i); 00647 i = rev_hes_sparse.next_element(); 00648 } 00649 if( user_i == 0 ) 00650 user_state = user_arg; 00651 break; 00652 00653 // ------------------------------------------------- 00654 00655 default: 00656 CPPAD_ASSERT_UNKNOWN(0); 00657 } 00658 # if CPPAD_REV_HES_SWEEP_TRACE 00659 for(j = 0; j < limit; j++) 00660 { zf_value[j] = false; 00661 zh_value[j] = false; 00662 } 00663 for_jac_sparse.begin(i_var);; 00664 j = for_jac_sparse.next_element();; 00665 while( j < limit ) 00666 { zf_value[j] = true; 00667 j = for_jac_sparse.next_element(); 00668 } 00669 rev_hes_sparse.begin(i_var);; 00670 j = rev_hes_sparse.next_element();; 00671 while( j < limit ) 00672 { zh_value[j] = true; 00673 j = rev_hes_sparse.next_element(); 00674 } 00675 // should also print RevJac[i_var], but printOp does not 00676 // yet allow for this. 00677 printOp( 00678 std::cout, 00679 play, 00680 i_var, 00681 op, 00682 arg, 00683 1, 00684 &zf_value, 00685 1, 00686 &zh_value 00687 ); 00688 # endif 00689 } 00690 // values corresponding to BeginOp 00691 CPPAD_ASSERT_UNKNOWN( i_op == 0 ); 00692 CPPAD_ASSERT_UNKNOWN( i_var == 0 ); 00693 00694 if( vecad_jac != CPPAD_NULL ) 00695 CPPAD_TRACK_DEL_VEC(vecad_jac); 00696 if( vecad_ind != CPPAD_NULL ) 00697 CPPAD_TRACK_DEL_VEC(vecad_ind); 00698 return; 00699 } 00700 00701 # undef CPPAD_REV_HES_SWEEP_TRACE 00702 00703 CPPAD_END_NAMESPACE 00704 # endif