示例#1
0
void operator()(
	const ADVector&  ax     ,
	      ADVector&  ay     ,
	size_t           id = 0 )
{	size_t i, j;
	size_t n = ax.size();
	size_t m = ay.size();
# ifndef NDEBUG
	bool ok;
	std::string msg = "atomic_base: " + afun_name() + ".eval: ";
	if( (n == 0) | (m == 0) )
	{	msg += "ax.size() or ay.size() is zero";
		CPPAD_ASSERT_KNOWN(false, msg.c_str() );
	}
# endif
	size_t thread = thread_alloc::thread_num();
	vector <Base>& tx  = afun_tx_[thread];
	vector <Base>& ty  = afun_ty_[thread];
	vector <bool>& vx  = afun_vx_[thread];
	vector <bool>& vy  = afun_vy_[thread];
	//
	if( vx.size() != n )
	{	vx.resize(n);
		tx.resize(n);
	}
	if( vy.size() != m )
	{	vy.resize(m);
		ty.resize(m);
	}
	// 
	// Determine tape corresponding to variables in ax
	tape_id_t     tape_id  = 0;
	ADTape<Base>* tape     = CPPAD_NULL;
	for(j = 0; j < n; j++)
	{	tx[j]  = ax[j].value_;
		vx[j]  = Variable( ax[j] );
		if( vx[j] )
		{
			if( tape_id == 0 )
			{	tape    = ax[j].tape_this();
				tape_id = ax[j].tape_id_;
				CPPAD_ASSERT_UNKNOWN( tape != CPPAD_NULL );
			}
# ifndef NDEBUG
			if( tape_id != ax[j].tape_id_ )
			{	msg += afun_name() + 
				": ax contains variables from different threads.";
				CPPAD_ASSERT_KNOWN(false, msg.c_str());
			}
# endif
		}
	}
	// Use zero order forward mode to compute values
	size_t q = 0, p = 0;
	set_id(id);
# ifdef NDEBUG
	forward(q, p, vx, vy, tx, ty);  
# else
	ok = forward(q, p, vx, vy, tx, ty);  
	if( ! ok )
	{	msg += afun_name() + ": ok is false for "
			"zero order forward mode calculation.";
		CPPAD_ASSERT_KNOWN(false, msg.c_str());
	}
# endif
	bool record_operation = false;
	for(i = 0; i < m; i++)
	{
		// pass back values
		ay[i].value_ = ty[i];

		// initialize entire vector parameters (not in tape)
		ay[i].tape_id_ = 0;
		ay[i].taddr_   = 0;

		// we need to record this operation if
		// any of the eleemnts of ay are variables,
		record_operation |= vy[i];
	}
# ifndef NDEBUG
	if( record_operation & (tape == CPPAD_NULL) )
	{	msg += 
		"all elements of vx are false but vy contains a true element";
		CPPAD_ASSERT_KNOWN(false, msg.c_str() );
	}
# endif
	// if tape is not null, ay is on the tape
	if( record_operation )
	{
		// Operator that marks beginning of this atomic operation
		CPPAD_ASSERT_UNKNOWN( NumRes(UserOp) == 0 );
		CPPAD_ASSERT_UNKNOWN( NumArg(UserOp) == 4 );
		tape->Rec_.PutArg(index_, id, n, m);
		tape->Rec_.PutOp(UserOp);

		// Now put n operators, one for each element of arugment vector
		CPPAD_ASSERT_UNKNOWN( NumRes(UsravOp) == 0 );
		CPPAD_ASSERT_UNKNOWN( NumRes(UsrapOp) == 0 );
		CPPAD_ASSERT_UNKNOWN( NumArg(UsravOp) == 1 );
		CPPAD_ASSERT_UNKNOWN( NumArg(UsrapOp) == 1 );
		for(j = 0; j < n; j++)
		{	if( vx[j] )
			{	// information for an argument that is a variable
				tape->Rec_.PutArg(ax[j].taddr_);
				tape->Rec_.PutOp(UsravOp);
			}
			else
			{	// information for an arugment that is parameter
				addr_t par = tape->Rec_.PutPar(ax[j].value_);
				tape->Rec_.PutArg(par);
				tape->Rec_.PutOp(UsrapOp);
			}
		}

		// Now put m operators, one for each element of result vector
		CPPAD_ASSERT_UNKNOWN( NumArg(UsrrpOp) == 1 );
		CPPAD_ASSERT_UNKNOWN( NumRes(UsrrpOp) == 0 );
		CPPAD_ASSERT_UNKNOWN( NumArg(UsrrvOp) == 0 );
		CPPAD_ASSERT_UNKNOWN( NumRes(UsrrvOp) == 1 );
		for(i = 0; i < m; i++)
		{	if( vy[i] )
			{	ay[i].taddr_    = tape->Rec_.PutOp(UsrrvOp);
				ay[i].tape_id_  = tape_id;
			}
			else
			{	addr_t par = tape->Rec_.PutPar(ay[i].value_);
				tape->Rec_.PutArg(par);
				tape->Rec_.PutOp(UsrrpOp);
			}
		}

		// Put a duplicate UserOp at end of UserOp sequence
		tape->Rec_.PutArg(index_, id, n, m);
		tape->Rec_.PutOp(UserOp);
	} 
	return;
}
示例#2
0
bool atomic_base<Base>::rev_sparse_hes(
    const vector<Base>&              x                ,
    const local::pod_vector<size_t>& x_index          ,
    const local::pod_vector<size_t>& y_index          ,
    const InternalSparsity&          for_jac_sparsity ,
    bool*                            rev_jac_flag     ,
    InternalSparsity&                rev_hes_sparsity )
{   CPPAD_ASSERT_UNKNOWN( for_jac_sparsity.end() == rev_hes_sparsity.end() );
    size_t q           = rev_hes_sparsity.end();
    size_t n           = x_index.size();
    size_t m           = y_index.size();
    bool   ok          = false;
    size_t thread      = thread_alloc::thread_num();
    allocate_work(thread);
    bool   zero_empty  = true;
    bool   input_empty = false;
    bool   transpose   = false;
    //
    // vx
    vector<bool> vx(n);
    for(size_t j = 0; j < n; j++)
        vx[j] = x_index[j] != 0;
    //
    // note that s and t are vectors so transpose does not matter for bool case
    vector<bool> bool_s( work_[thread]->bool_s );
    vector<bool> bool_t( work_[thread]->bool_t );
    //
    bool_s.resize(m);
    bool_t.resize(n);
    //
    for(size_t i = 0; i < m; i++)
    {   if( y_index[i] > 0  )
            bool_s[i] = rev_jac_flag[ y_index[i] ];
    }
    //
    std::string msg = ": atomic_base.rev_sparse_hes: returned false";
    if( sparsity_ == pack_sparsity_enum )
    {   vectorBool&  pack_r( work_[thread]->pack_r );
        vectorBool&  pack_u( work_[thread]->pack_u );
        vectorBool&  pack_v( work_[thread]->pack_h );
        //
        pack_v.resize(n * q);
        //
        local::get_internal_sparsity(
            transpose, x_index, for_jac_sparsity, pack_r
        );
        local::get_internal_sparsity(
            transpose, y_index, rev_hes_sparsity, pack_u
        );
        //
        ok = rev_sparse_hes(vx, bool_s, bool_t, q, pack_r, pack_u, pack_v, x);
        if( ! ok )
            ok = rev_sparse_hes(vx, bool_s, bool_t, q, pack_r, pack_u, pack_v);
        if( ! ok )
        {   msg = afun_name() + msg + " sparsity = pack_sparsity_enum";
            CPPAD_ASSERT_KNOWN(false, msg.c_str());
        }
        local::set_internal_sparsity(zero_empty, input_empty,
            transpose, x_index, rev_hes_sparsity, pack_v
        );
    }
    else if( sparsity_ == bool_sparsity_enum )
    {   vector<bool>&  bool_r( work_[thread]->bool_r );
        vector<bool>&  bool_u( work_[thread]->bool_u );
        vector<bool>&  bool_v( work_[thread]->bool_h );
        //
        bool_v.resize(n * q);
        //
        local::get_internal_sparsity(
            transpose, x_index, for_jac_sparsity, bool_r
        );
        local::get_internal_sparsity(
            transpose, y_index, rev_hes_sparsity, bool_u
        );
        //
        ok = rev_sparse_hes(vx, bool_s, bool_t, q, bool_r, bool_u, bool_v, x);
        if( ! ok )
            ok = rev_sparse_hes(vx, bool_s, bool_t, q, bool_r, bool_u, bool_v);
        if( ! ok )
        {   msg = afun_name() + msg + " sparsity = bool_sparsity_enum";
            CPPAD_ASSERT_KNOWN(false, msg.c_str());
        }
        local::set_internal_sparsity(zero_empty, input_empty,
            transpose, x_index, rev_hes_sparsity, bool_v
        );
    }
    else
    {   CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );
        vector< std::set<size_t> >&  set_r( work_[thread]->set_r );
        vector< std::set<size_t> >&  set_u( work_[thread]->set_u );
        vector< std::set<size_t> >&  set_v( work_[thread]->set_h );
        //
        set_v.resize(n);
        //
        local::get_internal_sparsity(
            transpose, x_index, for_jac_sparsity, set_r
        );
        local::get_internal_sparsity(
            transpose, y_index, rev_hes_sparsity, set_u
        );
        //
        ok = rev_sparse_hes(vx, bool_s, bool_t, q, set_r, set_u, set_v, x);
        if( ! ok )
            ok = rev_sparse_hes(vx, bool_s, bool_t, q, set_r, set_u, set_v);
        if( ! ok )
        {   msg = afun_name() + msg + " sparsity = set_sparsity_enum";
            CPPAD_ASSERT_KNOWN(false, msg.c_str());
        }
        local::set_internal_sparsity(zero_empty, input_empty,
            transpose, x_index, rev_hes_sparsity, set_v
        );
    }
    for(size_t j = 0; j < n; j++)
    {   if( x_index[j] > 0  )
            rev_jac_flag[ x_index[j] ] |= bool_t[j];
    }
    return ok;
}