236 lines
6.0 KiB
C++
236 lines
6.0 KiB
C++
# ifndef CPPAD_CORE_REV_TWO_HPP
|
|
# define CPPAD_CORE_REV_TWO_HPP
|
|
|
|
/* --------------------------------------------------------------------------
|
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
|
|
|
CppAD is distributed under multiple licenses. This distribution is under
|
|
the terms of the
|
|
Eclipse Public License Version 1.0.
|
|
|
|
A copy of this license is included in the COPYING file of this distribution.
|
|
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
|
|
-------------------------------------------------------------------------- */
|
|
|
|
/*
|
|
$begin RevTwo$$
|
|
$spell
|
|
ddw
|
|
typename
|
|
Taylor
|
|
const
|
|
$$
|
|
|
|
|
|
|
|
|
|
|
|
$section Reverse Mode Second Partial Derivative Driver$$
|
|
$mindex order easy$$
|
|
|
|
$head Syntax$$
|
|
$icode%ddw% = %f%.RevTwo(%x%, %i%, %j%)%$$
|
|
|
|
|
|
$head Purpose$$
|
|
We use $latex F : B^n \rightarrow B^m$$ to denote the
|
|
$cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$.
|
|
The syntax above sets
|
|
$latex \[
|
|
ddw [ k * p + \ell ]
|
|
=
|
|
\DD{ F_{i[ \ell ]} }{ x_{j[ \ell ]} }{ x_k } (x)
|
|
\] $$
|
|
for $latex k = 0 , \ldots , n-1$$
|
|
and $latex \ell = 0 , \ldots , p$$,
|
|
where $latex p$$ is the size of the vectors $icode i$$ and $icode j$$.
|
|
|
|
$head f$$
|
|
The object $icode f$$ has prototype
|
|
$codei%
|
|
ADFun<%Base%> %f%
|
|
%$$
|
|
Note that the $cref ADFun$$ object $icode f$$ is not $code const$$
|
|
(see $cref/RevTwo Uses Forward/RevTwo/RevTwo Uses Forward/$$ below).
|
|
|
|
$head x$$
|
|
The argument $icode x$$ has prototype
|
|
$codei%
|
|
const %VectorBase% &%x%
|
|
%$$
|
|
(see $cref/VectorBase/RevTwo/VectorBase/$$ below)
|
|
and its size
|
|
must be equal to $icode n$$, the dimension of the
|
|
$cref/domain/seq_property/Domain/$$ space for $icode f$$.
|
|
It specifies
|
|
that point at which to evaluate the partial derivatives listed above.
|
|
|
|
$head i$$
|
|
The argument $icode i$$ has prototype
|
|
$codei%
|
|
const %VectorSize_t% &%i%
|
|
%$$
|
|
(see $cref/VectorSize_t/RevTwo/VectorSize_t/$$ below)
|
|
We use $icode p$$ to denote the size of the vector $icode i$$.
|
|
All of the indices in $icode i$$
|
|
must be less than $icode m$$, the dimension of the
|
|
$cref/range/seq_property/Range/$$ space for $icode f$$; i.e.,
|
|
for $latex \ell = 0 , \ldots , p-1$$, $latex i[ \ell ] < m$$.
|
|
|
|
$head j$$
|
|
The argument $icode j$$ has prototype
|
|
$codei%
|
|
const %VectorSize_t% &%j%
|
|
%$$
|
|
(see $cref/VectorSize_t/RevTwo/VectorSize_t/$$ below)
|
|
and its size must be equal to $icode p$$,
|
|
the size of the vector $icode i$$.
|
|
All of the indices in $icode j$$
|
|
must be less than $icode n$$; i.e.,
|
|
for $latex \ell = 0 , \ldots , p-1$$, $latex j[ \ell ] < n$$.
|
|
|
|
$head ddw$$
|
|
The result $icode ddw$$ has prototype
|
|
$codei%
|
|
%VectorBase% %ddw%
|
|
%$$
|
|
(see $cref/VectorBase/RevTwo/VectorBase/$$ below)
|
|
and its size is $latex n * p$$.
|
|
It contains the requested partial derivatives; to be specific,
|
|
for $latex k = 0 , \ldots , n - 1 $$
|
|
and $latex \ell = 0 , \ldots , p - 1$$
|
|
$latex \[
|
|
ddw [ k * p + \ell ]
|
|
=
|
|
\DD{ F_{i[ \ell ]} }{ x_{j[ \ell ]} }{ x_k } (x)
|
|
\] $$
|
|
|
|
$head VectorBase$$
|
|
The type $icode VectorBase$$ must be a $cref SimpleVector$$ class with
|
|
$cref/elements of type Base/SimpleVector/Elements of Specified Type/$$.
|
|
The routine $cref CheckSimpleVector$$ will generate an error message
|
|
if this is not the case.
|
|
|
|
$head VectorSize_t$$
|
|
The type $icode VectorSize_t$$ must be a $cref SimpleVector$$ class with
|
|
$cref/elements of type size_t/SimpleVector/Elements of Specified Type/$$.
|
|
The routine $cref CheckSimpleVector$$ will generate an error message
|
|
if this is not the case.
|
|
|
|
$head RevTwo Uses Forward$$
|
|
After each call to $cref Forward$$,
|
|
the object $icode f$$ contains the corresponding
|
|
$cref/Taylor coefficients/glossary/Taylor Coefficient/$$.
|
|
After a call to $code RevTwo$$,
|
|
the zero order Taylor coefficients correspond to
|
|
$icode%f%.Forward(0, %x%)%$$
|
|
and the other coefficients are unspecified.
|
|
|
|
$head Examples$$
|
|
$children%
|
|
example/general/rev_two.cpp
|
|
%$$
|
|
The routine
|
|
$cref/RevTwo/rev_two.cpp/$$ is both an example and test.
|
|
It returns $code true$$, if it succeeds and $code false$$ otherwise.
|
|
|
|
$end
|
|
-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
// BEGIN CppAD namespace
|
|
namespace CppAD {
|
|
|
|
template <typename Base>
|
|
template <typename VectorBase, typename VectorSize_t>
|
|
VectorBase ADFun<Base>::RevTwo(
|
|
const VectorBase &x,
|
|
const VectorSize_t &i,
|
|
const VectorSize_t &j)
|
|
{ size_t i1;
|
|
size_t j1;
|
|
size_t k;
|
|
size_t l;
|
|
|
|
size_t n = Domain();
|
|
size_t m = Range();
|
|
size_t p = i.size();
|
|
|
|
// check VectorBase is Simple Vector class with Base elements
|
|
CheckSimpleVector<Base, VectorBase>();
|
|
|
|
// check VectorSize_t is Simple Vector class with size_t elements
|
|
CheckSimpleVector<size_t, VectorSize_t>();
|
|
|
|
CPPAD_ASSERT_KNOWN(
|
|
x.size() == n,
|
|
"RevTwo: Length of x not equal domain dimension for f."
|
|
);
|
|
CPPAD_ASSERT_KNOWN(
|
|
i.size() == j.size(),
|
|
"RevTwo: Lenght of the i and j vectors are not equal."
|
|
);
|
|
// point at which we are evaluating the second partials
|
|
Forward(0, x);
|
|
|
|
// dimension the return value
|
|
VectorBase ddw(n * p);
|
|
|
|
// direction vector in argument space
|
|
VectorBase dx(n);
|
|
for(j1 = 0; j1 < n; j1++)
|
|
dx[j1] = Base(0.0);
|
|
|
|
// direction vector in range space
|
|
VectorBase w(m);
|
|
for(i1 = 0; i1 < m; i1++)
|
|
w[i1] = Base(0.0);
|
|
|
|
// place to hold the results of a reverse calculation
|
|
VectorBase r(n * 2);
|
|
|
|
// check the indices in i and j
|
|
for(l = 0; l < p; l++)
|
|
{ i1 = i[l];
|
|
j1 = j[l];
|
|
CPPAD_ASSERT_KNOWN(
|
|
i1 < m,
|
|
"RevTwo: an eleemnt of i not less than range dimension for f."
|
|
);
|
|
CPPAD_ASSERT_KNOWN(
|
|
j1 < n,
|
|
"RevTwo: an element of j not less than domain dimension for f."
|
|
);
|
|
}
|
|
|
|
// loop over all forward directions
|
|
for(j1 = 0; j1 < n; j1++)
|
|
{ // first order forward mode calculation done
|
|
bool first_done = false;
|
|
for(l = 0; l < p; l++) if( j[l] == j1 )
|
|
{ if( ! first_done )
|
|
{ first_done = true;
|
|
|
|
// first order forward mode in j1 direction
|
|
dx[j1] = Base(1.0);
|
|
Forward(1, dx);
|
|
dx[j1] = Base(0.0);
|
|
}
|
|
// execute a reverse in this component direction
|
|
i1 = i[l];
|
|
w[i1] = Base(1.0);
|
|
r = Reverse(2, w);
|
|
w[i1] = Base(0.0);
|
|
|
|
// place the reverse result in return value
|
|
for(k = 0; k < n; k++)
|
|
ddw[k * p + l] = r[k * 2 + 1];
|
|
}
|
|
}
|
|
return ddw;
|
|
}
|
|
|
|
} // END CppAD namespace
|
|
|
|
# endif
|