CppAD: A C++ Algorithmic Differentiation Package 20110419
rev_hes_sweep.hpp
Go to the documentation of this file.
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