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