bool link_sparse_hessian( size_t size , size_t repeat , CppAD::vector<double>& x , const CppAD::vector<size_t>& row , const CppAD::vector<size_t>& col , CppAD::vector<double>& hessian ) { // ----------------------------------------------------- // setup typedef vector<double> DblVector; typedef vector< std::set<size_t> > SetVector; typedef CppAD::AD<double> ADScalar; typedef vector<ADScalar> ADVector; size_t i, j, k; 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 size_t K = row.size(); // number of non-zeros in lower triangle ADVector a_x(n); // AD domain space vector ADVector a_y(m); // AD range space vector DblVector w(m); // double range space vector DblVector hes(K); // non-zeros in lower triangle CppAD::ADFun<double> f; // AD function object // weights for hessian calculation (only one component of f) w[0] = 1.; // use the unspecified fact that size is non-decreasing between calls static size_t previous_size = 0; bool print = (repeat > 1) & (previous_size != size); previous_size = size; // declare sparsity pattern # if USE_SET_SPARSITY SetVector sparsity(n); # else typedef vector<bool> BoolVector; BoolVector sparsity(n * n); # endif // initialize all entries as zero for(i = 0; i < n; i++) { for(j = 0; j < n; j++) hessian[ i * n + j] = 0.; } // ------------------------------------------------------ extern bool global_retape; if( global_retape) while(repeat--) { // choose a value for x CppAD::uniform_01(n, x); for(j = 0; j < n; j++) a_x[j] = x[j]; // declare independent variables Independent(a_x); // AD computation of f(x) CppAD::sparse_hes_fun<ADScalar>(n, a_x, row, col, order, a_y); // create function object f : X -> Y f.Dependent(a_x, a_y); extern bool global_optimize; if( global_optimize ) { print_optimize(f, print, "cppad_sparse_hessian_optimize", size); print = false; } // calculate the Hessian sparsity pattern for this function calc_sparsity(sparsity, f); // structure that holds some of work done by SparseHessian CppAD::sparse_hessian_work work; // calculate this Hessian at this x f.SparseHessian(x, w, sparsity, row, col, hes, work); for(k = 0; k < K; k++) { hessian[ row[k] * n + col[k] ] = hes[k]; hessian[ col[k] * n + row[k] ] = hes[k]; } } else { // choose a value for x CppAD::uniform_01(n, x); for(j = 0; j < n; j++) a_x[j] = x[j]; // declare independent variables Independent(a_x); // AD computation of f(x) CppAD::sparse_hes_fun<ADScalar>(n, a_x, row, col, order, a_y); // create function object f : X -> Y f.Dependent(a_x, a_y); extern bool global_optimize; if( global_optimize ) { print_optimize(f, print, "cppad_sparse_hessian_optimize", size); print = false; } // calculate the Hessian sparsity pattern for this function calc_sparsity(sparsity, f); // declare structure that holds some of work done by SparseHessian CppAD::sparse_hessian_work work; while(repeat--) { // choose a value for x CppAD::uniform_01(n, x); // calculate sparsity at this x f.SparseHessian(x, w, sparsity, row, col, hes, work); for(k = 0; k < K; k++) { hessian[ row[k] * n + col[k] ] = hes[k]; hessian[ col[k] * n + row[k] ] = hes[k]; } } } return true; }
int mat_rank(int dim, double **mat) { int i, j; int count = 0; double *dr = NULL, *di = NULL; double **tmp; dr = new_double_vector(dim); di = new_double_vector(dim); tmp = new_double_matrix(dim, dim); /* 計算途中で値が上書きされるから元の行列のコピーを使う */ for(i = 0; i < dim; i++) for(j = 0; j < dim; j++) tmp[i][j] = mat[i][j]; /* 固有値の計算 */ hes(tmp, dim); hqr(tmp, dr, di, dim); /* 固有値を調べる */ /* drが実数成分、diが虚数成分 */ for(i = 0; i < dim; i++) if(dr[i] > 0.0 && (!(di[i] > 0.0 || di[i] < 0.0))) count++; /* 配列を解放 */ free_double_vector(dr); free_double_vector(di); free_double_matrix(tmp); return count; }
Vector ADFun<Base>::Hessian(const Vector &x, size_t i) { size_t j; size_t k; size_t l; size_t n = Domain(); size_t m = Range(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector<Base, Vector>(); CppADUsageError( x.size() == n, "Hessian: length of x not equal domain dimension for f" ); CppADUsageError( i < m, "Hessian: index i is not less than range dimension for f" ); // point at which we are evaluating the Hessian Forward(0, x); // define the return value Vector hes(n * n); // direction vector for calls to forward Vector u(n); for(j = 0; j < n; j++) u[j] = Base(0); // direction vector for calls to reverse Vector w(m); for(l = 0; l < m; l++) w[l] = Base(0); w[i] = Base(1); // location for return values from Reverse Vector ddw(n * 2); // loop over forward direstions for(j = 0; j < n; j++) { // evaluate partials of entire function w.r.t. j-th coordinate u[j] = Base(1); Forward(1, u); u[j] = Base(0); // evaluate derivative of partial corresponding to F_i ddw = Reverse(2, w); // return desired components for(k = 0; k < n; k++) hes[k * n + j] = ddw[k * 2 + 1]; } return hes; }
Vector ADFun<Base>::Hessian(const Vector &x, const Vector &w) { size_t j; size_t k; size_t n = Domain(); // check Vector is Simple Vector class with Base type elements CheckSimpleVector<Base, Vector>(); CPPAD_ASSERT_KNOWN( size_t(x.size()) == n, "Hessian: length of x not equal domain dimension for f" ); CPPAD_ASSERT_KNOWN( size_t(w.size()) == Range(), "Hessian: length of w not equal range dimension for f" ); // point at which we are evaluating the Hessian Forward(0, x); // define the return value Vector hes(n * n); // direction vector for calls to forward Vector u(n); for(j = 0; j < n; j++) u[j] = Base(0); // location for return values from Reverse Vector ddw(n * 2); // loop over forward directions for(j = 0; j < n; j++) { // evaluate partials of entire function w.r.t. j-th coordinate u[j] = Base(1); Forward(1, u); u[j] = Base(0); // evaluate derivative of partial corresponding to F_i ddw = Reverse(2, w); // return desired components for(k = 0; k < n; k++) hes[k * n + j] = ddw[k * 2 + 1]; } return hes; }