void for_hes( const local::player<Base>* play, size_t n, size_t numvar, const Vector_set& for_jac_sparse, const Vector_set& rev_jac_sparse, Vector_set& for_hes_sparse, const RecBase& not_used_rec_base ) { // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); size_t i, j, k; // check numvar argument size_t limit = n+1; CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( for_hes_sparse.n_set() == limit ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // upper limit exclusive for set elements CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit ); CPPAD_ASSERT_UNKNOWN( for_hes_sparse.end() == limit ); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index for the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparse; pod_vector<size_t> vecad_ind; pod_vector<bool> vecad_jac; if( num_vecad_vec > 0 ) { size_t length; vecad_sparse.resize(num_vecad_vec, limit); vecad_ind.extend(num_vecad_ind); vecad_jac.extend(num_vecad_vec); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set vecad_ind to proper index for this VecAD vecad_ind[j] = i; // make all other values for this vector invalid for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // start of next VecAD j += length + 1; // initialize this vector's reverse jacobian value vecad_jac[i] = false; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // ------------------------------------------------------------------------ // work space used by AFunOp. vector<Base> atom_x; //// value of parameter arguments to function vector<ad_type_enum> type_x; // argument types pod_vector<size_t> atom_ix; // variable index (on tape) for each argument pod_vector<size_t> atom_iy; // variable index (on tape) for each result // // information set by atomic forward (initialization to avoid warnings) size_t atom_index=0, atom_old=0, atom_m=0, atom_n=0, atom_i=0, atom_j=0; // information set by atomic forward (necessary initialization) enum_atom_state atom_state = start_atom; // ------------------------------------------------------------------------- // // pointer to the beginning of the parameter vector // (used by atomic functions) const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // // which parametes are dynamic const pod_vector<bool>& dyn_par_is( play->dyn_par_is() ); // // skip the BeginOp at the beginning of the recording play::const_sequential_iterator itr = play->begin(); // op_info OpCode op; size_t i_var; const Addr* arg; itr.op_info(op, arg, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); # if CPPAD_FOR_HES_TRACE vector<size_t> atom_funrp; // parameter index for FunrpOp operators std::cout << std::endl; CppAD::vectorBool zf_value(limit); CppAD::vectorBool zh_value(limit * limit); # endif bool flag; // temporary for use in switch cases below bool more_operators = true; while(more_operators) { // next op (++itr).op_info(op, arg, i_var); // does the Hessian in question have a non-zero derivative // with respect to this variable bool include = NumRes(op) > 0; if( include ) include = rev_jac_sparse.is_element(i_var, 0); // // operators to include even if derivative is zero include |= op == EndOp; include |= op == CSkipOp; include |= op == CSumOp; include |= op == AFunOp; include |= op == FunapOp; include |= op == FunavOp; include |= op == FunrpOp; include |= op == FunrvOp; // if( include ) switch( op ) { // operators that should not occurr // case BeginOp // ------------------------------------------------- // operators that do not affect hessian case AbsOp: case AddvvOp: case AddpvOp: case CExpOp: case DisOp: case DivvpOp: case InvOp: case LdpOp: case LdvOp: case MulpvOp: case ParOp: case PriOp: case SignOp: case StppOp: case StpvOp: case StvpOp: case StvvOp: case SubvvOp: case SubpvOp: case SubvpOp: case ZmulpvOp: case ZmulvpOp: break; // ------------------------------------------------- // nonlinear unary operators case AcosOp: case AsinOp: case AtanOp: case CosOp: case CoshOp: case ExpOp: case LogOp: case SinOp: case SinhOp: case SqrtOp: case TanOp: case TanhOp: # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: case AsinhOp: case AtanhOp: case Expm1Op: case Log1pOp: # endif CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ) forward_sparse_hessian_nonlinear_unary_op( size_t(arg[0]), for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case CSkipOp: itr.correct_before_increment(); break; // ------------------------------------------------- case CSumOp: itr.correct_before_increment(); break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_div_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_nonlinear_unary_op( size_t(arg[1]), for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[2] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); forward_sparse_hessian_nonlinear_unary_op( size_t(arg[0]), for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- // ------------------------------------------------- // logical comparision operators case EqppOp: case EqpvOp: case EqvvOp: case LtppOp: case LtpvOp: case LtvpOp: case LtvvOp: case LeppOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NeppOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_mul_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_nonlinear_unary_op( size_t(arg[1]), for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_nonlinear_unary_op( size_t(arg[0]), for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_pow_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case AFunOp: // start or end an atomic function call CPPAD_ASSERT_UNKNOWN( atom_state == start_atom || atom_state == end_atom ); flag = atom_state == start_atom; play::atom_op_info<RecBase>( op, arg, atom_index, atom_old, atom_m, atom_n ); if( flag ) { atom_state = arg_atom; atom_i = 0; atom_j = 0; // atom_x.resize( atom_n ); type_x.resize( atom_n ); atom_ix.resize( atom_n ); atom_iy.resize( atom_m ); # if CPPAD_FOR_HES_TRACE atom_funrp.resize( atom_m ); # endif } else { CPPAD_ASSERT_UNKNOWN( atom_i == atom_m ); CPPAD_ASSERT_UNKNOWN( atom_j == atom_n ); atom_state = start_atom; // call_atomic_for_hes_sparsity<Base,RecBase>( atom_index, atom_old, atom_x, type_x, atom_ix, atom_iy, for_jac_sparse, rev_jac_sparse, for_hes_sparse ); } break; case FunapOp: // parameter argument for a atomic function CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( atom_state == arg_atom ); CPPAD_ASSERT_UNKNOWN( atom_i == 0 ); CPPAD_ASSERT_UNKNOWN( atom_j < atom_n ); CPPAD_ASSERT_UNKNOWN( size_t( arg[0] ) < num_par ); // atom_x[atom_j] = parameter[arg[0]]; // argument type if( dyn_par_is[arg[0]] ) type_x[atom_j] = dynamic_enum; else type_x[atom_j] = constant_enum; atom_ix[atom_j] = 0; // special variable used for parameters // ++atom_j; if( atom_j == atom_n ) atom_state = ret_atom; break; case FunavOp: // variable argument for a atomic function CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ); CPPAD_ASSERT_UNKNOWN( atom_state == arg_atom ); CPPAD_ASSERT_UNKNOWN( atom_i == 0 ); CPPAD_ASSERT_UNKNOWN( atom_j < atom_n ); // // arguemnt variables not avaialbe during sparisty calculations atom_x[atom_j] = CppAD::numeric_limits<Base>::quiet_NaN(); type_x[atom_j] = variable_enum; atom_ix[atom_j] = size_t(arg[0]); // variable for this argument // ++atom_j; if( atom_j == atom_n ) atom_state = ret_atom; break; case FunrpOp: // parameter result for a atomic function CPPAD_ASSERT_NARG_NRES(op, 1, 0); CPPAD_ASSERT_UNKNOWN( atom_state == ret_atom ); CPPAD_ASSERT_UNKNOWN( atom_i < atom_m ); CPPAD_ASSERT_UNKNOWN( atom_j == atom_n ); CPPAD_ASSERT_UNKNOWN( size_t( arg[0] ) < num_par ); // atom_iy[atom_i] = 0; // special variable used for parameters # if CPPAD_FOR_HES_TRACE // remember argument for delayed tracing atom_funrp[atom_i] = arg[0]; # endif ++atom_i; if( atom_i == atom_m ) atom_state = end_atom; break; case FunrvOp: // variable result for a atomic function CPPAD_ASSERT_NARG_NRES(op, 0, 1); CPPAD_ASSERT_UNKNOWN( atom_state == ret_atom ); CPPAD_ASSERT_UNKNOWN( atom_i < atom_m ); CPPAD_ASSERT_UNKNOWN( atom_j == atom_n ); // atom_iy[atom_i] = i_var; // variable index for this result // ++atom_i; if( atom_i == atom_m ) atom_state = end_atom; break; // ------------------------------------------------- case ZmulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_mul_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FOR_HES_TRACE typedef typename Vector_set::const_iterator const_iterator; if( op == AFunOp && atom_state == start_atom ) { // print operators that have been delayed CPPAD_ASSERT_UNKNOWN( atom_m == atom_iy.size() ); CPPAD_ASSERT_UNKNOWN( itr.op_index() > atom_m ); CPPAD_ASSERT_NARG_NRES(FunrpOp, 1, 0); CPPAD_ASSERT_NARG_NRES(FunrvOp, 0, 1); addr_t arg_tmp[1]; for(k = 0; k < atom_m; k++) { size_t k_var = atom_iy[k]; // value for this variable for(i = 0; i < limit; i++) { zf_value[i] = false; for(j = 0; j < limit; j++) zh_value[i * limit + j] = false; } const_iterator itr_1(for_jac_sparse, i_var); j = *itr_1; while( j < limit ) { zf_value[j] = true; j = *(++itr_1); } for(i = 0; i < limit; i++) { const_iterator itr_2(for_hes_sparse, i); j = *itr_2; while( j < limit ) { zh_value[i * limit + j] = true; j = *(++itr_2); } } OpCode op_tmp = FunrvOp; if( k_var == 0 ) { op_tmp = FunrpOp; arg_tmp[0] = atom_funrp[k]; } // k_var is zero when there is no result printOp<Base, RecBase>( std::cout, play, itr.op_index() - atom_m + k, k_var, op_tmp, arg_tmp ); if( k_var > 0 ) printOpResult( std::cout, 1, &zf_value, 1, &zh_value ); std::cout << std::endl; } } for(i = 0; i < limit; i++) { zf_value[i] = false; for(j = 0; j < limit; j++) zh_value[i * limit + j] = false; } const_iterator itr_1(for_jac_sparse, i_var); j = *itr_1; while( j < limit ) { zf_value[j] = true; j = *(++itr_1); } for(i = 0; i < limit; i++) { const_iterator itr_2(for_hes_sparse, i); j = *itr_2; while( j < limit ) { zh_value[i * limit + j] = true; j = *(++itr_2); } } // must delay print for these cases till after atomic function call bool delay_print = op == FunrpOp; delay_print |= op == FunrvOp; if( ! delay_print ) { printOp<Base, RecBase>( std::cout, play, itr.op_index(), i_var, op, arg ); if( NumRes(op) > 0 && (! delay_print) ) printOpResult( std::cout, 1, &zf_value, 1, &zh_value ); std::cout << std::endl; } } std::cout << std::endl; # else }
void ADFun<Base,RecBase>::ForSparseHesCase( const std::set<size_t>& set_type , const SetVector& r , const SetVector& s , SetVector& h ) { // used to identify the RecBase type in calls to sweeps RecBase not_used_rec_base; // size_t n = Domain(); # ifndef NDEBUG size_t m = Range(); # endif std::set<size_t>::const_iterator itr_1; // // check SetVector is Simple Vector class with sets for elements CheckSimpleVector<std::set<size_t>, SetVector>( local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>() ); CPPAD_ASSERT_KNOWN( r.size() == 1, "ForSparseHes: size of s is not equal to one." ); CPPAD_ASSERT_KNOWN( s.size() == 1, "ForSparseHes: size of s is not equal to one." ); // // sparsity pattern corresponding to r local::sparse_list for_jac_pattern; for_jac_pattern.resize(num_var_tape_, n + 1); itr_1 = r[0].begin(); while( itr_1 != r[0].end() ) { size_t i = *itr_1++; CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] < n + 1 ); // ind_taddr_[i] is operator taddr for i-th independent variable CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp ); // // Use add_element when only adding one element per set is added. for_jac_pattern.add_element( ind_taddr_[i], ind_taddr_[i] ); } // compute forward Jacobiain sparsity pattern bool dependency = false; local::sweep::for_jac<addr_t>( &play_, dependency, n, num_var_tape_, for_jac_pattern, not_used_rec_base ); // sparsity pattern correspnding to s local::sparse_list rev_jac_pattern; rev_jac_pattern.resize(num_var_tape_, 1); itr_1 = s[0].begin(); while( itr_1 != s[0].end() ) { size_t i = *itr_1++; CPPAD_ASSERT_KNOWN( i < m, "ForSparseHes: an element of the set s[0] has value " "greater than or equal m" ); CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ ); // // Use add_element when only adding one element per set is added. rev_jac_pattern.add_element( dep_taddr_[i], 0); } // // compute reverse sparsity pattern for dependency analysis // (note that we are only want non-zero derivatives not true dependency) local::sweep::rev_jac<addr_t>( &play_, dependency, n, num_var_tape_, rev_jac_pattern, not_used_rec_base ); // // vector of sets that will hold reverse Hessain values local::sparse_list for_hes_pattern; for_hes_pattern.resize(n+1, n+1); // // compute the Hessian sparsity patterns local::sweep::for_hes<addr_t>( &play_, n, num_var_tape_, for_jac_pattern, rev_jac_pattern, for_hes_pattern, not_used_rec_base ); // return values corresponding to independent variables // j is index corresponding to reverse mode partial h.resize(n); CPPAD_ASSERT_UNKNOWN( for_hes_pattern.end() == n+1 ); for(size_t i = 0; i < n; i++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] == i + 1 ); CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp ); // extract the result from for_hes_pattern local::sparse_list::const_iterator itr_2(for_hes_pattern, ind_taddr_[i] ); size_t j = *itr_2; while( j < for_hes_pattern.end() ) { CPPAD_ASSERT_UNKNOWN( 0 < j ) h[i].insert(j-1); j = *(++itr_2); } } }
void ForHesSweep( size_t n, size_t numvar, local::player<Base>* play, const Vector_set& for_jac_sparse, const Vector_set& rev_jac_sparse, Vector_set& for_hes_sparse ) { OpCode op; size_t i_op; size_t i_var; const addr_t* arg = CPPAD_NULL; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_par_rec(); size_t i, j, k; // check numvar argument size_t limit = n+1; CPPAD_ASSERT_UNKNOWN( play->num_var_rec() == numvar ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( for_hes_sparse.n_set() == limit ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // upper limit exclusive for set elements CPPAD_ASSERT_UNKNOWN( for_jac_sparse.end() == limit ); CPPAD_ASSERT_UNKNOWN( for_hes_sparse.end() == limit ); // vecad_sparsity contains a sparsity pattern for each VecAD object. // vecad_ind maps a VecAD index (beginning of the VecAD object) // to the index for the corresponding set in vecad_sparsity. size_t num_vecad_ind = play->num_vec_ind_rec(); size_t num_vecad_vec = play->num_vecad_vec_rec(); Vector_set vecad_sparse; vecad_sparse.resize(num_vecad_vec, limit); pod_vector<size_t> vecad_ind; pod_vector<bool> vecad_jac; if( num_vecad_vec > 0 ) { size_t length; vecad_ind.extend(num_vecad_ind); vecad_jac.extend(num_vecad_vec); j = 0; for(i = 0; i < num_vecad_vec; i++) { // length of this VecAD length = play->GetVecInd(j); // set vecad_ind to proper index for this VecAD vecad_ind[j] = i; // make all other values for this vector invalid for(k = 1; k <= length; k++) vecad_ind[j+k] = num_vecad_vec; // start of next VecAD j += length + 1; // initialize this vector's reverse jacobian value vecad_jac[i] = false; } CPPAD_ASSERT_UNKNOWN( j == play->num_vec_ind_rec() ); } // ------------------------------------------------------------------------ // user's atomic op calculator atomic_base<Base>* user_atom = CPPAD_NULL; // user's atomic op calculator // // work space used by UserOp. vector<Base> user_x; // value of parameter arguments to function vector<size_t> user_ix; // variable index (on tape) for each argument vector<size_t> user_iy; // variable index (on tape) for each result // // information set by forward_user (initialization to avoid warnings) size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0; // information set by forward_user (necessary initialization) enum_user_state user_state = start_user; // ------------------------------------------------------------------------- // // pointer to the beginning of the parameter vector // (used by user atomic functions) const Base* parameter = CPPAD_NULL; if( num_par > 0 ) parameter = play->GetPar(); // Initialize play->forward_start(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == BeginOp ); bool more_operators = true; # if CPPAD_FOR_HES_SWEEP_TRACE vector<size_t> user_usrrp; // parameter index for UsrrpOp operators CppAD::vectorBool zf_value(limit); CppAD::vectorBool zh_value(limit * limit); # endif bool flag; // temporary for use in switch cases below while(more_operators) { // next op play->forward_next(op, arg, i_op, i_var); # ifndef NDEBUG if( i_op <= n ) { CPPAD_ASSERT_UNKNOWN((op == InvOp) | (op == BeginOp)); } else CPPAD_ASSERT_UNKNOWN((op != InvOp) & (op != BeginOp)); # endif // does the Hessian in question have a non-zero derivative // with respect to this variable bool include = rev_jac_sparse.is_element(i_var, 0); // // operators to include even if derivative is zero include |= op == EndOp; include |= op == CSkipOp; include |= op == CSumOp; include |= op == UserOp; include |= op == UsrapOp; include |= op == UsravOp; include |= op == UsrrpOp; include |= op == UsrrvOp; // if( include ) switch( op ) { // operators that should not occurr // case BeginOp // ------------------------------------------------- // operators that do not affect hessian case AbsOp: case AddvvOp: case AddpvOp: case CExpOp: case DisOp: case DivvpOp: case InvOp: case LdpOp: case LdvOp: case MulpvOp: case ParOp: case PriOp: case SignOp: case StppOp: case StpvOp: case StvpOp: case StvvOp: case SubvvOp: case SubpvOp: case SubvpOp: case ZmulpvOp: case ZmulvpOp: break; // ------------------------------------------------- // nonlinear unary operators case AcosOp: case AsinOp: case AtanOp: case CosOp: case CoshOp: case ExpOp: case LogOp: case SinOp: case SinhOp: case SqrtOp: case TanOp: case TanhOp: # if CPPAD_USE_CPLUSPLUS_2011 case AcoshOp: case AsinhOp: case AtanhOp: case Expm1Op: case Log1pOp: # endif CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 ) forward_sparse_hessian_nonlinear_unary_op( arg[0], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case CSkipOp: // CSkipOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->forward_cskip(op, arg, i_op, i_var); break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // reverse_next thinks it one has one argument. // We must inform reverse_next of this special case. play->forward_csum(op, arg, i_op, i_var); break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_div_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_nonlinear_unary_op( arg[1], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case EndOp: CPPAD_ASSERT_NARG_NRES(op, 0, 0); more_operators = false; break; // ------------------------------------------------- case ErfOp: // arg[1] is always the parameter 0 // arg[2] is always the parameter 2 / sqrt(pi) CPPAD_ASSERT_NARG_NRES(op, 3, 5); forward_sparse_hessian_nonlinear_unary_op( arg[0], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- // ------------------------------------------------- // logical comparision operators case EqpvOp: case EqvvOp: case LtpvOp: case LtvpOp: case LtvvOp: case LepvOp: case LevpOp: case LevvOp: case NepvOp: case NevvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_mul_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_nonlinear_unary_op( arg[1], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_nonlinear_unary_op( arg[0], for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) forward_sparse_hessian_pow_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- case UserOp: CPPAD_ASSERT_UNKNOWN( user_state == start_user || user_state == end_user ); flag = user_state == start_user; user_atom = play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); if( flag ) { // start of user atomic operation sequence user_x.resize( user_n ); user_ix.resize( user_n ); user_iy.resize( user_m ); # if CPPAD_FOR_HES_SWEEP_TRACE user_usrrp.resize( user_m ); # endif } else { // end of user atomic operation sequence user_atom->set_old(user_old); user_atom->for_sparse_hes( user_x, user_ix, user_iy, for_jac_sparse, rev_jac_sparse, for_hes_sparse ); } break; case UsrapOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); // argument parameter value user_x[user_j] = parameter[arg[0]]; // special variable user for parameters user_ix[user_j] = 0; // play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); break; case UsravOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) <= i_var ); CPPAD_ASSERT_UNKNOWN( 0 < arg[0] ); // arguemnt varialbes not avaialbe during sparisty calculations user_x[user_j] = CppAD::numeric_limits<Base>::quiet_NaN(); // varialbe index for this argument user_ix[user_j] = arg[0]; // play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); break; case UsrrpOp: CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < num_par ); // special variable index user for parameters user_iy[user_i] = 0; # if CPPAD_FOR_HES_SWEEP_TRACE // remember argument for delayed tracing user_usrrp[user_i] = arg[0]; # endif // play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); break; case UsrrvOp: // variable index for this result user_iy[user_i] = i_var; // play->forward_user(op, user_state, user_old, user_m, user_n, user_i, user_j ); break; // ------------------------------------------------- case ZmulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) forward_sparse_hessian_mul_op( arg, for_jac_sparse, for_hes_sparse ); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_FOR_HES_SWEEP_TRACE typedef typename Vector_set::const_iterator const_iterator; if( op == UserOp && user_state == start_user ) { // print operators that have been delayed CPPAD_ASSERT_UNKNOWN( user_m == user_iy.size() ); CPPAD_ASSERT_UNKNOWN( i_op > user_m ); CPPAD_ASSERT_NARG_NRES(UsrrpOp, 1, 0); CPPAD_ASSERT_NARG_NRES(UsrrvOp, 0, 1); addr_t arg_tmp[1]; for(k = 0; k < user_m; k++) { size_t k_var = user_iy[k]; // value for this variable for(i = 0; i < limit; i++) { zf_value[i] = false; for(j = 0; j < limit; j++) zh_value[i * limit + j] = false; } const_iterator itr_1(for_jac_sparse, i_var); j = *itr_1; while( j < limit ) { zf_value[j] = true; j = *(++itr_1); } for(i = 0; i < limit; i++) { const_iterator itr_2(for_hes_sparse, i); j = *itr_2; while( j < limit ) { zh_value[i * limit + j] = true; j = *(++itr_2); } } OpCode op_tmp = UsrrvOp; if( k_var == 0 ) { op_tmp = UsrrpOp; arg_tmp[0] = user_usrrp[k]; } // k_var is zero when there is no result //printOp( // std::cout, // play, // i_op - user_m + k, // k_var, // op_tmp, // arg_tmp //); if( k_var > 0 ){ // printOpResult( // std::cout, // 1, // &zf_value, // 1, // &zh_value //); } } } const addr_t* arg_tmp = arg; if( op == CSumOp ) arg_tmp = arg - arg[-1] - 4; if( op == CSkipOp ) arg_tmp = arg - arg[-1] - 7; for(i = 0; i < limit; i++) { zf_value[i] = false; for(j = 0; j < limit; j++) zh_value[i * limit + j] = false; } const_iterator itr_1(for_jac_sparse, i_var); j = *itr_1; while( j < limit ) { zf_value[j] = true; j = *(++itr_1); } for(i = 0; i < limit; i++) { const_iterator itr_2(for_hes_sparse, i); j = *itr_2; while( j < limit ) { zh_value[i * limit + j] = true; j = *(++itr_2); } } // must delay print for these cases till after atomic user call bool delay_print = op == UsrrpOp; delay_print |= op == UsrrvOp; if( ! delay_print ) { // printOp( // std::cout, // play, // i_op, // i_var, // op, // arg_tmp //); if( NumRes(op) > 0 && (! delay_print) ){ // printOpResult( // std::cout, // 1, // &zf_value, // 1, // &zh_value // ); } } } # else }