vec<Scalar>::~vec(void) { if( handle_ != 0 ) CPPAD_TRACK_DEL_VEC(handle_); if( pointer_ != 0 ) CPPAD_TRACK_DEL_VEC(pointer_); }
void vec<Scalar>::resize(size_t length) { if( handle_ != 0 ) CPPAD_TRACK_DEL_VEC(handle_); if( pointer_ != 0 ) CPPAD_TRACK_DEL_VEC(pointer_); pointer_ = CPPAD_TRACK_NEW_VEC(length, pointer_); handle_ = CPPAD_TRACK_NEW_VEC(length, handle_); length_ = length; for(size_t i = 0; i < length_; i++) handle_[i] = pointer_ + i; }
// resize void vec<double>::resize(size_t length) { if( allocated_ ) CPPAD_TRACK_DEL_VEC(pointer_); pointer_ = CPPAD_TRACK_NEW_VEC(length, pointer_); length_ = length; allocated_ = true; }
bool track_new_del(void) { bool ok = true; // initial count size_t count = CPPAD_TRACK_COUNT(); // allocate an array of lenght 5 double *ptr = CPPAD_NULL; size_t newlen = 5; ptr = CPPAD_TRACK_NEW_VEC(newlen, ptr); // copy data into the array size_t ncopy = newlen; size_t i; for(i = 0; i < ncopy; i++) ptr[i] = double(i); // extend the buffer to be lenght 10 newlen = 10; ptr = CPPAD_TRACK_EXTEND(newlen, ncopy, ptr); // copy data into the new part of the array for(i = ncopy; i < newlen; i++) ptr[i] = double(i); // check the values in the array for(i = 0; i < newlen; i++) ok &= (ptr[i] == double(i)); // free the memory allocated since previous call to TrackCount CPPAD_TRACK_DEL_VEC(ptr); // check for memory leak ok &= (count == CPPAD_TRACK_COUNT()); return ok; }
void ADFun<Base>::optimize(void) { // place to store the optimized version of the recording recorder<Base> rec; // number of independent variables size_t n = ind_taddr_.size(); # ifndef NDEBUG size_t i, j, m = dep_taddr_.size(); CppAD::vector<Base> x(n), y(m), check(m); bool check_zero_order = taylor_per_var_ > 0; if( check_zero_order ) { // zero order coefficients for independent vars for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == InvOp ); CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j+1 ); x[j] = taylor_[ ind_taddr_[j] * taylor_col_dim_ + 0]; } // zero order coefficients for dependent vars for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < total_num_var_ ); y[i] = taylor_[ dep_taddr_[i] * taylor_col_dim_ + 0]; } } # endif // create the optimized recording CppAD::optimize<Base>(n, dep_taddr_, &play_, &rec); // now replace the recording play_ = rec; // number of variables in the recording total_num_var_ = rec.num_rec_var(); // free memory allocated for sparse Jacobian calculation // (the results are no longer valid) for_jac_sparse_pack_.resize(0, 0); for_jac_sparse_set_.resize(0,0); // free old Taylor coefficient memory if( taylor_ != CPPAD_NULL ) CPPAD_TRACK_DEL_VEC(taylor_); taylor_ = CPPAD_NULL; taylor_per_var_ = 0; taylor_col_dim_ = 0; # ifndef NDEBUG if( check_zero_order ) { // zero order forward calculation using new operation sequence check = Forward(0, x); // check results for(i = 0; i < m; i++) CPPAD_ASSERT_KNOWN( check[i] == y[i] , "Error during check of f.optimize()." ); // Erase memory that this calculation was done so NDEBUG gives // same final state for this object (from users perspective) taylor_per_var_ = 0; } # endif }
// destructor vec<double>::~vec(void) { if( allocated_ ) CPPAD_TRACK_DEL_VEC(pointer_); }
bool link_sparse_hessian( size_t repeat , CppAD::vector<double> &x_arg , CppAD::vector<size_t> &i , CppAD::vector<size_t> &j , CppAD::vector<double> &h ) { // ----------------------------------------------------- // setup size_t k, m; size_t order = 0; // derivative order corresponding to function size_t tag = 0; // tape identifier size_t keep = 1; // keep forward mode results in buffer size_t n = x_arg.size(); // number of independent variables size_t ell = i.size(); // number of indices in i and j double f; // function value typedef CppAD::vector<double> DblVector; typedef CppAD::vector<adouble> ADVector; typedef CppAD::vector<size_t> SizeVector; ADVector X(n); // AD domain space vector double *x; // double domain space vector double **H; // Hessian ADVector Y(1); // AD range space value DblVector tmp(2 * ell); // double temporary vector x = 0; x = CPPAD_TRACK_NEW_VEC(n, x); H = 0; H = CPPAD_TRACK_NEW_VEC(n, H); for(k = 0; k < n; k++) { H[k] = 0; H[k] = CPPAD_TRACK_NEW_VEC(n, H[k]); } // choose a value for x CppAD::uniform_01(n, x); for(k = 0; k < n; k++) x_arg[k] = x[k]; // ------------------------------------------------------ while(repeat--) { // get the next set of indices CppAD::uniform_01(2 * ell, tmp); for(k = 0; k < ell; k++) { i[k] = size_t( n * tmp[k] ); i[k] = std::min(n-1, i[k]); // j[k] = size_t( n * tmp[k + ell] ); j[k] = std::min(n-1, j[k]); } // declare independent variables trace_on(tag, keep); for(k = 0; k < n; k++) X[k] <<= x[k]; // AD computation of f(x) CppAD::sparse_evaluate(X, i, j, order, Y); // create function object f : X -> Y Y[0] >>= f; trace_off(); // evaluate and return the hessian of f hessian(int(tag), int(n), x, H); } for(k = 0; k < n; k++) { for(m = 0; m <= k; m++) { h[ k * n + m] = H[k][m]; h[ m * n + k] = H[k][m]; } CPPAD_TRACK_DEL_VEC(H[k]); } CPPAD_TRACK_DEL_VEC(H); CPPAD_TRACK_DEL_VEC(x); return true; }
VectorBase ADFun<Base>::Reverse(size_t p, const VectorBase &w) const { // temporary indices size_t i, j, k; // number of independent variables size_t n = ind_taddr_.size(); // number of dependent variables size_t m = dep_taddr_.size(); Base *Partial = CPPAD_NULL; Partial = CPPAD_TRACK_NEW_VEC(total_num_var_ * p, Partial); // update maximum memory requirement // memoryMax = std::max( memoryMax, // Memory() + total_num_var_ * p * sizeof(Base) // ); // check VectorBase is Simple Vector class with Base type elements CheckSimpleVector<Base, VectorBase>(); CPPAD_ASSERT_KNOWN( w.size() == m, "Argument w to Reverse does not have length equal to\n" "the dimension of the range for the corresponding ADFun." ); CPPAD_ASSERT_KNOWN( p > 0, "The first argument to Reverse must be greater than zero." ); CPPAD_ASSERT_KNOWN( taylor_per_var_ >= p, "Less that p taylor_ coefficients are currently stored" " in this ADFun object." ); // initialize entire Partial matrix to zero for(i = 0; i < total_num_var_; i++) for(j = 0; j < p; j++) Partial[i * p + j] = Base(0); // set the dependent variable direction // (use += because two dependent variables can point to same location) for(i = 0; i < m; i++) { CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < total_num_var_ ); Partial[dep_taddr_[i] * p + p - 1] += w[i]; } // evaluate the derivatives ReverseSweep( p - 1, total_num_var_, &play_, taylor_col_dim_, taylor_, p, Partial ); // return the derivative values VectorBase value(n * p); for(j = 0; j < n; j++) { CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < total_num_var_ ); // independent variable taddr equals its operator taddr CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == InvOp ); // by the Reverse Identity Theorem // partial of y^{(k)} w.r.t. u^{(0)} is equal to // partial of y^{(p-1)} w.r.t. u^{(p - 1 - k)} for(k = 0; k < p; k++) value[j * p + k ] = Partial[ind_taddr_[j] * p + p - 1 - k]; } // done with the Partial array CPPAD_TRACK_DEL_VEC(Partial); return value; }
void RevHesSweep( size_t n, size_t numvar, player<Base> *play, Vector_set& for_jac_sparse, // should be const bool* RevJac, Vector_set& rev_hes_sparse ) { OpCode op; size_t i_op; size_t i_var; const size_t *arg = 0; // length of the parameter vector (used by CppAD assert macros) const size_t num_par = play->num_rec_par(); size_t i, j, k; // check numvar argument CPPAD_ASSERT_UNKNOWN( play->num_rec_var() == numvar ); CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.n_set() == numvar ); CPPAD_ASSERT_UNKNOWN( numvar > 0 ); // upper limit exclusive for set elements size_t limit = rev_hes_sparse.end(); CPPAD_ASSERT_UNKNOWN( rev_hes_sparse.end() == limit ); // check number of sets match CPPAD_ASSERT_UNKNOWN( for_jac_sparse.n_set() == rev_hes_sparse.n_set() ); // 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_rec_vecad_ind(); size_t num_vecad_vec = play->num_rec_vecad_vec(); Vector_set vecad_sparse; vecad_sparse.resize(num_vecad_vec, limit); size_t* vecad_ind = CPPAD_NULL; bool* vecad_jac = CPPAD_NULL; if( num_vecad_vec > 0 ) { size_t length; vecad_ind = CPPAD_TRACK_NEW_VEC(num_vecad_ind, vecad_ind); vecad_jac = CPPAD_TRACK_NEW_VEC(num_vecad_vec, vecad_jac); 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_rec_vecad_ind() ); } // Initialize play->start_reverse(op, arg, i_op, i_var); CPPAD_ASSERT_UNKNOWN( op == EndOp ); # if CPPAD_REV_HES_SWEEP_TRACE std::cout << std::endl; CppAD::vectorBool zf_value(limit); CppAD::vectorBool zh_value(limit); # endif while(op != BeginOp) { // next op play->next_reverse(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 // rest of information depends on the case switch( op ) { case AbsOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AddpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AcosOp: // acos(x) and sqrt(1 - x * x) are computed in pairs // but i_var + 1 should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AsinOp: // asin(x) and sqrt(1 - x * x) are computed in pairs // but i_var + 1 should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case AtanOp: // atan(x) and 1 + x * x must be computed in pairs // but i_var + 1 should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case BeginOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1) break; // ------------------------------------------------- case CSumOp: // CSumOp has a variable number of arguments and // next_reverse thinks it one has one argument. // We must inform next_reverse of this special case. play->reverse_csum(op, arg, i_op, i_var); reverse_sparse_hessian_csum_op( i_var, arg, RevJac, rev_hes_sparse ); break; // ------------------------------------------------- case CExpOp: reverse_sparse_hessian_cond_op( i_var, arg, num_par, RevJac, rev_hes_sparse ); break; // --------------------------------------------------- case ComOp: CPPAD_ASSERT_NARG_NRES(op, 4, 0) CPPAD_ASSERT_UNKNOWN( arg[1] > 1 ); break; // -------------------------------------------------- case CosOp: // cosine and sine must come in pairs // but i_var should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // --------------------------------------------------- case CoshOp: // hyperbolic cosine and sine must come in pairs // but i_var should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DisOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) break; // ------------------------------------------------- case DivvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_div_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case DivvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ExpOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case InvOp: CPPAD_ASSERT_NARG_NRES(op, 0, 1) // Z is already defined break; // ------------------------------------------------- case LdpOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind, rev_hes_sparse, vecad_sparse, RevJac, vecad_jac ); break; // ------------------------------------------------- case LdvOp: reverse_sparse_hessian_load_op( op, i_var, arg, num_vecad_ind, vecad_ind, rev_hes_sparse, vecad_sparse, RevJac, vecad_jac ); break; // ------------------------------------------------- case LogOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case MulvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_mul_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case MulpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case ParOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) break; // ------------------------------------------------- case PowpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PowvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 3) reverse_sparse_hessian_pow_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case PripOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case PrivOp: CPPAD_ASSERT_NARG_NRES(op, 2, 0); break; // ------------------------------------------------- case SinOp: // sine and cosine must come in pairs // but i_var should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SinhOp: // sine and cosine must come in pairs // but i_var should only be used here CPPAD_ASSERT_NARG_NRES(op, 1, 2) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SqrtOp: CPPAD_ASSERT_NARG_NRES(op, 1, 1) reverse_sparse_hessian_nonlinear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case StppOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StpvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind, rev_hes_sparse, vecad_sparse, RevJac, vecad_jac ); break; // ------------------------------------------------- case StvpOp: // sparsity cannot propagate through a parameter CPPAD_ASSERT_NARG_NRES(op, 3, 0) break; // ------------------------------------------------- case StvvOp: reverse_sparse_hessian_store_op( op, arg, num_vecad_ind, vecad_ind, rev_hes_sparse, vecad_sparse, RevJac, vecad_jac ); break; // ------------------------------------------------- case SubvvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_addsub_op( i_var, arg, RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubpvOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[1], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- case SubvpOp: CPPAD_ASSERT_NARG_NRES(op, 2, 1) reverse_sparse_hessian_linear_unary_op( i_var, arg[0], RevJac, for_jac_sparse, rev_hes_sparse ); break; // ------------------------------------------------- default: CPPAD_ASSERT_UNKNOWN(0); } # if CPPAD_REV_HES_SWEEP_TRACE for(j = 0; j < limit; j++) { zf_value[j] = false; zh_value[j] = false; } for_jac_sparse.begin(i_var);; j = for_jac_sparse.next_element();; while( j < limit ) { zf_value[j] = true; j = for_jac_sparse.next_element(); } rev_hes_sparse.begin(i_var);; j = rev_hes_sparse.next_element();; while( j < limit ) { zh_value[j] = true; j = rev_hes_sparse.next_element(); } // should also print RevJac[i_var], but printOp does not // yet allow for this. printOp( std::cout, play, i_var, op, arg, 1, &zf_value, 1, &zh_value ); # endif } // values corresponding to BeginOp CPPAD_ASSERT_UNKNOWN( i_op == 0 ); CPPAD_ASSERT_UNKNOWN( i_var == 0 ); if( vecad_jac != CPPAD_NULL ) CPPAD_TRACK_DEL_VEC(vecad_jac); if( vecad_ind != CPPAD_NULL ) CPPAD_TRACK_DEL_VEC(vecad_ind); return; }