Theory
This example demonstrates using atomic_base
to define the operation
@(@
f : \B{R}^n \rightarrow \B{R}^m
@)@ where
@(@
n = 2
@)@, @(@
m = 1
@)@, where
@[@
f(x) = x_0^2 + x_1^2
@]@
sparsity
This example only uses bool sparsity patterns.
# include <cppad/cppad.hpp>
namespace { // isolate items below to this fileusing CppAD::vector; // abbreviate as vector//class atomic_norm_sq : public CppAD::atomic_base<double> {
public:
// constructor (could use const char* for name)atomic_norm_sq(const std::string& name) :
// this example only uses boolean sparsity patterns
CppAD::atomic_base<double>(name, atomic_base<double>::bool_sparsity_enum)
{ }
private:
// reverse Hessian bool sparsity routine called by CppADvirtual bool rev_sparse_hes(
const vector<bool>& vx,
const vector<bool>& s ,
vector<bool>& t ,
size_t p ,
const vector<bool>& r ,
const vector<bool>& u ,
vector<bool>& v ,
const vector<double>& x )
{ // This function needed if using RevSparseHes# ifndef NDEBUG
size_t m = s.size();
# endif
size_t n = t.size();
assert( x.size() == n );
assert( r.size() == n * p );
assert( u.size() == m * p );
assert( v.size() == n * p );
assert( n == 2 );
assert( m == 1 );
// There are no cross term second derivatives for this case,// so it is not necessary to use vx.// sparsity for T(x) = S(x) * f'(x)
t[0] = s[0];
t[1] = s[0];
// V(x) = f'(x)^T * g''(y) * f'(x) * R + g'(y) * f''(x) * R// U(x) = g''(y) * f'(x) * R// S(x) = g'(y)// back propagate the sparsity for U
size_t j;
for(j = 0; j < p; j++)
for(size_t i = 0; i < n; i++)
v[ i * p + j] = u[j];
// include forward Jacobian sparsity in Hessian sparsity// sparsity for g'(y) * f''(x) * R (Note f''(x) has same sparsity// as the identity matrix)if( s[0] )
{ for(j = 0; j < p; j++)
for(size_t i = 0; i < n; i++)
{ // Visual Studio 2013 generates warning without bool below
v[ i * p + j] |= bool( r[ i * p + j] );
}
}
returntrue;
}
// Hessian sparsity (using previous ForSparseJac call)
CppAD::vectorBool s3(m), h(p * n);
s3[0] = true; // compute sparsity pattern for f[0]//
h = f.RevSparseHes(p, s3);
ok &= h[0] == true; // partial of f[0] w.r.t. x[0],x[0] is non-zero
ok &= h[1] == false; // partial of f[0] w.r.t. x[0],x[1] is zero
ok &= h[2] == false; // partial of f[0] w.r.t. x[1],x[0] is zero
ok &= h[3] == true; // partial of f[0] w.r.t. x[1],x[1] is non-zero//return ok;
}