Prev Next adolc_sparse_jacobian.cpp

@(@\newcommand{\W}[1]{ \; #1 \; } \newcommand{\R}[1]{ {\rm #1} } \newcommand{\B}[1]{ {\bf #1} } \newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} } \newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} } \newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} } \newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }@)@This is cppad-20221105 documentation. Here is a link to its current documentation .
Adolc Speed: Sparse Jacobian

Specifications
See link_sparse_jacobian .

Implementation
// suppress conversion warnings before other includes
# include <cppad/wno_conversion.hpp>
//
# include <adolc/adolc.h>
# include <adolc/adolc_sparse.h>
# include <cppad/utility/vector.hpp>
# include <cppad/speed/uniform_01.hpp>
# include <cppad/speed/sparse_jac_fun.hpp>

// list of possible options
# include <map>
extern std::map<std::string, bool> global_option;

namespace {
    using CppAD::vector;
    typedef vector<size_t>    s_vector;
    typedef vector<double>    d_vector;
    typedef vector<adouble>   a_vector;
    void setup(
        // inputs
        int             tag     ,
        size_t          size    ,
        size_t          m       ,
        const s_vector& row     ,
        const s_vector& col     ,
        const d_vector& x       ,
        int*            options , // const but adolc want non-const arg
        // outupts
        size_t&         n_color ,
        int&            nnz     ,
        unsigned int*&  rind    ,
        unsigned int*&  cind    ,
        double*&        values  )
    {   // independent variables
        CPPAD_ASSERT_UNKNOWN( size = x.size() );
        int keep = 0; // keep forward mode results
        trace_on(tag, keep);
        size_t n = size;
        a_vector a_x(n);
        for(size_t j = 0; j < n; ++j)
            a_x[j] <<= x[j];
        //
        // dependent variables
        a_vector a_y(m);
        //
        // AD computation of f(x)
        size_t order = 0;
        CppAD::sparse_jac_fun<adouble>(m, n, a_x, row, col, order, a_y);
        //
        // create function object f : x -> y
        double yi;
        for(size_t i = 0; i < m; i++)
            a_y[i] >>= yi;
        trace_off();
        //
        // null pointers for recalculation of sparsity pattern
        free(rind);
        free(cind);
        free(values);
        rind   = nullptr;
        cind   = nullptr;
        values = nullptr;
        //
        // Retrieve n_color using undocumented feature of sparsedrivers.cpp
        int same_pattern = 0;
        n_color = sparse_jac(tag, int(m), int(n),
            same_pattern, x.data(), &nnz, &rind, &cind, &values, options
        );
    }

}

bool link_sparse_jacobian(
    const std::string&               job      ,
    size_t                           size     ,
    size_t                           repeat   ,
    size_t                           m        ,
    const CppAD::vector<size_t>&     row      ,
    const CppAD::vector<size_t>&     col      ,
          CppAD::vector<double>&     x_return ,
          CppAD::vector<double>&     jacobian ,
          size_t&                    n_color  )
{
    // --------------------------------------------------------------------
    // check global options
    // Allow colpack true even though it is not used below because it is
    // true durng the adolc correctness tests.
    const char* valid[] = { "onetape", "optimize", "colpack"};
    size_t n_valid = sizeof(valid) / sizeof(valid[0]);
    typedef std::map<std::string, bool>::iterator iterator;
    //
    for(iterator itr=global_option.begin(); itr!=global_option.end(); ++itr)
    {   if( itr->second )
        {   bool ok = false;
            for(size_t i = 0; i < n_valid; i++)
                ok |= itr->first == valid[i];
            if( ! ok )
                return false;
        }
    }
    // -----------------------------------------------------
    static size_t  static_size     = 0;
    static int     static_nnz      = 0;
    unsigned int*  static_rind     = nullptr;
    unsigned int*  static_cind     = nullptr;
    double*        static_values   = nullptr;
    // -----------------------------------------------------
    int tag  = 0;
    //
    // options that control sparse_jac
    int        options[4];
    if( global_option["boolsparsity"] )
        options[0] = 1;  // sparsity by propagation of bit pattern
    else
        options[0] = 0;  // sparsity pattern by index domains
    options[1] = 0;  // 0 = safe mode, 1 = tight mode
    options[2] = 0;  // 0 = autodetect, 1 = forward, 2 = reverse
    options[3] = 0;  // 0 = column compression, 1 = row compression
    //
    // independent variiables
    size_t n = size;
    d_vector x(n);
    //
    // default value for n_color
    n_color = 0;
    //
    bool onetape = global_option["onetape"];
    // -----------------------------------------------------
    if( job == "setup" )
    {   // get a value for x
        CppAD::uniform_01(n, x);
        //
        // record the tape and run coloring problem
        options[2] = -1;
        setup(tag, size, m, row, col, x, options,
            n_color, static_nnz, static_rind, static_cind, static_values
        );
        static_size = size;
        //
        return true;
    }
    if( job == "teardown" )
    {   free(static_rind);
        free(static_cind);
        free(static_values);
        static_rind   = nullptr;
        static_cind   = nullptr;
        static_values = nullptr;
        return true;
    }
    // -----------------------------------------------------
    CPPAD_ASSERT_UNKNOWN( job == "run" );
    //
    while (repeat--)
    {   // choose a value for x
        CppAD::uniform_01(n, x);
        //
        if ( ! onetape )
        {   // retape and calculate jacobian
            options[2] = -1; // stop at sparsity pattern, return n_color
            setup(tag, size, m, row, col, x, options,
                n_color, static_nnz, static_rind, static_cind, static_values
            );
            options[2] = 0;
        }
        else
        {   if( size != static_size )
                CPPAD_ASSERT_UNKNOWN( size == static_size );
        }
        // calculate the jacobian at this x
        int same_pattern = 1;
        sparse_jac(
            tag, int(m), int(n), same_pattern, x.data(),
            &static_nnz, &static_rind, &static_cind, &static_values,
            options
        );
    }
    // --------------------------------------------------------------------
    // jacobian
    CPPAD_ASSERT_UNKNOWN( size_t(static_nnz) == row.size() );
    for(int ell = 0; ell < static_nnz; ell++)
    {   CPPAD_ASSERT_UNKNOWN( row[ell] == size_t(static_rind[ell]) );
        CPPAD_ASSERT_UNKNOWN( col[ell] == size_t(static_cind[ell]) );
        jacobian[ell] = static_values[ell];
    }
    // x_return
    for(size_t j = 0; j < n; j++)
        x_return[j] = x[j];
    //
    return true;
}

Input File: speed/adolc/sparse_jacobian.cpp