lines 6-222 of file: speed/adolc/sparse_hessian.cpp {xrst_begin adolc_sparse_hessian.cpp} Adolc Speed: Sparse Hessian ########################### Specifications ************** See :ref:`link_sparse_hessian-name` . Implementation ************** {xrst_spell_off} {xrst_code cpp} */ // suppress conversion warnings before other includes # include // # include # include # include # include # include # include # include // list of possible options # include extern std::map global_option; bool link_sparse_hessian( size_t size , size_t repeat , const CppAD::vector& row , const CppAD::vector& col , CppAD::vector& x_return , CppAD::vector& hessian , size_t& n_color ) { if( global_option["atomic"] || (! global_option["colpack"]) ) return false; if( global_option["memory"] || global_option["optimize"] || global_option["boolsparsity"] ) return false; // ----------------------------------------------------- // setup typedef unsigned int* IntVector; typedef double* DblVector; typedef adouble ADScalar; typedef ADScalar* ADVector; size_t order = 0; // derivative order corresponding to function size_t m = 1; // number of dependent variables size_t n = size; // number of independent variables // setup for thread_alloc memory allocator (fast and checks for leaks) using CppAD::thread_alloc; // the allocator size_t capacity; // capacity of an allocation // tape identifier int tag = 0; // AD domain space vector ADVector a_x = thread_alloc::create_array(n, capacity); // AD range space vector ADVector a_y = thread_alloc::create_array(m, capacity); // double argument value DblVector x = thread_alloc::create_array(n, capacity); // double function value double f; // options that control sparse_hess int options[2]; options[0] = 0; // safe mode options[1] = 0; // indirect recovery // structure that holds some of the work done by sparse_hess int nnz; // number of non-zero values IntVector rind = nullptr; // row indices IntVector cind = nullptr; // column indices DblVector values = nullptr; // Hessian values // ---------------------------------------------------------------------- if( ! global_option["onetape"] ) while(repeat--) { // choose a value for x CppAD::uniform_01(n, x); // declare independent variables int keep = 0; // keep forward mode results trace_on(tag, keep); for(size_t j = 0; j < n; j++) a_x[j] <<= x[j]; // AD computation of f (x) CppAD::sparse_hes_fun(n, a_x, row, col, order, a_y); // create function object f : x -> y a_y[0] >>= f; trace_off(); // is this a repeat call with the same sparsity pattern int same_pattern = 0; // calculate the hessian at this x rind = nullptr; cind = nullptr; values = nullptr; sparse_hess(tag, int(n), same_pattern, x, &nnz, &rind, &cind, &values, options ); // free raw memory allocated by sparse_hess // (keep on last repeat for correctness testing) if( repeat != 0 ) { free(rind); free(cind); free(values); } } else { // choose a value for x CppAD::uniform_01(n, x); // declare independent variables int keep = 0; // keep forward mode results trace_on(tag, keep); for(size_t j = 0; j < n; j++) a_x[j] <<= x[j]; // AD computation of f (x) CppAD::sparse_hes_fun(n, a_x, row, col, order, a_y); // create function object f : x -> y a_y[0] >>= f; trace_off(); // is this a repeat call at the same argument int same_pattern = 0; while(repeat--) { // choose a value for x CppAD::uniform_01(n, x); // calculate the hessian at this x sparse_hess(tag, int(n), same_pattern, x, &nnz, &rind, &cind, &values, options ); same_pattern = 1; } } // Adolc returns upper triangle in row major order while row, col are // lower trangle in row major order. CppAD::vector keys(nnz), ind(nnz); for(int ell = 0; ell < nnz; ++ell) { // transpose to get lower triangle size_t i = size_t( cind[ell] ); size_t j = size_t( rind[ell] ); keys[ell] = i * n + j; // row major order for lower triangle } CppAD::index_sort(keys, ind); size_t k = 0; // initialize index in row, col size_t r = row[k]; size_t c = col[k]; for(int ell = 0; ell < nnz; ++ell) { // Adolc version of lower trangle of Hessian in row major order size_t ind_ell = ind[ell]; size_t i = size_t( cind[ind_ell] ); size_t j = size_t( rind[ind_ell] ); while( (r < i) | ( (r == i) & (c < j) ) ) { // (r, c) not in Adolc sparsity pattern hessian[k++] = 0.0; if( k < row.size() ) { r = row[k]; c = col[k]; } else { r = n; c = n; } } if( (r == i) & (c == j) ) { // adolc value for (r, c) hessian[k++] = values[ind_ell]; if( k < row.size() ) { r = row[k]; c = col[k]; } else { r = n; c = n; } } else { // Hessian at (i, j) must be zero (but Adolc does not know this) assert( values[ind_ell] == 0.0 ); } } // free raw memory allocated by sparse_hessian free(rind); free(cind); free(values); // // return argument for(size_t j = 0; j < n; j++) x_return[j] = x[j]; // do not know how to return number of sweeps used n_color = 0; // tear down thread_alloc::delete_array(a_x); thread_alloc::delete_array(a_y); thread_alloc::delete_array(x); return true; } /* {xrst_code} {xrst_spell_on} {xrst_end adolc_sparse_hessian.cpp}