mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-06-20 21:42:05 +08:00
external folder
This commit is contained in:
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
wget 'http://www.coin-or.org/download/source/CppAD/cppad-20170816.epl.tgz'
|
||||
tar xvf cppad-20170816.epl.tgz
|
||||
cd cppad-20170816/
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -D cppad_prefix="$HOME/one/external/cppad" ..
|
||||
make install
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
// $Id: base_require.hpp 3845 2016-11-19 01:50:47Z bradbell $
|
||||
# ifndef CPPAD_BASE_REQUIRE_HPP
|
||||
# define CPPAD_BASE_REQUIRE_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 base_require$$
|
||||
$spell
|
||||
azmul
|
||||
ostream
|
||||
alloc
|
||||
eps
|
||||
std
|
||||
Lt
|
||||
Le
|
||||
Eq
|
||||
Ge
|
||||
Gt
|
||||
cppad.hpp
|
||||
namespace
|
||||
optimizations
|
||||
bool
|
||||
const
|
||||
CppAD
|
||||
enum
|
||||
Lt
|
||||
Le
|
||||
Eq
|
||||
Ge
|
||||
Gt
|
||||
inline
|
||||
Op
|
||||
std
|
||||
CondExp
|
||||
$$
|
||||
|
||||
$section AD<Base> Requirements for a CppAD Base Type$$
|
||||
|
||||
$head Syntax$$
|
||||
$code # include <cppad/base_require.hpp>$$
|
||||
|
||||
$head Purpose$$
|
||||
This section lists the requirements for the type
|
||||
$icode Base$$ so that the type $codei%AD<%Base%>%$$ can be used.
|
||||
|
||||
$head API Warning$$
|
||||
Defining a CppAD $icode Base$$ type is an advanced use of CppAD.
|
||||
This part of the CppAD API changes with time. The most common change
|
||||
is adding more requirements.
|
||||
Search for $code base_require$$ in the
|
||||
current $cref whats_new$$ section for these changes.
|
||||
|
||||
$head Standard Base Types$$
|
||||
In the case where $icode Base$$ is
|
||||
$code float$$,
|
||||
$code double$$,
|
||||
$code std::complex<float>$$,
|
||||
$code std::complex<double>$$,
|
||||
or $codei%AD<%Other%>%$$,
|
||||
these requirements are provided by including the file
|
||||
$code cppad/cppad.hpp$$.
|
||||
|
||||
$head Include Order$$
|
||||
If you are linking a non-standard base type to CppAD,
|
||||
you must first include the file $code cppad/base_require.hpp$$,
|
||||
then provide the specifications below,
|
||||
and then include the file $code cppad/cppad.hpp$$.
|
||||
|
||||
$head Numeric Type$$
|
||||
The type $icode Base$$ must support all the operations for a
|
||||
$cref NumericType$$.
|
||||
|
||||
$head Output Operator$$
|
||||
The type $icode Base$$ must support the syntax
|
||||
$codei%
|
||||
%os% << %x%
|
||||
%$$
|
||||
where $icode os$$ is an $code std::ostream&$$
|
||||
and $icode x$$ is a $code const base_alloc&$$.
|
||||
For example, see
|
||||
$cref/base_alloc/base_alloc.hpp/Output Operator/$$.
|
||||
|
||||
$head Integer$$
|
||||
The type $icode Base$$ must support the syntax
|
||||
$codei%
|
||||
%i% = CppAD::Integer(%x%)
|
||||
%$$
|
||||
which converts $icode x$$ to an $code int$$.
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
%$$
|
||||
and the return value $icode i$$ has prototype
|
||||
$codei%
|
||||
int %i%
|
||||
%$$
|
||||
|
||||
$subhead Suggestion$$
|
||||
In many cases, the $icode Base$$ version of the $code Integer$$ function
|
||||
can be defined by
|
||||
$codei%
|
||||
namespace CppAD {
|
||||
inline int Integer(const %Base%& x)
|
||||
{ return static_cast<int>(x); }
|
||||
}
|
||||
%$$
|
||||
For example, see
|
||||
$cref/base_float/base_float.hpp/Integer/$$ and
|
||||
$cref/base_alloc/base_alloc.hpp/Integer/$$.
|
||||
|
||||
$head Absolute Zero, azmul$$
|
||||
The type $icode Base$$ must support the syntax
|
||||
$codei%
|
||||
%z% = azmul(%x%, %y%)
|
||||
%$$
|
||||
see; $cref azmul$$.
|
||||
The following preprocessor macro invocation suffices
|
||||
(for most $icode Base$$ types):
|
||||
$codei%
|
||||
namespace CppAD {
|
||||
CPPAD_AZMUL(%Base%)
|
||||
}
|
||||
%$$
|
||||
where the macro is defined by
|
||||
$srccode%cpp% */
|
||||
# define CPPAD_AZMUL(Base) \
|
||||
inline Base azmul(const Base& x, const Base& y) \
|
||||
{ Base zero(0.0); \
|
||||
if( x == zero ) \
|
||||
return zero; \
|
||||
return x * y; \
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$childtable%
|
||||
omh/base_require/base_member.omh%
|
||||
cppad/core/base_cond_exp.hpp%
|
||||
omh/base_require/base_identical.omh%
|
||||
omh/base_require/base_ordered.omh%
|
||||
cppad/core/base_std_math.hpp%
|
||||
cppad/core/base_limits.hpp%
|
||||
cppad/core/base_to_string.hpp%
|
||||
cppad/core/base_hash.hpp%
|
||||
omh/base_require/base_example.omh
|
||||
%$$
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
// definitions that must come before base implementations
|
||||
# include <cppad/utility/error_handler.hpp>
|
||||
# include <cppad/core/define.hpp>
|
||||
# include <cppad/core/cppad_assert.hpp>
|
||||
# include <cppad/local/declare_ad.hpp>
|
||||
|
||||
// grouping documentation by feature
|
||||
# include <cppad/core/base_cond_exp.hpp>
|
||||
# include <cppad/core/base_std_math.hpp>
|
||||
# include <cppad/core/base_limits.hpp>
|
||||
# include <cppad/core/base_to_string.hpp>
|
||||
# include <cppad/core/base_hash.hpp>
|
||||
|
||||
// must define template class numeric_limits before the base cases
|
||||
# include <cppad/core/numeric_limits.hpp>
|
||||
# include <cppad/core/epsilon.hpp> // deprecated
|
||||
|
||||
// base cases that come with CppAD
|
||||
# include <cppad/core/base_float.hpp>
|
||||
# include <cppad/core/base_double.hpp>
|
||||
# include <cppad/core/base_complex.hpp>
|
||||
|
||||
// deprecated base type
|
||||
# include <cppad/core/zdouble.hpp>
|
||||
|
||||
# endif
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
# ifndef CPPAD_CONFIGURE_HPP
|
||||
# define CPPAD_CONFIGURE_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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
/*!
|
||||
\file configure.hpp
|
||||
Replacement for config.h so that all preprocessor symbols begin with CPPAD_
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_COMPILER_IS_GNUCXX
|
||||
is the compiler a variant of g++
|
||||
*/
|
||||
# define CPPAD_COMPILER_IS_GNUCXX 1
|
||||
|
||||
/*!
|
||||
\def CPPAD_DISABLE_SOME_MICROSOFT_COMPILER_WARNINGS
|
||||
This macro is only used to document the pragmas that disables the
|
||||
follow warnings:
|
||||
|
||||
\li C4100
|
||||
unreferenced formal parameter.
|
||||
\li C4127
|
||||
conditional expression is constant.
|
||||
*/
|
||||
# define CPPAD_DISABLE_SOME_MICROSOFT_COMPILER_WARNINGS 1
|
||||
# if _MSC_VER
|
||||
# pragma warning( disable : 4100 )
|
||||
# pragma warning( disable : 4127 )
|
||||
# endif
|
||||
# undef CPPAD_DISABLE_SOME_MICROSOFT_COMPILER_WARNINGS
|
||||
|
||||
/*!
|
||||
\def CPPAD_USE_CPLUSPLUS_2011
|
||||
Should CppAD use C++11 features. This will be true if the current
|
||||
compiler flags request C++11 features and the install procedure
|
||||
determined that all the necessary features are avaiable.
|
||||
*/
|
||||
# if _MSC_VER
|
||||
# define CPPAD_USE_CPLUSPLUS_2011 0
|
||||
# else //
|
||||
# if __cplusplus >= 201100
|
||||
# define CPPAD_USE_CPLUSPLUS_2011 0
|
||||
# else //
|
||||
# define CPPAD_USE_CPLUSPLUS_2011 0
|
||||
# endif //
|
||||
# endif //
|
||||
|
||||
/*!
|
||||
\def CPPAD_PACKAGE_STRING
|
||||
cppad-yyyymmdd as a C string where yyyy is year, mm is month, and dd is day.
|
||||
*/
|
||||
# define CPPAD_PACKAGE_STRING "cppad-20170816"
|
||||
|
||||
/*!
|
||||
def CPPAD_HAS_ADOLC
|
||||
Was a adolc_prefix specified on the cmake command line.
|
||||
*/
|
||||
# define CPPAD_HAS_ADOLC 0
|
||||
|
||||
/*!
|
||||
def CPPAD_HAS_COLPACK
|
||||
Was a colpack_prefix specified on the cmake command line.
|
||||
*/
|
||||
# define CPPAD_HAS_COLPACK 0
|
||||
|
||||
/*!
|
||||
def CPPAD_HAS_EIGEN
|
||||
Was a eigen_prefix specified on the cmake command line.
|
||||
*/
|
||||
# define CPPAD_HAS_EIGEN 0
|
||||
|
||||
/*!
|
||||
def CPPAD_HAS_IPOPT
|
||||
Was a ipopt_prefix specified on the cmake command line.
|
||||
*/
|
||||
# define CPPAD_HAS_IPOPT 0
|
||||
|
||||
/*!
|
||||
\def CPPAD_DEPRECATED
|
||||
This symbol is not currently being used.
|
||||
*/
|
||||
# define CPPAD_DEPRECATED 0
|
||||
|
||||
/*!
|
||||
\def CPPAD_BOOSTVECTOR
|
||||
If this symbol is one, and _MSC_VER is not defined,
|
||||
we are using boost vector for CPPAD_TESTVECTOR.
|
||||
It this symbol is zero,
|
||||
we are not using boost vector for CPPAD_TESTVECTOR.
|
||||
*/
|
||||
# define CPPAD_BOOSTVECTOR 0
|
||||
|
||||
/*!
|
||||
\def CPPAD_CPPADVECTOR
|
||||
If this symbol is one,
|
||||
we are using CppAD vector for CPPAD_TESTVECTOR.
|
||||
It this symbol is zero,
|
||||
we are not using CppAD vector for CPPAD_TESTVECTOR.
|
||||
*/
|
||||
# define CPPAD_CPPADVECTOR 1
|
||||
|
||||
/*!
|
||||
\def CPPAD_STDVECTOR
|
||||
If this symbol is one,
|
||||
we are using standard vector for CPPAD_TESTVECTOR.
|
||||
It this symbol is zero,
|
||||
we are not using standard vector for CPPAD_TESTVECTOR.
|
||||
*/
|
||||
# define CPPAD_STDVECTOR 0
|
||||
|
||||
/*!
|
||||
\def CPPAD_EIGENVECTOR
|
||||
If this symbol is one,
|
||||
we are using Eigen vector for CPPAD_TESTVECTOR.
|
||||
If this symbol is zero,
|
||||
we are not using Eigen vector for CPPAD_TESTVECTOR.
|
||||
*/
|
||||
# define CPPAD_EIGENVECTOR 0
|
||||
|
||||
/*!
|
||||
\def CPPAD_HAS_GETTIMEOFDAY
|
||||
If this symbol is one, and _MSC_VER is not defined,
|
||||
this system supports the gettimeofday funcgtion.
|
||||
Otherwise, this smybol should be zero.
|
||||
*/
|
||||
# define CPPAD_HAS_GETTIMEOFDAY 1
|
||||
|
||||
/*!
|
||||
\def CPPAD_SIZE_T_NOT_UNSIGNED_INT
|
||||
If this symbol is zero, the type size_t is the same as the type unsigned int,
|
||||
otherwise this symbol is one.
|
||||
*/
|
||||
# define CPPAD_SIZE_T_NOT_UNSIGNED_INT 1
|
||||
|
||||
/*!
|
||||
\def CPPAD_TAPE_ADDR_TYPE
|
||||
Is the type used to store address on the tape. If not size_t, then
|
||||
<code>sizeof(CPPAD_TAPE_ADDR_TYPE) <= sizeof( size_t )</code>
|
||||
to conserve memory.
|
||||
This type must support \c std::numeric_limits,
|
||||
the \c <= operator,
|
||||
and conversion to \c size_t.
|
||||
Make sure that the type chosen returns true for is_pod<CPPAD_TAPE_ADDR_TYPE>
|
||||
in pod_vector.hpp.
|
||||
This type is later defined as \c addr_t in the CppAD namespace.
|
||||
*/
|
||||
# define CPPAD_TAPE_ADDR_TYPE unsigned int
|
||||
|
||||
/*!
|
||||
\def CPPAD_TAPE_ID_TYPE
|
||||
Is the type used to store tape identifiers. If not size_t, then
|
||||
<code>sizeof(CPPAD_TAPE_ID_TYPE) <= sizeof( size_t )</code>
|
||||
to conserve memory.
|
||||
This type must support \c std::numeric_limits,
|
||||
the \c <= operator,
|
||||
and conversion to \c size_t.
|
||||
Make sure that the type chosen returns true for is_pod<CPPAD_TAPE_ID_TYPE>
|
||||
in pod_vector.hpp.
|
||||
This type is later defined as \c tape_id_t in the CppAD namespace.
|
||||
*/
|
||||
# define CPPAD_TAPE_ID_TYPE unsigned int
|
||||
|
||||
/*!
|
||||
\def CPPAD_MAX_NUM_THREADS
|
||||
Specifies the maximum number of threads that CppAD can support
|
||||
(must be greater than or equal four).
|
||||
|
||||
The user may define CPPAD_MAX_NUM_THREADS before including any of the CppAD
|
||||
header files. If it is not yet defined,
|
||||
*/
|
||||
# ifndef CPPAD_MAX_NUM_THREADS
|
||||
# define CPPAD_MAX_NUM_THREADS 48
|
||||
# endif
|
||||
|
||||
/*!
|
||||
\def CPPAD_HAS_MKSTEMP
|
||||
It true, mkstemp works in C++ on this system.
|
||||
*/
|
||||
# define CPPAD_HAS_MKSTEMP 1
|
||||
|
||||
/*!
|
||||
\def CPPAD_HAS_TMPNAM_S
|
||||
It true, tmpnam_s works in C++ on this system.
|
||||
*/
|
||||
# define CPPAD_HAS_TMPNAM_S 0
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// defines that only depend on values above
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
\def CPPAD_NULL
|
||||
This preprocessor symbol is used for a null pointer.
|
||||
|
||||
If it is not yet defined,
|
||||
it is defined when cppad/core/define.hpp is included.
|
||||
*/
|
||||
# ifndef CPPAD_NULL
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
# define CPPAD_NULL nullptr
|
||||
# else
|
||||
# define CPPAD_NULL 0
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,60 @@
|
||||
# ifndef CPPAD_CORE_ABORT_RECORDING_HPP
|
||||
# define CPPAD_CORE_ABORT_RECORDING_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 abort_recording$$
|
||||
$spell
|
||||
$$
|
||||
|
||||
$section Abort Recording of an Operation Sequence$$
|
||||
$mindex tape$$
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
$codei%AD<%Base%>::abort_recording()%$$
|
||||
|
||||
$head Purpose$$
|
||||
Sometimes it is necessary to abort the recording of an operation sequence
|
||||
that started with a call of the form
|
||||
$codei%
|
||||
Independent(%x%)
|
||||
%$$
|
||||
If such a recording is currently in progress,
|
||||
$code abort_recording$$ will stop the recording and delete the
|
||||
corresponding information.
|
||||
Otherwise, $code abort_recording$$ has no effect.
|
||||
|
||||
$children%
|
||||
example/general/abort_recording.cpp
|
||||
%$$
|
||||
$head Example$$
|
||||
The file
|
||||
$cref abort_recording.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
namespace CppAD {
|
||||
template <typename Base>
|
||||
void AD<Base>::abort_recording(void)
|
||||
{ local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape != CPPAD_NULL )
|
||||
AD<Base>::tape_manage(tape_manage_delete);
|
||||
}
|
||||
}
|
||||
|
||||
# endif
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
# ifndef CPPAD_CORE_ABS_HPP
|
||||
# define CPPAD_CORE_ABS_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 abs$$
|
||||
$spell
|
||||
fabs
|
||||
Vec
|
||||
std
|
||||
faq
|
||||
Taylor
|
||||
Cpp
|
||||
namespace
|
||||
const
|
||||
abs
|
||||
$$
|
||||
|
||||
$section AD Absolute Value Functions: abs, fabs$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = abs(%x%)
|
||||
%$$
|
||||
$icode%y% = fabs(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
In the case where $icode x$$ is an AD type,
|
||||
this is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Complex Types$$
|
||||
The functions $code abs$$ and $icode fabs$$
|
||||
are not defined for the base types
|
||||
$code std::complex<float>$$ or $code std::complex<double>$$
|
||||
because the complex $code abs$$ function is not complex differentiable
|
||||
(see $cref/complex types faq/Faq/Complex Types/$$).
|
||||
|
||||
$head Derivative$$
|
||||
CppAD defines the derivative of the $code abs$$ function is
|
||||
the $cref sign$$ function; i.e.,
|
||||
$latex \[
|
||||
{\rm abs}^{(1)} ( x ) = {\rm sign} (x ) =
|
||||
\left\{ \begin{array}{rl}
|
||||
+1 & {\rm if} \; x > 0 \\
|
||||
0 & {\rm if} \; x = 0 \\
|
||||
-1 & {\rm if} \; x < 0
|
||||
\end{array} \right.
|
||||
\] $$
|
||||
The result for $icode%x% == 0%$$ used to be a directional derivative.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/fabs.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref fabs.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base> AD<Base>::abs_me (void) const
|
||||
{
|
||||
AD<Base> result;
|
||||
result.value_ = abs(value_);
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||
|
||||
if( Variable(*this) )
|
||||
{ // add this operation to the tape
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AbsOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AbsOp) == 1 );
|
||||
local::ADTape<Base> *tape = tape_this();
|
||||
|
||||
// corresponding operand address
|
||||
tape->Rec_.PutArg(taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::AbsOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape->id_;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> abs(const AD<Base> &x)
|
||||
{ return x.abs_me(); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> abs(const VecAD_reference<Base> &x)
|
||||
{ return x.ADBase().abs_me(); }
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,867 @@
|
||||
# ifndef CPPAD_CORE_ABS_NORMAL_FUN_HPP
|
||||
# define CPPAD_CORE_ABS_NORMAL_FUN_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 abs_normal_fun$$
|
||||
$spell
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section Create An Abs-normal Representation of a Function$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.abs_normal_fun(%g%, %a%)%$$
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%>& %f%
|
||||
%$$
|
||||
It represents a function $latex f : \B{R}^n \rightarrow \B{R}^m$$.
|
||||
We assume that the only non-smooth terms in the representation are
|
||||
absolute value functions and use $latex s \in \B{Z}_+$$
|
||||
to represent the number of these terms.
|
||||
It is effectively $code const$$, except that some internal state
|
||||
that is not relevant to the user; see
|
||||
$cref/const ADFun/wish_list/const ADFun/$$.
|
||||
|
||||
$subhead n$$
|
||||
We use $icode n$$ to denote the dimension of the domain space for $icode f$$.
|
||||
|
||||
$subhead m$$
|
||||
We use $icode m$$ to denote the dimension of the range space for $icode f$$.
|
||||
|
||||
$subhead s$$
|
||||
We use $icode s$$ to denote the number of absolute value terms in $icode f$$.
|
||||
|
||||
|
||||
$head a$$
|
||||
The object $icode a$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %a%
|
||||
%$$
|
||||
The initial function representation in $icode a$$ is lost.
|
||||
Upon return it represents the result of the absolute terms
|
||||
$latex a : \B{R}^n \rightarrow \B{R}^s$$; see $latex a(x)$$ defined below.
|
||||
Note that $icode a$$ is constructed by copying $icode f$$
|
||||
and then changing the dependent variables. There may
|
||||
be many calculations in this representation that are not necessary
|
||||
and can be removed using
|
||||
$codei%
|
||||
%a%.optimize()
|
||||
%$$
|
||||
This optimization is not done automatically by $code abs_normal_fun$$
|
||||
because it may take a significant amount of time.
|
||||
|
||||
$subhead zeta$$
|
||||
Let $latex \zeta_0 ( x )$$
|
||||
denote the argument for the first absolute value term in $latex f(x)$$,
|
||||
$latex \zeta_1 ( x , |\zeta_0 (x)| )$$ for the second term, and so on.
|
||||
|
||||
$subhead a(x)$$
|
||||
For $latex i = 0 , \ldots , {s-1}$$ define
|
||||
$latex \[
|
||||
a_i (x)
|
||||
=
|
||||
| \zeta_i ( x , a_0 (x) , \ldots , a_{i-1} (x ) ) |
|
||||
\] $$
|
||||
This defines $latex a : \B{R}^n \rightarrow \B{R}^s$$.
|
||||
|
||||
$head g$$
|
||||
The object $icode g$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %g%
|
||||
%$$
|
||||
The initial function representation in $icode g$$ is lost.
|
||||
Upon return it represents the smooth function
|
||||
$latex g : \B{R}^{n + s} \rightarrow \B{R}^{m + s}$$ is defined by
|
||||
$latex \[
|
||||
g( x , u )
|
||||
=
|
||||
\left[ \begin{array}{c} y(x, u) \\ z(x, u) \end{array} \right]
|
||||
\] $$
|
||||
were $latex y(x, u)$$ and $latex z(x, u)$$ are defined below.
|
||||
|
||||
$subhead z(x, u)$$
|
||||
Define the smooth function
|
||||
$latex z : \B{R}^{n + s} \rightarrow \B{R}^s$$ by
|
||||
$latex \[
|
||||
z_i ( x , u ) = \zeta_i ( x , u_0 , \ldots , u_{i-1} )
|
||||
\] $$
|
||||
Note that the partial of $latex z_i$$ with respect to $latex u_j$$ is zero
|
||||
for $latex j \geq i$$.
|
||||
|
||||
$subhead y(x, u)$$
|
||||
There is a smooth function
|
||||
$latex y : \B{R}^{n + s} \rightarrow \B{R}^m$$
|
||||
such that $latex y( x , u ) = f(x)$$ whenever $latex u = a(x)$$.
|
||||
|
||||
$head Affine Approximation$$
|
||||
We define the affine approximations
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
y[ \hat{x} ]( x , u )
|
||||
& = &
|
||||
y ( \hat{x}, a( \hat{x} ) )
|
||||
+ \partial_x y ( \hat{x}, a( \hat{x} ) ) ( x - \hat{x} )
|
||||
+ \partial_u y ( \hat{x}, a( \hat{x} ) ) ( u - a( \hat{x} ) )
|
||||
\\
|
||||
z[ \hat{x} ]( x , u )
|
||||
& = &
|
||||
z ( \hat{x}, a( \hat{x} ) )
|
||||
+ \partial_x z ( \hat{x}, a( \hat{x} ) ) ( x - \hat{x} )
|
||||
+ \partial_u z ( \hat{x}, a( \hat{x} ) ) ( u - a( \hat{x} ) )
|
||||
\end{array}
|
||||
\] $$
|
||||
It follows that
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
y( x , u )
|
||||
& = &
|
||||
y[ \hat{x} ]( x , u ) + o ( x - \hat{x}, u - a( \hat{x} ) )
|
||||
\\
|
||||
z( x , u )
|
||||
& = &
|
||||
z[ \hat{x} ]( x , u ) + o ( x - \hat{x}, u - a( \hat{x} ) )
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Abs-normal Approximation$$
|
||||
|
||||
$subhead Approximating a(x)$$
|
||||
The function $latex a(x)$$ is not smooth, but it is equal to
|
||||
$latex | z(x, u) |$$ when $latex u = a(x)$$.
|
||||
Furthermore
|
||||
$latex \[
|
||||
z[ \hat{x} ]( x , u )
|
||||
=
|
||||
z ( \hat{x}, a( \hat{x} ) )
|
||||
+ \partial_x z ( \hat{x}, a( \hat{x} ) ) ( x - \hat{x} )
|
||||
+ \partial_u z ( \hat{x}, a( \hat{x} ) ) ( u - a( \hat{x} ) )
|
||||
\] $$
|
||||
The partial of $latex z_i$$ with respect to $latex u_j$$ is zero
|
||||
for $latex j \geq i$$. It follows that
|
||||
$latex \[
|
||||
z_i [ \hat{x} ]( x , u )
|
||||
=
|
||||
z_i ( \hat{x}, a( \hat{x} ) )
|
||||
+ \partial_x z_i ( \hat{x}, a( \hat{x} ) ) ( x - \hat{x} )
|
||||
+ \sum_{j < i} \partial_{u(j)}
|
||||
z_i ( \hat{x}, a( \hat{x} ) ) ( u_j - a_j ( \hat{x} ) )
|
||||
\] $$
|
||||
Considering the case $latex i = 0$$ we define
|
||||
$latex \[
|
||||
a_0 [ \hat{x} ]( x )
|
||||
=
|
||||
| z_0 [ \hat{x} ]( x , u ) |
|
||||
=
|
||||
\left|
|
||||
z_0 ( \hat{x}, a( \hat{x} ) )
|
||||
+ \partial_x z_0 ( \hat{x}, a( \hat{x} ) ) ( x - \hat{x} )
|
||||
\right|
|
||||
\] $$
|
||||
It follows that
|
||||
$latex \[
|
||||
a_0 (x) = a_0 [ \hat{x} ]( x ) + o ( x - \hat{x} )
|
||||
\] $$
|
||||
In general, we define $latex a_i [ \hat{x} ]$$ using
|
||||
$latex a_j [ \hat{x} ]$$ for $latex j < i$$ as follows:
|
||||
$latex \[
|
||||
a_i [ \hat{x} ]( x )
|
||||
=
|
||||
\left |
|
||||
z_i ( \hat{x}, a( \hat{x} ) )
|
||||
+ \partial_x z_i ( \hat{x}, a( \hat{x} ) ) ( x - \hat{x} )
|
||||
+ \sum_{j < i} \partial_{u(j)}
|
||||
z_i ( \hat{x}, a( \hat{x} ) )
|
||||
( a_j [ \hat{x} ] ( x ) - a_j ( \hat{x} ) )
|
||||
\right|
|
||||
\] $$
|
||||
It follows that
|
||||
$latex \[
|
||||
a (x) = a[ \hat{x} ]( x ) + o ( x - \hat{x} )
|
||||
\] $$
|
||||
Note that in the case where $latex z(x, u)$$ and $latex y(x, u)$$ are
|
||||
affine,
|
||||
$latex \[
|
||||
a[ \hat{x} ]( x ) = a( x )
|
||||
\] $$
|
||||
|
||||
|
||||
$subhead Approximating f(x)$$
|
||||
$latex \[
|
||||
f(x)
|
||||
=
|
||||
y ( x , a(x ) )
|
||||
=
|
||||
y [ \hat{x} ] ( x , a[ \hat{x} ] ( x ) )
|
||||
+ o( \Delta x )
|
||||
\] $$
|
||||
|
||||
$head Correspondence to Literature$$
|
||||
Using the notation
|
||||
$latex Z = \partial_x z(\hat{x}, \hat{u})$$,
|
||||
$latex L = \partial_u z(\hat{x}, \hat{u})$$,
|
||||
$latex J = \partial_x y(\hat{x}, \hat{u})$$,
|
||||
$latex Y = \partial_u y(\hat{x}, \hat{u})$$,
|
||||
the approximation for $latex z$$ and $latex y$$ are
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
z[ \hat{x} ]( x , u )
|
||||
& = &
|
||||
z ( \hat{x}, a( \hat{x} ) ) + Z ( x - \hat{x} ) + L ( u - a( \hat{x} ) )
|
||||
\\
|
||||
y[ \hat{x} ]( x , u )
|
||||
& = &
|
||||
y ( \hat{x}, a( \hat{x} ) ) + J ( x - \hat{x} ) + Y ( u - a( \hat{x} ) )
|
||||
\end{array}
|
||||
\] $$
|
||||
Moving the terms with $latex \hat{x}$$ together, we have
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
z[ \hat{x} ]( x , u )
|
||||
& = &
|
||||
z ( \hat{x}, a( \hat{x} ) ) - Z \hat{x} - L a( \hat{x} ) + Z x + L u
|
||||
\\
|
||||
y[ \hat{x} ]( x , u )
|
||||
& = &
|
||||
y ( \hat{x}, a( \hat{x} ) ) - J \hat{x} - Y a( \hat{x} ) + J x + Y u
|
||||
\end{array}
|
||||
\] $$
|
||||
Using the notation
|
||||
$latex c = z ( \hat{x}, \hat{u} ) - Z \hat{x} - L \hat{u}$$,
|
||||
$latex b = y ( \hat{x}, \hat{u} ) - J \hat{x} - Y \hat{u}$$,
|
||||
we have
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
z[ \hat{x} ]( x , u ) & = & c + Z x + L u
|
||||
\\
|
||||
y[ \hat{x} ]( x , u ) & = & b + J x + Y u
|
||||
\end{array}
|
||||
\] $$
|
||||
Considering the affine case, where the approximations are exact,
|
||||
and choosing $latex u = a(x) = |z(x, u)|$$, we obtain
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
z( x , a(x ) ) & = & c + Z x + L |z( x , a(x ) )|
|
||||
\\
|
||||
y( x , a(x ) ) & = & b + J x + Y |z( x , a(x ) )|
|
||||
\end{array}
|
||||
\] $$
|
||||
This is Equation (2) of the
|
||||
$cref/reference/abs_normal/Reference/$$.
|
||||
|
||||
$children%example/abs_normal/get_started.cpp
|
||||
%$$
|
||||
$head Example$$
|
||||
The file $cref abs_get_started.cpp$$ contains
|
||||
an example and test using this operation.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
/*!
|
||||
file abs_normal_fun.hpp
|
||||
Create an abs-normal representation of a function
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
Create an abs-normal representation of an ADFun object.
|
||||
|
||||
\tparam Base
|
||||
base type for this abs-normal form and for the function beging represented;
|
||||
i.e., f.
|
||||
|
||||
\param f
|
||||
is the function that this object will represent in abs-normal form.
|
||||
This is effectively const except that the play back state play_
|
||||
is used.
|
||||
*/
|
||||
|
||||
# define NOT_YET_COMPILING 0
|
||||
|
||||
template <class Base>
|
||||
void ADFun<Base>::abs_normal_fun(ADFun<Base>& g, ADFun<Base>& a)
|
||||
{ using namespace local;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Forward sweep to determine number of absolute value operations in f
|
||||
// -----------------------------------------------------------------------
|
||||
// The argument and result index in f for each absolute value operator
|
||||
CppAD::vector<addr_t> f_abs_arg;
|
||||
CppAD::vector<size_t> f_abs_res;
|
||||
//
|
||||
OpCode op; // this operator
|
||||
const addr_t* arg = CPPAD_NULL; // arguments for this operator
|
||||
size_t i_op; // index of this operator
|
||||
size_t i_var; // variable index for this operator
|
||||
play_.forward_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == BeginOp );
|
||||
//
|
||||
bool more_operators = true;
|
||||
while( more_operators )
|
||||
{
|
||||
// next op
|
||||
play_.forward_next(op, arg, i_op, i_var);
|
||||
switch( op )
|
||||
{ // absolute value operator
|
||||
case AbsOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
f_abs_arg.push_back( arg[0] );
|
||||
f_abs_res.push_back( i_var );
|
||||
break;
|
||||
|
||||
case CSumOp:
|
||||
// CSumOp has a variable number of arguments
|
||||
play_.forward_csum(op, arg, i_op, i_var);
|
||||
break;
|
||||
|
||||
case CSkipOp:
|
||||
// CSkip has a variable number of arguments
|
||||
play_.forward_cskip(op, arg, i_op, i_var);
|
||||
break;
|
||||
|
||||
case EndOp:
|
||||
more_operators = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
// Forward sweep to create new recording
|
||||
// ------------------------------------------------------------------------
|
||||
// recorder for new operation sequence
|
||||
recorder<Base> rec;
|
||||
//
|
||||
// number of variables in both operation sequences
|
||||
// (the AbsOp operators are replace by InvOp operators)
|
||||
const size_t num_var = play_.num_var_rec();
|
||||
//
|
||||
// mapping from old variable index to new variable index
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= num_var
|
||||
);
|
||||
CppAD::vector<addr_t> f2g_var(num_var);
|
||||
for(i_var = 0; i_var < num_var; i_var++)
|
||||
f2g_var[i_var] = addr_t( num_var ); // invalid (should not be used)
|
||||
//
|
||||
// record the independent variables in f
|
||||
play_.forward_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN( op == BeginOp );
|
||||
more_operators = true;
|
||||
while( more_operators )
|
||||
{ switch( op )
|
||||
{
|
||||
// phantom variable
|
||||
case BeginOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
CPPAD_ASSERT_UNKNOWN( arg[0] == 0 );
|
||||
rec.PutArg(0);
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// independent variables
|
||||
case InvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// end of independent variables
|
||||
default:
|
||||
more_operators = false;
|
||||
break;
|
||||
}
|
||||
if( more_operators )
|
||||
play_.forward_next(op, arg, i_op, i_var);
|
||||
}
|
||||
// add one for the phantom variable
|
||||
CPPAD_ASSERT_UNKNOWN( 1 + Domain() == i_var );
|
||||
//
|
||||
// record the independent variables corresponding AbsOp results
|
||||
size_t index_abs;
|
||||
for(index_abs = 0; index_abs < f_abs_res.size(); index_abs++)
|
||||
f2g_var[ f_abs_res[index_abs] ] = rec.PutOp(InvOp);
|
||||
//
|
||||
// used to hold new argument vector
|
||||
addr_t new_arg[6];
|
||||
//
|
||||
// Parameters in recording of f
|
||||
const Base* f_parameter = play_.GetPar();
|
||||
//
|
||||
// now loop through the rest of the
|
||||
more_operators = true;
|
||||
index_abs = 0;
|
||||
while( more_operators )
|
||||
{ addr_t mask; // temporary used in some switch cases
|
||||
switch( op )
|
||||
{
|
||||
// check setting of f_abs_arg and f_abs_res;
|
||||
case AbsOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
CPPAD_ASSERT_UNKNOWN( f_abs_arg[index_abs] == arg[0] );
|
||||
CPPAD_ASSERT_UNKNOWN( f_abs_res[index_abs] == i_var );
|
||||
CPPAD_ASSERT_UNKNOWN( f2g_var[i_var] > 0 );
|
||||
++index_abs;
|
||||
break;
|
||||
|
||||
// These operators come at beginning of take and are handled above
|
||||
case InvOp:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Unary operators, argument a parameter, one result
|
||||
case ParOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 1);
|
||||
new_arg[0] = rec.PutPar( f_parameter[ arg[0] ] );
|
||||
rec.PutArg( new_arg[0] );
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Unary operators, argument a variable, one result
|
||||
// (excluding the absolute value operator AbsOp)
|
||||
case AcosOp:
|
||||
case AcoshOp:
|
||||
case AsinOp:
|
||||
case AsinhOp:
|
||||
case AtanOp:
|
||||
case AtanhOp:
|
||||
case CosOp:
|
||||
case CoshOp:
|
||||
case ExpOp:
|
||||
case Expm1Op:
|
||||
case LogOp:
|
||||
case Log1pOp:
|
||||
case SignOp:
|
||||
case SinOp:
|
||||
case SinhOp:
|
||||
case SqrtOp:
|
||||
case TanOp:
|
||||
case TanhOp:
|
||||
// some of these operators have an auxillary result; e.g.,
|
||||
// sine and cosine are computed togeather.
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 1 || NumRes(op) == 2 );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );
|
||||
new_arg[0] = f2g_var[ arg[0] ];
|
||||
rec.PutArg( new_arg[0] );
|
||||
f2g_var[i_var] = rec.PutOp( op );
|
||||
break;
|
||||
|
||||
case ErfOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 5);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );
|
||||
// Error function is a special case
|
||||
// second argument is always the parameter 0
|
||||
// third argument is always the parameter 2 / sqrt(pi)
|
||||
rec.PutArg( rec.PutPar( Base(0.0) ) );
|
||||
rec.PutArg( rec.PutPar(
|
||||
Base( 1.0 / std::sqrt( std::atan(1.0) ) )
|
||||
) );
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
// --------------------------------------------------------------
|
||||
// Binary operators, left variable, right parameter, one result
|
||||
case SubvpOp:
|
||||
case DivvpOp:
|
||||
case PowvpOp:
|
||||
case ZmulvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );
|
||||
new_arg[0] = f2g_var[ arg[0] ];
|
||||
new_arg[1] = rec.PutPar( f_parameter[ arg[1] ] );
|
||||
rec.PutArg( new_arg[0], new_arg[1] );
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
// Binary operators, left index, right variable, one result
|
||||
case DisOp:
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
rec.PutArg( new_arg[0], new_arg[1] );
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Binary operators, left parameter, right variable, one result
|
||||
case AddpvOp:
|
||||
case SubpvOp:
|
||||
case MulpvOp:
|
||||
case DivpvOp:
|
||||
case PowpvOp:
|
||||
case ZmulpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );
|
||||
new_arg[0] = rec.PutPar( f_parameter[ arg[0] ] );
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
rec.PutArg( new_arg[0], new_arg[1] );
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
// --------------------------------------------------------------
|
||||
// Binary operators, left and right variables, one result
|
||||
case AddvvOp:
|
||||
case SubvvOp:
|
||||
case MulvvOp:
|
||||
case DivvvOp:
|
||||
case ZmulvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );
|
||||
new_arg[0] = f2g_var[ arg[0] ];
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
rec.PutArg( new_arg[0], new_arg[1] );
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
// Conditional expression operators
|
||||
case CExpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 6, 1);
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = arg[1];
|
||||
mask = 1;
|
||||
for(size_t i = 2; i < 6; i++)
|
||||
{ if( arg[1] & mask )
|
||||
{ CPPAD_ASSERT_UNKNOWN( size_t(f2g_var[arg[i]]) < num_var );
|
||||
new_arg[i] = f2g_var[ arg[i] ];
|
||||
}
|
||||
else
|
||||
new_arg[i] = rec.PutPar( f_parameter[ arg[i] ] );
|
||||
mask = mask << 1;
|
||||
}
|
||||
rec.PutArg(
|
||||
new_arg[0] ,
|
||||
new_arg[1] ,
|
||||
new_arg[2] ,
|
||||
new_arg[3] ,
|
||||
new_arg[4] ,
|
||||
new_arg[5]
|
||||
);
|
||||
f2g_var[i_var] = rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// --------------------------------------------------
|
||||
// Operators with no arguments and no results
|
||||
case EndOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 0);
|
||||
rec.PutOp(op);
|
||||
more_operators = false;
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Operations with two arguments and no results
|
||||
case LepvOp:
|
||||
case LtpvOp:
|
||||
case EqpvOp:
|
||||
case NepvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
new_arg[0] = rec.PutPar( f_parameter[ arg[0] ] );
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
rec.PutArg(new_arg[0], new_arg[1]);
|
||||
rec.PutOp(op);
|
||||
break;
|
||||
//
|
||||
case LevpOp:
|
||||
case LtvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
new_arg[0] = f2g_var[ arg[0] ];
|
||||
new_arg[1] = rec.PutPar( f_parameter[ arg[1] ] );
|
||||
rec.PutArg(new_arg[0], new_arg[1]);
|
||||
rec.PutOp(op);
|
||||
break;
|
||||
//
|
||||
case LevvOp:
|
||||
case LtvvOp:
|
||||
case EqvvOp:
|
||||
case NevvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 2, 0);
|
||||
new_arg[0] = f2g_var[ arg[0] ];
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
rec.PutArg(new_arg[0], new_arg[1]);
|
||||
rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// print forward operator
|
||||
case PriOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 5, 0);
|
||||
//
|
||||
// arg[0]
|
||||
new_arg[0] = arg[0];
|
||||
//
|
||||
// arg[1]
|
||||
if( arg[0] & 1 )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
}
|
||||
else
|
||||
{ new_arg[1] = rec.PutPar( f_parameter[ arg[1] ] );
|
||||
}
|
||||
//
|
||||
// arg[3]
|
||||
if( arg[0] & 2 )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[3] ] ) < num_var );
|
||||
new_arg[3] = f2g_var[ arg[3] ];
|
||||
}
|
||||
else
|
||||
{ new_arg[3] = rec.PutPar( f_parameter[ arg[3] ] );
|
||||
}
|
||||
new_arg[2] = rec.PutTxt( play_.GetTxt( arg[2] ) );
|
||||
new_arg[4] = rec.PutTxt( play_.GetTxt( arg[4] ) );
|
||||
//
|
||||
rec.PutArg(
|
||||
new_arg[0] ,
|
||||
new_arg[1] ,
|
||||
new_arg[2] ,
|
||||
new_arg[3] ,
|
||||
new_arg[4]
|
||||
);
|
||||
// no result
|
||||
rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// ---------------------------------------------------
|
||||
// VecAD operators
|
||||
|
||||
// Load using a parameter index
|
||||
case LdpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 1);
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = arg[1];
|
||||
new_arg[2] = arg[2];
|
||||
rec.PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
f2g_var[i_var] = rec.PutLoadOp(op);
|
||||
break;
|
||||
|
||||
// Load using a variable index
|
||||
case LdvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 1);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
new_arg[2] = arg[2];
|
||||
rec.PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
f2g_var[i_var] = rec.PutLoadOp(op);
|
||||
break;
|
||||
|
||||
// Store a parameter using a parameter index
|
||||
case StppOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = rec.PutPar( f_parameter[ arg[1] ] );
|
||||
new_arg[2] = rec.PutPar( f_parameter[ arg[2] ] );
|
||||
rec.PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// Store a parameter using a variable index
|
||||
case StvpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
new_arg[2] = rec.PutPar( f_parameter[ arg[2] ] );
|
||||
rec.PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// Store a variable using a parameter index
|
||||
case StpvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[2] ] ) < num_var );
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = rec.PutPar( f_parameter[ arg[1] ] );
|
||||
new_arg[2] = f2g_var[ arg[2] ];
|
||||
rec.PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
rec.PutOp(op);
|
||||
break;
|
||||
|
||||
// Store a variable using a variable index
|
||||
case StvvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 3, 0);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[2] ] ) < num_var );
|
||||
new_arg[0] = arg[0];
|
||||
new_arg[1] = f2g_var[ arg[1] ];
|
||||
new_arg[2] = f2g_var[ arg[2] ];
|
||||
rec.PutArg(
|
||||
new_arg[0],
|
||||
new_arg[1],
|
||||
new_arg[2]
|
||||
);
|
||||
break;
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// user atomic function call operators
|
||||
|
||||
case UserOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 4, 0);
|
||||
// atomic_index, user_old, user_n, user_m
|
||||
rec.PutArg(arg[0], arg[1], arg[2], arg[3]);
|
||||
rec.PutOp(UserOp);
|
||||
break;
|
||||
|
||||
case UsrapOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 0);
|
||||
new_arg[0] = rec.PutPar( f_parameter[ arg[0] ] );
|
||||
rec.PutArg(new_arg[0]);
|
||||
rec.PutOp(UsrapOp);
|
||||
break;
|
||||
|
||||
case UsravOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 0);
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[arg[0]] ) < num_var );
|
||||
new_arg[0] = f2g_var[ arg[0] ];
|
||||
rec.PutArg(new_arg[0]);
|
||||
rec.PutOp(UsravOp);
|
||||
break;
|
||||
|
||||
case UsrrpOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 1, 0);
|
||||
new_arg[0] = rec.PutPar( f_parameter[ arg[0] ] );
|
||||
rec.PutArg(new_arg[0]);
|
||||
rec.PutOp(UsrrpOp);
|
||||
break;
|
||||
|
||||
case UsrrvOp:
|
||||
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||
f2g_var[i_var] = rec.PutOp(UsrrvOp);
|
||||
break;
|
||||
// ---------------------------------------------------
|
||||
|
||||
// all cases should be handled above
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(false);
|
||||
}
|
||||
if( more_operators )
|
||||
play_.forward_next(op, arg, i_op, i_var);
|
||||
}
|
||||
// Check a few expected results
|
||||
CPPAD_ASSERT_UNKNOWN( rec.num_op_rec() == play_.num_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( rec.num_var_rec() == play_.num_var_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( rec.num_load_op_rec() == play_.num_load_op_rec() );
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Use rec to create the function g
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// number of variables in the recording
|
||||
g.num_var_tape_ = rec.num_var_rec();
|
||||
|
||||
// dimension cskip_op vector to number of operators
|
||||
g.cskip_op_.erase();
|
||||
g.cskip_op_.extend( rec.num_op_rec() );
|
||||
|
||||
// independent variables in g: (x, u)
|
||||
size_t s = f_abs_res.size();
|
||||
size_t n = Domain();
|
||||
g.ind_taddr_.resize(n + s);
|
||||
// (x, u)
|
||||
for(size_t j = 0; j < n; j++)
|
||||
{ g.ind_taddr_[j] = f2g_var[ ind_taddr_[j] ];
|
||||
CPPAD_ASSERT_UNKNOWN( g.ind_taddr_[j] == j + 1 );
|
||||
}
|
||||
for(size_t j = 0; j < s; j++)
|
||||
{ g.ind_taddr_[n + j] = f2g_var[ f_abs_res[j] ];
|
||||
CPPAD_ASSERT_UNKNOWN( g.ind_taddr_[n + j] == n + j + 1 );
|
||||
}
|
||||
|
||||
// dependent variable in g: (y, z)
|
||||
CPPAD_ASSERT_UNKNOWN( s == f_abs_arg.size() );
|
||||
size_t m = Range();
|
||||
g.dep_taddr_.resize(m + s);
|
||||
for(size_t i = 0; i < m; i++)
|
||||
{ g.dep_taddr_[i] = f2g_var[ dep_taddr_[i] ];
|
||||
CPPAD_ASSERT_UNKNOWN( g.dep_taddr_[i] < num_var );
|
||||
}
|
||||
for(size_t i = 0; i < s; i++)
|
||||
{ g.dep_taddr_[m + i] = f2g_var[ f_abs_arg[i] ];
|
||||
CPPAD_ASSERT_UNKNOWN( g.dep_taddr_[m + i] < num_var );
|
||||
}
|
||||
|
||||
// which dependent variables are parameters
|
||||
g.dep_parameter_.resize(m + s);
|
||||
for(size_t i = 0; i < m; i++)
|
||||
g.dep_parameter_[i] = dep_parameter_[i];
|
||||
for(size_t i = 0; i < s; i++)
|
||||
g.dep_parameter_[m + i] = false;
|
||||
|
||||
// free memory allocated for sparse Jacobian calculation
|
||||
// (the resutls are no longer valid)
|
||||
g.for_jac_sparse_pack_.resize(0, 0);
|
||||
g.for_jac_sparse_set_.resize(0, 0);
|
||||
|
||||
// free taylor coefficient memory
|
||||
g.taylor_.free();
|
||||
g.num_order_taylor_ = 0;
|
||||
g.cap_order_taylor_ = 0;
|
||||
|
||||
// Transferring the recording swaps its vectors so do this last
|
||||
// replace the recording in g (this ADFun object)
|
||||
g.play_.get(rec);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Create the function a
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// start with a copy of f
|
||||
a = *this;
|
||||
|
||||
// dependent variables in a(x)
|
||||
CPPAD_ASSERT_UNKNOWN( s == f_abs_arg.size() );
|
||||
a.dep_taddr_.resize(s);
|
||||
for(size_t i = 0; i < s; i++)
|
||||
{ a.dep_taddr_[i] = f_abs_res[i];
|
||||
CPPAD_ASSERT_UNKNOWN( a.dep_taddr_[i] < num_var );
|
||||
}
|
||||
|
||||
// free memory allocated for sparse Jacobian calculation
|
||||
// (the resutls are no longer valid)
|
||||
a.for_jac_sparse_pack_.resize(0, 0);
|
||||
a.for_jac_sparse_set_.resize(0, 0);
|
||||
|
||||
// free taylor coefficient memory
|
||||
a.taylor_.free();
|
||||
a.num_order_taylor_ = 0;
|
||||
a.cap_order_taylor_ = 0;
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
# endif
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
# ifndef CPPAD_CORE_ACOSH_HPP
|
||||
# define CPPAD_CORE_ACOSH_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 acosh$$
|
||||
$spell
|
||||
acosh
|
||||
const
|
||||
Vec
|
||||
std
|
||||
cmath
|
||||
CppAD
|
||||
$$
|
||||
$section The Inverse Hyperbolic Cosine Function: acosh$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = acosh(%x%)%$$
|
||||
|
||||
$head Description$$
|
||||
The inverse hyperbolic cosine function is defined by
|
||||
$icode%x% == cosh(%y%)%$$.
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head CPPAD_USE_CPLUSPLUS_2011$$
|
||||
|
||||
$subhead true$$
|
||||
If this preprocessor symbol is true ($code 1$$),
|
||||
and $icode x$$ is an AD type,
|
||||
this is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$subhead false$$
|
||||
If this preprocessor symbol is false ($code 0$$),
|
||||
CppAD uses the representation
|
||||
$latex \[
|
||||
\R{acosh} (x) = \log \left( x + \sqrt{ x^2 - 1 } \right)
|
||||
\] $$
|
||||
to compute this function.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/acosh.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref acosh.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/configure.hpp>
|
||||
# if ! CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Type>
|
||||
Type acosh_template(const Type &x)
|
||||
{ return CppAD::log( x + CppAD::sqrt( x * x - Type(1) ) );
|
||||
}
|
||||
|
||||
inline float acosh(const float &x)
|
||||
{ return acosh_template(x); }
|
||||
|
||||
inline double acosh(const double &x)
|
||||
{ return acosh_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> acosh(const AD<Base> &x)
|
||||
{ return acosh_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> acosh(const VecAD_reference<Base> &x)
|
||||
{ return acosh_template( x.ADBase() ); }
|
||||
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif // CPPAD_USE_CPLUSPLUS_2011
|
||||
# endif // CPPAD_ACOSH_INCLUDED
|
||||
+291
@@ -0,0 +1,291 @@
|
||||
# ifndef CPPAD_CORE_AD_HPP
|
||||
# define CPPAD_CORE_AD_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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
// simple AD operations that must be defined for AD as well as base class
|
||||
# include <cppad/core/ordered.hpp>
|
||||
# include <cppad/core/identical.hpp>
|
||||
|
||||
// define the template classes that are used by the AD template class
|
||||
# include <cppad/local/op_code.hpp>
|
||||
# include <cppad/local/recorder.hpp>
|
||||
# include <cppad/local/player.hpp>
|
||||
# include <cppad/local/ad_tape.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
typedef enum {
|
||||
tape_manage_new,
|
||||
tape_manage_delete,
|
||||
tape_manage_clear
|
||||
} tape_manage_job;
|
||||
|
||||
template <class Base>
|
||||
class AD {
|
||||
private :
|
||||
// -----------------------------------------------------------------------
|
||||
// value_ corresponding to this object
|
||||
Base value_;
|
||||
|
||||
// Tape identifier corresponding to taddr
|
||||
tape_id_t tape_id_;
|
||||
|
||||
// taddr_ in tape for this variable
|
||||
addr_t taddr_;
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// enable use of AD<Base> in parallel mode
|
||||
template <class Type>
|
||||
friend void parallel_ad(void);
|
||||
|
||||
// template friend functions where template parameter is not bound
|
||||
template <class VectorAD>
|
||||
friend void Independent(VectorAD &x, size_t abort_op_index);
|
||||
|
||||
// one argument functions
|
||||
friend bool Parameter <Base>
|
||||
(const AD<Base> &u);
|
||||
friend bool Parameter <Base>
|
||||
(const VecAD<Base> &u);
|
||||
friend bool Variable <Base>
|
||||
(const AD<Base> &u);
|
||||
friend bool Variable <Base>
|
||||
(const VecAD<Base> &u);
|
||||
friend int Integer <Base>
|
||||
(const AD<Base> &u);
|
||||
friend AD Var2Par <Base>
|
||||
(const AD<Base> &u);
|
||||
|
||||
// power function
|
||||
friend AD pow <Base>
|
||||
(const AD<Base> &x, const AD<Base> &y);
|
||||
|
||||
// azmul function
|
||||
friend AD azmul <Base>
|
||||
(const AD<Base> &x, const AD<Base> &y);
|
||||
|
||||
// order determining functions, see ordered.hpp
|
||||
friend bool GreaterThanZero <Base> (const AD<Base> &x);
|
||||
friend bool GreaterThanOrZero <Base> (const AD<Base> &x);
|
||||
friend bool LessThanZero <Base> (const AD<Base> &x);
|
||||
friend bool LessThanOrZero <Base> (const AD<Base> &x);
|
||||
friend bool abs_geq <Base>
|
||||
(const AD<Base>& x, const AD<Base>& y);
|
||||
|
||||
// The identical property functions, see identical.hpp
|
||||
friend bool IdenticalPar <Base> (const AD<Base> &x);
|
||||
friend bool IdenticalZero <Base> (const AD<Base> &x);
|
||||
friend bool IdenticalOne <Base> (const AD<Base> &x);
|
||||
friend bool IdenticalEqualPar <Base>
|
||||
(const AD<Base> &x, const AD<Base> &y);
|
||||
|
||||
// EqualOpSeq function
|
||||
friend bool EqualOpSeq <Base>
|
||||
(const AD<Base> &u, const AD<Base> &v);
|
||||
|
||||
// NearEqual function
|
||||
friend bool NearEqual <Base> (
|
||||
const AD<Base> &x, const AD<Base> &y, const Base &r, const Base &a);
|
||||
|
||||
friend bool NearEqual <Base> (
|
||||
const Base &x, const AD<Base> &y, const Base &r, const Base &a);
|
||||
|
||||
friend bool NearEqual <Base> (
|
||||
const AD<Base> &x, const Base &y, const Base &r, const Base &a);
|
||||
|
||||
// CondExp function
|
||||
friend AD<Base> CondExpOp <Base> (
|
||||
enum CompareOp cop ,
|
||||
const AD<Base> &left ,
|
||||
const AD<Base> &right ,
|
||||
const AD<Base> &trueCase ,
|
||||
const AD<Base> &falseCase
|
||||
);
|
||||
|
||||
// classes
|
||||
friend class local::ADTape<Base>;
|
||||
friend class ADFun<Base>;
|
||||
friend class atomic_base<Base>;
|
||||
friend class discrete<Base>;
|
||||
friend class VecAD<Base>;
|
||||
friend class VecAD_reference<Base>;
|
||||
|
||||
// arithematic binary operators
|
||||
friend AD<Base> operator + <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend AD<Base> operator - <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend AD<Base> operator * <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend AD<Base> operator / <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
|
||||
// comparison operators
|
||||
friend bool operator < <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool operator <= <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool operator > <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool operator >= <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool operator == <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
friend bool operator != <Base>
|
||||
(const AD<Base> &left, const AD<Base> &right);
|
||||
|
||||
// input operator
|
||||
friend std::istream& operator >> <Base>
|
||||
(std::istream &is, AD<Base> &x);
|
||||
|
||||
// output operations
|
||||
friend std::ostream& operator << <Base>
|
||||
(std::ostream &os, const AD<Base> &x);
|
||||
friend void PrintFor <Base> (
|
||||
const AD<Base>& flag ,
|
||||
const char* before ,
|
||||
const AD<Base>& var ,
|
||||
const char* after
|
||||
);
|
||||
public:
|
||||
// type of value
|
||||
typedef Base value_type;
|
||||
|
||||
// implicit default constructor
|
||||
inline AD(void);
|
||||
|
||||
// use default implicit copy constructor and assignment operator
|
||||
// inline AD(const AD &x);
|
||||
// inline AD& operator=(const AD &x);
|
||||
|
||||
// implicit construction and assingment from base type
|
||||
inline AD(const Base &b);
|
||||
inline AD& operator=(const Base &b);
|
||||
|
||||
// implicit contructor and assignment from VecAD<Base>::reference
|
||||
inline AD(const VecAD_reference<Base> &x);
|
||||
inline AD& operator=(const VecAD_reference<Base> &x);
|
||||
|
||||
// explicit construction from some other type (depricated)
|
||||
template <class T> inline explicit AD(const T &t);
|
||||
|
||||
// assignment from some other type
|
||||
template <class T> inline AD& operator=(const T &right);
|
||||
|
||||
// base type corresponding to an AD object
|
||||
friend Base Value <Base> (const AD<Base> &x);
|
||||
|
||||
// compound assignment operators
|
||||
inline AD& operator += (const AD &right);
|
||||
inline AD& operator -= (const AD &right);
|
||||
inline AD& operator *= (const AD &right);
|
||||
inline AD& operator /= (const AD &right);
|
||||
|
||||
// unary operators
|
||||
inline AD operator +(void) const;
|
||||
inline AD operator -(void) const;
|
||||
|
||||
// destructor
|
||||
~AD(void)
|
||||
{ }
|
||||
|
||||
// interface so these functions need not be friends
|
||||
inline AD abs_me(void) const;
|
||||
inline AD acos_me(void) const;
|
||||
inline AD asin_me(void) const;
|
||||
inline AD atan_me(void) const;
|
||||
inline AD cos_me(void) const;
|
||||
inline AD cosh_me(void) const;
|
||||
inline AD exp_me(void) const;
|
||||
inline AD fabs_me(void) const;
|
||||
inline AD log_me(void) const;
|
||||
inline AD sin_me(void) const;
|
||||
inline AD sign_me(void) const;
|
||||
inline AD sinh_me(void) const;
|
||||
inline AD sqrt_me(void) const;
|
||||
inline AD tan_me(void) const;
|
||||
inline AD tanh_me(void) const;
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
inline AD erf_me(void) const;
|
||||
inline AD asinh_me(void) const;
|
||||
inline AD acosh_me(void) const;
|
||||
inline AD atanh_me(void) const;
|
||||
inline AD expm1_me(void) const;
|
||||
inline AD log1p_me(void) const;
|
||||
# endif
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// static public member functions
|
||||
|
||||
// abort current AD<Base> recording
|
||||
static void abort_recording(void);
|
||||
|
||||
// set the maximum number of OpenMP threads (deprecated)
|
||||
static void omp_max_thread(size_t number);
|
||||
|
||||
// These functions declared public so can be accessed by user through
|
||||
// a macro interface and are not intended for direct use.
|
||||
// The macro interface is documented in bool_fun.hpp.
|
||||
// Developer documentation for these fucntions is in bool_fun.hpp
|
||||
static inline bool UnaryBool(
|
||||
bool FunName(const Base &x),
|
||||
const AD<Base> &x
|
||||
);
|
||||
static inline bool BinaryBool(
|
||||
bool FunName(const Base &x, const Base &y),
|
||||
const AD<Base> &x , const AD<Base> &y
|
||||
);
|
||||
|
||||
private:
|
||||
//
|
||||
// Make this variable a parameter
|
||||
//
|
||||
void make_parameter(void)
|
||||
{ CPPAD_ASSERT_UNKNOWN( Variable(*this) ); // currently a var
|
||||
tape_id_ = 0;
|
||||
}
|
||||
//
|
||||
// Make this parameter a new variable
|
||||
//
|
||||
void make_variable(tape_id_t id, addr_t taddr)
|
||||
{ CPPAD_ASSERT_UNKNOWN( Parameter(*this) ); // currently a par
|
||||
CPPAD_ASSERT_UNKNOWN( taddr > 0 ); // sure valid taddr
|
||||
|
||||
taddr_ = taddr;
|
||||
tape_id_ = id;
|
||||
}
|
||||
// ---------------------------------------------------------------
|
||||
// tape linking functions
|
||||
//
|
||||
// not static
|
||||
inline local::ADTape<Base>* tape_this(void) const;
|
||||
//
|
||||
// static
|
||||
inline static tape_id_t** tape_id_handle(size_t thread);
|
||||
inline static tape_id_t* tape_id_ptr(size_t thread);
|
||||
inline static local::ADTape<Base>** tape_handle(size_t thread);
|
||||
static local::ADTape<Base>* tape_manage(tape_manage_job job);
|
||||
inline static local::ADTape<Base>* tape_ptr(void);
|
||||
inline static local::ADTape<Base>* tape_ptr(tape_id_t tape_id);
|
||||
};
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
// tape linking private functions
|
||||
# include <cppad/core/tape_link.hpp>
|
||||
|
||||
// operations that expect the AD template class to be defined
|
||||
|
||||
|
||||
# endif
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
# ifndef CPPAD_CORE_AD_ASSIGN_HPP
|
||||
# define CPPAD_CORE_AD_ASSIGN_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 ad_assign$$
|
||||
$spell
|
||||
Vec
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section AD Assignment Operator$$
|
||||
$mindex assign Base VecAD$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = %x%$$
|
||||
|
||||
$head Purpose$$
|
||||
Assigns the value in $icode x$$ to the object $icode y$$.
|
||||
In either case,
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Type% &%x%
|
||||
%$$
|
||||
where $icode Type$$ is
|
||||
$codei%VecAD<%Base%>::reference%$$,
|
||||
$codei%AD<%Base%>%$$,
|
||||
$icode Base$$,
|
||||
or any type that has an implicit constructor of the form
|
||||
$icode%Base%(%x%)%$$.
|
||||
|
||||
$head y$$
|
||||
The target $icode y$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %y%
|
||||
%$$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/ad_assign.cpp
|
||||
%$$
|
||||
The file $cref ad_assign.cpp$$ contain examples and tests of these operations.
|
||||
It test returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
\file ad_assign.hpp
|
||||
AD<Base> constructors and and copy operations.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AD_default_assign
|
||||
Use default assignment operator
|
||||
because they may be optimized better than the code below:
|
||||
\code
|
||||
template <class Base>
|
||||
inline AD<Base>& AD<Base>::operator=(const AD<Base> &right)
|
||||
{ value_ = right.value_;
|
||||
tape_id_ = right.tape_id_;
|
||||
taddr_ = right.taddr_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
/*!
|
||||
Assignment to Base type value.
|
||||
|
||||
\tparam Base
|
||||
Base type for this AD object.
|
||||
|
||||
\param b
|
||||
is the Base type value being assignment to this AD object.
|
||||
The tape identifier will be an invalid tape identifier,
|
||||
so this object is initially a parameter.
|
||||
*/
|
||||
template <class Base>
|
||||
inline AD<Base>& AD<Base>::operator=(const Base &b)
|
||||
{ value_ = b;
|
||||
tape_id_ = 0;
|
||||
|
||||
// check that this is a parameter
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(*this) );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
Assignment to an ADVec<Base> element drops the vector information.
|
||||
|
||||
\tparam Base
|
||||
Base type for this AD object.
|
||||
*/
|
||||
template <class Base>
|
||||
inline AD<Base>& AD<Base>::operator=(const VecAD_reference<Base> &x)
|
||||
{ return *this = x.ADBase(); }
|
||||
|
||||
/*!
|
||||
Assignment from any other type, converts to Base type, and then uses assignment
|
||||
from Base type.
|
||||
|
||||
\tparam Base
|
||||
Base type for this AD object.
|
||||
|
||||
\tparam T
|
||||
is the the type that is being assigned to AD<Base>.
|
||||
There must be an assignment for Base from Type.
|
||||
|
||||
\param t
|
||||
is the object that is being assigned to an AD<Base> object.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class T>
|
||||
inline AD<Base>& AD<Base>::operator=(const T &t)
|
||||
{ return *this = Base(t); }
|
||||
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
# ifndef CPPAD_CORE_AD_BINARY_HPP
|
||||
# define CPPAD_CORE_AD_BINARY_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 ad_binary$$
|
||||
$spell
|
||||
Op
|
||||
VecAD
|
||||
const
|
||||
$$
|
||||
|
||||
$section AD Binary Arithmetic Operators$$
|
||||
$mindex + add plus - subtract minus * multiply times / divide$$
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
$icode%z% = %x% %Op% %y%$$
|
||||
|
||||
$head Purpose$$
|
||||
Performs arithmetic operations where either $icode x$$ or $icode y$$
|
||||
has type
|
||||
$codei%AD<%Base%>%$$ or
|
||||
$cref%VecAD<Base>::reference%VecAD%VecAD<Base>::reference%$$.
|
||||
|
||||
$head Op$$
|
||||
The operator $icode Op$$ is one of the following
|
||||
$table
|
||||
$bold Op$$ $cnext $bold Meaning$$ $rnext
|
||||
$code +$$ $cnext $icode z$$ is $icode x$$ plus $icode y$$ $rnext
|
||||
$code -$$ $cnext $icode z$$ is $icode x$$ minus $icode y$$ $rnext
|
||||
$code *$$ $cnext $icode z$$ is $icode x$$ times $icode y$$ $rnext
|
||||
$code /$$ $cnext $icode z$$ is $icode x$$ divided by $icode y$$
|
||||
$tend
|
||||
|
||||
$head Base$$
|
||||
The type $icode Base$$ is determined by the operand that
|
||||
has type $codei%AD<%Base%>%$$ or $codei%VecAD<%Base%>::reference%$$.
|
||||
|
||||
$head x$$
|
||||
The operand $icode x$$ has the following prototype
|
||||
$codei%
|
||||
const %Type% &%x%
|
||||
%$$
|
||||
where $icode Type$$ is
|
||||
$codei%VecAD<%Base%>::reference%$$,
|
||||
$codei%AD<%Base%>%$$,
|
||||
$icode Base$$, or
|
||||
$code double$$.
|
||||
|
||||
$head y$$
|
||||
The operand $icode y$$ has the following prototype
|
||||
$codei%
|
||||
const %Type% &%y%
|
||||
%$$
|
||||
where $icode Type$$ is
|
||||
$codei%VecAD<%Base%>::reference%$$,
|
||||
$codei%AD<%Base%>%$$,
|
||||
$icode Base$$, or
|
||||
$code double$$.
|
||||
|
||||
|
||||
$head z$$
|
||||
The result $icode z$$ has the following prototype
|
||||
$codei%
|
||||
%Type% %z%
|
||||
%$$
|
||||
where $icode Type$$ is
|
||||
$codei%AD<%Base%>%$$.
|
||||
|
||||
$head Operation Sequence$$
|
||||
This is an $cref/atomic/glossary/Operation/Atomic/$$
|
||||
$cref/AD of Base/glossary/AD of Base/$$ operation
|
||||
and hence it is part of the current
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$children%
|
||||
example/general/add.cpp%
|
||||
example/general/sub.cpp%
|
||||
example/general/mul.cpp%
|
||||
example/general/div.cpp
|
||||
%$$
|
||||
|
||||
$head Example$$
|
||||
The following files contain examples and tests of these functions.
|
||||
Each test returns true if it succeeds and false otherwise.
|
||||
$table
|
||||
$rref add.cpp$$
|
||||
$rref sub.cpp$$
|
||||
$rref mul.cpp$$
|
||||
$rref div.cpp$$
|
||||
$tend
|
||||
|
||||
$head Derivative$$
|
||||
If $latex f$$ and $latex g$$ are
|
||||
$cref/Base functions/glossary/Base Function/$$
|
||||
|
||||
$subhead Addition$$
|
||||
$latex \[
|
||||
\D{[ f(x) + g(x) ]}{x} = \D{f(x)}{x} + \D{g(x)}{x}
|
||||
\] $$
|
||||
|
||||
$subhead Subtraction$$
|
||||
$latex \[
|
||||
\D{[ f(x) - g(x) ]}{x} = \D{f(x)}{x} - \D{g(x)}{x}
|
||||
\] $$
|
||||
|
||||
$subhead Multiplication$$
|
||||
$latex \[
|
||||
\D{[ f(x) * g(x) ]}{x} = g(x) * \D{f(x)}{x} + f(x) * \D{g(x)}{x}
|
||||
\] $$
|
||||
|
||||
$subhead Division$$
|
||||
$latex \[
|
||||
\D{[ f(x) / g(x) ]}{x} =
|
||||
[1/g(x)] * \D{f(x)}{x} - [f(x)/g(x)^2] * \D{g(x)}{x}
|
||||
\] $$
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/core/add.hpp>
|
||||
# include <cppad/core/sub.hpp>
|
||||
# include <cppad/core/mul.hpp>
|
||||
# include <cppad/core/div.hpp>
|
||||
|
||||
# endif
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
# ifndef CPPAD_CORE_AD_CTOR_HPP
|
||||
# define CPPAD_CORE_AD_CTOR_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 ad_ctor$$
|
||||
$spell
|
||||
cppad
|
||||
ctor
|
||||
initializes
|
||||
Vec
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section AD Constructors $$
|
||||
$mindex convert Base VecAD$$
|
||||
|
||||
$head Syntax$$
|
||||
$codei%AD<%Base%> %y%()
|
||||
%$$
|
||||
$codei%AD<%Base%> %y%(%x%)
|
||||
%$$
|
||||
|
||||
$head Purpose$$
|
||||
creates a new $codei%AD<%Base%>%$$ object $icode y$$
|
||||
and initializes its value as equal to $icode x$$.
|
||||
|
||||
$head x$$
|
||||
|
||||
$subhead implicit$$
|
||||
There is an implicit constructor where $icode x$$ has one of the following
|
||||
prototypes:
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
const VecAD<%Base%>& %x%
|
||||
%$$
|
||||
|
||||
$subhead explicit$$
|
||||
There is an explicit constructor where $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Type%& %x%
|
||||
%$$
|
||||
for any type that has an explicit constructor of the form
|
||||
$icode%Base%(%x%)%$$.
|
||||
|
||||
$head y$$
|
||||
The target $icode y$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %y%
|
||||
%$$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/ad_ctor.cpp
|
||||
%$$
|
||||
The files $cref ad_ctor.cpp$$ contain examples and tests of these operations.
|
||||
It test returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
\file ad_ctor.hpp
|
||||
AD<Base> constructors and and copy operations.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AD_default_ctor
|
||||
Use default copy constructor
|
||||
because they may be optimized better than the code below:
|
||||
\code
|
||||
template <class Base>
|
||||
inline AD<Base>::AD(const AD &x)
|
||||
{
|
||||
value_ = x.value_;
|
||||
tape_id_ = x.tape_id_;
|
||||
taddr_ = x.taddr_;
|
||||
|
||||
return;
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
/*!
|
||||
Default Constructor.
|
||||
|
||||
\tparam Base
|
||||
Base type for this AD object.
|
||||
*/
|
||||
template <class Base>
|
||||
inline AD<Base>::AD(void)
|
||||
: value_()
|
||||
, tape_id_(0)
|
||||
, taddr_(0)
|
||||
{ }
|
||||
|
||||
|
||||
/*!
|
||||
Constructor from Base type.
|
||||
|
||||
\tparam Base
|
||||
Base type for this AD object.
|
||||
|
||||
\param b
|
||||
is the Base type value corresponding to this AD object.
|
||||
The tape identifier will be an invalid tape identifier,
|
||||
so this object is initially a parameter.
|
||||
*/
|
||||
template <class Base>
|
||||
inline AD<Base>::AD(const Base &b)
|
||||
: value_(b)
|
||||
, tape_id_(0)
|
||||
, taddr_(0)
|
||||
{ // check that this is a parameter
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(*this) );
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructor from an ADVec<Base> element drops the vector information.
|
||||
|
||||
\tparam Base
|
||||
Base type for this AD object.
|
||||
*/
|
||||
template <class Base>
|
||||
inline AD<Base>::AD(const VecAD_reference<Base> &x)
|
||||
{ *this = x.ADBase(); }
|
||||
|
||||
/*!
|
||||
Constructor from any other type, converts to Base type, and uses constructor
|
||||
from Base type.
|
||||
|
||||
\tparam Base
|
||||
Base type for this AD object.
|
||||
|
||||
\tparam T
|
||||
is the the type that is being converted to AD<Base>.
|
||||
There must be a constructor for Base from Type.
|
||||
|
||||
\param t
|
||||
is the object that is being converted from T to AD<Base>.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class T>
|
||||
inline AD<Base>::AD(const T &t)
|
||||
: value_(Base(t))
|
||||
, tape_id_(0)
|
||||
, taddr_(0)
|
||||
{ }
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+712
@@ -0,0 +1,712 @@
|
||||
# ifndef CPPAD_CORE_AD_FUN_HPP
|
||||
# define CPPAD_CORE_AD_FUN_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 ADFun$$
|
||||
$spell
|
||||
xk
|
||||
Ind
|
||||
bool
|
||||
taylor_
|
||||
sizeof
|
||||
const
|
||||
std
|
||||
ind_taddr_
|
||||
dep_taddr_
|
||||
$$
|
||||
|
||||
$spell
|
||||
$$
|
||||
|
||||
$section ADFun Objects$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
An AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$
|
||||
is stored in an $code ADFun$$ object by its $cref FunConstruct$$.
|
||||
The $code ADFun$$ object can then be used to calculate function values,
|
||||
derivative values, and other values related to the corresponding function.
|
||||
|
||||
$childtable%
|
||||
omh/adfun.omh%
|
||||
cppad/core/optimize.hpp%
|
||||
example/abs_normal/abs_normal.omh%
|
||||
cppad/core/fun_check.hpp%
|
||||
cppad/core/check_for_nan.hpp
|
||||
%$$
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file ad_fun.hpp
|
||||
File used to define the ADFun<Base> class.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Class used to hold function objects
|
||||
|
||||
\tparam Base
|
||||
A function object has a recording of <tt>AD<Base></tt> operations.
|
||||
It does it calculations using \c Base operations.
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
class ADFun {
|
||||
// ------------------------------------------------------------
|
||||
// Private member variables
|
||||
private:
|
||||
/// Has this ADFun object been optmized
|
||||
bool has_been_optimized_;
|
||||
|
||||
/// Check for nan's and report message to user (default value is true).
|
||||
bool check_for_nan_;
|
||||
|
||||
/// If zero, ignoring comparison operators. Otherwise is the
|
||||
/// compare change count at which to store the operator index.
|
||||
size_t compare_change_count_;
|
||||
|
||||
/// If compare_change_count_ is zero, compare_change_number_ is also zero.
|
||||
/// Otherwise, it is set to the number of comparison operations that had a
|
||||
/// different result during the subsequent zero order forward.
|
||||
size_t compare_change_number_;
|
||||
|
||||
/// If compare_change_count is zero, compare_change_op_index_ is also
|
||||
/// zero. Otherwise it is the operator index for the comparison operator
|
||||
//// that corresponded to the number changing from count-1 to count.
|
||||
size_t compare_change_op_index_;
|
||||
|
||||
/// number of orders stored in taylor_
|
||||
size_t num_order_taylor_;
|
||||
|
||||
/// maximum number of orders that will fit in taylor_
|
||||
size_t cap_order_taylor_;
|
||||
|
||||
/// number of directions stored in taylor_
|
||||
size_t num_direction_taylor_;
|
||||
|
||||
/// number of variables in the recording (play_)
|
||||
size_t num_var_tape_;
|
||||
|
||||
/// tape address for the independent variables
|
||||
CppAD::vector<size_t> ind_taddr_;
|
||||
|
||||
/// tape address and parameter flag for the dependent variables
|
||||
CppAD::vector<size_t> dep_taddr_;
|
||||
|
||||
/// which dependent variables are actually parameters
|
||||
CppAD::vector<bool> dep_parameter_;
|
||||
|
||||
/// results of the forward mode calculations
|
||||
local::pod_vector<Base> taylor_;
|
||||
|
||||
/// which operations can be conditionally skipped
|
||||
/// Set during forward pass of order zero
|
||||
local::pod_vector<bool> cskip_op_;
|
||||
|
||||
/// Variable on the tape corresponding to each vecad load operation
|
||||
/// (if zero, the operation corresponds to a parameter).
|
||||
local::pod_vector<addr_t> load_op_;
|
||||
|
||||
/// the operation sequence corresponding to this object
|
||||
local::player<Base> play_;
|
||||
|
||||
/// Packed results of the forward mode Jacobian sparsity calculations.
|
||||
/// for_jac_sparse_pack_.n_set() != 0 implies other sparsity results
|
||||
/// are empty
|
||||
local::sparse_pack for_jac_sparse_pack_;
|
||||
|
||||
/// Set results of the forward mode Jacobian sparsity calculations
|
||||
/// for_jac_sparse_set_.n_set() != 0 implies for_sparse_pack_ is empty.
|
||||
local::sparse_list for_jac_sparse_set_;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Private member functions
|
||||
|
||||
/// change the operation sequence corresponding to this object
|
||||
template <typename ADvector>
|
||||
void Dependent(local::ADTape<Base> *tape, const ADvector &y);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// vector of bool version of ForSparseJac
|
||||
// (see doxygen in for_sparse_jac.hpp)
|
||||
template <class VectorSet>
|
||||
void ForSparseJacCase(
|
||||
bool set_type ,
|
||||
bool transpose ,
|
||||
bool dependency,
|
||||
size_t q ,
|
||||
const VectorSet& r ,
|
||||
VectorSet& s
|
||||
);
|
||||
// vector of std::set<size_t> version of ForSparseJac
|
||||
// (see doxygen in for_sparse_jac.hpp)
|
||||
template <class VectorSet>
|
||||
void ForSparseJacCase(
|
||||
const std::set<size_t>& set_type ,
|
||||
bool transpose ,
|
||||
bool dependency,
|
||||
size_t q ,
|
||||
const VectorSet& r ,
|
||||
VectorSet& s
|
||||
);
|
||||
// ------------------------------------------------------------
|
||||
// vector of bool version of RevSparseJac
|
||||
// (see doxygen in rev_sparse_jac.hpp)
|
||||
template <class VectorSet>
|
||||
void RevSparseJacCase(
|
||||
bool set_type ,
|
||||
bool transpose ,
|
||||
bool dependency,
|
||||
size_t p ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& r
|
||||
);
|
||||
// vector of std::set<size_t> version of RevSparseJac
|
||||
// (see doxygen in rev_sparse_jac.hpp)
|
||||
template <class VectorSet>
|
||||
void RevSparseJacCase(
|
||||
const std::set<size_t>& set_type ,
|
||||
bool transpose ,
|
||||
bool dependency,
|
||||
size_t p ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& r
|
||||
);
|
||||
// ------------------------------------------------------------
|
||||
// vector of bool version of ForSparseHes
|
||||
// (see doxygen in rev_sparse_hes.hpp)
|
||||
template <class VectorSet>
|
||||
void ForSparseHesCase(
|
||||
bool set_type ,
|
||||
const VectorSet& r ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& h
|
||||
);
|
||||
// vector of std::set<size_t> version of ForSparseHes
|
||||
// (see doxygen in rev_sparse_hes.hpp)
|
||||
template <class VectorSet>
|
||||
void ForSparseHesCase(
|
||||
const std::set<size_t>& set_type ,
|
||||
const VectorSet& r ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& h
|
||||
);
|
||||
// ------------------------------------------------------------
|
||||
// vector of bool version of RevSparseHes
|
||||
// (see doxygen in rev_sparse_hes.hpp)
|
||||
template <class VectorSet>
|
||||
void RevSparseHesCase(
|
||||
bool set_type ,
|
||||
bool transpose ,
|
||||
size_t q ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& h
|
||||
);
|
||||
// vector of std::set<size_t> version of RevSparseHes
|
||||
// (see doxygen in rev_sparse_hes.hpp)
|
||||
template <class VectorSet>
|
||||
void RevSparseHesCase(
|
||||
const std::set<size_t>& set_type ,
|
||||
bool transpose ,
|
||||
size_t q ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& h
|
||||
);
|
||||
// ------------------------------------------------------------
|
||||
// Forward mode version of SparseJacobian
|
||||
// (see doxygen in sparse_jacobian.hpp)
|
||||
template <class VectorBase, class VectorSet, class VectorSize>
|
||||
size_t SparseJacobianFor(
|
||||
const VectorBase& x ,
|
||||
VectorSet& p_transpose ,
|
||||
const VectorSize& row ,
|
||||
const VectorSize& col ,
|
||||
VectorBase& jac ,
|
||||
sparse_jacobian_work& work
|
||||
);
|
||||
// Reverse mode version of SparseJacobian
|
||||
// (see doxygen in sparse_jacobian.hpp)
|
||||
template <class VectorBase, class VectorSet, class VectorSize>
|
||||
size_t SparseJacobianRev(
|
||||
const VectorBase& x ,
|
||||
VectorSet& p ,
|
||||
const VectorSize& row ,
|
||||
const VectorSize& col ,
|
||||
VectorBase& jac ,
|
||||
sparse_jacobian_work& work
|
||||
);
|
||||
// ------------------------------------------------------------
|
||||
// combined sparse_list and sparse_pack version of
|
||||
// SparseHessian (see doxygen in sparse_hessian.hpp)
|
||||
template <class VectorBase, class VectorSet, class VectorSize>
|
||||
size_t SparseHessianCompute(
|
||||
const VectorBase& x ,
|
||||
const VectorBase& w ,
|
||||
VectorSet& sparsity ,
|
||||
const VectorSize& row ,
|
||||
const VectorSize& col ,
|
||||
VectorBase& hes ,
|
||||
sparse_hessian_work& work
|
||||
);
|
||||
// ------------------------------------------------------------
|
||||
public:
|
||||
/// copy constructor
|
||||
ADFun(const ADFun& g)
|
||||
: num_var_tape_(0)
|
||||
{ CppAD::ErrorHandler::Call(
|
||||
true,
|
||||
__LINE__,
|
||||
__FILE__,
|
||||
"ADFun(const ADFun& g)",
|
||||
"Attempting to use the ADFun<Base> copy constructor.\n"
|
||||
"Perhaps you are passing an ADFun<Base> object "
|
||||
"by value instead of by reference."
|
||||
);
|
||||
}
|
||||
|
||||
/// default constructor
|
||||
ADFun(void);
|
||||
|
||||
// assignment operator
|
||||
// (see doxygen in fun_construct.hpp)
|
||||
void operator=(const ADFun& f);
|
||||
|
||||
/// sequence constructor
|
||||
template <typename ADvector>
|
||||
ADFun(const ADvector &x, const ADvector &y);
|
||||
|
||||
/// destructor
|
||||
~ADFun(void)
|
||||
{ }
|
||||
|
||||
/// set value of check_for_nan_
|
||||
void check_for_nan(bool value)
|
||||
{ check_for_nan_ = value; }
|
||||
bool check_for_nan(void) const
|
||||
{ return check_for_nan_; }
|
||||
|
||||
/// assign a new operation sequence
|
||||
template <typename ADvector>
|
||||
void Dependent(const ADvector &x, const ADvector &y);
|
||||
|
||||
/// forward mode user API, one order multiple directions.
|
||||
template <typename VectorBase>
|
||||
VectorBase Forward(size_t q, size_t r, const VectorBase& x);
|
||||
|
||||
/// forward mode user API, multiple directions one order.
|
||||
template <typename VectorBase>
|
||||
VectorBase Forward(size_t q,
|
||||
const VectorBase& x, std::ostream& s = std::cout
|
||||
);
|
||||
|
||||
/// reverse mode sweep
|
||||
template <typename VectorBase>
|
||||
VectorBase Reverse(size_t p, const VectorBase &v);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Jacobian sparsity
|
||||
template <typename VectorSet>
|
||||
VectorSet ForSparseJac(
|
||||
size_t q, const VectorSet &r, bool transpose = false,
|
||||
bool dependency = false
|
||||
);
|
||||
template <typename VectorSet>
|
||||
VectorSet RevSparseJac(
|
||||
size_t q, const VectorSet &s, bool transpose = false,
|
||||
bool dependency = false
|
||||
);
|
||||
// ---------------------------------------------------------------------
|
||||
template <typename SizeVector, typename BaseVector>
|
||||
size_t sparse_jac_for(
|
||||
size_t group_max ,
|
||||
const BaseVector& x ,
|
||||
sparse_rcv<SizeVector, BaseVector>& subset ,
|
||||
const sparse_rc<SizeVector>& pattern ,
|
||||
const std::string& coloring ,
|
||||
sparse_jac_work& work
|
||||
);
|
||||
template <typename SizeVector, typename BaseVector>
|
||||
size_t sparse_jac_rev(
|
||||
const BaseVector& x ,
|
||||
sparse_rcv<SizeVector, BaseVector>& subset ,
|
||||
const sparse_rc<SizeVector>& pattern ,
|
||||
const std::string& coloring ,
|
||||
sparse_jac_work& work
|
||||
);
|
||||
template <typename SizeVector, typename BaseVector>
|
||||
size_t sparse_hes(
|
||||
const BaseVector& x ,
|
||||
const BaseVector& w ,
|
||||
sparse_rcv<SizeVector, BaseVector>& subset ,
|
||||
const sparse_rc<SizeVector>& pattern ,
|
||||
const std::string& coloring ,
|
||||
sparse_hes_work& work
|
||||
);
|
||||
// ---------------------------------------------------------------------
|
||||
template <typename SizeVector>
|
||||
void for_jac_sparsity(
|
||||
const sparse_rc<SizeVector>& pattern_in ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
bool internal_bool ,
|
||||
sparse_rc<SizeVector>& pattern_out
|
||||
);
|
||||
template <typename SizeVector>
|
||||
void rev_jac_sparsity(
|
||||
const sparse_rc<SizeVector>& pattern_in ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
bool internal_bool ,
|
||||
sparse_rc<SizeVector>& pattern_out
|
||||
);
|
||||
template <typename BoolVector, typename SizeVector>
|
||||
void rev_hes_sparsity(
|
||||
const BoolVector& select_range ,
|
||||
bool transpose ,
|
||||
bool internal_bool ,
|
||||
sparse_rc<SizeVector>& pattern_out
|
||||
);
|
||||
template <typename BoolVector, typename SizeVector>
|
||||
void for_hes_sparsity(
|
||||
const BoolVector& select_domain ,
|
||||
const BoolVector& select_range ,
|
||||
bool internal_bool ,
|
||||
sparse_rc<SizeVector>& pattern_out
|
||||
);
|
||||
// ---------------------------------------------------------------------
|
||||
// forward mode Hessian sparsity
|
||||
// (see doxygen documentation in rev_sparse_hes.hpp)
|
||||
template <typename VectorSet>
|
||||
VectorSet ForSparseHes(
|
||||
const VectorSet &r, const VectorSet &s
|
||||
);
|
||||
// internal set sparsity version of ForSparseHes
|
||||
// (used by checkpoint functions only)
|
||||
void ForSparseHesCheckpoint(
|
||||
vector<bool>& r ,
|
||||
vector<bool>& s ,
|
||||
local::sparse_list& h
|
||||
);
|
||||
// reverse mode Hessian sparsity
|
||||
// (see doxygen documentation in rev_sparse_hes.hpp)
|
||||
template <typename VectorSet>
|
||||
VectorSet RevSparseHes(
|
||||
size_t q, const VectorSet &s, bool transpose = false
|
||||
);
|
||||
// internal set sparsity version of RevSparseHes
|
||||
// (used by checkpoint functions only)
|
||||
void RevSparseHesCheckpoint(
|
||||
size_t q ,
|
||||
vector<bool>& s ,
|
||||
bool transpose ,
|
||||
local::sparse_list& h
|
||||
);
|
||||
// internal set sparsity version of RevSparseJac
|
||||
// (used by checkpoint functions only)
|
||||
void RevSparseJacCheckpoint(
|
||||
size_t q ,
|
||||
const local::sparse_list& r ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
local::sparse_list& s
|
||||
);
|
||||
// internal set sparsity version of RevSparseJac
|
||||
// (used by checkpoint functions only)
|
||||
void ForSparseJacCheckpoint(
|
||||
size_t q ,
|
||||
const local::sparse_list& r ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
local::sparse_list& s
|
||||
);
|
||||
|
||||
/// amount of memory used for boolean Jacobain sparsity pattern
|
||||
size_t size_forward_bool(void) const
|
||||
{ return for_jac_sparse_pack_.memory(); }
|
||||
|
||||
/// free memory used for Jacobain sparsity pattern
|
||||
void size_forward_bool(size_t zero)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
zero == 0,
|
||||
"size_forward_bool: argument not equal to zero"
|
||||
);
|
||||
for_jac_sparse_pack_.resize(0, 0);
|
||||
}
|
||||
|
||||
/// amount of memory used for vector of set Jacobain sparsity pattern
|
||||
size_t size_forward_set(void) const
|
||||
{ return for_jac_sparse_set_.memory(); }
|
||||
|
||||
/// free memory used for Jacobain sparsity pattern
|
||||
void size_forward_set(size_t zero)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
zero == 0,
|
||||
"size_forward_bool: argument not equal to zero"
|
||||
);
|
||||
for_jac_sparse_set_.resize(0, 0);
|
||||
}
|
||||
|
||||
/// number of operators in the operation sequence
|
||||
size_t size_op(void) const
|
||||
{ return play_.num_op_rec(); }
|
||||
|
||||
/// number of operator arguments in the operation sequence
|
||||
size_t size_op_arg(void) const
|
||||
{ return play_.num_op_arg_rec(); }
|
||||
|
||||
/// amount of memory required for the operation sequence
|
||||
size_t size_op_seq(void) const
|
||||
{ return play_.Memory(); }
|
||||
|
||||
/// number of parameters in the operation sequence
|
||||
size_t size_par(void) const
|
||||
{ return play_.num_par_rec(); }
|
||||
|
||||
/// number taylor coefficient orders calculated
|
||||
size_t size_order(void) const
|
||||
{ return num_order_taylor_; }
|
||||
|
||||
/// number taylor coefficient directions calculated
|
||||
size_t size_direction(void) const
|
||||
{ return num_direction_taylor_; }
|
||||
|
||||
/// number of characters in the operation sequence
|
||||
size_t size_text(void) const
|
||||
{ return play_.num_text_rec(); }
|
||||
|
||||
/// number of variables in opertion sequence
|
||||
size_t size_var(void) const
|
||||
{ return num_var_tape_; }
|
||||
|
||||
/// number of VecAD indices in the operation sequence
|
||||
size_t size_VecAD(void) const
|
||||
{ return play_.num_vec_ind_rec(); }
|
||||
|
||||
/// set number of orders currently allocated (user API)
|
||||
void capacity_order(size_t c);
|
||||
|
||||
/// set number of orders and directions currently allocated
|
||||
void capacity_order(size_t c, size_t r);
|
||||
|
||||
/// number of variables in conditional expressions that can be skipped
|
||||
size_t number_skip(void);
|
||||
|
||||
/// number of independent variables
|
||||
size_t Domain(void) const
|
||||
{ return ind_taddr_.size(); }
|
||||
|
||||
/// number of dependent variables
|
||||
size_t Range(void) const
|
||||
{ return dep_taddr_.size(); }
|
||||
|
||||
/// is variable a parameter
|
||||
bool Parameter(size_t i)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
i < dep_taddr_.size(),
|
||||
"Argument to Parameter is >= dimension of range space"
|
||||
);
|
||||
return dep_parameter_[i];
|
||||
}
|
||||
|
||||
/// Deprecated: number of comparison operations that changed
|
||||
/// for the previous zero order forward (than when function was recorded)
|
||||
size_t CompareChange(void) const
|
||||
{ return compare_change_number_; }
|
||||
|
||||
/// count as which to store operator index
|
||||
void compare_change_count(size_t count)
|
||||
{ compare_change_count_ = count;
|
||||
compare_change_number_ = 0;
|
||||
compare_change_op_index_ = 0;
|
||||
}
|
||||
|
||||
/// number of comparison operations that changed
|
||||
size_t compare_change_number(void) const
|
||||
{ return compare_change_number_; }
|
||||
|
||||
/// operator index for the count-th comparison change
|
||||
size_t compare_change_op_index(void) const
|
||||
{ if( has_been_optimized_ )
|
||||
return 0;
|
||||
return compare_change_op_index_;
|
||||
}
|
||||
|
||||
/// calculate entire Jacobian
|
||||
template <typename VectorBase>
|
||||
VectorBase Jacobian(const VectorBase &x);
|
||||
|
||||
/// calculate Hessian for one component of f
|
||||
template <typename VectorBase>
|
||||
VectorBase Hessian(const VectorBase &x, const VectorBase &w);
|
||||
template <typename VectorBase>
|
||||
VectorBase Hessian(const VectorBase &x, size_t i);
|
||||
|
||||
/// forward mode calculation of partial w.r.t one domain component
|
||||
template <typename VectorBase>
|
||||
VectorBase ForOne(
|
||||
const VectorBase &x ,
|
||||
size_t j );
|
||||
|
||||
/// reverse mode calculation of derivative of one range component
|
||||
template <typename VectorBase>
|
||||
VectorBase RevOne(
|
||||
const VectorBase &x ,
|
||||
size_t i );
|
||||
|
||||
/// forward mode calculation of a subset of second order partials
|
||||
template <typename VectorBase, typename VectorSize_t>
|
||||
VectorBase ForTwo(
|
||||
const VectorBase &x ,
|
||||
const VectorSize_t &J ,
|
||||
const VectorSize_t &K );
|
||||
|
||||
/// reverse mode calculation of a subset of second order partials
|
||||
template <typename VectorBase, typename VectorSize_t>
|
||||
VectorBase RevTwo(
|
||||
const VectorBase &x ,
|
||||
const VectorSize_t &I ,
|
||||
const VectorSize_t &J );
|
||||
|
||||
/// calculate sparse Jacobians
|
||||
template <typename VectorBase>
|
||||
VectorBase SparseJacobian(
|
||||
const VectorBase &x
|
||||
);
|
||||
template <typename VectorBase, typename VectorSet>
|
||||
VectorBase SparseJacobian(
|
||||
const VectorBase &x ,
|
||||
const VectorSet &p
|
||||
);
|
||||
template <class VectorBase, class VectorSet, class VectorSize>
|
||||
size_t SparseJacobianForward(
|
||||
const VectorBase& x ,
|
||||
const VectorSet& p ,
|
||||
const VectorSize& r ,
|
||||
const VectorSize& c ,
|
||||
VectorBase& jac ,
|
||||
sparse_jacobian_work& work
|
||||
);
|
||||
template <class VectorBase, class VectorSet, class VectorSize>
|
||||
size_t SparseJacobianReverse(
|
||||
const VectorBase& x ,
|
||||
const VectorSet& p ,
|
||||
const VectorSize& r ,
|
||||
const VectorSize& c ,
|
||||
VectorBase& jac ,
|
||||
sparse_jacobian_work& work
|
||||
);
|
||||
|
||||
/// calculate sparse Hessians
|
||||
template <typename VectorBase>
|
||||
VectorBase SparseHessian(
|
||||
const VectorBase& x ,
|
||||
const VectorBase& w
|
||||
);
|
||||
template <typename VectorBase, typename VectorBool>
|
||||
VectorBase SparseHessian(
|
||||
const VectorBase& x ,
|
||||
const VectorBase& w ,
|
||||
const VectorBool& p
|
||||
);
|
||||
template <class VectorBase, class VectorSet, class VectorSize>
|
||||
size_t SparseHessian(
|
||||
const VectorBase& x ,
|
||||
const VectorBase& w ,
|
||||
const VectorSet& p ,
|
||||
const VectorSize& r ,
|
||||
const VectorSize& c ,
|
||||
VectorBase& hes ,
|
||||
sparse_hessian_work& work
|
||||
);
|
||||
|
||||
// Optimize the tape
|
||||
// (see doxygen documentation in optimize.hpp)
|
||||
void optimize( const std::string& options = "" );
|
||||
|
||||
// create abs-normal representation of the function f(x)
|
||||
void abs_normal_fun( ADFun& g, ADFun& a );
|
||||
// ------------------- Deprecated -----------------------------
|
||||
|
||||
/// deprecated: assign a new operation sequence
|
||||
template <typename ADvector>
|
||||
void Dependent(const ADvector &y);
|
||||
|
||||
/// Deprecated: number of variables in opertion sequence
|
||||
size_t Size(void) const
|
||||
{ return num_var_tape_; }
|
||||
|
||||
/// Deprecated: # taylor_ coefficients currently stored
|
||||
/// (per variable,direction)
|
||||
size_t Order(void) const
|
||||
{ return num_order_taylor_ - 1; }
|
||||
|
||||
/// Deprecated: amount of memory for this object
|
||||
/// Note that an approximation is used for the std::set<size_t> memory
|
||||
size_t Memory(void) const
|
||||
{ size_t pervar = cap_order_taylor_ * sizeof(Base)
|
||||
+ for_jac_sparse_pack_.memory()
|
||||
+ for_jac_sparse_set_.memory();
|
||||
size_t total = num_var_tape_ * pervar + play_.Memory();
|
||||
return total;
|
||||
}
|
||||
|
||||
/// Deprecated: # taylor_ coefficient orderss stored
|
||||
/// (per variable,direction)
|
||||
size_t taylor_size(void) const
|
||||
{ return num_order_taylor_; }
|
||||
|
||||
/// Deprecated: Does this AD operation sequence use
|
||||
/// VecAD<Base>::reference operands
|
||||
bool use_VecAD(void) const
|
||||
{ return play_.num_vec_ind_rec() > 0; }
|
||||
|
||||
/// Deprecated: # taylor_ coefficient orders calculated
|
||||
/// (per variable,direction)
|
||||
size_t size_taylor(void) const
|
||||
{ return num_order_taylor_; }
|
||||
|
||||
/// Deprecated: set number of orders currently allocated
|
||||
/// (per variable,direction)
|
||||
void capacity_taylor(size_t per_var);
|
||||
};
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
// non-user interfaces
|
||||
# include <cppad/local/forward0sweep.hpp>
|
||||
# include <cppad/local/forward1sweep.hpp>
|
||||
# include <cppad/local/forward2sweep.hpp>
|
||||
# include <cppad/local/reverse_sweep.hpp>
|
||||
# include <cppad/local/for_jac_sweep.hpp>
|
||||
# include <cppad/local/rev_jac_sweep.hpp>
|
||||
# include <cppad/local/rev_hes_sweep.hpp>
|
||||
# include <cppad/local/for_hes_sweep.hpp>
|
||||
|
||||
// user interfaces
|
||||
# include <cppad/core/parallel_ad.hpp>
|
||||
# include <cppad/core/independent.hpp>
|
||||
# include <cppad/core/dependent.hpp>
|
||||
# include <cppad/core/fun_construct.hpp>
|
||||
# include <cppad/core/abort_recording.hpp>
|
||||
# include <cppad/core/fun_eval.hpp>
|
||||
# include <cppad/core/drivers.hpp>
|
||||
# include <cppad/core/fun_check.hpp>
|
||||
# include <cppad/core/omp_max_thread.hpp>
|
||||
# include <cppad/core/optimize.hpp>
|
||||
# include <cppad/core/abs_normal_fun.hpp>
|
||||
|
||||
# endif
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
# ifndef CPPAD_CORE_AD_IO_HPP
|
||||
# define CPPAD_CORE_AD_IO_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 ad_input$$
|
||||
$spell
|
||||
VecAD
|
||||
std
|
||||
istream
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section AD Output Stream Operator$$
|
||||
$mindex >> input write$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%is% >> %x%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Sets $icode x$$ to a $cref/parameter/glossary/Parameter/$$
|
||||
with value $icode b$$ corresponding to
|
||||
$codei%
|
||||
%is% >> %b%
|
||||
%$$
|
||||
where $icode b$$ is a $icode Base$$ object.
|
||||
It is assumed that this $icode Base$$ input operation returns
|
||||
a reference to $icode is$$.
|
||||
|
||||
$head is$$
|
||||
The operand $icode is$$ has prototype
|
||||
$codei%
|
||||
std::istream& %is%
|
||||
%$$
|
||||
|
||||
$head x$$
|
||||
The operand $icode x$$ has one of the following prototypes
|
||||
$codei%
|
||||
AD<%Base%>& %x%
|
||||
%$$
|
||||
|
||||
$head Result$$
|
||||
The result of this operation can be used as a reference to $icode is$$.
|
||||
For example, if the operand $icode y$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %y%
|
||||
%$$
|
||||
then the syntax
|
||||
$codei%
|
||||
%is% >> %x% >> %y%
|
||||
%$$
|
||||
will first read the $icode Base$$ value of $icode x$$ from $icode is$$,
|
||||
and then read the $icode Base$$ value to $icode y$$.
|
||||
|
||||
$head Operation Sequence$$
|
||||
The result of this operation is not an
|
||||
$cref/AD of Base/glossary/AD of Base/$$ object.
|
||||
Thus it will not be recorded as part of an
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/ad_input.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref ad_input.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
$begin ad_output$$
|
||||
$spell
|
||||
VecAD
|
||||
std
|
||||
ostream
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section AD Output Stream Operator$$
|
||||
$mindex <<$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%os% << %x%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Writes the $icode Base$$ value, corresponding to $icode x$$,
|
||||
to the output stream $icode os$$.
|
||||
|
||||
$head Assumption$$
|
||||
If $icode b$$ is a $icode Base$$ object,
|
||||
$codei%
|
||||
%os% << %b%
|
||||
%$$
|
||||
returns a reference to $icode os$$.
|
||||
|
||||
$head os$$
|
||||
The operand $icode os$$ has prototype
|
||||
$codei%
|
||||
std::ostream& %os%
|
||||
%$$
|
||||
|
||||
$head x$$
|
||||
The operand $icode x$$ has one of the following prototypes
|
||||
$codei%
|
||||
const AD<%Base%>& %x%
|
||||
const VecAD<%Base%>::reference& %x%
|
||||
%$$
|
||||
|
||||
$head Result$$
|
||||
The result of this operation can be used as a reference to $icode os$$.
|
||||
For example, if the operand $icode y$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %y%
|
||||
%$$
|
||||
then the syntax
|
||||
$codei%
|
||||
%os% << %x% << %y%
|
||||
%$$
|
||||
will output the value corresponding to $icode x$$
|
||||
followed by the value corresponding to $icode y$$.
|
||||
|
||||
$head Operation Sequence$$
|
||||
The result of this operation is not an
|
||||
$cref/AD of Base/glossary/AD of Base/$$ object.
|
||||
Thus it will not be recorded as part of an
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/ad_output.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref ad_output.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file ad_io.hpp
|
||||
AD<Base> input and ouput stream operators.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Read an AD<Base> object from an input stream.
|
||||
|
||||
\tparam Base
|
||||
Base type for the AD object.
|
||||
|
||||
\param is [in,out]
|
||||
Is the input stream from which that value is read.
|
||||
|
||||
\param x [out]
|
||||
is the object that is being set to a value.
|
||||
Upone return, x.value_ is read from the input stream
|
||||
and x.tape_is_ is zero; i.e., x is a parameter.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
std::istream& operator >> (std::istream& is, AD<Base>& x)
|
||||
{ // like assignment to a base type value
|
||||
x.tape_id_ = 0;
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(x) );
|
||||
return (is >> x.value_);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Write an AD<Base> object to an output stream.
|
||||
|
||||
\tparam Base
|
||||
Base type for the AD object.
|
||||
|
||||
\param os [in,out]
|
||||
Is the output stream to which that value is written.
|
||||
|
||||
\param x
|
||||
is the object that is being written to the output stream.
|
||||
This is equivalent to writing x.value_ to the output stream.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
std::ostream& operator << (std::ostream &os, const AD<Base> &x)
|
||||
{ return (os << x.value_); }
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Write a VecAD_reference<Base> object to an output stream.
|
||||
|
||||
\tparam Base
|
||||
Base type for the VecAD_reference object.
|
||||
|
||||
\param os [in,out]
|
||||
Is the output stream to which that value is written.
|
||||
|
||||
\param x
|
||||
is the element of the VecAD object that is being written to the output stream.
|
||||
This is equivalent to writing the corresponing Base value to the stream.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
std::ostream& operator << (std::ostream &os, const VecAD_reference<Base> &x)
|
||||
{ return (os << x.ADBase()); }
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,71 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_AD_TO_STRING_HPP
|
||||
# define CPPAD_CORE_AD_TO_STRING_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 ad_to_string$$
|
||||
$spell
|
||||
const
|
||||
std
|
||||
$$
|
||||
|
||||
$section Convert An AD or Base Type to String$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%s% = to_string(%value%)%$$.
|
||||
|
||||
$head See Also$$
|
||||
$cref to_string$$, $cref base_to_string$$
|
||||
|
||||
$head value$$
|
||||
The argument $icode value$$ has prototype
|
||||
$codei%
|
||||
const AD<%Base%>& %value%
|
||||
const %Base%& %value%
|
||||
%$$
|
||||
where $icode Base$$ is a type that supports the
|
||||
$cref base_to_string$$ type requirement.
|
||||
|
||||
$head s$$
|
||||
The return value has prototype
|
||||
$codei%
|
||||
std::string %s%
|
||||
%$$
|
||||
and contains a representation of the specified $icode value$$.
|
||||
If $icode value$$ is an AD type,
|
||||
the result has the same precision as for the $icode Base$$ type.
|
||||
|
||||
$head Example$$
|
||||
The file $cref to_string.cpp$$
|
||||
includes an example and test of $code to_string$$ with AD types.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
*/
|
||||
# include <cppad/utility/to_string.hpp>
|
||||
# include <cppad/core/ad.hpp>
|
||||
|
||||
namespace CppAD {
|
||||
|
||||
// Template definition is in cppad/utility/to_string.hpp.
|
||||
// Partial specialzation for AD<Base> types
|
||||
template<class Base>
|
||||
struct to_string_struct< CppAD::AD<Base> >
|
||||
{ std::string operator()(const CppAD::AD<Base>& value)
|
||||
{ to_string_struct<Base> ts;
|
||||
return ts( Value( Var2Par( value ) ) ); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
# endif
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_AD_VALUED_HPP
|
||||
# define CPPAD_CORE_AD_VALUED_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 ADValued$$
|
||||
$spell
|
||||
$$
|
||||
|
||||
|
||||
$section AD Valued Operations and Functions$$
|
||||
|
||||
$comment atomic.omh includes atomic_base.omh which atomic_base.hpp$$
|
||||
$childtable%
|
||||
cppad/core/arithmetic.hpp%
|
||||
cppad/core/standard_math.hpp%
|
||||
cppad/core/cond_exp.hpp%
|
||||
cppad/core/discrete.hpp%
|
||||
cppad/core/numeric_limits.hpp%
|
||||
omh/atomic.omh
|
||||
%$$
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
// include MathOther.h after CondExp.h because some MathOther.h routines use
|
||||
// CondExp.h and CondExp.h is not sufficently declared in Declare.h
|
||||
|
||||
# include <cppad/core/arithmetic.hpp>
|
||||
# include <cppad/core/standard_math.hpp>
|
||||
# include <cppad/core/azmul.hpp>
|
||||
# include <cppad/core/cond_exp.hpp>
|
||||
# include <cppad/core/discrete.hpp>
|
||||
# include <cppad/core/atomic_base.hpp>
|
||||
# include <cppad/core/checkpoint.hpp>
|
||||
# include <cppad/core/old_atomic.hpp>
|
||||
|
||||
# endif
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_ADD_HPP
|
||||
# define CPPAD_CORE_ADD_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base> operator + (const AD<Base> &left , const AD<Base> &right)
|
||||
{
|
||||
// compute the Base part of this AD object
|
||||
AD<Base> result;
|
||||
result.value_ = left.value_ + right.value_;
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return result;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_left = left.tape_id_ == tape_id;
|
||||
bool var_right = right.tape_id_ == tape_id;
|
||||
|
||||
if( var_left )
|
||||
{ if( var_right )
|
||||
{ // result = variable + variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::AddvvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
else if( IdenticalZero(right.value_) )
|
||||
{ // result = variable + 0
|
||||
result.make_variable(left.tape_id_, left.taddr_);
|
||||
}
|
||||
else
|
||||
{ // result = variable + parameter
|
||||
// = parameter + variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(p, left.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::AddpvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
else if( var_right )
|
||||
{ if( IdenticalZero(left.value_) )
|
||||
{ // result = 0 + variable
|
||||
result.make_variable(right.tape_id_, right.taddr_);
|
||||
}
|
||||
else
|
||||
{ // result = parameter + variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(left.value_);
|
||||
tape->Rec_.PutArg(p, right.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::AddpvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(+)
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_ADD_EQ_HPP
|
||||
# define CPPAD_CORE_ADD_EQ_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base>& AD<Base>::operator += (const AD<Base> &right)
|
||||
{
|
||||
// compute the Base part
|
||||
Base left;
|
||||
left = value_;
|
||||
value_ += right.value_;
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return *this;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_left = tape_id_ == tape_id;
|
||||
bool var_right = right.tape_id_ == tape_id;
|
||||
|
||||
if( var_left )
|
||||
{ if( var_right )
|
||||
{ // this = variable + variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(taddr_, right.taddr_);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::AddvvOp);
|
||||
// make this a variable
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||
}
|
||||
else if( ! IdenticalZero( right.value_ ) )
|
||||
{ // this = variable + parameter
|
||||
// = parameter + variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(p, taddr_);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::AddpvOp);
|
||||
// make this a variable
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||
}
|
||||
}
|
||||
else if( var_right )
|
||||
{ if( IdenticalZero(left) )
|
||||
{ // this = 0 + right
|
||||
make_variable(right.tape_id_, right.taddr_);
|
||||
}
|
||||
else
|
||||
{ // this = parameter + variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AddpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AddpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(left);
|
||||
tape->Rec_.PutArg(p, right.taddr_);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::AddpvOp);
|
||||
// make this a variable
|
||||
tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CPPAD_FOLD_ASSIGNMENT_OPERATOR(+=)
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,42 @@
|
||||
# ifndef CPPAD_CORE_ARITHMETIC_HPP
|
||||
# define CPPAD_CORE_ARITHMETIC_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 Arithmetic$$
|
||||
$spell
|
||||
Op
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
|
||||
$section AD Arithmetic Operators and Compound Assignments$$
|
||||
|
||||
$childtable%
|
||||
cppad/core/unary_plus.hpp%
|
||||
cppad/core/unary_minus.hpp%
|
||||
cppad/core/ad_binary.hpp%
|
||||
cppad/core/compound_assign.hpp
|
||||
%$$
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/core/unary_plus.hpp>
|
||||
# include <cppad/core/unary_minus.hpp>
|
||||
# include <cppad/core/ad_binary.hpp>
|
||||
# include <cppad/core/compound_assign.hpp>
|
||||
|
||||
# endif
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
# ifndef CPPAD_CORE_ASINH_HPP
|
||||
# define CPPAD_CORE_ASINH_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 asinh$$
|
||||
$spell
|
||||
asinh
|
||||
const
|
||||
Vec
|
||||
std
|
||||
cmath
|
||||
CppAD
|
||||
$$
|
||||
$section The Inverse Hyperbolic Sine Function: asinh$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = asinh(%x%)%$$
|
||||
|
||||
$head Description$$
|
||||
The inverse hyperbolic sine function is defined by
|
||||
$icode%x% == sinh(%y%)%$$.
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head CPPAD_USE_CPLUSPLUS_2011$$
|
||||
|
||||
$subhead true$$
|
||||
If this preprocessor symbol is true ($code 1$$),
|
||||
and $icode x$$ is an AD type,
|
||||
this is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$subhead false$$
|
||||
If this preprocessor symbol is false ($code 0$$),
|
||||
CppAD uses the representation
|
||||
$latex \[
|
||||
\R{asinh} (x) = \log \left( x + \sqrt{ 1 + x^2 } \right)
|
||||
\] $$
|
||||
to compute this function.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/asinh.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref asinh.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/configure.hpp>
|
||||
# if ! CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Type>
|
||||
Type asinh_template(const Type &x)
|
||||
{ return CppAD::log( x + CppAD::sqrt( Type(1) + x * x ) );
|
||||
}
|
||||
|
||||
inline float asinh(const float &x)
|
||||
{ return asinh_template(x); }
|
||||
|
||||
inline double asinh(const double &x)
|
||||
{ return asinh_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> asinh(const AD<Base> &x)
|
||||
{ return asinh_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> asinh(const VecAD_reference<Base> &x)
|
||||
{ return asinh_template( x.ADBase() ); }
|
||||
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif // CPPAD_USE_CPLUSPLUS_2011
|
||||
# endif // CPPAD_ASINH_INCLUDED
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
# ifndef CPPAD_CORE_ATAN2_HPP
|
||||
# define CPPAD_CORE_ATAN2_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 atan2$$
|
||||
$spell
|
||||
Vec
|
||||
CppAD
|
||||
namespace
|
||||
std
|
||||
atan
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section AD Two Argument Inverse Tangent Function$$
|
||||
$mindex tan atan2$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%theta% = atan2(%y%, %x%)%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Determines an angle $latex \theta \in [ - \pi , + \pi ]$$
|
||||
such that
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
\sin ( \theta ) & = & y / \sqrt{ x^2 + y^2 } \\
|
||||
\cos ( \theta ) & = & x / \sqrt{ x^2 + y^2 }
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head y$$
|
||||
The argument $icode y$$ has one of the following prototypes
|
||||
$codei%
|
||||
const AD<%Base%> &%y%
|
||||
const VecAD<%Base%>::reference &%y%
|
||||
%$$
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has one of the following prototypes
|
||||
$codei%
|
||||
const AD<%Base%> &%x%
|
||||
const VecAD<%Base%>::reference &%x%
|
||||
%$$
|
||||
|
||||
$head theta$$
|
||||
The result $icode theta$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %theta%
|
||||
%$$
|
||||
|
||||
$head Operation Sequence$$
|
||||
The AD of $icode Base$$
|
||||
operation sequence used to calculate $icode theta$$ is
|
||||
$cref/independent/glossary/Operation/Independent/$$
|
||||
of $icode x$$ and $icode y$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/atan2.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref atan2.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN CppAD namespace
|
||||
|
||||
inline float atan2(float x, float y)
|
||||
{ return std::atan2(x, y); }
|
||||
|
||||
inline double atan2(double x, double y)
|
||||
{ return std::atan2(x, y); }
|
||||
|
||||
// The code below is used as an example by the CondExp documentation.
|
||||
// BEGIN CondExp
|
||||
template <class Base>
|
||||
AD<Base> atan2 (const AD<Base> &y, const AD<Base> &x)
|
||||
{ AD<Base> alpha;
|
||||
AD<Base> beta;
|
||||
AD<Base> theta;
|
||||
|
||||
AD<Base> zero(0.);
|
||||
AD<Base> pi2(2. * atan(1.));
|
||||
AD<Base> pi(2. * pi2);
|
||||
|
||||
AD<Base> ax = fabs(x);
|
||||
AD<Base> ay = fabs(y);
|
||||
|
||||
// if( ax > ay )
|
||||
// theta = atan(ay / ax);
|
||||
// else theta = pi2 - atan(ax / ay);
|
||||
alpha = atan(ay / ax);
|
||||
beta = pi2 - atan(ax / ay);
|
||||
theta = CondExpGt(ax, ay, alpha, beta); // use of CondExp
|
||||
|
||||
// if( x <= 0 )
|
||||
// theta = pi - theta;
|
||||
theta = CondExpLe(x, zero, pi - theta, theta); // use of CondExp
|
||||
|
||||
// if( y <= 0 )
|
||||
// theta = - theta;
|
||||
theta = CondExpLe(y, zero, -theta, theta); // use of CondExp
|
||||
|
||||
return theta;
|
||||
}
|
||||
// END CondExp
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> atan2 (const VecAD_reference<Base> &y, const AD<Base> &x)
|
||||
{ return atan2( y.ADBase() , x ); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> atan2 (const AD<Base> &y, const VecAD_reference<Base> &x)
|
||||
{ return atan2( y , x.ADBase() ); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> atan2
|
||||
(const VecAD_reference<Base> &y, const VecAD_reference<Base> &x)
|
||||
{ return atan2( y.ADBase() , x.ADBase() ); }
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
# ifndef CPPAD_CORE_ATANH_HPP
|
||||
# define CPPAD_CORE_ATANH_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 atanh$$
|
||||
$spell
|
||||
atanh
|
||||
const
|
||||
Vec
|
||||
std
|
||||
cmath
|
||||
CppAD
|
||||
tanh
|
||||
$$
|
||||
$section The Inverse Hyperbolic Tangent Function: atanh$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = atanh(%x%)%$$
|
||||
|
||||
$head Description$$
|
||||
The inverse hyperbolic tangent function is defined by
|
||||
$icode%x% == tanh(%y%)%$$.
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head CPPAD_USE_CPLUSPLUS_2011$$
|
||||
|
||||
$subhead true$$
|
||||
If this preprocessor symbol is true ($code 1$$),
|
||||
and $icode x$$ is an AD type,
|
||||
this is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$subhead false$$
|
||||
If this preprocessor symbol is false ($code 0$$),
|
||||
CppAD uses the representation
|
||||
$latex \[
|
||||
\R{atanh} (x) = \frac{1}{2} \log \left( \frac{1 + x}{1 - x} \right)
|
||||
\] $$
|
||||
to compute this function.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/atanh.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref atanh.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/configure.hpp>
|
||||
# if ! CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Type>
|
||||
Type atanh_template(const Type &x)
|
||||
{ return CppAD::log( (Type(1) + x) / (Type(1) - x) ) / Type(2);
|
||||
}
|
||||
|
||||
inline float atanh(const float &x)
|
||||
{ return atanh_template(x); }
|
||||
|
||||
inline double atanh(const double &x)
|
||||
{ return atanh_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> atanh(const AD<Base> &x)
|
||||
{ return atanh_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> atanh(const VecAD_reference<Base> &x)
|
||||
{ return atanh_template( x.ADBase() ); }
|
||||
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif // CPPAD_USE_CPLUSPLUS_2011
|
||||
# endif // CPPAD_ATANH_INCLUDED
|
||||
+2423
File diff suppressed because it is too large
Load Diff
+213
@@ -0,0 +1,213 @@
|
||||
# ifndef CPPAD_CORE_AZMUL_HPP
|
||||
# define CPPAD_CORE_AZMUL_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 azmul$$
|
||||
$spell
|
||||
azmul
|
||||
const
|
||||
namespace
|
||||
Vec
|
||||
$$
|
||||
|
||||
$section Absolute Zero Multiplication$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%z% = azmul(%x%, %y%)%$$
|
||||
|
||||
$head Purpose$$
|
||||
Evaluates multiplication with an absolute zero
|
||||
for any of the possible types listed below.
|
||||
The result is given by
|
||||
$latex \[
|
||||
z = \left\{ \begin{array}{ll}
|
||||
0 & {\rm if} \; x = 0 \\
|
||||
x \cdot y & {\rm otherwise}
|
||||
\end{array} \right.
|
||||
\] $$
|
||||
Note if $icode x$$ is zero and $icode y$$ is infinity,
|
||||
ieee multiplication would result in not a number whereas
|
||||
$icode z$$ would be zero.
|
||||
|
||||
$head Base$$
|
||||
If $icode Base$$ satisfies the
|
||||
$cref/base type requirements/base_require/$$
|
||||
and arguments $icode x$$, $icode y$$ have prototypes
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
const %Base%& %y%
|
||||
%$$
|
||||
then the result $icode z$$ has prototype
|
||||
$codei%
|
||||
%Base% %z%
|
||||
%$$
|
||||
|
||||
$head AD<Base>$$
|
||||
If the arguments $icode x$$, $icode y$$ have prototype
|
||||
$codei%
|
||||
const AD<%Base%>& %x%
|
||||
const AD<%Base%>& %y%
|
||||
%$$
|
||||
then the result $icode z$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %z%
|
||||
%$$
|
||||
|
||||
$head VecAD<Base>$$
|
||||
If the arguments $icode x$$, $icode y$$ have prototype
|
||||
$codei%
|
||||
const VecAD<%Base%>::reference& %x%
|
||||
const VecAD<%Base%>::reference& %y%
|
||||
%$$
|
||||
then the result $icode z$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %z%
|
||||
%$$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/azmul.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref azmul.cpp$$
|
||||
is an examples and tests of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
// ==========================================================================
|
||||
|
||||
// case where x and y are AD<Base> -------------------------------------------
|
||||
template <class Base> AD<Base>
|
||||
azmul(const AD<Base>& x, const AD<Base>& y)
|
||||
{
|
||||
// compute the Base part
|
||||
AD<Base> result;
|
||||
result.value_ = azmul(x.value_, y.value_);
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return result;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_x = x.tape_id_ == tape_id;
|
||||
bool var_y = y.tape_id_ == tape_id;
|
||||
|
||||
if( var_x )
|
||||
{ if( var_y )
|
||||
{ // result = azmul(variable, variable)
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::ZmulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::ZmulvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(x.taddr_, y.taddr_);
|
||||
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::ZmulvvOp);
|
||||
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
else if( IdenticalZero( y.value_ ) )
|
||||
{ // result = variable * 0
|
||||
}
|
||||
else if( IdenticalOne( y.value_ ) )
|
||||
{ // result = variable * 1
|
||||
result.make_variable(x.tape_id_, x.taddr_);
|
||||
}
|
||||
else
|
||||
{ // result = zmul(variable, parameter)
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::ZmulvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::ZmulvpOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(y.value_);
|
||||
tape->Rec_.PutArg(x.taddr_, p);
|
||||
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::ZmulvpOp);
|
||||
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
else if( var_y )
|
||||
{ if( IdenticalZero(x.value_) )
|
||||
{ // result = 0 * variable
|
||||
}
|
||||
else if( IdenticalOne( x.value_ ) )
|
||||
{ // result = 1 * variable
|
||||
result.make_variable(y.tape_id_, y.taddr_);
|
||||
}
|
||||
else
|
||||
{ // result = zmul(parameter, variable)
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::ZmulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::ZmulpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(x.value_);
|
||||
tape->Rec_.PutArg(p, y.taddr_);
|
||||
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::ZmulpvOp);
|
||||
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// =========================================================================
|
||||
// Fold operations into case above
|
||||
// -------------------------------------------------------------------------
|
||||
// Operations with VecAD_reference<Base> and AD<Base> only
|
||||
|
||||
template <class Base> AD<Base>
|
||||
azmul(const AD<Base>& x, const VecAD_reference<Base>& y)
|
||||
{ return azmul(x, y.ADBase()); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
azmul(const VecAD_reference<Base>& x, const VecAD_reference<Base>& y)
|
||||
{ return azmul(x.ADBase(), y.ADBase()); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
azmul(const VecAD_reference<Base>& x, const AD<Base>& y)
|
||||
{ return azmul(x.ADBase(), y); }
|
||||
// -------------------------------------------------------------------------
|
||||
// Operations with Base
|
||||
|
||||
template <class Base> AD<Base>
|
||||
azmul(const Base& x, const AD<Base>& y)
|
||||
{ return azmul(AD<Base>(x), y); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
azmul(const Base& x, const VecAD_reference<Base>& y)
|
||||
{ return azmul(AD<Base>(x), y.ADBase()); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
azmul(const AD<Base>& x, const Base& y)
|
||||
{ return azmul(x, AD<Base>(y)); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
azmul(const VecAD_reference<Base>& x, const Base& y)
|
||||
{ return azmul(x.ADBase(), AD<Base>(y)); }
|
||||
|
||||
// ==========================================================================
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
# endif
|
||||
+384
@@ -0,0 +1,384 @@
|
||||
# ifndef CPPAD_CORE_BASE_COMPLEX_HPP
|
||||
# define CPPAD_CORE_BASE_COMPLEX_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.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/configure.hpp>
|
||||
# include <limits>
|
||||
# include <complex>
|
||||
|
||||
// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
|
||||
# include <cppad/utility/thread_alloc.hpp>
|
||||
|
||||
/*
|
||||
$begin base_complex.hpp$$
|
||||
$spell
|
||||
azmul
|
||||
expm1
|
||||
atanh
|
||||
acosh
|
||||
asinh
|
||||
endif
|
||||
eps
|
||||
abs_geq
|
||||
Rel
|
||||
Lt Le Eq Ge Gt
|
||||
imag
|
||||
gcc
|
||||
isnan
|
||||
cppad.hpp
|
||||
sqrt
|
||||
exp
|
||||
cos
|
||||
std
|
||||
const
|
||||
CppAD
|
||||
Op
|
||||
inline
|
||||
enum
|
||||
undef
|
||||
acos
|
||||
asin
|
||||
atan
|
||||
erf
|
||||
Cond
|
||||
namespace
|
||||
bool
|
||||
$$
|
||||
|
||||
|
||||
$section Enable use of AD<Base> where Base is std::complex<double>$$
|
||||
|
||||
$children%example/general/complex_poly.cpp
|
||||
%$$
|
||||
$head Example$$
|
||||
The file $cref complex_poly.cpp$$ contains an example use of
|
||||
$code std::complex<double>$$ type for a CppAD $icode Base$$ type.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$head Include Order$$
|
||||
This file is included before $code <cppad/cppad.hpp>$$
|
||||
so it is necessary to define the error handler
|
||||
in addition to including
|
||||
$cref/base_require.hpp/base_require/Include Order/$$
|
||||
$srccode%cpp% */
|
||||
# include <limits>
|
||||
# include <complex>
|
||||
# include <cppad/base_require.hpp>
|
||||
# include <cppad/core/cppad_assert.hpp>
|
||||
|
||||
/* %$$
|
||||
|
||||
$head CondExpOp$$
|
||||
The type $code std::complex<double>$$ does not supports the
|
||||
$code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators; see
|
||||
$cref/not ordered/base_cond_exp/CondExpTemplate/Not Ordered/$$.
|
||||
Hence its $code CondExpOp$$ function is defined by
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline std::complex<double> CondExpOp(
|
||||
enum CppAD::CompareOp cop ,
|
||||
const std::complex<double> &left ,
|
||||
const std::complex<double> &right ,
|
||||
const std::complex<double> &trueCase ,
|
||||
const std::complex<double> &falseCase )
|
||||
{ CppAD::ErrorHandler::Call(
|
||||
true , __LINE__ , __FILE__ ,
|
||||
"std::complex<float> CondExpOp(...)",
|
||||
"Error: cannot use CondExp with a complex type"
|
||||
);
|
||||
return std::complex<double>(0);
|
||||
}
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head CondExpRel$$
|
||||
The $cref/CPPAD_COND_EXP_REL/base_cond_exp/CondExpRel/$$ macro invocation
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_COND_EXP_REL( std::complex<double> )
|
||||
}
|
||||
/* %$$
|
||||
used $code CondExpOp$$ above to
|
||||
define $codei%CondExp%Rel%$$ for $code std::complex<double>$$ arguments
|
||||
and $icode%Rel%$$ equal to
|
||||
$code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, and $code Gt$$.
|
||||
|
||||
$head EqualOpSeq$$
|
||||
Complex numbers do not carry operation sequence information.
|
||||
Thus they are equal in this sense if and only if there values are equal.
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool EqualOpSeq(
|
||||
const std::complex<double> &x ,
|
||||
const std::complex<double> &y )
|
||||
{ return x == y;
|
||||
}
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Identical$$
|
||||
Complex numbers do not carry operation sequence information.
|
||||
Thus they are all parameters so the identical functions just check values.
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool IdenticalPar(const std::complex<double> &x)
|
||||
{ return true; }
|
||||
inline bool IdenticalZero(const std::complex<double> &x)
|
||||
{ return (x == std::complex<double>(0., 0.) ); }
|
||||
inline bool IdenticalOne(const std::complex<double> &x)
|
||||
{ return (x == std::complex<double>(1., 0.) ); }
|
||||
inline bool IdenticalEqualPar(
|
||||
const std::complex<double> &x, const std::complex<double> &y)
|
||||
{ return (x == y); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Ordered$$
|
||||
Complex types do not support comparison operators,
|
||||
$srccode%cpp% */
|
||||
# undef CPPAD_USER_MACRO
|
||||
# define CPPAD_USER_MACRO(Fun) \
|
||||
inline bool Fun(const std::complex<double>& x) \
|
||||
{ CppAD::ErrorHandler::Call( \
|
||||
true , __LINE__ , __FILE__ , \
|
||||
#Fun"(x)", \
|
||||
"Error: cannot use " #Fun " with x complex<double> " \
|
||||
); \
|
||||
return false; \
|
||||
}
|
||||
namespace CppAD {
|
||||
CPPAD_USER_MACRO(LessThanZero)
|
||||
CPPAD_USER_MACRO(LessThanOrZero)
|
||||
CPPAD_USER_MACRO(GreaterThanOrZero)
|
||||
CPPAD_USER_MACRO(GreaterThanZero)
|
||||
inline bool abs_geq(
|
||||
const std::complex<double>& x ,
|
||||
const std::complex<double>& y )
|
||||
{ return std::abs(x) >= std::abs(y); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Integer$$
|
||||
The implementation of this function must agree
|
||||
with the CppAD user specifications for complex arguments to the
|
||||
$cref/Integer/Integer/x/Complex Types/$$ function:
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline int Integer(const std::complex<double> &x)
|
||||
{ return static_cast<int>( x.real() ); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head azmul$$
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_AZMUL( std::complex<double> )
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head isnan$$
|
||||
The gcc 4.1.1 complier defines the function
|
||||
$codei%
|
||||
int std::complex<double>::isnan( std::complex<double> %z% )
|
||||
%$$
|
||||
(which is not specified in the C++ 1998 standard ISO/IEC 14882).
|
||||
This causes an ambiguity between the function above and the CppAD
|
||||
$cref/isnan/nan/$$ template function.
|
||||
We avoid this ambiguity by defining a non-template version of
|
||||
this function in the CppAD namespace.
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool isnan(const std::complex<double>& z)
|
||||
{ return (z != z);
|
||||
}
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Valid Unary Math$$
|
||||
The following macro invocations define the standard unary
|
||||
math functions that are valid with complex arguments and are
|
||||
required to use $code AD< std::complex<double> >$$.
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<double>, cos)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<double>, cosh)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<double>, exp)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<double>, log)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sin)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sinh)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<double>, sqrt)
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Invalid Unary Math$$
|
||||
The following macro definition and invocations define the standard unary
|
||||
math functions that are invalid with complex arguments and are
|
||||
required to use $code AD< std::complex<double> >$$.
|
||||
$srccode%cpp% */
|
||||
# undef CPPAD_USER_MACRO
|
||||
# define CPPAD_USER_MACRO(Fun) \
|
||||
inline std::complex<double> Fun(const std::complex<double>& x) \
|
||||
{ CppAD::ErrorHandler::Call( \
|
||||
true , __LINE__ , __FILE__ , \
|
||||
#Fun"(x)", \
|
||||
"Error: cannot use " #Fun " with x complex<double> " \
|
||||
); \
|
||||
return std::complex<double>(0); \
|
||||
}
|
||||
namespace CppAD {
|
||||
CPPAD_USER_MACRO(abs)
|
||||
CPPAD_USER_MACRO(fabs)
|
||||
CPPAD_USER_MACRO(acos)
|
||||
CPPAD_USER_MACRO(asin)
|
||||
CPPAD_USER_MACRO(atan)
|
||||
CPPAD_USER_MACRO(sign)
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
CPPAD_USER_MACRO(erf)
|
||||
CPPAD_USER_MACRO(asinh)
|
||||
CPPAD_USER_MACRO(acosh)
|
||||
CPPAD_USER_MACRO(atanh)
|
||||
CPPAD_USER_MACRO(expm1)
|
||||
CPPAD_USER_MACRO(log1p)
|
||||
# endif
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head pow $$
|
||||
The following defines a $code CppAD::pow$$ function that
|
||||
is required to use $code AD< std::complex<double> >$$:
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline std::complex<double> pow(
|
||||
const std::complex<double> &x ,
|
||||
const std::complex<double> &y )
|
||||
{ return std::pow(x, y); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head numeric_limits$$
|
||||
The following defines the CppAD $cref numeric_limits$$
|
||||
for the type $code std::complex<double>$$:
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_NUMERIC_LIMITS(double, std::complex<double>)
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head to_string$$
|
||||
The following defines the function CppAD $cref to_string$$
|
||||
for the type $code std::complex<double>$$:
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_TO_STRING(std::complex<double>)
|
||||
}
|
||||
/* %$$
|
||||
$end
|
||||
*/
|
||||
# undef CPPAD_USER_MACRO_ONE
|
||||
# define CPPAD_USER_MACRO_ONE(Fun) \
|
||||
inline bool Fun(const std::complex<float>& x) \
|
||||
{ CppAD::ErrorHandler::Call( \
|
||||
true , __LINE__ , __FILE__ , \
|
||||
#Fun"(x)", \
|
||||
"Error: cannot use " #Fun " with x complex<float> " \
|
||||
); \
|
||||
return false; \
|
||||
}
|
||||
# undef CPPAD_USER_MACRO_TWO
|
||||
# define CPPAD_USER_MACRO_TWO(Fun) \
|
||||
inline std::complex<float> Fun(const std::complex<float>& x) \
|
||||
{ CppAD::ErrorHandler::Call( \
|
||||
true , __LINE__ , __FILE__ , \
|
||||
#Fun"(x)", \
|
||||
"Error: cannot use " #Fun " with x complex<float> " \
|
||||
); \
|
||||
return std::complex<float>(0); \
|
||||
}
|
||||
namespace CppAD {
|
||||
// CondExpOp ------------------------------------------------------
|
||||
inline std::complex<float> CondExpOp(
|
||||
enum CppAD::CompareOp cop ,
|
||||
const std::complex<float> &left ,
|
||||
const std::complex<float> &right ,
|
||||
const std::complex<float> &trueCase ,
|
||||
const std::complex<float> &falseCase )
|
||||
{ CppAD::ErrorHandler::Call(
|
||||
true , __LINE__ , __FILE__ ,
|
||||
"std::complex<float> CondExpOp(...)",
|
||||
"Error: cannot use CondExp with a complex type"
|
||||
);
|
||||
return std::complex<float>(0);
|
||||
}
|
||||
// CondExpRel --------------------------------------------------------
|
||||
CPPAD_COND_EXP_REL( std::complex<float> )
|
||||
// EqualOpSeq -----------------------------------------------------
|
||||
inline bool EqualOpSeq(
|
||||
const std::complex<float> &x ,
|
||||
const std::complex<float> &y )
|
||||
{ return x == y;
|
||||
}
|
||||
// Identical ------------------------------------------------------
|
||||
inline bool IdenticalPar(const std::complex<float> &x)
|
||||
{ return true; }
|
||||
inline bool IdenticalZero(const std::complex<float> &x)
|
||||
{ return (x == std::complex<float>(0., 0.) ); }
|
||||
inline bool IdenticalOne(const std::complex<float> &x)
|
||||
{ return (x == std::complex<float>(1., 0.) ); }
|
||||
inline bool IdenticalEqualPar(
|
||||
const std::complex<float> &x, const std::complex<float> &y)
|
||||
{ return (x == y); }
|
||||
// Ordered --------------------------------------------------------
|
||||
CPPAD_USER_MACRO_ONE(LessThanZero)
|
||||
CPPAD_USER_MACRO_ONE(LessThanOrZero)
|
||||
CPPAD_USER_MACRO_ONE(GreaterThanOrZero)
|
||||
CPPAD_USER_MACRO_ONE(GreaterThanZero)
|
||||
inline bool abs_geq(
|
||||
const std::complex<float>& x ,
|
||||
const std::complex<float>& y )
|
||||
{ return std::abs(x) >= std::abs(y); }
|
||||
// Integer ------------------------------------------------------
|
||||
inline int Integer(const std::complex<float> &x)
|
||||
{ return static_cast<int>( x.real() ); }
|
||||
// isnan -------------------------------------------------------------
|
||||
inline bool isnan(const std::complex<float>& z)
|
||||
{ return (z != z);
|
||||
}
|
||||
// Valid standard math functions --------------------------------
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<float>, cos)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<float>, cosh)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<float>, exp)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<float>, log)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sin)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sinh)
|
||||
CPPAD_STANDARD_MATH_UNARY(std::complex<float>, sqrt)
|
||||
// Invalid standrd math functions -------------------------------
|
||||
CPPAD_USER_MACRO_TWO(abs)
|
||||
CPPAD_USER_MACRO_TWO(acos)
|
||||
CPPAD_USER_MACRO_TWO(asin)
|
||||
CPPAD_USER_MACRO_TWO(atan)
|
||||
CPPAD_USER_MACRO_TWO(sign)
|
||||
// The pow function
|
||||
inline std::complex<float> pow(
|
||||
const std::complex<float> &x ,
|
||||
const std::complex<float> &y )
|
||||
{ return std::pow(x, y); }
|
||||
// numeric_limits -------------------------------------------------
|
||||
CPPAD_NUMERIC_LIMITS(float, std::complex<float>)
|
||||
// to_string -------------------------------------------------
|
||||
CPPAD_TO_STRING(std::complex<float>)
|
||||
}
|
||||
|
||||
// undefine macros only used by this file
|
||||
# undef CPPAD_USER_MACRO
|
||||
# undef CPPAD_USER_MACRO_ONE
|
||||
# undef CPPAD_USER_MACRO_TWO
|
||||
|
||||
# endif
|
||||
+281
@@ -0,0 +1,281 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_BASE_COND_EXP_HPP
|
||||
# define CPPAD_CORE_BASE_COND_EXP_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 base_cond_exp$$
|
||||
$spell
|
||||
alloc
|
||||
Rel
|
||||
hpp
|
||||
enum
|
||||
namespace
|
||||
Op
|
||||
Lt
|
||||
Le
|
||||
Eq
|
||||
Ge
|
||||
Gt
|
||||
Ne
|
||||
cond
|
||||
exp
|
||||
const
|
||||
adolc
|
||||
CppAD
|
||||
inline
|
||||
$$
|
||||
|
||||
$section Base Type Requirements for Conditional Expressions$$
|
||||
$mindex CondExp require CPPAD_COND_EXP_REL$$
|
||||
|
||||
$head Purpose$$
|
||||
These definitions are required by the user's code to support the
|
||||
$codei%AD<%Base%>%$$ type for $cref CondExp$$ operations:
|
||||
|
||||
$head CompareOp$$
|
||||
The following $code enum$$ type is used in the specifications below:
|
||||
$codep
|
||||
namespace CppAD {
|
||||
// The conditional expression operator enum type
|
||||
enum CompareOp
|
||||
{ CompareLt, // less than
|
||||
CompareLe, // less than or equal
|
||||
CompareEq, // equal
|
||||
CompareGe, // greater than or equal
|
||||
CompareGt, // greater than
|
||||
CompareNe // not equal
|
||||
};
|
||||
}
|
||||
$$
|
||||
|
||||
$head CondExpTemplate$$
|
||||
The type $icode Base$$ must support the syntax
|
||||
$codei%
|
||||
%result% = CppAD::CondExpOp(
|
||||
%cop%, %left%, %right%, %exp_if_true%, %exp_if_false%
|
||||
)
|
||||
%$$
|
||||
which computes implements the corresponding $cref CondExp$$
|
||||
function when the result has prototype
|
||||
$codei%
|
||||
%Base% %result%
|
||||
%$$
|
||||
The argument $icode cop$$ has prototype
|
||||
$codei%
|
||||
enum CppAD::CompareOp %cop%
|
||||
%$$
|
||||
The other arguments have the prototype
|
||||
$codei%
|
||||
const %Base%& %left%
|
||||
const %Base%& %right%
|
||||
const %Base%& %exp_if_true%
|
||||
const %Base%& %exp_if_false%
|
||||
%$$
|
||||
|
||||
$subhead Ordered Type$$
|
||||
If $icode Base$$ is a relatively simple type
|
||||
that supports
|
||||
$code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators
|
||||
its $code CondExpOp$$ function can be defined by
|
||||
$codei%
|
||||
namespace CppAD {
|
||||
inline %Base% CondExpOp(
|
||||
enum CppAD::CompareOp cop ,
|
||||
const %Base% &left ,
|
||||
const %Base% &right ,
|
||||
const %Base% &exp_if_true ,
|
||||
const %Base% &exp_if_false )
|
||||
{ return CondExpTemplate(
|
||||
cop, left, right, trueCase, falseCase);
|
||||
}
|
||||
}
|
||||
%$$
|
||||
For example, see
|
||||
$cref/double CondExpOp/base_alloc.hpp/CondExpOp/$$.
|
||||
For an example of and implementation of $code CondExpOp$$ with
|
||||
a more involved $icode Base$$ type see
|
||||
$cref/adolc CondExpOp/base_adolc.hpp/CondExpOp/$$.
|
||||
|
||||
|
||||
$subhead Not Ordered$$
|
||||
If the type $icode Base$$ does not support ordering,
|
||||
the $code CondExpOp$$ function does not make sense.
|
||||
In this case one might (but need not) define $code CondExpOp$$ as follows:
|
||||
$codei%
|
||||
namespace CppAD {
|
||||
inline %Base% CondExpOp(
|
||||
enum CompareOp cop ,
|
||||
const %Base% &left ,
|
||||
const %Base% &right ,
|
||||
const %Base% &exp_if_true ,
|
||||
const %Base% &exp_if_false )
|
||||
{ // attempt to use CondExp with a %Base% argument
|
||||
assert(0);
|
||||
return %Base%(0);
|
||||
}
|
||||
}
|
||||
%$$
|
||||
For example, see
|
||||
$cref/complex CondExpOp/base_complex.hpp/CondExpOp/$$.
|
||||
|
||||
$head CondExpRel$$
|
||||
The macro invocation
|
||||
$codei%
|
||||
CPPAD_COND_EXP_REL(%Base%)
|
||||
%$$
|
||||
uses $code CondExpOp$$ above to define the following functions
|
||||
$codei%
|
||||
CondExpLt(%left%, %right%, %exp_if_true%, %exp_if_false%)
|
||||
CondExpLe(%left%, %right%, %exp_if_true%, %exp_if_false%)
|
||||
CondExpEq(%left%, %right%, %exp_if_true%, %exp_if_false%)
|
||||
CondExpGe(%left%, %right%, %exp_if_true%, %exp_if_false%)
|
||||
CondExpGt(%left%, %right%, %exp_if_true%, %exp_if_false%)
|
||||
%$$
|
||||
where the arguments have type $icode Base$$.
|
||||
This should be done inside of the CppAD namespace.
|
||||
For example, see
|
||||
$cref/base_alloc/base_alloc.hpp/CondExpRel/$$.
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
\file base_cond_exp.hpp
|
||||
CondExp operations that aid in meeting Base type requirements.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_COND_EXP_BASE_REL(Type, Rel, Op)
|
||||
This macro defines the operation
|
||||
\verbatim
|
||||
CondExpRel(left, right, exp_if_true, exp_if_false)
|
||||
\endverbatim
|
||||
The argument \c Type is the \c Base type for this base require operation.
|
||||
The argument \c Rel is one of \c Lt, \c Le, \c Eq, \c Ge, \c Gt.
|
||||
The argument \c Op is the corresponding \c CompareOp value.
|
||||
*/
|
||||
# define CPPAD_COND_EXP_BASE_REL(Type, Rel, Op) \
|
||||
inline Type CondExp##Rel( \
|
||||
const Type& left , \
|
||||
const Type& right , \
|
||||
const Type& exp_if_true , \
|
||||
const Type& exp_if_false ) \
|
||||
{ return CondExpOp(Op, left, right, exp_if_true, exp_if_false); \
|
||||
}
|
||||
|
||||
/*!
|
||||
\def CPPAD_COND_EXP_REL(Type)
|
||||
The macro defines the operations
|
||||
\verbatim
|
||||
CondExpLt(left, right, exp_if_true, exp_if_false)
|
||||
CondExpLe(left, right, exp_if_true, exp_if_false)
|
||||
CondExpEq(left, right, exp_if_true, exp_if_false)
|
||||
CondExpGe(left, right, exp_if_true, exp_if_false)
|
||||
CondExpGt(left, right, exp_if_true, exp_if_false)
|
||||
\endverbatim
|
||||
The argument \c Type is the \c Base type for this base require operation.
|
||||
*/
|
||||
# define CPPAD_COND_EXP_REL(Type) \
|
||||
CPPAD_COND_EXP_BASE_REL(Type, Lt, CompareLt) \
|
||||
CPPAD_COND_EXP_BASE_REL(Type, Le, CompareLe) \
|
||||
CPPAD_COND_EXP_BASE_REL(Type, Eq, CompareEq) \
|
||||
CPPAD_COND_EXP_BASE_REL(Type, Ge, CompareGe) \
|
||||
CPPAD_COND_EXP_BASE_REL(Type, Gt, CompareGt)
|
||||
|
||||
/*!
|
||||
Template function to implement Conditional Expressions for simple types
|
||||
that have comparision operators.
|
||||
|
||||
\tparam CompareType
|
||||
is the type of the left and right operands to the comparision operator.
|
||||
|
||||
\tparam ResultType
|
||||
is the type of the result, which is the same as \c CompareType except
|
||||
during forward and reverse mode sparese calculations.
|
||||
|
||||
\param cop
|
||||
specifices which comparision to use; i.e.,
|
||||
$code <$$,
|
||||
$code <=$$,
|
||||
$code ==$$,
|
||||
$code >=$$,
|
||||
$code >$$, or
|
||||
$code !=$$.
|
||||
|
||||
\param left
|
||||
is the left operand to the comparision operator.
|
||||
|
||||
\param right
|
||||
is the right operand to the comparision operator.
|
||||
|
||||
\param exp_if_true
|
||||
is the return value is the comparision results in true.
|
||||
|
||||
\param exp_if_false
|
||||
is the return value is the comparision results in false.
|
||||
|
||||
\return
|
||||
see \c exp_if_true and \c exp_if_false above.
|
||||
*/
|
||||
template <class CompareType, class ResultType>
|
||||
ResultType CondExpTemplate(
|
||||
enum CompareOp cop ,
|
||||
const CompareType& left ,
|
||||
const CompareType& right ,
|
||||
const ResultType& exp_if_true ,
|
||||
const ResultType& exp_if_false )
|
||||
{ ResultType returnValue;
|
||||
switch( cop )
|
||||
{
|
||||
case CompareLt:
|
||||
if( left < right )
|
||||
returnValue = exp_if_true;
|
||||
else returnValue = exp_if_false;
|
||||
break;
|
||||
|
||||
case CompareLe:
|
||||
if( left <= right )
|
||||
returnValue = exp_if_true;
|
||||
else returnValue = exp_if_false;
|
||||
break;
|
||||
|
||||
case CompareEq:
|
||||
if( left == right )
|
||||
returnValue = exp_if_true;
|
||||
else returnValue = exp_if_false;
|
||||
break;
|
||||
|
||||
case CompareGe:
|
||||
if( left >= right )
|
||||
returnValue = exp_if_true;
|
||||
else returnValue = exp_if_false;
|
||||
break;
|
||||
|
||||
case CompareGt:
|
||||
if( left > right )
|
||||
returnValue = exp_if_true;
|
||||
else returnValue = exp_if_false;
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(0);
|
||||
returnValue = exp_if_true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_BASE_DOUBLE_HPP
|
||||
# define CPPAD_CORE_BASE_DOUBLE_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/configure.hpp>
|
||||
# include <limits>
|
||||
|
||||
/*
|
||||
$begin base_double.hpp$$
|
||||
$spell
|
||||
namespaces
|
||||
cppad
|
||||
hpp
|
||||
azmul
|
||||
expm1
|
||||
atanh
|
||||
acosh
|
||||
asinh
|
||||
erf
|
||||
endif
|
||||
abs_geq
|
||||
acos
|
||||
asin
|
||||
atan
|
||||
cos
|
||||
sqrt
|
||||
tanh
|
||||
std
|
||||
fabs
|
||||
bool
|
||||
Lt Le Eq Ge Gt
|
||||
Rel
|
||||
CppAD
|
||||
CondExpOp
|
||||
namespace
|
||||
inline
|
||||
enum
|
||||
const
|
||||
exp
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section Enable use of AD<Base> where Base is double$$
|
||||
|
||||
$head CondExpOp$$
|
||||
The type $code double$$ is a relatively simple type that supports
|
||||
$code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators; see
|
||||
$cref/ordered type/base_cond_exp/CondExpTemplate/Ordered Type/$$.
|
||||
Hence its $code CondExpOp$$ function is defined by
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline double CondExpOp(
|
||||
enum CompareOp cop ,
|
||||
const double& left ,
|
||||
const double& right ,
|
||||
const double& exp_if_true ,
|
||||
const double& exp_if_false )
|
||||
{ return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false);
|
||||
}
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head CondExpRel$$
|
||||
The $cref/CPPAD_COND_EXP_REL/base_cond_exp/CondExpRel/$$ macro invocation
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_COND_EXP_REL(double)
|
||||
}
|
||||
/* %$$
|
||||
uses $code CondExpOp$$ above to
|
||||
define $codei%CondExp%Rel%$$ for $code double$$ arguments
|
||||
and $icode%Rel%$$ equal to
|
||||
$code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, and $code Gt$$.
|
||||
|
||||
$head EqualOpSeq$$
|
||||
The type $code double$$ is simple (in this respect) and so we define
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool EqualOpSeq(const double& x, const double& y)
|
||||
{ return x == y; }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Identical$$
|
||||
The type $code double$$ is simple (in this respect) and so we define
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool IdenticalPar(const double& x)
|
||||
{ return true; }
|
||||
inline bool IdenticalZero(const double& x)
|
||||
{ return (x == 0.); }
|
||||
inline bool IdenticalOne(const double& x)
|
||||
{ return (x == 1.); }
|
||||
inline bool IdenticalEqualPar(const double& x, const double& y)
|
||||
{ return (x == y); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Integer$$
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline int Integer(const double& x)
|
||||
{ return static_cast<int>(x); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head azmul$$
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_AZMUL( double )
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Ordered$$
|
||||
The $code double$$ type supports ordered comparisons
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool GreaterThanZero(const double& x)
|
||||
{ return x > 0.; }
|
||||
inline bool GreaterThanOrZero(const double& x)
|
||||
{ return x >= 0.; }
|
||||
inline bool LessThanZero(const double& x)
|
||||
{ return x < 0.; }
|
||||
inline bool LessThanOrZero(const double& x)
|
||||
{ return x <= 0.; }
|
||||
inline bool abs_geq(const double& x, const double& y)
|
||||
{ return std::fabs(x) >= std::fabs(y); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Unary Standard Math$$
|
||||
The following macro invocations import the $code double$$ versions of
|
||||
the unary standard math functions into the $code CppAD$$ namespace.
|
||||
Importing avoids ambiguity errors when using both the
|
||||
$code CppAD$$ and $code std$$ namespaces.
|
||||
Note this also defines the $cref/float/base_float.hpp/Unary Standard Math/$$
|
||||
versions of these functions.
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
using std::acos;
|
||||
using std::asin;
|
||||
using std::atan;
|
||||
using std::cos;
|
||||
using std::cosh;
|
||||
using std::exp;
|
||||
using std::fabs;
|
||||
using std::log;
|
||||
using std::log10;
|
||||
using std::sin;
|
||||
using std::sinh;
|
||||
using std::sqrt;
|
||||
using std::tan;
|
||||
using std::tanh;
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
using std::erf;
|
||||
using std::asinh;
|
||||
using std::acosh;
|
||||
using std::atanh;
|
||||
using std::expm1;
|
||||
using std::log1p;
|
||||
# endif
|
||||
}
|
||||
/* %$$
|
||||
The absolute value function is special because its $code std$$ name is
|
||||
$code fabs$$
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline double abs(const double& x)
|
||||
{ return std::fabs(x); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head sign$$
|
||||
The following defines the $code CppAD::sign$$ function that
|
||||
is required to use $code AD<double>$$:
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline double sign(const double& x)
|
||||
{ if( x > 0. )
|
||||
return 1.;
|
||||
if( x == 0. )
|
||||
return 0.;
|
||||
return -1.;
|
||||
}
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head pow$$
|
||||
The following defines a $code CppAD::pow$$ function that
|
||||
is required to use $code AD<double>$$.
|
||||
As with the unary standard math functions,
|
||||
this has the exact same signature as $code std::pow$$,
|
||||
so use it instead of defining another function.
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
using std::pow;
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head numeric_limits$$
|
||||
The following defines the CppAD $cref numeric_limits$$
|
||||
for the type $code double$$:
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_NUMERIC_LIMITS(double, double)
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head to_string$$
|
||||
There is no need to define $code to_string$$ for $code double$$
|
||||
because it is defined by including $code cppad/utility/to_string.hpp$$;
|
||||
see $cref to_string$$.
|
||||
See $cref/base_complex.hpp/base_complex.hpp/to_string/$$ for an example where
|
||||
it is necessary to define $code to_string$$ for a $icode Base$$ type.
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
# endif
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_BASE_FLOAT_HPP
|
||||
# define CPPAD_CORE_BASE_FLOAT_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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.
|
||||
-------------------------------------------------------------------------- */
|
||||
# include <cppad/configure.hpp>
|
||||
# include <limits>
|
||||
|
||||
/*
|
||||
$begin base_float.hpp$$
|
||||
$spell
|
||||
namespaces
|
||||
cppad
|
||||
hpp
|
||||
azmul
|
||||
expm1
|
||||
atanh
|
||||
acosh
|
||||
asinh
|
||||
erf
|
||||
endif
|
||||
abs_geq
|
||||
acos
|
||||
asin
|
||||
atan
|
||||
cos
|
||||
sqrt
|
||||
tanh
|
||||
std
|
||||
fabs
|
||||
bool
|
||||
Lt Le Eq Ge Gt
|
||||
Rel
|
||||
CppAD
|
||||
CondExpOp
|
||||
namespace
|
||||
inline
|
||||
enum
|
||||
const
|
||||
exp
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section Enable use of AD<Base> where Base is float$$
|
||||
|
||||
$head CondExpOp$$
|
||||
The type $code float$$ is a relatively simple type that supports
|
||||
$code <$$, $code <=$$, $code ==$$, $code >=$$, and $code >$$ operators; see
|
||||
$cref/ordered type/base_cond_exp/CondExpTemplate/Ordered Type/$$.
|
||||
Hence its $code CondExpOp$$ function is defined by
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline float CondExpOp(
|
||||
enum CompareOp cop ,
|
||||
const float& left ,
|
||||
const float& right ,
|
||||
const float& exp_if_true ,
|
||||
const float& exp_if_false )
|
||||
{ return CondExpTemplate(cop, left, right, exp_if_true, exp_if_false);
|
||||
}
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head CondExpRel$$
|
||||
The $cref/CPPAD_COND_EXP_REL/base_cond_exp/CondExpRel/$$ macro invocation
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_COND_EXP_REL(float)
|
||||
}
|
||||
/* %$$
|
||||
uses $code CondExpOp$$ above to
|
||||
define $codei%CondExp%Rel%$$ for $code float$$ arguments
|
||||
and $icode%Rel%$$ equal to
|
||||
$code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, and $code Gt$$.
|
||||
|
||||
$head EqualOpSeq$$
|
||||
The type $code float$$ is simple (in this respect) and so we define
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool EqualOpSeq(const float& x, const float& y)
|
||||
{ return x == y; }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Identical$$
|
||||
The type $code float$$ is simple (in this respect) and so we define
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool IdenticalPar(const float& x)
|
||||
{ return true; }
|
||||
inline bool IdenticalZero(const float& x)
|
||||
{ return (x == 0.f); }
|
||||
inline bool IdenticalOne(const float& x)
|
||||
{ return (x == 1.f); }
|
||||
inline bool IdenticalEqualPar(const float& x, const float& y)
|
||||
{ return (x == y); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Integer$$
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline int Integer(const float& x)
|
||||
{ return static_cast<int>(x); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head azmul$$
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_AZMUL( float )
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Ordered$$
|
||||
The $code float$$ type supports ordered comparisons
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline bool GreaterThanZero(const float& x)
|
||||
{ return x > 0.f; }
|
||||
inline bool GreaterThanOrZero(const float& x)
|
||||
{ return x >= 0.f; }
|
||||
inline bool LessThanZero(const float& x)
|
||||
{ return x < 0.f; }
|
||||
inline bool LessThanOrZero(const float& x)
|
||||
{ return x <= 0.f; }
|
||||
inline bool abs_geq(const float& x, const float& y)
|
||||
{ return std::fabs(x) >= std::fabs(y); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head Unary Standard Math$$
|
||||
The following macro invocations import the $code float$$ versions of
|
||||
the unary standard math functions into the $code CppAD$$ namespace.
|
||||
Importing avoids ambiguity errors when using both the
|
||||
$code CppAD$$ and $code std$$ namespaces.
|
||||
Note this also defines the $cref/double/base_double.hpp/Unary Standard Math/$$
|
||||
versions of these functions.
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
using std::acos;
|
||||
using std::asin;
|
||||
using std::atan;
|
||||
using std::cos;
|
||||
using std::cosh;
|
||||
using std::exp;
|
||||
using std::fabs;
|
||||
using std::log;
|
||||
using std::log10;
|
||||
using std::sin;
|
||||
using std::sinh;
|
||||
using std::sqrt;
|
||||
using std::tan;
|
||||
using std::tanh;
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
using std::erf;
|
||||
using std::asinh;
|
||||
using std::acosh;
|
||||
using std::atanh;
|
||||
using std::expm1;
|
||||
using std::log1p;
|
||||
# endif
|
||||
}
|
||||
|
||||
/* %$$
|
||||
The absolute value function is special because its $code std$$ name is
|
||||
$code fabs$$
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline float abs(const float& x)
|
||||
{ return std::fabs(x); }
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head sign$$
|
||||
The following defines the $code CppAD::sign$$ function that
|
||||
is required to use $code AD<float>$$:
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
inline float sign(const float& x)
|
||||
{ if( x > 0.f )
|
||||
return 1.f;
|
||||
if( x == 0.f )
|
||||
return 0.f;
|
||||
return -1.f;
|
||||
}
|
||||
}
|
||||
/* %$$
|
||||
$head pow$$
|
||||
The following defines a $code CppAD::pow$$ function that
|
||||
is required to use $code AD<float>$$.
|
||||
As with the unary standard math functions,
|
||||
this has the exact same signature as $code std::pow$$,
|
||||
so use it instead of defining another function.
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
using std::pow;
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head numeric_limits$$
|
||||
The following defines the CppAD $cref numeric_limits$$
|
||||
for the type $code float$$:
|
||||
$srccode%cpp% */
|
||||
namespace CppAD {
|
||||
CPPAD_NUMERIC_LIMITS(float, float)
|
||||
}
|
||||
/* %$$
|
||||
|
||||
$head to_string$$
|
||||
There is no need to define $code to_string$$ for $code float$$
|
||||
because it is defined by including $code cppad/utility/to_string.hpp$$;
|
||||
see $cref to_string$$.
|
||||
See $cref/base_complex.hpp/base_complex.hpp/to_string/$$ for an example where
|
||||
it is necessary to define $code to_string$$ for a $icode Base$$ type.
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
|
||||
# endif
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_BASE_HASH_HPP
|
||||
# define CPPAD_CORE_BASE_HASH_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 base_hash$$
|
||||
$spell
|
||||
alloc
|
||||
Cpp
|
||||
adouble
|
||||
valgrind
|
||||
const
|
||||
inline
|
||||
$$
|
||||
|
||||
$section Base Type Requirements for Hash Coding Values$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%code% = hash_code(%x%)%$$
|
||||
|
||||
$head Purpose$$
|
||||
CppAD uses a table of $icode Base$$ type values when recording
|
||||
$codei%AD<%Base%>%$$ operations.
|
||||
A hashing function is used to reduce number of values stored in this table;
|
||||
for example, it is not necessary to store the value 3.0 every
|
||||
time it is used as a $cref/parameter/parvar/$$.
|
||||
|
||||
$head Default$$
|
||||
The default hashing function works with the set of bits that correspond
|
||||
to a $icode Base$$ value.
|
||||
In most cases this works well, but in some cases
|
||||
it does not. For example, in the
|
||||
$cref base_adolc.hpp$$ case, an $code adouble$$ value can have
|
||||
fields that are not initialized and $code valgrind$$ reported an error
|
||||
when these are used to form the hash code.
|
||||
|
||||
$head x$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
const %Base%& %x
|
||||
%$$
|
||||
It is the value we are forming a hash code for.
|
||||
|
||||
$head code$$
|
||||
The return value $icode code$$ has prototype
|
||||
$codei%
|
||||
unsigned short %code%
|
||||
%$$
|
||||
It is the hash code corresponding to $icode x$$. This intention is the
|
||||
commonly used values will have different hash codes.
|
||||
The hash code must satisfy
|
||||
$codei%
|
||||
%code% < CPPAD_HASH_TABLE_SIZE
|
||||
%$$
|
||||
so that it is a valid index into the hash code table.
|
||||
|
||||
$head inline$$
|
||||
If you define this function, it should declare it to be $code inline$$,
|
||||
so that you do not get multiple definitions from different compilation units.
|
||||
|
||||
$head Example$$
|
||||
See the $code base_alloc$$ $cref/hash_code/base_alloc.hpp/hash_code/$$
|
||||
and the $code adouble$$ $cref/hash_code/base_adolc.hpp/hash_code/$$.
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_HASH_TABLE_SIZE
|
||||
the codes retruned by hash_code are between zero and CPPAD_HASH_TABLE_SIZE
|
||||
minus one.
|
||||
*/
|
||||
# define CPPAD_HASH_TABLE_SIZE 10000
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,67 @@
|
||||
# ifndef CPPAD_CORE_BASE_LIMITS_HPP
|
||||
# define CPPAD_CORE_BASE_LIMITS_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 base_limits$$
|
||||
$spell
|
||||
std
|
||||
namespace
|
||||
CppAD
|
||||
$$
|
||||
|
||||
$section Base Type Requirements for Numeric Limits$$
|
||||
|
||||
$head CppAD::numeric_limits$$
|
||||
A specialization for
|
||||
$cref/CppAD::numeric_limits/numeric_limits/$$
|
||||
must be defined in order to use the type $codei%AD<%Base%>%$$.
|
||||
CppAD does not use a specialization of
|
||||
$codei%std::numeric_limits<%Base%>%$$.
|
||||
Since C++11, using a specialization of
|
||||
$codei%std::numeric_limits<%Base%>%$$
|
||||
would require that $icode Base$$ be a literal type.
|
||||
|
||||
$head CPPAD_NUMERIC_LIMITS$$
|
||||
In most cases, this macro can be used to define the specialization where
|
||||
the numeric limits for the type $icode Base$$
|
||||
are the same as the standard numeric limits for the type $icode Other$$.
|
||||
For most $icode Base$$ types,
|
||||
there is a choice of $icode Other$$,
|
||||
for which the following preprocessor macro invocation suffices:
|
||||
$codei%
|
||||
namespace CppAD {
|
||||
CPPAD_NUMERIC_LIMITS(%Other%, %Base%)
|
||||
}
|
||||
%$$
|
||||
where the macro is defined by
|
||||
$srccode%cpp% */
|
||||
# define CPPAD_NUMERIC_LIMITS(Other, Base) \
|
||||
template <> class numeric_limits<Base>\
|
||||
{\
|
||||
public:\
|
||||
static Base min(void) \
|
||||
{ return static_cast<Base>( std::numeric_limits<Other>::min() ); }\
|
||||
static Base max(void) \
|
||||
{ return static_cast<Base>( std::numeric_limits<Other>::max() ); }\
|
||||
static Base epsilon(void) \
|
||||
{ return static_cast<Base>( std::numeric_limits<Other>::epsilon() ); }\
|
||||
static Base quiet_NaN(void) \
|
||||
{ return static_cast<Base>( std::numeric_limits<Other>::quiet_NaN() ); }\
|
||||
static const int digits10 = std::numeric_limits<Other>::digits10;\
|
||||
};
|
||||
/* %$$
|
||||
$end
|
||||
*/
|
||||
|
||||
# endif
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_BASE_STD_MATH_HPP
|
||||
# define CPPAD_CORE_BASE_STD_MATH_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 base_std_math$$
|
||||
$spell
|
||||
expm1
|
||||
atanh
|
||||
acosh
|
||||
asinh
|
||||
inline
|
||||
fabs
|
||||
isnan
|
||||
alloc
|
||||
std
|
||||
acos
|
||||
asin
|
||||
atan
|
||||
cos
|
||||
exp
|
||||
sqrt
|
||||
const
|
||||
CppAD
|
||||
namespace
|
||||
erf
|
||||
$$
|
||||
|
||||
$section Base Type Requirements for Standard Math Functions$$
|
||||
|
||||
$head Purpose$$
|
||||
These definitions are required for the user's code to use the type
|
||||
$codei%AD<%Base%>%$$:
|
||||
|
||||
$head Unary Standard Math$$
|
||||
The type $icode Base$$ must support the following functions
|
||||
unary standard math functions (in the CppAD namespace):
|
||||
$table
|
||||
$bold Syntax$$ $cnext $bold Result$$
|
||||
$rnext
|
||||
$icode%y% = abs(%x%)%$$ $cnext absolute value $rnext
|
||||
$icode%y% = acos(%x%)%$$ $cnext inverse cosine $rnext
|
||||
$icode%y% = asin(%x%)%$$ $cnext inverse sine $rnext
|
||||
$icode%y% = atan(%x%)%$$ $cnext inverse tangent $rnext
|
||||
$icode%y% = cos(%x%)%$$ $cnext cosine $rnext
|
||||
$icode%y% = cosh(%x%)%$$ $cnext hyperbolic cosine $rnext
|
||||
$icode%y% = exp(%x%)%$$ $cnext exponential $rnext
|
||||
$icode%y% = fabs(%x%)%$$ $cnext absolute value $rnext
|
||||
$icode%y% = log(%x%)%$$ $cnext natural logarithm $rnext
|
||||
$icode%y% = sin(%x%)%$$ $cnext sine $rnext
|
||||
$icode%y% = sinh(%x%)%$$ $cnext hyperbolic sine $rnext
|
||||
$icode%y% = sqrt(%x%)%$$ $cnext square root $rnext
|
||||
$icode%y% = tan(%x%)%$$ $cnext tangent
|
||||
$tend
|
||||
where the arguments and return value have the prototypes
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
%Base% %y%
|
||||
%$$
|
||||
For example,
|
||||
$cref/base_alloc/base_alloc.hpp/Unary Standard Math/$$,
|
||||
|
||||
|
||||
$head CPPAD_STANDARD_MATH_UNARY$$
|
||||
The macro invocation, within the CppAD namespace,
|
||||
$codei%
|
||||
CPPAD_STANDARD_MATH_UNARY(%Base%, %Fun%)
|
||||
%$$
|
||||
defines the syntax
|
||||
$codei%
|
||||
%y% = CppAD::%Fun%(%x%)
|
||||
%$$
|
||||
This macro uses the functions $codei%std::%Fun%$$ which
|
||||
must be defined and have the same prototype as $codei%CppAD::%Fun%$$.
|
||||
For example,
|
||||
$cref/float/base_float.hpp/Unary Standard Math/$$.
|
||||
|
||||
$head erf, asinh, acosh, atanh, expm1, log1p$$
|
||||
If this preprocessor symbol
|
||||
$code CPPAD_USE_CPLUSPLUS_2011$$ is true ($code 1$$),
|
||||
when compiling for c++11, the type
|
||||
$code double$$ is supported for the functions listed below.
|
||||
In this case, the type $icode Base$$ must also support these functions:
|
||||
$table
|
||||
$bold Syntax$$ $cnext $bold Result$$
|
||||
$rnext
|
||||
$icode%y% = erf(%x%)%$$ $cnext error function $rnext
|
||||
$icode%y% = asinh(%x%)%$$ $cnext inverse hyperbolic sin $rnext
|
||||
$icode%y% = acosh(%x%)%$$ $cnext inverse hyperbolic cosine $rnext
|
||||
$icode%y% = atanh(%x%)%$$ $cnext inverse hyperbolic tangent $rnext
|
||||
$icode%y% = expm1(%x%)%$$ $cnext exponential of x minus one $rnext
|
||||
$icode%y% = log1p(%x%)%$$ $cnext logarithm of one plus x
|
||||
$tend
|
||||
where the arguments and return value have the prototypes
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
%Base% %y%
|
||||
%$$
|
||||
|
||||
$head sign$$
|
||||
The type $icode Base$$ must support the syntax
|
||||
$codei%
|
||||
%y% = CppAD::sign(%x%)
|
||||
%$$
|
||||
which computes
|
||||
$latex \[
|
||||
y = \left\{ \begin{array}{ll}
|
||||
+1 & {\rm if} \; x > 0 \\
|
||||
0 & {\rm if} \; x = 0 \\
|
||||
-1 & {\rm if} \; x < 0
|
||||
\end{array} \right.
|
||||
\] $$
|
||||
where $icode x$$ and $icode y$$ have the same prototype as above.
|
||||
For example, see
|
||||
$cref/base_alloc/base_alloc.hpp/sign/$$.
|
||||
Note that, if ordered comparisons are not defined for the type $icode Base$$,
|
||||
the $code code sign$$ function should generate an assert if it is used; see
|
||||
$cref/complex invalid unary math/base_complex.hpp/Invalid Unary Math/$$.
|
||||
|
||||
$head pow$$
|
||||
The type $icode Base$$ must support the syntax
|
||||
$codei%
|
||||
%z% = CppAD::pow(%x%, %y%)
|
||||
%$$
|
||||
which computes $latex z = x^y$$.
|
||||
The arguments $icode x$$ and $icode y$$ have prototypes
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
const %Base%& %y%
|
||||
%$$
|
||||
and the return value $icode z$$ has prototype
|
||||
$codei%
|
||||
%Base% %z%
|
||||
%$$
|
||||
For example, see
|
||||
$cref/base_alloc/base_alloc.hpp/pow/$$.
|
||||
|
||||
|
||||
$head isnan$$
|
||||
If $icode Base$$ defines the $code isnan$$ function,
|
||||
you may also have to provide a definition in the CppAD namespace
|
||||
(to avoid a function ambiguity).
|
||||
For example, see
|
||||
$cref/base_complex/base_complex.hpp/isnan/$$.
|
||||
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
# include <cmath>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
\file base_std_math.hpp
|
||||
Defintions that aid meeting Base type requirements for standard math functions.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_STANDARD_MATH_UNARY(Type, Fun)
|
||||
This macro defines the function
|
||||
\verbatim
|
||||
y = CppAD:Fun(x)
|
||||
\endverbatim
|
||||
where the argument \c x and return value \c y have type \c Type
|
||||
using the corresponding function <code>std::Fun</code>.
|
||||
*/
|
||||
# define CPPAD_STANDARD_MATH_UNARY(Type, Fun) \
|
||||
inline Type Fun(const Type& x) \
|
||||
{ return std::Fun(x); }
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,65 @@
|
||||
# ifndef CPPAD_CORE_BASE_TO_STRING_HPP
|
||||
# define CPPAD_CORE_BASE_TO_STRING_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 base_to_string$$
|
||||
$spell
|
||||
std
|
||||
namespace
|
||||
CppAD
|
||||
struct
|
||||
const
|
||||
stringstream
|
||||
setprecision
|
||||
str
|
||||
$$
|
||||
|
||||
$section Extending to_string To Another Floating Point Type$$
|
||||
|
||||
$head Base Requirement$$
|
||||
If the function $cref to_string$$ is used by an
|
||||
$cref/AD type above Base/glossary/AD Type Above Base/$$,
|
||||
A specialization for the template structure
|
||||
$code CppAD::to_string_struct$$ must be defined.
|
||||
|
||||
$head CPPAD_TO_STRING$$
|
||||
For most $icode Base$$ types,
|
||||
the following can be used to define the specialization:
|
||||
$codei%
|
||||
namespace CppAD {
|
||||
CPPAD_TO_STRING(%Base%)
|
||||
}
|
||||
%$$
|
||||
Note that the $code CPPAD_TO_STRING$$ macro assumes that the
|
||||
$cref base_limits$$ and $cref base_std_math$$ have already been defined
|
||||
for this type.
|
||||
This macro is defined as follows:
|
||||
$srccode%cpp% */
|
||||
# define CPPAD_TO_STRING(Base) \
|
||||
template <> struct to_string_struct<Base>\
|
||||
{ std::string operator()(const Base& value) \
|
||||
{ std::stringstream os;\
|
||||
int n_digits = 1 + CppAD::numeric_limits<Base>::digits10; \
|
||||
os << std::setprecision(n_digits);\
|
||||
os << value;\
|
||||
return os.str();\
|
||||
}\
|
||||
};
|
||||
/* %$$
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
// make sure to_string has been included
|
||||
# include <cppad/utility/to_string.hpp>
|
||||
|
||||
# endif
|
||||
+404
@@ -0,0 +1,404 @@
|
||||
# ifndef CPPAD_CORE_BENDER_QUAD_HPP
|
||||
# define CPPAD_CORE_BENDER_QUAD_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 BenderQuad$$
|
||||
$spell
|
||||
cppad.hpp
|
||||
BAvector
|
||||
gx
|
||||
gxx
|
||||
CppAD
|
||||
Fy
|
||||
dy
|
||||
Jacobian
|
||||
ADvector
|
||||
const
|
||||
dg
|
||||
ddg
|
||||
$$
|
||||
|
||||
|
||||
$section Computing Jacobian and Hessian of Bender's Reduced Objective$$
|
||||
$mindex BenderQuad$$
|
||||
|
||||
$head Syntax$$
|
||||
$codei%
|
||||
# include <cppad/cppad.hpp>
|
||||
BenderQuad(%x%, %y%, %fun%, %g%, %gx%, %gxx%)%$$
|
||||
|
||||
$head See Also$$
|
||||
$cref opt_val_hes$$
|
||||
|
||||
$head Problem$$
|
||||
The type $cref/ADvector/BenderQuad/ADvector/$$ cannot be determined
|
||||
form the arguments above
|
||||
(currently the type $icode ADvector$$ must be
|
||||
$codei%CPPAD_TESTVECTOR(%Base%)%$$.)
|
||||
This will be corrected in the future by requiring $icode Fun$$
|
||||
to define $icode%Fun%::vector_type%$$ which will specify the
|
||||
type $icode ADvector$$.
|
||||
|
||||
$head Purpose$$
|
||||
We are given the optimization problem
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
{\rm minimize} & F(x, y) & {\rm w.r.t.} \; (x, y) \in \B{R}^n \times \B{R}^m
|
||||
\end{array}
|
||||
\] $$
|
||||
that is convex with respect to $latex y$$.
|
||||
In addition, we are given a set of equations $latex H(x, y)$$
|
||||
such that
|
||||
$latex \[
|
||||
H[ x , Y(x) ] = 0 \;\; \Rightarrow \;\; F_y [ x , Y(x) ] = 0
|
||||
\] $$
|
||||
(In fact, it is often the case that $latex H(x, y) = F_y (x, y)$$.)
|
||||
Furthermore, it is easy to calculate a Newton step for these equations; i.e.,
|
||||
$latex \[
|
||||
dy = - [ \partial_y H(x, y)]^{-1} H(x, y)
|
||||
\] $$
|
||||
The purpose of this routine is to compute the
|
||||
value, Jacobian, and Hessian of the reduced objective function
|
||||
$latex \[
|
||||
G(x) = F[ x , Y(x) ]
|
||||
\] $$
|
||||
Note that if only the value and Jacobian are needed, they can be
|
||||
computed more quickly using the relations
|
||||
$latex \[
|
||||
G^{(1)} (x) = \partial_x F [x, Y(x) ]
|
||||
\] $$
|
||||
|
||||
$head x$$
|
||||
The $code BenderQuad$$ argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %BAvector% &%x%
|
||||
%$$
|
||||
(see $cref/BAvector/BenderQuad/BAvector/$$ below)
|
||||
and its size must be equal to $icode n$$.
|
||||
It specifies the point at which we evaluating
|
||||
the reduced objective function and its derivatives.
|
||||
|
||||
|
||||
$head y$$
|
||||
The $code BenderQuad$$ argument $icode y$$ has prototype
|
||||
$codei%
|
||||
const %BAvector% &%y%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
It must be equal to $latex Y(x)$$; i.e.,
|
||||
it must solve the problem in $latex y$$ for this given value of $latex x$$
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
{\rm minimize} & F(x, y) & {\rm w.r.t.} \; y \in \B{R}^m
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head fun$$
|
||||
The $code BenderQuad$$ object $icode fun$$
|
||||
must support the member functions listed below.
|
||||
The $codei%AD<%Base%>%$$ arguments will be variables for
|
||||
a tape created by a call to $cref Independent$$ from $code BenderQuad$$
|
||||
(hence they can not be combined with variables corresponding to a
|
||||
different tape).
|
||||
|
||||
$subhead fun.f$$
|
||||
The $code BenderQuad$$ argument $icode fun$$ supports the syntax
|
||||
$codei%
|
||||
%f% = %fun%.f(%x%, %y%)
|
||||
%$$
|
||||
The $icode%fun%.f%$$ argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %ADvector% &%x%
|
||||
%$$
|
||||
(see $cref/ADvector/BenderQuad/ADvector/$$ below)
|
||||
and its size must be equal to $icode n$$.
|
||||
The $icode%fun%.f%$$ argument $icode y$$ has prototype
|
||||
$codei%
|
||||
const %ADvector% &%y%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
The $icode%fun%.f%$$ result $icode f$$ has prototype
|
||||
$codei%
|
||||
%ADvector% %f%
|
||||
%$$
|
||||
and its size must be equal to one.
|
||||
The value of $icode f$$ is
|
||||
$latex \[
|
||||
f = F(x, y)
|
||||
\] $$.
|
||||
|
||||
$subhead fun.h$$
|
||||
The $code BenderQuad$$ argument $icode fun$$ supports the syntax
|
||||
$codei%
|
||||
%h% = %fun%.h(%x%, %y%)
|
||||
%$$
|
||||
The $icode%fun%.h%$$ argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %ADvector% &%x%
|
||||
%$$
|
||||
and its size must be equal to $icode n$$.
|
||||
The $icode%fun%.h%$$ argument $icode y$$ has prototype
|
||||
$codei%
|
||||
const %BAvector% &%y%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
The $icode%fun%.h%$$ result $icode h$$ has prototype
|
||||
$codei%
|
||||
%ADvector% %h%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
The value of $icode h$$ is
|
||||
$latex \[
|
||||
h = H(x, y)
|
||||
\] $$.
|
||||
|
||||
$subhead fun.dy$$
|
||||
The $code BenderQuad$$ argument $icode fun$$ supports the syntax
|
||||
$codei%
|
||||
%dy% = %fun%.dy(%x%, %y%, %h%)
|
||||
|
||||
%x%
|
||||
%$$
|
||||
The $icode%fun%.dy%$$ argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %BAvector% &%x%
|
||||
%$$
|
||||
and its size must be equal to $icode n$$.
|
||||
Its value will be exactly equal to the $code BenderQuad$$ argument
|
||||
$icode x$$ and values depending on it can be stored as private objects
|
||||
in $icode f$$ and need not be recalculated.
|
||||
$codei%
|
||||
|
||||
%y%
|
||||
%$$
|
||||
The $icode%fun%.dy%$$ argument $icode y$$ has prototype
|
||||
$codei%
|
||||
const %BAvector% &%y%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
Its value will be exactly equal to the $code BenderQuad$$ argument
|
||||
$icode y$$ and values depending on it can be stored as private objects
|
||||
in $icode f$$ and need not be recalculated.
|
||||
$codei%
|
||||
|
||||
%h%
|
||||
%$$
|
||||
The $icode%fun%.dy%$$ argument $icode h$$ has prototype
|
||||
$codei%
|
||||
const %ADvector% &%h%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
$codei%
|
||||
|
||||
%dy%
|
||||
%$$
|
||||
The $icode%fun%.dy%$$ result $icode dy$$ has prototype
|
||||
$codei%
|
||||
%ADvector% %dy%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
The return value $icode dy$$ is given by
|
||||
$latex \[
|
||||
dy = - [ \partial_y H (x , y) ]^{-1} h
|
||||
\] $$
|
||||
Note that if $icode h$$ is equal to $latex H(x, y)$$,
|
||||
$latex dy$$ is the Newton step for finding a zero
|
||||
of $latex H(x, y)$$ with respect to $latex y$$;
|
||||
i.e.,
|
||||
$latex y + dy$$ is an approximate solution for the equation
|
||||
$latex H (x, y + dy) = 0$$.
|
||||
|
||||
$head g$$
|
||||
The argument $icode g$$ has prototype
|
||||
$codei%
|
||||
%BAvector% &%g%
|
||||
%$$
|
||||
and has size one.
|
||||
The input value of its element does not matter.
|
||||
On output,
|
||||
it contains the value of $latex G (x)$$; i.e.,
|
||||
$latex \[
|
||||
g[0] = G (x)
|
||||
\] $$
|
||||
|
||||
$head gx$$
|
||||
The argument $icode gx$$ has prototype
|
||||
$codei%
|
||||
%BAvector% &%gx%
|
||||
%$$
|
||||
and has size $latex n $$.
|
||||
The input values of its elements do not matter.
|
||||
On output,
|
||||
it contains the Jacobian of $latex G (x)$$; i.e.,
|
||||
for $latex j = 0 , \ldots , n-1$$,
|
||||
$latex \[
|
||||
gx[ j ] = G^{(1)} (x)_j
|
||||
\] $$
|
||||
|
||||
$head gxx$$
|
||||
The argument $icode gx$$ has prototype
|
||||
$codei%
|
||||
%BAvector% &%gxx%
|
||||
%$$
|
||||
and has size $latex n \times n$$.
|
||||
The input values of its elements do not matter.
|
||||
On output,
|
||||
it contains the Hessian of $latex G (x)$$; i.e.,
|
||||
for $latex i = 0 , \ldots , n-1$$, and
|
||||
$latex j = 0 , \ldots , n-1$$,
|
||||
$latex \[
|
||||
gxx[ i * n + j ] = G^{(2)} (x)_{i,j}
|
||||
\] $$
|
||||
|
||||
$head BAvector$$
|
||||
The type $icode BAvector$$ must be a
|
||||
$cref SimpleVector$$ class.
|
||||
We use $icode Base$$ to refer to the type of the elements of
|
||||
$icode BAvector$$; i.e.,
|
||||
$codei%
|
||||
%BAvector%::value_type
|
||||
%$$
|
||||
|
||||
$head ADvector$$
|
||||
The type $icode ADvector$$ must be a
|
||||
$cref SimpleVector$$ class with elements of type
|
||||
$codei%AD<%Base%>%$$; i.e.,
|
||||
$codei%
|
||||
%ADvector%::value_type
|
||||
%$$
|
||||
must be the same type as
|
||||
$codei%
|
||||
AD< %BAvector%::value_type >
|
||||
%$$.
|
||||
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/bender_quad.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref bender_quad.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN CppAD namespace
|
||||
|
||||
template <class BAvector, class Fun>
|
||||
void BenderQuad(
|
||||
const BAvector &x ,
|
||||
const BAvector &y ,
|
||||
Fun fun ,
|
||||
BAvector &g ,
|
||||
BAvector &gx ,
|
||||
BAvector &gxx )
|
||||
{ // determine the base type
|
||||
typedef typename BAvector::value_type Base;
|
||||
|
||||
// check that BAvector is a SimpleVector class
|
||||
CheckSimpleVector<Base, BAvector>();
|
||||
|
||||
// declare the ADvector type
|
||||
typedef CPPAD_TESTVECTOR(AD<Base>) ADvector;
|
||||
|
||||
// size of the x and y spaces
|
||||
size_t n = size_t(x.size());
|
||||
size_t m = size_t(y.size());
|
||||
|
||||
// check the size of gx and gxx
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
g.size() == 1,
|
||||
"BenderQuad: size of the vector g is not equal to 1"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(gx.size()) == n,
|
||||
"BenderQuad: size of the vector gx is not equal to n"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(gxx.size()) == n * n,
|
||||
"BenderQuad: size of the vector gxx is not equal to n * n"
|
||||
);
|
||||
|
||||
// some temporary indices
|
||||
size_t i, j;
|
||||
|
||||
// variable versions x
|
||||
ADvector vx(n);
|
||||
for(j = 0; j < n; j++)
|
||||
vx[j] = x[j];
|
||||
|
||||
// declare the independent variables
|
||||
Independent(vx);
|
||||
|
||||
// evaluate h = H(x, y)
|
||||
ADvector h(m);
|
||||
h = fun.h(vx, y);
|
||||
|
||||
// evaluate dy (x) = Newton step as a function of x through h only
|
||||
ADvector dy(m);
|
||||
dy = fun.dy(x, y, h);
|
||||
|
||||
// variable version of y
|
||||
ADvector vy(m);
|
||||
for(j = 0; j < m; j++)
|
||||
vy[j] = y[j] + dy[j];
|
||||
|
||||
// evaluate G~ (x) = F [ x , y + dy(x) ]
|
||||
ADvector gtilde(1);
|
||||
gtilde = fun.f(vx, vy);
|
||||
|
||||
// AD function object that corresponds to G~ (x)
|
||||
// We will make heavy use of this tape, so optimize it
|
||||
ADFun<Base> Gtilde;
|
||||
Gtilde.Dependent(vx, gtilde);
|
||||
Gtilde.optimize();
|
||||
|
||||
// value of G(x)
|
||||
g = Gtilde.Forward(0, x);
|
||||
|
||||
// initial forward direction vector as zero
|
||||
BAvector dx(n);
|
||||
for(j = 0; j < n; j++)
|
||||
dx[j] = Base(0.0);
|
||||
|
||||
// weight, first and second order derivative values
|
||||
BAvector dg(1), w(1), ddw(2 * n);
|
||||
w[0] = 1.;
|
||||
|
||||
|
||||
// Jacobian and Hessian of G(x) is equal Jacobian and Hessian of Gtilde
|
||||
for(j = 0; j < n; j++)
|
||||
{ // compute partials in x[j] direction
|
||||
dx[j] = Base(1.0);
|
||||
dg = Gtilde.Forward(1, dx);
|
||||
gx[j] = dg[0];
|
||||
|
||||
// restore the dx vector to zero
|
||||
dx[j] = Base(0.0);
|
||||
|
||||
// compute second partials w.r.t x[j] and x[l] for l = 1, n
|
||||
ddw = Gtilde.Reverse(2, w);
|
||||
for(i = 0; i < n; i++)
|
||||
gxx[ i * n + j ] = ddw[ i * 2 + 1 ];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
# ifndef CPPAD_CORE_BOOL_FUN_HPP
|
||||
# define CPPAD_CORE_BOOL_FUN_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 BoolFun$$
|
||||
$spell
|
||||
namespace
|
||||
bool
|
||||
CppAD
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section AD Boolean Functions$$
|
||||
$mindex bool CPPAD_BOOL_UNARY CPPAD_BOOL_BINARY$$
|
||||
|
||||
$head Syntax$$
|
||||
$codei%CPPAD_BOOL_UNARY(%Base%, %unary_name%)
|
||||
%$$
|
||||
$icode%b% = %unary_name%(%u%)
|
||||
%$$
|
||||
$icode%b% = %unary_name%(%x%)
|
||||
%$$
|
||||
$codei%CPPAD_BOOL_BINARY(%Base%, %binary_name%)
|
||||
%$$
|
||||
$icode%b% = %binary_name%(%u%, %v%)
|
||||
%$$
|
||||
$icode%b% = %binary_name%(%x%, %y%)%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Create a $code bool$$ valued function that has $codei%AD<%Base%>%$$ arguments.
|
||||
|
||||
$head unary_name$$
|
||||
This is the name of the $code bool$$ valued function with one argument
|
||||
(as it is used in the source code).
|
||||
The user must provide a version of $icode unary_name$$ where
|
||||
the argument has type $icode Base$$.
|
||||
CppAD uses this to create a version of $icode unary_name$$ where the
|
||||
argument has type $codei%AD<%Base%>%$$.
|
||||
|
||||
$head u$$
|
||||
The argument $icode u$$ has prototype
|
||||
$codei%
|
||||
const %Base% &%u%
|
||||
%$$
|
||||
It is the value at which the user provided version of $icode unary_name$$
|
||||
is to be evaluated.
|
||||
It is also used for the first argument to the
|
||||
user provided version of $icode binary_name$$.
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const AD<%Base%> &%x%
|
||||
%$$
|
||||
It is the value at which the CppAD provided version of $icode unary_name$$
|
||||
is to be evaluated.
|
||||
It is also used for the first argument to the
|
||||
CppAD provided version of $icode binary_name$$.
|
||||
|
||||
$head b$$
|
||||
The result $icode b$$ has prototype
|
||||
$codei%
|
||||
bool %b%
|
||||
%$$
|
||||
|
||||
$head Create Unary$$
|
||||
The preprocessor macro invocation
|
||||
$codei%
|
||||
CPPAD_BOOL_UNARY(%Base%, %unary_name%)
|
||||
%$$
|
||||
defines the version of $icode unary_name$$ with a $codei%AD<%Base%>%$$
|
||||
argument.
|
||||
This can with in a namespace
|
||||
(not the $code CppAD$$ namespace)
|
||||
but must be outside of any routine.
|
||||
|
||||
$head binary_name$$
|
||||
This is the name of the $code bool$$ valued function with two arguments
|
||||
(as it is used in the source code).
|
||||
The user must provide a version of $icode binary_name$$ where
|
||||
the arguments have type $icode Base$$.
|
||||
CppAD uses this to create a version of $icode binary_name$$ where the
|
||||
arguments have type $codei%AD<%Base%>%$$.
|
||||
|
||||
$head v$$
|
||||
The argument $icode v$$ has prototype
|
||||
$codei%
|
||||
const %Base% &%v%
|
||||
%$$
|
||||
It is the second argument to
|
||||
the user provided version of $icode binary_name$$.
|
||||
|
||||
$head y$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const AD<%Base%> &%y%
|
||||
%$$
|
||||
It is the second argument to
|
||||
the CppAD provided version of $icode binary_name$$.
|
||||
|
||||
$head Create Binary$$
|
||||
The preprocessor macro invocation
|
||||
$codei%
|
||||
CPPAD_BOOL_BINARY(%Base%, %binary_name%)
|
||||
%$$
|
||||
defines the version of $icode binary_name$$ with $codei%AD<%Base%>%$$
|
||||
arguments.
|
||||
This can with in a namespace
|
||||
(not the $code CppAD$$ namespace)
|
||||
but must be outside of any routine.
|
||||
|
||||
|
||||
$head Operation Sequence$$
|
||||
The result of this operation is not an
|
||||
$cref/AD of Base/glossary/AD of Base/$$ object.
|
||||
Thus it will not be recorded as part of an
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/bool_fun.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref bool_fun.cpp$$
|
||||
contains an example and test of these operations.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$head Deprecated 2007-07-31$$
|
||||
The preprocessor symbols $code CppADCreateUnaryBool$$
|
||||
and $code CppADCreateBinaryBool$$ are defined to be the same as
|
||||
$code CPPAD_BOOL_UNARY$$ and $code CPPAD_BOOL_BINARY$$ respectively
|
||||
(but their use is deprecated).
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file bool_fun.hpp
|
||||
Routines and macros that implement functions from AD<Base> to bool.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Macro that defines a unary function <tt>bool F(AD<Base> x)</tt>
|
||||
using <tt>bool F(Base x)</tt>.
|
||||
|
||||
\param Base
|
||||
base for the AD type of arguments to this unary bool valued function.
|
||||
|
||||
\param unary_name
|
||||
name of this unary function; i.e., \c F.
|
||||
*/
|
||||
# define CPPAD_BOOL_UNARY(Base, unary_name) \
|
||||
inline bool unary_name (const CppAD::AD<Base> &x) \
|
||||
{ \
|
||||
return CppAD::AD<Base>::UnaryBool(unary_name, x); \
|
||||
}
|
||||
|
||||
/*!
|
||||
Deprecated name for CPPAD_BOOL_UNARY
|
||||
*/
|
||||
# define CppADCreateUnaryBool CPPAD_BOOL_UNARY
|
||||
|
||||
/*!
|
||||
Link a function name, and AD value pair to function call with base argument
|
||||
and bool retrun value.
|
||||
|
||||
\param FunName
|
||||
is the name of the function that we are linking.
|
||||
|
||||
\param x
|
||||
is the argument where we are evaluating the function.
|
||||
*/
|
||||
template <class Base>
|
||||
inline bool AD<Base>::UnaryBool(
|
||||
bool FunName(const Base &x),
|
||||
const AD<Base> &x
|
||||
)
|
||||
{
|
||||
return FunName(x.value_);
|
||||
}
|
||||
|
||||
/*!
|
||||
Macro that defines a binary function <tt>bool F(AD<Base> x, AD<Base> y)</tt>
|
||||
using <tt>bool F(Base x, Base y)</tt>.
|
||||
|
||||
\param Base
|
||||
base for the AD type of arguments to this binary bool valued function.
|
||||
|
||||
\param binary_name
|
||||
name of this binary function; i.e., \c F.
|
||||
*/
|
||||
|
||||
# define CPPAD_BOOL_BINARY(Base, binary_name) \
|
||||
inline bool binary_name ( \
|
||||
const CppAD::AD<Base> &x, const CppAD::AD<Base> &y) \
|
||||
{ \
|
||||
return CppAD::AD<Base>::BinaryBool(binary_name, x, y); \
|
||||
}
|
||||
/*!
|
||||
Deprecated name for CPPAD_BOOL_BINARY
|
||||
*/
|
||||
# define CppADCreateBinaryBool CPPAD_BOOL_BINARY
|
||||
|
||||
|
||||
/*!
|
||||
Link a function name, and two AD values to function call with base arguments
|
||||
and bool retrun value.
|
||||
|
||||
\param FunName
|
||||
is the name of the function that we are linking.
|
||||
|
||||
\param x
|
||||
is the first argument where we are evaluating the function at.
|
||||
|
||||
\param y
|
||||
is the second argument where we are evaluating the function at.
|
||||
*/
|
||||
template <class Base>
|
||||
inline bool AD<Base>::BinaryBool(
|
||||
bool FunName(const Base &x, const Base &y),
|
||||
const AD<Base> &x, const AD<Base> &y
|
||||
)
|
||||
{
|
||||
return FunName(x.value_, y.value_);
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,50 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_BOOL_VALUED_HPP
|
||||
# define CPPAD_CORE_BOOL_VALUED_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 BoolValued$$
|
||||
$spell
|
||||
Bool
|
||||
$$
|
||||
|
||||
|
||||
$section Bool Valued Operations and Functions with AD Arguments$$
|
||||
|
||||
$children%
|
||||
cppad/core/compare.hpp%
|
||||
cppad/core/near_equal_ext.hpp%
|
||||
cppad/core/bool_fun.hpp%
|
||||
cppad/core/par_var.hpp%
|
||||
cppad/core/equal_op_seq.hpp
|
||||
%$$
|
||||
$table
|
||||
$rref Compare$$
|
||||
$rref NearEqualExt$$
|
||||
$rref BoolFun$$
|
||||
$rref ParVar$$
|
||||
$rref EqualOpSeq$$
|
||||
$tend
|
||||
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
# include <cppad/core/compare.hpp>
|
||||
# include <cppad/core/near_equal_ext.hpp>
|
||||
# include <cppad/core/bool_fun.hpp>
|
||||
# include <cppad/core/par_var.hpp>
|
||||
# include <cppad/core/equal_op_seq.hpp>
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,259 @@
|
||||
# ifndef CPPAD_CORE_CAPACITY_ORDER_HPP
|
||||
# define CPPAD_CORE_CAPACITY_ORDER_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 capacity_order$$
|
||||
$spell
|
||||
var
|
||||
taylor_
|
||||
xq
|
||||
yq
|
||||
$$
|
||||
|
||||
|
||||
$section Controlling Taylor Coefficients Memory Allocation$$
|
||||
$mindex Forward capacity_order control$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.capacity_order(%c%)%$$
|
||||
|
||||
$subhead See Also$$
|
||||
$cref seq_property$$
|
||||
|
||||
$head Purpose$$
|
||||
The Taylor coefficients calculated by $cref Forward$$ mode calculations
|
||||
are retained in an $cref ADFun$$ object for subsequent use during
|
||||
$cref Reverse$$ mode and higher order Forward mode calculations.
|
||||
For example, a call to $cref/Forward/forward_order/$$ with the syntax
|
||||
$codei%
|
||||
%yq% = %f%.Forward(%q%, %xq%)
|
||||
%$$
|
||||
where $icode%q% > 0%$$ and $code%xq%.size() == %f%.Domain()%$$,
|
||||
uses the lower order Taylor coefficients and
|
||||
computes the $th q$$ order Taylor coefficients for all
|
||||
the variables in the operation sequence corresponding to $icode f$$.
|
||||
The $code capacity_order$$ operation allows you to control that
|
||||
amount of memory that is retained by an AD function object
|
||||
(to hold $code Forward$$ results for subsequent calculations).
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head c$$
|
||||
The argument $icode c$$ has prototype
|
||||
$codei%
|
||||
size_t %c%
|
||||
%$$
|
||||
It specifies the number of Taylor coefficient orders that are allocated
|
||||
in the AD operation sequence corresponding to $icode f$$.
|
||||
|
||||
$subhead Pre-Allocating Memory$$
|
||||
If you plan to make calls to $code Forward$$ with the maximum value of
|
||||
$icode q$$ equal to $icode Q$$,
|
||||
it should be faster to pre-allocate memory for these calls using
|
||||
$codei%
|
||||
%f%.capacity_order(%c%)
|
||||
%$$
|
||||
with $icode c$$ equal to $latex Q + 1$$.
|
||||
If you do no do this, $code Forward$$ will automatically allocate memory
|
||||
and will copy the results to a larger buffer, when necessary.
|
||||
$pre
|
||||
|
||||
$$
|
||||
Note that each call to $cref Dependent$$ frees the old memory
|
||||
connected to the function object and sets the corresponding
|
||||
taylor capacity to zero.
|
||||
|
||||
$subhead Freeing Memory$$
|
||||
If you no longer need the Taylor coefficients of order $icode q$$
|
||||
and higher (that are stored in $icode f$$),
|
||||
you can reduce the memory allocated to $icode f$$ using
|
||||
$codei%
|
||||
%f%.capacity_order(%c%)
|
||||
%$$
|
||||
with $icode c$$ equal to $icode q$$.
|
||||
Note that, if $cref ta_hold_memory$$ is true, this memory is not actually
|
||||
returned to the system, but rather held for future use by the same thread.
|
||||
|
||||
$head Original State$$
|
||||
If $icode f$$ is $cref/constructed/FunConstruct/$$ with the syntax
|
||||
$codei%
|
||||
ADFun<%Base%> %f%(%x%, %y%)
|
||||
%$$,
|
||||
there is an implicit call to $cref forward_zero$$ with $icode xq$$ equal to
|
||||
the value of the
|
||||
$cref/independent variables/glossary/Tape/Independent Variable/$$
|
||||
when the AD operation sequence was recorded.
|
||||
This corresponds to $icode%c% == 1%$$.
|
||||
|
||||
$children%
|
||||
example/general/capacity_order.cpp
|
||||
%$$
|
||||
$head Example$$
|
||||
The file
|
||||
$cref capacity_order.cpp$$
|
||||
contains an example and test of these operations.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file capacity_order.hpp
|
||||
Control of number of orders allocated.
|
||||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
Control of number of orders and directions allocated.
|
||||
|
||||
\tparam Base
|
||||
The type used during the forward mode computations; i.e., the corresponding
|
||||
recording of operations used the type AD<Base>.
|
||||
|
||||
\param c
|
||||
is the number of orders to allocate memory for.
|
||||
If <code>c == 0</code> then \c r must also be zero.
|
||||
In this case num_order_taylor_, cap_order_taylor_, and num_direction_taylor_
|
||||
are all set to zero.
|
||||
In addition, taylor_.free() is called.
|
||||
|
||||
\param r
|
||||
is the number of directions to allocate memory for.
|
||||
If <code>c == 1</code> then \c r must also be one.
|
||||
In all cases, it must hold that
|
||||
<code>
|
||||
r == num_direction_taylor_ || num_order_taylor <= 1
|
||||
</code>
|
||||
Upon return, num_direction_taylor_ is equal to r.
|
||||
|
||||
\par num_order_taylor_
|
||||
The output value of num_order_taylor_ is the mininumum of its input
|
||||
value and c. This minimum is the number of orders that are copied to the
|
||||
new taylor coefficient buffer.
|
||||
|
||||
\par num_direction_taylor_
|
||||
The output value of num_direction_taylor_ is equal to \c r.
|
||||
*/
|
||||
|
||||
template <typename Base>
|
||||
void ADFun<Base>::capacity_order(size_t c, size_t r)
|
||||
{ // temporary indices
|
||||
size_t i, k, ell;
|
||||
|
||||
if( (c == cap_order_taylor_) & (r == num_direction_taylor_) )
|
||||
return;
|
||||
|
||||
if( c == 0 )
|
||||
{ CPPAD_ASSERT_UNKNOWN( r == 0 );
|
||||
taylor_.free();
|
||||
num_order_taylor_ = 0;
|
||||
cap_order_taylor_ = 0;
|
||||
num_direction_taylor_ = r;
|
||||
return;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN(r==num_direction_taylor_ || num_order_taylor_<=1);
|
||||
|
||||
// Allocate new taylor with requested number of orders and directions
|
||||
size_t new_len = ( (c-1)*r + 1 ) * num_var_tape_;
|
||||
local::pod_vector<Base> new_taylor;
|
||||
new_taylor.extend(new_len);
|
||||
|
||||
// number of orders to copy
|
||||
size_t p = std::min(num_order_taylor_, c);
|
||||
if( p > 0 )
|
||||
{
|
||||
// old order capacity
|
||||
size_t C = cap_order_taylor_;
|
||||
|
||||
// old number of directions
|
||||
size_t R = num_direction_taylor_;
|
||||
|
||||
// copy the old data into the new matrix
|
||||
CPPAD_ASSERT_UNKNOWN( p == 1 || r == R );
|
||||
for(i = 0; i < num_var_tape_; i++)
|
||||
{ // copy zero order
|
||||
size_t old_index = ((C-1) * R + 1) * i + 0;
|
||||
size_t new_index = ((c-1) * r + 1) * i + 0;
|
||||
new_taylor[ new_index ] = taylor_[ old_index ];
|
||||
// copy higher orders
|
||||
for(k = 1; k < p; k++)
|
||||
{ for(ell = 0; ell < R; ell++)
|
||||
{ old_index = ((C-1) * R + 1) * i + (k-1) * R + ell + 1;
|
||||
new_index = ((c-1) * r + 1) * i + (k-1) * r + ell + 1;
|
||||
new_taylor[ new_index ] = taylor_[ old_index ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// replace taylor_ by new_taylor
|
||||
taylor_.swap(new_taylor);
|
||||
cap_order_taylor_ = c;
|
||||
num_order_taylor_ = p;
|
||||
num_direction_taylor_ = r;
|
||||
|
||||
// note that the destructor for new_taylor will free the old taylor memory
|
||||
return;
|
||||
}
|
||||
|
||||
/*!
|
||||
User API control of number of orders allocated.
|
||||
|
||||
\tparam Base
|
||||
The type used during the forward mode computations; i.e., the corresponding
|
||||
recording of operations used the type AD<Base>.
|
||||
|
||||
\param c
|
||||
is the number of orders to allocate memory for.
|
||||
If <code>c == 0</code>,
|
||||
num_order_taylor_, cap_order_taylor_, and num_direction_taylor_
|
||||
are all set to zero.
|
||||
In addition, taylor_.free() is called.
|
||||
|
||||
\par num_order_taylor_
|
||||
The output value of num_order_taylor_ is the mininumum of its input
|
||||
value and c. This minimum is the number of orders that are copied to the
|
||||
new taylor coefficient buffer.
|
||||
|
||||
\par num_direction_taylor_
|
||||
If \c is zero (one), \c num_direction_taylor_ is set to zero (one).
|
||||
Otherwise, if \c num_direction_taylor_ is zero, it is set to one.
|
||||
Othwerwise, \c num_direction_taylor_ is not modified.
|
||||
*/
|
||||
|
||||
template <typename Base>
|
||||
void ADFun<Base>::capacity_order(size_t c)
|
||||
{ size_t r;
|
||||
if( (c == 0) | (c == 1) )
|
||||
{ r = c;
|
||||
capacity_order(c, r);
|
||||
return;
|
||||
}
|
||||
r = num_direction_taylor_;
|
||||
if( r == 0 )
|
||||
r = 1;
|
||||
capacity_order(c, r);
|
||||
return;
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
|
||||
# endif
|
||||
+198
@@ -0,0 +1,198 @@
|
||||
# ifndef CPPAD_CORE_CHECK_FOR_NAN_HPP
|
||||
# define CPPAD_CORE_CHECK_FOR_NAN_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 check_for_nan$$
|
||||
$spell
|
||||
std
|
||||
vec
|
||||
Cpp
|
||||
const
|
||||
bool
|
||||
newline
|
||||
$$
|
||||
$section Check an ADFun Object For Nan Results$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.check_for_nan(%b%)
|
||||
%$$
|
||||
$icode%b% = %f%.check_for_nan()
|
||||
%$$
|
||||
$codei%get_check_for_nan(%vec%, %file%)
|
||||
%$$
|
||||
|
||||
$head Debugging$$
|
||||
If $code NDEBUG$$ is not defined, and
|
||||
the result of a $cref/forward/forward_order/$$ or $cref/reverse/reverse_any/$$
|
||||
calculation contains a $cref nan$$,
|
||||
CppAD can halt with an error message.
|
||||
|
||||
$head f$$
|
||||
For the syntax where $icode b$$ is an argument,
|
||||
$icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
(see $codei%ADFun<%Base%>%$$ $cref/constructor/FunConstruct/$$).
|
||||
For the syntax where $icode b$$ is the result,
|
||||
$icode f$$ has prototype
|
||||
$codei%
|
||||
const ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head b$$
|
||||
This argument or result has prototype
|
||||
$codei%
|
||||
bool %b%
|
||||
%$$
|
||||
Future calls to $icode%f%.Forward%$$ will (will not) check for $code nan$$.
|
||||
depending on if $icode b$$ is true (false).
|
||||
|
||||
$head Default$$
|
||||
The value for this setting after construction of $icode f$$) is true.
|
||||
The value of this setting is not affected by calling
|
||||
$cref Dependent$$ for this function object.
|
||||
|
||||
$head Error Message$$
|
||||
If this error is detected during zero order forward mode,
|
||||
the values of the independent variables that resulted in the $code nan$$
|
||||
are written to a temporary binary file.
|
||||
This is so that you can run the original source code with those values
|
||||
to see what is causing the $code nan$$.
|
||||
|
||||
$subhead vector_size$$
|
||||
The error message with contain the text
|
||||
$codei%vector_size = %vector_size%$$ followed the newline character
|
||||
$code '\n'$$.
|
||||
The value of $icode vector_size$$ is the number of elements
|
||||
in the independent vector.
|
||||
|
||||
$subhead file_name$$
|
||||
The error message with contain the text
|
||||
$codei%file_name = %file_name%$$ followed the newline character
|
||||
$code '\n'$$.
|
||||
The value of $icode file_name$$ is the name of the temporary file
|
||||
that contains the dependent variable values.
|
||||
|
||||
$subhead index$$
|
||||
The error message will contain the text
|
||||
$codei%index = %index%$$ followed by the newline character $code '\n'$$.
|
||||
The value of $icode index$$ is the lowest dependent variable index
|
||||
that has the value $code nan$$.
|
||||
|
||||
$head get_check_for_nan$$
|
||||
This routine can be used to get the independent variable
|
||||
values that result in a $code nan$$.
|
||||
|
||||
$subhead vec$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
CppAD::vector<%Base%>& %vec%
|
||||
%$$
|
||||
It size must be equal to the corresponding value of
|
||||
$cref/vector_size/check_for_nan/Error Message/vector_size/$$
|
||||
in the corresponding error message.
|
||||
The input value of its elements does not matter.
|
||||
Upon return, it will contain the values for the independent variables,
|
||||
in the corresponding call to $cref Independent$$,
|
||||
that resulted in the $code nan$$.
|
||||
(Note that the call to $code Independent$$ uses an vector with elements
|
||||
of type $codei%AD<%Base%>%$$ and $icode vec$$ has elements of type
|
||||
$icode Base$$.)
|
||||
|
||||
$subhead file$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
const std::string& %file%
|
||||
%$$
|
||||
It must be the value of
|
||||
$cref/file_name/check_for_nan/Error Message/file_name/$$
|
||||
in the corresponding error message.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/check_for_nan.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref check_for_nan.cpp$$
|
||||
contains an example and test of these operations.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
# include <cppad/utility/vector.hpp>
|
||||
# include <cppad/configure.hpp>
|
||||
# include <fstream>
|
||||
|
||||
# if CPPAD_HAS_MKSTEMP
|
||||
# include <stdlib.h>
|
||||
# include <unistd.h>
|
||||
# else
|
||||
# if CPPAD_HAS_TMPNAM_S
|
||||
# include <stdio.h>
|
||||
# else
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
template <class Base>
|
||||
void put_check_for_nan(const CppAD::vector<Base>& vec, std::string& file_name)
|
||||
{
|
||||
size_t char_size = sizeof(Base) * vec.size();
|
||||
const char* char_ptr = reinterpret_cast<const char*>( vec.data() );
|
||||
# if CPPAD_HAS_MKSTEMP
|
||||
char pattern[] = "/tmp/fileXXXXXX";
|
||||
int fd = mkstemp(pattern);
|
||||
file_name = pattern;
|
||||
write(fd, char_ptr, char_size);
|
||||
close(fd);
|
||||
# else
|
||||
# if CPPAD_HAS_TMPNAM_S
|
||||
std::vector<char> name(L_tmpnam_s);
|
||||
if( tmpnam_s( name.data(), L_tmpnam_s ) != 0 )
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"Cannot create a temporary file name"
|
||||
);
|
||||
}
|
||||
file_name = name.data();
|
||||
# else
|
||||
file_name = tmpnam( CPPAD_NULL );
|
||||
# endif
|
||||
std::fstream file_out(file_name.c_str(), std::ios::out|std::ios::binary );
|
||||
file_out.write(char_ptr, char_size);
|
||||
file_out.close();
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
void get_check_for_nan(CppAD::vector<Base>& vec, const std::string& file_name)
|
||||
{ //
|
||||
size_t n = vec.size();
|
||||
size_t char_size = sizeof(Base) * n;
|
||||
char* char_ptr = reinterpret_cast<char*>( vec.data() );
|
||||
//
|
||||
std::fstream file_in(file_name.c_str(), std::ios::in|std::ios::binary );
|
||||
file_in.read(char_ptr, char_size);
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
# endif
|
||||
+1058
File diff suppressed because it is too large
Load Diff
+415
@@ -0,0 +1,415 @@
|
||||
# ifndef CPPAD_CORE_COMPARE_HPP
|
||||
# define CPPAD_CORE_COMPARE_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 Compare$$
|
||||
$spell
|
||||
cos
|
||||
Op
|
||||
bool
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
|
||||
$section AD Binary Comparison Operators$$
|
||||
$mindex compare < <= > >= == !=$$
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
|
||||
$icode%b% = %x% %Op% %y%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Compares two operands where one of the operands is an
|
||||
$codei%AD<%Base%>%$$ object.
|
||||
The comparison has the same interpretation as for
|
||||
the $icode Base$$ type.
|
||||
|
||||
|
||||
$head Op$$
|
||||
The operator $icode Op$$ is one of the following:
|
||||
$table
|
||||
$bold Op$$ $pre $$ $cnext $bold Meaning$$ $rnext
|
||||
$code <$$ $cnext is $icode x$$ less than $icode y$$ $rnext
|
||||
$code <=$$ $cnext is $icode x$$ less than or equal $icode y$$ $rnext
|
||||
$code >$$ $cnext is $icode x$$ greater than $icode y$$ $rnext
|
||||
$code >=$$ $cnext is $icode x$$ greater than or equal $icode y$$ $rnext
|
||||
$code ==$$ $cnext is $icode x$$ equal to $icode y$$ $rnext
|
||||
$code !=$$ $cnext is $icode x$$ not equal to $icode y$$
|
||||
$tend
|
||||
|
||||
$head x$$
|
||||
The operand $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Type% &%x%
|
||||
%$$
|
||||
where $icode Type$$ is $codei%AD<%Base%>%$$, $icode Base$$, or $code int$$.
|
||||
|
||||
$head y$$
|
||||
The operand $icode y$$ has prototype
|
||||
$codei%
|
||||
const %Type% &%y%
|
||||
%$$
|
||||
where $icode Type$$ is $codei%AD<%Base%>%$$, $icode Base$$, or $code int$$.
|
||||
|
||||
$head b$$
|
||||
The result $icode b$$ has type
|
||||
$codei%
|
||||
bool %b%
|
||||
%$$
|
||||
|
||||
$head Operation Sequence$$
|
||||
The result of this operation is a $code bool$$ value
|
||||
(not an $cref/AD of Base/glossary/AD of Base/$$ object).
|
||||
Thus it will not be recorded as part of an
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
$pre
|
||||
|
||||
$$
|
||||
For example, suppose
|
||||
$icode x$$ and $icode y$$ are $codei%AD<%Base%>%$$ objects,
|
||||
the tape corresponding to $codei%AD<%Base%>%$$ is recording,
|
||||
$icode b$$ is true,
|
||||
and the subsequent code is
|
||||
$codei%
|
||||
if( %b% )
|
||||
%y% = cos(%x%);
|
||||
else %y% = sin(%x%);
|
||||
%$$
|
||||
only the assignment $icode%y% = cos(%x%)%$$ is recorded on the tape
|
||||
(if $icode x$$ is a $cref/parameter/glossary/Parameter/$$,
|
||||
nothing is recorded).
|
||||
The $cref CompareChange$$ function can yield
|
||||
some information about changes in comparison operation results.
|
||||
You can use $cref CondExp$$ to obtain comparison operations
|
||||
that depends on the
|
||||
$cref/independent variable/glossary/Tape/Independent Variable/$$
|
||||
values with out re-taping the AD sequence of operations.
|
||||
|
||||
$head Assumptions$$
|
||||
If one of the $icode Op$$ operators listed above
|
||||
is used with an $codei%AD<%Base%>%$$ object,
|
||||
it is assumed that the same operator is supported by the base type
|
||||
$icode Base$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/compare.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref compare.cpp$$
|
||||
contains an example and test of these operations.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
// -------------------------------- < --------------------------
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool operator < (const AD<Base> &left , const AD<Base> &right)
|
||||
{ bool result = (left.value_ < right.value_);
|
||||
bool var_left = Variable(left);
|
||||
bool var_right = Variable(right);
|
||||
|
||||
local::ADTape<Base> *tape = CPPAD_NULL;
|
||||
if( var_left )
|
||||
{ tape = left.tape_this();
|
||||
if( var_right )
|
||||
{ if( result )
|
||||
{ tape->Rec_.PutOp(local::LtvvOp);
|
||||
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LevvOp);
|
||||
tape->Rec_.PutArg(right.taddr_, left.taddr_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ addr_t arg1 = tape->Rec_.PutPar(right.value_);
|
||||
if( result )
|
||||
{ tape->Rec_.PutOp(local::LtvpOp);
|
||||
tape->Rec_.PutArg(left.taddr_, arg1);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LepvOp);
|
||||
tape->Rec_.PutArg(arg1, left.taddr_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( var_right )
|
||||
{ tape = right.tape_this();
|
||||
addr_t arg0 = tape->Rec_.PutPar(left.value_);
|
||||
if( result )
|
||||
{ tape->Rec_.PutOp(local::LtpvOp);
|
||||
tape->Rec_.PutArg(arg0, right.taddr_);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LevpOp);
|
||||
tape->Rec_.PutArg(right.taddr_, arg0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(<)
|
||||
|
||||
// -------------------------------- <= -------------------------
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool operator <= (const AD<Base> &left , const AD<Base> &right)
|
||||
{ bool result = (left.value_ <= right.value_);
|
||||
bool var_left = Variable(left);
|
||||
bool var_right = Variable(right);
|
||||
|
||||
local::ADTape<Base> *tape = CPPAD_NULL;
|
||||
if( var_left )
|
||||
{ tape = left.tape_this();
|
||||
if( var_right )
|
||||
{ if( result )
|
||||
{ tape->Rec_.PutOp(local::LevvOp);
|
||||
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LtvvOp);
|
||||
tape->Rec_.PutArg(right.taddr_, left.taddr_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ addr_t arg1 = tape->Rec_.PutPar(right.value_);
|
||||
if( result )
|
||||
{ tape->Rec_.PutOp(local::LevpOp);
|
||||
tape->Rec_.PutArg(left.taddr_, arg1);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LtpvOp);
|
||||
tape->Rec_.PutArg(arg1, left.taddr_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( var_right )
|
||||
{ tape = right.tape_this();
|
||||
addr_t arg0 = tape->Rec_.PutPar(left.value_);
|
||||
if( result )
|
||||
{ tape->Rec_.PutOp(local::LepvOp);
|
||||
tape->Rec_.PutArg(arg0, right.taddr_);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LtvpOp);
|
||||
tape->Rec_.PutArg(right.taddr_, arg0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(<=)
|
||||
|
||||
// -------------------------------- > --------------------------
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool operator > (const AD<Base> &left , const AD<Base> &right)
|
||||
{ bool result = (left.value_ > right.value_);
|
||||
bool var_left = Variable(left);
|
||||
bool var_right = Variable(right);
|
||||
|
||||
local::ADTape<Base> *tape = CPPAD_NULL;
|
||||
if( var_left )
|
||||
{ tape = left.tape_this();
|
||||
if( var_right )
|
||||
{ if( result )
|
||||
{ tape->Rec_.PutOp(local::LtvvOp);
|
||||
tape->Rec_.PutArg(right.taddr_, left.taddr_);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LevvOp);
|
||||
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ addr_t arg1 = tape->Rec_.PutPar(right.value_);
|
||||
if( result )
|
||||
{ tape->Rec_.PutOp(local::LtpvOp);
|
||||
tape->Rec_.PutArg(arg1, left.taddr_);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LevpOp);
|
||||
tape->Rec_.PutArg(left.taddr_, arg1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( var_right )
|
||||
{ tape = right.tape_this();
|
||||
addr_t arg0 = tape->Rec_.PutPar(left.value_);
|
||||
if( result )
|
||||
{ tape->Rec_.PutOp(local::LtvpOp);
|
||||
tape->Rec_.PutArg(right.taddr_, arg0);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LepvOp);
|
||||
tape->Rec_.PutArg(arg0, right.taddr_);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(>)
|
||||
|
||||
// -------------------------------- >= -------------------------
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool operator >= (const AD<Base> &left , const AD<Base> &right)
|
||||
{ bool result = (left.value_ >= right.value_);
|
||||
bool var_left = Variable(left);
|
||||
bool var_right = Variable(right);
|
||||
|
||||
local::ADTape<Base> *tape = CPPAD_NULL;
|
||||
if( var_left )
|
||||
{ tape = left.tape_this();
|
||||
if( var_right )
|
||||
{ if( result )
|
||||
{ tape->Rec_.PutOp(local::LevvOp);
|
||||
tape->Rec_.PutArg(right.taddr_, left.taddr_);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LtvvOp);
|
||||
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ addr_t arg1 = tape->Rec_.PutPar(right.value_);
|
||||
if( result )
|
||||
{ tape->Rec_.PutOp(local::LepvOp);
|
||||
tape->Rec_.PutArg(arg1, left.taddr_);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LtvpOp);
|
||||
tape->Rec_.PutArg(left.taddr_, arg1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( var_right )
|
||||
{ tape = right.tape_this();
|
||||
addr_t arg0 = tape->Rec_.PutPar(left.value_);
|
||||
if( result )
|
||||
{ tape->Rec_.PutOp(local::LevpOp);
|
||||
tape->Rec_.PutArg(right.taddr_, arg0);
|
||||
}
|
||||
else
|
||||
{ tape->Rec_.PutOp(local::LtpvOp);
|
||||
tape->Rec_.PutArg(arg0, right.taddr_);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(>=)
|
||||
|
||||
// -------------------------------- == -------------------------
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool operator == (const AD<Base> &left , const AD<Base> &right)
|
||||
{ bool result = (left.value_ == right.value_);
|
||||
bool var_left = Variable(left);
|
||||
bool var_right = Variable(right);
|
||||
|
||||
local::ADTape<Base> *tape = CPPAD_NULL;
|
||||
if( var_left )
|
||||
{ tape = left.tape_this();
|
||||
if( var_right )
|
||||
{ tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
if( result )
|
||||
tape->Rec_.PutOp(local::EqvvOp);
|
||||
else
|
||||
tape->Rec_.PutOp(local::NevvOp);
|
||||
}
|
||||
else
|
||||
{ addr_t arg1 = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(arg1, left.taddr_);
|
||||
if( result )
|
||||
tape->Rec_.PutOp(local::EqpvOp);
|
||||
else
|
||||
tape->Rec_.PutOp(local::NepvOp);
|
||||
}
|
||||
}
|
||||
else if ( var_right )
|
||||
{ tape = right.tape_this();
|
||||
addr_t arg0 = tape->Rec_.PutPar(left.value_);
|
||||
tape->Rec_.PutArg(arg0, right.taddr_);
|
||||
if( result )
|
||||
tape->Rec_.PutOp(local::EqpvOp);
|
||||
else
|
||||
tape->Rec_.PutOp(local::NepvOp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(==)
|
||||
|
||||
// -------------------------------- != -------------------------
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool operator != (const AD<Base> &left , const AD<Base> &right)
|
||||
{ bool result = (left.value_ != right.value_);
|
||||
bool var_left = Variable(left);
|
||||
bool var_right = Variable(right);
|
||||
|
||||
local::ADTape<Base> *tape = CPPAD_NULL;
|
||||
if( var_left )
|
||||
{ tape = left.tape_this();
|
||||
if( var_right )
|
||||
{ tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
if( result )
|
||||
tape->Rec_.PutOp(local::NevvOp);
|
||||
else
|
||||
tape->Rec_.PutOp(local::EqvvOp);
|
||||
}
|
||||
else
|
||||
{ addr_t arg1 = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(arg1, left.taddr_);
|
||||
if( result )
|
||||
tape->Rec_.PutOp(local::NepvOp);
|
||||
else
|
||||
tape->Rec_.PutOp(local::EqpvOp);
|
||||
}
|
||||
}
|
||||
else if ( var_right )
|
||||
{ tape = right.tape_this();
|
||||
addr_t arg0 = tape->Rec_.PutPar(left.value_);
|
||||
tape->Rec_.PutArg(arg0, right.taddr_);
|
||||
if( result )
|
||||
tape->Rec_.PutOp(local::NepvOp);
|
||||
else
|
||||
tape->Rec_.PutOp(local::EqpvOp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(!=)
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,142 @@
|
||||
# ifndef CPPAD_CORE_COMPOUND_ASSIGN_HPP
|
||||
# define CPPAD_CORE_COMPOUND_ASSIGN_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 compound_assign$$
|
||||
$spell
|
||||
Op
|
||||
VecAD
|
||||
const
|
||||
$$
|
||||
|
||||
$section AD Compound Assignment Operators$$
|
||||
$mindex + add plus - subtract minus * multiply times / divide multiple$$
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
$icode%x% %Op% %y%$$
|
||||
|
||||
$head Purpose$$
|
||||
Performs compound assignment operations
|
||||
where either $icode x$$ has type
|
||||
$codei%AD<%Base%>%$$.
|
||||
|
||||
$head Op$$
|
||||
The operator $icode Op$$ is one of the following
|
||||
$table
|
||||
$bold Op$$ $cnext $bold Meaning$$ $rnext
|
||||
$code +=$$ $cnext $icode x$$ is assigned $icode x$$ plus $icode y$$ $rnext
|
||||
$code -=$$ $cnext $icode x$$ is assigned $icode x$$ minus $icode y$$ $rnext
|
||||
$code *=$$ $cnext $icode x$$ is assigned $icode x$$ times $icode y$$ $rnext
|
||||
$code /=$$ $cnext $icode x$$ is assigned $icode x$$ divided by $icode y$$
|
||||
$tend
|
||||
|
||||
$head Base$$
|
||||
The type $icode Base$$ is determined by the operand $icode x$$.
|
||||
|
||||
$head x$$
|
||||
The operand $icode x$$ has the following prototype
|
||||
$codei%
|
||||
AD<%Base%> &%x%
|
||||
%$$
|
||||
|
||||
$head y$$
|
||||
The operand $icode y$$ has the following prototype
|
||||
$codei%
|
||||
const %Type% &%y%
|
||||
%$$
|
||||
where $icode Type$$ is
|
||||
$codei%VecAD<%Base%>::reference%$$,
|
||||
$codei%AD<%Base%>%$$,
|
||||
$icode Base$$, or
|
||||
$code double$$.
|
||||
|
||||
$head Result$$
|
||||
The result of this assignment
|
||||
can be used as a reference to $icode x$$.
|
||||
For example, if $icode z$$ has the following type
|
||||
$codei%
|
||||
AD<%Base%> %z%
|
||||
%$$
|
||||
then the syntax
|
||||
$codei%
|
||||
%z% = %x% += %y%
|
||||
%$$
|
||||
will compute $icode x$$ plus $icode y$$
|
||||
and then assign this value to both $icode x$$ and $icode z$$.
|
||||
|
||||
|
||||
$head Operation Sequence$$
|
||||
This is an $cref/atomic/glossary/Operation/Atomic/$$
|
||||
$cref/AD of Base/glossary/AD of Base/$$ operation
|
||||
and hence it is part of the current
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$children%
|
||||
example/general/add_eq.cpp%
|
||||
example/general/sub_eq.cpp%
|
||||
example/general/mul_eq.cpp%
|
||||
example/general/div_eq.cpp
|
||||
%$$
|
||||
|
||||
$head Example$$
|
||||
The following files contain examples and tests of these functions.
|
||||
Each test returns true if it succeeds and false otherwise.
|
||||
$table
|
||||
$rref AddEq.cpp$$
|
||||
$rref sub_eq.cpp$$
|
||||
$rref mul_eq.cpp$$
|
||||
$rref div_eq.cpp$$
|
||||
$tend
|
||||
|
||||
$head Derivative$$
|
||||
If $latex f$$ and $latex g$$ are
|
||||
$cref/Base functions/glossary/Base Function/$$
|
||||
|
||||
$subhead Addition$$
|
||||
$latex \[
|
||||
\D{[ f(x) + g(x) ]}{x} = \D{f(x)}{x} + \D{g(x)}{x}
|
||||
\] $$
|
||||
|
||||
$subhead Subtraction$$
|
||||
$latex \[
|
||||
\D{[ f(x) - g(x) ]}{x} = \D{f(x)}{x} - \D{g(x)}{x}
|
||||
\] $$
|
||||
|
||||
$subhead Multiplication$$
|
||||
$latex \[
|
||||
\D{[ f(x) * g(x) ]}{x} = g(x) * \D{f(x)}{x} + f(x) * \D{g(x)}{x}
|
||||
\] $$
|
||||
|
||||
$subhead Division$$
|
||||
$latex \[
|
||||
\D{[ f(x) / g(x) ]}{x} =
|
||||
[1/g(x)] * \D{f(x)}{x} - [f(x)/g(x)^2] * \D{g(x)}{x}
|
||||
\] $$
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/core/add_eq.hpp>
|
||||
# include <cppad/core/sub_eq.hpp>
|
||||
# include <cppad/core/mul_eq.hpp>
|
||||
# include <cppad/core/div_eq.hpp>
|
||||
|
||||
# endif
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
# ifndef CPPAD_CORE_COND_EXP_HPP
|
||||
# define CPPAD_CORE_COND_EXP_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 CondExp$$
|
||||
$spell
|
||||
Atan2
|
||||
CondExp
|
||||
Taylor
|
||||
std
|
||||
Cpp
|
||||
namespace
|
||||
inline
|
||||
const
|
||||
abs
|
||||
Rel
|
||||
bool
|
||||
Lt
|
||||
Le
|
||||
Eq
|
||||
Ge
|
||||
Gt
|
||||
$$
|
||||
|
||||
|
||||
$section AD Conditional Expressions$$
|
||||
$mindex assign$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%result% = CondExp%Rel%(%left%, %right%, %if_true%, %if_false%)%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Record,
|
||||
as part of an AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$,
|
||||
the conditional result
|
||||
$codei%
|
||||
if( %left% %Cop% %right% )
|
||||
%result% = %if_true%
|
||||
else %result% = %if_false%
|
||||
%$$
|
||||
The relational $icode Rel$$ and comparison operator $icode Cop$$
|
||||
above have the following correspondence:
|
||||
$codei%
|
||||
%Rel% Lt Le Eq Ge Gt
|
||||
%Cop% < <= == >= >
|
||||
%$$
|
||||
If $icode f$$ is the $cref ADFun$$ object corresponding to the
|
||||
AD operation sequence,
|
||||
the assignment choice for $icode result$$
|
||||
in an AD conditional expression is made each time
|
||||
$cref/f.Forward/Forward/$$ is used to evaluate the zero order Taylor
|
||||
coefficients with new values for the
|
||||
$cref/independent variables/glossary/Tape/Independent Variable/$$.
|
||||
This is in contrast to the $cref/AD comparison operators/Compare/$$
|
||||
which are boolean valued and not included in the AD operation sequence.
|
||||
|
||||
$head Rel$$
|
||||
In the syntax above, the relation $icode Rel$$ represents one of the following
|
||||
two characters: $code Lt$$, $code Le$$, $code Eq$$, $code Ge$$, $code Gt$$.
|
||||
As in the table above,
|
||||
$icode Rel$$ determines which comparison operator $icode Cop$$ is used
|
||||
when comparing $icode left$$ and $icode right$$.
|
||||
|
||||
$head Type$$
|
||||
These functions are defined in the CppAD namespace for arguments of
|
||||
$icode Type$$ is $code float$$ , $code double$$, or any type of the form
|
||||
$codei%AD<%Base%>%$$.
|
||||
(Note that all four arguments must have the same type.)
|
||||
|
||||
$head left$$
|
||||
The argument $icode left$$ has prototype
|
||||
$codei%
|
||||
const %Type%& %left%
|
||||
%$$
|
||||
It specifies the value for the left side of the comparison operator.
|
||||
|
||||
$head right$$
|
||||
The argument $icode right$$ has prototype
|
||||
$codei%
|
||||
const %Type%& %right%
|
||||
%$$
|
||||
It specifies the value for the right side of the comparison operator.
|
||||
|
||||
$head if_true$$
|
||||
The argument $icode if_true$$ has prototype
|
||||
$codei%
|
||||
const %Type%& %if_true%
|
||||
%$$
|
||||
It specifies the return value if the result of the comparison is true.
|
||||
|
||||
$head if_false$$
|
||||
The argument $icode if_false$$ has prototype
|
||||
$codei%
|
||||
const %Type%& %if_false%
|
||||
%$$
|
||||
It specifies the return value if the result of the comparison is false.
|
||||
|
||||
$head result$$
|
||||
The $icode result$$ has prototype
|
||||
$codei%
|
||||
%Type%& %if_false%
|
||||
%$$
|
||||
|
||||
$head Optimize$$
|
||||
The $cref optimize$$ method will optimize conditional expressions
|
||||
in the following way:
|
||||
During $cref/zero order forward mode/forward_zero/$$,
|
||||
once the value of the $icode left$$ and $icode right$$ have been determined,
|
||||
it is known if the true or false case is required.
|
||||
From this point on, values corresponding to the case that is not required
|
||||
are not computed.
|
||||
This optimization is done for the rest of zero order forward mode
|
||||
as well as forward and reverse derivatives calculations.
|
||||
|
||||
$head Deprecate 2005-08-07$$
|
||||
Previous versions of CppAD used
|
||||
$codei%
|
||||
CondExp(%flag%, %if_true%, %if_false%)
|
||||
%$$
|
||||
for the same meaning as
|
||||
$codei%
|
||||
CondExpGt(%flag%, %Type%(0), %if_true%, %if_false%)
|
||||
%$$
|
||||
Use of $code CondExp$$ is deprecated, but continues to be supported.
|
||||
|
||||
$head Operation Sequence$$
|
||||
This is an AD of $icode Base$$
|
||||
$cref/atomic operation/glossary/Operation/Atomic/$$
|
||||
and hence is part of the current
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
|
||||
$head Example$$
|
||||
|
||||
$head Test$$
|
||||
$children%
|
||||
example/general/cond_exp.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref cond_exp.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$head Atan2$$
|
||||
The following implementation of the
|
||||
AD $cref atan2$$ function is a more complex
|
||||
example of using conditional expressions:
|
||||
$code
|
||||
$srcfile%cppad/core/atan2.hpp%0%BEGIN CondExp%// END CondExp%$$
|
||||
$$
|
||||
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
AD<Base> CondExpOp(
|
||||
enum CompareOp cop ,
|
||||
const AD<Base> &left ,
|
||||
const AD<Base> &right ,
|
||||
const AD<Base> &if_true ,
|
||||
const AD<Base> &if_false )
|
||||
{
|
||||
AD<Base> returnValue;
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(returnValue) );
|
||||
|
||||
// check first case where do not need to tape
|
||||
if( IdenticalPar(left) & IdenticalPar(right) )
|
||||
{ switch( cop )
|
||||
{
|
||||
case CompareLt:
|
||||
if( left.value_ < right.value_ )
|
||||
returnValue = if_true;
|
||||
else returnValue = if_false;
|
||||
break;
|
||||
|
||||
case CompareLe:
|
||||
if( left.value_ <= right.value_ )
|
||||
returnValue = if_true;
|
||||
else returnValue = if_false;
|
||||
break;
|
||||
|
||||
case CompareEq:
|
||||
if( left.value_ == right.value_ )
|
||||
returnValue = if_true;
|
||||
else returnValue = if_false;
|
||||
break;
|
||||
|
||||
case CompareGe:
|
||||
if( left.value_ >= right.value_ )
|
||||
returnValue = if_true;
|
||||
else returnValue = if_false;
|
||||
break;
|
||||
|
||||
case CompareGt:
|
||||
if( left.value_ > right.value_ )
|
||||
returnValue = if_true;
|
||||
else returnValue = if_false;
|
||||
break;
|
||||
|
||||
default:
|
||||
CPPAD_ASSERT_UNKNOWN(0);
|
||||
returnValue = if_true;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
// must use CondExp incase Base is an AD type and recording
|
||||
returnValue.value_ = CondExpOp(cop,
|
||||
left.value_, right.value_, if_true.value_, if_false.value_);
|
||||
|
||||
local::ADTape<Base> *tape = CPPAD_NULL;
|
||||
if( Variable(left) )
|
||||
tape = left.tape_this();
|
||||
if( Variable(right) )
|
||||
tape = right.tape_this();
|
||||
if( Variable(if_true) )
|
||||
tape = if_true.tape_this();
|
||||
if( Variable(if_false) )
|
||||
tape = if_false.tape_this();
|
||||
|
||||
// add this operation to the tape
|
||||
if( tape != CPPAD_NULL )
|
||||
tape->RecordCondExp(cop,
|
||||
returnValue, left, right, if_true, if_false);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
// --- RecordCondExp(cop, returnValue, left, right, if_true, if_false) -----
|
||||
|
||||
/// All these operations are done in \c Rec_, so we should move this
|
||||
/// routine to <tt>recorder<Base></tt>.
|
||||
template <class Base>
|
||||
void local::ADTape<Base>::RecordCondExp(
|
||||
enum CompareOp cop ,
|
||||
AD<Base> &returnValue ,
|
||||
const AD<Base> &left ,
|
||||
const AD<Base> &right ,
|
||||
const AD<Base> &if_true ,
|
||||
const AD<Base> &if_false )
|
||||
{ addr_t ind0, ind1, ind2, ind3, ind4, ind5;
|
||||
addr_t returnValue_taddr;
|
||||
|
||||
// taddr_ of this variable
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(CExpOp) == 1 );
|
||||
returnValue_taddr = Rec_.PutOp(CExpOp);
|
||||
|
||||
// ind[0] = cop
|
||||
ind0 = addr_t( cop );
|
||||
|
||||
// ind[1] = base 2 represenation of the value
|
||||
// [Var(left), Var(right), Var(if_true), Var(if_false)]
|
||||
ind1 = 0;
|
||||
|
||||
// Make sure returnValue is in the list of variables and set its taddr
|
||||
if( Parameter(returnValue) )
|
||||
returnValue.make_variable(id_, returnValue_taddr );
|
||||
else returnValue.taddr_ = returnValue_taddr;
|
||||
|
||||
// ind[2] = left address
|
||||
if( Parameter(left) )
|
||||
ind2 = Rec_.PutPar(left.value_);
|
||||
else
|
||||
{ ind1 += 1;
|
||||
ind2 = left.taddr_;
|
||||
}
|
||||
|
||||
// ind[3] = right address
|
||||
if( Parameter(right) )
|
||||
ind3 = Rec_.PutPar(right.value_);
|
||||
else
|
||||
{ ind1 += 2;
|
||||
ind3 = right.taddr_;
|
||||
}
|
||||
|
||||
// ind[4] = if_true address
|
||||
if( Parameter(if_true) )
|
||||
ind4 = Rec_.PutPar(if_true.value_);
|
||||
else
|
||||
{ ind1 += 4;
|
||||
ind4 = if_true.taddr_;
|
||||
}
|
||||
|
||||
// ind[5] = if_false address
|
||||
if( Parameter(if_false) )
|
||||
ind5 = Rec_.PutPar(if_false.value_);
|
||||
else
|
||||
{ ind1 += 8;
|
||||
ind5 = if_false.taddr_;
|
||||
}
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(CExpOp) == 6 );
|
||||
CPPAD_ASSERT_UNKNOWN( ind1 > 0 );
|
||||
Rec_.PutArg(ind0, ind1, ind2, ind3, ind4, ind5);
|
||||
|
||||
// check that returnValue is a dependent variable
|
||||
CPPAD_ASSERT_UNKNOWN( Variable(returnValue) );
|
||||
}
|
||||
|
||||
// ------------ CondExpOp(left, right, if_true, if_false) ----------------
|
||||
|
||||
# define CPPAD_COND_EXP(Name) \
|
||||
template <class Base> \
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION \
|
||||
AD<Base> CondExp##Name( \
|
||||
const AD<Base> &left , \
|
||||
const AD<Base> &right , \
|
||||
const AD<Base> &if_true , \
|
||||
const AD<Base> &if_false ) \
|
||||
{ \
|
||||
return CondExpOp(Compare##Name, \
|
||||
left, right, if_true, if_false); \
|
||||
}
|
||||
|
||||
// AD<Base>
|
||||
CPPAD_COND_EXP(Lt)
|
||||
CPPAD_COND_EXP(Le)
|
||||
CPPAD_COND_EXP(Eq)
|
||||
CPPAD_COND_EXP(Ge)
|
||||
CPPAD_COND_EXP(Gt)
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
AD<Base> CondExp(
|
||||
const AD<Base> &flag ,
|
||||
const AD<Base> &if_true ,
|
||||
const AD<Base> &if_false )
|
||||
{
|
||||
return CondExpOp(CompareGt, flag, AD<Base>(0), if_true, if_false);
|
||||
}
|
||||
|
||||
# undef CPPAD_COND_EXP
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_CONVERT_HPP
|
||||
# define CPPAD_CORE_CONVERT_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 Convert$$
|
||||
$spell
|
||||
$$
|
||||
|
||||
|
||||
$section Conversion and I/O of AD Objects$$
|
||||
$mindex convert from$$
|
||||
|
||||
$children%
|
||||
cppad/core/value.hpp%
|
||||
cppad/core/integer.hpp%
|
||||
cppad/core/ad_to_string.hpp%
|
||||
cppad/core/ad_io.hpp%
|
||||
cppad/core/print_for.hpp%
|
||||
cppad/core/var2par.hpp
|
||||
%$$
|
||||
$table
|
||||
$rref Value$$
|
||||
$rref Integer$$
|
||||
$rref ad_output$$
|
||||
$rref PrintFor$$
|
||||
$rref Var2Par$$
|
||||
$tend
|
||||
|
||||
|
||||
$end
|
||||
*/
|
||||
|
||||
# include <cppad/core/value.hpp>
|
||||
# include <cppad/core/integer.hpp>
|
||||
# include <cppad/core/ad_to_string.hpp>
|
||||
# include <cppad/core/ad_io.hpp>
|
||||
# include <cppad/core/print_for.hpp>
|
||||
# include <cppad/core/var2par.hpp>
|
||||
|
||||
# endif
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_CPPAD_ASSERT_HPP
|
||||
# define CPPAD_CORE_CPPAD_ASSERT_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
/*!
|
||||
\file cppad_assert.hpp
|
||||
Define the CppAD error checking macros (all of which begin with CPPAD_ASSERT_)
|
||||
*/
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
$begin cppad_assert$$
|
||||
$spell
|
||||
CppAD
|
||||
exp
|
||||
const
|
||||
bool
|
||||
$$
|
||||
|
||||
|
||||
$section CppAD Assertions During Execution$$
|
||||
$mindex assert macro CPPAD_ASSERT_KNOWN CPPAD_ASSERT_UNKNOWN$$
|
||||
|
||||
$head Syntax$$
|
||||
$codei%CPPAD_ASSERT_KNOWN(%exp%, %msg%)
|
||||
%$$
|
||||
$codei%CPPAD_ASSERT_UNKNOWN(%exp%)%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
These CppAD macros are used to detect and report errors.
|
||||
They are documented here because they correspond to the C++
|
||||
source code that the error is reported at.
|
||||
|
||||
$head NDEBUG$$
|
||||
If the preprocessor symbol
|
||||
$cref/NDEBUG/Faq/Speed/NDEBUG/$$ is defined,
|
||||
these macros do nothing; i.e., they are optimized out.
|
||||
|
||||
$head Restriction$$
|
||||
The CppAD user should not uses these macros.
|
||||
You can however write your own macros that do not begin with $code CPPAD$$
|
||||
and that call the $cref/CppAD error handler/ErrorHandler/$$.
|
||||
|
||||
$head Known$$
|
||||
The $code CPPAD_ASSERT_KNOWN$$ macro is used to check for an error
|
||||
with a known cause.
|
||||
For example, many CppAD routines uses these macros
|
||||
to make sure their arguments conform to their specifications.
|
||||
|
||||
$head Unknown$$
|
||||
The $code CPPAD_ASSERT_UNKNOWN$$ macro is used to check that the
|
||||
CppAD internal data structures conform as expected.
|
||||
If this is not the case, CppAD does not know why the error has
|
||||
occurred; for example, the user may have written past the end
|
||||
of an allocated array.
|
||||
|
||||
$head Exp$$
|
||||
The argument $icode exp$$ is a C++ source code expression
|
||||
that results in a $code bool$$ value that should be true.
|
||||
If it is false, an error has occurred.
|
||||
This expression may be execute any number of times
|
||||
(including zero times) so it must have not side effects.
|
||||
|
||||
$head Msg$$
|
||||
The argument $icode msg$$ has prototype
|
||||
$codei%
|
||||
const char *%msg%
|
||||
%$$
|
||||
and contains a $code '\0'$$ terminated character string.
|
||||
This string is a description of the error
|
||||
corresponding to $icode exp$$ being false.
|
||||
|
||||
$head Error Handler$$
|
||||
These macros use the
|
||||
$cref/CppAD error handler/ErrorHandler/$$ to report errors.
|
||||
This error handler can be replaced by the user.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
# include <cassert>
|
||||
# include <iostream>
|
||||
# include <cppad/utility/error_handler.hpp>
|
||||
|
||||
/*!
|
||||
\def CPPAD_ASSERT_KNOWN(exp, msg)
|
||||
Check that \a exp is true, if not print \a msg and terminate execution.
|
||||
|
||||
The C++ expression \a exp is expected to be true.
|
||||
If it is false,
|
||||
the CppAD use has made an error that is described by \a msg.
|
||||
If the preprocessor symbol \a NDEBUG is not defined,
|
||||
and \a exp is false,
|
||||
this macro will report the source code line number at
|
||||
which this expected result occurred.
|
||||
In addition, it will print the specified error message \a msg.
|
||||
*/
|
||||
# ifdef NDEBUG
|
||||
# define CPPAD_ASSERT_KNOWN(exp, msg) // do nothing
|
||||
# else
|
||||
# define CPPAD_ASSERT_KNOWN(exp, msg) \
|
||||
{ if( ! ( exp ) ) \
|
||||
CppAD::ErrorHandler::Call( \
|
||||
true , \
|
||||
__LINE__ , \
|
||||
__FILE__ , \
|
||||
#exp , \
|
||||
msg ); \
|
||||
}
|
||||
# endif
|
||||
|
||||
/*!
|
||||
\def CPPAD_ASSERT_UNKNOWN(exp)
|
||||
Check that \a exp is true, if not terminate execution.
|
||||
|
||||
The C++ expression \a exp is expected to be true.
|
||||
If it is false,
|
||||
CppAD has detected an error but does not know the cause of the error.
|
||||
If the preprocessor symbol \a NDEBUG is not defined,
|
||||
and \a exp is false,
|
||||
this macro will report the source code line number at
|
||||
which this expected result occurred.
|
||||
*/
|
||||
# ifdef NDEBUG
|
||||
# define CPPAD_ASSERT_UNKNOWN(exp) // do nothing
|
||||
# else
|
||||
# define CPPAD_ASSERT_UNKNOWN(exp) \
|
||||
{ if( ! ( exp ) ) \
|
||||
CppAD::ErrorHandler::Call( \
|
||||
false , \
|
||||
__LINE__ , \
|
||||
__FILE__ , \
|
||||
#exp , \
|
||||
"" ); \
|
||||
}
|
||||
# endif
|
||||
|
||||
/*!
|
||||
\def CPPAD_ASSERT_NARG_NRES(op, n_arg, n_res)
|
||||
Check that operator \a op has the specified number of of arguments and results.
|
||||
|
||||
If \a NDEBUG is not defined and either the number of arguments
|
||||
or the number of results are not as expected,
|
||||
execution is terminated and the source code line number is reported.
|
||||
*/
|
||||
# define CPPAD_ASSERT_NARG_NRES(op, n_arg, n_res) \
|
||||
CPPAD_ASSERT_UNKNOWN( NumArg(op) == n_arg ) \
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == n_res )
|
||||
|
||||
/*!
|
||||
\def CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
|
||||
Check that the first call to a routine is not during parallel execution mode.
|
||||
|
||||
If \c NDEBUG is defined, this macro has no effect
|
||||
(not even the definition of (\c assert_first_call).
|
||||
Otherwise, the variable
|
||||
\code
|
||||
static bool assert_first_call
|
||||
\endcode
|
||||
is defined and if the first call is executed in parallel mode,
|
||||
execution is terminated and the source code line number is reported.
|
||||
*/
|
||||
# ifdef NDEBUG
|
||||
# define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
|
||||
# else
|
||||
# define CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL \
|
||||
static bool assert_first_call = true; \
|
||||
if( assert_first_call ) \
|
||||
{ CPPAD_ASSERT_KNOWN( \
|
||||
! (CppAD::thread_alloc::in_parallel() ), \
|
||||
"In parallel mode and parallel_setup has not been called." \
|
||||
); \
|
||||
assert_first_call = false; \
|
||||
}
|
||||
# endif
|
||||
|
||||
/*!
|
||||
\def CPPAD_ASSERT_ARG_BEFORE_RESULT
|
||||
Check that operator arguments come before result.
|
||||
|
||||
If \c NDEBUG is defined, this macro has no effect,
|
||||
otherwise it calls the function assert_arg_before_result.
|
||||
*/
|
||||
# ifdef NDEBUG
|
||||
# define CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, result)
|
||||
# else
|
||||
# define CPPAD_ASSERT_ARG_BEFORE_RESULT(op, arg, result) \
|
||||
assert_arg_before_result(op, arg, result)
|
||||
|
||||
# endif
|
||||
|
||||
# endif
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_DEFINE_HPP
|
||||
# define CPPAD_CORE_DEFINE_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
/*!
|
||||
\file define.hpp
|
||||
Define processor symbols and macros that are used by CppAD.
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/*!
|
||||
\def CPPAD_OP_CODE_TYPE
|
||||
Is the type used to store enum OpCode values. If not the same as OpCode, then
|
||||
<code>sizeof(CPPAD_OP_CODE_TYPE) <= sizeof( enum OpCode )</code>
|
||||
to conserve memory.
|
||||
This type must support \c std::numeric_limits,
|
||||
the \c <= operator,
|
||||
and conversion to \c size_t.
|
||||
Make sure that the type chosen returns true for is_pod<CPPAD_OP_CODE_TYPE>
|
||||
in pod_vector.hpp.
|
||||
*/
|
||||
# define CPPAD_OP_CODE_TYPE unsigned char
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/*!
|
||||
\def CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
A version of the inline command that works with MC compiler.
|
||||
|
||||
Microsoft Visual C++ version 9.0 generates a warning if a template
|
||||
function is declared as a friend
|
||||
(this was not a problem for version 7.0).
|
||||
The warning identifier is
|
||||
\verbatim
|
||||
warning C4396
|
||||
\endverbatim
|
||||
and it contains the text
|
||||
\verbatim
|
||||
the inline specifier cannot be used when a friend declaration refers
|
||||
to a specialization of a function template
|
||||
\endverbatim
|
||||
This happens even if the function is not a specialization.
|
||||
This macro is defined as empty for Microsoft compilers.
|
||||
*/
|
||||
# ifdef _MSC_VER
|
||||
# define CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
# else
|
||||
# define CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION inline
|
||||
# endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/*!
|
||||
\def CPPAD_LIB_EXPORT
|
||||
Special macro for exporting windows DLL symbols; see
|
||||
https://cmake.org/Wiki/BuildingWinDLL
|
||||
*/
|
||||
# ifdef _MSC_VER
|
||||
# ifdef cppad_lib_EXPORTS
|
||||
# define CPPAD_LIB_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define CPPAD_LIB_EXPORT __declspec(dllimport)
|
||||
# endif // cppad_lib_EXPORTS
|
||||
# else // _MSC_VER
|
||||
# define CPPAD_LIB_EXPORT
|
||||
# endif
|
||||
|
||||
|
||||
// ============================================================================
|
||||
/*!
|
||||
\def CPPAD_FOLD_ASSIGNMENT_OPERATOR(Op)
|
||||
Declares automatic coercion for certain AD assignment operations.
|
||||
|
||||
This macro assumes that the operator
|
||||
\verbatim
|
||||
left Op right
|
||||
\endverbatim
|
||||
is defined for the case where left and right have type AD<Base>.
|
||||
It uses this case to define the cases where
|
||||
left has type AD<Base> and right has type
|
||||
VecAD_reference<Base>,
|
||||
Base, or
|
||||
double.
|
||||
The argument right is const and call by reference.
|
||||
This macro converts the operands to AD<Base> and then
|
||||
uses the definition of the same operation for that case.
|
||||
*/
|
||||
|
||||
# define CPPAD_FOLD_ASSIGNMENT_OPERATOR(Op) \
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
template <class Base> \
|
||||
inline AD<Base>& operator Op \
|
||||
(AD<Base> &left, double right) \
|
||||
{ return left Op AD<Base>(right); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base>& operator Op \
|
||||
(AD<Base> &left, const Base &right) \
|
||||
{ return left Op AD<Base>(right); } \
|
||||
\
|
||||
inline AD<double>& operator Op \
|
||||
(AD<double> &left, const double &right) \
|
||||
{ return left Op AD<double>(right); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base>& operator Op \
|
||||
(AD<Base> &left, const VecAD_reference<Base> &right) \
|
||||
{ return left Op right.ADBase(); }
|
||||
|
||||
// =====================================================================
|
||||
/*!
|
||||
\def CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op)
|
||||
Declares automatic coercion for certain binary operations with AD result.
|
||||
|
||||
This macro assumes that the operator
|
||||
\verbatim
|
||||
left Op right
|
||||
\endverbatim
|
||||
is defined for the case where left and right
|
||||
and the result of the operation all
|
||||
have type AD<Base>.
|
||||
It uses this case to define the cases either left
|
||||
or right has type VecAD_reference<Base> or AD<Base>
|
||||
and the type of the other operand is one of the following:
|
||||
VecAD_reference<Base>, AD<Base>, Base, double.
|
||||
All of the arguments are const and call by reference.
|
||||
This macro converts the operands to AD<Base> and then
|
||||
uses the definition of the same operation for that case.
|
||||
*/
|
||||
# define CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op) \
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
/* Operations with VecAD_reference<Base> and AD<Base> only*/ \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const AD<Base> &left, const VecAD_reference<Base> &right) \
|
||||
{ return left Op right.ADBase(); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const VecAD_reference<Base> &left, const VecAD_reference<Base> &right)\
|
||||
{ return left.ADBase() Op right.ADBase(); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const VecAD_reference<Base> &left, const AD<Base> &right) \
|
||||
{ return left.ADBase() Op right; } \
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
/* Operations Base */ \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const Base &left, const AD<Base> &right) \
|
||||
{ return AD<Base>(left) Op right; } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const Base &left, const VecAD_reference<Base> &right) \
|
||||
{ return AD<Base>(left) Op right.ADBase(); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const AD<Base> &left, const Base &right) \
|
||||
{ return left Op AD<Base>(right); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const VecAD_reference<Base> &left, const Base &right) \
|
||||
{ return left.ADBase() Op AD<Base>(right); } \
|
||||
\
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
/* Operations double */ \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const double &left, const AD<Base> &right) \
|
||||
{ return AD<Base>(left) Op right; } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const double &left, const VecAD_reference<Base> &right) \
|
||||
{ return AD<Base>(left) Op right.ADBase(); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const AD<Base> &left, const double &right) \
|
||||
{ return left Op AD<Base>(right); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline AD<Base> operator Op \
|
||||
(const VecAD_reference<Base> &left, const double &right) \
|
||||
{ return left.ADBase() Op AD<Base>(right); } \
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
/* Special case to avoid ambuigity when Base is double */ \
|
||||
\
|
||||
inline AD<double> operator Op \
|
||||
(const double &left, const AD<double> &right) \
|
||||
{ return AD<double>(left) Op right; } \
|
||||
\
|
||||
inline AD<double> operator Op \
|
||||
(const double &left, const VecAD_reference<double> &right) \
|
||||
{ return AD<double>(left) Op right.ADBase(); } \
|
||||
\
|
||||
inline AD<double> operator Op \
|
||||
(const AD<double> &left, const double &right) \
|
||||
{ return left Op AD<double>(right); } \
|
||||
\
|
||||
inline AD<double> operator Op \
|
||||
(const VecAD_reference<double> &left, const double &right) \
|
||||
{ return left.ADBase() Op AD<double>(right); }
|
||||
|
||||
// =======================================================================
|
||||
|
||||
/*!
|
||||
\def CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(Op)
|
||||
Declares automatic coercion for certain binary operations with bool result.
|
||||
|
||||
This macro assumes that the operator
|
||||
\verbatim
|
||||
left Op right
|
||||
\endverbatim
|
||||
is defined for the case where left and right
|
||||
have type AD<Base> and the result has type bool.
|
||||
It uses this case to define the cases either left
|
||||
or right has type
|
||||
VecAD_reference<Base> or AD<Base>
|
||||
and the type of the other operand is one of the following:
|
||||
VecAD_reference<Base>, AD<Base>, Base, double.
|
||||
All of the arguments are const and call by reference.
|
||||
This macro converts the operands to AD<Base> and then
|
||||
uses the definition of the same operation for that case.
|
||||
*/
|
||||
# define CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(Op) \
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
/* Operations with VecAD_reference<Base> and AD<Base> only*/ \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const AD<Base> &left, const VecAD_reference<Base> &right) \
|
||||
{ return left Op right.ADBase(); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const VecAD_reference<Base> &left, const VecAD_reference<Base> &right)\
|
||||
{ return left.ADBase() Op right.ADBase(); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const VecAD_reference<Base> &left, const AD<Base> &right) \
|
||||
{ return left.ADBase() Op right; } \
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
/* Operations Base */ \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const Base &left, const AD<Base> &right) \
|
||||
{ return AD<Base>(left) Op right; } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const Base &left, const VecAD_reference<Base> &right) \
|
||||
{ return AD<Base>(left) Op right.ADBase(); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const AD<Base> &left, const Base &right) \
|
||||
{ return left Op AD<Base>(right); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const VecAD_reference<Base> &left, const Base &right) \
|
||||
{ return left.ADBase() Op AD<Base>(right); } \
|
||||
\
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
/* Operations double */ \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const double &left, const AD<Base> &right) \
|
||||
{ return AD<Base>(left) Op right; } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const double &left, const VecAD_reference<Base> &right) \
|
||||
{ return AD<Base>(left) Op right.ADBase(); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const AD<Base> &left, const double &right) \
|
||||
{ return left Op AD<Base>(right); } \
|
||||
\
|
||||
template <class Base> \
|
||||
inline bool operator Op \
|
||||
(const VecAD_reference<Base> &left, const double &right) \
|
||||
{ return left.ADBase() Op AD<Base>(right); } \
|
||||
/* ----------------------------------------------------------------*/ \
|
||||
/* Special case to avoid ambuigity when Base is double */ \
|
||||
\
|
||||
inline bool operator Op \
|
||||
(const double &left, const AD<double> &right) \
|
||||
{ return AD<double>(left) Op right; } \
|
||||
\
|
||||
inline bool operator Op \
|
||||
(const double &left, const VecAD_reference<double> &right) \
|
||||
{ return AD<double>(left) Op right.ADBase(); } \
|
||||
\
|
||||
inline bool operator Op \
|
||||
(const AD<double> &left, const double &right) \
|
||||
{ return left Op AD<double>(right); } \
|
||||
\
|
||||
inline bool operator Op \
|
||||
(const VecAD_reference<double> &left, const double &right) \
|
||||
{ return left.ADBase() Op AD<double>(right); }
|
||||
|
||||
# endif
|
||||
+332
@@ -0,0 +1,332 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_DEPENDENT_HPP
|
||||
# define CPPAD_CORE_DEPENDENT_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 Dependent$$
|
||||
$spell
|
||||
alloc
|
||||
num
|
||||
taylor_
|
||||
ADvector
|
||||
const
|
||||
$$
|
||||
|
||||
$spell
|
||||
$$
|
||||
|
||||
$section Stop Recording and Store Operation Sequence$$
|
||||
$mindex ADFun tape Dependent$$
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.Dependent(%x%, %y%)%$$
|
||||
|
||||
$head Purpose$$
|
||||
Stop recording and the AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$
|
||||
that started with the call
|
||||
$codei%
|
||||
Independent(%x%)
|
||||
%$$
|
||||
and store the operation sequence in $icode f$$.
|
||||
The operation sequence defines an
|
||||
$cref/AD function/glossary/AD Function/$$
|
||||
$latex \[
|
||||
F : B^n \rightarrow B^m
|
||||
\] $$
|
||||
where $latex B$$ is the space corresponding to objects of type $icode Base$$.
|
||||
The value $latex n$$ is the dimension of the
|
||||
$cref/domain/seq_property/Domain/$$ space for the operation sequence.
|
||||
The value $latex m$$ is the dimension of the
|
||||
$cref/range/seq_property/Range/$$ space for the operation sequence
|
||||
(which is determined by the size of $icode y$$).
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
The AD of $icode Base$$ operation sequence is stored in $icode f$$; i.e.,
|
||||
it becomes the operation sequence corresponding to $icode f$$.
|
||||
If a previous operation sequence was stored in $icode f$$,
|
||||
it is deleted.
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$
|
||||
must be the vector argument in a previous call to
|
||||
$cref Independent$$.
|
||||
Neither its size, or any of its values, are allowed to change
|
||||
between calling
|
||||
$codei%
|
||||
Independent(%x%)
|
||||
%$$
|
||||
and
|
||||
$codei%
|
||||
%f%.Dependent(%x%, %y%)
|
||||
%$$.
|
||||
|
||||
$head y$$
|
||||
The vector $icode y$$ has prototype
|
||||
$codei%
|
||||
const %ADvector% &%y%
|
||||
%$$
|
||||
(see $cref/ADvector/FunConstruct/$$ below).
|
||||
The length of $icode y$$ must be greater than zero
|
||||
and is the dimension of the range space for $icode f$$.
|
||||
|
||||
$head ADvector$$
|
||||
The type $icode ADvector$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$codei%AD<%Base%>%$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head Taping$$
|
||||
The tape,
|
||||
that was created when $codei%Independent(%x%)%$$ was called,
|
||||
will stop recording.
|
||||
The AD operation sequence will be transferred from
|
||||
the tape to the object $icode f$$ and the tape will then be deleted.
|
||||
|
||||
$head Forward$$
|
||||
No $cref Forward$$ calculation is preformed during this operation.
|
||||
Thus, directly after this operation,
|
||||
$codei%
|
||||
%f%.size_order()
|
||||
%$$
|
||||
is zero (see $cref size_order$$).
|
||||
|
||||
$head Parallel Mode$$
|
||||
The call to $code Independent$$,
|
||||
and the corresponding call to
|
||||
$codei%
|
||||
ADFun<%Base%> %f%( %x%, %y%)
|
||||
%$$
|
||||
or
|
||||
$codei%
|
||||
%f%.Dependent( %x%, %y%)
|
||||
%$$
|
||||
or $cref abort_recording$$,
|
||||
must be preformed by the same thread; i.e.,
|
||||
$cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same.
|
||||
|
||||
$head Example$$
|
||||
The file
|
||||
$cref fun_check.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
/*!
|
||||
\file dependent.hpp
|
||||
Different versions of Dependent function.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Determine the \c tape corresponding to this exeuction thread and then use
|
||||
<code>Dependent(tape, y)</code> to store this tapes recording in a function.
|
||||
|
||||
\param y [in]
|
||||
The dependent variable vector for the corresponding function.
|
||||
*/
|
||||
template <typename Base>
|
||||
template <typename ADvector>
|
||||
void ADFun<Base>::Dependent(const ADvector &y)
|
||||
{ local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
tape != CPPAD_NULL,
|
||||
"Can't store current operation sequence in this ADFun object"
|
||||
"\nbecause there is no active tape (for this thread)."
|
||||
);
|
||||
|
||||
// code above just determines the tape and checks for errors
|
||||
Dependent(tape, y);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Determine the \c tape corresponding to this exeuction thread and then use
|
||||
<code>Dependent(tape, y)</code> to store this tapes recording in a function.
|
||||
|
||||
\param x [in]
|
||||
The independent variable vector for this tape. This informaiton is
|
||||
also stored in the tape so a check is done to make sure it is correct
|
||||
(if NDEBUG is not defined).
|
||||
|
||||
\param y [in]
|
||||
The dependent variable vector for the corresponding function.
|
||||
*/
|
||||
template <typename Base>
|
||||
template <typename ADvector>
|
||||
void ADFun<Base>::Dependent(const ADvector &x, const ADvector &y)
|
||||
{
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
x.size() > 0,
|
||||
"Dependent: independent variable vector has size zero."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
Variable(x[0]),
|
||||
"Dependent: independent variable vector has been changed."
|
||||
);
|
||||
local::ADTape<Base> *tape = AD<Base>::tape_ptr(x[0].tape_id_);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
tape->size_independent_ == size_t( x.size() ),
|
||||
"Dependent: independent variable vector has been changed."
|
||||
);
|
||||
# ifndef NDEBUG
|
||||
size_t i, j;
|
||||
for(j = 0; j < size_t(x.size()); j++)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
size_t(x[j].taddr_) == (j+1),
|
||||
"ADFun<Base>: independent variable vector has been changed."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
x[j].tape_id_ == x[0].tape_id_,
|
||||
"ADFun<Base>: independent variable vector has been changed."
|
||||
);
|
||||
}
|
||||
for(i = 0; i < size_t(y.size()); i++)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
CppAD::Parameter( y[i] ) | (y[i].tape_id_ == x[0].tape_id_) ,
|
||||
"ADFun<Base>: dependent vector contains a variable for"
|
||||
"\na different tape (thread) than the independent variables."
|
||||
);
|
||||
}
|
||||
# endif
|
||||
|
||||
// code above just determines the tape and checks for errors
|
||||
Dependent(tape, y);
|
||||
}
|
||||
|
||||
/*!
|
||||
Replace the floationg point operations sequence for this function object.
|
||||
|
||||
\param tape
|
||||
is a tape that contains the new floating point operation sequence
|
||||
for this function.
|
||||
After this operation, all memory allocated for this tape is deleted.
|
||||
|
||||
\param y
|
||||
The dependent variable vector for the function being stored in this object.
|
||||
|
||||
\par
|
||||
All of the private member data in ad_fun.hpp is set to correspond to the
|
||||
new tape except for check_for_nan_.
|
||||
*/
|
||||
|
||||
template <typename Base>
|
||||
template <typename ADvector>
|
||||
void ADFun<Base>::Dependent(local::ADTape<Base> *tape, const ADvector &y)
|
||||
{
|
||||
size_t m = y.size();
|
||||
size_t n = tape->size_independent_;
|
||||
size_t i, j;
|
||||
size_t y_taddr;
|
||||
|
||||
// check ADvector is Simple Vector class with AD<Base> elements
|
||||
CheckSimpleVector< AD<Base>, ADvector>();
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
y.size() > 0,
|
||||
"ADFun operation sequence dependent variable size is zero size"
|
||||
);
|
||||
// ---------------------------------------------------------------------
|
||||
// Begin setting ad_fun.hpp private member data
|
||||
// ---------------------------------------------------------------------
|
||||
// dep_parameter_, dep_taddr_
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::ParOp) == 1 );
|
||||
dep_parameter_.resize(m);
|
||||
dep_taddr_.resize(m);
|
||||
for(i = 0; i < m; i++)
|
||||
{ dep_parameter_[i] = CppAD::Parameter(y[i]);
|
||||
if( dep_parameter_[i] )
|
||||
{ // make a tape copy of dependent variables that are parameters,
|
||||
y_taddr = tape->RecordParOp( y[i].value_ );
|
||||
}
|
||||
else y_taddr = y[i].taddr_;
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( y_taddr > 0 );
|
||||
dep_taddr_[i] = y_taddr;
|
||||
}
|
||||
|
||||
// put an EndOp at the end of the tape
|
||||
tape->Rec_.PutOp(local::EndOp);
|
||||
|
||||
// some size_t values in ad_fun.hpp
|
||||
has_been_optimized_ = false;
|
||||
compare_change_count_ = 1;
|
||||
compare_change_number_ = 0;
|
||||
compare_change_op_index_ = 0;
|
||||
num_order_taylor_ = 0;
|
||||
num_direction_taylor_ = 0;
|
||||
cap_order_taylor_ = 0;
|
||||
|
||||
// num_var_tape_
|
||||
// Now that all the variables are in the tape, we can set this value.
|
||||
num_var_tape_ = tape->Rec_.num_var_rec();
|
||||
|
||||
// taylor_
|
||||
taylor_.erase();
|
||||
|
||||
// cskip_op_
|
||||
cskip_op_.erase();
|
||||
cskip_op_.extend( tape->Rec_.num_op_rec() );
|
||||
|
||||
// load_op_
|
||||
load_op_.erase();
|
||||
load_op_.extend( tape->Rec_.num_load_op_rec() );
|
||||
|
||||
// play_
|
||||
// Now that each dependent variable has a place in the tape,
|
||||
// and there is a EndOp at the end of the tape, we can transfer the
|
||||
// recording to the player and and erase the tape.
|
||||
play_.get(tape->Rec_);
|
||||
|
||||
// ind_taddr_
|
||||
// Note that play_ has been set, we can use it to check operators
|
||||
ind_taddr_.resize(n);
|
||||
CPPAD_ASSERT_UNKNOWN( n < num_var_tape_);
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == local::InvOp );
|
||||
ind_taddr_[j] = j+1;
|
||||
}
|
||||
|
||||
// for_jac_sparse_pack_, for_jac_sparse_set_
|
||||
for_jac_sparse_pack_.resize(0, 0);
|
||||
for_jac_sparse_set_.resize(0,0);
|
||||
// ---------------------------------------------------------------------
|
||||
// End set ad_fun.hpp private member data
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
// now we can delete the tape
|
||||
AD<Base>::tape_manage(tape_manage_delete);
|
||||
|
||||
// total number of varables in this recording
|
||||
CPPAD_ASSERT_UNKNOWN( num_var_tape_ == play_.num_var_rec() );
|
||||
|
||||
// used to determine if there is an operation sequence in *this
|
||||
CPPAD_ASSERT_UNKNOWN( num_var_tape_ > 0 );
|
||||
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+306
@@ -0,0 +1,306 @@
|
||||
# ifndef CPPAD_CORE_DISCRETE_HPP
|
||||
# define CPPAD_CORE_DISCRETE_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 Discrete$$
|
||||
$spell
|
||||
retaping
|
||||
namespace
|
||||
std
|
||||
Eq
|
||||
Cpp
|
||||
const
|
||||
inline
|
||||
Geq
|
||||
$$
|
||||
|
||||
$section Discrete AD Functions$$
|
||||
$mindex CPPAD_DISCRETE_FUNCTION$$
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
$codei%CPPAD_DISCRETE_FUNCTION(%Base%, %name%)
|
||||
%$$
|
||||
$icode%y% = %name%(%x%)
|
||||
%$$
|
||||
$icode%ay% = %name%(%ax%)
|
||||
%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Record the evaluation of a discrete function as part
|
||||
of an $codei%AD<%Base%>%$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
The value of a discrete function can depend on the
|
||||
$cref/independent variables/glossary/Tape/Independent Variable/$$,
|
||||
but its derivative is identically zero.
|
||||
For example, suppose that the integer part of
|
||||
a $cref/variable/glossary/Variable/$$ $icode x$$ is the
|
||||
index into an array of values.
|
||||
|
||||
$head Base$$
|
||||
This is the
|
||||
$cref/base type/base_require/$$
|
||||
corresponding to the operations sequence;
|
||||
i.e., use of the $icode name$$ with arguments of type
|
||||
$codei%AD<%Base%>%$$ can be recorded in an operation sequence.
|
||||
|
||||
$head name$$
|
||||
This is the name of the function (as it is used in the source code).
|
||||
The user must provide a version of $icode name$$
|
||||
where the argument has type $icode Base$$.
|
||||
CppAD uses this to create a version of $icode name$$
|
||||
where the argument has type $codei%AD<%Base%>%$$.
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
%$$
|
||||
It is the value at which the user provided version of $icode name$$
|
||||
is to be evaluated.
|
||||
|
||||
$head y$$
|
||||
The result $icode y$$ has prototype
|
||||
$codei%
|
||||
%Base% %y%
|
||||
%$$
|
||||
It is the return value for the user provided version of $icode name$$.
|
||||
|
||||
$head ax$$
|
||||
The argument $icode ax$$ has prototype
|
||||
$codei%
|
||||
const AD<%Base%>& %ax%
|
||||
%$$
|
||||
It is the value at which the CppAD provided version of $icode name$$
|
||||
is to be evaluated.
|
||||
|
||||
$head ay$$
|
||||
The result $icode ay$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %ay%
|
||||
%$$
|
||||
It is the return value for the CppAD provided version of $icode name$$.
|
||||
|
||||
|
||||
$head Create AD Version$$
|
||||
The preprocessor macro invocation
|
||||
$codei%
|
||||
CPPAD_DISCRETE_FUNCTION(%Base%, %name%)
|
||||
%$$
|
||||
defines the $codei%AD<%Base%>%$$ version of $icode name$$.
|
||||
This can be with in a namespace (not the $code CppAD$$ namespace)
|
||||
but must be outside of any routine.
|
||||
|
||||
$head Operation Sequence$$
|
||||
This is an AD of $icode Base$$
|
||||
$cref/atomic operation/glossary/Operation/Atomic/$$
|
||||
and hence is part of the current
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Derivatives$$
|
||||
During a zero order $cref Forward$$ operation,
|
||||
an $cref ADFun$$ object will compute the value of $icode name$$
|
||||
using the user provided $icode Base$$ version of this routine.
|
||||
All the derivatives of $icode name$$ will be evaluated as zero.
|
||||
|
||||
$head Parallel Mode$$
|
||||
The first call to
|
||||
$codei%
|
||||
%ay% = %name%(%ax%)
|
||||
%$$
|
||||
must not be in $cref/parallel/ta_in_parallel/$$ execution mode.
|
||||
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/tape_index.cpp%
|
||||
example/general/interp_onetape.cpp%
|
||||
example/general/interp_retape.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref tape_index.cpp$$
|
||||
contains an example and test that uses a discrete function
|
||||
to vary an array index during $cref Forward$$ mode calculations.
|
||||
The file
|
||||
$cref interp_onetape.cpp$$
|
||||
contains an example and test that uses discrete
|
||||
functions to avoid retaping a calculation that requires interpolation.
|
||||
(The file
|
||||
$cref interp_retape.cpp$$
|
||||
shows how interpolation can be done with retaping.)
|
||||
|
||||
$head CppADCreateDiscrete Deprecated 2007-07-28$$
|
||||
The preprocessor symbol $code CppADCreateDiscrete$$
|
||||
is defined to be the same as $code CPPAD_DISCRETE_FUNCTION$$
|
||||
but its use is deprecated.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <vector>
|
||||
# include <cppad/core/cppad_assert.hpp>
|
||||
|
||||
// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
|
||||
# include <cppad/utility/thread_alloc.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file discrete.hpp
|
||||
user define discrete functions
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_DISCRETE_FUNCTION(Base, name)
|
||||
Defines the function <code>name(ax, ay)</code>
|
||||
where \c ax and \c ay are vectors with <code>AD<Base></code> elements.
|
||||
|
||||
\par Base
|
||||
is the base type for the discrete function.
|
||||
|
||||
\par name
|
||||
is the name of the user defined function that corresponding to this operation.
|
||||
*/
|
||||
|
||||
# define CPPAD_DISCRETE_FUNCTION(Base, name) \
|
||||
inline CppAD::AD<Base> name (const CppAD::AD<Base>& ax) \
|
||||
{ \
|
||||
static CppAD::discrete<Base> fun(#name, name); \
|
||||
\
|
||||
return fun.ad(ax); \
|
||||
}
|
||||
# define CppADCreateDiscrete CPPAD_DISCRETE_FUNCTION
|
||||
|
||||
|
||||
/*
|
||||
Class that acutally implemnets the <code>ay = name(ax)</code> call.
|
||||
|
||||
A new discrete function is generated for ech time the user invokes
|
||||
the CPPAD_DISCRETE_FUNCTION macro; see static object in that macro.
|
||||
*/
|
||||
template <class Base>
|
||||
class discrete {
|
||||
/// parallel_ad needs to call List to initialize static
|
||||
template <class Type>
|
||||
friend void parallel_ad(void);
|
||||
|
||||
/// type for the user routine that computes function values
|
||||
typedef Base (*F) (const Base& x);
|
||||
private:
|
||||
/// name of this user defined function
|
||||
const std::string name_;
|
||||
/// user's implementation of the function for Base operations
|
||||
const F f_;
|
||||
/// index of this objec in the vector of all objects for this class
|
||||
const size_t index_;
|
||||
|
||||
/*!
|
||||
List of all objects in this class.
|
||||
|
||||
If we use CppAD::vector for this vector, it will appear that
|
||||
there is a memory leak because this list is not distroyed before
|
||||
thread_alloc::free_available(thread) is called by the testing routines.
|
||||
*/
|
||||
static std::vector<discrete *>& List(void)
|
||||
{ CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
|
||||
static std::vector<discrete *> list;
|
||||
return list;
|
||||
}
|
||||
public:
|
||||
/*!
|
||||
Constructor called for each invocation of CPPAD_DISCRETE_FUNCTION.
|
||||
|
||||
Put this object in the list of all objects for this class and set
|
||||
the constant private data name_, f_, and index_.
|
||||
|
||||
\param Name
|
||||
is the user's name for this discrete function.
|
||||
|
||||
\param f
|
||||
user routine that implements this function for \c Base class.
|
||||
|
||||
\par
|
||||
This constructor can ont be used in parallel mode because it changes
|
||||
the static object \c List.
|
||||
*/
|
||||
discrete(const char* Name, F f) :
|
||||
name_(Name)
|
||||
, f_(f)
|
||||
, index_( List().size() )
|
||||
{
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
! thread_alloc::in_parallel() ,
|
||||
"discrete: First call the function *Name is in parallel mode."
|
||||
);
|
||||
List().push_back(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
Implement the user call to <code>ay = name(ax)</code>.
|
||||
|
||||
\param ax
|
||||
is the argument for this call.
|
||||
|
||||
\return
|
||||
the return value is called \c ay above.
|
||||
*/
|
||||
AD<Base> ad(const AD<Base> &ax) const
|
||||
{ AD<Base> ay;
|
||||
|
||||
ay.value_ = f_(ax.value_);
|
||||
if( Variable(ax) )
|
||||
{ local::ADTape<Base> *tape = ax.tape_this();
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DisOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DisOp) == 2 );
|
||||
|
||||
// put operand addresses in the tape
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::numeric_limits<addr_t>::max() >= index_,
|
||||
"discrete: cppad_tape_addr_type maximum not large enough"
|
||||
);
|
||||
tape->Rec_.PutArg(addr_t(index_), ax.taddr_);
|
||||
// put operator in the tape
|
||||
ay.taddr_ = tape->Rec_.PutOp(local::DisOp);
|
||||
// make result a variable
|
||||
ay.tape_id_ = tape->id_;
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( Variable(ay) );
|
||||
}
|
||||
return ay;
|
||||
}
|
||||
|
||||
/// Name corresponding to a discrete object
|
||||
static const char* name(size_t index)
|
||||
{ return List()[index]->name_.c_str(); }
|
||||
|
||||
/*!
|
||||
Link from forward mode sweep to users routine
|
||||
|
||||
\param index
|
||||
index for this function in the list of all discrete object
|
||||
|
||||
\param x
|
||||
argument value at which to evaluate this function
|
||||
*/
|
||||
static Base eval(size_t index, const Base& x)
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN(index < List().size() );
|
||||
|
||||
return List()[index]->f_(x);
|
||||
}
|
||||
};
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_DIV_HPP
|
||||
# define CPPAD_CORE_DIV_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base> operator / (const AD<Base> &left , const AD<Base> &right)
|
||||
{
|
||||
// compute the Base part
|
||||
AD<Base> result;
|
||||
result.value_ = left.value_ / right.value_;
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return result;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_left = left.tape_id_ == tape_id;
|
||||
bool var_right = right.tape_id_ == tape_id;
|
||||
|
||||
if( var_left )
|
||||
{ if( var_right )
|
||||
{ // result = variable / variable
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
left.tape_id_ == right.tape_id_,
|
||||
"Dividing AD objects that are"
|
||||
" variables on different tapes."
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::DivvvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
else if( IdenticalOne(right.value_) )
|
||||
{ // result = variable / 1
|
||||
result.make_variable(left.tape_id_, left.taddr_);
|
||||
}
|
||||
else
|
||||
{ // result = variable / parameter
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvpOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(left.taddr_, p);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::DivvpOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
else if( var_right )
|
||||
{ if( IdenticalZero(left.value_) )
|
||||
{ // result = 0 / variable
|
||||
}
|
||||
else
|
||||
{ // result = parameter / variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(left.value_);
|
||||
tape->Rec_.PutArg(p, right.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::DivpvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(/)
|
||||
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_DIV_EQ_HPP
|
||||
# define CPPAD_CORE_DIV_EQ_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base>& AD<Base>::operator /= (const AD<Base> &right)
|
||||
{
|
||||
// compute the Base part
|
||||
Base left;
|
||||
left = value_;
|
||||
value_ /= right.value_;
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return *this;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_left = tape_id_ == tape_id;
|
||||
bool var_right = right.tape_id_ == tape_id;
|
||||
|
||||
if( var_left )
|
||||
{ if( var_right )
|
||||
{ // this = variable / variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(taddr_, right.taddr_);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::DivvvOp);
|
||||
// make this a variable
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||
}
|
||||
else if( IdenticalOne( right.value_ ) )
|
||||
{ // this = variable * 1
|
||||
}
|
||||
else
|
||||
{ // this = variable / parameter
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvpOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(taddr_, p);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::DivvpOp);
|
||||
// make this a variable
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||
}
|
||||
}
|
||||
else if( var_right )
|
||||
{ if( IdenticalZero(left) )
|
||||
{ // this = 0 / variable
|
||||
}
|
||||
else
|
||||
{ // this = parameter / variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(left);
|
||||
tape->Rec_.PutArg(p, right.taddr_);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::DivpvOp);
|
||||
// make this a variable
|
||||
tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CPPAD_FOLD_ASSIGNMENT_OPERATOR(/=)
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
# ifndef CPPAD_CORE_DRIVERS_HPP
|
||||
# define CPPAD_CORE_DRIVERS_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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/core/jacobian.hpp>
|
||||
# include <cppad/core/hessian.hpp>
|
||||
# include <cppad/core/for_one.hpp>
|
||||
# include <cppad/core/rev_one.hpp>
|
||||
# include <cppad/core/for_two.hpp>
|
||||
# include <cppad/core/rev_two.hpp>
|
||||
|
||||
# endif
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_EPSILON_HPP
|
||||
# define CPPAD_CORE_EPSILON_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 epsilon$$
|
||||
$spell
|
||||
std
|
||||
eps
|
||||
CppAD
|
||||
namespace
|
||||
const
|
||||
$$
|
||||
|
||||
$section Machine Epsilon For AD Types$$
|
||||
|
||||
$head Deprecated 2012-06-17$$
|
||||
This routine has been deprecated.
|
||||
You should use the $cref numeric_limits$$ $code epsilon$$ instead.
|
||||
|
||||
$head Syntax$$
|
||||
$icode%eps% = epsilon<%Float%>()%$$
|
||||
|
||||
$head Purpose$$
|
||||
Obtain the value of machine epsilon corresponding
|
||||
to the type $icode%Float%$$.
|
||||
|
||||
$head Float$$
|
||||
this type can either be $codei%AD<%Base%>%$$,
|
||||
or it can be $icode Base$$ for any $codei%AD<%Base%>%$$ type.
|
||||
|
||||
$head eps$$
|
||||
The result $icode eps$$ has prototype
|
||||
$codei%
|
||||
%Float% eps
|
||||
%$$
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD {
|
||||
|
||||
template <class Type>
|
||||
inline Type epsilon(void)
|
||||
{ return Type ( numeric_limits<Type>::epsilon() ); }
|
||||
|
||||
}
|
||||
# endif
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
# ifndef CPPAD_CORE_EQUAL_OP_SEQ_HPP
|
||||
# define CPPAD_CORE_EQUAL_OP_SEQ_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 EqualOpSeq$$
|
||||
$spell
|
||||
Op
|
||||
const
|
||||
bool
|
||||
$$
|
||||
|
||||
|
||||
$section Check if Two Value are Identically Equal$$
|
||||
$mindex EqualOpSeq operation sequence$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%b% = EqualOpSeq(%x%, %y%)%$$
|
||||
|
||||
$head Purpose$$
|
||||
Determine if two $icode x$$ and $icode y$$ are identically equal; i.e.,
|
||||
not only is $icode%x% == %y%$$ true, but
|
||||
if they are $cref/variables/glossary/Variable/$$,
|
||||
they correspond have the same
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Motivation$$
|
||||
Sometimes it is useful to cache information
|
||||
and only recalculate when a function's arguments change.
|
||||
In the case of AD variables,
|
||||
it may be important not only when the argument values are equal,
|
||||
but when they are related to the
|
||||
$cref/independent variables/glossary/Tape/Independent Variable/$$
|
||||
by the same operation sequence.
|
||||
After the assignment
|
||||
$codei%
|
||||
%y% = %x%
|
||||
%$$
|
||||
these two AD objects would not only have equal values,
|
||||
but would also correspond to the same operation sequence.
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const AD<%Base%> &%x%
|
||||
%$$
|
||||
|
||||
$head y$$
|
||||
The argument $icode y$$ has prototype
|
||||
$codei%
|
||||
const AD<%Base%> &%y%
|
||||
%$$
|
||||
|
||||
$head b$$
|
||||
The result $icode b$$ has prototype
|
||||
$codei%
|
||||
bool %b%
|
||||
%$$
|
||||
The result is true if and only if one of the following cases holds:
|
||||
|
||||
$list number$$
|
||||
Both $icode x$$ and $icode y$$ are variables
|
||||
and correspond to the same operation sequence.
|
||||
$lnext
|
||||
Both $icode x$$ and $icode y$$ are parameters,
|
||||
$icode Base$$ is an AD type,
|
||||
and $codei%EqualOpSeq( Value(%x%) , Value(%y%) )%$$ is true.
|
||||
$lnext
|
||||
Both $icode x$$ and $icode y$$ are parameters,
|
||||
$icode Base$$ is not an AD type,
|
||||
and $icode%x% == %y%%$$ is true.
|
||||
$lend
|
||||
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/equal_op_seq.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref equal_op_seq.cpp$$
|
||||
contains an example and test of $code EqualOpSeq$$.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
namespace CppAD {
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool EqualOpSeq(const AD<Base> &x, const AD<Base> &y)
|
||||
{
|
||||
if( Parameter(x) )
|
||||
{ if( Parameter(y) )
|
||||
return EqualOpSeq(x.value_, y.value_);
|
||||
else return false;
|
||||
}
|
||||
else if( Parameter(y) )
|
||||
return false;
|
||||
|
||||
return (x.taddr_ == y.taddr_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# endif
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
# ifndef CPPAD_CORE_ERF_HPP
|
||||
# define CPPAD_CORE_ERF_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 erf$$
|
||||
$spell
|
||||
erf
|
||||
const
|
||||
Vec
|
||||
std
|
||||
cmath
|
||||
CppAD
|
||||
Vedder
|
||||
$$
|
||||
$section The Error Function$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = erf(%x%)%$$
|
||||
|
||||
$head Description$$
|
||||
Returns the value of the error function which is defined by
|
||||
$latex \[
|
||||
{\rm erf} (x) = \frac{2}{ \sqrt{\pi} } \int_0^x \exp( - t * t ) \; {\bf d} t
|
||||
\] $$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head CPPAD_USE_CPLUSPLUS_2011$$
|
||||
|
||||
$subhead true$$
|
||||
If this preprocessor symbol is true ($code 1$$),
|
||||
and $icode x$$ is an AD type,
|
||||
this is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$subhead false$$
|
||||
If this preprocessor symbol is false ($code 0$$),
|
||||
CppAD uses a fast approximation (few numerical operations)
|
||||
with relative error bound $latex 4 \times 10^{-4}$$; see
|
||||
Vedder, J.D.,
|
||||
$icode Simple approximations for the error function and its inverse$$,
|
||||
American Journal of Physics,
|
||||
v 55,
|
||||
n 8,
|
||||
1987,
|
||||
p 762-3.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/erf.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref erf.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/configure.hpp>
|
||||
# if ! CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Type>
|
||||
Type erf_template(const Type &x)
|
||||
{ using CppAD::exp;
|
||||
const Type a = static_cast<Type>(993./880.);
|
||||
const Type b = static_cast<Type>(89./880.);
|
||||
|
||||
return tanh( (a + b * x * x) * x );
|
||||
}
|
||||
|
||||
inline float erf(const float &x)
|
||||
{ return erf_template(x); }
|
||||
|
||||
inline double erf(const double &x)
|
||||
{ return erf_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> erf(const AD<Base> &x)
|
||||
{ return erf_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> erf(const VecAD_reference<Base> &x)
|
||||
{ return erf_template( x.ADBase() ); }
|
||||
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif // CPPAD_USE_CPLUSPLUS_2011
|
||||
# endif // CPPAD_ERF_INCLUDED
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
# ifndef CPPAD_CORE_EXPM1_HPP
|
||||
# define CPPAD_CORE_EXPM1_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 expm1$$
|
||||
$spell
|
||||
exp
|
||||
expm1
|
||||
const
|
||||
Vec
|
||||
std
|
||||
cmath
|
||||
CppAD
|
||||
$$
|
||||
$section The Exponential Function Minus One: expm1$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = expm1(%x%)%$$
|
||||
|
||||
$head Description$$
|
||||
Returns the value of the exponential function minus one which is defined
|
||||
by $icode%y% == exp(%x%) - 1%$$.
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head CPPAD_USE_CPLUSPLUS_2011$$
|
||||
|
||||
$subhead true$$
|
||||
If this preprocessor symbol is true ($code 1$$),
|
||||
and $icode x$$ is an AD type,
|
||||
this is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$subhead false$$
|
||||
If this preprocessor symbol is false ($code 0$$),
|
||||
CppAD uses the representation
|
||||
$latex \[
|
||||
\R{expm1} (x) = \exp(x) - 1
|
||||
\] $$
|
||||
to compute this function.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/expm1.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref expm1.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/configure.hpp>
|
||||
# if ! CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Type>
|
||||
Type expm1_template(const Type &x)
|
||||
{ return CppAD::exp(x) - Type(1);
|
||||
}
|
||||
|
||||
inline float expm1(const float &x)
|
||||
{ return expm1_template(x); }
|
||||
|
||||
inline double expm1(const double &x)
|
||||
{ return expm1_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> expm1(const AD<Base> &x)
|
||||
{ return expm1_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> expm1(const VecAD_reference<Base> &x)
|
||||
{ return expm1_template( x.ADBase() ); }
|
||||
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif // CPPAD_USE_CPLUSPLUS_2011
|
||||
# endif // CPPAD_EXPM1_INCLUDED
|
||||
@@ -0,0 +1,302 @@
|
||||
# ifndef CPPAD_CORE_FOR_HES_SPARSITY_HPP
|
||||
# define CPPAD_CORE_FOR_HES_SPARSITY_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 for_hes_sparsity$$
|
||||
$spell
|
||||
Andrea Walther
|
||||
Jacobian
|
||||
Hessian
|
||||
jac
|
||||
hes
|
||||
bool
|
||||
const
|
||||
rc
|
||||
cpp
|
||||
$$
|
||||
|
||||
$section Forward Mode Hessian Sparsity Patterns$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.for_hes_sparsity(
|
||||
%select_domain%, %select_range%, %internal_bool%, %pattern_out%
|
||||
)%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to
|
||||
the operation sequence stored in $icode f$$.
|
||||
Fix a diagonal matrix $latex D \in \B{R}^{n \times n}$$,
|
||||
a vector $latex s \in \B{R}^m$$ and define the function
|
||||
$latex \[
|
||||
H(x) = D ( s^\R{T} F )^{(2)} ( x ) D
|
||||
\] $$
|
||||
Given the sparsity for $latex D$$ and $latex s$$,
|
||||
$code for_hes_sparsity$$ computes a sparsity pattern for $latex H(x)$$.
|
||||
|
||||
$head x$$
|
||||
Note that the sparsity pattern $latex H(x)$$ corresponds to the
|
||||
operation sequence stored in $icode f$$ and does not depend on
|
||||
the argument $icode x$$.
|
||||
|
||||
$head BoolVector$$
|
||||
The type $icode BoolVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code bool$$.
|
||||
|
||||
$head SizeVector$$
|
||||
The type $icode SizeVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head select_domain$$
|
||||
The argument $icode diagonal$$ has prototype
|
||||
$codei%
|
||||
const %BoolVector%& %select_domain%
|
||||
%$$
|
||||
It has size $latex n$$ and specifies which components of the diagonal of
|
||||
$latex D$$ are non-zero; i.e., $icode%select_domain%[%j%]%$$ is true
|
||||
if and only if $latex D_{j,j}$$ is possibly non-zero.
|
||||
|
||||
|
||||
$head select_range$$
|
||||
The argument $icode select_range$$ has prototype
|
||||
$codei%
|
||||
const %BoolVector%& %select_range%
|
||||
%$$
|
||||
It has size $latex m$$ and specifies which components of the vector
|
||||
$latex s$$ are non-zero; i.e., $icode%select_range%[%i%]%$$ is true
|
||||
if and only if $latex s_i$$ is possibly non-zero.
|
||||
|
||||
$head internal_bool$$
|
||||
If this is true, calculations are done with sets represented by a vector
|
||||
of boolean values. Otherwise, a vector of sets of integers is used.
|
||||
|
||||
$head pattern_out$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
sparse_rc<%SizeVector%>& %pattern_out%
|
||||
%$$
|
||||
This input value of $icode pattern_out$$ does not matter.
|
||||
Upon return $icode pattern_out$$ is a sparsity pattern for $latex H(x)$$.
|
||||
|
||||
$head Sparsity for Entire Hessian$$
|
||||
Suppose that $latex R$$ is the $latex n \times n$$ identity matrix.
|
||||
In this case, $icode pattern_out$$ is a sparsity pattern for
|
||||
$latex (s^\R{T} F) F^{(2)} ( x )$$.
|
||||
|
||||
$head Algorithm$$
|
||||
See Algorithm II in
|
||||
$italic Computing sparse Hessians with automatic differentiation$$
|
||||
by Andrea Walther.
|
||||
Note that $icode s$$ provides the information so that
|
||||
'dead ends' are not included in the sparsity pattern.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/for_hes_sparsity.cpp
|
||||
%$$
|
||||
The file $cref for_hes_sparsity.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/core/ad_fun.hpp>
|
||||
# include <cppad/local/sparse_internal.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
Forward Hessian sparsity patterns.
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\tparam BoolVector
|
||||
is the simple vector with elements of type bool that is used for
|
||||
sparsity for the vector s.
|
||||
|
||||
\tparam SizeVector
|
||||
is the simple vector with elements of type size_t that is used for
|
||||
row, column index sparsity patterns.
|
||||
|
||||
\param select_domain
|
||||
is a sparsity pattern for for the diagonal of D.
|
||||
|
||||
\param select_range
|
||||
is a sparsity pattern for for s.
|
||||
|
||||
\param internal_bool
|
||||
If this is true, calculations are done with sets represented by a vector
|
||||
of boolean values. Otherwise, a vector of standard sets is used.
|
||||
|
||||
\param pattern_out
|
||||
The return value is a sparsity pattern for H(x) where
|
||||
\f[
|
||||
H(x) = D * F^{(1)} (x) * D
|
||||
\f]
|
||||
Here F is the function corresponding to the operation sequence
|
||||
and x is any argument value.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class BoolVector, class SizeVector>
|
||||
void ADFun<Base>::for_hes_sparsity(
|
||||
const BoolVector& select_domain ,
|
||||
const BoolVector& select_range ,
|
||||
bool internal_bool ,
|
||||
sparse_rc<SizeVector>& pattern_out )
|
||||
{ size_t n = Domain();
|
||||
size_t m = Range();
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t( select_domain.size() ) == n,
|
||||
"for_hes_sparsity: size of select_domain is not equal to "
|
||||
"number of independent variables"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t( select_range.size() ) == m,
|
||||
"for_hes_sparsity: size of select_range is not equal to "
|
||||
"number of dependent variables"
|
||||
);
|
||||
// do not need transpose or depenency
|
||||
bool transpose = false;
|
||||
bool dependency = false;
|
||||
//
|
||||
sparse_rc<SizeVector> pattern_tmp;
|
||||
if( internal_bool )
|
||||
{ // forward Jacobian sparsity pattern for independent variables
|
||||
local::sparse_pack internal_for_jac;
|
||||
internal_for_jac.resize(num_var_tape_, n + 1 );
|
||||
for(size_t j = 0; j < n; j++) if( select_domain[j] )
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < n + 1 );
|
||||
internal_for_jac.add_element( ind_taddr_[j] , ind_taddr_[j] );
|
||||
}
|
||||
// forward Jacobian sparsity for all variables on tape
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
internal_for_jac
|
||||
);
|
||||
// reverse Jacobian sparsity pattern for select_range
|
||||
local::sparse_pack internal_rev_jac;
|
||||
internal_rev_jac.resize(num_var_tape_, 1);
|
||||
for(size_t i = 0; i < m; i++) if( select_range[i] )
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
internal_rev_jac.add_element( dep_taddr_[i] , 0 );
|
||||
}
|
||||
// reverse Jacobian sparsity for all variables on tape
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
internal_rev_jac
|
||||
);
|
||||
// internal vector of sets that will hold Hessian
|
||||
local::sparse_pack internal_for_hes;
|
||||
internal_for_hes.resize(n + 1, n + 1);
|
||||
//
|
||||
// compute forward Hessian sparsity pattern
|
||||
local::ForHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
internal_for_jac,
|
||||
internal_rev_jac,
|
||||
internal_for_hes
|
||||
);
|
||||
//
|
||||
// put the result in pattern_tmp
|
||||
get_internal_sparsity(
|
||||
transpose, ind_taddr_, internal_for_hes, pattern_tmp
|
||||
);
|
||||
}
|
||||
else
|
||||
{ // forward Jacobian sparsity pattern for independent variables
|
||||
// (corresponds to D)
|
||||
local::sparse_list internal_for_jac;
|
||||
internal_for_jac.resize(num_var_tape_, n + 1 );
|
||||
for(size_t j = 0; j < n; j++) if( select_domain[j] )
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < n + 1 );
|
||||
internal_for_jac.add_element( ind_taddr_[j] , ind_taddr_[j] );
|
||||
}
|
||||
// forward Jacobian sparsity for all variables on tape
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
internal_for_jac
|
||||
);
|
||||
// reverse Jacobian sparsity pattern for select_range
|
||||
// (corresponds to s)
|
||||
local::sparse_list internal_rev_jac;
|
||||
internal_rev_jac.resize(num_var_tape_, 1);
|
||||
for(size_t i = 0; i < m; i++) if( select_range[i] )
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
internal_rev_jac.add_element( dep_taddr_[i] , 0 );
|
||||
}
|
||||
// reverse Jacobian sparsity for all variables on tape
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
internal_rev_jac
|
||||
);
|
||||
// internal vector of sets that will hold Hessian
|
||||
local::sparse_list internal_for_hes;
|
||||
internal_for_hes.resize(n + 1, n + 1);
|
||||
//
|
||||
// compute forward Hessian sparsity pattern
|
||||
local::ForHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
internal_for_jac,
|
||||
internal_rev_jac,
|
||||
internal_for_hes
|
||||
);
|
||||
//
|
||||
// put the result in pattern_tmp
|
||||
get_internal_sparsity(
|
||||
transpose, ind_taddr_, internal_for_hes, pattern_tmp
|
||||
);
|
||||
}
|
||||
// subtract 1 from all column values
|
||||
CPPAD_ASSERT_UNKNOWN( pattern_tmp.nr() == n );
|
||||
CPPAD_ASSERT_UNKNOWN( pattern_tmp.nc() == n + 1 );
|
||||
const SizeVector& row( pattern_tmp.row() );
|
||||
const SizeVector& col( pattern_tmp.col() );
|
||||
size_t nr = n;
|
||||
size_t nc = n;
|
||||
size_t nnz = pattern_tmp.nnz();
|
||||
pattern_out.resize(nr, nc, nnz);
|
||||
for(size_t k = 0; k < nnz; k++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( 0 < col[k] );
|
||||
pattern_out.set(k, row[k], col[k] - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,294 @@
|
||||
# ifndef CPPAD_CORE_FOR_JAC_SPARSITY_HPP
|
||||
# define CPPAD_CORE_FOR_JAC_SPARSITY_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 for_jac_sparsity$$
|
||||
$spell
|
||||
Jacobian
|
||||
jac
|
||||
bool
|
||||
const
|
||||
rc
|
||||
cpp
|
||||
$$
|
||||
|
||||
$section Forward Mode Jacobian Sparsity Patterns$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.for_jac_sparsity(
|
||||
%pattern_in%, %transpose%, %dependency%, %internal_bool%, %pattern_out%
|
||||
)%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to
|
||||
the operation sequence stored in $icode f$$.
|
||||
Fix $latex R \in \B{R}^{n \times \ell}$$ and define the function
|
||||
$latex \[
|
||||
J(x) = F^{(1)} ( x ) * R
|
||||
\] $$
|
||||
Given the $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$,
|
||||
$code for_jac_sparsity$$ computes a sparsity pattern for $latex J(x)$$.
|
||||
|
||||
$head x$$
|
||||
Note that the sparsity pattern $latex J(x)$$ corresponds to the
|
||||
operation sequence stored in $icode f$$ and does not depend on
|
||||
the argument $icode x$$.
|
||||
(The operation sequence may contain
|
||||
$cref CondExp$$ and $cref VecAD$$ operations.)
|
||||
|
||||
$head SizeVector$$
|
||||
The type $icode SizeVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
The $cref ADFun$$ object $icode f$$ is not $code const$$.
|
||||
After a call to $code for_jac_sparsity$$, a sparsity pattern
|
||||
for each of the variables in the operation sequence
|
||||
is held in $icode f$$ for possible later use during
|
||||
reverse Hessian sparsity calculations.
|
||||
|
||||
$subhead size_forward_bool$$
|
||||
After $code for_jac_sparsity$$, if $icode k$$ is a $code size_t$$ object,
|
||||
$codei%
|
||||
%k% = %f%.size_forward_bool()
|
||||
%$$
|
||||
sets $icode k$$ to the amount of memory (in unsigned character units)
|
||||
used to store the
|
||||
$cref/boolean vector/glossary/Sparsity Pattern/Boolean Vector/$$
|
||||
sparsity patterns.
|
||||
If $icode internal_bool$$ if false, $icode k$$ will be zero.
|
||||
Otherwise it will be non-zero.
|
||||
If you do not need this information for $cref RevSparseHes$$
|
||||
calculations, it can be deleted
|
||||
(and the corresponding memory freed) using
|
||||
$codei%
|
||||
%f%.size_forward_bool(0)
|
||||
%$$
|
||||
after which $icode%f%.size_forward_bool()%$$ will return zero.
|
||||
|
||||
$subhead size_forward_set$$
|
||||
After $code for_jac_sparsity$$, if $icode k$$ is a $code size_t$$ object,
|
||||
$codei%
|
||||
%k% = %f%.size_forward_set()
|
||||
%$$
|
||||
sets $icode k$$ to the amount of memory (in unsigned character units)
|
||||
used to store the
|
||||
$cref/vector of sets/glossary/Sparsity Pattern/Vector of Sets/$$
|
||||
sparsity patterns.
|
||||
If $icode internal_bool$$ if true, $icode k$$ will be zero.
|
||||
Otherwise it will be non-zero.
|
||||
If you do not need this information for future $cref rev_hes_sparsity$$
|
||||
calculations, it can be deleted
|
||||
(and the corresponding memory freed) using
|
||||
$codei%
|
||||
%f%.size_forward_set(0)
|
||||
%$$
|
||||
after which $icode%f%.size_forward_set()%$$ will return zero.
|
||||
|
||||
$head pattern_in$$
|
||||
The argument $icode pattern_in$$ has prototype
|
||||
$codei%
|
||||
const sparse_rc<%SizeVector%>& %pattern_in%
|
||||
%$$
|
||||
see $cref sparse_rc$$.
|
||||
If $icode transpose$$ it is false (true),
|
||||
$icode pattern_in$$ is a sparsity pattern for $latex R$$ ($latex R^\R{T}$$).
|
||||
|
||||
$head transpose$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
bool %transpose%
|
||||
%$$
|
||||
See $cref/pattern_in/for_jac_sparsity/pattern_in/$$ above and
|
||||
$cref/pattern_out/for_jac_sparsity/pattern_out/$$ below.
|
||||
|
||||
$head dependency$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
bool %dependency%
|
||||
%$$
|
||||
see $cref/pattern_out/for_jac_sparsity/pattern_out/$$ below.
|
||||
|
||||
$head internal_bool$$
|
||||
If this is true, calculations are done with sets represented by a vector
|
||||
of boolean values. Otherwise, a vector of sets of integers is used.
|
||||
|
||||
$head pattern_out$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
sparse_rc<%SizeVector%>& %pattern_out%
|
||||
%$$
|
||||
This input value of $icode pattern_out$$ does not matter.
|
||||
If $icode transpose$$ it is false (true),
|
||||
upon return $icode pattern_out$$ is a sparsity pattern for
|
||||
$latex J(x)$$ ($latex J(x)^\R{T}$$).
|
||||
If $icode dependency$$ is true, $icode pattern_out$$ is a
|
||||
$cref/dependency pattern/dependency.cpp/Dependency Pattern/$$
|
||||
instead of sparsity pattern.
|
||||
|
||||
$head Sparsity for Entire Jacobian$$
|
||||
Suppose that
|
||||
$latex R$$ is the $latex n \times n$$ identity matrix.
|
||||
In this case, $icode pattern_out$$ is a sparsity pattern for
|
||||
$latex F^{(1)} ( x )$$ ( $latex F^{(1)} (x)^\R{T}$$ )
|
||||
if $icode transpose$$ is false (true).
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/for_jac_sparsity.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref for_jac_sparsity.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/core/ad_fun.hpp>
|
||||
# include <cppad/local/sparse_internal.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
Forward Jacobian sparsity patterns.
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\tparam SizeVector
|
||||
is the simple vector with elements of type size_t that is used for
|
||||
row, column index sparsity patterns.
|
||||
|
||||
\param pattern_in
|
||||
is the sparsity pattern for for R or R^T depending on transpose.
|
||||
|
||||
\param transpose
|
||||
Is the input and returned sparsity pattern transposed.
|
||||
|
||||
\param dependency
|
||||
Are the derivatives with respect to left and right of the expression below
|
||||
considered to be non-zero:
|
||||
\code
|
||||
CondExpRel(left, right, if_true, if_false)
|
||||
\endcode
|
||||
This is used by the optimizer to obtain the correct dependency relations.
|
||||
|
||||
\param internal_bool
|
||||
If this is true, calculations are done with sets represented by a vector
|
||||
of boolean values. Othewise, a vector of standard sets is used.
|
||||
|
||||
\param pattern_out
|
||||
The value of transpose is false (true),
|
||||
the return value is a sparsity pattern for J(x) ( J(x)^T ) where
|
||||
\f[
|
||||
J(x) = F^{(1)} (x) * R
|
||||
\f]
|
||||
Here F is the function corresponding to the operation sequence
|
||||
and x is any argument value.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class SizeVector>
|
||||
void ADFun<Base>::for_jac_sparsity(
|
||||
const sparse_rc<SizeVector>& pattern_in ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
bool internal_bool ,
|
||||
sparse_rc<SizeVector>& pattern_out )
|
||||
{ // number or rows, columns, and non-zeros in pattern_in
|
||||
size_t nr_in = pattern_in.nr();
|
||||
size_t nc_in = pattern_in.nc();
|
||||
//
|
||||
size_t n = nr_in;
|
||||
size_t ell = nc_in;
|
||||
if( transpose )
|
||||
std::swap(n, ell);
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
n == Domain() ,
|
||||
"for_jac_sparsity: number rows in R "
|
||||
"is not equal number of independent variables."
|
||||
);
|
||||
bool zero_empty = true;
|
||||
bool input_empty = true;
|
||||
if( internal_bool )
|
||||
{ // allocate memory for bool sparsity calculation
|
||||
// (sparsity pattern is emtpy after a resize)
|
||||
for_jac_sparse_pack_.resize(num_var_tape_, ell);
|
||||
for_jac_sparse_set_.resize(0, 0);
|
||||
//
|
||||
// set sparsity patttern for independent variables
|
||||
local::set_internal_sparsity(
|
||||
zero_empty ,
|
||||
input_empty ,
|
||||
transpose ,
|
||||
ind_taddr_ ,
|
||||
for_jac_sparse_pack_ ,
|
||||
pattern_in
|
||||
);
|
||||
|
||||
// compute sparsity for other variables
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_pack_
|
||||
);
|
||||
// set the output pattern
|
||||
local::get_internal_sparsity(
|
||||
transpose, dep_taddr_, for_jac_sparse_pack_, pattern_out
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// allocate memory for set sparsity calculation
|
||||
// (sparsity pattern is emtpy after a resize)
|
||||
for_jac_sparse_set_.resize(num_var_tape_, ell);
|
||||
for_jac_sparse_pack_.resize(0, 0);
|
||||
//
|
||||
// set sparsity patttern for independent variables
|
||||
local::set_internal_sparsity(
|
||||
zero_empty ,
|
||||
input_empty ,
|
||||
transpose ,
|
||||
ind_taddr_ ,
|
||||
for_jac_sparse_set_ ,
|
||||
pattern_in
|
||||
);
|
||||
|
||||
// compute sparsity for other variables
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_set_
|
||||
);
|
||||
// get the ouput pattern
|
||||
local::get_internal_sparsity(
|
||||
transpose, dep_taddr_, for_jac_sparse_set_, pattern_out
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
# ifndef CPPAD_CORE_FOR_ONE_HPP
|
||||
# define CPPAD_CORE_FOR_ONE_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 ForOne$$
|
||||
$spell
|
||||
dy
|
||||
typename
|
||||
Taylor
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
|
||||
|
||||
$section First Order Partial Derivative: Driver Routine$$
|
||||
$mindex easy$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%dy% = %f%.ForOne(%x%, %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 $icode dy$$ to the
|
||||
partial of $latex F$$ with respect to $latex x_j$$; i.e.,
|
||||
$latex \[
|
||||
dy
|
||||
= \D{F}{ x_j } (x)
|
||||
= \left[
|
||||
\D{ F_0 }{ x_j } (x) , \cdots , \D{ F_{m-1} }{ x_j } (x)
|
||||
\right]
|
||||
\] $$
|
||||
|
||||
$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/ForOne Uses Forward/ForOne/ForOne Uses Forward/$$ below).
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Vector% &%x%
|
||||
%$$
|
||||
(see $cref/Vector/ForOne/Vector/$$ 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 derivative.
|
||||
|
||||
$head j$$
|
||||
The argument $icode j$$ has prototype
|
||||
$codei%
|
||||
size_t %j%
|
||||
%$$
|
||||
an is less than $icode n$$,
|
||||
$cref/domain/seq_property/Domain/$$ space for $icode f$$.
|
||||
It specifies the component of $icode F$$
|
||||
for which we are computing the partial derivative.
|
||||
|
||||
$head dy$$
|
||||
The result $icode dy$$ has prototype
|
||||
$codei%
|
||||
%Vector% %dy%
|
||||
%$$
|
||||
(see $cref/Vector/ForOne/Vector/$$ below)
|
||||
and its size is $latex m$$, the dimension of the
|
||||
$cref/range/seq_property/Range/$$ space for $icode f$$.
|
||||
The value of $icode dy$$ is the partial of $latex F$$ with respect to
|
||||
$latex x_j$$ evaluated at $icode x$$; i.e.,
|
||||
for $latex i = 0 , \ldots , m - 1$$
|
||||
$latex \[.
|
||||
dy[i] = \D{ F_i }{ x_j } ( x )
|
||||
\] $$
|
||||
|
||||
|
||||
$head Vector$$
|
||||
The type $icode Vector$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$icode Base$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head ForOne 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 ForOne$$,
|
||||
the zero order Taylor coefficients correspond to
|
||||
$icode%f%.Forward(0,%x%)%$$
|
||||
and the other coefficients are unspecified.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/for_one.cpp
|
||||
%$$
|
||||
The routine
|
||||
$cref/ForOne/for_one.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 Vector>
|
||||
Vector ADFun<Base>::ForOne(const Vector &x, size_t j)
|
||||
{ size_t j1;
|
||||
|
||||
size_t n = Domain();
|
||||
size_t m = Range();
|
||||
|
||||
// check Vector is Simple Vector class with Base type elements
|
||||
CheckSimpleVector<Base, Vector>();
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
x.size() == n,
|
||||
"ForOne: Length of x not equal domain dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
j < n,
|
||||
"ForOne: the index j is not less than domain dimension for f"
|
||||
);
|
||||
|
||||
// point at which we are evaluating the second partials
|
||||
Forward(0, x);
|
||||
|
||||
// direction in which are are taking the derivative
|
||||
Vector dx(n);
|
||||
for(j1 = 0; j1 < n; j1++)
|
||||
dx[j1] = Base(0.0);
|
||||
dx[j] = Base(1.0);
|
||||
|
||||
// dimension the return value
|
||||
Vector dy(m);
|
||||
|
||||
// compute the return value
|
||||
dy = Forward(1, dx);
|
||||
|
||||
return dy;
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,559 @@
|
||||
# ifndef CPPAD_CORE_FOR_SPARSE_HES_HPP
|
||||
# define CPPAD_CORE_FOR_SPARSE_HES_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 ForSparseHes$$
|
||||
$spell
|
||||
Andrea Walther
|
||||
std
|
||||
VecAD
|
||||
Jacobian
|
||||
Jac
|
||||
Hessian
|
||||
Hes
|
||||
const
|
||||
Bool
|
||||
Dep
|
||||
proportional
|
||||
var
|
||||
cpp
|
||||
$$
|
||||
|
||||
$section Hessian Sparsity Pattern: Forward Mode$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%h% = %f%.ForSparseHes(%r%, %s%)
|
||||
%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$.
|
||||
we define
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
H(x)
|
||||
& = & \partial_x \left[ \partial_u S \cdot F[ x + R \cdot u ] \right]_{u=0}
|
||||
\\
|
||||
& = & R^\R{T} \cdot (S \cdot F)^{(2)} ( x ) \cdot R
|
||||
\end{array}
|
||||
\] $$
|
||||
Where $latex R \in \B{R}^{n \times n}$$ is a diagonal matrix
|
||||
and $latex S \in \B{R}^{1 \times m}$$ is a row vector.
|
||||
Given a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the diagonal of $latex R$$ and the vector $latex S$$,
|
||||
$code ForSparseHes$$ returns a sparsity pattern for the $latex H(x)$$.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
const ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head x$$
|
||||
If the operation sequence in $icode f$$ is
|
||||
$cref/independent/glossary/Operation/Independent/$$ of
|
||||
the independent variables in $latex x \in B^n$$,
|
||||
the sparsity pattern is valid for all values of
|
||||
(even if it has $cref CondExp$$ or $cref VecAD$$ operations).
|
||||
|
||||
$head r$$
|
||||
The argument $icode r$$ has prototype
|
||||
$codei%
|
||||
const %VectorSet%& %r%
|
||||
%$$
|
||||
(see $cref/VectorSet/ForSparseHes/VectorSet/$$ below)
|
||||
If it has elements of type $code bool$$,
|
||||
its size is $latex n$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is one and all the elements of $icode%s%[0]%$$
|
||||
are between zero and $latex n - 1$$.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the diagonal of $latex R$$.
|
||||
The fewer non-zero elements in this sparsity pattern,
|
||||
the faster the calculation should be and the more sparse
|
||||
$latex H(x)$$ should be.
|
||||
|
||||
$head s$$
|
||||
The argument $icode s$$ has prototype
|
||||
$codei%
|
||||
const %VectorSet%& %s%
|
||||
%$$
|
||||
(see $cref/VectorSet/ForSparseHes/VectorSet/$$ below)
|
||||
If it has elements of type $code bool$$,
|
||||
its size is $latex m$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is one and all the elements of $icode%s%[0]%$$
|
||||
are between zero and $latex m - 1$$.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the vector $icode S$$.
|
||||
The fewer non-zero elements in this sparsity pattern,
|
||||
the faster the calculation should be and the more sparse
|
||||
$latex H(x)$$ should be.
|
||||
|
||||
$head h$$
|
||||
The result $icode h$$ has prototype
|
||||
$codei%
|
||||
%VectorSet%& %h%
|
||||
%$$
|
||||
(see $cref/VectorSet/ForSparseHes/VectorSet/$$ below).
|
||||
If $icode h$$ has elements of type $code bool$$,
|
||||
its size is $latex n * n$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $latex n$$ and all the set elements are between
|
||||
zero and $icode%n%-1%$$ inclusive.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex H(x)$$.
|
||||
|
||||
$head VectorSet$$
|
||||
The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code bool$$ or $code std::set<size_t>$$;
|
||||
see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion
|
||||
of the difference.
|
||||
The type of the elements of
|
||||
$cref/VectorSet/ForSparseHes/VectorSet/$$ must be the
|
||||
same as the type of the elements of $icode r$$.
|
||||
|
||||
$head Algorithm$$
|
||||
See Algorithm II in
|
||||
$italic Computing sparse Hessians with automatic differentiation$$
|
||||
by Andrea Walther.
|
||||
Note that $icode s$$ provides the information so that
|
||||
'dead ends' are not included in the sparsity pattern.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/for_sparse_hes.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref for_sparse_hes.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <algorithm>
|
||||
# include <cppad/local/pod_vector.hpp>
|
||||
# include <cppad/local/std_set.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file for_sparse_hes.hpp
|
||||
Forward mode Hessian sparsity patterns.
|
||||
*/
|
||||
// ===========================================================================
|
||||
// ForSparseHesCase
|
||||
/*!
|
||||
Private helper function for ForSparseHes(q, s) bool sparsity.
|
||||
|
||||
All of the description in the public member function ForSparseHes(q, s)
|
||||
applies.
|
||||
|
||||
\param set_type
|
||||
is a \c bool value. This argument is used to dispatch to the proper source
|
||||
code depending on the vlaue of \c VectorSet::value_type.
|
||||
|
||||
\param r
|
||||
See \c ForSparseHes(r, s).
|
||||
|
||||
\param s
|
||||
See \c ForSparseHes(r, s).
|
||||
|
||||
\param h
|
||||
is the return value for the corresponging call to \c ForSparseJac(q, s).
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
void ADFun<Base>::ForSparseHesCase(
|
||||
bool set_type ,
|
||||
const VectorSet& r ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& h )
|
||||
{ size_t n = Domain();
|
||||
size_t m = Range();
|
||||
//
|
||||
// check Vector is Simple VectorSet class with bool elements
|
||||
CheckSimpleVector<bool, VectorSet>();
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(r.size()) == n,
|
||||
"ForSparseHes: size of r is not equal to\n"
|
||||
"domain dimension for ADFun object."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(s.size()) == m,
|
||||
"ForSparseHes: size of s is not equal to\n"
|
||||
"range dimension for ADFun object."
|
||||
);
|
||||
//
|
||||
// sparsity pattern corresponding to r
|
||||
local::sparse_pack for_jac_pattern;
|
||||
for_jac_pattern.resize(num_var_tape_, n + 1);
|
||||
for(size_t i = 0; i < n; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] < n + 1 );
|
||||
// ind_taddr_[i] is operator taddr for i-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );
|
||||
//
|
||||
if( r[i] )
|
||||
for_jac_pattern.add_element( ind_taddr_[i], ind_taddr_[i] );
|
||||
}
|
||||
// compute forward Jacobiain sparsity pattern
|
||||
bool dependency = false;
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_pattern
|
||||
);
|
||||
// sparsity pattern correspnding to s
|
||||
local::sparse_pack rev_jac_pattern;
|
||||
rev_jac_pattern.resize(num_var_tape_, 1);
|
||||
for(size_t i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
if( s[i] )
|
||||
rev_jac_pattern.add_element( dep_taddr_[i], 0);
|
||||
}
|
||||
// compute reverse sparsity pattern for dependency analysis
|
||||
// (note that we are only want non-zero derivatives not true dependency)
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
rev_jac_pattern
|
||||
);
|
||||
// vector of sets that will hold the forward Hessain values
|
||||
local::sparse_pack for_hes_pattern;
|
||||
for_hes_pattern.resize(n+1, n+1);
|
||||
//
|
||||
// compute the Hessian sparsity patterns
|
||||
local::ForHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_pattern,
|
||||
rev_jac_pattern,
|
||||
for_hes_pattern
|
||||
);
|
||||
// initialize return values corresponding to independent variables
|
||||
h.resize(n * n);
|
||||
for(size_t i = 0; i < n; i++)
|
||||
{ for(size_t j = 0; j < n; j++)
|
||||
h[ i * n + j ] = false;
|
||||
}
|
||||
// copy to result pattern
|
||||
CPPAD_ASSERT_UNKNOWN( for_hes_pattern.end() == n+1 );
|
||||
for(size_t i = 0; i < n; i++)
|
||||
{ // ind_taddr_[i] is operator taddr for i-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] == i + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );
|
||||
|
||||
// extract the result from for_hes_pattern
|
||||
local::sparse_pack::const_iterator itr(for_hes_pattern, ind_taddr_[i] );
|
||||
size_t j = *itr;
|
||||
while( j < for_hes_pattern.end() )
|
||||
{ CPPAD_ASSERT_UNKNOWN( 0 < j )
|
||||
h[ i * n + (j-1) ] = true;
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Private helper function for ForSparseHes(q, s) set sparsity.
|
||||
|
||||
All of the description in the public member function ForSparseHes(q, s)
|
||||
applies.
|
||||
|
||||
\param set_type
|
||||
is a \c std::set<size_t> value.
|
||||
This argument is used to dispatch to the proper source
|
||||
code depending on the vlaue of \c VectorSet::value_type.
|
||||
|
||||
\param r
|
||||
See \c ForSparseHes(r, s).
|
||||
|
||||
\param s
|
||||
See \c ForSparseHes(q, s).
|
||||
|
||||
\param h
|
||||
is the return value for the corresponging call to \c ForSparseJac(q, s).
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
void ADFun<Base>::ForSparseHesCase(
|
||||
const std::set<size_t>& set_type ,
|
||||
const VectorSet& r ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& h )
|
||||
{ size_t n = Domain();
|
||||
# ifndef NDEBUG
|
||||
size_t m = Range();
|
||||
# endif
|
||||
std::set<size_t>::const_iterator itr_1;
|
||||
//
|
||||
// check VectorSet is Simple Vector class with sets for elements
|
||||
CheckSimpleVector<std::set<size_t>, VectorSet>(
|
||||
local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>()
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
r.size() == 1,
|
||||
"ForSparseHes: size of s is not equal to one."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
s.size() == 1,
|
||||
"ForSparseHes: size of s is not equal to one."
|
||||
);
|
||||
//
|
||||
// sparsity pattern corresponding to r
|
||||
local::sparse_list for_jac_pattern;
|
||||
for_jac_pattern.resize(num_var_tape_, n + 1);
|
||||
itr_1 = r[0].begin();
|
||||
while( itr_1 != r[0].end() )
|
||||
{ size_t i = *itr_1++;
|
||||
CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] < n + 1 );
|
||||
// ind_taddr_[i] is operator taddr for i-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );
|
||||
//
|
||||
for_jac_pattern.add_element( ind_taddr_[i], ind_taddr_[i] );
|
||||
}
|
||||
// compute forward Jacobiain sparsity pattern
|
||||
bool dependency = false;
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_pattern
|
||||
);
|
||||
// sparsity pattern correspnding to s
|
||||
local::sparse_list rev_jac_pattern;
|
||||
rev_jac_pattern.resize(num_var_tape_, 1);
|
||||
itr_1 = s[0].begin();
|
||||
while( itr_1 != s[0].end() )
|
||||
{ size_t i = *itr_1++;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
i < m,
|
||||
"ForSparseHes: an element of the set s[0] has value "
|
||||
"greater than or equal m"
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
rev_jac_pattern.add_element( dep_taddr_[i], 0);
|
||||
}
|
||||
//
|
||||
// compute reverse sparsity pattern for dependency analysis
|
||||
// (note that we are only want non-zero derivatives not true dependency)
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
rev_jac_pattern
|
||||
);
|
||||
//
|
||||
// vector of sets that will hold reverse Hessain values
|
||||
local::sparse_list for_hes_pattern;
|
||||
for_hes_pattern.resize(n+1, n+1);
|
||||
//
|
||||
// compute the Hessian sparsity patterns
|
||||
local::ForHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_pattern,
|
||||
rev_jac_pattern,
|
||||
for_hes_pattern
|
||||
);
|
||||
// return values corresponding to independent variables
|
||||
// j is index corresponding to reverse mode partial
|
||||
h.resize(n);
|
||||
CPPAD_ASSERT_UNKNOWN( for_hes_pattern.end() == n+1 );
|
||||
for(size_t i = 0; i < n; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] == i + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );
|
||||
|
||||
// extract the result from for_hes_pattern
|
||||
local::sparse_list::const_iterator itr_2(for_hes_pattern, ind_taddr_[i] );
|
||||
size_t j = *itr_2;
|
||||
while( j < for_hes_pattern.end() )
|
||||
{ CPPAD_ASSERT_UNKNOWN( 0 < j )
|
||||
h[i].insert(j-1);
|
||||
j = *(++itr_2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// ForSparseHes
|
||||
|
||||
/*!
|
||||
User API for Hessian sparsity patterns using reverse mode.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
h = f.ForSparseHes(q, r)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\tparam VectorSet
|
||||
is a simple vector with elements of type \c bool
|
||||
or \c std::set<size_t>.
|
||||
|
||||
\param r
|
||||
is a vector with size \c n that specifies the sparsity pattern
|
||||
for the diagonal of the matrix \f$ R \f$,
|
||||
where \c n is the number of independent variables
|
||||
corresponding to the operation sequence stored in \a play.
|
||||
|
||||
\param s
|
||||
is a vector with size \c m that specifies the sparsity pattern
|
||||
for the vector \f$ S \f$,
|
||||
where \c m is the number of dependent variables
|
||||
corresponding to the operation sequence stored in \a play.
|
||||
|
||||
\return
|
||||
The return vector is a sparsity pattern for \f$ H(x) \f$
|
||||
\f[
|
||||
H(x) = R^T ( S * F)^{(2)} (x) R
|
||||
\f]
|
||||
where \f$ F \f$ is the function corresponding to the operation sequence
|
||||
and \a x is any argument value.
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
VectorSet ADFun<Base>::ForSparseHes(
|
||||
const VectorSet& r, const VectorSet& s
|
||||
)
|
||||
{ VectorSet h;
|
||||
typedef typename VectorSet::value_type Set_type;
|
||||
|
||||
// Should check to make sure q is same as in previous call to
|
||||
// forward sparse Jacobian.
|
||||
ForSparseHesCase(
|
||||
Set_type() ,
|
||||
r ,
|
||||
s ,
|
||||
h
|
||||
);
|
||||
|
||||
return h;
|
||||
}
|
||||
// ===========================================================================
|
||||
// ForSparseHesCheckpoint
|
||||
/*!
|
||||
Hessian sparsity patterns calculation used by checkpoint functions.
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\param r
|
||||
is a vector with size n that specifies the sparsity pattern
|
||||
for the diagonal of \f$ R \f$,
|
||||
where n is the number of independent variables
|
||||
corresponding to the operation sequence stored in play_.
|
||||
|
||||
\param s
|
||||
is a vector with size m that specifies the sparsity pattern
|
||||
for the vector \f$ S \f$,
|
||||
where m is the number of dependent variables
|
||||
corresponding to the operation sequence stored in play_.
|
||||
|
||||
\param h
|
||||
The input size and elements of h do not matter.
|
||||
On output, h is the sparsity pattern for the matrix \f$ H(x) R \f$.
|
||||
|
||||
\par Assumptions
|
||||
The forward jacobian sparsity pattern must be currently stored
|
||||
in this ADFUN object.
|
||||
*/
|
||||
|
||||
// The checkpoint class is not yet using forward sparse Hessians.
|
||||
# ifdef CPPAD_NOT_DEFINED
|
||||
template <class Base>
|
||||
void ADFun<Base>::ForSparseHesCheckpoint(
|
||||
vector<bool>& r ,
|
||||
vector<bool>& s ,
|
||||
local::sparse_list& h )
|
||||
{
|
||||
size_t n = Domain();
|
||||
size_t m = Range();
|
||||
|
||||
// checkpoint functions should get this right
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( s.size() == m );
|
||||
|
||||
// Array that holds the reverse Jacobiain dependcy flags.
|
||||
// Initialize as true for dependent variables, flase for others.
|
||||
local::pod_vector<bool> RevJac;
|
||||
RevJac.extend(num_var_tape_);
|
||||
for(size_t i = 0; i < num_var_tape_; i++)
|
||||
RevJac[i] = false;
|
||||
for(size_t i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ )
|
||||
RevJac[ dep_taddr_[i] ] = s[i];
|
||||
}
|
||||
|
||||
// holds forward Hessian sparsity pattern for all variables
|
||||
local::sparse_list for_hes_pattern;
|
||||
for_hes_pattern.resize(n+1, n+1);
|
||||
|
||||
// compute Hessian sparsity pattern for all variables
|
||||
local::ForHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_set_,
|
||||
RevJac.data(),
|
||||
for_hes_pattern
|
||||
);
|
||||
|
||||
// dimension the return value
|
||||
if( transpose )
|
||||
h.resize(n, n);
|
||||
else
|
||||
h.resize(n, n);
|
||||
|
||||
// j is index corresponding to reverse mode partial
|
||||
for(size_t j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );
|
||||
|
||||
// ind_taddr_[j] is operator taddr for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
// extract the result from for_hes_pattern
|
||||
CPPAD_ASSERT_UNKNOWN( for_hes_pattern.end() == q );
|
||||
local::sparse_list::const_iterator itr(for_hes_pattern, .j + 1);
|
||||
size_t i = *itr;
|
||||
while( i < q )
|
||||
{ if( transpose )
|
||||
h.add_element(j, i);
|
||||
else h.add_element(i, j);
|
||||
i = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,729 @@
|
||||
# ifndef CPPAD_CORE_FOR_SPARSE_JAC_HPP
|
||||
# define CPPAD_CORE_FOR_SPARSE_JAC_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 ForSparseJac$$
|
||||
$spell
|
||||
std
|
||||
var
|
||||
Jacobian
|
||||
Jac
|
||||
const
|
||||
Bool
|
||||
proportional
|
||||
VecAD
|
||||
CondExpRel
|
||||
optimizer
|
||||
cpp
|
||||
$$
|
||||
|
||||
$section Jacobian Sparsity Pattern: Forward Mode$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%s% = %f%.ForSparseJac(%q%, %r%)
|
||||
%$$
|
||||
$icode%s% = %f%.ForSparseJac(%q%, %r%, %transpose%, %dependency%)%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : B^n \rightarrow B^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$.
|
||||
For a fixed $latex n \times q$$ matrix $latex R$$,
|
||||
the Jacobian of $latex F[ x + R * u ]$$
|
||||
with respect to $latex u$$ at $latex u = 0$$ is
|
||||
$latex \[
|
||||
S(x) = F^{(1)} ( x ) * R
|
||||
\] $$
|
||||
Given a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for $latex R$$,
|
||||
$code ForSparseJac$$ returns a sparsity pattern for the $latex S(x)$$.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
Note that the $cref ADFun$$ object $icode f$$ is not $code const$$.
|
||||
After a call to $code ForSparseJac$$, the sparsity pattern
|
||||
for each of the variables in the operation sequence
|
||||
is held in $icode f$$ (for possible later use by $cref RevSparseHes$$).
|
||||
These sparsity patterns are stored with elements of type $code bool$$
|
||||
or elements of type $code std::set<size_t>$$
|
||||
(see $cref/VectorSet/ForSparseJac/VectorSet/$$ below).
|
||||
|
||||
$subhead size_forward_bool$$
|
||||
After $code ForSparseJac$$, if $icode k$$ is a $code size_t$$ object,
|
||||
$codei%
|
||||
%k% = %f%.size_forward_bool()
|
||||
%$$
|
||||
sets $icode k$$ to the amount of memory (in unsigned character units)
|
||||
used to store the sparsity pattern with elements of type $code bool$$
|
||||
in the function object $icode f$$.
|
||||
If the sparsity patterns for the previous $code ForSparseJac$$ used
|
||||
elements of type $code bool$$,
|
||||
the return value for $code size_forward_bool$$ will be non-zero.
|
||||
Otherwise, its return value will be zero.
|
||||
This sparsity pattern is stored for use by $cref RevSparseHes$$ and
|
||||
when it is not longer needed, it can be deleted
|
||||
(and the corresponding memory freed) using
|
||||
$codei%
|
||||
%f%.size_forward_bool(0)
|
||||
%$$
|
||||
After this call, $icode%f%.size_forward_bool()%$$ will return zero.
|
||||
|
||||
$subhead size_forward_set$$
|
||||
After $code ForSparseJac$$, if $icode k$$ is a $code size_t$$ object,
|
||||
$codei%
|
||||
%k% = %f%.size_forward_set()
|
||||
%$$
|
||||
sets $icode k$$ to the amount of memory (in unsigned character units)
|
||||
used to store the
|
||||
$cref/vector of sets/glossary/Sparsity Pattern/Vector of Sets/$$
|
||||
sparsity patterns.
|
||||
If the sparsity patterns for this operation use elements of type $code bool$$,
|
||||
the return value for $code size_forward_set$$ will be zero.
|
||||
Otherwise, its return value will be non-zero.
|
||||
This sparsity pattern is stored for use by $cref RevSparseHes$$ and
|
||||
when it is not longer needed, it can be deleted
|
||||
(and the corresponding memory freed) using
|
||||
$codei%
|
||||
%f%.size_forward_set(0)
|
||||
%$$
|
||||
After this call, $icode%f%.size_forward_set()%$$ will return zero.
|
||||
|
||||
$head x$$
|
||||
If the operation sequence in $icode f$$ is
|
||||
$cref/independent/glossary/Operation/Independent/$$ of
|
||||
the independent variables in $latex x \in B^n$$,
|
||||
the sparsity pattern is valid for all values of
|
||||
(even if it has $cref CondExp$$ or $cref VecAD$$ operations).
|
||||
|
||||
$head q$$
|
||||
The argument $icode q$$ has prototype
|
||||
$codei%
|
||||
size_t %q%
|
||||
%$$
|
||||
It specifies the number of columns in
|
||||
$latex R \in B^{n \times q}$$ and the Jacobian
|
||||
$latex S(x) \in B^{m \times q}$$.
|
||||
|
||||
$head transpose$$
|
||||
The argument $icode transpose$$ has prototype
|
||||
$codei%
|
||||
bool %transpose%
|
||||
%$$
|
||||
The default value $code false$$ is used when $icode transpose$$ is not present.
|
||||
|
||||
$head dependency$$
|
||||
The argument $icode dependency$$ has prototype
|
||||
$codei%
|
||||
bool %dependency%
|
||||
%$$
|
||||
If $icode dependency$$ is true,
|
||||
the $cref/dependency pattern/dependency.cpp/Dependency Pattern/$$
|
||||
(instead of sparsity pattern) is computed.
|
||||
|
||||
$head r$$
|
||||
The argument $icode r$$ has prototype
|
||||
$codei%
|
||||
const %VectorSet%& %r%
|
||||
%$$
|
||||
see $cref/VectorSet/ForSparseJac/VectorSet/$$ below.
|
||||
|
||||
$subhead transpose false$$
|
||||
If $icode r$$ has elements of type $code bool$$,
|
||||
its size is $latex n * q$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $latex n$$ and all the set elements must be between
|
||||
zero and $icode%q%-1%$$ inclusive.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex R \in B^{n \times q}$$.
|
||||
|
||||
$subhead transpose true$$
|
||||
If $icode r$$ has elements of type $code bool$$,
|
||||
its size is $latex q * n$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $latex q$$ and all the set elements must be between
|
||||
zero and $icode%n%-1%$$ inclusive.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex R^\R{T} \in B^{q \times n}$$.
|
||||
|
||||
$head s$$
|
||||
The return value $icode s$$ has prototype
|
||||
$codei%
|
||||
%VectorSet% %s%
|
||||
%$$
|
||||
see $cref/VectorSet/ForSparseJac/VectorSet/$$ below.
|
||||
|
||||
$subhead transpose false$$
|
||||
If $icode s$$ has elements of type $code bool$$,
|
||||
its size is $latex m * q$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $latex m$$ and all its set elements are between
|
||||
zero and $icode%q%-1%$$ inclusive.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex S(x) \in B^{m \times q}$$.
|
||||
|
||||
$subhead transpose true$$
|
||||
If $icode s$$ has elements of type $code bool$$,
|
||||
its size is $latex q * m$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $latex q$$ and all its set elements are between
|
||||
zero and $icode%m%-1%$$ inclusive.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex S(x)^\R{T} \in B^{q \times m}$$.
|
||||
|
||||
$head VectorSet$$
|
||||
The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code bool$$ or $code std::set<size_t>$$;
|
||||
see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion
|
||||
of the difference.
|
||||
|
||||
$head Entire Sparsity Pattern$$
|
||||
Suppose that $latex q = n$$ and
|
||||
$latex R$$ is the $latex n \times n$$ identity matrix.
|
||||
In this case,
|
||||
the corresponding value for $icode s$$ is a
|
||||
sparsity pattern for the Jacobian $latex S(x) = F^{(1)} ( x )$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/for_sparse_jac.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref for_sparse_jac.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
The file
|
||||
$cref/sparsity_sub.cpp/sparsity_sub.cpp/ForSparseJac/$$
|
||||
contains an example and test of using $code ForSparseJac$$
|
||||
to compute the sparsity pattern for a subset of the Jacobian.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
# include <cppad/local/std_set.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file for_sparse_jac.hpp
|
||||
Forward mode Jacobian sparsity patterns.
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Private helper function for ForSparseJac(q, r) boolean sparsity patterns.
|
||||
|
||||
All of the description in the public member function ForSparseJac(q, r)
|
||||
applies.
|
||||
|
||||
\param set_type
|
||||
is a \c bool value. This argument is used to dispatch to the proper source
|
||||
code depending on the value of \c VectorSet::value_type.
|
||||
|
||||
\param transpose
|
||||
See \c ForSparseJac(q, r, transpose, dependency).
|
||||
|
||||
\param dependency
|
||||
See \c ForSparseJac(q, r, transpose, dependency).
|
||||
|
||||
\param q
|
||||
See \c ForSparseJac(q, r, transpose, dependency).
|
||||
|
||||
\param r
|
||||
See \c ForSparseJac(q, r, transpose, dependency).
|
||||
|
||||
\param s
|
||||
is the return value for the corresponding call to \c ForSparseJac(q, r).
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
void ADFun<Base>::ForSparseJacCase(
|
||||
bool set_type ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
size_t q ,
|
||||
const VectorSet& r ,
|
||||
VectorSet& s )
|
||||
{ size_t m = Range();
|
||||
size_t n = Domain();
|
||||
|
||||
// check VectorSet is Simple Vector class with bool elements
|
||||
CheckSimpleVector<bool, VectorSet>();
|
||||
|
||||
// dimension size of result vector
|
||||
s.resize( m * q );
|
||||
|
||||
// temporary indices
|
||||
size_t i, j;
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q > 0,
|
||||
"ForSparseJac: q is not greater than zero"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(r.size()) == n * q,
|
||||
"ForSparseJac: size of r is not equal to\n"
|
||||
"q times domain dimension for ADFun object."
|
||||
);
|
||||
//
|
||||
// allocate memory for the requested sparsity calculation result
|
||||
for_jac_sparse_pack_.resize(num_var_tape_, q);
|
||||
|
||||
// set values corresponding to independent variables
|
||||
for(i = 0; i < n; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] < num_var_tape_ );
|
||||
// ind_taddr_[i] is operator taddr for i-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );
|
||||
|
||||
// set bits that are true
|
||||
if( transpose )
|
||||
{ for(j = 0; j < q; j++) if( r[ j * n + i ] )
|
||||
for_jac_sparse_pack_.add_element( ind_taddr_[i], j);
|
||||
}
|
||||
else
|
||||
{ for(j = 0; j < q; j++) if( r[ i * q + j ] )
|
||||
for_jac_sparse_pack_.add_element( ind_taddr_[i], j);
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate the sparsity patterns
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_pack_
|
||||
);
|
||||
|
||||
// return values corresponding to dependent variables
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == m * q );
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
|
||||
// extract the result from for_jac_sparse_pack_
|
||||
if( transpose )
|
||||
{ for(j = 0; j < q; j++)
|
||||
s[ j * m + i ] = false;
|
||||
}
|
||||
else
|
||||
{ for(j = 0; j < q; j++)
|
||||
s[ i * q + j ] = false;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.end() == q );
|
||||
local::sparse_pack::const_iterator itr(for_jac_sparse_pack_, dep_taddr_[i] );
|
||||
j = *itr;
|
||||
while( j < q )
|
||||
{ if( transpose )
|
||||
s[j * m + i] = true;
|
||||
else s[i * q + j] = true;
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Private helper function for \c ForSparseJac(q, r) set sparsity.
|
||||
|
||||
All of the description in the public member function \c ForSparseJac(q, r)
|
||||
applies.
|
||||
|
||||
\param set_type
|
||||
is a \c std::set<size_t> object.
|
||||
This argument is used to dispatch to the proper source
|
||||
code depending on the value of \c VectorSet::value_type.
|
||||
|
||||
\param transpose
|
||||
See \c ForSparseJac(q, r, transpose, dependency).
|
||||
|
||||
\param dependency
|
||||
See \c ForSparseJac(q, r, transpose, dependency).
|
||||
|
||||
\param q
|
||||
See \c ForSparseJac(q, r, transpose, dependency).
|
||||
|
||||
\param r
|
||||
See \c ForSparseJac(q, r, transpose, dependency).
|
||||
|
||||
\param s
|
||||
is the return value for the corresponding call to \c ForSparseJac(q, r).
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
void ADFun<Base>::ForSparseJacCase(
|
||||
const std::set<size_t>& set_type ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
size_t q ,
|
||||
const VectorSet& r ,
|
||||
VectorSet& s )
|
||||
{ size_t m = Range();
|
||||
size_t n = Domain();
|
||||
|
||||
// check VectorSet is Simple Vector class with sets for elements
|
||||
CheckSimpleVector<std::set<size_t>, VectorSet>(
|
||||
local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>()
|
||||
);
|
||||
|
||||
// dimension size of result vector
|
||||
if( transpose )
|
||||
s.resize(q);
|
||||
else s.resize( m );
|
||||
|
||||
// temporary indices
|
||||
size_t i, j;
|
||||
std::set<size_t>::const_iterator itr_1;
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q > 0,
|
||||
"ForSparseJac: q is not greater than zero"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(r.size()) == n || transpose,
|
||||
"ForSparseJac: size of r is not equal to n and transpose is false."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(r.size()) == q || ! transpose,
|
||||
"ForSparseJac: size of r is not equal to q and transpose is true."
|
||||
);
|
||||
//
|
||||
// allocate memory for the requested sparsity calculation
|
||||
for_jac_sparse_set_.resize(num_var_tape_, q);
|
||||
|
||||
// set values corresponding to independent variables
|
||||
if( transpose )
|
||||
{ for(i = 0; i < q; i++)
|
||||
{ // add the elements that are present
|
||||
itr_1 = r[i].begin();
|
||||
while( itr_1 != r[i].end() )
|
||||
{ j = *itr_1++;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
j < n,
|
||||
"ForSparseJac: transpose is true and element of the set\n"
|
||||
"r[j] has value greater than or equal n."
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );
|
||||
// operator for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
for_jac_sparse_set_.add_element( ind_taddr_[j], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ for(i = 0; i < n; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[i] < num_var_tape_ );
|
||||
// ind_taddr_[i] is operator taddr for i-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[i] ) == local::InvOp );
|
||||
|
||||
// add the elements that are present
|
||||
itr_1 = r[i].begin();
|
||||
while( itr_1 != r[i].end() )
|
||||
{ j = *itr_1++;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
j < q,
|
||||
"ForSparseJac: an element of the set r[i] "
|
||||
"has value greater than or equal q."
|
||||
);
|
||||
for_jac_sparse_set_.add_element( ind_taddr_[i], j);
|
||||
}
|
||||
}
|
||||
}
|
||||
// evaluate the sparsity patterns
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_set_
|
||||
);
|
||||
|
||||
// return values corresponding to dependent variables
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == m || transpose );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q || ! transpose );
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
|
||||
// extract results from for_jac_sparse_set_
|
||||
// and add corresponding elements to sets in s
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.end() == q );
|
||||
local::sparse_list::const_iterator itr_2(for_jac_sparse_set_, dep_taddr_[i] );
|
||||
j = *itr_2;
|
||||
while( j < q )
|
||||
{ if( transpose )
|
||||
s[j].insert(i);
|
||||
else s[i].insert(j);
|
||||
j = *(++itr_2);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*!
|
||||
User API for Jacobian sparsity patterns using forward mode.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
s = f.ForSparseJac(q, r, transpose, dependency)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\tparam VectorSet
|
||||
is a simple vector with elements of type \c bool
|
||||
or \c std::set<size_t>.
|
||||
|
||||
\param q
|
||||
is the number of columns in the matrix \f$ R \f$.
|
||||
|
||||
\param r
|
||||
is a sparsity pattern for the matrix \f$ R \f$.
|
||||
|
||||
\param transpose
|
||||
are sparsity patterns for \f$ R \f$ and \f$ S(x) \f$ transposed.
|
||||
|
||||
\param dependency
|
||||
Are the derivatives with respect to left and right of the expression below
|
||||
considered to be non-zero:
|
||||
\code
|
||||
CondExpRel(left, right, if_true, if_false)
|
||||
\endcode
|
||||
This is used by the optimizer to obtain the correct dependency relations.
|
||||
|
||||
\return
|
||||
The value of \c transpose is false (true),
|
||||
the return value is a sparsity pattern for \f$ S(x) \f$ (\f$ S(x)^T \f$) where
|
||||
\f[
|
||||
S(x) = F^{(1)} (x) * R
|
||||
\f]
|
||||
where \f$ F \f$ is the function corresponding to the operation sequence
|
||||
and \a x is any argument value.
|
||||
If \c VectorSet::value_type is \c bool,
|
||||
the return value has size \f$ m * q \f$ (\f$ q * m \f$).
|
||||
where \c m is the number of dependent variables
|
||||
corresponding to the operation sequence stored in \c f.
|
||||
If \c VectorSet::value_type is \c std::set<size_t>,
|
||||
the return value has size \f$ m \f$ ( \f$ q \f$ )
|
||||
and with all its elements between zero and
|
||||
\f$ q - 1 \f$ ( \f$ m - 1 \f$).
|
||||
|
||||
\par Side Effects
|
||||
If \c VectorSet::value_type is \c bool,
|
||||
the forward sparsity pattern for all of the variables on the
|
||||
tape is stored in \c for_jac_sparse_pack__.
|
||||
In this case
|
||||
\verbatim
|
||||
for_jac_sparse_pack_.n_set() == num_var_tape_
|
||||
for_jac_sparse_pack_.end() == q
|
||||
for_jac_sparse_set_.n_set() == 0
|
||||
for_jac_sparse_set_.end() == 0
|
||||
\endverbatim
|
||||
\n
|
||||
\n
|
||||
If \c VectorSet::value_type is \c std::set<size_t>,
|
||||
the forward sparsity pattern for all of the variables on the
|
||||
tape is stored in \c for_jac_sparse_set__.
|
||||
In this case
|
||||
\verbatim
|
||||
for_jac_sparse_set_.n_set() == num_var_tape_
|
||||
for_jac_sparse_set_.end() == q
|
||||
for_jac_sparse_pack_.n_set() == 0
|
||||
for_jac_sparse_pack_.end() == 0
|
||||
\endverbatim
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
VectorSet ADFun<Base>::ForSparseJac(
|
||||
size_t q ,
|
||||
const VectorSet& r ,
|
||||
bool transpose ,
|
||||
bool dependency )
|
||||
{ VectorSet s;
|
||||
typedef typename VectorSet::value_type Set_type;
|
||||
|
||||
// free all memory currently in sparsity patterns
|
||||
for_jac_sparse_pack_.resize(0, 0);
|
||||
for_jac_sparse_set_.resize(0, 0);
|
||||
|
||||
ForSparseJacCase(
|
||||
Set_type() ,
|
||||
transpose ,
|
||||
dependency ,
|
||||
q ,
|
||||
r ,
|
||||
s
|
||||
);
|
||||
|
||||
return s;
|
||||
}
|
||||
// ===========================================================================
|
||||
// ForSparseJacCheckpoint
|
||||
/*!
|
||||
Forward mode Jacobian sparsity calculation used by checkpoint functions.
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\param transpose
|
||||
is true (false) s is equal to \f$ S(x) \f$ (\f$ S(x)^T \f$)
|
||||
where
|
||||
\f[
|
||||
S(x) = F^{(1)} (x) * R
|
||||
\f]
|
||||
where \f$ F \f$ is the function corresponding to the operation sequence
|
||||
and \f$ x \f$ is any argument value.
|
||||
|
||||
\param q
|
||||
is the number of columns in the matrix \f$ R \f$.
|
||||
|
||||
\param r
|
||||
is a sparsity pattern for the matrix \f$ R \f$.
|
||||
|
||||
\param transpose
|
||||
are the sparsity patterns for \f$ R \f$ and \f$ S(x) \f$ transposed.
|
||||
|
||||
\param dependency
|
||||
Are the derivatives with respect to left and right of the expression below
|
||||
considered to be non-zero:
|
||||
\code
|
||||
CondExpRel(left, right, if_true, if_false)
|
||||
\endcode
|
||||
This is used by the optimizer to obtain the correct dependency relations.
|
||||
|
||||
\param s
|
||||
The input size and elements of s do not matter.
|
||||
On output, s is the sparsity pattern for the matrix \f$ S(x) \f$
|
||||
or \f$ S(x)^T \f$ depending on transpose.
|
||||
|
||||
\par Side Effects
|
||||
If \c VectorSet::value_type is \c bool,
|
||||
the forward sparsity pattern for all of the variables on the
|
||||
tape is stored in \c for_jac_sparse_pack__.
|
||||
In this case
|
||||
\verbatim
|
||||
for_jac_sparse_pack_.n_set() == num_var_tape_
|
||||
for_jac_sparse_pack_.end() == q
|
||||
for_jac_sparse_set_.n_set() == 0
|
||||
for_jac_sparse_set_.end() == 0
|
||||
\endverbatim
|
||||
\n
|
||||
\n
|
||||
If \c VectorSet::value_type is \c std::set<size_t>,
|
||||
the forward sparsity pattern for all of the variables on the
|
||||
tape is stored in \c for_jac_sparse_set__.
|
||||
In this case
|
||||
\verbatim
|
||||
for_jac_sparse_set_.n_set() == num_var_tape_
|
||||
for_jac_sparse_set_.end() == q
|
||||
for_jac_sparse_pack_.n_set() == 0
|
||||
for_jac_sparse_pack_.end() == 0
|
||||
\endverbatim
|
||||
*/
|
||||
template <class Base>
|
||||
void ADFun<Base>::ForSparseJacCheckpoint(
|
||||
size_t q ,
|
||||
const local::sparse_list& r ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
local::sparse_list& s )
|
||||
{ size_t n = Domain();
|
||||
size_t m = Range();
|
||||
|
||||
# ifndef NDEBUG
|
||||
if( transpose )
|
||||
{ CPPAD_ASSERT_UNKNOWN( r.n_set() == q );
|
||||
CPPAD_ASSERT_UNKNOWN( r.end() == n );
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( r.n_set() == n );
|
||||
CPPAD_ASSERT_UNKNOWN( r.end() == q );
|
||||
}
|
||||
for(size_t j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
}
|
||||
# endif
|
||||
|
||||
// free all memory currently in sparsity patterns
|
||||
for_jac_sparse_pack_.resize(0, 0);
|
||||
for_jac_sparse_set_.resize(0, 0);
|
||||
|
||||
// allocate new sparsity pattern
|
||||
for_jac_sparse_set_.resize(num_var_tape_, q);
|
||||
|
||||
// set sparsity pattern for dependent variables
|
||||
if( transpose )
|
||||
{ for(size_t i = 0; i < q; i++)
|
||||
{ local::sparse_list::const_iterator itr(r, i);
|
||||
size_t j = *itr;
|
||||
while( j < n )
|
||||
{ for_jac_sparse_set_.add_element( ind_taddr_[j], i );
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ for(size_t j = 0; j < n; j++)
|
||||
{ local::sparse_list::const_iterator itr(r, j);
|
||||
size_t i = *itr;
|
||||
while( i < q )
|
||||
{ for_jac_sparse_set_.add_element( ind_taddr_[j], i );
|
||||
i = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate the sparsity pattern for all variables
|
||||
local::ForJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_set_
|
||||
);
|
||||
|
||||
// dimension the return value
|
||||
if( transpose )
|
||||
s.resize(q, m);
|
||||
else
|
||||
s.resize(m, q);
|
||||
|
||||
// return values corresponding to dependent variables
|
||||
for(size_t i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
|
||||
// extract the result from for_jac_sparse_set_
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.end() == q );
|
||||
local::sparse_list::const_iterator itr(for_jac_sparse_set_, dep_taddr_[i] );
|
||||
size_t j = *itr;
|
||||
while( j < q )
|
||||
{ if( transpose )
|
||||
s.add_element(j, i);
|
||||
else
|
||||
s.add_element(i, j);
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
# ifndef CPPAD_CORE_FOR_TWO_HPP
|
||||
# define CPPAD_CORE_FOR_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 ForTwo$$
|
||||
$spell
|
||||
ddy
|
||||
typename
|
||||
Taylor
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$section Forward Mode Second Partial Derivative Driver$$
|
||||
$mindex order easy$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%ddy% = %f%.ForTwo(%x%, %j%, %k%)%$$
|
||||
|
||||
|
||||
$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 \[
|
||||
ddy [ i * p + \ell ]
|
||||
=
|
||||
\DD{ F_i }{ x_{j[ \ell ]} }{ x_{k[ \ell ]} } (x)
|
||||
\] $$
|
||||
for $latex i = 0 , \ldots , m-1$$
|
||||
and $latex \ell = 0 , \ldots , p$$,
|
||||
where $latex p$$ is the size of the vectors $icode j$$ and $icode k$$.
|
||||
|
||||
$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/ForTwo Uses Forward/ForTwo/ForTwo Uses Forward/$$ below).
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %VectorBase% &%x%
|
||||
%$$
|
||||
(see $cref/VectorBase/ForTwo/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 j$$
|
||||
The argument $icode j$$ has prototype
|
||||
$codei%
|
||||
const %VectorSize_t% &%j%
|
||||
%$$
|
||||
(see $cref/VectorSize_t/ForTwo/VectorSize_t/$$ below)
|
||||
We use $icode p$$ to denote the size of the vector $icode j$$.
|
||||
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 k$$
|
||||
The argument $icode k$$ has prototype
|
||||
$codei%
|
||||
const %VectorSize_t% &%k%
|
||||
%$$
|
||||
(see $cref/VectorSize_t/ForTwo/VectorSize_t/$$ below)
|
||||
and its size must be equal to $icode p$$,
|
||||
the size of the vector $icode j$$.
|
||||
All of the indices in $icode k$$
|
||||
must be less than $icode n$$; i.e.,
|
||||
for $latex \ell = 0 , \ldots , p-1$$, $latex k[ \ell ] < n$$.
|
||||
|
||||
$head ddy$$
|
||||
The result $icode ddy$$ has prototype
|
||||
$codei%
|
||||
%VectorBase% %ddy%
|
||||
%$$
|
||||
(see $cref/VectorBase/ForTwo/VectorBase/$$ below)
|
||||
and its size is $latex m * p$$.
|
||||
It contains the requested partial derivatives; to be specific,
|
||||
for $latex i = 0 , \ldots , m - 1 $$
|
||||
and $latex \ell = 0 , \ldots , p - 1$$
|
||||
$latex \[
|
||||
ddy [ i * p + \ell ]
|
||||
=
|
||||
\DD{ F_i }{ x_{j[ \ell ]} }{ x_{k[ \ell ]} } (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 ForTwo 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 ForTwo$$,
|
||||
the zero order Taylor coefficients correspond to
|
||||
$icode%f%.Forward(0, %x%)%$$
|
||||
and the other coefficients are unspecified.
|
||||
|
||||
$head Examples$$
|
||||
$children%
|
||||
example/general/for_two.cpp
|
||||
%$$
|
||||
The routine
|
||||
$cref/ForTwo/for_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>::ForTwo(
|
||||
const VectorBase &x,
|
||||
const VectorSize_t &j,
|
||||
const VectorSize_t &k)
|
||||
{ size_t i;
|
||||
size_t j1;
|
||||
size_t k1;
|
||||
size_t l;
|
||||
|
||||
size_t n = Domain();
|
||||
size_t m = Range();
|
||||
size_t p = j.size();
|
||||
|
||||
// check VectorBase is Simple Vector class with Base type 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,
|
||||
"ForTwo: Length of x not equal domain dimension for f."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
j.size() == k.size(),
|
||||
"ForTwo: Lenght of the j and k vectors are not equal."
|
||||
);
|
||||
// point at which we are evaluating the second partials
|
||||
Forward(0, x);
|
||||
|
||||
|
||||
// dimension the return value
|
||||
VectorBase ddy(m * p);
|
||||
|
||||
// allocate memory to hold all possible diagonal Taylor coefficients
|
||||
// (for large sparse cases, this is not efficient)
|
||||
VectorBase D(m * n);
|
||||
|
||||
// boolean flag for which diagonal coefficients are computed
|
||||
CppAD::vector<bool> c(n);
|
||||
for(j1 = 0; j1 < n; j1++)
|
||||
c[j1] = false;
|
||||
|
||||
// direction vector in argument space
|
||||
VectorBase dx(n);
|
||||
for(j1 = 0; j1 < n; j1++)
|
||||
dx[j1] = Base(0.0);
|
||||
|
||||
// result vector in range space
|
||||
VectorBase dy(m);
|
||||
|
||||
// compute the diagonal coefficients that are needed
|
||||
for(l = 0; l < p; l++)
|
||||
{ j1 = j[l];
|
||||
k1 = k[l];
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
j1 < n,
|
||||
"ForTwo: an element of j not less than domain dimension for f."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
k1 < n,
|
||||
"ForTwo: an element of k not less than domain dimension for f."
|
||||
);
|
||||
size_t count = 2;
|
||||
while(count)
|
||||
{ count--;
|
||||
if( ! c[j1] )
|
||||
{ // diagonal term in j1 direction
|
||||
c[j1] = true;
|
||||
dx[j1] = Base(1.0);
|
||||
Forward(1, dx);
|
||||
|
||||
dx[j1] = Base(0.0);
|
||||
dy = Forward(2, dx);
|
||||
for(i = 0; i < m; i++)
|
||||
D[i * n + j1 ] = dy[i];
|
||||
}
|
||||
j1 = k1;
|
||||
}
|
||||
}
|
||||
// compute all the requested cross partials
|
||||
for(l = 0; l < p; l++)
|
||||
{ j1 = j[l];
|
||||
k1 = k[l];
|
||||
if( j1 == k1 )
|
||||
{ for(i = 0; i < m; i++)
|
||||
ddy[i * p + l] = Base(2.0) * D[i * n + j1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// cross term in j1 and k1 directions
|
||||
dx[j1] = Base(1.0);
|
||||
dx[k1] = Base(1.0);
|
||||
Forward(1, dx);
|
||||
|
||||
dx[j1] = Base(0.0);
|
||||
dx[k1] = Base(0.0);
|
||||
dy = Forward(2, dx);
|
||||
|
||||
// place result in return value
|
||||
for(i = 0; i < m; i++)
|
||||
ddy[i * p + l] = dy[i] - D[i*n+j1] - D[i*n+k1];
|
||||
|
||||
}
|
||||
}
|
||||
return ddy;
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+432
@@ -0,0 +1,432 @@
|
||||
# ifndef CPPAD_CORE_FORWARD_HPP
|
||||
# define CPPAD_CORE_FORWARD_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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
// documened after Forward but included here so easy to see
|
||||
# include <cppad/core/capacity_order.hpp>
|
||||
# include <cppad/core/num_skip.hpp>
|
||||
# include <cppad/core/check_for_nan.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file forward.hpp
|
||||
User interface to forward mode computations.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Multiple orders, one direction, forward mode Taylor coefficieints.
|
||||
|
||||
\tparam Base
|
||||
The type used during the forward mode computations; i.e., the corresponding
|
||||
recording of operations used the type AD<Base>.
|
||||
|
||||
\tparam VectorBase
|
||||
is a Simple Vector class with eleements of type Base.
|
||||
|
||||
\param q
|
||||
is the hightest order for this forward mode computation; i.e.,
|
||||
after this calculation there will be <code>q+1</code>
|
||||
Taylor coefficients per variable.
|
||||
|
||||
\param xq
|
||||
contains Taylor coefficients for the independent variables.
|
||||
The size of xq must either be n or <code>(q+1)*n</code>,
|
||||
We define <code>p = q + 1 - xq.size()/n</code>.
|
||||
For <code>j = 0 , ... , n-1</code>,
|
||||
<code>k = p, ... , q</code>, are
|
||||
<code>xq[ (q+1-p)*j + k - p ]</code>
|
||||
is the k-th order coefficient for the j-th independent variable.
|
||||
|
||||
\param s
|
||||
Is the stream where output corresponding to PriOp operations will written.
|
||||
|
||||
\return
|
||||
contains Taylor coefficients for the dependent variables.
|
||||
The size of the return value y is <code>m*(q+1-p)</code>.
|
||||
For <code>i = 0, ... , m-1</code>,
|
||||
<code>k = p, ..., q</code>,
|
||||
<code>y[(q+1-p)*i + (k-p)]</code>
|
||||
is the k-th order coefficient for the i-th dependent variable.
|
||||
|
||||
\par taylor_
|
||||
The Taylor coefficients up to order p-1 are inputs
|
||||
and the coefficents from order p through q are outputs.
|
||||
Let <code>N = num_var_tape_</code>, and
|
||||
<code>C = cap_order_taylor_</code>.
|
||||
Note that for
|
||||
<code>i = 1 , ..., N-1</code>,
|
||||
<code>k = 0 , ..., q</code>,
|
||||
<code>taylor_[ C*i + k ]</code>
|
||||
is the k-th order cofficent,
|
||||
for the i-th varaible on the tape.
|
||||
(The first independent variable has index one on the tape
|
||||
and there is no variable with index zero.)
|
||||
*/
|
||||
|
||||
template <typename Base>
|
||||
template <typename VectorBase>
|
||||
VectorBase ADFun<Base>::Forward(
|
||||
size_t q ,
|
||||
const VectorBase& xq ,
|
||||
std::ostream& s )
|
||||
{ // temporary indices
|
||||
size_t i, j, k;
|
||||
|
||||
// number of independent variables
|
||||
size_t n = ind_taddr_.size();
|
||||
|
||||
// number of dependent variables
|
||||
size_t m = dep_taddr_.size();
|
||||
|
||||
// check Vector is Simple Vector class with Base type elements
|
||||
CheckSimpleVector<Base, VectorBase>();
|
||||
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(xq.size()) == n || size_t(xq.size()) == n*(q+1),
|
||||
"Forward(q, xq): xq.size() is not equal n or n*(q+1)"
|
||||
);
|
||||
|
||||
// lowest order we are computing
|
||||
size_t p = q + 1 - size_t(xq.size()) / n;
|
||||
CPPAD_ASSERT_UNKNOWN( p == 0 || p == q );
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q <= num_order_taylor_ || p == 0,
|
||||
"Forward(q, xq): Number of Taylor coefficient orders stored in this"
|
||||
" ADFun\nis less than q and xq.size() != n*(q+1)."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
p <= 1 || num_direction_taylor_ == 1,
|
||||
"Forward(q, xq): computing order q >= 2"
|
||||
" and number of directions is not one."
|
||||
"\nMust use Forward(q, r, xq) for this case"
|
||||
);
|
||||
// does taylor_ need more orders or fewer directions
|
||||
if( (cap_order_taylor_ <= q) | (num_direction_taylor_ != 1) )
|
||||
{ if( p == 0 )
|
||||
{ // no need to copy old values during capacity_order
|
||||
num_order_taylor_ = 0;
|
||||
}
|
||||
else num_order_taylor_ = q;
|
||||
size_t c = std::max(q + 1, cap_order_taylor_);
|
||||
size_t r = 1;
|
||||
capacity_order(c, r);
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q );
|
||||
CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 1 );
|
||||
|
||||
// short hand notation for order capacity
|
||||
size_t C = cap_order_taylor_;
|
||||
|
||||
// The optimizer may skip a step that does not affect dependent variables.
|
||||
// Initilaizing zero order coefficients avoids following valgrind warning:
|
||||
// "Conditional jump or move depends on uninitialised value(s)".
|
||||
for(j = 0; j < num_var_tape_; j++)
|
||||
{ for(k = p; k <= q; k++)
|
||||
taylor_[C * j + k] = CppAD::numeric_limits<Base>::quiet_NaN();
|
||||
}
|
||||
|
||||
// set Taylor coefficients for independent variables
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );
|
||||
|
||||
// ind_taddr_[j] is operator taddr for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
if( p == q )
|
||||
taylor_[ C * ind_taddr_[j] + q] = xq[j];
|
||||
else
|
||||
{ for(k = 0; k <= q; k++)
|
||||
taylor_[ C * ind_taddr_[j] + k] = xq[ (q+1)*j + k];
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate the derivatives
|
||||
CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() );
|
||||
if( q == 0 )
|
||||
{ local::forward0sweep(s, true,
|
||||
n, num_var_tape_, &play_, C,
|
||||
taylor_.data(), cskip_op_.data(), load_op_,
|
||||
compare_change_count_,
|
||||
compare_change_number_,
|
||||
compare_change_op_index_
|
||||
);
|
||||
}
|
||||
else
|
||||
{ local::forward1sweep(s, true, p, q,
|
||||
n, num_var_tape_, &play_, C,
|
||||
taylor_.data(), cskip_op_.data(), load_op_,
|
||||
compare_change_count_,
|
||||
compare_change_number_,
|
||||
compare_change_op_index_
|
||||
);
|
||||
}
|
||||
|
||||
// return Taylor coefficients for dependent variables
|
||||
VectorBase yq;
|
||||
if( p == q )
|
||||
{ yq.resize(m);
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
yq[i] = taylor_[ C * dep_taddr_[i] + q];
|
||||
}
|
||||
}
|
||||
else
|
||||
{ yq.resize(m * (q+1) );
|
||||
for(i = 0; i < m; i++)
|
||||
{ for(k = 0; k <= q; k++)
|
||||
yq[ (q+1) * i + k] =
|
||||
taylor_[ C * dep_taddr_[i] + k ];
|
||||
}
|
||||
}
|
||||
# ifndef NDEBUG
|
||||
if( check_for_nan_ )
|
||||
{ bool ok = true;
|
||||
size_t index = m;
|
||||
if( p == 0 )
|
||||
{ for(i = 0; i < m; i++)
|
||||
{ // Visual Studio 2012, CppAD required in front of isnan ?
|
||||
if( CppAD::isnan( yq[ (q+1) * i + 0 ] ) )
|
||||
{ ok = false;
|
||||
if( index == m )
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( ! ok )
|
||||
{ CPPAD_ASSERT_UNKNOWN( index < m );
|
||||
//
|
||||
CppAD::vector<Base> x0(n);
|
||||
for(j = 0; j < n; j++)
|
||||
x0[j] = taylor_[ C * ind_taddr_[j] + 0 ];
|
||||
std::string file_name;
|
||||
put_check_for_nan(x0, file_name);
|
||||
std::stringstream ss;
|
||||
ss <<
|
||||
"yq = f.Forward(q, xq): a zero order Taylor coefficient is nan.\n"
|
||||
"Corresponding independent variables vector was written "
|
||||
"to binary a file.\n"
|
||||
"vector_size = " << n << "\n" <<
|
||||
"file_name = " << file_name << "\n" <<
|
||||
"index = " << index << "\n";
|
||||
// ss.str() returns a string object with a copy of the current
|
||||
// contents in the stream buffer.
|
||||
std::string msg_str = ss.str();
|
||||
// msg_str.c_str() returns a pointer to the c-string
|
||||
// representation of the string object's value.
|
||||
const char* msg_char_star = msg_str.c_str();
|
||||
ErrorHandler::Call(
|
||||
true,
|
||||
__LINE__,
|
||||
__FILE__,
|
||||
"if( CppAD::isnan( yq[ (q+1) * index + 0 ] )",
|
||||
msg_char_star
|
||||
);
|
||||
}
|
||||
CPPAD_ASSERT_KNOWN(ok,
|
||||
"with the value nan."
|
||||
);
|
||||
if( 0 < q )
|
||||
{ for(i = 0; i < m; i++)
|
||||
{ for(k = p; k <= q; k++)
|
||||
{ // Studio 2012, CppAD required in front of isnan ?
|
||||
ok &= ! CppAD::isnan( yq[ (q+1-p)*i + k-p ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
CPPAD_ASSERT_KNOWN(ok,
|
||||
"yq = f.Forward(q, xq): has a non-zero order Taylor coefficient\n"
|
||||
"with the value nan (but zero order coefficients are not nan)."
|
||||
);
|
||||
}
|
||||
# endif
|
||||
|
||||
// now we have q + 1 taylor_ coefficient orders per variable
|
||||
num_order_taylor_ = q + 1;
|
||||
|
||||
return yq;
|
||||
}
|
||||
|
||||
/*!
|
||||
One order, multiple directions, forward mode Taylor coefficieints.
|
||||
|
||||
\tparam Base
|
||||
The type used during the forward mode computations; i.e., the corresponding
|
||||
recording of operations used the type AD<Base>.
|
||||
|
||||
\tparam VectorBase
|
||||
is a Simple Vector class with eleements of type Base.
|
||||
|
||||
\param q
|
||||
is the order for this forward mode computation,
|
||||
<code>q > 0</code>.
|
||||
There must be at least <code>q</code> Taylor coefficients
|
||||
per variable before this call.
|
||||
After this call there will be <code>q+1</code>
|
||||
Taylor coefficients per variable.
|
||||
|
||||
\param r
|
||||
is the number of directions for this calculation.
|
||||
If <code>q != 1</code>, \c r must be the same as in the previous
|
||||
call to Forward where \c q was equal to one.
|
||||
|
||||
\param xq
|
||||
contains Taylor coefficients for the independent variables.
|
||||
The size of xq must either be <code>r*n</code>,
|
||||
For <code>j = 0 , ... , n-1</code>,
|
||||
<code>ell = 0, ... , r-1</code>,
|
||||
<code>xq[ ( r*j + ell ]</code>
|
||||
is the q-th order coefficient for the j-th independent variable
|
||||
and the ell-th direction.
|
||||
|
||||
\return
|
||||
contains Taylor coefficients for the dependent variables.
|
||||
The size of the return value \c y is <code>r*m</code>.
|
||||
For <code>i = 0, ... , m-1</code>,
|
||||
<code>ell = 0, ... , r-1</code>,
|
||||
<code>y[ r*i + ell ]</code>
|
||||
is the q-th order coefficient for the i-th dependent variable
|
||||
and the ell-th direction.
|
||||
|
||||
\par taylor_
|
||||
The Taylor coefficients up to order <code>q-1</code> are inputs
|
||||
and the coefficents of order \c q are outputs.
|
||||
Let <code>N = num_var_tape_</code>, and
|
||||
<code>C = cap_order_taylor_</code>.
|
||||
Note that for
|
||||
<code>i = 1 , ..., N-1</code>,
|
||||
<code>taylor_[ (C-1)*r*i + i + 0 ]</code>
|
||||
is the zero order cofficent,
|
||||
for the i-th varaible, and all directions.
|
||||
For <code>i = 1 , ..., N-1</code>,
|
||||
<code>k = 1 , ..., q</code>,
|
||||
<code>ell = 0 , ..., r-1</code>,
|
||||
<code>taylor_[ (C-1)*r*i + i + (k-1)*r + ell + 1 ]</code>
|
||||
is the k-th order cofficent,
|
||||
for the i-th varaible, and ell-th direction.
|
||||
(The first independent variable has index one on the tape
|
||||
and there is no variable with index zero.)
|
||||
*/
|
||||
|
||||
template <typename Base>
|
||||
template <typename VectorBase>
|
||||
VectorBase ADFun<Base>::Forward(
|
||||
size_t q ,
|
||||
size_t r ,
|
||||
const VectorBase& xq )
|
||||
{ // temporary indices
|
||||
size_t i, j, ell;
|
||||
|
||||
// number of independent variables
|
||||
size_t n = ind_taddr_.size();
|
||||
|
||||
// number of dependent variables
|
||||
size_t m = dep_taddr_.size();
|
||||
|
||||
// check Vector is Simple Vector class with Base type elements
|
||||
CheckSimpleVector<Base, VectorBase>();
|
||||
|
||||
CPPAD_ASSERT_KNOWN( q > 0, "Forward(q, r, xq): q == 0" );
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(xq.size()) == r * n,
|
||||
"Forward(q, r, xq): xq.size() is not equal r * n"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q <= num_order_taylor_ ,
|
||||
"Forward(q, r, xq): Number of Taylor coefficient orders stored in"
|
||||
" this ADFun is less than q"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q == 1 || num_direction_taylor_ == r ,
|
||||
"Forward(q, r, xq): q > 1 and number of Taylor directions r"
|
||||
" is not same as previous Forward(1, r, xq)"
|
||||
);
|
||||
|
||||
// does taylor_ need more orders or new number of directions
|
||||
if( cap_order_taylor_ <= q || num_direction_taylor_ != r )
|
||||
{ if( num_direction_taylor_ != r )
|
||||
num_order_taylor_ = 1;
|
||||
|
||||
size_t c = std::max(q + 1, cap_order_taylor_);
|
||||
capacity_order(c, r);
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ > q );
|
||||
CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == r )
|
||||
|
||||
// short hand notation for order capacity
|
||||
size_t c = cap_order_taylor_;
|
||||
|
||||
// set Taylor coefficients for independent variables
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );
|
||||
|
||||
// ind_taddr_[j] is operator taddr for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ size_t index = ((c-1)*r + 1)*ind_taddr_[j] + (q-1)*r + ell + 1;
|
||||
taylor_[ index ] = xq[ r * j + ell ];
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate the derivatives
|
||||
CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() );
|
||||
local::forward2sweep(
|
||||
q,
|
||||
r,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
c,
|
||||
taylor_.data(),
|
||||
cskip_op_.data(),
|
||||
load_op_
|
||||
);
|
||||
|
||||
// return Taylor coefficients for dependent variables
|
||||
VectorBase yq;
|
||||
yq.resize(r * m);
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
for(ell = 0; ell < r; ell++)
|
||||
{ size_t index = ((c-1)*r + 1)*dep_taddr_[i] + (q-1)*r + ell + 1;
|
||||
yq[ r * i + ell ] = taylor_[ index ];
|
||||
}
|
||||
}
|
||||
# ifndef NDEBUG
|
||||
if( check_for_nan_ )
|
||||
{ bool ok = true;
|
||||
for(i = 0; i < m; i++)
|
||||
{ for(ell = 0; ell < r; ell++)
|
||||
{ // Studio 2012, CppAD required in front of isnan ?
|
||||
ok &= ! CppAD::isnan( yq[ r * i + ell ] );
|
||||
}
|
||||
}
|
||||
CPPAD_ASSERT_KNOWN(ok,
|
||||
"yq = f.Forward(q, r, xq): has a non-zero order Taylor coefficient\n"
|
||||
"with the value nan (but zero order coefficients are not nan)."
|
||||
);
|
||||
}
|
||||
# endif
|
||||
|
||||
// now we have q + 1 taylor_ coefficient orders per variable
|
||||
num_order_taylor_ = q + 1;
|
||||
|
||||
return yq;
|
||||
}
|
||||
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
# ifndef CPPAD_CORE_FUN_CHECK_HPP
|
||||
# define CPPAD_CORE_FUN_CHECK_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 FunCheck$$
|
||||
$spell
|
||||
exp
|
||||
bool
|
||||
const
|
||||
Taylor
|
||||
$$
|
||||
|
||||
|
||||
$section Check an ADFun Sequence of Operations$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%ok% = FunCheck(%f%, %g%, %x%, %r%, %a%)%$$
|
||||
$pre
|
||||
$$
|
||||
$bold See Also$$
|
||||
$cref CompareChange$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : B^n \rightarrow B^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$.
|
||||
We use $latex G : B^n \rightarrow B^m$$ to denote the
|
||||
function corresponding to the C++ function object $icode g$$.
|
||||
This routine check if
|
||||
$latex \[
|
||||
F(x) = G(x)
|
||||
\]$$
|
||||
If $latex F(x) \neq G(x)$$, the
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$
|
||||
corresponding to $icode f$$ does not represents the algorithm used
|
||||
by $icode g$$ to calculate values for $latex G$$
|
||||
(see $cref/Discussion/FunCheck/Discussion/$$ below).
|
||||
|
||||
$head f$$
|
||||
The $code FunCheck$$ argument $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
Note that the $cref ADFun$$ object $icode f$$ is not $code const$$
|
||||
(see $cref/Forward/FunCheck/FunCheck Uses Forward/$$ below).
|
||||
|
||||
$head g$$
|
||||
The $code FunCheck$$ argument $icode g$$ has prototype
|
||||
$codei%
|
||||
%Fun% &%g%
|
||||
%$$
|
||||
($icode Fun$$ is defined the properties of $icode g$$).
|
||||
The C++ function object $icode g$$ supports the syntax
|
||||
$codei%
|
||||
%y% = %g%(%x%)
|
||||
%$$
|
||||
which computes $latex y = G(x)$$.
|
||||
|
||||
$subhead x$$
|
||||
The $icode g$$ argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Vector% &%x%
|
||||
%$$
|
||||
(see $cref/Vector/FunCheck/Vector/$$ below)
|
||||
and its size
|
||||
must be equal to $icode n$$, the dimension of the
|
||||
$cref/domain/seq_property/Domain/$$ space for $icode f$$.
|
||||
|
||||
$head y$$
|
||||
The $icode g$$ result $icode y$$ has prototype
|
||||
$codei%
|
||||
%Vector% %y%
|
||||
%$$
|
||||
and its value is $latex G(x)$$.
|
||||
The size of $icode y$$
|
||||
is equal to $icode m$$, the dimension of the
|
||||
$cref/range/seq_property/Range/$$ space for $icode f$$.
|
||||
|
||||
$head x$$
|
||||
The $code FunCheck$$ argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Vector% &%x%
|
||||
%$$
|
||||
and its size
|
||||
must be equal to $icode n$$, the dimension of the
|
||||
$cref/domain/seq_property/Domain/$$ space for $icode f$$.
|
||||
This specifies that point at which to compare the values
|
||||
calculated by $icode f$$ and $icode G$$.
|
||||
|
||||
$head r$$
|
||||
The $code FunCheck$$ argument $icode r$$ has prototype
|
||||
$codei%
|
||||
const %Base% &%r%
|
||||
%$$
|
||||
It specifies the relative error the element by element
|
||||
comparison of the value of $latex F(x)$$ and $latex G(x)$$.
|
||||
|
||||
$head a$$
|
||||
The $code FunCheck$$ argument $icode a$$ has prototype
|
||||
$codei%
|
||||
const %Base% &%a%
|
||||
%$$
|
||||
It specifies the absolute error the element by element
|
||||
comparison of the value of $latex F(x)$$ and $latex G(x)$$.
|
||||
|
||||
$head ok$$
|
||||
The $code FunCheck$$ result $icode ok$$ has prototype
|
||||
$codei%
|
||||
bool %ok%
|
||||
%$$
|
||||
It is true, if for $latex i = 0 , \ldots , m-1$$
|
||||
either the relative error bound is satisfied
|
||||
$latex \[
|
||||
| F_i (x) - G_i (x) |
|
||||
\leq
|
||||
r ( | F_i (x) | + | G_i (x) | )
|
||||
\] $$
|
||||
or the absolute error bound is satisfied
|
||||
$latex \[
|
||||
| F_i (x) - G_i (x) | \leq a
|
||||
\] $$
|
||||
It is false if for some $latex (i, j)$$ neither
|
||||
of these bounds is satisfied.
|
||||
|
||||
$head Vector$$
|
||||
The type $icode Vector$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$icode Base$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head FunCheck Uses Forward$$
|
||||
After each call to $cref Forward$$,
|
||||
the object $icode f$$ contains the corresponding
|
||||
$cref/Taylor coefficients/glossary/Taylor Coefficient/$$.
|
||||
After $code FunCheck$$,
|
||||
the previous calls to $cref Forward$$ are undefined.
|
||||
|
||||
$head Discussion$$
|
||||
Suppose that the algorithm corresponding to $icode g$$ contains
|
||||
$codei%
|
||||
if( %x% >= 0 )
|
||||
%y% = exp(%x%)
|
||||
else %y% = exp(-%x%)
|
||||
%$$
|
||||
where $icode x$$ and $icode y$$ are $codei%AD<double>%$$ objects.
|
||||
It follows that the
|
||||
AD of $code double$$ $cref/operation sequence/glossary/Operation/Sequence/$$
|
||||
depends on the value of $icode x$$.
|
||||
If the sequence of operations stored in $icode f$$ corresponds to
|
||||
$icode g$$ with $latex x \geq 0$$,
|
||||
the function values computed using $icode f$$ when $latex x < 0$$
|
||||
will not agree with the function values computed by $latex g$$.
|
||||
This is because the operation sequence corresponding to $icode g$$ changed
|
||||
(and hence the object $icode f$$ does not represent the function
|
||||
$latex G$$ for this value of $icode x$$).
|
||||
In this case, you probably want to re-tape the calculations
|
||||
performed by $icode g$$ with the
|
||||
$cref/independent variables/glossary/Tape/Independent Variable/$$
|
||||
equal to the values in $icode x$$
|
||||
(so AD operation sequence properly represents the algorithm
|
||||
for this value of independent variables).
|
||||
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/fun_check.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref fun_check.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD {
|
||||
template <class Base, class Fun, class Vector>
|
||||
bool FunCheck(
|
||||
ADFun<Base> &f ,
|
||||
Fun &g ,
|
||||
const Vector &x ,
|
||||
const Base &r ,
|
||||
const Base &a )
|
||||
{ bool ok = true;
|
||||
|
||||
size_t m = f.Range();
|
||||
Vector yf = f.Forward(0, x);
|
||||
Vector yg = g(x);
|
||||
|
||||
size_t i;
|
||||
for(i = 0; i < m; i++)
|
||||
ok &= NearEqual(yf[i], yg[i], r, a);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
# endif
|
||||
+488
@@ -0,0 +1,488 @@
|
||||
# ifndef CPPAD_CORE_FUN_CONSTRUCT_HPP
|
||||
# define CPPAD_CORE_FUN_CONSTRUCT_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 FunConstruct$$
|
||||
$spell
|
||||
alloc
|
||||
num
|
||||
Jac
|
||||
bool
|
||||
taylor
|
||||
var
|
||||
ADvector
|
||||
const
|
||||
Jacobian
|
||||
$$
|
||||
|
||||
$spell
|
||||
$$
|
||||
|
||||
$section Construct an ADFun Object and Stop Recording$$
|
||||
$mindex tape$$
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
$codei%ADFun<%Base%> %f%, %g%
|
||||
%$$
|
||||
$codei%ADFun<%Base%> %f%(%x%, %y%)
|
||||
%$$
|
||||
$icode%g% = %f%
|
||||
%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
The $codei%AD<%Base%>%$$ object $icode f$$ can
|
||||
store an AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
It can then be used to calculate derivatives of the corresponding
|
||||
$cref/AD function/glossary/AD Function/$$
|
||||
$latex \[
|
||||
F : B^n \rightarrow B^m
|
||||
\] $$
|
||||
where $latex B$$ is the space corresponding to objects of type $icode Base$$.
|
||||
|
||||
$head x$$
|
||||
If the argument $icode x$$ is present, it has prototype
|
||||
$codei%
|
||||
const %VectorAD% &%x%
|
||||
%$$
|
||||
It must be the vector argument in the previous call to
|
||||
$cref Independent$$.
|
||||
Neither its size, or any of its values, are allowed to change
|
||||
between calling
|
||||
$codei%
|
||||
Independent(%x%)
|
||||
%$$
|
||||
and
|
||||
$codei%
|
||||
ADFun<%Base%> %f%(%x%, %y%)
|
||||
%$$
|
||||
|
||||
$head y$$
|
||||
If the argument $icode y$$ is present, it has prototype
|
||||
$codei%
|
||||
const %VectorAD% &%y%
|
||||
%$$
|
||||
The sequence of operations that map $icode x$$
|
||||
to $icode y$$ are stored in the ADFun object $icode f$$.
|
||||
|
||||
$head VectorAD$$
|
||||
The type $icode VectorAD$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$codei%AD<%Base%>%$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head Default Constructor$$
|
||||
The default constructor
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
creates an
|
||||
$codei%AD<%Base%>%$$ object with no corresponding operation sequence; i.e.,
|
||||
$codei%
|
||||
%f%.size_var()
|
||||
%$$
|
||||
returns the value zero (see $cref/size_var/seq_property/size_var/$$).
|
||||
|
||||
$head Sequence Constructor$$
|
||||
The sequence constructor
|
||||
$codei%
|
||||
ADFun<%Base%> %f%(%x%, %y%)
|
||||
%$$
|
||||
creates the $codei%AD<%Base%>%$$ object $icode f$$,
|
||||
stops the recording of AD of $icode Base$$ operations
|
||||
corresponding to the call
|
||||
$codei%
|
||||
Independent(%x%)
|
||||
%$$
|
||||
and stores the corresponding operation sequence in the object $icode f$$.
|
||||
It then stores the zero order Taylor coefficients
|
||||
(corresponding to the value of $icode x$$) in $icode f$$.
|
||||
This is equivalent to the following steps using the default constructor:
|
||||
|
||||
$list number$$
|
||||
Create $icode f$$ with the default constructor
|
||||
$codei%
|
||||
ADFun<%Base%> %f%;
|
||||
%$$
|
||||
$lnext
|
||||
Stop the tape and storing the operation sequence using
|
||||
$codei%
|
||||
%f%.Dependent(%x%, %y%);
|
||||
%$$
|
||||
(see $cref Dependent$$).
|
||||
$lnext
|
||||
Calculate the zero order Taylor coefficients for all
|
||||
the variables in the operation sequence using
|
||||
$codei%
|
||||
%f%.Forward(%p%, %x_p%)
|
||||
%$$
|
||||
with $icode p$$ equal to zero and the elements of $icode x_p$$
|
||||
equal to the corresponding elements of $icode x$$
|
||||
(see $cref Forward$$).
|
||||
$lend
|
||||
|
||||
$head Copy Constructor$$
|
||||
It is an error to attempt to use the $codei%ADFun<%Base%>%$$ copy constructor;
|
||||
i.e., the following syntax is not allowed:
|
||||
$codei%
|
||||
ADFun<%Base%> %g%(%f%)
|
||||
%$$
|
||||
where $icode f$$ is an $codei%ADFun<%Base%>%$$ object.
|
||||
Use its $cref/default constructor/FunConstruct/Default Constructor/$$ instead
|
||||
and its assignment operator.
|
||||
|
||||
$head Assignment Operator$$
|
||||
The $codei%ADFun<%Base%>%$$ assignment operation
|
||||
$codei%
|
||||
%g% = %f%
|
||||
%$$
|
||||
makes a copy of the operation sequence currently stored in $icode f$$
|
||||
in the object $icode g$$.
|
||||
The object $icode f$$ is not affected by this operation and
|
||||
can be $code const$$.
|
||||
All of information (state) stored in $icode f$$ is copied to $icode g$$
|
||||
and any information originally in $icode g$$ is lost.
|
||||
|
||||
$subhead Taylor Coefficients$$
|
||||
The Taylor coefficient information currently stored in $icode f$$
|
||||
(computed by $cref/f.Forward/Forward/$$) is
|
||||
copied to $icode g$$.
|
||||
Hence, directly after this operation
|
||||
$codei%
|
||||
%g%.size_order() == %f%.size_order()
|
||||
%$$
|
||||
|
||||
$subhead Sparsity Patterns$$
|
||||
The forward Jacobian sparsity pattern currently stored in $icode f$$
|
||||
(computed by $cref/f.ForSparseJac/ForSparseJac/$$) is
|
||||
copied to $icode g$$.
|
||||
Hence, directly after this operation
|
||||
$codei%
|
||||
%g%.size_forward_bool() == %f%.size_forward_bool()
|
||||
%g%.size_forward_set() == %f%.size_forward_set()
|
||||
%$$
|
||||
|
||||
$head Parallel Mode$$
|
||||
The call to $code Independent$$,
|
||||
and the corresponding call to
|
||||
$codei%
|
||||
ADFun<%Base%> %f%( %x%, %y%)
|
||||
%$$
|
||||
or
|
||||
$codei%
|
||||
%f%.Dependent( %x%, %y%)
|
||||
%$$
|
||||
or $cref abort_recording$$,
|
||||
must be preformed by the same thread; i.e.,
|
||||
$cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same.
|
||||
|
||||
$head Example$$
|
||||
|
||||
$subhead Sequence Constructor$$
|
||||
The file
|
||||
$cref independent.cpp$$
|
||||
contains an example and test of the sequence constructor.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$subhead Default Constructor$$
|
||||
The files
|
||||
$cref fun_check.cpp$$
|
||||
and
|
||||
$cref hes_lagrangian.cpp$$
|
||||
contain an examples and tests using the default constructor.
|
||||
They return true if they succeed and false otherwise.
|
||||
|
||||
$children%
|
||||
example/general/fun_assign.cpp
|
||||
%$$
|
||||
$subhead Assignment Operator$$
|
||||
The file
|
||||
$cref fun_assign.cpp$$
|
||||
contains an example and test of the $codei%ADFun<%Base%>%$$
|
||||
assignment operator.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file fun_construct.hpp
|
||||
ADFun function constructors and assignment operator.
|
||||
*/
|
||||
|
||||
/*!
|
||||
ADFun default constructor
|
||||
|
||||
The C++ syntax for this operation is
|
||||
\verbatim
|
||||
ADFun<Base> f
|
||||
\endverbatim
|
||||
An empty ADFun object is created.
|
||||
The Dependent member function,
|
||||
or the ADFun<Base> assingment operator,
|
||||
can then be used to put an operation sequence in this ADFun object.
|
||||
|
||||
\tparam Base
|
||||
is the base for the recording that can be stored in this ADFun object;
|
||||
i.e., operation sequences that were recorded using the type \c AD<Base>.
|
||||
*/
|
||||
template <typename Base>
|
||||
ADFun<Base>::ADFun(void) :
|
||||
has_been_optimized_(false),
|
||||
check_for_nan_(true) ,
|
||||
compare_change_count_(1),
|
||||
compare_change_number_(0),
|
||||
compare_change_op_index_(0),
|
||||
num_var_tape_(0)
|
||||
{ }
|
||||
|
||||
/*!
|
||||
ADFun assignment operator
|
||||
|
||||
The C++ syntax for this operation is
|
||||
\verbatim
|
||||
g = f
|
||||
\endverbatim
|
||||
where \c g and \c f are ADFun<Base> ADFun objects.
|
||||
A copy of the the operation sequence currently stored in \c f
|
||||
is placed in this ADFun object (called \c g above).
|
||||
Any information currently stored in this ADFun object is lost.
|
||||
|
||||
\tparam Base
|
||||
is the base for the recording that can be stored in this ADFun object;
|
||||
i.e., operation sequences that were recorded using the type \c AD<Base>.
|
||||
|
||||
\param f
|
||||
ADFun object containing the operation sequence to be copied.
|
||||
*/
|
||||
template <typename Base>
|
||||
void ADFun<Base>::operator=(const ADFun<Base>& f)
|
||||
{ size_t m = f.Range();
|
||||
size_t n = f.Domain();
|
||||
size_t i;
|
||||
|
||||
// go through member variables in ad_fun.hpp order
|
||||
//
|
||||
// size_t objects
|
||||
has_been_optimized_ = f.has_been_optimized_;
|
||||
check_for_nan_ = f.check_for_nan_;
|
||||
compare_change_count_ = f.compare_change_count_;
|
||||
compare_change_number_ = f.compare_change_number_;
|
||||
compare_change_op_index_ = f.compare_change_op_index_;
|
||||
num_order_taylor_ = f.num_order_taylor_;
|
||||
cap_order_taylor_ = f.cap_order_taylor_;
|
||||
num_direction_taylor_ = f.num_direction_taylor_;
|
||||
num_var_tape_ = f.num_var_tape_;
|
||||
//
|
||||
// CppAD::vector objects
|
||||
ind_taddr_.resize(n);
|
||||
ind_taddr_ = f.ind_taddr_;
|
||||
dep_taddr_.resize(m);
|
||||
dep_taddr_ = f.dep_taddr_;
|
||||
dep_parameter_.resize(m);
|
||||
dep_parameter_ = f.dep_parameter_;
|
||||
//
|
||||
// pod_vector objects
|
||||
taylor_ = f.taylor_;
|
||||
cskip_op_ = f.cskip_op_;
|
||||
load_op_ = f.load_op_;
|
||||
//
|
||||
// player
|
||||
play_ = f.play_;
|
||||
//
|
||||
// sparse_pack
|
||||
for_jac_sparse_pack_.resize(0, 0);
|
||||
size_t n_set = f.for_jac_sparse_pack_.n_set();
|
||||
size_t end = f.for_jac_sparse_pack_.end();
|
||||
if( n_set > 0 )
|
||||
{ CPPAD_ASSERT_UNKNOWN( n_set == num_var_tape_ );
|
||||
CPPAD_ASSERT_UNKNOWN( f.for_jac_sparse_set_.n_set() == 0 );
|
||||
for_jac_sparse_pack_.resize(n_set, end);
|
||||
for(i = 0; i < num_var_tape_ ; i++)
|
||||
{ for_jac_sparse_pack_.assignment(
|
||||
i ,
|
||||
i ,
|
||||
f.for_jac_sparse_pack_
|
||||
);
|
||||
}
|
||||
}
|
||||
//
|
||||
// sparse_set
|
||||
for_jac_sparse_set_.resize(0, 0);
|
||||
n_set = f.for_jac_sparse_set_.n_set();
|
||||
end = f.for_jac_sparse_set_.end();
|
||||
if( n_set > 0 )
|
||||
{ CPPAD_ASSERT_UNKNOWN( n_set == num_var_tape_ );
|
||||
CPPAD_ASSERT_UNKNOWN( f.for_jac_sparse_pack_.n_set() == 0 );
|
||||
for_jac_sparse_set_.resize(n_set, end);
|
||||
for(i = 0; i < num_var_tape_; i++)
|
||||
{ for_jac_sparse_set_.assignment(
|
||||
i ,
|
||||
i ,
|
||||
f.for_jac_sparse_set_
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
ADFun constructor from an operation sequence.
|
||||
|
||||
The C++ syntax for this operation is
|
||||
\verbatim
|
||||
ADFun<Base> f(x, y)
|
||||
\endverbatim
|
||||
The operation sequence that started with the previous call
|
||||
\c Independent(x), and that ends with this operation, is stored
|
||||
in this \c ADFun<Base> object \c f.
|
||||
|
||||
\tparam Base
|
||||
is the base for the recording that will be stored in the object \c f;
|
||||
i.e., the operations were recorded using the type \c AD<Base>.
|
||||
|
||||
\tparam VectorAD
|
||||
is a simple vector class with elements of typea \c AD<Base>.
|
||||
|
||||
\param x
|
||||
is the independent variable vector for this ADFun object.
|
||||
The domain dimension of this object will be the size of \a x.
|
||||
|
||||
\param y
|
||||
is the dependent variable vector for this ADFun object.
|
||||
The range dimension of this object will be the size of \a y.
|
||||
|
||||
\par Taylor Coefficients
|
||||
A zero order forward mode sweep is done,
|
||||
and if NDEBUG is not defined the resulting values for the
|
||||
depenedent variables are checked against the values in \a y.
|
||||
Thus, the zero order Taylor coefficients
|
||||
corresponding to the value of the \a x vector
|
||||
are stored in this ADFun object.
|
||||
*/
|
||||
template <typename Base>
|
||||
template <typename VectorAD>
|
||||
ADFun<Base>::ADFun(const VectorAD &x, const VectorAD &y)
|
||||
{
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
x.size() > 0,
|
||||
"ADFun<Base>: independent variable vector has size zero."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
Variable(x[0]),
|
||||
"ADFun<Base>: independent variable vector has been changed."
|
||||
);
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr(x[0].tape_id_);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
tape->size_independent_ == size_t ( x.size() ),
|
||||
"ADFun<Base>: independent variable vector has been changed."
|
||||
);
|
||||
size_t j, n = x.size();
|
||||
# ifndef NDEBUG
|
||||
size_t i, m = y.size();
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
size_t(x[j].taddr_) == (j+1),
|
||||
"ADFun<Base>: independent variable vector has been changed."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
x[j].tape_id_ == x[0].tape_id_,
|
||||
"ADFun<Base>: independent variable vector has been changed."
|
||||
);
|
||||
}
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
CppAD::Parameter( y[i] ) | (y[i].tape_id_ == x[0].tape_id_) ,
|
||||
"ADFun<Base>: dependent vector contains variables for"
|
||||
"\na different tape than the independent variables."
|
||||
);
|
||||
}
|
||||
# endif
|
||||
|
||||
// stop the tape and store the operation sequence
|
||||
Dependent(tape, y);
|
||||
|
||||
|
||||
// ad_fun.hpp member values not set by dependent
|
||||
check_for_nan_ = true;
|
||||
|
||||
// allocate memory for one zero order taylor_ coefficient
|
||||
CPPAD_ASSERT_UNKNOWN( num_order_taylor_ == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == 0 );
|
||||
size_t c = 1;
|
||||
size_t r = 1;
|
||||
capacity_order(c, r);
|
||||
CPPAD_ASSERT_UNKNOWN( cap_order_taylor_ == c );
|
||||
CPPAD_ASSERT_UNKNOWN( num_direction_taylor_ == r );
|
||||
|
||||
// set zero order coefficients corresponding to indpendent variables
|
||||
CPPAD_ASSERT_UNKNOWN( n == ind_taddr_.size() );
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(x[j].taddr_) == (j+1) );
|
||||
taylor_[ ind_taddr_[j] ] = x[j].value_;
|
||||
}
|
||||
|
||||
// use independent variable values to fill in values for others
|
||||
CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() );
|
||||
local::forward0sweep(std::cout, false,
|
||||
n, num_var_tape_, &play_, cap_order_taylor_, taylor_.data(),
|
||||
cskip_op_.data(), load_op_,
|
||||
compare_change_count_,
|
||||
compare_change_number_,
|
||||
compare_change_op_index_
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( compare_change_count_ == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( compare_change_number_ == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( compare_change_op_index_ == 0 );
|
||||
|
||||
// now set the number of orders stored
|
||||
num_order_taylor_ = 1;
|
||||
|
||||
# ifndef NDEBUG
|
||||
// on MS Visual Studio 2012, CppAD required in front of isnan ?
|
||||
for(i = 0; i < m; i++)
|
||||
if( taylor_[dep_taddr_[i]] != y[i].value_ || CppAD::isnan( y[i].value_ ) )
|
||||
{ using std::endl;
|
||||
std::ostringstream buf;
|
||||
buf << "A dependent variable value is not equal to "
|
||||
<< "its tape evaluation value," << endl
|
||||
<< "perhaps it is nan." << endl
|
||||
<< "Dependent variable value = "
|
||||
<< y[i].value_ << endl
|
||||
<< "Tape evaluation value = "
|
||||
<< taylor_[dep_taddr_[i]] << endl
|
||||
<< "Difference = "
|
||||
<< y[i].value_ - taylor_[dep_taddr_[i]] << endl
|
||||
;
|
||||
// buf.str() returns a string object with a copy of the current
|
||||
// contents in the stream buffer.
|
||||
std::string msg_str = buf.str();
|
||||
// msg_str.c_str() returns a pointer to the c-string
|
||||
// representation of the string object's value.
|
||||
const char* msg_char_star = msg_str.c_str();
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
0,
|
||||
msg_char_star
|
||||
);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# ifndef CPPAD_CORE_FUN_EVAL_HPP
|
||||
# define CPPAD_CORE_FUN_EVAL_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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/core/forward.hpp>
|
||||
# include <cppad/core/reverse.hpp>
|
||||
# include <cppad/core/sparse.hpp>
|
||||
|
||||
# endif
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_HASH_CODE_HPP
|
||||
# define CPPAD_CORE_HASH_CODE_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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.
|
||||
-------------------------------------------------------------------------- */
|
||||
/*!
|
||||
\file core/hash_code.hpp
|
||||
CppAD hashing utility.
|
||||
*/
|
||||
# include <cppad/local/hash_code.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
General purpose hash code for an arbitrary value.
|
||||
|
||||
\tparam Value
|
||||
is the type of the argument being hash coded.
|
||||
It should be a plain old data class; i.e.,
|
||||
the values included in the equality operator in the object and
|
||||
not pointed to by the object.
|
||||
|
||||
\param value
|
||||
the value that we are generating a hash code for.
|
||||
All of the fields in value should have been set before the hash code
|
||||
is computed (otherwise undefined values are used).
|
||||
|
||||
\return
|
||||
is a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.
|
||||
|
||||
\par Checked Assertions
|
||||
\li \c std::numeric_limits<unsigned short>::max() >= CPPAD_HASH_TABLE_SIZE
|
||||
\li \c sizeof(value) is even
|
||||
\li \c sizeof(unsigned short) == 2
|
||||
*/
|
||||
template <class Value>
|
||||
unsigned short hash_code(const Value& value)
|
||||
{ return local::local_hash_code(value); }
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
|
||||
# endif
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
# ifndef CPPAD_CORE_HESSIAN_HPP
|
||||
# define CPPAD_CORE_HESSIAN_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 Hessian$$
|
||||
$spell
|
||||
hes
|
||||
typename
|
||||
Taylor
|
||||
HesLuDet
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section Hessian: Easy Driver$$
|
||||
$mindex second derivative$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%hes% = %f%.Hessian(%x%, %w%)
|
||||
%$$
|
||||
$icode%hes% = %f%.Hessian(%x%, %l%)
|
||||
%$$
|
||||
|
||||
|
||||
$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 $icode hes$$ to the Hessian
|
||||
The syntax above sets $icode h$$ to the Hessian
|
||||
$latex \[
|
||||
hes = \dpow{2}{x} \sum_{i=1}^m w_i F_i (x)
|
||||
\] $$
|
||||
The routine $cref sparse_hessian$$ may be faster in the case
|
||||
where the Hessian is sparse.
|
||||
|
||||
$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/Hessian Uses Forward/Hessian/Hessian Uses Forward/$$ below).
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Vector% &%x%
|
||||
%$$
|
||||
(see $cref/Vector/Hessian/Vector/$$ 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 Hessian.
|
||||
|
||||
$head l$$
|
||||
If the argument $icode l$$ is present, it has prototype
|
||||
$codei%
|
||||
size_t %l%
|
||||
%$$
|
||||
and is less than $icode m$$, the dimension of the
|
||||
$cref/range/seq_property/Range/$$ space for $icode f$$.
|
||||
It specifies the component of $icode F$$
|
||||
for which we are evaluating the Hessian.
|
||||
To be specific, in the case where the argument $icode l$$ is present,
|
||||
$latex \[
|
||||
w_i = \left\{ \begin{array}{ll}
|
||||
1 & i = l \\
|
||||
0 & {\rm otherwise}
|
||||
\end{array} \right.
|
||||
\] $$
|
||||
|
||||
$head w$$
|
||||
If the argument $icode w$$ is present, it has prototype
|
||||
$codei%
|
||||
const %Vector% &%w%
|
||||
%$$
|
||||
and size $latex m$$.
|
||||
It specifies the value of $latex w_i$$ in the expression
|
||||
for $icode h$$.
|
||||
|
||||
$head hes$$
|
||||
The result $icode hes$$ has prototype
|
||||
$codei%
|
||||
%Vector% %hes%
|
||||
%$$
|
||||
(see $cref/Vector/Hessian/Vector/$$ below)
|
||||
and its size is $latex n * n$$.
|
||||
For $latex j = 0 , \ldots , n - 1 $$
|
||||
and $latex \ell = 0 , \ldots , n - 1$$
|
||||
$latex \[
|
||||
hes [ j * n + \ell ] = \DD{ w^{\rm T} F }{ x_j }{ x_\ell } ( x )
|
||||
\] $$
|
||||
|
||||
$head Vector$$
|
||||
The type $icode Vector$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$icode Base$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head Hessian 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 Hessian$$,
|
||||
the zero order Taylor coefficients correspond to
|
||||
$icode%f%.Forward(0, %x%)%$$
|
||||
and the other coefficients are unspecified.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/hessian.cpp%
|
||||
example/general/hes_lagrangian.cpp
|
||||
%$$
|
||||
The routines
|
||||
$cref hessian.cpp$$ and
|
||||
$cref hes_lagrangian.cpp$$
|
||||
are examples and tests of $code Hessian$$.
|
||||
They return $code true$$, if they succeed and $code false$$ otherwise.
|
||||
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <typename Base>
|
||||
template <typename Vector>
|
||||
Vector ADFun<Base>::Hessian(const Vector &x, size_t l)
|
||||
{ size_t i, m = Range();
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
l < m,
|
||||
"Hessian: index i is not less than range dimension for f"
|
||||
);
|
||||
|
||||
Vector w(m);
|
||||
for(i = 0; i < m; i++)
|
||||
w[i] = Base(0.0);
|
||||
w[l] = Base(1.0);
|
||||
|
||||
return Hessian(x, w);
|
||||
}
|
||||
|
||||
|
||||
template <typename Base>
|
||||
template <typename Vector>
|
||||
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.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.0);
|
||||
Forward(1, u);
|
||||
u[j] = Base(0.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;
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_IDENTICAL_HPP
|
||||
# define CPPAD_CORE_IDENTICAL_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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/core/define.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file identical.hpp
|
||||
Check if certain properties is true for any possible AD tape play back.
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/*!
|
||||
Determine if an AD<Base> object is a parameter, and could never have
|
||||
a different value during any tape playback.
|
||||
|
||||
An AD<Base> object \c x is identically a parameter if and only if
|
||||
all of the objects in the following chain are parameters:
|
||||
\code
|
||||
x , x.value , x.value.value , ...
|
||||
\endcode
|
||||
In such a case, the value of the object will always be the same
|
||||
no matter what the independent variable values are at any level.
|
||||
|
||||
\param x
|
||||
values that we are checking for identically a pamameter.
|
||||
|
||||
\return
|
||||
returns true iff \c x is identically a parameter.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool IdenticalPar(const AD<Base> &x)
|
||||
{ return Parameter(x) && IdenticalPar(x.value_); }
|
||||
// Zero ==============================================================
|
||||
/*!
|
||||
Determine if an AD<Base> is equal to zero,
|
||||
and must be equal zero during any tape playback.
|
||||
|
||||
\param x
|
||||
object that we are checking.
|
||||
|
||||
\return
|
||||
returns true if and only if
|
||||
\c x is equals zero and is identically a parameter \ref CppAD::IdenticalPar.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool IdenticalZero(const AD<Base> &x)
|
||||
{ return Parameter(x) && IdenticalZero(x.value_); }
|
||||
// One ==============================================================
|
||||
/*!
|
||||
Determine if an AD<Base> is equal to one,
|
||||
and must be equal one during any tape playback.
|
||||
|
||||
\param x
|
||||
object that we are checking.
|
||||
|
||||
\return
|
||||
returns true if and only if
|
||||
\c x is equals one and is identically a parameter \ref CppAD::IdenticalPar.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool IdenticalOne(const AD<Base> &x)
|
||||
{ return Parameter(x) && IdenticalOne(x.value_); }
|
||||
// Equal ===================================================================
|
||||
/*!
|
||||
Determine if two AD<Base> objects are equal,
|
||||
and must be equal during any tape playback.
|
||||
|
||||
\param x
|
||||
first of two objects we are checking for equal.
|
||||
|
||||
\param y
|
||||
second of two objects we are checking for equal.
|
||||
|
||||
\return
|
||||
returns true if and only if
|
||||
the arguments are equal and both identically parameters \ref CppAD::IdenticalPar.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool IdenticalEqualPar
|
||||
(const AD<Base> &x, const AD<Base> &y)
|
||||
{ bool parameter;
|
||||
parameter = ( Parameter(x) & Parameter(y) );
|
||||
return parameter && IdenticalEqualPar(x.value_, y.value_);
|
||||
}
|
||||
// ==========================================================================
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
# ifndef CPPAD_CORE_INDEPENDENT_HPP
|
||||
# define CPPAD_CORE_INDEPENDENT_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 Independent$$
|
||||
$spell
|
||||
op
|
||||
alloc
|
||||
num
|
||||
Cpp
|
||||
bool
|
||||
const
|
||||
var
|
||||
typename
|
||||
$$
|
||||
|
||||
$section Declare Independent Variables and Start Recording$$
|
||||
|
||||
$head Syntax$$
|
||||
$codei%Independent(%x%)
|
||||
%$$
|
||||
$codei%Independent(%x%, %abort_op_index%)
|
||||
%$$
|
||||
|
||||
$head Purpose$$
|
||||
Start recording
|
||||
$cref/AD of Base/glossary/AD of Base/$$ operations
|
||||
with $icode x$$ as the independent variable vector.
|
||||
Once the
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$ is completed,
|
||||
it must be transferred to a function object; see below.
|
||||
|
||||
$head Start Recording$$
|
||||
An operation sequence recording is started by the commands
|
||||
$codei%
|
||||
Independent(%x%)
|
||||
Independent(%x%, %abort_op_index%)
|
||||
%$$
|
||||
|
||||
$head Stop Recording$$
|
||||
The recording is stopped,
|
||||
and the operation sequence is transferred to the AD function object $icode f$$,
|
||||
using either the $cref/function constructor/FunConstruct/$$
|
||||
$codei%
|
||||
ADFun<%Base%> %f%(%x%, %y%)
|
||||
%$$
|
||||
or the $cref/dependent variable specifier/Dependent/$$
|
||||
$codei%
|
||||
%f%.Dependent(%x%, %y%)
|
||||
%$$
|
||||
The only other way to stop a recording is using
|
||||
$cref abort_recording$$.
|
||||
Between when the recording is started and when it stopped,
|
||||
we refer to the elements of $icode x$$,
|
||||
and the values that depend on the elements of $icode x$$,
|
||||
as $codei%AD<%Base%>%$$ variables.
|
||||
|
||||
$head x$$
|
||||
The vector $icode x$$ has prototype
|
||||
$codei%
|
||||
%VectorAD% &%x%
|
||||
%$$
|
||||
(see $icode VectorAD$$ below).
|
||||
The size of the vector $icode x$$, must be greater than zero,
|
||||
and is the number of independent variables for this
|
||||
AD operation sequence.
|
||||
|
||||
$head abort_op_index$$
|
||||
It specifies the operator index at which the execution is be aborted
|
||||
by calling the CppAD $cref/error handler/ErrorHandler/$$.
|
||||
When this error handler leads to an assert, the user
|
||||
can inspect the call stack to see the source code corresponding to
|
||||
this operator index; see
|
||||
$cref/purpose/compare_change/op_index/Purpose/$$.
|
||||
No abort will occur if $icode abort_op_index$$ is zero,
|
||||
of if $cref/NDEBUG/Faq/Speed/NDEBUG/$$ is defined.
|
||||
|
||||
$head VectorAD$$
|
||||
The type $icode VectorAD$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$codei%AD<%Base%>%$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head Parallel Mode$$
|
||||
Each thread can have one, and only one, active recording.
|
||||
A call to $code Independent$$ starts the recording for the current thread.
|
||||
The recording must be stopped by a corresponding call to
|
||||
$codei%
|
||||
ADFun<%Base%> %f%( %x%, %y%)
|
||||
%$$
|
||||
or
|
||||
$codei%
|
||||
%f%.Dependent( %x%, %y%)
|
||||
%$$
|
||||
or $cref abort_recording$$
|
||||
preformed by the same thread; i.e.,
|
||||
$cref/thread_alloc::thread_num/ta_thread_num/$$ must be the same.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/independent.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref independent.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/local/independent.hpp>
|
||||
/*!
|
||||
\file core/independent.hpp
|
||||
Declare the independent variables
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
Declaration of independent variables.
|
||||
|
||||
\tparam VectorAD
|
||||
This is simple vector type with elements of type AD<Base>.
|
||||
|
||||
\param x
|
||||
Vector of the independent variablerd.
|
||||
|
||||
\param abort_op_index
|
||||
operator index at which execution will be aborted (during the recording
|
||||
of operations). The value zero corresponds to not aborting (will not match).
|
||||
*/
|
||||
template <typename VectorAD>
|
||||
inline void Independent(VectorAD &x, size_t abort_op_index)
|
||||
{ typedef typename VectorAD::value_type ADBase;
|
||||
typedef typename ADBase::value_type Base;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
ADBase::tape_ptr() == CPPAD_NULL,
|
||||
"Independent: cannot create a new tape because\n"
|
||||
"a previous tape is still active (for this thread).\n"
|
||||
"AD<Base>::abort_recording() would abort this previous recording."
|
||||
);
|
||||
local::ADTape<Base>* tape = ADBase::tape_manage(tape_manage_new);
|
||||
tape->Independent(x, abort_op_index);
|
||||
}
|
||||
/*!
|
||||
Declaration of independent variables without abort option.
|
||||
|
||||
\tparam VectorAD
|
||||
This is simple vector type with elements of type AD<Base>.
|
||||
|
||||
\param x
|
||||
Vector of the independent variablerd.
|
||||
*/
|
||||
template <typename VectorAD>
|
||||
inline void Independent(VectorAD &x)
|
||||
{ size_t abort_op_index = 0;
|
||||
Independent(x, abort_op_index);
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
# endif
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
# ifndef CPPAD_CORE_INTEGER_HPP
|
||||
# define CPPAD_CORE_INTEGER_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 Integer$$
|
||||
$spell
|
||||
std
|
||||
VecAD
|
||||
CppAD
|
||||
namespace
|
||||
const
|
||||
bool
|
||||
$$
|
||||
|
||||
|
||||
|
||||
$section Convert From AD to Integer$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%i% = Integer(%x%)%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Converts from an AD type to the corresponding integer value.
|
||||
|
||||
$head i$$
|
||||
The result $icode i$$ has prototype
|
||||
$codei%
|
||||
int %i%
|
||||
%$$
|
||||
|
||||
$head x$$
|
||||
|
||||
$subhead Real Types$$
|
||||
If the argument $icode x$$ has either of the following prototypes:
|
||||
$codei%
|
||||
const float %% &%x%
|
||||
const double %% &%x%
|
||||
%$$
|
||||
the fractional part is dropped to form the integer value.
|
||||
For example, if $icode x$$ is 1.5, $icode i$$ is 1.
|
||||
In general, if $latex x \geq 0$$, $icode i$$ is the
|
||||
greatest integer less than or equal $icode x$$.
|
||||
If $latex x \leq 0$$, $icode i$$ is the
|
||||
smallest integer greater than or equal $icode x$$.
|
||||
|
||||
$subhead Complex Types$$
|
||||
If the argument $icode x$$ has either of the following prototypes:
|
||||
$codei%
|
||||
const std::complex<float> %% &%x%
|
||||
const std::complex<double> %% &%x%
|
||||
%$$
|
||||
The result $icode i$$ is given by
|
||||
$codei%
|
||||
%i% = Integer(%x%.real())
|
||||
%$$
|
||||
|
||||
$subhead AD Types$$
|
||||
If the argument $icode x$$ has either of the following prototypes:
|
||||
$codei%
|
||||
const AD<%Base%> &%x%
|
||||
const VecAD<%Base%>::reference &%x%
|
||||
%$$
|
||||
$icode Base$$ must support the $code Integer$$ function and
|
||||
the conversion has the same meaning as for $icode Base$$.
|
||||
|
||||
$head Operation Sequence$$
|
||||
The result of this operation is not an
|
||||
$cref/AD of Base/glossary/AD of Base/$$ object.
|
||||
Thus it will not be recorded as part of an
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/integer.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref integer.cpp$$
|
||||
contains an example and test of this operation.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
int Integer(const AD<Base> &x)
|
||||
{ return Integer(x.value_); }
|
||||
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
int Integer(const VecAD_reference<Base> &x)
|
||||
{ return Integer( x.ADBase() ); }
|
||||
}
|
||||
# endif
|
||||
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
# ifndef CPPAD_CORE_JACOBIAN_HPP
|
||||
# define CPPAD_CORE_JACOBIAN_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 Jacobian$$
|
||||
$spell
|
||||
jac
|
||||
typename
|
||||
Taylor
|
||||
Jacobian
|
||||
DetLu
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section Jacobian: Driver Routine$$
|
||||
$mindex Jacobian first derivative$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%jac% = %f%.Jacobian(%x%)%$$
|
||||
|
||||
|
||||
$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 $icode jac$$ to the
|
||||
Jacobian of $icode F$$ evaluated at $icode x$$; i.e.,
|
||||
$latex \[
|
||||
jac = F^{(1)} (x)
|
||||
\] $$
|
||||
|
||||
$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/Forward or Reverse/Jacobian/Forward or Reverse/$$ below).
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Vector% &%x%
|
||||
%$$
|
||||
(see $cref/Vector/Jacobian/Vector/$$ 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 Jacobian.
|
||||
|
||||
$head jac$$
|
||||
The result $icode jac$$ has prototype
|
||||
$codei%
|
||||
%Vector% %jac%
|
||||
%$$
|
||||
(see $cref/Vector/Jacobian/Vector/$$ below)
|
||||
and its size is $latex m * n$$; i.e., the product of the
|
||||
$cref/domain/seq_property/Domain/$$
|
||||
and
|
||||
$cref/range/seq_property/Range/$$
|
||||
dimensions for $icode f$$.
|
||||
For $latex i = 0 , \ldots , m - 1 $$
|
||||
and $latex j = 0 , \ldots , n - 1$$
|
||||
$latex \[.
|
||||
jac[ i * n + j ] = \D{ F_i }{ x_j } ( x )
|
||||
\] $$
|
||||
|
||||
|
||||
$head Vector$$
|
||||
The type $icode Vector$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$icode Base$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head Forward or Reverse$$
|
||||
This will use order zero Forward mode and either
|
||||
order one Forward or order one Reverse to compute the Jacobian
|
||||
(depending on which it estimates will require less work).
|
||||
After each call to $cref Forward$$,
|
||||
the object $icode f$$ contains the corresponding
|
||||
$cref/Taylor coefficients/glossary/Taylor Coefficient/$$.
|
||||
After a call to $code Jacobian$$,
|
||||
the zero order Taylor coefficients correspond to
|
||||
$icode%f%.Forward(0, %x%)%$$
|
||||
and the other coefficients are unspecified.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/jacobian.cpp
|
||||
%$$
|
||||
The routine
|
||||
$cref/Jacobian/jacobian.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, typename Vector>
|
||||
void JacobianFor(ADFun<Base> &f, const Vector &x, Vector &jac)
|
||||
{ size_t i;
|
||||
size_t j;
|
||||
|
||||
size_t n = f.Domain();
|
||||
size_t m = f.Range();
|
||||
|
||||
// check Vector is Simple Vector class with Base type elements
|
||||
CheckSimpleVector<Base, Vector>();
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == f.Domain() );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(jac.size()) == f.Range() * f.Domain() );
|
||||
|
||||
// argument and result for forward mode calculations
|
||||
Vector u(n);
|
||||
Vector v(m);
|
||||
|
||||
// initialize all the components
|
||||
for(j = 0; j < n; j++)
|
||||
u[j] = Base(0.0);
|
||||
|
||||
// loop through the different coordinate directions
|
||||
for(j = 0; j < n; j++)
|
||||
{ // set u to the j-th coordinate direction
|
||||
u[j] = Base(1.0);
|
||||
|
||||
// compute the partial of f w.r.t. this coordinate direction
|
||||
v = f.Forward(1, u);
|
||||
|
||||
// reset u to vector of all zeros
|
||||
u[j] = Base(0.0);
|
||||
|
||||
// return the result
|
||||
for(i = 0; i < m; i++)
|
||||
jac[ i * n + j ] = v[i];
|
||||
}
|
||||
}
|
||||
template <typename Base, typename Vector>
|
||||
void JacobianRev(ADFun<Base> &f, const Vector &x, Vector &jac)
|
||||
{ size_t i;
|
||||
size_t j;
|
||||
|
||||
size_t n = f.Domain();
|
||||
size_t m = f.Range();
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == f.Domain() );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(jac.size()) == f.Range() * f.Domain() );
|
||||
|
||||
// argument and result for reverse mode calculations
|
||||
Vector u(n);
|
||||
Vector v(m);
|
||||
|
||||
// initialize all the components
|
||||
for(i = 0; i < m; i++)
|
||||
v[i] = Base(0.0);
|
||||
|
||||
// loop through the different coordinate directions
|
||||
for(i = 0; i < m; i++)
|
||||
{ if( f.Parameter(i) )
|
||||
{ // return zero for this component of f
|
||||
for(j = 0; j < n; j++)
|
||||
jac[ i * n + j ] = Base(0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// set v to the i-th coordinate direction
|
||||
v[i] = Base(1.0);
|
||||
|
||||
// compute the derivative of this component of f
|
||||
u = f.Reverse(1, v);
|
||||
|
||||
// reset v to vector of all zeros
|
||||
v[i] = Base(0.0);
|
||||
|
||||
// return the result
|
||||
for(j = 0; j < n; j++)
|
||||
jac[ i * n + j ] = u[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Base>
|
||||
template <typename Vector>
|
||||
Vector ADFun<Base>::Jacobian(const Vector &x)
|
||||
{ size_t i;
|
||||
size_t n = Domain();
|
||||
size_t m = Range();
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(x.size()) == n,
|
||||
"Jacobian: length of x not equal domain dimension for F"
|
||||
);
|
||||
|
||||
// point at which we are evaluating the Jacobian
|
||||
Forward(0, x);
|
||||
|
||||
// work factor for forward mode
|
||||
size_t workForward = n;
|
||||
|
||||
// work factor for reverse mode
|
||||
size_t workReverse = 0;
|
||||
for(i = 0; i < m; i++)
|
||||
{ if( ! Parameter(i) )
|
||||
++workReverse;
|
||||
}
|
||||
|
||||
// choose the method with the least work
|
||||
Vector jac( n * m );
|
||||
if( workForward <= workReverse )
|
||||
JacobianFor(*this, x, jac);
|
||||
else JacobianRev(*this, x, jac);
|
||||
|
||||
return jac;
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
# ifndef CPPAD_CORE_LOG1P_HPP
|
||||
# define CPPAD_CORE_LOG1P_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 log1p$$
|
||||
$spell
|
||||
CppAD
|
||||
$$
|
||||
|
||||
$section The Logarithm of One Plus Argument: log1p$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = log1p(%x%)%$$
|
||||
|
||||
$head Description$$
|
||||
Returns the value of the logarithm of one plus argument which is defined
|
||||
by $icode%y% == log(1 + %x%)%$$.
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head CPPAD_USE_CPLUSPLUS_2011$$
|
||||
|
||||
$subhead true$$
|
||||
If this preprocessor symbol is true ($code 1$$),
|
||||
and $icode x$$ is an AD type,
|
||||
this is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$subhead false$$
|
||||
If this preprocessor symbol is false ($code 0$$),
|
||||
CppAD uses the representation
|
||||
$latex \[
|
||||
\R{log1p} (x) = \log(1 + x)
|
||||
\] $$
|
||||
to compute this function.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/log1p.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref log1p.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/configure.hpp>
|
||||
# if ! CPPAD_USE_CPLUSPLUS_2011
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Type>
|
||||
Type log1p_template(const Type &x)
|
||||
{ return CppAD::log(Type(1) + x);
|
||||
}
|
||||
|
||||
inline float log1p(const float &x)
|
||||
{ return log1p_template(x); }
|
||||
|
||||
inline double log1p(const double &x)
|
||||
{ return log1p_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> log1p(const AD<Base> &x)
|
||||
{ return log1p_template(x); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> log1p(const VecAD_reference<Base> &x)
|
||||
{ return log1p_template( x.ADBase() ); }
|
||||
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif // CPPAD_USE_CPLUSPLUS_2011
|
||||
# endif // CPPAD_LOG1P_INCLUDED
|
||||
+337
@@ -0,0 +1,337 @@
|
||||
# ifndef CPPAD_CORE_LU_RATIO_HPP
|
||||
# define CPPAD_CORE_LU_RATIO_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 LuRatio$$
|
||||
$spell
|
||||
cppad.hpp
|
||||
xk
|
||||
Cpp
|
||||
Lu
|
||||
bool
|
||||
const
|
||||
ip
|
||||
jp
|
||||
std
|
||||
ADvector
|
||||
$$
|
||||
|
||||
|
||||
$section LU Factorization of A Square Matrix and Stability Calculation$$
|
||||
$mindex LuRatio linear equation solve$$
|
||||
|
||||
$head Syntax$$
|
||||
$code# include <cppad/cppad.hpp>$$
|
||||
$pre
|
||||
$$
|
||||
$icode%sign% = LuRatio(%ip%, %jp%, %LU%, %ratio%)%$$
|
||||
|
||||
|
||||
$head Description$$
|
||||
Computes an LU factorization of the matrix $icode A$$
|
||||
where $icode A$$ is a square matrix.
|
||||
A measure of the numerical stability called $icode ratio$$ is calculated.
|
||||
This ratio is useful when the results of $code LuRatio$$ are
|
||||
used as part of an $cref ADFun$$ object.
|
||||
|
||||
$head Include$$
|
||||
This routine is designed to be used with AD objects and
|
||||
requires the $code cppad/cppad.hpp$$ file to be included.
|
||||
|
||||
$head Matrix Storage$$
|
||||
All matrices are stored in row major order.
|
||||
To be specific, if $latex Y$$ is a vector
|
||||
that contains a $latex p$$ by $latex q$$ matrix,
|
||||
the size of $latex Y$$ must be equal to $latex p * q $$ and for
|
||||
$latex i = 0 , \ldots , p-1$$,
|
||||
$latex j = 0 , \ldots , q-1$$,
|
||||
$latex \[
|
||||
Y_{i,j} = Y[ i * q + j ]
|
||||
\] $$
|
||||
|
||||
$head sign$$
|
||||
The return value $icode sign$$ has prototype
|
||||
$codei%
|
||||
int %sign%
|
||||
%$$
|
||||
If $icode A$$ is invertible, $icode sign$$ is plus or minus one
|
||||
and is the sign of the permutation corresponding to the row ordering
|
||||
$icode ip$$ and column ordering $icode jp$$.
|
||||
If $icode A$$ is not invertible, $icode sign$$ is zero.
|
||||
|
||||
$head ip$$
|
||||
The argument $icode ip$$ has prototype
|
||||
$codei%
|
||||
%SizeVector% &%ip%
|
||||
%$$
|
||||
(see description of $cref/SizeVector/LuFactor/SizeVector/$$ below).
|
||||
The size of $icode ip$$ is referred to as $icode n$$ in the
|
||||
specifications below.
|
||||
The input value of the elements of $icode ip$$ does not matter.
|
||||
The output value of the elements of $icode ip$$ determine
|
||||
the order of the rows in the permuted matrix.
|
||||
|
||||
$head jp$$
|
||||
The argument $icode jp$$ has prototype
|
||||
$codei%
|
||||
%SizeVector% &%jp%
|
||||
%$$
|
||||
(see description of $cref/SizeVector/LuFactor/SizeVector/$$ below).
|
||||
The size of $icode jp$$ must be equal to $icode n$$.
|
||||
The input value of the elements of $icode jp$$ does not matter.
|
||||
The output value of the elements of $icode jp$$ determine
|
||||
the order of the columns in the permuted matrix.
|
||||
|
||||
$head LU$$
|
||||
The argument $icode LU$$ has the prototype
|
||||
$codei%
|
||||
%ADvector% &%LU%
|
||||
%$$
|
||||
and the size of $icode LU$$ must equal $latex n * n$$
|
||||
(see description of $cref/ADvector/LuRatio/ADvector/$$ below).
|
||||
|
||||
$subhead A$$
|
||||
We define $icode A$$ as the matrix corresponding to the input
|
||||
value of $icode LU$$.
|
||||
|
||||
$subhead P$$
|
||||
We define the permuted matrix $icode P$$ in terms of $icode A$$ by
|
||||
$codei%
|
||||
%P%(%i%, %j%) = %A%[ %ip%[%i%] * %n% + %jp%[%j%] ]
|
||||
%$$
|
||||
|
||||
$subhead L$$
|
||||
We define the lower triangular matrix $icode L$$ in terms of the
|
||||
output value of $icode LU$$.
|
||||
The matrix $icode L$$ is zero above the diagonal
|
||||
and the rest of the elements are defined by
|
||||
$codei%
|
||||
%L%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ]
|
||||
%$$
|
||||
for $latex i = 0 , \ldots , n-1$$ and $latex j = 0 , \ldots , i$$.
|
||||
|
||||
$subhead U$$
|
||||
We define the upper triangular matrix $icode U$$ in terms of the
|
||||
output value of $icode LU$$.
|
||||
The matrix $icode U$$ is zero below the diagonal,
|
||||
one on the diagonal,
|
||||
and the rest of the elements are defined by
|
||||
$codei%
|
||||
%U%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ]
|
||||
%$$
|
||||
for $latex i = 0 , \ldots , n-2$$ and $latex j = i+1 , \ldots , n-1$$.
|
||||
|
||||
$subhead Factor$$
|
||||
If the return value $icode sign$$ is non-zero,
|
||||
$codei%
|
||||
%L% * %U% = %P%
|
||||
%$$
|
||||
If the return value of $icode sign$$ is zero,
|
||||
the contents of $icode L$$ and $icode U$$ are not defined.
|
||||
|
||||
$subhead Determinant$$
|
||||
If the return value $icode sign$$ is zero,
|
||||
the determinant of $icode A$$ is zero.
|
||||
If $icode sign$$ is non-zero,
|
||||
using the output value of $icode LU$$
|
||||
the determinant of the matrix $icode A$$ is equal to
|
||||
$codei%
|
||||
%sign% * %LU%[%ip%[0], %jp%[0]] * %...% * %LU%[%ip%[%n%-1], %jp%[%n%-1]]
|
||||
%$$
|
||||
|
||||
$head ratio$$
|
||||
The argument $icode ratio$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> &%ratio%
|
||||
%$$
|
||||
On input, the value of $icode ratio$$ does not matter.
|
||||
On output it is a measure of how good the choice of pivots is.
|
||||
For $latex p = 0 , \ldots , n-1$$,
|
||||
the $th p$$ pivot element is the element of maximum absolute value of a
|
||||
$latex (n-p) \times (n-p)$$ sub-matrix.
|
||||
The ratio of each element of sub-matrix divided by the pivot element
|
||||
is computed.
|
||||
The return value of $icode ratio$$ is the maximum absolute value of
|
||||
such ratios over with respect to all elements and all the pivots.
|
||||
|
||||
$subhead Purpose$$
|
||||
Suppose that the execution of a call to $code LuRatio$$
|
||||
is recorded in the $codei%ADFun<%Base%>%$$ object $icode F$$.
|
||||
Then a call to $cref Forward$$ of the form
|
||||
$codei%
|
||||
%F%.Forward(%k%, %xk%)
|
||||
%$$
|
||||
with $icode k$$ equal to zero will revaluate this Lu factorization
|
||||
with the same pivots and a new value for $icode A$$.
|
||||
In this case, the resulting $icode ratio$$ may not be one.
|
||||
If $icode ratio$$ is too large (the meaning of too large is up to you),
|
||||
the current pivots do not yield a stable LU factorization of $icode A$$.
|
||||
A better choice for the pivots (for this value of $icode A$$)
|
||||
will be made if you recreate the $code ADFun$$ object
|
||||
starting with the $cref Independent$$ variable values
|
||||
that correspond to the vector $icode xk$$.
|
||||
|
||||
$head SizeVector$$
|
||||
The type $icode SizeVector$$ 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 ADvector$$
|
||||
The type $icode ADvector$$ must be a
|
||||
$cref/simple vector class/SimpleVector/$$ with elements of type
|
||||
$codei%AD<%Base%>%$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/lu_ratio.cpp
|
||||
%$$
|
||||
The file $cref lu_ratio.cpp$$
|
||||
contains an example and test of using $code LuRatio$$.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
--------------------------------------------------------------------------
|
||||
*/
|
||||
namespace CppAD { // BEGIN CppAD namespace
|
||||
|
||||
// Lines different from the code in cppad/lu_factor.hpp end with //
|
||||
template <class SizeVector, class ADvector, class Base> //
|
||||
int LuRatio(SizeVector &ip, SizeVector &jp, ADvector &LU, AD<Base> &ratio) //
|
||||
{
|
||||
typedef ADvector FloatVector; //
|
||||
typedef AD<Base> Float; //
|
||||
|
||||
// check numeric type specifications
|
||||
CheckNumericType<Float>();
|
||||
|
||||
// check simple vector class specifications
|
||||
CheckSimpleVector<Float, FloatVector>();
|
||||
CheckSimpleVector<size_t, SizeVector>();
|
||||
|
||||
size_t i, j; // some temporary indices
|
||||
const Float zero( 0 ); // the value zero as a Float object
|
||||
size_t imax; // row index of maximum element
|
||||
size_t jmax; // column indx of maximum element
|
||||
Float emax; // maximum absolute value
|
||||
size_t p; // count pivots
|
||||
int sign; // sign of the permutation
|
||||
Float etmp; // temporary element
|
||||
Float pivot; // pivot element
|
||||
|
||||
// -------------------------------------------------------
|
||||
size_t n = size_t(ip.size());
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(jp.size()) == n,
|
||||
"Error in LuFactor: jp must have size equal to n"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(LU.size()) == n * n,
|
||||
"Error in LuFactor: LU must have size equal to n * m"
|
||||
);
|
||||
// -------------------------------------------------------
|
||||
|
||||
// initialize row and column order in matrix not yet pivoted
|
||||
for(i = 0; i < n; i++)
|
||||
{ ip[i] = i;
|
||||
jp[i] = i;
|
||||
}
|
||||
// initialize the sign of the permutation
|
||||
sign = 1;
|
||||
// initialize the ratio //
|
||||
ratio = Float(1); //
|
||||
// ---------------------------------------------------------
|
||||
|
||||
// Reduce the matrix P to L * U using n pivots
|
||||
for(p = 0; p < n; p++)
|
||||
{ // determine row and column corresponding to element of
|
||||
// maximum absolute value in remaining part of P
|
||||
imax = jmax = n;
|
||||
emax = zero;
|
||||
for(i = p; i < n; i++)
|
||||
{ for(j = p; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN(
|
||||
(ip[i] < n) & (jp[j] < n)
|
||||
);
|
||||
etmp = LU[ ip[i] * n + jp[j] ];
|
||||
|
||||
// check if maximum absolute value so far
|
||||
if( AbsGeq (etmp, emax) )
|
||||
{ imax = i;
|
||||
jmax = j;
|
||||
emax = etmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i = p; i < n; i++) //
|
||||
{ for(j = p; j < n; j++) //
|
||||
{ etmp = fabs(LU[ ip[i] * n + jp[j] ] / emax); //
|
||||
ratio = //
|
||||
CondExpGt(etmp, ratio, etmp, ratio); //
|
||||
} //
|
||||
} //
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
(imax < n) & (jmax < n) ,
|
||||
"AbsGeq must return true when second argument is zero"
|
||||
);
|
||||
if( imax != p )
|
||||
{ // switch rows so max absolute element is in row p
|
||||
i = ip[p];
|
||||
ip[p] = ip[imax];
|
||||
ip[imax] = i;
|
||||
sign = -sign;
|
||||
}
|
||||
if( jmax != p )
|
||||
{ // switch columns so max absolute element is in column p
|
||||
j = jp[p];
|
||||
jp[p] = jp[jmax];
|
||||
jp[jmax] = j;
|
||||
sign = -sign;
|
||||
}
|
||||
// pivot using the max absolute element
|
||||
pivot = LU[ ip[p] * n + jp[p] ];
|
||||
|
||||
// check for determinant equal to zero
|
||||
if( pivot == zero )
|
||||
{ // abort the mission
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reduce U by the elementary transformations that maps
|
||||
// LU( ip[p], jp[p] ) to one. Only need transform elements
|
||||
// above the diagonal in U and LU( ip[p] , jp[p] ) is
|
||||
// corresponding value below diagonal in L.
|
||||
for(j = p+1; j < n; j++)
|
||||
LU[ ip[p] * n + jp[j] ] /= pivot;
|
||||
|
||||
// Reduce U by the elementary transformations that maps
|
||||
// LU( ip[i], jp[p] ) to zero. Only need transform elements
|
||||
// above the diagonal in U and LU( ip[i], jp[p] ) is
|
||||
// corresponding value below diagonal in L.
|
||||
for(i = p+1; i < n; i++ )
|
||||
{ etmp = LU[ ip[i] * n + jp[p] ];
|
||||
for(j = p+1; j < n; j++)
|
||||
{ LU[ ip[i] * n + jp[j] ] -=
|
||||
etmp * LU[ ip[p] * n + jp[j] ];
|
||||
}
|
||||
}
|
||||
}
|
||||
return sign;
|
||||
}
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_MUL_HPP
|
||||
# define CPPAD_CORE_MUL_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base> operator * (const AD<Base> &left , const AD<Base> &right)
|
||||
{
|
||||
// compute the Base part
|
||||
AD<Base> result;
|
||||
result.value_ = left.value_ * right.value_;
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return result;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_left = left.tape_id_ == tape_id;
|
||||
bool var_right = right.tape_id_ == tape_id;
|
||||
|
||||
if( var_left )
|
||||
{ if( var_right )
|
||||
{ // result = variable * variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::MulvvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
else if( IdenticalZero(right.value_) )
|
||||
{ // result = variable * 0
|
||||
}
|
||||
else if( IdenticalOne(right.value_) )
|
||||
{ // result = variable * 1
|
||||
result.make_variable(left.tape_id_, left.taddr_);
|
||||
}
|
||||
else
|
||||
{ // result = variable * parameter
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(p, left.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::MulpvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
else if( var_right )
|
||||
{ if( IdenticalZero(left.value_) )
|
||||
{ // result = 0 * variable
|
||||
}
|
||||
else if( IdenticalOne(left.value_) )
|
||||
{ // result = 1 * variable
|
||||
result.make_variable(right.tape_id_, right.taddr_);
|
||||
}
|
||||
else
|
||||
{ // result = parameter * variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(left.value_);
|
||||
tape->Rec_.PutArg(p, right.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::MulpvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(*)
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_MUL_EQ_HPP
|
||||
# define CPPAD_CORE_MUL_EQ_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base>& AD<Base>::operator *= (const AD<Base> &right)
|
||||
{
|
||||
// compute the Base part
|
||||
Base left;
|
||||
left = value_;
|
||||
value_ *= right.value_;
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return *this;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_left = tape_id_ == tape_id;
|
||||
bool var_right = right.tape_id_ == tape_id;
|
||||
|
||||
if( var_left )
|
||||
{ if( var_right )
|
||||
{ // this = variable * variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(taddr_, right.taddr_);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::MulvvOp);
|
||||
// make this a variable
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||
}
|
||||
else if( IdenticalOne( right.value_ ) )
|
||||
{ // this = variable * 1
|
||||
}
|
||||
else if( IdenticalZero( right.value_ ) )
|
||||
{ // this = variable * 0
|
||||
make_parameter();
|
||||
}
|
||||
else
|
||||
{ // this = variable * parameter
|
||||
// = parameter * variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(p, taddr_);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::MulpvOp);
|
||||
// make this a variable
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||
}
|
||||
}
|
||||
else if( var_right )
|
||||
{ if( IdenticalZero(left) )
|
||||
{ // this = 0 * right
|
||||
}
|
||||
else if( IdenticalOne(left) )
|
||||
{ // this = 1 * right
|
||||
make_variable(right.tape_id_, right.taddr_);
|
||||
}
|
||||
else
|
||||
{ // this = parameter * variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::MulpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::MulpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(left);
|
||||
tape->Rec_.PutArg(p, right.taddr_);
|
||||
// put operator in the tape
|
||||
taddr_ = tape->Rec_.PutOp(local::MulpvOp);
|
||||
// make this a variable
|
||||
tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CPPAD_FOLD_ASSIGNMENT_OPERATOR(*=)
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,188 @@
|
||||
# ifndef CPPAD_CORE_NEAR_EQUAL_EXT_HPP
|
||||
# define CPPAD_CORE_NEAR_EQUAL_EXT_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 NearEqualExt$$
|
||||
$spell
|
||||
cout
|
||||
endl
|
||||
Microsoft
|
||||
std
|
||||
Cpp
|
||||
namespace
|
||||
const
|
||||
bool
|
||||
$$
|
||||
|
||||
$section Compare AD and Base Objects for Nearly Equal$$
|
||||
$mindex NearEqual with$$
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
$icode%b% = NearEqual(%x%, %y%, %r%, %a%)%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
The routine $cref NearEqual$$ determines if two objects of
|
||||
the same type are nearly.
|
||||
This routine is extended to the case where one object can have type
|
||||
$icode Type$$ while the other can have type
|
||||
$codei%AD<%Type%>%$$ or
|
||||
$codei%AD< std::complex<%Type%> >%$$.
|
||||
|
||||
$head x$$
|
||||
The arguments $icode x$$
|
||||
has one of the following possible prototypes:
|
||||
$codei%
|
||||
const %Type% &%x%
|
||||
const AD<%Type%> &%x%
|
||||
const AD< std::complex<%Type%> > &%x%
|
||||
%$$
|
||||
|
||||
$head y$$
|
||||
The arguments $icode y$$
|
||||
has one of the following possible prototypes:
|
||||
$codei%
|
||||
const %Type% &%y%
|
||||
const AD<%Type%> &%y%
|
||||
const AD< std::complex<%Type%> > &%x%
|
||||
%$$
|
||||
|
||||
|
||||
$head r$$
|
||||
The relative error criteria $icode r$$ has prototype
|
||||
$codei%
|
||||
const %Type% &%r%
|
||||
%$$
|
||||
It must be greater than or equal to zero.
|
||||
The relative error condition is defined as:
|
||||
$latex \[
|
||||
\frac{ | x - y | } { |x| + |y| } \leq r
|
||||
\] $$
|
||||
|
||||
$head a$$
|
||||
The absolute error criteria $icode a$$ has prototype
|
||||
$codei%
|
||||
const %Type% &%a%
|
||||
%$$
|
||||
It must be greater than or equal to zero.
|
||||
The absolute error condition is defined as:
|
||||
$latex \[
|
||||
| x - y | \leq a
|
||||
\] $$
|
||||
|
||||
$head b$$
|
||||
The return value $icode b$$ has prototype
|
||||
$codei%
|
||||
bool %b%
|
||||
%$$
|
||||
If either $icode x$$ or $icode y$$ is infinite or not a number,
|
||||
the return value is false.
|
||||
Otherwise, if either the relative or absolute error
|
||||
condition (defined above) is satisfied, the return value is true.
|
||||
Otherwise, the return value is false.
|
||||
|
||||
$head Type$$
|
||||
The type $icode Type$$ must be a
|
||||
$cref NumericType$$.
|
||||
The routine $cref CheckNumericType$$ will generate
|
||||
an error message if this is not the case.
|
||||
If $icode a$$ and $icode b$$ have type $icode Type$$,
|
||||
the following operation must be defined
|
||||
$table
|
||||
$bold Operation$$ $cnext
|
||||
$bold Description$$ $rnext
|
||||
$icode%a% <= %b%$$ $cnext
|
||||
less that or equal operator (returns a $code bool$$ object)
|
||||
$tend
|
||||
|
||||
$head Operation Sequence$$
|
||||
The result of this operation is not an
|
||||
$cref/AD of Base/glossary/AD of Base/$$ object.
|
||||
Thus it will not be recorded as part of an
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/near_equal_ext.cpp
|
||||
%$$
|
||||
The file $cref near_equal_ext.cpp$$ contains an example
|
||||
and test of this extension of $cref NearEqual$$.
|
||||
It return true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
|
||||
*/
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// fold into base type and then use <cppad/near_equal.hpp>
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool NearEqual(
|
||||
const AD<Base> &x, const AD<Base> &y, const Base &r, const Base &a)
|
||||
{ return NearEqual(x.value_, y.value_, r, a);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool NearEqual(
|
||||
const Base &x, const AD<Base> &y, const Base &r, const Base &a)
|
||||
{ return NearEqual(x, y.value_, r, a);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool NearEqual(
|
||||
const AD<Base> &x, const Base &y, const Base &r, const Base &a)
|
||||
{ return NearEqual(x.value_, y, r, a);
|
||||
}
|
||||
|
||||
// fold into AD type and then use cases above
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool NearEqual(
|
||||
const VecAD_reference<Base> &x, const VecAD_reference<Base> &y,
|
||||
const Base &r, const Base &a)
|
||||
{ return NearEqual(x.ADBase(), y.ADBase(), r, a);
|
||||
}
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool NearEqual(const VecAD_reference<Base> &x, const AD<Base> &y,
|
||||
const Base &r, const Base &a)
|
||||
{ return NearEqual(x.ADBase(), y, r, a);
|
||||
}
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool NearEqual(const VecAD_reference<Base> &x, const Base &y,
|
||||
const Base &r, const Base &a)
|
||||
{ return NearEqual(x.ADBase(), y, r, a);
|
||||
}
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool NearEqual(const AD<Base> &x, const VecAD_reference<Base> &y,
|
||||
const Base &r, const Base &a)
|
||||
{ return NearEqual(x, y.ADBase(), r, a);
|
||||
}
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool NearEqual(const Base &x, const VecAD_reference<Base> &y,
|
||||
const Base &r, const Base &a)
|
||||
{ return NearEqual(x, y.ADBase(), r, a);
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
# ifndef CPPAD_CORE_NUM_SKIP_HPP
|
||||
# define CPPAD_CORE_NUM_SKIP_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 number_skip$$
|
||||
$spell
|
||||
optimizer
|
||||
var
|
||||
taylor_
|
||||
$$
|
||||
|
||||
|
||||
$section Number of Variables that Can be Skipped$$
|
||||
$mindex number_skip$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%n% = %f%.number_skip()%$$
|
||||
|
||||
$subhead See Also$$
|
||||
$cref seq_property$$
|
||||
|
||||
$head Purpose$$
|
||||
The $cref/conditional expressions/CondExp/$$ use either the
|
||||
$cref/if_true/CondExp/$$ or $cref/if_false/CondExp/$$.
|
||||
Hence, some terms only need to be evaluated
|
||||
depending on the value of the comparison in the conditional expression.
|
||||
The $cref optimize$$ option is capable of detecting some of these
|
||||
case and determining variables that can be skipped.
|
||||
This routine returns the number such variables.
|
||||
|
||||
$head n$$
|
||||
The return value $icode n$$ has type $code size_t$$
|
||||
is the number of variables that the optimizer has determined can be skipped
|
||||
(given the independent variable values specified by the previous call to
|
||||
$cref/f.Forward/Forward/$$ for order zero).
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$children%
|
||||
example/general/number_skip.cpp
|
||||
%$$
|
||||
$head Example$$
|
||||
The file $cref number_skip.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
// This routine is not const because it runs through the operations sequence
|
||||
// 2DO: compute this value during zero order forward operations.
|
||||
template <typename Base>
|
||||
size_t ADFun<Base>::number_skip(void)
|
||||
{ // must pass through operation sequence to map operations to variables
|
||||
local::OpCode op;
|
||||
size_t i_op;
|
||||
size_t i_var;
|
||||
const addr_t* arg;
|
||||
|
||||
// information defined by forward_user
|
||||
size_t user_old=0, user_m=0, user_n=0, user_i=0, user_j=0;
|
||||
local::enum_user_state user_state;
|
||||
|
||||
// number of variables skipped
|
||||
size_t num_var_skip = 0;
|
||||
|
||||
// start playback
|
||||
user_state = local::start_user;
|
||||
play_.forward_start(op, arg, i_op, i_var);
|
||||
CPPAD_ASSERT_UNKNOWN(op == local::BeginOp)
|
||||
while(op != local::EndOp)
|
||||
{ // next op
|
||||
play_.forward_next(op, arg, i_op, i_var);
|
||||
//
|
||||
if( op == local::UserOp )
|
||||
{ // skip only appears at front or back UserOp of user atomic call
|
||||
bool skip_call = cskip_op_[i_op];
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == local::start_user );
|
||||
play_.forward_user(
|
||||
op, user_state, user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( NumRes(op) == 0 );
|
||||
size_t num_op = user_m + user_n + 1;
|
||||
for(size_t i = 0; i < num_op; i++)
|
||||
{ play_.forward_next(op, arg, i_op, i_var);
|
||||
play_.forward_user(
|
||||
op, user_state, user_old, user_m, user_n, user_i, user_j
|
||||
);
|
||||
if( skip_call )
|
||||
num_var_skip += NumRes(op);
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( user_state == local::start_user );
|
||||
}
|
||||
else
|
||||
{ if( op == local::CSumOp)
|
||||
play_.forward_csum(op, arg, i_op, i_var);
|
||||
else if (op == local::CSkipOp)
|
||||
play_.forward_cskip(op, arg, i_op, i_var);
|
||||
//
|
||||
if( cskip_op_[i_op] )
|
||||
num_var_skip += NumRes(op);
|
||||
}
|
||||
}
|
||||
return num_var_skip;
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,214 @@
|
||||
# ifndef CPPAD_CORE_NUMERIC_LIMITS_HPP
|
||||
# define CPPAD_CORE_NUMERIC_LIMITS_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 numeric_limits$$
|
||||
$spell
|
||||
std
|
||||
eps
|
||||
CppAD
|
||||
namespace
|
||||
const
|
||||
$$
|
||||
|
||||
$section Numeric Limits For an AD and Base Types$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%eps% = numeric_limits<%Float%>::epsilon()
|
||||
%$$
|
||||
$icode%min% = numeric_limits<%Float%>::min()
|
||||
%$$
|
||||
$icode%max% = numeric_limits<%Float%>::max()
|
||||
%$$
|
||||
$icode%nan% = numeric_limits<%Float%>::quiet_NaN()
|
||||
%$$
|
||||
$codei%numeric_limits<%Float%>::digits10%$$
|
||||
|
||||
$head CppAD::numeric_limits$$
|
||||
These functions and have the prototype
|
||||
$codei%
|
||||
static %Float% CppAD::numeric_limits<%Float%>::%fun%(%void%)
|
||||
%$$
|
||||
where $icode fun$$ is
|
||||
$code epsilon$$, $code min$$, $code max$$, and $code quiet_NaN$$.
|
||||
(Note that $code digits10$$ is member variable and not a function.)
|
||||
|
||||
$head std::numeric_limits$$
|
||||
CppAD does not use a specialization of $code std::numeric_limits$$
|
||||
because this would be to restrictive.
|
||||
The C++ standard specifies that Non-fundamental standard
|
||||
types, such as
|
||||
$cref/std::complex<double>/base_complex.hpp/$$ shall not have specializations
|
||||
of $code std::numeric_limits$$; see Section 18.2 of
|
||||
ISO/IEC 14882:1998(E).
|
||||
In addition, since C++11, a only literal types can have a specialization
|
||||
of $code std::numeric_limits$$.
|
||||
|
||||
$head Float$$
|
||||
These functions are defined for all $codei%AD<%Base%>%$$,
|
||||
and for all corresponding $icode Base$$ types;
|
||||
see $icode Base$$ type $cref base_limits$$.
|
||||
|
||||
$head epsilon$$
|
||||
The result $icode eps$$ is equal to machine epsilon and has prototype
|
||||
$codei%
|
||||
%Float% %eps%
|
||||
%$$
|
||||
The file $cref num_limits.cpp$$
|
||||
tests the value $icode eps$$ by checking that the following are true
|
||||
$codei%
|
||||
1 != 1 + %eps%
|
||||
1 == 1 + %eps% / 2
|
||||
%$$
|
||||
where all the values, and calculations, are done with the precision
|
||||
corresponding to $icode Float$$.
|
||||
|
||||
$head min$$
|
||||
The result $icode min$$ is equal to
|
||||
the minimum positive normalized value and has prototype
|
||||
$codei%
|
||||
%Float% %min%
|
||||
%$$
|
||||
The file $cref num_limits.cpp$$
|
||||
tests the value $icode min$$ by checking that the following are true
|
||||
$codei%
|
||||
abs( ((%min% / 100) * 100) / %min% - 1 ) > 3 * %eps%
|
||||
abs( ((%min% * 100) / 100) / %min% - 1 ) < 3 * %eps%
|
||||
%$$
|
||||
where all the values, and calculations, are done with the precision
|
||||
corresponding to $icode Float$$.
|
||||
|
||||
$head max$$
|
||||
The result $icode max$$ is equal to
|
||||
the maximum finite value and has prototype
|
||||
$codei%
|
||||
%Float% %max%
|
||||
%$$
|
||||
The file $cref num_limits.cpp$$
|
||||
tests the value $icode max$$ by checking that the following are true
|
||||
$codei%
|
||||
abs( ((%max% * 100) / 100) / %max% - 1 ) > 3 * %eps%
|
||||
abs( ((%max% / 100) * 100) / %max% - 1 ) < 3 * %eps%
|
||||
%$$
|
||||
where all the values, and calculations, are done with the precision
|
||||
corresponding to $icode Float$$.
|
||||
|
||||
$head quiet_NaN$$
|
||||
The result $icode nan$$ is not a number and has prototype
|
||||
$codei%
|
||||
%Float% %nan%
|
||||
%$$
|
||||
The file $cref num_limits.cpp$$
|
||||
tests the value $icode nan$$ by checking that the following is true
|
||||
$codei%
|
||||
%nan% != %nan%
|
||||
%$$
|
||||
|
||||
$head digits10$$
|
||||
The member variable $code digits10$$ has prototype
|
||||
$codei%
|
||||
static const int numeric_limits<%Float%>::digits10
|
||||
%$$
|
||||
It is the number of decimal digits that can be represented by a
|
||||
$icode Float$$ value. A number with this many decimal digits can be
|
||||
converted to $icode Float$$ and back to a string,
|
||||
without change due to rounding or overflow.
|
||||
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/num_limits.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref num_limits.cpp$$
|
||||
contains an example and test of these functions.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
# include <iostream>
|
||||
|
||||
# include <cppad/configure.hpp>
|
||||
# include <cppad/core/define.hpp>
|
||||
# include <cppad/core/cppad_assert.hpp>
|
||||
# include <cppad/local/declare_ad.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file numeric_limits.hpp
|
||||
File that defines CppAD numeric_limits for AD types
|
||||
*/
|
||||
|
||||
/// All tthese defaults correspond to errors
|
||||
template <class Float>
|
||||
class numeric_limits {
|
||||
public:
|
||||
/// machine epsilon
|
||||
static Float epsilon(void)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"numeric_limits<Float>::epsilon() is not specialized for this Float"
|
||||
);
|
||||
return Float(0);
|
||||
}
|
||||
/// minimum positive normalized value
|
||||
static Float min(void)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"numeric_limits<Float>::min() is not specialized for this Float"
|
||||
);
|
||||
return Float(0);
|
||||
}
|
||||
/// maximum finite value
|
||||
static Float max(void)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"numeric_limits<Float>::max() is not specialized for this Float"
|
||||
);
|
||||
return Float(0);
|
||||
}
|
||||
/// not a number
|
||||
static Float quiet_NaN(void)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"numeric_limits<Float>::quiet_NaN() is not specialized for this Float"
|
||||
);
|
||||
return Float(0);
|
||||
}
|
||||
/// number of decimal digits
|
||||
static const int digits10 = -1;
|
||||
};
|
||||
|
||||
/// Partial specialization that defines limits for for all AD types
|
||||
template <class Base>
|
||||
class numeric_limits< AD<Base> > {
|
||||
public:
|
||||
/// machine epsilon
|
||||
static AD<Base> epsilon(void)
|
||||
{ return AD<Base>( numeric_limits<Base>::epsilon() ); }
|
||||
/// minimum positive normalized value
|
||||
static AD<Base> min(void)
|
||||
{ return AD<Base>( numeric_limits<Base>::min() ); }
|
||||
/// maximum finite value
|
||||
static AD<Base> max(void)
|
||||
{ return AD<Base>( numeric_limits<Base>::max() ); }
|
||||
/// not a number
|
||||
static AD<Base> quiet_NaN(void)
|
||||
{ return AD<Base>( numeric_limits<Base>::quiet_NaN() ); }
|
||||
/// number of decimal digits
|
||||
static const int digits10 = numeric_limits<Base>::digits10;
|
||||
};
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+1088
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,95 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_OMP_MAX_THREAD_HPP
|
||||
# define CPPAD_CORE_OMP_MAX_THREAD_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 omp_max_thread$$
|
||||
$spell
|
||||
alloc
|
||||
num
|
||||
omp
|
||||
OpenMp
|
||||
CppAD
|
||||
$$
|
||||
|
||||
$section OpenMP Parallel Setup$$
|
||||
$mindex omp_max_thread$$
|
||||
|
||||
$head Deprecated 2011-06-23$$
|
||||
Use $cref/thread_alloc::parallel_setup/ta_parallel_setup/$$
|
||||
to set the number of threads.
|
||||
|
||||
$head Syntax$$
|
||||
$codei%AD<%Base%>::omp_max_thread(%number%)
|
||||
%$$
|
||||
|
||||
$head Purpose$$
|
||||
By default, for each $codei%AD<%Base%>%$$ class there is only one
|
||||
tape that records $cref/AD of Base/glossary/AD of Base/$$ operations.
|
||||
This tape is a global variable and hence it cannot be used
|
||||
by multiple OpenMP threads at the same time.
|
||||
The $code omp_max_thread$$ function is used to set the
|
||||
maximum number of OpenMP threads that can be active.
|
||||
In this case, there is a different tape corresponding to each
|
||||
$codei%AD<%Base%>%$$ class and thread pair.
|
||||
|
||||
$head number$$
|
||||
The argument $icode number$$ has prototype
|
||||
$codei%
|
||||
size_t %number%
|
||||
%$$
|
||||
It must be greater than zero and specifies the maximum number of
|
||||
OpenMp threads that will be active at one time.
|
||||
|
||||
|
||||
$head Independent$$
|
||||
Each call to $cref/Independent(x)/Independent/$$
|
||||
creates a new $cref/active/glossary/Tape/Active/$$ tape.
|
||||
All of the operations with the corresponding variables
|
||||
must be preformed by the same OpenMP thread.
|
||||
This includes the corresponding call to
|
||||
$cref/f.Dependent(x,y)/Dependent/$$ or the
|
||||
$cref/ADFun f(x, y)/FunConstruct/Sequence Constructor/$$
|
||||
during which the tape stops recording and the variables
|
||||
become parameters.
|
||||
|
||||
$head Restriction$$
|
||||
No tapes can be
|
||||
$cref/active/glossary/Tape/Active/$$ when this function is called.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
void AD<Base>::omp_max_thread(size_t number)
|
||||
{
|
||||
# ifdef _OPENMP
|
||||
thread_alloc::parallel_setup(
|
||||
number, omp_alloc::in_parallel, omp_alloc::get_thread_num
|
||||
);
|
||||
# else
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
number == 1,
|
||||
"omp_max_thread: number > 1 and _OPENMP is not defined"
|
||||
);
|
||||
# endif
|
||||
parallel_ad<Base>();
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+524
@@ -0,0 +1,524 @@
|
||||
# ifndef CPPAD_CORE_OPT_VAL_HES_HPP
|
||||
# define CPPAD_CORE_OPT_VAL_HES_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 opt_val_hes$$
|
||||
$spell
|
||||
hes
|
||||
sy
|
||||
Jacobian
|
||||
hes
|
||||
signdet
|
||||
jac
|
||||
Bradley
|
||||
const
|
||||
CppAD
|
||||
$$
|
||||
|
||||
|
||||
|
||||
$section Jacobian and Hessian of Optimal Values$$
|
||||
$mindex opt_val_hes$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%signdet% = opt_val_hes(%x%, %y%, %fun%, %jac%, %hes%)%$$
|
||||
|
||||
$head See Also$$
|
||||
$cref BenderQuad$$
|
||||
|
||||
$head Reference$$
|
||||
Algorithmic differentiation of implicit functions and optimal values,
|
||||
Bradley M. Bell and James V. Burke, Advances in Automatic Differentiation,
|
||||
2008, Springer.
|
||||
|
||||
$head Purpose$$
|
||||
We are given a function
|
||||
$latex S : \B{R}^n \times \B{R}^m \rightarrow \B{R}^\ell$$
|
||||
and we define $latex F : \B{R}^n \times \B{R}^m \rightarrow \B{R}$$
|
||||
and $latex V : \B{R}^n \rightarrow \B{R} $$ by
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
F(x, y) & = & \sum_{k=0}^{\ell-1} S_k ( x , y)
|
||||
\\
|
||||
V(x) & = & F [ x , Y(x) ]
|
||||
\\
|
||||
0 & = & \partial_y F [x , Y(x) ]
|
||||
\end{array}
|
||||
\] $$
|
||||
We wish to compute the Jacobian
|
||||
and possibly also the Hessian, of $latex V (x)$$.
|
||||
|
||||
$head BaseVector$$
|
||||
The type $icode BaseVector$$ must be a
|
||||
$cref SimpleVector$$ class.
|
||||
We use $icode Base$$ to refer to the type of the elements of
|
||||
$icode BaseVector$$; i.e.,
|
||||
$codei%
|
||||
%BaseVector%::value_type
|
||||
%$$
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %BaseVector%& %x%
|
||||
%$$
|
||||
and its size must be equal to $icode n$$.
|
||||
It specifies the point at which we evaluating
|
||||
the Jacobian $latex V^{(1)} (x)$$
|
||||
(and possibly the Hessian $latex V^{(2)} (x)$$).
|
||||
|
||||
|
||||
$head y$$
|
||||
The argument $icode y$$ has prototype
|
||||
$codei%
|
||||
const %BaseVector%& %y%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
It must be equal to $latex Y(x)$$; i.e.,
|
||||
it must solve the implicit equation
|
||||
$latex \[
|
||||
0 = \partial_y F ( x , y)
|
||||
\] $$
|
||||
|
||||
$head Fun$$
|
||||
The argument $icode fun$$ is an object of type $icode Fun$$
|
||||
which must support the member functions listed below.
|
||||
CppAD will may be recording operations of the type $codei%AD<%Base%>%$$
|
||||
when these member functions are called.
|
||||
These member functions must not stop such a recording; e.g.,
|
||||
they must not call $cref/AD<Base>::abort_recording/abort_recording/$$.
|
||||
|
||||
$subhead Fun::ad_vector$$
|
||||
The type $icode%Fun%::ad_vector%$$ must be a
|
||||
$cref SimpleVector$$ class with elements of type $codei%AD<%Base%>%$$; i.e.
|
||||
$codei%
|
||||
%Fun%::ad_vector::value_type
|
||||
%$$
|
||||
is equal to $codei%AD<%Base%>%$$.
|
||||
|
||||
$subhead fun.ell$$
|
||||
The type $icode Fun$$ must support the syntax
|
||||
$codei%
|
||||
%ell% = %fun%.ell()
|
||||
%$$
|
||||
where $icode ell$$ has prototype
|
||||
$codei%
|
||||
size_t %ell%
|
||||
%$$
|
||||
and is the value of $latex \ell$$; i.e.,
|
||||
the number of terms in the summation.
|
||||
$pre
|
||||
|
||||
$$
|
||||
One can choose $icode ell$$ equal to one, and have
|
||||
$latex S(x,y)$$ the same as $latex F(x, y)$$.
|
||||
Each of the functions $latex S_k (x , y)$$,
|
||||
(in the summation defining $latex F(x, y)$$)
|
||||
is differentiated separately using AD.
|
||||
For very large problems, breaking $latex F(x, y)$$ into the sum
|
||||
of separate simpler functions may reduce the amount of memory necessary for
|
||||
algorithmic differentiation and there by speed up the process.
|
||||
|
||||
$subhead fun.s$$
|
||||
The type $icode Fun$$ must support the syntax
|
||||
$codei%
|
||||
%s_k% = %fun%.s(%k%, %x%, %y%)
|
||||
%$$
|
||||
The $icode%fun%.s%$$ argument $icode k$$ has prototype
|
||||
$codei%
|
||||
size_t %k%
|
||||
%$$
|
||||
and is between zero and $icode%ell% - 1%$$.
|
||||
The argument $icode x$$ to $icode%fun%.s%$$ has prototype
|
||||
$codei%
|
||||
const %Fun%::ad_vector& %x%
|
||||
%$$
|
||||
and its size must be equal to $icode n$$.
|
||||
The argument $icode y$$ to $icode%fun%.s%$$ has prototype
|
||||
$codei%
|
||||
const %Fun%::ad_vector& %y%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
The $icode%fun%.s%$$ result $icode s_k$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %s_k%
|
||||
%$$
|
||||
and its value must be given by $latex s_k = S_k ( x , y )$$.
|
||||
|
||||
$subhead fun.sy$$
|
||||
The type $icode Fun$$ must support the syntax
|
||||
$codei%
|
||||
%sy_k% = %fun%.sy(%k%, %x%, %y%)
|
||||
%$$
|
||||
The argument $icode k$$ to $icode%fun%.sy%$$ has prototype
|
||||
$codei%
|
||||
size_t %k%
|
||||
%$$
|
||||
The argument $icode x$$ to $icode%fun%.sy%$$ has prototype
|
||||
$codei%
|
||||
const %Fun%::ad_vector& %x%
|
||||
%$$
|
||||
and its size must be equal to $icode n$$.
|
||||
The argument $icode y$$ to $icode%fun%.sy%$$ has prototype
|
||||
$codei%
|
||||
const %Fun%::ad_vector& %y%
|
||||
%$$
|
||||
and its size must be equal to $icode m$$.
|
||||
The $icode%fun%.sy%$$ result $icode sy_k$$ has prototype
|
||||
$codei%
|
||||
%Fun%::ad_vector %sy_k%
|
||||
%$$
|
||||
its size must be equal to $icode m$$,
|
||||
and its value must be given by $latex sy_k = \partial_y S_k ( x , y )$$.
|
||||
|
||||
$head jac$$
|
||||
The argument $icode jac$$ has prototype
|
||||
$codei%
|
||||
%BaseVector%& %jac%
|
||||
%$$
|
||||
and has size $icode n$$ or zero.
|
||||
The input values of its elements do not matter.
|
||||
If it has size zero, it is not affected. Otherwise, on output
|
||||
it contains the Jacobian of $latex V (x)$$; i.e.,
|
||||
for $latex j = 0 , \ldots , n-1$$,
|
||||
$latex \[
|
||||
jac[ j ] = V^{(1)} (x)_j
|
||||
\] $$
|
||||
where $icode x$$ is the first argument to $code opt_val_hes$$.
|
||||
|
||||
$head hes$$
|
||||
The argument $icode hes$$ has prototype
|
||||
$codei%
|
||||
%BaseVector%& %hes%
|
||||
%$$
|
||||
and has size $icode%n% * %n%$$ or zero.
|
||||
The input values of its elements do not matter.
|
||||
If it has size zero, it is not affected. Otherwise, on output
|
||||
it contains the Hessian of $latex V (x)$$; i.e.,
|
||||
for $latex i = 0 , \ldots , n-1$$, and
|
||||
$latex j = 0 , \ldots , n-1$$,
|
||||
$latex \[
|
||||
hes[ i * n + j ] = V^{(2)} (x)_{i,j}
|
||||
\] $$
|
||||
|
||||
|
||||
$head signdet$$
|
||||
If $icode%hes%$$ has size zero, $icode signdet$$ is not defined.
|
||||
Otherwise
|
||||
the return value $icode signdet$$ is the sign of the determinant for
|
||||
$latex \partial_{yy}^2 F(x , y) $$.
|
||||
If it is zero, then the matrix is singular and
|
||||
the Hessian is not computed ($icode hes$$ is not changed).
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/opt_val_hes.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref opt_val_hes.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file opt_val_hes.hpp
|
||||
\brief Computing Jabobians and Hessians of Optimal Values
|
||||
*/
|
||||
|
||||
/*!
|
||||
Computing Jabobians and Hessians of Optimal Values
|
||||
|
||||
We are given a function
|
||||
\f$ S : {\rm R}^n \times {\rm R}^m \rightarrow {\rm R}^\ell \f$
|
||||
and we define \f$ F : {\rm R}^n \times {\rm R}^m \rightarrow {\rm R} \f$
|
||||
and \f$ V : {\rm R}^n \rightarrow {\rm R} \f$ by
|
||||
\f[
|
||||
\begin{array}{rcl}
|
||||
F(x, y) & = & \sum_{k=0}^{\ell-1} S_k ( x , y)
|
||||
\\
|
||||
V(x) & = & F [ x , Y(x) ]
|
||||
\\
|
||||
0 & = & \partial_y F [x , Y(x) ]
|
||||
\end{array}
|
||||
\f]
|
||||
We wish to compute the Jacobian
|
||||
and possibly also the Hessian, of \f$ V (x) \f$.
|
||||
|
||||
\tparam BaseVector
|
||||
The type \c BaseVector must be a SimpleVector class.
|
||||
We use \c Base to refer to the type of the elements of
|
||||
\c BaseVector; i.e.,
|
||||
<tt>BaseVector::value_type</tt>.
|
||||
|
||||
\param x
|
||||
is a vector with size \c n.
|
||||
It specifies the point at which we evaluating
|
||||
the Jacobian \f$ V^{(1)} (x) \f$
|
||||
(and possibly the Hessian \f$ V^{(2)} (x) \f$).
|
||||
|
||||
|
||||
\param y
|
||||
is a vector with size \c m.
|
||||
It must be equal to \f$ Y(x) \f$; i.e.,
|
||||
it must solve the implicit equation
|
||||
\f[
|
||||
0 = \partial_y F ( x , y)
|
||||
\f]
|
||||
|
||||
\param fun
|
||||
The argument \c fun is an object of type \c Fun
|
||||
wich must support the member functions listed below.
|
||||
CppAD will may be recording operations of the type \c AD<Base>
|
||||
when these member functions are called.
|
||||
These member functions must not stop such a recording; e.g.,
|
||||
they must not call \c AD<Base>::abort_recording.
|
||||
|
||||
\par Fun::ad_vector</tt>
|
||||
The type <tt>Fun::ad_vector</tt> must be a
|
||||
SimpleVector class with elements of type \c AD<Base>; i.e.
|
||||
<tt>Fun::ad_vector::value_type</tt>
|
||||
is equal to \c AD<Base>.
|
||||
|
||||
\par fun.ell
|
||||
the type \c Fun must support the syntax
|
||||
\verbatim
|
||||
ell = fun.ell()
|
||||
\endverbatim
|
||||
where \c ell is a \c size_t value that is set to \f$ \ell \f$; i.e.,
|
||||
the number of terms in the summation.
|
||||
|
||||
\par fun.s
|
||||
The type \c Fun must support the syntax
|
||||
\verbatim
|
||||
s_k = fun.s(k, x, y)
|
||||
\endverbatim
|
||||
The argument \c k has prototype <tt>size_t k</tt>.
|
||||
The argument \c x has prototype <tt>const Fun::ad_vector& x</tt>
|
||||
and its size must be equal to \c n.
|
||||
The argument \c y has prototype <tt>const Fun::ad_vector& y</tt>
|
||||
and its size must be equal to \c m.
|
||||
The return value \c s_k has prototype \c AD<Base> s_k
|
||||
and its value must be given by \f$ s_k = S_k ( x , y ) \f$.
|
||||
|
||||
\par fun.sy
|
||||
The type \c Fun must support the syntax
|
||||
\verbatim
|
||||
sy_k = fun.sy(k, x, y)
|
||||
\endverbatim
|
||||
The argument \c k has prototype <tt>size_t k</tt>.
|
||||
The argument \c x has prototype <tt>const Fun::ad_vector& x</tt>
|
||||
and its size must be equal to \c n.
|
||||
The argument \c y has prototype <tt>const Fun::ad_vector& y</tt>
|
||||
and its size must be equal to \c m.
|
||||
The return value \c sy_k has prototype <tt>Fun::ad_vector& sy_k</tt>,
|
||||
its size is \c m
|
||||
and its value must be given by \f$ sy_k = \partial_y S_k ( x , y ) \f$.
|
||||
|
||||
\param jac
|
||||
is a vector with size \c n or zero.
|
||||
The input values of its elements do not matter.
|
||||
If it has size zero, it is not affected. Otherwise, on output
|
||||
it contains the Jacobian of \f$ V (x) \f$; i.e.,
|
||||
for \f$ j = 0 , \ldots , n-1 \f$,
|
||||
\f[
|
||||
jac[ j ] = V^{(1)} (x)_j
|
||||
\f] $$
|
||||
where \c x is the first argument to \c opt_val_hes.
|
||||
|
||||
\param hes
|
||||
is a vector with size <tt>n * n</tt> or zero.
|
||||
The input values of its elements do not matter.
|
||||
If it has size zero, it is not affected. Otherwise, on output
|
||||
it contains the Hessian of \f$ V (x) \f$; i.e.,
|
||||
for \f$ i = 0 , \ldots , n-1 \f$, and
|
||||
\f$ j = 0 , \ldots , n-1 \f$,
|
||||
\f[
|
||||
hes[ i * n + j ] = V^{(2)} (x)_{i,j}
|
||||
\f]
|
||||
|
||||
\return
|
||||
If <tt>hes.size() == 0</tt>, the return value is not defined.
|
||||
Otherwise,
|
||||
the return value is the sign of the determinant for
|
||||
\f$ \partial_{yy}^2 F(x , y) \f$$.
|
||||
If it is zero, then the matrix is singular and \c hes is not set
|
||||
to its specified value.
|
||||
*/
|
||||
|
||||
|
||||
template <class BaseVector, class Fun>
|
||||
int opt_val_hes(
|
||||
const BaseVector& x ,
|
||||
const BaseVector& y ,
|
||||
Fun fun ,
|
||||
BaseVector& jac ,
|
||||
BaseVector& hes )
|
||||
{ // determine the base type
|
||||
typedef typename BaseVector::value_type Base;
|
||||
|
||||
// check that BaseVector is a SimpleVector class with Base elements
|
||||
CheckSimpleVector<Base, BaseVector>();
|
||||
|
||||
// determine the AD vector type
|
||||
typedef typename Fun::ad_vector ad_vector;
|
||||
|
||||
// check that ad_vector is a SimpleVector class with AD<Base> elements
|
||||
CheckSimpleVector< AD<Base> , ad_vector >();
|
||||
|
||||
// size of the x and y spaces
|
||||
size_t n = size_t(x.size());
|
||||
size_t m = size_t(y.size());
|
||||
|
||||
// number of terms in the summation
|
||||
size_t ell = fun.ell();
|
||||
|
||||
// check size of return values
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(jac.size()) == n || jac.size() == 0,
|
||||
"opt_val_hes: size of the vector jac is not equal to n or zero"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(hes.size()) == n * n || hes.size() == 0,
|
||||
"opt_val_hes: size of the vector hes is not equal to n * n or zero"
|
||||
);
|
||||
|
||||
// some temporary indices
|
||||
size_t i, j, k;
|
||||
|
||||
// AD version of S_k(x, y)
|
||||
ad_vector s_k(1);
|
||||
|
||||
// ADFun version of S_k(x, y)
|
||||
ADFun<Base> S_k;
|
||||
|
||||
// AD version of x
|
||||
ad_vector a_x(n);
|
||||
|
||||
// AD version of y
|
||||
ad_vector a_y(n);
|
||||
|
||||
if( jac.size() > 0 )
|
||||
{ // this is the easy part, computing the V^{(1)} (x) which is equal
|
||||
// to \partial_x F (x, y) (see Thoerem 2 of the reference).
|
||||
|
||||
// copy x and y to AD version
|
||||
for(j = 0; j < n; j++)
|
||||
a_x[j] = x[j];
|
||||
for(j = 0; j < m; j++)
|
||||
a_y[j] = y[j];
|
||||
|
||||
// initialize summation
|
||||
for(j = 0; j < n; j++)
|
||||
jac[j] = Base(0.);
|
||||
|
||||
// add in \partial_x S_k (x, y)
|
||||
for(k = 0; k < ell; k++)
|
||||
{ // start recording
|
||||
Independent(a_x);
|
||||
// record
|
||||
s_k[0] = fun.s(k, a_x, a_y);
|
||||
// stop recording and store in S_k
|
||||
S_k.Dependent(a_x, s_k);
|
||||
// compute partial of S_k with respect to x
|
||||
BaseVector jac_k = S_k.Jacobian(x);
|
||||
// add \partial_x S_k (x, y) to jac
|
||||
for(j = 0; j < n; j++)
|
||||
jac[j] += jac_k[j];
|
||||
}
|
||||
}
|
||||
// check if we are done
|
||||
if( hes.size() == 0 )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
In this case, we need to compute the Hessian. Using Theorem 1 of the
|
||||
reference:
|
||||
Y^{(1)}(x) = - F_yy (x, y)^{-1} F_yx (x, y)
|
||||
Using Theorem 2 of the reference:
|
||||
V^{(2)}(x) = F_xx (x, y) + F_xy (x, y) Y^{(1)}(x)
|
||||
*/
|
||||
// Base and AD version of xy
|
||||
BaseVector xy(n + m);
|
||||
ad_vector a_xy(n + m);
|
||||
for(j = 0; j < n; j++)
|
||||
a_xy[j] = xy[j] = x[j];
|
||||
for(j = 0; j < m; j++)
|
||||
a_xy[n+j] = xy[n+j] = y[j];
|
||||
|
||||
// Initialization summation for Hessian of F
|
||||
size_t nm_sq = (n + m) * (n + m);
|
||||
BaseVector F_hes(nm_sq);
|
||||
for(j = 0; j < nm_sq; j++)
|
||||
F_hes[j] = Base(0.);
|
||||
BaseVector hes_k(nm_sq);
|
||||
|
||||
// add in Hessian of S_k to hes
|
||||
for(k = 0; k < ell; k++)
|
||||
{ // start recording
|
||||
Independent(a_xy);
|
||||
// split out x
|
||||
for(j = 0; j < n; j++)
|
||||
a_x[j] = a_xy[j];
|
||||
// split out y
|
||||
for(j = 0; j < m; j++)
|
||||
a_y[j] = a_xy[n+j];
|
||||
// record
|
||||
s_k[0] = fun.s(k, a_x, a_y);
|
||||
// stop recording and store in S_k
|
||||
S_k.Dependent(a_xy, s_k);
|
||||
// when computing the Hessian it pays to optimize the tape
|
||||
S_k.optimize();
|
||||
// compute Hessian of S_k
|
||||
hes_k = S_k.Hessian(xy, 0);
|
||||
// add \partial_x S_k (x, y) to jac
|
||||
for(j = 0; j < nm_sq; j++)
|
||||
F_hes[j] += hes_k[j];
|
||||
}
|
||||
// Extract F_yx
|
||||
BaseVector F_yx(m * n);
|
||||
for(i = 0; i < m; i++)
|
||||
{ for(j = 0; j < n; j++)
|
||||
F_yx[i * n + j] = F_hes[ (i+n)*(n+m) + j ];
|
||||
}
|
||||
// Extract F_yy
|
||||
BaseVector F_yy(n * m);
|
||||
for(i = 0; i < m; i++)
|
||||
{ for(j = 0; j < m; j++)
|
||||
F_yy[i * m + j] = F_hes[ (i+n)*(n+m) + j + n ];
|
||||
}
|
||||
|
||||
// compute - Y^{(1)}(x) = F_yy (x, y)^{-1} F_yx (x, y)
|
||||
BaseVector neg_Y_x(m * n);
|
||||
Base logdet;
|
||||
int signdet = CppAD::LuSolve(m, n, F_yy, F_yx, neg_Y_x, logdet);
|
||||
if( signdet == 0 )
|
||||
return signdet;
|
||||
|
||||
// compute hes = F_xx (x, y) + F_xy (x, y) Y^{(1)}(x)
|
||||
for(i = 0; i < n; i++)
|
||||
{ for(j = 0; j < n; j++)
|
||||
{ hes[i * n + j] = F_hes[ i*(n+m) + j ];
|
||||
for(k = 0; k < m; k++)
|
||||
hes[i*n+j] -= F_hes[i*(n+m) + k+n] * neg_Y_x[k*n+j];
|
||||
}
|
||||
}
|
||||
return signdet;
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
# endif
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_OPTIMIZE_HPP
|
||||
# define CPPAD_CORE_OPTIMIZE_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 optimize$$
|
||||
$spell
|
||||
enum
|
||||
jac
|
||||
bool
|
||||
Taylor
|
||||
CppAD
|
||||
cppad
|
||||
std
|
||||
const
|
||||
onetape
|
||||
op
|
||||
$$
|
||||
|
||||
$section Optimize an ADFun Object Tape$$
|
||||
$mindex sequence operations speed memory NDEBUG$$
|
||||
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.optimize()
|
||||
%$$
|
||||
$icode%f%.optimize(%options%)
|
||||
%$$
|
||||
|
||||
$head Purpose$$
|
||||
The operation sequence corresponding to an $cref ADFun$$ object can
|
||||
be very large and involve many operations; see the
|
||||
size functions in $cref seq_property$$.
|
||||
The $icode%f%.optimize%$$ procedure reduces the number of operations,
|
||||
and thereby the time and the memory, required to
|
||||
compute function and derivative values.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head options$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
const std::string& %options%
|
||||
%$$
|
||||
The default for $icode options$$ is the empty string.
|
||||
If it is present, it must consist of one or more of the options below
|
||||
separated by a single space character.
|
||||
|
||||
$subhead no_conditional_skip$$
|
||||
The $code optimize$$ function can create conditional skip operators
|
||||
to improve the speed of conditional expressions; see
|
||||
$cref/optimize/CondExp/Optimize/$$.
|
||||
If the sub-string $code no_conditional_skip$$ appears in $icode options$$,
|
||||
conditional skip operations are not be generated.
|
||||
This may make the optimize routine use significantly less memory
|
||||
and take less time to optimize $icode f$$.
|
||||
If conditional skip operations are generated,
|
||||
it may save a significant amount of time when
|
||||
using $icode f$$ for $cref forward$$ or $cref reverse$$ mode calculations;
|
||||
see $cref number_skip$$.
|
||||
|
||||
$subhead no_compare_op$$
|
||||
If the sub-string $code no_compare_op$$ appears in $icode options$$,
|
||||
comparison operators will be removed from the optimized function.
|
||||
These operators are necessary for the
|
||||
$cref compare_change$$ functions to be meaningful.
|
||||
On the other hand, they are not necessary, and take extra time,
|
||||
when the compare_change functions are not used.
|
||||
|
||||
$subhead no_print_for_op$$
|
||||
If the sub-string $code no_compare_op$$ appears in $icode options$$,
|
||||
$cref PrintFor$$ operations will be removed form the optimized function.
|
||||
These operators are useful for reporting problems evaluating derivatives
|
||||
at independent variable values different from those used to record a function.
|
||||
|
||||
$head Examples$$
|
||||
$children%
|
||||
example/optimize/forward_active.cpp
|
||||
%example/optimize/reverse_active.cpp
|
||||
%example/optimize/compare_op.cpp
|
||||
%example/optimize/print_for.cpp
|
||||
%example/optimize/conditional_skip.cpp
|
||||
%example/optimize/nest_conditional.cpp
|
||||
%example/optimize/cumulative_sum.cpp
|
||||
%$$
|
||||
$table
|
||||
$cref/forward_active.cpp/optimize_forward_active.cpp/$$ $cnext
|
||||
$title optimize_forward_active.cpp$$
|
||||
$rnext
|
||||
$cref/reverse_active.cpp/optimize_reverse_active.cpp/$$ $cnext
|
||||
$title optimize_reverse_active.cpp$$
|
||||
$rnext
|
||||
$cref/compare_op.cpp/optimize_compare_op.cpp/$$ $cnext
|
||||
$title optimize_compare_op.cpp$$
|
||||
$rnext
|
||||
$cref/print_for_op.cpp/optimize_print_for.cpp/$$ $cnext
|
||||
$title optimize_print_for.cpp$$
|
||||
$rnext
|
||||
$cref/conditional_skip.cpp/optimize_conditional_skip.cpp/$$ $cnext
|
||||
$title optimize_conditional_skip.cpp$$
|
||||
$rnext
|
||||
$cref/nest_conditional.cpp/optimize_nest_conditional.cpp/$$ $cnext
|
||||
$title optimize_nest_conditional.cpp$$
|
||||
$rnext
|
||||
$cref/cumulative_sum.cpp/optimize_cumulative_sum.cpp/$$ $cnext
|
||||
$title optimize_cumulative_sum.cpp$$
|
||||
$tend
|
||||
|
||||
$head Efficiency$$
|
||||
If a $cref/zero order forward/forward_zero/$$ calculation is done during
|
||||
the construction of $icode f$$, it will require more memory
|
||||
and time than required after the optimization procedure.
|
||||
In addition, it will need to be redone.
|
||||
For this reason, it is more efficient to use
|
||||
$codei%
|
||||
ADFun<%Base%> %f%;
|
||||
%f%.Dependent(%x%, %y%);
|
||||
%f%.optimize();
|
||||
%$$
|
||||
instead of
|
||||
$codei%
|
||||
ADFun<%Base%> %f%(%x%, %y%)
|
||||
%f%.optimize();
|
||||
%$$
|
||||
See the discussion about
|
||||
$cref/sequence constructors/FunConstruct/Sequence Constructor/$$.
|
||||
|
||||
$head Speed Testing$$
|
||||
You can run the CppAD $cref/speed/speed_main/$$ tests and see
|
||||
the corresponding changes in number of variables and execution time.
|
||||
Note that there is an interaction between using
|
||||
$cref/optimize/speed_main/Global Options/optimize/$$ and
|
||||
$cref/onetape/speed_main/Global Options/onetape/$$.
|
||||
If $icode onetape$$ is true and $icode optimize$$ is true,
|
||||
the optimized tape will be reused many times.
|
||||
If $icode onetape$$ is false and $icode optimize$$ is true,
|
||||
the tape will be re-optimized for each test.
|
||||
|
||||
$head Atomic Functions$$
|
||||
There are some subtitle issue with optimized $cref atomic$$ functions
|
||||
$latex v = g(u)$$:
|
||||
|
||||
$subhead rev_sparse_jac$$
|
||||
The $cref atomic_rev_sparse_jac$$ function is be used to determine
|
||||
which components of $icode u$$ affect the dependent variables of $icode f$$.
|
||||
For each atomic operation, the current
|
||||
$cref/atomic_sparsity/atomic_option/atomic_sparsity/$$ setting is used
|
||||
to determine if $code pack_sparsity_enum$$, $code bool_sparsity_enum$$,
|
||||
or $code set_sparsity_enum$$ is used to determine dependency relations
|
||||
between argument and result variables.
|
||||
|
||||
$subhead nan$$
|
||||
If $icode%u%[%i%]%$$ does not affect the value of
|
||||
the dependent variables for $icode f$$,
|
||||
the value of $icode%u%[%i%]%$$ is set to $cref nan$$.
|
||||
|
||||
$head Checking Optimization$$
|
||||
If $cref/NDEBUG/Faq/Speed/NDEBUG/$$ is not defined,
|
||||
and $cref/f.size_order()/size_order/$$ is greater than zero,
|
||||
a $cref forward_zero$$ calculation is done using the optimized version
|
||||
of $icode f$$ and the results are checked to see that they are
|
||||
the same as before.
|
||||
If they are not the same, the
|
||||
$cref ErrorHandler$$ is called with a known error message
|
||||
related to $icode%f%.optimize()%$$.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/local/optimize/optimize_run.hpp>
|
||||
/*!
|
||||
\file optimize.hpp
|
||||
Optimize a player object operation sequence
|
||||
*/
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
Optimize a player object operation sequence
|
||||
|
||||
The operation sequence for this object is replaced by one with fewer operations
|
||||
but the same funcition and derivative values.
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation was recorded
|
||||
using AD<Base> and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\param options
|
||||
\li
|
||||
If the sub-string "no_conditional_skip" appears,
|
||||
conditional skip operations will not be generated.
|
||||
This may make the optimize routine use significantly less memory
|
||||
and take significantly less time.
|
||||
\li
|
||||
If the sub-string "no_compare_op" appears,
|
||||
then comparison operators will be removed from the optimized tape.
|
||||
These operators are necessary for the compare_change function to be
|
||||
be meaningful in the resulting recording.
|
||||
On the other hand, they are not necessary and take extra time
|
||||
when compare_change is not used.
|
||||
*/
|
||||
template <class Base>
|
||||
void ADFun<Base>::optimize(const std::string& options)
|
||||
{ // place to store the optimized version of the recording
|
||||
local::recorder<Base> rec;
|
||||
|
||||
// number of independent variables
|
||||
size_t n = ind_taddr_.size();
|
||||
|
||||
# ifndef NDEBUG
|
||||
size_t i, j, m = dep_taddr_.size();
|
||||
CppAD::vector<Base> x(n), y(m), check(m);
|
||||
Base max_taylor(0);
|
||||
bool check_zero_order = num_order_taylor_ > 0;
|
||||
if( check_zero_order )
|
||||
{ // zero order coefficients for independent vars
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( play_.GetOp(j+1) == local::InvOp );
|
||||
CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j+1 );
|
||||
x[j] = taylor_[ ind_taddr_[j] * cap_order_taylor_ + 0];
|
||||
}
|
||||
// zero order coefficients for dependent vars
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
y[i] = taylor_[ dep_taddr_[i] * cap_order_taylor_ + 0];
|
||||
}
|
||||
// maximum zero order coefficient not counting BeginOp at beginning
|
||||
// (which is correpsonds to uninitialized memory).
|
||||
for(i = 1; i < num_var_tape_; i++)
|
||||
{ if( abs_geq(taylor_[i*cap_order_taylor_+0] , max_taylor) )
|
||||
max_taylor = taylor_[i*cap_order_taylor_+0];
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
// create the optimized recording
|
||||
local::optimize::optimize_run<Base>(options, n, dep_taddr_, &play_, &rec);
|
||||
|
||||
// number of variables in the recording
|
||||
num_var_tape_ = rec.num_var_rec();
|
||||
|
||||
// now replace the recording
|
||||
play_.get(rec);
|
||||
|
||||
// set flag so this function knows it has been optimized
|
||||
has_been_optimized_ = true;
|
||||
|
||||
// free memory allocated for sparse Jacobian calculation
|
||||
// (the results are no longer valid)
|
||||
for_jac_sparse_pack_.resize(0, 0);
|
||||
for_jac_sparse_set_.resize(0,0);
|
||||
|
||||
// free old Taylor coefficient memory
|
||||
taylor_.free();
|
||||
num_order_taylor_ = 0;
|
||||
cap_order_taylor_ = 0;
|
||||
|
||||
// resize and initilaize conditional skip vector
|
||||
// (must use player size because it now has the recoreder information)
|
||||
cskip_op_.erase();
|
||||
cskip_op_.extend( play_.num_op_rec() );
|
||||
|
||||
# ifndef NDEBUG
|
||||
if( check_zero_order )
|
||||
{
|
||||
// zero order forward calculation using new operation sequence
|
||||
check = Forward(0, x);
|
||||
|
||||
// check results
|
||||
Base eps = 10. * CppAD::numeric_limits<Base>::epsilon();
|
||||
for(i = 0; i < m; i++) CPPAD_ASSERT_KNOWN(
|
||||
abs_geq( eps * max_taylor , check[i] - y[i] ) ,
|
||||
"Error during check of f.optimize()."
|
||||
);
|
||||
|
||||
// Erase memory that this calculation was done so NDEBUG gives
|
||||
// same final state for this object (from users perspective)
|
||||
num_order_taylor_ = 0;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_ORDERED_HPP
|
||||
# define CPPAD_CORE_ORDERED_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/core/define.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
\file ordered.hpp
|
||||
Check and AD values ordering properties relative to zero.
|
||||
*/
|
||||
|
||||
// GreaterThanZero ============================================================
|
||||
/*!
|
||||
Check if an AD<Base> is greater than zero.
|
||||
|
||||
\param x
|
||||
value we are checking.
|
||||
|
||||
\return
|
||||
returns true iff the \c x is greater than zero.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool GreaterThanZero(const AD<Base> &x)
|
||||
{ return GreaterThanZero(x.value_); }
|
||||
// GreaterThanOrZero =========================================================
|
||||
/*!
|
||||
Check if an AD<Base> is greater than or equal zero.
|
||||
|
||||
\param x
|
||||
value we are checking.
|
||||
|
||||
\return
|
||||
returns true iff the \c x is greater than or equal zero.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool GreaterThanOrZero(const AD<Base> &x)
|
||||
{ return GreaterThanOrZero(x.value_); }
|
||||
// LessThanZero ============================================================
|
||||
/*!
|
||||
Check if an AD<Base> is less than zero.
|
||||
|
||||
\param x
|
||||
value we are checking.
|
||||
|
||||
\return
|
||||
returns true iff the \c x is less than zero.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool LessThanZero(const AD<Base> &x)
|
||||
{ return LessThanZero(x.value_); }
|
||||
// LessThanOrZero =========================================================
|
||||
/*!
|
||||
Check if an AD<Base> is less than or equal zero.
|
||||
|
||||
\param x
|
||||
value we are checking.
|
||||
|
||||
\return
|
||||
returns true iff the \c x is less than or equal zero.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool LessThanOrZero(const AD<Base> &x)
|
||||
{ return LessThanOrZero(x.value_); }
|
||||
// abs_geq =========================================================
|
||||
/*!
|
||||
Check if absolute value of one AD<Base> is greater or equal another.
|
||||
|
||||
\param x
|
||||
value we are checking if it is greater than or equal other.
|
||||
|
||||
\param y
|
||||
value we are checking if it is less than other.
|
||||
|
||||
\return
|
||||
returns true iff the absolute value of \c x is greater than or equal
|
||||
absolute value of \c y.
|
||||
*/
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool abs_geq(const AD<Base>& x, const AD<Base>& y)
|
||||
{ return abs_geq(x.value_, y.value_); }
|
||||
// ============================================================================
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
# ifndef CPPAD_CORE_PAR_VAR_HPP
|
||||
# define CPPAD_CORE_PAR_VAR_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 ParVar$$
|
||||
$spell
|
||||
VecAD
|
||||
const
|
||||
bool
|
||||
$$
|
||||
|
||||
$section Is an AD Object a Parameter or Variable$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%b% = Parameter(%x%)%$$
|
||||
$pre
|
||||
$$
|
||||
$icode%b% = Variable(%x%)%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Determine if $icode x$$ is a
|
||||
$cref/parameter/glossary/Parameter/$$ or
|
||||
$cref/variable/glossary/Variable/$$.
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const AD<%Base%> &%x%
|
||||
const VecAD<%Base%> &%x%
|
||||
%$$
|
||||
|
||||
$head b$$
|
||||
The return value $icode b$$ has prototype
|
||||
$codei%
|
||||
bool %b%
|
||||
%$$
|
||||
The return value for $code Parameter$$ ($code Variable$$)
|
||||
is true if and only if $icode x$$ is a parameter (variable).
|
||||
Note that a $cref/VecAD<Base>/VecAD/$$ object
|
||||
is a variable if any element of the vector depends on the independent
|
||||
variables.
|
||||
|
||||
$head Operation Sequence$$
|
||||
The result of this operation is not an
|
||||
$cref/AD of Base/glossary/AD of Base/$$ object.
|
||||
Thus it will not be recorded as part of an
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/par_var.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref par_var.cpp$$
|
||||
contains an example and test of these functions.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
namespace CppAD {
|
||||
// Parameter
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool Parameter(const AD<Base> &x)
|
||||
{ if( x.tape_id_ == 0 )
|
||||
return true;
|
||||
size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);
|
||||
return x.tape_id_ != *AD<Base>::tape_id_ptr(thread);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool Parameter(const VecAD<Base> &x)
|
||||
{ if( x.tape_id_ == 0 )
|
||||
return true;
|
||||
size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);
|
||||
return x.tape_id_ != *AD<Base>::tape_id_ptr(thread);
|
||||
}
|
||||
|
||||
// Variable
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool Variable(const AD<Base> &x)
|
||||
{ if( x.tape_id_ == 0 )
|
||||
return false;
|
||||
size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);
|
||||
return x.tape_id_ == *AD<Base>::tape_id_ptr(thread);
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
|
||||
bool Variable(const VecAD<Base> &x)
|
||||
{ if( x.tape_id_ == 0 )
|
||||
return false;
|
||||
size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);
|
||||
return x.tape_id_ == *AD<Base>::tape_id_ptr(thread);
|
||||
}
|
||||
}
|
||||
// END CppAD namespace
|
||||
|
||||
|
||||
# endif
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_PARALLEL_AD_HPP
|
||||
# define CPPAD_CORE_PARALLEL_AD_HPP
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 parallel_ad$$
|
||||
$spell
|
||||
CppAD
|
||||
num
|
||||
std
|
||||
$$
|
||||
|
||||
$section Enable AD Calculations During Parallel Mode$$
|
||||
|
||||
$head Syntax$$
|
||||
$codei%parallel_ad<%Base%>()%$$
|
||||
|
||||
$head Purpose$$
|
||||
The function
|
||||
$codei%parallel_ad<%Base%>()%$$
|
||||
must be called before any $codei%AD<%Base>%$$ objects are used
|
||||
in $cref/parallel/ta_in_parallel/$$ mode.
|
||||
In addition, if this routine is called after one is done using
|
||||
parallel mode, it will free extra memory used to keep track of
|
||||
the multiple $codei%AD<%Base%>%$$ tapes required for parallel execution.
|
||||
|
||||
$head Discussion$$
|
||||
By default, for each $codei%AD<%Base%>%$$ class there is only one
|
||||
tape that records $cref/AD of Base/glossary/AD of Base/$$ operations.
|
||||
This tape is a global variable and hence it cannot be used
|
||||
by multiple threads at the same time.
|
||||
The $cref/parallel_setup/ta_parallel_setup/$$ function informs CppAD of the
|
||||
maximum number of threads that can be active in parallel mode.
|
||||
This routine does extra setup
|
||||
(and teardown) for the particular $icode Base$$ type.
|
||||
|
||||
$head CheckSimpleVector$$
|
||||
This routine has the side effect of calling the routines
|
||||
$codei%
|
||||
CheckSimpleVector< %Type%, CppAD::vector<%Type%> >()
|
||||
%$$
|
||||
where $icode Type$$ is $icode Base$$ and $codei%AD<%Base%>%$$.
|
||||
|
||||
$head Example$$
|
||||
The files
|
||||
$cref team_openmp.cpp$$,
|
||||
$cref team_bthread.cpp$$, and
|
||||
$cref team_pthread.cpp$$,
|
||||
contain examples and tests that implement this function.
|
||||
|
||||
$head Restriction$$
|
||||
This routine cannot be called in parallel mode or while
|
||||
there is a tape recording $codei%AD<%Base%>%$$ operations.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
# include <cppad/local/std_set.hpp>
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
/*!
|
||||
Enable parallel execution mode with <code>AD<Base></code> by initializing
|
||||
static variables that my be used.
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
void parallel_ad(void)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
! thread_alloc::in_parallel() ,
|
||||
"parallel_ad must be called before entering parallel execution mode."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
AD<Base>::tape_ptr() == CPPAD_NULL ,
|
||||
"parallel_ad cannot be called while a tape recording is in progress"
|
||||
);
|
||||
|
||||
// ensure statics in following functions are initialized
|
||||
elapsed_seconds();
|
||||
ErrorHandler::Current();
|
||||
local::NumArg(local::BeginOp);
|
||||
local::NumRes(local::BeginOp);
|
||||
local::one_element_std_set<size_t>();
|
||||
local::two_element_std_set<size_t>();
|
||||
|
||||
// the sparse_pack class has member functions with static data
|
||||
local::sparse_pack sp;
|
||||
sp.resize(1, 1); // so can call add_element
|
||||
sp.add_element(0, 0); // has static data
|
||||
sp.clear(0); // has static data
|
||||
sp.is_element(0, 0); // has static data
|
||||
local::sparse_pack::const_iterator itr(sp, 0); // has static data
|
||||
++itr; // has static data
|
||||
|
||||
// statics that depend on the value of Base
|
||||
AD<Base>::tape_id_handle(0);
|
||||
AD<Base>::tape_handle(0);
|
||||
AD<Base>::tape_manage(tape_manage_clear);
|
||||
discrete<Base>::List();
|
||||
CheckSimpleVector< Base, CppAD::vector<Base> >();
|
||||
CheckSimpleVector< AD<Base>, CppAD::vector< AD<Base> > >();
|
||||
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+257
@@ -0,0 +1,257 @@
|
||||
# ifndef CPPAD_CORE_POW_HPP
|
||||
# define CPPAD_CORE_POW_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 pow$$
|
||||
$spell
|
||||
Vec
|
||||
std
|
||||
namespace
|
||||
CppAD
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section The AD Power Function$$
|
||||
$mindex pow exponent$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%z% = pow(%x%, %y%)%$$
|
||||
|
||||
$head See Also$$
|
||||
$cref pow_int$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
Determines the value of the power function which is defined by
|
||||
$latex \[
|
||||
{\rm pow} (x, y) = x^y
|
||||
\] $$
|
||||
This version of the $code pow$$ function may use
|
||||
logarithms and exponentiation to compute derivatives.
|
||||
This will not work if $icode x$$ is less than or equal zero.
|
||||
If the value of $icode y$$ is an integer,
|
||||
the $cref pow_int$$ function is used to compute this value
|
||||
using only multiplication (and division if $icode y$$ is negative).
|
||||
(This will work even if $icode x$$ is less than or equal zero.)
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has one of the following prototypes
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
const AD<%Base%>& %x%
|
||||
const VecAD<%Base%>::reference& %x%
|
||||
%$$
|
||||
|
||||
$head y$$
|
||||
The argument $icode y$$ has one of the following prototypes
|
||||
$codei%
|
||||
const %Base%& %y%
|
||||
const AD<%Base%>& %y%
|
||||
const VecAD<%Base%>::reference& %y%
|
||||
%$$
|
||||
|
||||
$head z$$
|
||||
If both $icode x$$ and $icode y$$ are $icode Base$$ objects,
|
||||
the result $icode z$$ is also a $icode Base$$ object.
|
||||
Otherwise, it has prototype
|
||||
$codei%
|
||||
AD<%Base%> %z%
|
||||
%$$
|
||||
|
||||
$head Operation Sequence$$
|
||||
This is an AD of $icode Base$$
|
||||
$cref/atomic operation/glossary/Operation/Atomic/$$
|
||||
and hence is part of the current
|
||||
AD of $icode Base$$
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/pow.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref pow.cpp$$
|
||||
is an examples and tests of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
// case where x and y are AD<Base> -----------------------------------------
|
||||
template <class Base> AD<Base>
|
||||
pow(const AD<Base>& x, const AD<Base>& y)
|
||||
{
|
||||
// compute the Base part
|
||||
AD<Base> result;
|
||||
result.value_ = pow(x.value_, y.value_);
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return result;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_x = x.tape_id_ == tape_id;
|
||||
bool var_y = y.tape_id_ == tape_id;
|
||||
|
||||
if( var_x )
|
||||
{ if( var_y )
|
||||
{ // result = variable^variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::PowvvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::PowvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(x.taddr_, y.taddr_);
|
||||
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::PowvvOp);
|
||||
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
else if( IdenticalZero( y.value_ ) )
|
||||
{ // result = variable^0
|
||||
}
|
||||
else
|
||||
{ // result = variable^parameter
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::PowvpOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::PowvpOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(y.value_);
|
||||
tape->Rec_.PutArg(x.taddr_, p);
|
||||
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::PowvpOp);
|
||||
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
else if( var_y )
|
||||
{ if( IdenticalZero(x.value_) )
|
||||
{ // result = 0^variable
|
||||
}
|
||||
else
|
||||
{ // result = parameter^variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::PowpvOp) == 3 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::PowpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(x.value_);
|
||||
tape->Rec_.PutArg(p, y.taddr_);
|
||||
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::PowpvOp);
|
||||
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// =========================================================================
|
||||
// Fold operations in same way as CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(Op)
|
||||
// -------------------------------------------------------------------------
|
||||
// Operations with VecAD_reference<Base> and AD<Base> only
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const AD<Base>& x, const VecAD_reference<Base>& y)
|
||||
{ return pow(x, y.ADBase()); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const VecAD_reference<Base>& x, const VecAD_reference<Base>& y)
|
||||
{ return pow(x.ADBase(), y.ADBase()); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const VecAD_reference<Base>& x, const AD<Base>& y)
|
||||
{ return pow(x.ADBase(), y); }
|
||||
// -------------------------------------------------------------------------
|
||||
// Operations with Base
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const Base& x, const AD<Base>& y)
|
||||
{ return pow(AD<Base>(x), y); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const Base& x, const VecAD_reference<Base>& y)
|
||||
{ return pow(AD<Base>(x), y.ADBase()); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const AD<Base>& x, const Base& y)
|
||||
{ return pow(x, AD<Base>(y)); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const VecAD_reference<Base>& x, const Base& y)
|
||||
{ return pow(x.ADBase(), AD<Base>(y)); }
|
||||
// -------------------------------------------------------------------------
|
||||
// Operations with double
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const double& x, const AD<Base>& y)
|
||||
{ return pow(AD<Base>(x), y); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const double& x, const VecAD_reference<Base>& y)
|
||||
{ return pow(AD<Base>(x), y.ADBase()); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const AD<Base>& x, const double& y)
|
||||
{ return pow(x, AD<Base>(y)); }
|
||||
|
||||
template <class Base> AD<Base>
|
||||
pow(const VecAD_reference<Base>& x, const double& y)
|
||||
{ return pow(x.ADBase(), AD<Base>(y)); }
|
||||
// -------------------------------------------------------------------------
|
||||
// Special case to avoid ambuigity when Base is double
|
||||
|
||||
inline AD<double>
|
||||
pow(const double& x, const AD<double>& y)
|
||||
{ return pow(AD<double>(x), y); }
|
||||
|
||||
inline AD<double>
|
||||
pow(const double& x, const VecAD_reference<double>& y)
|
||||
{ return pow(AD<double>(x), y.ADBase()); }
|
||||
|
||||
inline AD<double>
|
||||
pow(const AD<double>& x, const double& y)
|
||||
{ return pow(x, AD<double>(y)); }
|
||||
|
||||
inline AD<double>
|
||||
pow(const VecAD_reference<double>& x, const double& y)
|
||||
{ return pow(x.ADBase(), AD<double>(y)); }
|
||||
|
||||
// =========================================================================
|
||||
// Fold operations for the cases where x is an int,
|
||||
// but let cppad/utility/pow_int.hpp handle the cases where y is an int.
|
||||
// -------------------------------------------------------------------------
|
||||
template <class Base> AD<Base> pow
|
||||
(const int& x, const VecAD_reference<Base>& y)
|
||||
{ return pow(AD<Base>(x), y.ADBase()); }
|
||||
|
||||
template <class Base> AD<Base> pow
|
||||
(const int& x, const AD<Base>& y)
|
||||
{ return pow(AD<Base>(x), y); }
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
# ifndef CPPAD_CORE_PRINT_FOR_HPP
|
||||
# define CPPAD_CORE_PRINT_FOR_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 PrintFor$$
|
||||
$spell
|
||||
pos
|
||||
var
|
||||
VecAD
|
||||
std
|
||||
cout
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
$section Printing AD Values During Forward Mode$$
|
||||
$mindex print text output debug$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.Forward(0, %x%)
|
||||
%$$
|
||||
$codei%PrintFor(%before%, %var%)
|
||||
%$$
|
||||
$codei%PrintFor(%pos%, %before%, %var%, %after%)
|
||||
%$$
|
||||
|
||||
$head Purpose$$
|
||||
The $cref/zero order forward/forward_zero/$$ mode command
|
||||
$codei%
|
||||
%f%.Forward(0, %x%)
|
||||
%$$
|
||||
assigns the
|
||||
$cref/independent variable/glossary/Tape/Independent Variable/$$ vector
|
||||
equal to $icode x$$.
|
||||
It then computes a value for all of the dependent variables in the
|
||||
$cref/operation sequence/glossary/Operation/Sequence/$$ corresponding
|
||||
to $icode f$$.
|
||||
Putting a $code PrintFor$$ in the operation sequence will
|
||||
cause the value of $icode var$$, corresponding to $icode x$$,
|
||||
to be printed during zero order forward operations.
|
||||
|
||||
$head f.Forward(0, x)$$
|
||||
The objects $icode f$$, $icode x$$, and the purpose
|
||||
for this operation, are documented in $cref Forward$$.
|
||||
|
||||
$head pos$$
|
||||
If present, the argument $icode pos$$ has one of the following prototypes
|
||||
$codei%
|
||||
const AD<%Base%>& %pos%
|
||||
const VecAD<%Base%>::reference& %pos%
|
||||
%$$
|
||||
In this case
|
||||
the text and $icode var$$ will be printed if and only if
|
||||
$icode pos$$ is not greater than zero and a finite number.
|
||||
|
||||
$head before$$
|
||||
The argument $icode before$$ has prototype
|
||||
$codei%
|
||||
const char* %before%
|
||||
%$$
|
||||
This text is written to $code std::cout$$ before $icode var$$.
|
||||
|
||||
$head var$$
|
||||
The argument $icode var$$ has one of the following prototypes
|
||||
$codei%
|
||||
const AD<%Base%>& %var%
|
||||
const VecAD<%Base%>::reference& %var%
|
||||
%$$
|
||||
The value of $icode var$$, that corresponds to $icode x$$,
|
||||
is written to $code std::cout$$ during the execution of
|
||||
$codei%
|
||||
%f%.Forward(0, %x%)
|
||||
%$$
|
||||
Note that $icode var$$ may be a
|
||||
$cref/variable/glossary/Variable/$$ or
|
||||
$cref/parameter/glossary/Parameter/$$.
|
||||
(A parameters value does not depend on the value of
|
||||
the independent variable vector $icode x$$.)
|
||||
|
||||
$head after$$
|
||||
The argument $icode after$$ has prototype
|
||||
$codei%
|
||||
const char* %after%
|
||||
%$$
|
||||
This text is written to $code std::cout$$ after $icode var$$.
|
||||
|
||||
$head Redirecting Output$$
|
||||
You can redirect this output to any standard output stream; see the
|
||||
$cref/s/forward_order/s/$$ in the forward mode documentation.
|
||||
|
||||
$head Discussion$$
|
||||
This is helpful for understanding why tape evaluations
|
||||
have trouble.
|
||||
For example, if one of the operations in $icode f$$ is
|
||||
$codei%log(%var%)%$$ and $icode%var% <= 0%$$,
|
||||
the corresponding result will be $cref nan$$.
|
||||
|
||||
$head Alternative$$
|
||||
The $cref ad_output$$ section describes the normal
|
||||
printing of values; i.e., printing when the corresponding
|
||||
code is executed.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/print_for/print_for.cpp%
|
||||
example/general/print_for.cpp
|
||||
%$$
|
||||
The program
|
||||
$cref print_for_cout.cpp$$
|
||||
is an example and test that prints to standard output.
|
||||
The output of this program
|
||||
states the conditions for passing and failing the test.
|
||||
The function
|
||||
$cref print_for_string.cpp$$
|
||||
is an example and test that prints to an standard string stream.
|
||||
This function automatically check for correct output.
|
||||
|
||||
$end
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
# include <cstring>
|
||||
|
||||
namespace CppAD {
|
||||
template <class Base>
|
||||
void PrintFor(const AD<Base>& pos,
|
||||
const char *before, const AD<Base>& var, const char* after)
|
||||
{ CPPAD_ASSERT_NARG_NRES(local::PriOp, 5, 0);
|
||||
|
||||
// check for case where we are not recording operations
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return;
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::strlen(before) <= 1000 ,
|
||||
"PrintFor: length of before is greater than 1000 characters"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
std::strlen(after) <= 1000 ,
|
||||
"PrintFor: length of after is greater than 1000 characters"
|
||||
);
|
||||
addr_t ind0, ind1, ind2, ind3, ind4;
|
||||
|
||||
// ind[0] = base 2 representation of the value [Var(pos), Var(var)]
|
||||
ind0 = 0;
|
||||
|
||||
// ind[1] = address for pos
|
||||
if( Parameter(pos) )
|
||||
ind1 = tape->Rec_.PutPar(pos.value_);
|
||||
else
|
||||
{ ind0 += 1;
|
||||
ind1 = pos.taddr_;
|
||||
}
|
||||
|
||||
// ind[2] = address of before
|
||||
ind2 = tape->Rec_.PutTxt(before);
|
||||
|
||||
// ind[3] = address for var
|
||||
if( Parameter(var) )
|
||||
ind3 = tape->Rec_.PutPar(var.value_);
|
||||
else
|
||||
{ ind0 += 2;
|
||||
ind3 = var.taddr_;
|
||||
}
|
||||
|
||||
// ind[4] = address of after
|
||||
ind4 = tape->Rec_.PutTxt(after);
|
||||
|
||||
// put the operator in the tape
|
||||
tape->Rec_.PutArg(ind0, ind1, ind2, ind3, ind4);
|
||||
tape->Rec_.PutOp(local::PriOp);
|
||||
}
|
||||
// Fold all other cases into the case above
|
||||
template <class Base>
|
||||
void PrintFor(const char* before, const AD<Base>& var)
|
||||
{ PrintFor(AD<Base>(0), before, var, "" ); }
|
||||
//
|
||||
template <class Base>
|
||||
void PrintFor(const char* before, const VecAD_reference<Base>& var)
|
||||
{ PrintFor(AD<Base>(0), before, var.ADBase(), "" ); }
|
||||
//
|
||||
template <class Base>
|
||||
void PrintFor(
|
||||
const VecAD_reference<Base>& pos ,
|
||||
const char *before ,
|
||||
const VecAD_reference<Base>& var ,
|
||||
const char *after )
|
||||
{ PrintFor(pos.ADBase(), before, var.ADBase(), after); }
|
||||
//
|
||||
template <class Base>
|
||||
void PrintFor(
|
||||
const VecAD_reference<Base>& pos ,
|
||||
const char *before ,
|
||||
const AD<Base>& var ,
|
||||
const char *after )
|
||||
{ PrintFor(pos.ADBase(), before, var, after); }
|
||||
//
|
||||
template <class Base>
|
||||
void PrintFor(
|
||||
const AD<Base>& pos ,
|
||||
const char *before ,
|
||||
const VecAD_reference<Base>& var ,
|
||||
const char *after )
|
||||
{ PrintFor(pos, before, var.ADBase(), after); }
|
||||
}
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,251 @@
|
||||
# ifndef CPPAD_CORE_REV_HES_SPARSITY_HPP
|
||||
# define CPPAD_CORE_REV_HES_SPARSITY_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 rev_hes_sparsity$$
|
||||
$spell
|
||||
Jacobian
|
||||
Hessian
|
||||
jac
|
||||
hes
|
||||
bool
|
||||
const
|
||||
rc
|
||||
cpp
|
||||
$$
|
||||
|
||||
$section Reverse Mode Hessian Sparsity Patterns$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.rev_hes_sparsity(
|
||||
%select_range%, %transpose%, %internal_bool%, %pattern_out%
|
||||
)%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to
|
||||
the operation sequence stored in $icode f$$.
|
||||
Fix $latex R \in \B{R}^{n \times \ell}$$, $latex s \in \B{R}^m$$
|
||||
and define the function
|
||||
$latex \[
|
||||
H(x) = ( s^\R{T} F )^{(2)} ( x ) R
|
||||
\] $$
|
||||
Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$
|
||||
and for the vector $latex s$$,
|
||||
$code rev_hes_sparsity$$ computes a sparsity pattern for $latex H(x)$$.
|
||||
|
||||
$head x$$
|
||||
Note that the sparsity pattern $latex H(x)$$ corresponds to the
|
||||
operation sequence stored in $icode f$$ and does not depend on
|
||||
the argument $icode x$$.
|
||||
|
||||
$head BoolVector$$
|
||||
The type $icode BoolVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code bool$$.
|
||||
|
||||
$head SizeVector$$
|
||||
The type $icode SizeVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head R$$
|
||||
The sparsity pattern for the matrix $latex R$$ is specified by
|
||||
$cref/pattern_in/for_jac_sparsity/pattern_in/$$ in the previous call
|
||||
$codei%
|
||||
%f%.for_jac_sparsity(
|
||||
%pattern_in%, %transpose%, %dependency%, %internal_bool%, %pattern_out%
|
||||
)%$$
|
||||
|
||||
$head select_range$$
|
||||
The argument $icode select_range$$ has prototype
|
||||
$codei%
|
||||
const %BoolVector%& %select_range%
|
||||
%$$
|
||||
It has size $latex m$$ and specifies which components of the vector
|
||||
$latex s$$ are non-zero; i.e., $icode%select_range%[%i%]%$$ is true
|
||||
if and only if $latex s_i$$ is possibly non-zero.
|
||||
|
||||
$head transpose$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
bool %transpose%
|
||||
%$$
|
||||
See $cref/pattern_out/rev_hes_sparsity/pattern_out/$$ below.
|
||||
|
||||
$head internal_bool$$
|
||||
If this is true, calculations are done with sets represented by a vector
|
||||
of boolean values. Otherwise, a vector of sets of integers is used.
|
||||
This must be the same as in the previous call to
|
||||
$icode%f%.for_jac_sparsity%$$.
|
||||
|
||||
$head pattern_out$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
sparse_rc<%SizeVector%>& %pattern_out%
|
||||
%$$
|
||||
This input value of $icode pattern_out$$ does not matter.
|
||||
If $icode transpose$$ it is false (true),
|
||||
upon return $icode pattern_out$$ is a sparsity pattern for
|
||||
$latex H(x)$$ ($latex H(x)^\R{T}$$).
|
||||
|
||||
$head Sparsity for Entire Hessian$$
|
||||
Suppose that $latex R$$ is the $latex n \times n$$ identity matrix.
|
||||
In this case, $icode pattern_out$$ is a sparsity pattern for
|
||||
$latex (s^\R{T} F) F^{(2)} ( x )$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/rev_hes_sparsity.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref rev_hes_sparsity.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/core/ad_fun.hpp>
|
||||
# include <cppad/local/sparse_internal.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
Reverse Hessian sparsity patterns.
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\tparam BoolVector
|
||||
is the simple vector with elements of type bool that is used for
|
||||
sparsity for the vector s.
|
||||
|
||||
\tparam SizeVector
|
||||
is the simple vector with elements of type size_t that is used for
|
||||
row, column index sparsity patterns.
|
||||
|
||||
\param select_range
|
||||
is a sparsity pattern for for s.
|
||||
|
||||
\param transpose
|
||||
Is the returned sparsity pattern transposed.
|
||||
|
||||
\param internal_bool
|
||||
If this is true, calculations are done with sets represented by a vector
|
||||
of boolean values. Otherwise, a vector of standard sets is used.
|
||||
|
||||
\param pattern_out
|
||||
The value of transpose is false (true),
|
||||
the return value is a sparsity pattern for H(x) ( H(x)^T ) where
|
||||
\f[
|
||||
H(x) = R * F^{(1)} (x)
|
||||
\f]
|
||||
Here F is the function corresponding to the operation sequence
|
||||
and x is any argument value.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class BoolVector, class SizeVector>
|
||||
void ADFun<Base>::rev_hes_sparsity(
|
||||
const BoolVector& select_range ,
|
||||
bool transpose ,
|
||||
bool internal_bool ,
|
||||
sparse_rc<SizeVector>& pattern_out )
|
||||
{ size_t n = Domain();
|
||||
size_t m = Range();
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t( select_range.size() ) == m,
|
||||
"rev_hes_sparsity: size of select_range is not equal to "
|
||||
"number of dependent variables"
|
||||
);
|
||||
//
|
||||
// vector that holds reverse Jacobian sparsity flag
|
||||
local::pod_vector<bool> rev_jac_pattern;
|
||||
rev_jac_pattern.extend(num_var_tape_);
|
||||
for(size_t i = 0; i < num_var_tape_; i++)
|
||||
rev_jac_pattern[i] = false;
|
||||
//
|
||||
// initialize rev_jac_pattern for dependent variables
|
||||
for(size_t i = 0; i < m; i++)
|
||||
rev_jac_pattern[ dep_taddr_[i] ] = select_range[i];
|
||||
//
|
||||
//
|
||||
if( internal_bool )
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
for_jac_sparse_pack_.n_set() > 0,
|
||||
"rev_hes_sparsity: previous call to for_jac_sparsity did not "
|
||||
"use bool for interanl sparsity patterns."
|
||||
);
|
||||
// column dimension of internal sparstiy pattern
|
||||
size_t ell = for_jac_sparse_pack_.end();
|
||||
//
|
||||
// allocate memory for bool sparsity calculation
|
||||
// (sparsity pattern is emtpy after a resize)
|
||||
local::sparse_pack internal_hes;
|
||||
internal_hes.resize(num_var_tape_, ell);
|
||||
//
|
||||
// compute the Hessian sparsity pattern
|
||||
local::RevHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_pack_,
|
||||
rev_jac_pattern.data(),
|
||||
internal_hes
|
||||
|
||||
);
|
||||
// get sparstiy pattern for independent variables
|
||||
local::get_internal_sparsity(
|
||||
transpose, ind_taddr_, internal_hes, pattern_out
|
||||
);
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
for_jac_sparse_set_.n_set() > 0,
|
||||
"rev_hes_sparsity: previous call to for_jac_sparsity did not "
|
||||
"use bool for interanl sparsity patterns."
|
||||
);
|
||||
// column dimension of internal sparstiy pattern
|
||||
size_t ell = for_jac_sparse_set_.end();
|
||||
//
|
||||
// allocate memory for bool sparsity calculation
|
||||
// (sparsity pattern is emtpy after a resize)
|
||||
local::sparse_list internal_hes;
|
||||
internal_hes.resize(num_var_tape_, ell);
|
||||
//
|
||||
// compute the Hessian sparsity pattern
|
||||
local::RevHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_set_,
|
||||
rev_jac_pattern.data(),
|
||||
internal_hes
|
||||
|
||||
);
|
||||
// get sparstiy pattern for independent variables
|
||||
local::get_internal_sparsity(
|
||||
transpose, ind_taddr_, internal_hes, pattern_out
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,251 @@
|
||||
# ifndef CPPAD_CORE_REV_JAC_SPARSITY_HPP
|
||||
# define CPPAD_CORE_REV_JAC_SPARSITY_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 rev_jac_sparsity$$
|
||||
$spell
|
||||
Jacobian
|
||||
jac
|
||||
bool
|
||||
const
|
||||
rc
|
||||
cpp
|
||||
$$
|
||||
|
||||
$section Reverse Mode Jacobian Sparsity Patterns$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%f%.rev_jac_sparsity(
|
||||
%pattern_in%, %transpose%, %dependency%, %internal_bool%, %pattern_out%
|
||||
)%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to
|
||||
the operation sequence stored in $icode f$$.
|
||||
Fix $latex R \in \B{R}^{\ell \times m}$$ and define the function
|
||||
$latex \[
|
||||
J(x) = R * F^{(1)} ( x )
|
||||
\] $$
|
||||
Given the $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$,
|
||||
$code rev_jac_sparsity$$ computes a sparsity pattern for $latex J(x)$$.
|
||||
|
||||
$head x$$
|
||||
Note that the sparsity pattern $latex J(x)$$ corresponds to the
|
||||
operation sequence stored in $icode f$$ and does not depend on
|
||||
the argument $icode x$$.
|
||||
(The operation sequence may contain
|
||||
$cref CondExp$$ and $cref VecAD$$ operations.)
|
||||
|
||||
$head SizeVector$$
|
||||
The type $icode SizeVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head pattern_in$$
|
||||
The argument $icode pattern_in$$ has prototype
|
||||
$codei%
|
||||
const sparse_rc<%SizeVector%>& %pattern_in%
|
||||
%$$
|
||||
see $cref sparse_rc$$.
|
||||
If $icode transpose$$ it is false (true),
|
||||
$icode pattern_in$$ is a sparsity pattern for $latex R$$ ($latex R^\R{T}$$).
|
||||
|
||||
$head transpose$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
bool %transpose%
|
||||
%$$
|
||||
See $cref/pattern_in/rev_jac_sparsity/pattern_in/$$ above and
|
||||
$cref/pattern_out/rev_jac_sparsity/pattern_out/$$ below.
|
||||
|
||||
$head dependency$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
bool %dependency%
|
||||
%$$
|
||||
see $cref/pattern_out/rev_jac_sparsity/pattern_out/$$ below.
|
||||
|
||||
$head internal_bool$$
|
||||
If this is true, calculations are done with sets represented by a vector
|
||||
of boolean values. Otherwise, a vector of sets of integers is used.
|
||||
|
||||
$head pattern_out$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
sparse_rc<%SizeVector%>& %pattern_out%
|
||||
%$$
|
||||
This input value of $icode pattern_out$$ does not matter.
|
||||
If $icode transpose$$ it is false (true),
|
||||
upon return $icode pattern_out$$ is a sparsity pattern for
|
||||
$latex J(x)$$ ($latex J(x)^\R{T}$$).
|
||||
If $icode dependency$$ is true, $icode pattern_out$$ is a
|
||||
$cref/dependency pattern/dependency.cpp/Dependency Pattern/$$
|
||||
instead of sparsity pattern.
|
||||
|
||||
$head Sparsity for Entire Jacobian$$
|
||||
Suppose that
|
||||
$latex R$$ is the $latex m \times m$$ identity matrix.
|
||||
In this case, $icode pattern_out$$ is a sparsity pattern for
|
||||
$latex F^{(1)} ( x )$$ ( $latex F^{(1)} (x)^\R{T}$$ )
|
||||
if $icode transpose$$ is false (true).
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/rev_jac_sparsity.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref rev_jac_sparsity.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/core/ad_fun.hpp>
|
||||
# include <cppad/local/sparse_internal.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
Reverse Jacobian sparsity patterns.
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\tparam SizeVector
|
||||
is the simple vector with elements of type size_t that is used for
|
||||
row, column index sparsity patterns.
|
||||
|
||||
\param pattern_in
|
||||
is the sparsity pattern for for R or R^T depending on transpose.
|
||||
|
||||
\param transpose
|
||||
Is the input and returned sparsity pattern transposed.
|
||||
|
||||
\param dependency
|
||||
Are the derivatives with respect to left and right of the expression below
|
||||
considered to be non-zero:
|
||||
\code
|
||||
CondExpRel(left, right, if_true, if_false)
|
||||
\endcode
|
||||
This is used by the optimizer to obtain the correct dependency relations.
|
||||
|
||||
\param internal_bool
|
||||
If this is true, calculations are done with sets represented by a vector
|
||||
of boolean values. Otherwise, a vector of standard sets is used.
|
||||
|
||||
\param pattern_out
|
||||
The value of transpose is false (true),
|
||||
the return value is a sparsity pattern for J(x) ( J(x)^T ) where
|
||||
\f[
|
||||
J(x) = R * F^{(1)} (x)
|
||||
\f]
|
||||
Here F is the function corresponding to the operation sequence
|
||||
and x is any argument value.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class SizeVector>
|
||||
void ADFun<Base>::rev_jac_sparsity(
|
||||
const sparse_rc<SizeVector>& pattern_in ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
bool internal_bool ,
|
||||
sparse_rc<SizeVector>& pattern_out )
|
||||
{ // number or rows, columns, and non-zeros in pattern_in
|
||||
size_t nr_in = pattern_in.nr();
|
||||
size_t nc_in = pattern_in.nc();
|
||||
//
|
||||
size_t ell = nr_in;
|
||||
size_t m = nc_in;
|
||||
if( transpose )
|
||||
std::swap(ell, m);
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
m == Range() ,
|
||||
"rev_jac_sparsity: number columns in R "
|
||||
"is not equal number of dependent variables."
|
||||
);
|
||||
// number of independent variables
|
||||
size_t n = Domain();
|
||||
//
|
||||
bool zero_empty = true;
|
||||
bool input_empty = true;
|
||||
if( internal_bool )
|
||||
{ // allocate memory for bool sparsity calculation
|
||||
// (sparsity pattern is emtpy after a resize)
|
||||
local::sparse_pack internal_jac;
|
||||
internal_jac.resize(num_var_tape_, ell);
|
||||
//
|
||||
// set sparsity patttern for dependent variables
|
||||
local::set_internal_sparsity(
|
||||
zero_empty ,
|
||||
input_empty ,
|
||||
! transpose ,
|
||||
dep_taddr_ ,
|
||||
internal_jac ,
|
||||
pattern_in
|
||||
);
|
||||
|
||||
// compute sparsity for other variables
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
internal_jac
|
||||
);
|
||||
// get sparstiy pattern for independent variables
|
||||
local::get_internal_sparsity(
|
||||
! transpose, ind_taddr_, internal_jac, pattern_out
|
||||
);
|
||||
}
|
||||
else
|
||||
{ // allocate memory for bool sparsity calculation
|
||||
// (sparsity pattern is emtpy after a resize)
|
||||
local::sparse_list internal_jac;
|
||||
internal_jac.resize(num_var_tape_, ell);
|
||||
//
|
||||
// set sparsity patttern for dependent variables
|
||||
local::set_internal_sparsity(
|
||||
zero_empty ,
|
||||
input_empty ,
|
||||
! transpose ,
|
||||
dep_taddr_ ,
|
||||
internal_jac ,
|
||||
pattern_in
|
||||
);
|
||||
|
||||
// compute sparsity for other variables
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
internal_jac
|
||||
);
|
||||
// get sparstiy pattern for independent variables
|
||||
local::get_internal_sparsity(
|
||||
! transpose, ind_taddr_, internal_jac, pattern_out
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
# ifndef CPPAD_CORE_REV_ONE_HPP
|
||||
# define CPPAD_CORE_REV_ONE_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 RevOne$$
|
||||
$spell
|
||||
dw
|
||||
Taylor
|
||||
const
|
||||
$$
|
||||
|
||||
|
||||
|
||||
|
||||
$section First Order Derivative: Driver Routine$$
|
||||
$mindex derivative easy$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%dw% = %f%.RevOne(%x%, %i%)%$$
|
||||
|
||||
|
||||
$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 $icode dw$$ to the
|
||||
derivative of $latex F_i$$ with respect to $latex x$$; i.e.,
|
||||
$latex \[
|
||||
dw =
|
||||
F_i^{(1)} (x)
|
||||
= \left[
|
||||
\D{ F_i }{ x_0 } (x) , \cdots , \D{ F_i }{ x_{n-1} } (x)
|
||||
\right]
|
||||
\] $$
|
||||
|
||||
$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/RevOne Uses Forward/RevOne/RevOne Uses Forward/$$ below).
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Vector% &%x%
|
||||
%$$
|
||||
(see $cref/Vector/RevOne/Vector/$$ 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 derivative.
|
||||
|
||||
$head i$$
|
||||
The index $icode i$$ has prototype
|
||||
$codei%
|
||||
size_t %i%
|
||||
%$$
|
||||
and is less than $latex m$$, the dimension of the
|
||||
$cref/range/seq_property/Range/$$ space for $icode f$$.
|
||||
It specifies the
|
||||
component of $latex F$$ that we are computing the derivative of.
|
||||
|
||||
$head dw$$
|
||||
The result $icode dw$$ has prototype
|
||||
$codei%
|
||||
%Vector% %dw%
|
||||
%$$
|
||||
(see $cref/Vector/RevOne/Vector/$$ below)
|
||||
and its size is $icode n$$, the dimension of the
|
||||
$cref/domain/seq_property/Domain/$$ space for $icode f$$.
|
||||
The value of $icode dw$$ is the derivative of $latex F_i$$
|
||||
evaluated at $icode x$$; i.e.,
|
||||
for $latex j = 0 , \ldots , n - 1 $$
|
||||
$latex \[.
|
||||
dw[ j ] = \D{ F_i }{ x_j } ( x )
|
||||
\] $$
|
||||
|
||||
$head Vector$$
|
||||
The type $icode Vector$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$icode Base$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head RevOne 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 RevOne$$,
|
||||
the zero order Taylor coefficients correspond to
|
||||
$icode%f%.Forward(0, %x%)%$$
|
||||
and the other coefficients are unspecified.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/rev_one.cpp
|
||||
%$$
|
||||
The routine
|
||||
$cref/RevOne/rev_one.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 Vector>
|
||||
Vector ADFun<Base>::RevOne(const Vector &x, size_t i)
|
||||
{ size_t i1;
|
||||
|
||||
size_t n = Domain();
|
||||
size_t m = Range();
|
||||
|
||||
// check Vector is Simple Vector class with Base type elements
|
||||
CheckSimpleVector<Base, Vector>();
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
x.size() == n,
|
||||
"RevOne: Length of x not equal domain dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
i < m,
|
||||
"RevOne: the index i is not less than range dimension for f"
|
||||
);
|
||||
|
||||
// point at which we are evaluating the derivative
|
||||
Forward(0, x);
|
||||
|
||||
// component which are are taking the derivative of
|
||||
Vector w(m);
|
||||
for(i1 = 0; i1 < m; i1++)
|
||||
w[i1] = 0.;
|
||||
w[i] = Base(1.0);
|
||||
|
||||
// dimension the return value
|
||||
Vector dw(n);
|
||||
|
||||
// compute the return value
|
||||
dw = Reverse(1, w);
|
||||
|
||||
return dw;
|
||||
}
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,621 @@
|
||||
# ifndef CPPAD_CORE_REV_SPARSE_HES_HPP
|
||||
# define CPPAD_CORE_REV_SPARSE_HES_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 RevSparseHes$$
|
||||
$spell
|
||||
std
|
||||
VecAD
|
||||
Jacobian
|
||||
Jac
|
||||
Hessian
|
||||
Hes
|
||||
const
|
||||
Bool
|
||||
Dep
|
||||
proportional
|
||||
var
|
||||
cpp
|
||||
$$
|
||||
|
||||
$section Hessian Sparsity Pattern: Reverse Mode$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%h% = %f%.RevSparseHes(%q%, %s%)
|
||||
%$$
|
||||
$icode%h% = %f%.RevSparseHes(%q%, %s%, %transpose%)%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$.
|
||||
For a fixed matrix $latex R \in \B{R}^{n \times q}$$
|
||||
and a fixed vector $latex S \in \B{R}^{1 \times m}$$,
|
||||
we define
|
||||
$latex \[
|
||||
\begin{array}{rcl}
|
||||
H(x)
|
||||
& = & \partial_x \left[ \partial_u S * F[ x + R * u ] \right]_{u=0}
|
||||
\\
|
||||
& = & R^\R{T} * (S * F)^{(2)} ( x )
|
||||
\\
|
||||
H(x)^\R{T}
|
||||
& = & (S * F)^{(2)} ( x ) * R
|
||||
\end{array}
|
||||
\] $$
|
||||
Given a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex R$$ and the vector $latex S$$,
|
||||
$code RevSparseHes$$ returns a sparsity pattern for the $latex H(x)$$.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
const ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head x$$
|
||||
If the operation sequence in $icode f$$ is
|
||||
$cref/independent/glossary/Operation/Independent/$$ of
|
||||
the independent variables in $latex x \in B^n$$,
|
||||
the sparsity pattern is valid for all values of
|
||||
(even if it has $cref CondExp$$ or $cref VecAD$$ operations).
|
||||
|
||||
$head q$$
|
||||
The argument $icode q$$ has prototype
|
||||
$codei%
|
||||
size_t %q%
|
||||
%$$
|
||||
It specifies the number of columns in $latex R \in \B{R}^{n \times q}$$
|
||||
and the number of rows in $latex H(x) \in \B{R}^{q \times n}$$.
|
||||
It must be the same value as in the previous $cref ForSparseJac$$ call
|
||||
$codei%
|
||||
%f%.ForSparseJac(%q%, %r%, %r_transpose%)
|
||||
%$$
|
||||
Note that if $icode r_transpose$$ is true, $icode r$$ in the call above
|
||||
corresponding to $latex R^\R{T} \in \B{R}^{q \times n}$$
|
||||
|
||||
$head transpose$$
|
||||
The argument $icode transpose$$ has prototype
|
||||
$codei%
|
||||
bool %transpose%
|
||||
%$$
|
||||
The default value $code false$$ is used when $icode transpose$$ is not present.
|
||||
|
||||
|
||||
$head r$$
|
||||
The matrix $latex R$$ is specified by the previous call
|
||||
$codei%
|
||||
%f%.ForSparseJac(%q%, %r%, %transpose%)
|
||||
%$$
|
||||
see $cref/r/ForSparseJac/r/$$.
|
||||
The type of the elements of
|
||||
$cref/VectorSet/RevSparseHes/VectorSet/$$ must be the
|
||||
same as the type of the elements of $icode r$$.
|
||||
|
||||
$head s$$
|
||||
The argument $icode s$$ has prototype
|
||||
$codei%
|
||||
const %VectorSet%& %s%
|
||||
%$$
|
||||
(see $cref/VectorSet/RevSparseHes/VectorSet/$$ below)
|
||||
If it has elements of type $code bool$$,
|
||||
its size is $latex m$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is one and all the elements of $icode%s%[0]%$$
|
||||
are between zero and $latex m - 1$$.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the vector $icode S$$.
|
||||
|
||||
$head h$$
|
||||
The result $icode h$$ has prototype
|
||||
$codei%
|
||||
%VectorSet%& %h%
|
||||
%$$
|
||||
(see $cref/VectorSet/RevSparseHes/VectorSet/$$ below).
|
||||
|
||||
$subhead transpose false$$
|
||||
If $icode h$$ has elements of type $code bool$$,
|
||||
its size is $latex q * n$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $latex q$$ and all the set elements are between
|
||||
zero and $icode%n%-1%$$ inclusive.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex H(x)$$.
|
||||
|
||||
$subhead transpose true$$
|
||||
If $icode h$$ has elements of type $code bool$$,
|
||||
its size is $latex n * q$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $latex n$$ and all the set elements are between
|
||||
zero and $icode%q%-1%$$ inclusive.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex H(x)^\R{T}$$.
|
||||
|
||||
$head VectorSet$$
|
||||
The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code bool$$ or $code std::set<size_t>$$;
|
||||
see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion
|
||||
of the difference.
|
||||
The type of the elements of
|
||||
$cref/VectorSet/RevSparseHes/VectorSet/$$ must be the
|
||||
same as the type of the elements of $icode r$$.
|
||||
|
||||
$head Entire Sparsity Pattern$$
|
||||
Suppose that $latex q = n$$ and
|
||||
$latex R \in \B{R}^{n \times n}$$ is the $latex n \times n$$ identity matrix.
|
||||
Further suppose that the $latex S$$ is the $th k$$
|
||||
$cref/elementary vector/glossary/Elementary Vector/$$; i.e.
|
||||
$latex \[
|
||||
S_j = \left\{ \begin{array}{ll}
|
||||
1 & {\rm if} \; j = k
|
||||
\\
|
||||
0 & {\rm otherwise}
|
||||
\end{array} \right.
|
||||
\] $$
|
||||
In this case,
|
||||
the corresponding value $icode h$$ is a
|
||||
sparsity pattern for the Hessian matrix
|
||||
$latex F_k^{(2)} (x) \in \B{R}^{n \times n}$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/rev_sparse_hes.cpp
|
||||
%example/sparse/sparsity_sub.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref rev_sparse_hes.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
The file
|
||||
$cref/sparsity_sub.cpp/sparsity_sub.cpp/RevSparseHes/$$
|
||||
contains an example and test of using $code RevSparseHes$$
|
||||
to compute the sparsity pattern for a subset of the Hessian.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <algorithm>
|
||||
# include <cppad/local/pod_vector.hpp>
|
||||
# include <cppad/local/std_set.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file rev_sparse_hes.hpp
|
||||
Reverse mode Hessian sparsity patterns.
|
||||
*/
|
||||
// ===========================================================================
|
||||
// RevSparseHesCase
|
||||
/*!
|
||||
Private helper function for RevSparseHes(q, s) bool sparsity.
|
||||
|
||||
All of the description in the public member function RevSparseHes(q, s)
|
||||
applies.
|
||||
|
||||
\param set_type
|
||||
is a \c bool value. This argument is used to dispatch to the proper source
|
||||
code depending on the vlaue of \c VectorSet::value_type.
|
||||
|
||||
\param transpose
|
||||
See \c RevSparseHes(q, s).
|
||||
|
||||
\param q
|
||||
See \c RevSparseHes(q, s).
|
||||
|
||||
\param s
|
||||
See \c RevSparseHes(q, s).
|
||||
|
||||
\param h
|
||||
is the return value for the corresponging call to \c RevSparseJac(q, s).
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
void ADFun<Base>::RevSparseHesCase(
|
||||
bool set_type ,
|
||||
bool transpose ,
|
||||
size_t q ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& h )
|
||||
{ size_t n = Domain();
|
||||
size_t m = Range();
|
||||
//
|
||||
h.resize(q * n );
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
for_jac_sparse_pack_.n_set() > 0,
|
||||
"RevSparseHes: previous stored call to ForSparseJac did not "
|
||||
"use bool for the elements of r."
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == num_var_tape_ );
|
||||
//
|
||||
// temporary indices
|
||||
size_t i, j;
|
||||
|
||||
// check Vector is Simple VectorSet class with bool elements
|
||||
CheckSimpleVector<bool, VectorSet>();
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q == for_jac_sparse_pack_.end(),
|
||||
"RevSparseHes: q is not equal to its value\n"
|
||||
"in the previous call to ForSparseJac with this ADFun object."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(s.size()) == m,
|
||||
"RevSparseHes: size of s is not equal to\n"
|
||||
"range dimension for ADFun object."
|
||||
);
|
||||
|
||||
// Array that will hold reverse Jacobian dependency flag.
|
||||
// Initialize as true for the dependent variables.
|
||||
local::pod_vector<bool> RevJac;
|
||||
RevJac.extend(num_var_tape_);
|
||||
for(i = 0; i < num_var_tape_; i++)
|
||||
RevJac[i] = false;
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
RevJac[ dep_taddr_[i] ] = s[i];
|
||||
}
|
||||
|
||||
// vector of sets that will hold reverse Hessain values
|
||||
local::sparse_pack rev_hes_pattern;
|
||||
rev_hes_pattern.resize(num_var_tape_, q);
|
||||
|
||||
// compute the Hessian sparsity patterns
|
||||
local::RevHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_pack_,
|
||||
RevJac.data(),
|
||||
rev_hes_pattern
|
||||
);
|
||||
|
||||
// return values corresponding to independent variables
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == n * q );
|
||||
for(j = 0; j < n; j++)
|
||||
{ for(i = 0; i < q; i++)
|
||||
{ if( transpose )
|
||||
h[ j * q + i ] = false;
|
||||
else h[ i * n + j ] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// j is index corresponding to reverse mode partial
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );
|
||||
|
||||
// ind_taddr_[j] is operator taddr for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
// extract the result from rev_hes_pattern
|
||||
CPPAD_ASSERT_UNKNOWN( rev_hes_pattern.end() == q );
|
||||
local::sparse_pack::const_iterator itr(rev_hes_pattern, j + 1);
|
||||
i = *itr;
|
||||
while( i < q )
|
||||
{ if( transpose )
|
||||
h[ j * q + i ] = true;
|
||||
else h[ i * n + j ] = true;
|
||||
i = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!
|
||||
Private helper function for RevSparseHes(q, s) set sparsity.
|
||||
|
||||
All of the description in the public member function RevSparseHes(q, s)
|
||||
applies.
|
||||
|
||||
\param set_type
|
||||
is a \c std::set<size_t> value.
|
||||
This argument is used to dispatch to the proper source
|
||||
code depending on the vlaue of \c VectorSet::value_type.
|
||||
|
||||
\param transpose
|
||||
See \c RevSparseHes(q, s).
|
||||
|
||||
\param q
|
||||
See \c RevSparseHes(q, s).
|
||||
|
||||
\param s
|
||||
See \c RevSparseHes(q, s).
|
||||
|
||||
\param h
|
||||
is the return value for the corresponging call to \c RevSparseJac(q, s).
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
void ADFun<Base>::RevSparseHesCase(
|
||||
const std::set<size_t>& set_type ,
|
||||
bool transpose ,
|
||||
size_t q ,
|
||||
const VectorSet& s ,
|
||||
VectorSet& h )
|
||||
{ size_t n = Domain();
|
||||
# ifndef NDEBUG
|
||||
size_t m = Range();
|
||||
# endif
|
||||
//
|
||||
if( transpose )
|
||||
h.resize(n);
|
||||
else h.resize(q);
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
for_jac_sparse_set_.n_set() > 0,
|
||||
"RevSparseHes: previous stored call to ForSparseJac did not "
|
||||
"use std::set<size_t> for the elements of r."
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == num_var_tape_ );
|
||||
//
|
||||
// temporary indices
|
||||
size_t i, j;
|
||||
std::set<size_t>::const_iterator itr_1;
|
||||
|
||||
// check VectorSet is Simple Vector class with sets for elements
|
||||
CheckSimpleVector<std::set<size_t>, VectorSet>(
|
||||
local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>()
|
||||
);
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q == for_jac_sparse_set_.end(),
|
||||
"RevSparseHes: q is not equal to its value\n"
|
||||
"in the previous call to ForSparseJac with this ADFun object."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
s.size() == 1,
|
||||
"RevSparseHes: size of s is not equal to one."
|
||||
);
|
||||
|
||||
// Array that will hold reverse Jacobian dependency flag.
|
||||
// Initialize as true for the dependent variables.
|
||||
local::pod_vector<bool> RevJac;
|
||||
RevJac.extend(num_var_tape_);
|
||||
for(i = 0; i < num_var_tape_; i++)
|
||||
RevJac[i] = false;
|
||||
itr_1 = s[0].begin();
|
||||
while( itr_1 != s[0].end() )
|
||||
{ i = *itr_1++;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
i < m,
|
||||
"RevSparseHes: an element of the set s[0] has value "
|
||||
"greater than or equal m"
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
RevJac[ dep_taddr_[i] ] = true;
|
||||
}
|
||||
|
||||
|
||||
// vector of sets that will hold reverse Hessain values
|
||||
local::sparse_list rev_hes_pattern;
|
||||
rev_hes_pattern.resize(num_var_tape_, q);
|
||||
|
||||
// compute the Hessian sparsity patterns
|
||||
local::RevHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_set_,
|
||||
RevJac.data(),
|
||||
rev_hes_pattern
|
||||
);
|
||||
|
||||
// return values corresponding to independent variables
|
||||
// j is index corresponding to reverse mode partial
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == q || transpose );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(h.size()) == n || ! transpose );
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );
|
||||
CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
// extract the result from rev_hes_pattern
|
||||
// and add corresponding elements to result sets in h
|
||||
CPPAD_ASSERT_UNKNOWN( rev_hes_pattern.end() == q );
|
||||
local::sparse_list::const_iterator itr_2(rev_hes_pattern, j+1);
|
||||
i = *itr_2;
|
||||
while( i < q )
|
||||
{ if( transpose )
|
||||
h[j].insert(i);
|
||||
else h[i].insert(j);
|
||||
i = *(++itr_2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// RevSparseHes
|
||||
|
||||
/*!
|
||||
User API for Hessian sparsity patterns using reverse mode.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
h = f.RevSparseHes(q, r)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\tparam VectorSet
|
||||
is a simple vector with elements of type \c bool
|
||||
or \c std::set<size_t>.
|
||||
|
||||
\param transpose
|
||||
is true (false) if \c is is equal to \f$ H(x) \f$ (\f$ H(x)^T \f$)
|
||||
where
|
||||
\f[
|
||||
H(x) = R^T (S * F)^{(2)} (x)
|
||||
\f]
|
||||
where \f$ F \f$ is the function corresponding to the operation sequence
|
||||
and \a x is any argument value.
|
||||
|
||||
\param q
|
||||
is the value of \a q in the
|
||||
by the previous call of the form
|
||||
\verbatim
|
||||
f.ForSparseJac(q, r, packed)
|
||||
\endverbatim
|
||||
The value \c r in this call is a sparsity pattern for the matrix \f$ R \f$.
|
||||
The type of the element of \c r for the previous call to \c ForSparseJac
|
||||
must be the same as the type of the elements of \c s.
|
||||
|
||||
\param s
|
||||
is a vector with size \c m that specifies the sparsity pattern
|
||||
for the vector \f$ S \f$,
|
||||
where \c m is the number of dependent variables
|
||||
corresponding to the operation sequence stored in \a play.
|
||||
|
||||
\return
|
||||
If \c transpose is false (true),
|
||||
the return vector is a sparsity pattern for \f$ H(x) \f$ (\f$ H(x)^T \f$).
|
||||
\f[
|
||||
H(x) = R^T ( S * F)^{(2)} (x)
|
||||
\f]
|
||||
where \f$ F \f$ is the function corresponding to the operation sequence
|
||||
and \a x is any argument value.
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
VectorSet ADFun<Base>::RevSparseHes(
|
||||
size_t q, const VectorSet& s, bool transpose
|
||||
)
|
||||
{ VectorSet h;
|
||||
typedef typename VectorSet::value_type Set_type;
|
||||
|
||||
// Should check to make sure q is same as in previous call to
|
||||
// forward sparse Jacobian.
|
||||
RevSparseHesCase(
|
||||
Set_type() ,
|
||||
transpose ,
|
||||
q ,
|
||||
s ,
|
||||
h
|
||||
);
|
||||
|
||||
return h;
|
||||
}
|
||||
// ===========================================================================
|
||||
// RevSparseHesCheckpoint
|
||||
/*!
|
||||
Hessian sparsity patterns calculation used by checkpoint functions.
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\param transpose
|
||||
is true (false) h is equal to \f$ H(x) \f$ (\f$ H(x)^T \f$)
|
||||
where
|
||||
\f[
|
||||
H(x) = R^T (S * F)^{(2)} (x)
|
||||
\f]
|
||||
where \f$ F \f$ is the function corresponding to the operation sequence
|
||||
and \f$ x \f$ is any argument value.
|
||||
|
||||
\param q
|
||||
is the value of q in the by the previous call of the form
|
||||
\verbatim
|
||||
f.ForSparseJac(q, r)
|
||||
\endverbatim
|
||||
The value r in this call is a sparsity pattern for the matrix \f$ R \f$.
|
||||
|
||||
\param s
|
||||
is a vector with size m that specifies the sparsity pattern
|
||||
for the vector \f$ S \f$,
|
||||
where m is the number of dependent variables
|
||||
corresponding to the operation sequence stored in play_.
|
||||
|
||||
\param h
|
||||
The input size and elements of h do not matter.
|
||||
On output, h is the sparsity pattern for the matrix \f$ H(x) \f$
|
||||
or \f$ H(x)^T \f$ depending on transpose.
|
||||
|
||||
\par Assumptions
|
||||
The forward jacobian sparsity pattern must be currently stored
|
||||
in this ADFUN object.
|
||||
*/
|
||||
template <class Base>
|
||||
void ADFun<Base>::RevSparseHesCheckpoint(
|
||||
size_t q ,
|
||||
vector<bool>& s ,
|
||||
bool transpose ,
|
||||
local::sparse_list& h )
|
||||
{ size_t n = Domain();
|
||||
size_t m = Range();
|
||||
|
||||
// checkpoint functions should get this right
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.n_set() == 0 );
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.n_set() == num_var_tape_ );
|
||||
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_set_.end() == q );
|
||||
CPPAD_ASSERT_UNKNOWN( s.size() == m );
|
||||
|
||||
// Array that holds the reverse Jacobiain dependcy flags.
|
||||
// Initialize as true for dependent variables, flase for others.
|
||||
local::pod_vector<bool> RevJac;
|
||||
RevJac.extend(num_var_tape_);
|
||||
for(size_t i = 0; i < num_var_tape_; i++)
|
||||
RevJac[i] = false;
|
||||
for(size_t i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ )
|
||||
RevJac[ dep_taddr_[i] ] = s[i];
|
||||
}
|
||||
|
||||
// holds reverse Hessian sparsity pattern for all variables
|
||||
local::sparse_list rev_hes_pattern;
|
||||
rev_hes_pattern.resize(num_var_tape_, q);
|
||||
|
||||
// compute Hessian sparsity pattern for all variables
|
||||
local::RevHesSweep(
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
for_jac_sparse_set_,
|
||||
RevJac.data(),
|
||||
rev_hes_pattern
|
||||
);
|
||||
|
||||
// dimension the return value
|
||||
if( transpose )
|
||||
h.resize(n, q);
|
||||
else
|
||||
h.resize(q, n);
|
||||
|
||||
// j is index corresponding to reverse mode partial
|
||||
for(size_t j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );
|
||||
|
||||
// ind_taddr_[j] is operator taddr for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
// extract the result from rev_hes_pattern
|
||||
CPPAD_ASSERT_UNKNOWN( rev_hes_pattern.end() == q );
|
||||
local::sparse_list::const_iterator itr(rev_hes_pattern, j + 1);
|
||||
size_t i = *itr;
|
||||
while( i < q )
|
||||
{ if( transpose )
|
||||
h.add_element(j, i);
|
||||
else h.add_element(i, j);
|
||||
i = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
@@ -0,0 +1,626 @@
|
||||
# ifndef CPPAD_CORE_REV_SPARSE_JAC_HPP
|
||||
# define CPPAD_CORE_REV_SPARSE_JAC_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 RevSparseJac$$
|
||||
$spell
|
||||
optimizer
|
||||
nz
|
||||
CondExpRel
|
||||
std
|
||||
VecAD
|
||||
var
|
||||
Jacobian
|
||||
Jac
|
||||
const
|
||||
Bool
|
||||
Dep
|
||||
proportional
|
||||
$$
|
||||
|
||||
$section Jacobian Sparsity Pattern: Reverse Mode$$
|
||||
$mindex RevSparseJac sparse$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%s% = %f%.RevSparseJac(%q%, %r%)
|
||||
%$$
|
||||
$icode%s% = %f%.RevSparseJac(%q%, %r%, %transpose%, %dependency%)%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : B^n \rightarrow B^m$$ to denote the
|
||||
$cref/AD function/glossary/AD Function/$$ corresponding to $icode f$$.
|
||||
For a fixed matrix $latex R \in B^{q \times m}$$,
|
||||
the Jacobian of $latex R * F( x )$$
|
||||
with respect to $latex x$$ is
|
||||
$latex \[
|
||||
S(x) = R * F^{(1)} ( x )
|
||||
\] $$
|
||||
Given a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for $latex R$$,
|
||||
$code RevSparseJac$$ returns a sparsity pattern for the $latex S(x)$$.
|
||||
|
||||
$head f$$
|
||||
The object $icode f$$ has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
|
||||
$head x$$
|
||||
If the operation sequence in $icode f$$ is
|
||||
$cref/independent/glossary/Operation/Independent/$$ of
|
||||
the independent variables in $latex x \in B^n$$,
|
||||
the sparsity pattern is valid for all values of
|
||||
(even if it has $cref CondExp$$ or $cref VecAD$$ operations).
|
||||
|
||||
$head q$$
|
||||
The argument $icode q$$ has prototype
|
||||
$codei%
|
||||
size_t %q%
|
||||
%$$
|
||||
It specifies the number of rows in
|
||||
$latex R \in B^{q \times m}$$ and the
|
||||
Jacobian $latex S(x) \in B^{q \times n}$$.
|
||||
|
||||
$head transpose$$
|
||||
The argument $icode transpose$$ has prototype
|
||||
$codei%
|
||||
bool %transpose%
|
||||
%$$
|
||||
The default value $code false$$ is used when $icode transpose$$ is not present.
|
||||
|
||||
$head dependency$$
|
||||
The argument $icode dependency$$ has prototype
|
||||
$codei%
|
||||
bool %dependency%
|
||||
%$$
|
||||
If $icode dependency$$ is true,
|
||||
the $cref/dependency pattern/dependency.cpp/Dependency Pattern/$$
|
||||
(instead of sparsity pattern) is computed.
|
||||
|
||||
$head r$$
|
||||
The argument $icode s$$ has prototype
|
||||
$codei%
|
||||
const %VectorSet%& %r%
|
||||
%$$
|
||||
see $cref/VectorSet/RevSparseJac/VectorSet/$$ below.
|
||||
|
||||
$subhead transpose false$$
|
||||
If $icode r$$ has elements of type $code bool$$,
|
||||
its size is $latex q * m$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $icode q$$ and all its set elements are between
|
||||
zero and $latex m - 1$$.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex R \in B^{q \times m}$$.
|
||||
|
||||
$subhead transpose true$$
|
||||
If $icode r$$ has elements of type $code bool$$,
|
||||
its size is $latex m * q$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $icode m$$ and all its set elements are between
|
||||
zero and $latex q - 1$$.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex R^\R{T} \in B^{m \times q}$$.
|
||||
|
||||
$head s$$
|
||||
The return value $icode s$$ has prototype
|
||||
$codei%
|
||||
%VectorSet% %s%
|
||||
%$$
|
||||
see $cref/VectorSet/RevSparseJac/VectorSet/$$ below.
|
||||
|
||||
$subhead transpose false$$
|
||||
If it has elements of type $code bool$$,
|
||||
its size is $latex q * n$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $icode q$$ and all its set elements are between
|
||||
zero and $latex n - 1$$.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex S(x) \in {q \times n}$$.
|
||||
|
||||
$subhead transpose true$$
|
||||
If it has elements of type $code bool$$,
|
||||
its size is $latex n * q$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $icode n$$ and all its set elements are between
|
||||
zero and $latex q - 1$$.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the matrix $latex S(x)^\R{T} \in {n \times q}$$.
|
||||
|
||||
$head VectorSet$$
|
||||
The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code bool$$ or $code std::set<size_t>$$;
|
||||
see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion
|
||||
of the difference.
|
||||
|
||||
$head Entire Sparsity Pattern$$
|
||||
Suppose that $latex q = m$$ and
|
||||
$latex R$$ is the $latex m \times m$$ identity matrix.
|
||||
In this case,
|
||||
the corresponding value for $icode s$$ is a
|
||||
sparsity pattern for the Jacobian $latex S(x) = F^{(1)} ( x )$$.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/rev_sparse_jac.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref rev_sparse_jac.cpp$$
|
||||
contains an example and test of this operation.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
# include <cppad/local/std_set.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file rev_sparse_jac.hpp
|
||||
Reverse mode Jacobian sparsity patterns.
|
||||
*/
|
||||
// =========================================================================
|
||||
// RevSparseJacCase
|
||||
|
||||
/*!
|
||||
Private helper function for RevSparseJac(q, r, transpose) boolean sparsity.
|
||||
|
||||
All of the description in the public member function
|
||||
\c RevSparseJac(q, r, transpose) apply.
|
||||
|
||||
\param set_type
|
||||
is a \c bool value.
|
||||
This argument is used to dispatch to the proper source code
|
||||
depending on the value of \c VectorSet::value_type.
|
||||
|
||||
\param transpose
|
||||
See \c RevSparseJac(q, r, transpose, dependency)
|
||||
|
||||
\param dependency
|
||||
See \c RevSparseJac(q, r, transpose, dependency)
|
||||
|
||||
\param q
|
||||
See \c RevSparseJac(q, r, transpose, dependency)
|
||||
|
||||
\param r
|
||||
See \c RevSparseJac(q, r, transpose, dependency)
|
||||
|
||||
\param s
|
||||
is the return value for the corresponding call to
|
||||
RevSparseJac(q, r, transpose).
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
void ADFun<Base>::RevSparseJacCase(
|
||||
bool set_type ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
size_t q ,
|
||||
const VectorSet& r ,
|
||||
VectorSet& s )
|
||||
{ size_t n = Domain();
|
||||
size_t m = Range();
|
||||
|
||||
// dimension of the result vector
|
||||
s.resize( q * n );
|
||||
|
||||
// temporary indices
|
||||
size_t i, j;
|
||||
|
||||
// check VectorSet is Simple Vector class with bool elements
|
||||
CheckSimpleVector<bool, VectorSet>();
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q > 0,
|
||||
"RevSparseJac: q is not greater than zero"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(r.size()) == q * m,
|
||||
"RevSparseJac: size of r is not equal to\n"
|
||||
"q times range dimension for ADFun object."
|
||||
);
|
||||
//
|
||||
// vector of sets that will hold the results
|
||||
local::sparse_pack var_sparsity;
|
||||
var_sparsity.resize(num_var_tape_, q);
|
||||
|
||||
// The sparsity pattern corresponding to the dependent variables
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
if( transpose )
|
||||
{ for(j = 0; j < q; j++) if( r[ i * q + j ] )
|
||||
var_sparsity.add_element( dep_taddr_[i], j );
|
||||
}
|
||||
else
|
||||
{ for(j = 0; j < q; j++) if( r[ j * m + i ] )
|
||||
var_sparsity.add_element( dep_taddr_[i], j );
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate the sparsity patterns
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
var_sparsity
|
||||
);
|
||||
|
||||
// return values corresponding to dependent variables
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q * n );
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );
|
||||
|
||||
// ind_taddr_[j] is operator taddr for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
// extract the result from var_sparsity
|
||||
if( transpose )
|
||||
{ for(i = 0; i < q; i++)
|
||||
s[ j * q + i ] = false;
|
||||
}
|
||||
else
|
||||
{ for(i = 0; i < q; i++)
|
||||
s[ i * n + j ] = false;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( var_sparsity.end() == q );
|
||||
local::sparse_pack::const_iterator itr(var_sparsity, j+1);
|
||||
i = *itr;
|
||||
while( i < q )
|
||||
{ if( transpose )
|
||||
s[ j * q + i ] = true;
|
||||
else s[ i * n + j ] = true;
|
||||
i = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Private helper function for RevSparseJac(q, r, transpose) set sparsity
|
||||
|
||||
All of the description in the public member function
|
||||
\c RevSparseJac(q, r, transpose) apply.
|
||||
|
||||
\param set_type
|
||||
is a \c std::set<size_t> object.
|
||||
This argument is used to dispatch to the proper source code
|
||||
depending on the value of \c VectorSet::value_type.
|
||||
|
||||
\param transpose
|
||||
See \c RevSparseJac(q, r, transpose, dependency)
|
||||
|
||||
\param dependency
|
||||
See \c RevSparseJac(q, r, transpose, dependency)
|
||||
|
||||
\param q
|
||||
See \c RevSparseJac(q, r, transpose, dependency)
|
||||
|
||||
\param r
|
||||
See \c RevSparseJac(q, r, transpose, dependency)
|
||||
|
||||
\param s
|
||||
is the return value for the corresponding call to RevSparseJac(q, r, transpose)
|
||||
*/
|
||||
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
void ADFun<Base>::RevSparseJacCase(
|
||||
const std::set<size_t>& set_type ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
size_t q ,
|
||||
const VectorSet& r ,
|
||||
VectorSet& s )
|
||||
{ // dimension of the result vector
|
||||
if( transpose )
|
||||
s.resize( Domain() );
|
||||
else s.resize( q );
|
||||
|
||||
// temporary indices
|
||||
size_t i, j;
|
||||
std::set<size_t>::const_iterator itr_1;
|
||||
|
||||
// check VectorSet is Simple Vector class with sets for elements
|
||||
CheckSimpleVector<std::set<size_t>, VectorSet>(
|
||||
local::one_element_std_set<size_t>(), local::two_element_std_set<size_t>()
|
||||
);
|
||||
|
||||
// domain dimensions for F
|
||||
size_t n = ind_taddr_.size();
|
||||
size_t m = dep_taddr_.size();
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q > 0,
|
||||
"RevSparseJac: q is not greater than zero"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(r.size()) == q || transpose,
|
||||
"RevSparseJac: size of r is not equal to q and transpose is false."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(r.size()) == m || ! transpose,
|
||||
"RevSparseJac: size of r is not equal to m and transpose is true."
|
||||
);
|
||||
|
||||
// vector of lists that will hold the results
|
||||
local::sparse_list var_sparsity;
|
||||
var_sparsity.resize(num_var_tape_, q);
|
||||
|
||||
// The sparsity pattern corresponding to the dependent variables
|
||||
if( transpose )
|
||||
{ for(i = 0; i < m; i++)
|
||||
{ itr_1 = r[i].begin();
|
||||
while(itr_1 != r[i].end())
|
||||
{ j = *itr_1++;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
j < q,
|
||||
"RevSparseJac: transpose is true and element of the set\n"
|
||||
"r[i] has value greater than or equal q."
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
var_sparsity.add_element( dep_taddr_[i], j );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ for(i = 0; i < q; i++)
|
||||
{ itr_1 = r[i].begin();
|
||||
while(itr_1 != r[i].end())
|
||||
{ j = *itr_1++;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
j < m,
|
||||
"RevSparseJac: transpose is false and element of the set\n"
|
||||
"r[i] has value greater than or equal range dimension."
|
||||
);
|
||||
CPPAD_ASSERT_UNKNOWN( dep_taddr_[j] < num_var_tape_ );
|
||||
var_sparsity.add_element( dep_taddr_[j], i );
|
||||
}
|
||||
}
|
||||
}
|
||||
// evaluate the sparsity patterns
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
var_sparsity
|
||||
);
|
||||
|
||||
// return values corresponding to dependent variables
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == q || transpose );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == n || ! transpose );
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );
|
||||
|
||||
// ind_taddr_[j] is operator taddr for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( var_sparsity.end() == q );
|
||||
local::sparse_list::const_iterator itr_2(var_sparsity, j+1);
|
||||
i = *itr_2;
|
||||
while( i < q )
|
||||
{ if( transpose )
|
||||
s[j].insert(i);
|
||||
else s[i].insert(j);
|
||||
i = *(++itr_2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// RevSparseJac
|
||||
/*!
|
||||
User API for Jacobian sparsity patterns using reverse mode.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
s = f.RevSparseJac(q, r, transpose, dependency)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\tparam VectorSet
|
||||
is a simple vector with elements of type \c bool.
|
||||
or \c std::set<size_t>.
|
||||
|
||||
\param q
|
||||
is the number of rows in the matrix \f$ R \f$.
|
||||
|
||||
\param r
|
||||
is a sparsity pattern for the matrix \f$ R \f$.
|
||||
|
||||
\param transpose
|
||||
are the sparsity patterns for \f$ R \f$ and \f$ S(x) \f$ transposed.
|
||||
|
||||
\param dependency
|
||||
Are the derivatives with respect to left and right of the expression below
|
||||
considered to be non-zero:
|
||||
\code
|
||||
CondExpRel(left, right, if_true, if_false)
|
||||
\endcode
|
||||
This is used by the optimizer to obtain the correct dependency relations.
|
||||
|
||||
|
||||
\return
|
||||
If \c transpose is false (true), the return value is a sparsity pattern
|
||||
for \f$ S(x) \f$ (\f$ S(x)^T \f$) where
|
||||
\f[
|
||||
S(x) = R * F^{(1)} (x)
|
||||
\f]
|
||||
and \f$ F \f$ is the function corresponding to the operation sequence
|
||||
and \a x is any argument value.
|
||||
If \c VectorSet::value_type is \c bool,
|
||||
the return value has size \f$ q * n \f$ ( \f$ n * q \f$).
|
||||
If \c VectorSet::value_type is \c std::set<size_t>,
|
||||
the return value has size \f$ q \f$ ( \f$ n \f$)
|
||||
and with all its elements between zero and \f$ n - 1 \f$ (\f$ q - 1 \f$).
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorSet>
|
||||
VectorSet ADFun<Base>::RevSparseJac(
|
||||
size_t q ,
|
||||
const VectorSet& r ,
|
||||
bool transpose ,
|
||||
bool dependency )
|
||||
{
|
||||
VectorSet s;
|
||||
typedef typename VectorSet::value_type Set_type;
|
||||
|
||||
RevSparseJacCase(
|
||||
Set_type() ,
|
||||
transpose ,
|
||||
dependency ,
|
||||
q ,
|
||||
r ,
|
||||
s
|
||||
);
|
||||
return s;
|
||||
}
|
||||
// ===========================================================================
|
||||
// RevSparseJacCheckpoint
|
||||
/*!
|
||||
Reverse mode Jacobian sparsity calculation used by checkpoint functions.
|
||||
|
||||
\tparam Base
|
||||
is the base type for this recording.
|
||||
|
||||
\param transpose
|
||||
is true (false) s is equal to \f$ S(x) \f$ (\f$ S(x)^T \f$)
|
||||
where
|
||||
\f[
|
||||
S(x) = R * F^{(1)} (x)
|
||||
\f]
|
||||
where \f$ F \f$ is the function corresponding to the operation sequence
|
||||
and \f$ x \f$ is any argument value.
|
||||
|
||||
\param q
|
||||
is the number of rows in the matrix \f$ R \f$.
|
||||
|
||||
\param r
|
||||
is a sparsity pattern for the matrix \f$ R \f$.
|
||||
|
||||
\param transpose
|
||||
are the sparsity patterns for \f$ R \f$ and \f$ S(x) \f$ transposed.
|
||||
|
||||
\param dependency
|
||||
Are the derivatives with respect to left and right of the expression below
|
||||
considered to be non-zero:
|
||||
\code
|
||||
CondExpRel(left, right, if_true, if_false)
|
||||
\endcode
|
||||
This is used by the optimizer to obtain the correct dependency relations.
|
||||
|
||||
\param s
|
||||
The input size and elements of s do not matter.
|
||||
On output, s is the sparsity pattern for the matrix \f$ S(x) \f$
|
||||
or \f$ S(x)^T \f$ depending on transpose.
|
||||
|
||||
*/
|
||||
template <class Base>
|
||||
void ADFun<Base>::RevSparseJacCheckpoint(
|
||||
size_t q ,
|
||||
const local::sparse_list& r ,
|
||||
bool transpose ,
|
||||
bool dependency ,
|
||||
local::sparse_list& s )
|
||||
{ size_t n = Domain();
|
||||
size_t m = Range();
|
||||
|
||||
# ifndef NDEBUG
|
||||
if( transpose )
|
||||
{ CPPAD_ASSERT_UNKNOWN( r.n_set() == m );
|
||||
CPPAD_ASSERT_UNKNOWN( r.end() == q );
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( r.n_set() == q );
|
||||
CPPAD_ASSERT_UNKNOWN( r.end() == m );
|
||||
}
|
||||
for(size_t i = 0; i < m; i++)
|
||||
CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
# endif
|
||||
|
||||
// holds reverse Jacobian sparsity pattern for all variables
|
||||
local::sparse_list var_sparsity;
|
||||
var_sparsity.resize(num_var_tape_, q);
|
||||
|
||||
// set sparsity pattern for dependent variables
|
||||
if( transpose )
|
||||
{ for(size_t i = 0; i < m; i++)
|
||||
{ local::sparse_list::const_iterator itr(r, i);
|
||||
size_t j = *itr;
|
||||
while( j < q )
|
||||
{ var_sparsity.add_element( dep_taddr_[i], j );
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ for(size_t j = 0; j < q; j++)
|
||||
{ local::sparse_list::const_iterator itr(r, j);
|
||||
size_t i = *itr;
|
||||
while( i < m )
|
||||
{ var_sparsity.add_element( dep_taddr_[i], j );
|
||||
i = *(++itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate the sparsity pattern for all variables
|
||||
local::RevJacSweep(
|
||||
dependency,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
var_sparsity
|
||||
);
|
||||
|
||||
// dimension the return value
|
||||
if( transpose )
|
||||
s.resize(n, m);
|
||||
else
|
||||
s.resize(m, n);
|
||||
|
||||
// return values corresponding to independent variables
|
||||
for(size_t j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == (j+1) );
|
||||
|
||||
// ind_taddr_[j] is operator taddr for j-th independent variable
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
// extract the result from var_sparsity
|
||||
CPPAD_ASSERT_UNKNOWN( var_sparsity.end() == q );
|
||||
local::sparse_list::const_iterator itr(var_sparsity, j+1);
|
||||
size_t i = *itr;
|
||||
while( i < q )
|
||||
{ if( transpose )
|
||||
s.add_element(j, i);
|
||||
else
|
||||
s.add_element(i, j);
|
||||
i = *(++itr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
# 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
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_REVERSE_HPP
|
||||
# define CPPAD_CORE_REVERSE_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <algorithm>
|
||||
# include <cppad/local/pod_vector.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file reverse.hpp
|
||||
Compute derivatives using reverse mode.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
Use reverse mode to compute derivative of forward mode Taylor coefficients.
|
||||
|
||||
The function
|
||||
\f$ X : {\rm R} \times {\rm R}^{n \times q} \rightarrow {\rm R} \f$
|
||||
is defined by
|
||||
\f[
|
||||
X(t , u) = \sum_{k=0}^{q-1} u^{(k)} t^k
|
||||
\f]
|
||||
The function
|
||||
\f$ Y : {\rm R} \times {\rm R}^{n \times q} \rightarrow {\rm R} \f$
|
||||
is defined by
|
||||
\f[
|
||||
Y(t , u) = F[ X(t, u) ]
|
||||
\f]
|
||||
The function
|
||||
\f$ W : {\rm R}^{n \times q} \rightarrow {\rm R} \f$ is defined by
|
||||
\f[
|
||||
W(u) = \sum_{k=0}^{q-1} ( w^{(k)} )^{\rm T}
|
||||
\frac{1}{k !} \frac{ \partial^k } { t^k } Y(0, u)
|
||||
\f]
|
||||
|
||||
\tparam Base
|
||||
base type for the operator; i.e., this operation sequence was recorded
|
||||
using AD< \a Base > and computations by this routine are done using type
|
||||
\a Base.
|
||||
|
||||
\tparam VectorBase
|
||||
is a Simple Vector class with elements of type \a Base.
|
||||
|
||||
\param q
|
||||
is the number of the number of Taylor coefficients that are being
|
||||
differentiated (per variable).
|
||||
|
||||
\param w
|
||||
is the weighting for each of the Taylor coefficients corresponding
|
||||
to dependent variables.
|
||||
If the argument \a w has size <tt>m * q </tt>,
|
||||
for \f$ k = 0 , \ldots , q-1 \f$ and \f$ i = 0, \ldots , m-1 \f$,
|
||||
\f[
|
||||
w_i^{(k)} = w [ i * q + k ]
|
||||
\f]
|
||||
If the argument \a w has size \c m ,
|
||||
for \f$ k = 0 , \ldots , q-1 \f$ and \f$ i = 0, \ldots , m-1 \f$,
|
||||
\f[
|
||||
w_i^{(k)} = \left\{ \begin{array}{ll}
|
||||
w [ i ] & {\rm if} \; k = q-1
|
||||
\\
|
||||
0 & {\rm otherwise}
|
||||
\end{array} \right.
|
||||
\f]
|
||||
|
||||
\return
|
||||
Is a vector \f$ dw \f$ such that
|
||||
for \f$ j = 0 , \ldots , n-1 \f$ and
|
||||
\f$ k = 0 , \ldots , q-1 \f$
|
||||
\f[
|
||||
dw[ j * q + k ] = W^{(1)} ( x )_{j,k}
|
||||
\f]
|
||||
where the matrix \f$ x \f$ is the value for \f$ u \f$
|
||||
that corresponding to the forward mode Taylor coefficients
|
||||
for the independent variables as specified by previous calls to Forward.
|
||||
|
||||
*/
|
||||
template <typename Base>
|
||||
template <typename VectorBase>
|
||||
VectorBase ADFun<Base>::Reverse(size_t q, const VectorBase &w)
|
||||
{ // constants
|
||||
const Base zero(0);
|
||||
|
||||
// temporary indices
|
||||
size_t i, j, k;
|
||||
|
||||
// number of independent variables
|
||||
size_t n = ind_taddr_.size();
|
||||
|
||||
// number of dependent variables
|
||||
size_t m = dep_taddr_.size();
|
||||
|
||||
local::pod_vector<Base> Partial;
|
||||
Partial.extend(num_var_tape_ * q);
|
||||
|
||||
// update maximum memory requirement
|
||||
// memoryMax = std::max( memoryMax,
|
||||
// Memory() + num_var_tape_ * q * sizeof(Base)
|
||||
// );
|
||||
|
||||
// check VectorBase is Simple Vector class with Base type elements
|
||||
CheckSimpleVector<Base, VectorBase>();
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(w.size()) == m || size_t(w.size()) == (m * q),
|
||||
"Argument w to Reverse does not have length equal to\n"
|
||||
"the dimension of the range for the corresponding ADFun."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
q > 0,
|
||||
"The first argument to Reverse must be greater than zero."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
num_order_taylor_ >= q,
|
||||
"Less that q taylor_ coefficients are currently stored"
|
||||
" in this ADFun object."
|
||||
);
|
||||
// special case where multiple forward directions have been computed,
|
||||
// but we are only using the one direction zero order results
|
||||
if( (q == 1) & (num_direction_taylor_ > 1) )
|
||||
{ num_order_taylor_ = 1; // number of orders to copy
|
||||
size_t c = cap_order_taylor_; // keep the same capacity setting
|
||||
size_t r = 1; // only keep one direction
|
||||
capacity_order(c, r);
|
||||
}
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
num_direction_taylor_ == 1,
|
||||
"Reverse mode for Forward(q, r, xq) with more than one direction"
|
||||
"\n(r > 1) is not yet supported for q > 1."
|
||||
);
|
||||
// initialize entire Partial matrix to zero
|
||||
for(i = 0; i < num_var_tape_; i++)
|
||||
for(j = 0; j < q; j++)
|
||||
Partial[i * q + j] = zero;
|
||||
|
||||
// set the dependent variable direction
|
||||
// (use += because two dependent variables can point to same location)
|
||||
for(i = 0; i < m; i++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( dep_taddr_[i] < num_var_tape_ );
|
||||
if( size_t(w.size()) == m )
|
||||
Partial[dep_taddr_[i] * q + q - 1] += w[i];
|
||||
else
|
||||
{ for(k = 0; k < q; k++)
|
||||
// ? should use += here, first make test to demonstrate bug
|
||||
Partial[ dep_taddr_[i] * q + k ] = w[i * q + k ];
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate the derivatives
|
||||
CPPAD_ASSERT_UNKNOWN( cskip_op_.size() == play_.num_op_rec() );
|
||||
CPPAD_ASSERT_UNKNOWN( load_op_.size() == play_.num_load_op_rec() );
|
||||
local::ReverseSweep(
|
||||
q - 1,
|
||||
n,
|
||||
num_var_tape_,
|
||||
&play_,
|
||||
cap_order_taylor_,
|
||||
taylor_.data(),
|
||||
q,
|
||||
Partial.data(),
|
||||
cskip_op_.data(),
|
||||
load_op_
|
||||
);
|
||||
|
||||
// return the derivative values
|
||||
VectorBase value(n * q);
|
||||
for(j = 0; j < n; j++)
|
||||
{ CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] < num_var_tape_ );
|
||||
|
||||
// independent variable taddr equals its operator taddr
|
||||
CPPAD_ASSERT_UNKNOWN( play_.GetOp( ind_taddr_[j] ) == local::InvOp );
|
||||
|
||||
// by the Reverse Identity Theorem
|
||||
// partial of y^{(k)} w.r.t. u^{(0)} is equal to
|
||||
// partial of y^{(q-1)} w.r.t. u^{(q - 1 - k)}
|
||||
if( size_t(w.size()) == m )
|
||||
{ for(k = 0; k < q; k++)
|
||||
value[j * q + k ] =
|
||||
Partial[ind_taddr_[j] * q + q - 1 - k];
|
||||
}
|
||||
else
|
||||
{ for(k = 0; k < q; k++)
|
||||
value[j * q + k ] =
|
||||
Partial[ind_taddr_[j] * q + k];
|
||||
}
|
||||
}
|
||||
CPPAD_ASSERT_KNOWN( ! ( hasnan(value) && check_for_nan_ ) ,
|
||||
"dw = f.Reverse(q, w): has a nan,\n"
|
||||
"but none of its Taylor coefficents are nan."
|
||||
);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
# ifndef CPPAD_CORE_SIGN_HPP
|
||||
# define CPPAD_CORE_SIGN_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 sign$$
|
||||
$spell
|
||||
CppAD
|
||||
Dirac
|
||||
$$
|
||||
$section The Sign: sign$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = sign(%x%)%$$
|
||||
|
||||
$head Description$$
|
||||
Evaluates the $code sign$$ function which is defined by
|
||||
$latex \[
|
||||
{\rm sign} (x) =
|
||||
\left\{ \begin{array}{rl}
|
||||
+1 & {\rm if} \; x > 0 \\
|
||||
0 & {\rm if} \; x = 0 \\
|
||||
-1 & {\rm if} \; x < 0
|
||||
\end{array} \right.
|
||||
\] $$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
CppAD computes the derivative of the $code sign$$ function as zero for all
|
||||
argument values $icode x$$.
|
||||
The correct mathematical derivative is different and
|
||||
is given by
|
||||
$latex \[
|
||||
{\rm sign}^{(1)} (x) = 2 \delta (x)
|
||||
\] $$
|
||||
where $latex \delta (x)$$ is the Dirac Delta function.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/sign.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref sign.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base> AD<Base>::sign_me (void) const
|
||||
{
|
||||
AD<Base> result;
|
||||
result.value_ = sign(value_);
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||
|
||||
if( Variable(*this) )
|
||||
{ // add this operation to the tape
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SignOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SignOp) == 1 );
|
||||
local::ADTape<Base> *tape = tape_this();
|
||||
|
||||
// corresponding operand address
|
||||
tape->Rec_.PutArg(taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::SignOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape->id_;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> sign(const AD<Base> &x)
|
||||
{ return x.sign_me(); }
|
||||
|
||||
template <class Base>
|
||||
inline AD<Base> sign(const VecAD_reference<Base> &x)
|
||||
{ return x.ADBase().sign_me(); }
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# ifndef CPPAD_CORE_SPARSE_HPP
|
||||
# define CPPAD_CORE_SPARSE_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.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
# include <cppad/core/for_jac_sparsity.hpp>
|
||||
# include <cppad/core/rev_jac_sparsity.hpp>
|
||||
# include <cppad/core/rev_hes_sparsity.hpp>
|
||||
# include <cppad/core/for_hes_sparsity.hpp>
|
||||
//
|
||||
# include <cppad/core/for_sparse_jac.hpp>
|
||||
# include <cppad/core/rev_sparse_jac.hpp>
|
||||
# include <cppad/core/rev_sparse_hes.hpp>
|
||||
# include <cppad/core/for_sparse_hes.hpp>
|
||||
//
|
||||
# include <cppad/core/sparse_jac.hpp>
|
||||
# include <cppad/core/sparse_hes.hpp>
|
||||
//
|
||||
# include <cppad/core/sparse_jacobian.hpp>
|
||||
# include <cppad/core/sparse_hessian.hpp>
|
||||
|
||||
# endif
|
||||
+540
@@ -0,0 +1,540 @@
|
||||
# ifndef CPPAD_CORE_SPARSE_HES_HPP
|
||||
# define CPPAD_CORE_SPARSE_HES_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 sparse_hes$$
|
||||
$spell
|
||||
const
|
||||
Taylor
|
||||
rc
|
||||
rcv
|
||||
nr
|
||||
nc
|
||||
hes
|
||||
std
|
||||
cppad
|
||||
colpack
|
||||
cmake
|
||||
Jacobian
|
||||
$$
|
||||
|
||||
$section Computing Sparse Hessians$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%n_sweep% = %f%.sparse_hes(
|
||||
%x%, %w%, %subset%, %pattern%, %coloring%, %work%
|
||||
)%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
|
||||
function corresponding to $icode f$$.
|
||||
Here $icode n$$ is the $cref/domain/seq_property/Domain/$$ size,
|
||||
and $icode m$$ is the $cref/range/seq_property/Range/$$ size, or $icode f$$.
|
||||
The syntax above takes advantage of sparsity when computing the Hessian
|
||||
$latex \[
|
||||
H(x) = \dpow{2}{x} \sum_{i=0}^{m-1} w_i F_i (x)
|
||||
\] $$
|
||||
In the sparse case, this should be faster and take less memory than
|
||||
$cref Hessian$$.
|
||||
The matrix element $latex H_{i,j} (x)$$ is the second partial of
|
||||
$latex w^\R{T} F (x)$$ with respect to $latex x_i$$ and $latex x_j$$.
|
||||
|
||||
$head SizeVector$$
|
||||
The type $icode SizeVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
|
||||
$head BaseVector$$
|
||||
The type $icode BaseVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
|
||||
$head f$$
|
||||
This object has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
Note that the Taylor coefficients stored in $icode f$$ are affected
|
||||
by this operation; see
|
||||
$cref/uses forward/sparse_hes/Uses Forward/$$ below.
|
||||
|
||||
$head x$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
const %BaseVector%& %x%
|
||||
%$$
|
||||
and its size is $icode n$$.
|
||||
It specifies the point at which to evaluate the Hessian
|
||||
$latex H(x)$$.
|
||||
|
||||
$head w$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
const %BaseVector%& %w%
|
||||
%$$
|
||||
and its size is $icode m$$.
|
||||
It specifies the weight for each of the components of $latex F(x)$$;
|
||||
i.e. $latex w_i$$ is the weight for $latex F_i (x)$$.
|
||||
|
||||
$head subset$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
sparse_rcv<%SizeVector%, %BaseVector%>& %subset%
|
||||
%$$
|
||||
Its row size and column size is $icode n$$; i.e.,
|
||||
$icode%subset%.nr() == %n%$$ and $icode%subset%.nc() == %n%$$.
|
||||
It specifies which elements of the Hessian are computed.
|
||||
$list number$$
|
||||
The input value of its value vector
|
||||
$icode%subset%.val()%$$ does not matter.
|
||||
Upon return it contains the value of the corresponding elements
|
||||
of the Hessian.
|
||||
$lnext
|
||||
All of the row, column pairs in $icode subset$$ must also appear in
|
||||
$icode pattern$$; i.e., they must be possibly non-zero.
|
||||
$lnext
|
||||
The Hessian is symmetric, so one has a choice as to which off diagonal
|
||||
elements to put in $icode subset$$.
|
||||
It will probably be more efficient if one makes this choice so that
|
||||
the there are more entries in each non-zero column of $icode subset$$;
|
||||
see $cref/n_sweep/sparse_hes/n_sweep/$$ below.
|
||||
$lend
|
||||
|
||||
$head pattern$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
const sparse_rc<%SizeVector%>& %pattern%
|
||||
%$$
|
||||
Its row size and column size is $icode n$$; i.e.,
|
||||
$icode%pattern%.nr() == %n%$$ and $icode%pattern%.nc() == %n%$$.
|
||||
It is a sparsity pattern for the Hessian $latex H(x)$$.
|
||||
If the $th i$$ row ($th j$$ column) does not appear in $icode subset$$,
|
||||
the $th i$$ row ($th j$$ column) of $icode pattern$$ does not matter
|
||||
and need not be computed.
|
||||
This argument is not used (and need not satisfy any conditions),
|
||||
when $cref/work/sparse_hes/work/$$ is non-empty.
|
||||
|
||||
$subhead subset$$
|
||||
If the $th i$$ row and $th i$$ column do not appear in $icode subset$$,
|
||||
the $th i$$ row and column of $icode pattern$$ do not matter.
|
||||
In this case the $th i-th$$ row and column may have no entries in
|
||||
$icode pattern$$ even though they are possibly non-zero in $latex H(x)$$.
|
||||
(This can be used to reduce the amount of computation required to find
|
||||
$icode pattern$$.)
|
||||
|
||||
$head coloring$$
|
||||
The coloring algorithm determines which rows and columns
|
||||
can be computed during the same sweep.
|
||||
This field has prototype
|
||||
$codei%
|
||||
const std::string& %coloring%
|
||||
%$$
|
||||
This value only matters when work is empty; i.e.,
|
||||
after the $icode work$$ constructor or $icode%work%.clear()%$$.
|
||||
|
||||
$subhead cppad.symmetric$$
|
||||
This coloring takes advantage of the fact that the Hessian matrix
|
||||
is symmetric when find a coloring that requires fewer
|
||||
$cref/sweeps/sparse_hes/n_sweep/$$.
|
||||
|
||||
$subhead cppad.general$$
|
||||
This is the same as the sparse Jacobian
|
||||
$cref/cppad/sparse_jac/coloring/cppad/$$ method
|
||||
which does not take advantage of symmetry.
|
||||
|
||||
$subhead colpack.symmetric$$
|
||||
If $cref colpack_prefix$$ was specified on the
|
||||
$cref/cmake command/cmake/CMake Command/$$ line,
|
||||
you can set $icode coloring$$ to $code colpack.symmetric$$.
|
||||
This also takes advantage of the fact that the Hessian matrix is symmetric.
|
||||
|
||||
$subhead colpack.general$$
|
||||
If $cref colpack_prefix$$ was specified on the
|
||||
$cref/cmake command/cmake/CMake Command/$$ line,
|
||||
you can set $icode coloring$$ to $code colpack.general$$.
|
||||
This is the same as the sparse Jacobian
|
||||
$cref/colpack/sparse_jac/coloring/colpack/$$ method
|
||||
which does not take advantage of symmetry.
|
||||
|
||||
$subhead colpack.star Deprecated 2017-06-01$$
|
||||
The $code colpack.star$$ method is deprecated.
|
||||
It is the same as the $code colpack.symmetric$$ method
|
||||
which should be used instead.
|
||||
|
||||
|
||||
$head work$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
sparse_hes_work& %work%
|
||||
%$$
|
||||
We refer to its initial value,
|
||||
and its value after $icode%work%.clear()%$$, as empty.
|
||||
If it is empty, information is stored in $icode work$$.
|
||||
This can be used to reduce computation when
|
||||
a future call is for the same object $icode f$$,
|
||||
and the same subset of the Hessian.
|
||||
If either of these values change, use $icode%work%.clear()%$$ to
|
||||
empty this structure.
|
||||
|
||||
$head n_sweep$$
|
||||
The return value $icode n_sweep$$ has prototype
|
||||
$codei%
|
||||
size_t %n_sweep%
|
||||
%$$
|
||||
It is the number of first order forward sweeps
|
||||
used to compute the requested Hessian values.
|
||||
Each first forward sweep is followed by a second order reverse sweep
|
||||
so it is also the number of reverse sweeps.
|
||||
It is also the number of colors determined by the coloring method
|
||||
mentioned above.
|
||||
This is proportional to the total computational work,
|
||||
not counting the zero order forward sweep,
|
||||
or combining multiple columns and rows into a single sweep.
|
||||
|
||||
$head 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 sparse_hes$$
|
||||
the zero order coefficients correspond to
|
||||
$codei%
|
||||
%f%.Forward(0, %x%)
|
||||
%$$
|
||||
All the other forward mode coefficients are unspecified.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/sparse_hes.cpp
|
||||
%$$
|
||||
The files $cref sparse_hes.cpp$$
|
||||
is an example and test of $code sparse_hes$$.
|
||||
It returns $code true$$, if it succeeds, and $code false$$ otherwise.
|
||||
|
||||
$head Subset Hessian$$
|
||||
The routine
|
||||
$cref sparse_sub_hes.cpp$$
|
||||
is an example and test that compute a subset of a sparse Hessian.
|
||||
It returns $code true$$, for success, and $code false$$ otherwise.
|
||||
|
||||
$end
|
||||
*/
|
||||
# include <cppad/core/cppad_assert.hpp>
|
||||
# include <cppad/local/sparse_internal.hpp>
|
||||
# include <cppad/local/color_general.hpp>
|
||||
# include <cppad/local/color_symmetric.hpp>
|
||||
|
||||
/*!
|
||||
\file sparse_hes.hpp
|
||||
Sparse Hessian calculation routines.
|
||||
*/
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
|
||||
/*!
|
||||
Class used to hold information used by Sparse Hessian routine in this file,
|
||||
so it does not need to be recomputed every time.
|
||||
*/
|
||||
class sparse_hes_work {
|
||||
public:
|
||||
/// row and column indicies for return values
|
||||
/// (some may be reflected by symmetric coloring algorithms)
|
||||
CppAD::vector<size_t> row;
|
||||
CppAD::vector<size_t> col;
|
||||
/// indices that sort the row and col arrays by color
|
||||
CppAD::vector<size_t> order;
|
||||
/// results of the coloring algorithm
|
||||
CppAD::vector<size_t> color;
|
||||
|
||||
/// constructor
|
||||
sparse_hes_work(void)
|
||||
{ }
|
||||
/// inform CppAD that this information needs to be recomputed
|
||||
void clear(void)
|
||||
{
|
||||
row.clear();
|
||||
col.clear();
|
||||
order.clear();
|
||||
color.clear();
|
||||
}
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
/*!
|
||||
Calculate sparse Hessians using forward mode
|
||||
|
||||
\tparam Base
|
||||
the base type for the recording that is stored in the ADFun object.
|
||||
|
||||
\tparam SizeVector
|
||||
a simple vector class with elements of type size_t.
|
||||
|
||||
\tparam BaseVector
|
||||
a simple vector class with elements of type Base.
|
||||
|
||||
\param x
|
||||
a vector of length n, the number of independent variables in f
|
||||
(this ADFun object).
|
||||
|
||||
\param w
|
||||
a vector of length m, the number of dependent variables in f
|
||||
(this ADFun object).
|
||||
|
||||
\param subset
|
||||
specifices the subset of the sparsity pattern where the Hessian is evaluated.
|
||||
subset.nr() == n,
|
||||
subset.nc() == n.
|
||||
|
||||
\param pattern
|
||||
is a sparsity pattern for the Hessian of w^T * f;
|
||||
pattern.nr() == n,
|
||||
pattern.nc() == n,
|
||||
where m is number of dependent variables in f.
|
||||
|
||||
\param coloring
|
||||
determines which coloring algorithm is used.
|
||||
This must be cppad.symmetric, cppad.general, colpack.symmetic,
|
||||
or colpack.star.
|
||||
|
||||
\param work
|
||||
this structure must be empty, or contain the information stored
|
||||
by a previous call to sparse_hes.
|
||||
The previous call must be for the same ADFun object f
|
||||
and the same subset.
|
||||
|
||||
\return
|
||||
This is the number of first order forward
|
||||
(and second order reverse) sweeps used to compute thhe Hessian.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class SizeVector, class BaseVector>
|
||||
size_t ADFun<Base>::sparse_hes(
|
||||
const BaseVector& x ,
|
||||
const BaseVector& w ,
|
||||
sparse_rcv<SizeVector , BaseVector>& subset ,
|
||||
const sparse_rc<SizeVector>& pattern ,
|
||||
const std::string& coloring ,
|
||||
sparse_hes_work& work )
|
||||
{ size_t n = Domain();
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
subset.nr() == n,
|
||||
"sparse_hes: subset.nr() not equal domain dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
subset.nc() == n,
|
||||
"sparse_hes: subset.nc() not equal domain dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t( x.size() ) == n,
|
||||
"sparse_hes: x.size() not equal domain dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t( w.size() ) == Range(),
|
||||
"sparse_hes: w.size() not equal range dimension for f"
|
||||
);
|
||||
//
|
||||
// work information
|
||||
vector<size_t>& row(work.row);
|
||||
vector<size_t>& col(work.col);
|
||||
vector<size_t>& color(work.color);
|
||||
vector<size_t>& order(work.order);
|
||||
//
|
||||
// subset information
|
||||
const SizeVector& subset_row( subset.row() );
|
||||
const SizeVector& subset_col( subset.col() );
|
||||
//
|
||||
// point at which we are evaluationg the Hessian
|
||||
Forward(0, x);
|
||||
//
|
||||
// number of elements in the subset
|
||||
size_t K = subset.nnz();
|
||||
//
|
||||
// check for case were there is nothing to do
|
||||
// (except for call to Forward(0, x)
|
||||
if( K == 0 )
|
||||
return 0;
|
||||
//
|
||||
# ifndef NDEBUG
|
||||
if( color.size() != 0 )
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
color.size() == n,
|
||||
"sparse_hes: work is non-empty and conditions have changed"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
row.size() == K,
|
||||
"sparse_hes: work is non-empty and conditions have changed"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
col.size() == K,
|
||||
"sparse_hes: work is non-empty and conditions have changed"
|
||||
);
|
||||
//
|
||||
for(size_t k = 0; k < K; k++)
|
||||
{ bool ok = row[k] == subset_row[k] && col[k] == subset_col[k];
|
||||
ok |= row[k] == subset_col[k] && col[k] == subset_row[k];
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
ok,
|
||||
"sparse_hes: work is non-empty and conditions have changed"
|
||||
);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
//
|
||||
// check for case where input work is empty
|
||||
if( color.size() == 0 )
|
||||
{ // compute work color and order vectors
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
pattern.nr() == n,
|
||||
"sparse_hes: pattern.nr() not equal domain dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
pattern.nc() == n,
|
||||
"sparse_hes: pattern.nc() not equal domain dimension for f"
|
||||
);
|
||||
//
|
||||
// initialize work row, col to be same as subset row, col
|
||||
row.resize(K);
|
||||
col.resize(K);
|
||||
// cannot assign vectors becasue may be of different types
|
||||
// (SizeVector and CppAD::vector<size_t>)
|
||||
for(size_t k = 0; k < K; k++)
|
||||
{ row[k] = subset_row[k];
|
||||
col[k] = subset_col[k];
|
||||
}
|
||||
//
|
||||
// convert pattern to an internal version of its transpose
|
||||
vector<size_t> internal_index(n);
|
||||
for(size_t j = 0; j < n; j++)
|
||||
internal_index[j] = j;
|
||||
bool transpose = true;
|
||||
bool zero_empty = false;
|
||||
bool input_empty = true;
|
||||
local::sparse_list internal_pattern;
|
||||
internal_pattern.resize(n, n);
|
||||
local::set_internal_sparsity(zero_empty, input_empty,
|
||||
transpose, internal_index, internal_pattern, pattern
|
||||
);
|
||||
//
|
||||
// execute coloring algorithm
|
||||
// (we are using transpose becasue coloring groups rows, not columns)
|
||||
color.resize(n);
|
||||
if( coloring == "cppad.general" )
|
||||
local::color_general_cppad(internal_pattern, col, row, color);
|
||||
else if( coloring == "cppad.symmetric" )
|
||||
local::color_symmetric_cppad(internal_pattern, col, row, color);
|
||||
else if( coloring == "colpack.general" )
|
||||
{
|
||||
# if CPPAD_HAS_COLPACK
|
||||
local::color_general_colpack(internal_pattern, col, row, color);
|
||||
# else
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"sparse_hes: coloring = colpack.star "
|
||||
"and colpack_prefix not in cmake command line."
|
||||
);
|
||||
# endif
|
||||
}
|
||||
else if(
|
||||
coloring == "colpack.symmetric" ||
|
||||
coloring == "colpack.star"
|
||||
)
|
||||
{
|
||||
# if CPPAD_HAS_COLPACK
|
||||
local::color_symmetric_colpack(internal_pattern, col, row, color);
|
||||
# else
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"sparse_hes: coloring = colpack.symmetic or colpack.star "
|
||||
"and colpack_prefix not in cmake command line."
|
||||
);
|
||||
# endif
|
||||
}
|
||||
else CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"sparse_hes: coloring is not valid."
|
||||
);
|
||||
//
|
||||
// put sorting indices in color order
|
||||
SizeVector key(K);
|
||||
order.resize(K);
|
||||
for(size_t k = 0; k < K; k++)
|
||||
key[k] = color[ col[k] ];
|
||||
index_sort(key, order);
|
||||
}
|
||||
// Base versions of zero and one
|
||||
Base one(1.0);
|
||||
Base zero(0.0);
|
||||
//
|
||||
size_t n_color = 1;
|
||||
for(size_t j = 0; j < n; j++) if( color[j] < n )
|
||||
n_color = std::max(n_color, color[j] + 1);
|
||||
//
|
||||
// initialize the return Hessian values as zero
|
||||
for(size_t k = 0; k < K; k++)
|
||||
subset.set(k, zero);
|
||||
//
|
||||
// direction vector for calls to first order forward
|
||||
BaseVector dx(n);
|
||||
//
|
||||
// return values for calls to second order reverse
|
||||
BaseVector ddw(2 * n);
|
||||
//
|
||||
// loop over colors
|
||||
size_t k = 0;
|
||||
for(size_t ell = 0; ell < n_color; ell++)
|
||||
if( k == K )
|
||||
{ // kludge because colpack returns colors that are not used
|
||||
// (it does not know about the subset corresponding to row, col)
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
coloring == "colpack.general" ||
|
||||
coloring == "colpack.symmetric" ||
|
||||
coloring == "colpack.star"
|
||||
);
|
||||
}
|
||||
else if( color[ col[ order[k] ] ] != ell )
|
||||
{ // kludge because colpack returns colors that are not used
|
||||
// (it does not know about the subset corresponding to row, col)
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
coloring == "colpack.general" ||
|
||||
coloring == "colpack.symmetic" ||
|
||||
coloring == "colpack.star"
|
||||
);
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( color[ col[ order[k] ] ] == ell );
|
||||
//
|
||||
// combine all columns with this color
|
||||
for(size_t j = 0; j < n; j++)
|
||||
{ dx[j] = zero;
|
||||
if( color[j] == ell )
|
||||
dx[j] = one;
|
||||
}
|
||||
// call forward mode for all these rows at once
|
||||
Forward(1, dx);
|
||||
//
|
||||
// evaluate derivative of w^T * F'(x) * dx
|
||||
ddw = Reverse(2, w);
|
||||
//
|
||||
// set the corresponding components of the result
|
||||
while( k < K && color[ col[order[k]] ] == ell )
|
||||
{ size_t index = row[ order[k] ] * 2 + 1;
|
||||
subset.set(order[k], ddw[index] );
|
||||
k++;
|
||||
}
|
||||
}
|
||||
// check that all the required entries have been set
|
||||
CPPAD_ASSERT_UNKNOWN( k == K );
|
||||
return n_color;
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
|
||||
# endif
|
||||
@@ -0,0 +1,861 @@
|
||||
# ifndef CPPAD_CORE_SPARSE_HESSIAN_HPP
|
||||
# define CPPAD_CORE_SPARSE_HESSIAN_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 sparse_hessian$$
|
||||
$spell
|
||||
jacobian
|
||||
recomputed
|
||||
CppAD
|
||||
valarray
|
||||
std
|
||||
Bool
|
||||
hes
|
||||
const
|
||||
Taylor
|
||||
cppad
|
||||
cmake
|
||||
colpack
|
||||
$$
|
||||
|
||||
$section Sparse Hessian$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%hes% = %f%.SparseHessian(%x%, %w%)
|
||||
%hes% = %f%.SparseHessian(%x%, %w%, %p%)
|
||||
%n_sweep% = %f%.SparseHessian(%x%, %w%, %p%, %row%, %col%, %hes%, %work%)
|
||||
%$$
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex n$$ for the $cref/domain/seq_property/Domain/$$ size,
|
||||
and $latex m$$ for the $cref/range/seq_property/Range/$$ size of $icode f$$.
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ do denote the
|
||||
$cref/AD function/glossary/AD Function/$$
|
||||
corresponding to $icode f$$.
|
||||
The syntax above sets $icode hes$$ to the Hessian
|
||||
$latex \[
|
||||
H(x) = \dpow{2}{x} \sum_{i=1}^m w_i F_i (x)
|
||||
\] $$
|
||||
This routine takes advantage of the sparsity of the Hessian
|
||||
in order to reduce the amount of computation necessary.
|
||||
If $icode row$$ and $icode col$$ are present, it also takes
|
||||
advantage of the reduced set of elements of the Hessian that
|
||||
need to be computed.
|
||||
One can use speed tests (e.g. $cref speed_test$$)
|
||||
to verify that results are computed faster
|
||||
than when using the routine $cref Hessian$$.
|
||||
|
||||
$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/Uses Forward/sparse_hessian/Uses Forward/$$ below).
|
||||
|
||||
$head x$$
|
||||
The argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %VectorBase%& %x%
|
||||
%$$
|
||||
(see $cref/VectorBase/sparse_hessian/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 Hessian.
|
||||
|
||||
$head w$$
|
||||
The argument $icode w$$ has prototype
|
||||
$codei%
|
||||
const %VectorBase%& %w%
|
||||
%$$
|
||||
and size $latex m$$.
|
||||
It specifies the value of $latex w_i$$ in the expression
|
||||
for $icode hes$$.
|
||||
The more components of $latex w$$ that are identically zero,
|
||||
the more sparse the resulting Hessian may be (and hence the more efficient
|
||||
the calculation of $icode hes$$ may be).
|
||||
|
||||
$head p$$
|
||||
The argument $icode p$$ is optional and has prototype
|
||||
$codei%
|
||||
const %VectorSet%& %p%
|
||||
%$$
|
||||
(see $cref/VectorSet/sparse_hessian/VectorSet/$$ below)
|
||||
If it has elements of type $code bool$$,
|
||||
its size is $latex n * n$$.
|
||||
If it has elements of type $code std::set<size_t>$$,
|
||||
its size is $latex n$$ and all its set elements are between
|
||||
zero and $latex n - 1$$.
|
||||
It specifies a
|
||||
$cref/sparsity pattern/glossary/Sparsity Pattern/$$
|
||||
for the Hessian $latex H(x)$$.
|
||||
|
||||
$subhead Purpose$$
|
||||
If this sparsity pattern does not change between calls to
|
||||
$codei SparseHessian$$, it should be faster to calculate $icode p$$ once and
|
||||
pass this argument to $codei SparseHessian$$.
|
||||
If you specify $icode p$$, CppAD will use the same
|
||||
type of sparsity representation
|
||||
(vectors of $code bool$$ or vectors of $code std::set<size_t>$$)
|
||||
for its internal calculations.
|
||||
Otherwise, the representation
|
||||
for the internal calculations is unspecified.
|
||||
|
||||
$subhead work$$
|
||||
If you specify $icode work$$ in the calling sequence,
|
||||
it is not necessary to keep the sparsity pattern; see the heading
|
||||
$cref/p/sparse_hessian/work/p/$$ under the $icode work$$ description.
|
||||
|
||||
$subhead Column Subset$$
|
||||
If the arguments $icode row$$ and $icode col$$ are present,
|
||||
and $cref/color_method/sparse_hessian/work/color_method/$$ is
|
||||
$code cppad.general$$ or $code cppad.symmetric$$,
|
||||
it is not necessary to compute the entire sparsity pattern.
|
||||
Only the following subset of column values will matter:
|
||||
$codei%
|
||||
{ %col%[%k%] : %k% = 0 , %...% , %K%-1 }
|
||||
%$$.
|
||||
|
||||
|
||||
$head row, col$$
|
||||
The arguments $icode row$$ and $icode col$$ are optional and have prototype
|
||||
$codei%
|
||||
const %VectorSize%& %row%
|
||||
const %VectorSize%& %col%
|
||||
%$$
|
||||
(see $cref/VectorSize/sparse_hessian/VectorSize/$$ below).
|
||||
They specify which rows and columns of $latex H (x)$$ are
|
||||
returned and in what order.
|
||||
We use $latex K$$ to denote the value $icode%hes%.size()%$$
|
||||
which must also equal the size of $icode row$$ and $icode col$$.
|
||||
Furthermore,
|
||||
for $latex k = 0 , \ldots , K-1$$, it must hold that
|
||||
$latex row[k] < n$$ and $latex col[k] < n$$.
|
||||
In addition,
|
||||
all of the $latex (row[k], col[k])$$ pairs must correspond to a true value
|
||||
in the sparsity pattern $icode p$$.
|
||||
|
||||
$head hes$$
|
||||
The result $icode hes$$ has prototype
|
||||
$codei%
|
||||
%VectorBase% %hes%
|
||||
%$$
|
||||
In the case where $icode row$$ and $icode col$$ are not present,
|
||||
the size of $icode hes$$ is $latex n * n$$ and
|
||||
its size is $latex n * n$$.
|
||||
In this case, for $latex i = 0 , \ldots , n - 1 $$
|
||||
and $latex ell = 0 , \ldots , n - 1$$
|
||||
$latex \[
|
||||
hes [ j * n + \ell ] = \DD{ w^{\rm T} F }{ x_j }{ x_\ell } ( x )
|
||||
\] $$
|
||||
$pre
|
||||
|
||||
$$
|
||||
In the case where the arguments $icode row$$ and $icode col$$ are present,
|
||||
we use $latex K$$ to denote the size of $icode hes$$.
|
||||
The input value of its elements does not matter.
|
||||
Upon return, for $latex k = 0 , \ldots , K - 1$$,
|
||||
$latex \[
|
||||
hes [ k ] = \DD{ w^{\rm T} F }{ x_j }{ x_\ell } (x)
|
||||
\; , \;
|
||||
\; {\rm where} \;
|
||||
j = row[k]
|
||||
\; {\rm and } \;
|
||||
\ell = col[k]
|
||||
\] $$
|
||||
|
||||
$head work$$
|
||||
If this argument is present, it has prototype
|
||||
$codei%
|
||||
sparse_hessian_work& %work%
|
||||
%$$
|
||||
This object can only be used with the routines $code SparseHessian$$.
|
||||
During its the first use, information is stored in $icode work$$.
|
||||
This is used to reduce the work done by future calls to $code SparseHessian$$
|
||||
with the same $icode f$$, $icode p$$, $icode row$$, and $icode col$$.
|
||||
If a future call is made where any of these values have changed,
|
||||
you must first call $icode%work%.clear()%$$
|
||||
to inform CppAD that this information needs to be recomputed.
|
||||
|
||||
$subhead color_method$$
|
||||
The coloring algorithm determines which rows and columns
|
||||
can be computed during the same sweep.
|
||||
This field has prototype
|
||||
$codei%
|
||||
std::string %work%.color_method
|
||||
%$$
|
||||
This value only matters on the first call to $code sparse_hessian$$ that
|
||||
follows the $icode work$$ constructor or a call to
|
||||
$icode%work%.clear()%$$.
|
||||
$codei%
|
||||
|
||||
"cppad.symmetric"
|
||||
%$$
|
||||
This is the default coloring method (after a constructor or $code clear()$$).
|
||||
It takes advantage of the fact that the Hessian matrix
|
||||
is symmetric to find a coloring that requires fewer
|
||||
$cref/sweeps/sparse_hessian/n_sweep/$$.
|
||||
$codei%
|
||||
|
||||
"cppad.general"
|
||||
%$$
|
||||
This is the same as the $code "cppad"$$ method for the
|
||||
$cref/sparse_jacobian/sparse_jacobian/work/color_method/$$ calculation.
|
||||
$codei%
|
||||
|
||||
"colpack.symmetric"
|
||||
%$$
|
||||
This method requires that
|
||||
$cref colpack_prefix$$ was specified on the
|
||||
$cref/cmake command/cmake/CMake Command/$$ line.
|
||||
It also takes advantage of the fact that the Hessian matrix is symmetric.
|
||||
$codei%
|
||||
|
||||
"colpack.general"
|
||||
%$$
|
||||
This is the same as the $code "colpack"$$ method for the
|
||||
$cref/sparse_jacobian/sparse_jacobian/work/color_method/$$ calculation.
|
||||
|
||||
$subhead colpack.star Deprecated 2017-06-01$$
|
||||
The $code colpack.star$$ method is deprecated.
|
||||
It is the same as the $code colpack.symmetric$$
|
||||
which should be used instead.
|
||||
|
||||
$subhead p$$
|
||||
If $icode work$$ is present, and it is not the first call after
|
||||
its construction or a clear,
|
||||
the sparsity pattern $icode p$$ is not used.
|
||||
This enables one to free the sparsity pattern
|
||||
and still compute corresponding sparse Hessians.
|
||||
|
||||
$head n_sweep$$
|
||||
The return value $icode n_sweep$$ has prototype
|
||||
$codei%
|
||||
size_t %n_sweep%
|
||||
%$$
|
||||
It is the number of first order forward sweeps
|
||||
used to compute the requested Hessian values.
|
||||
Each first forward sweep is followed by a second order reverse sweep
|
||||
so it is also the number of reverse sweeps.
|
||||
This is proportional to the total work that $code SparseHessian$$ does,
|
||||
not counting the zero order forward sweep,
|
||||
or the work to combine multiple columns into a single
|
||||
forward-reverse sweep pair.
|
||||
|
||||
$head VectorBase$$
|
||||
The type $icode VectorBase$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$icode Base$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head VectorSet$$
|
||||
The type $icode VectorSet$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code bool$$ or $code std::set<size_t>$$;
|
||||
see $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for a discussion
|
||||
of the difference.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$subhead Restrictions$$
|
||||
If $icode VectorSet$$ has elements of $code std::set<size_t>$$,
|
||||
then $icode%p%[%i%]%$$ must return a reference (not a copy) to the
|
||||
corresponding set.
|
||||
According to section 26.3.2.3 of the 1998 C++ standard,
|
||||
$code std::valarray< std::set<size_t> >$$ does not satisfy
|
||||
this condition.
|
||||
|
||||
$head VectorSize$$
|
||||
The type $icode VectorSize$$ must be a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
The routine $cref CheckSimpleVector$$ will generate an error message
|
||||
if this is not the case.
|
||||
|
||||
$head 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 any of the sparse Hessian routines,
|
||||
the zero order Taylor coefficients correspond to
|
||||
$icode%f%.Forward(0, %x%)%$$
|
||||
and the other coefficients are unspecified.
|
||||
|
||||
$children%
|
||||
example/sparse/sparse_hessian.cpp%
|
||||
example/sparse/sub_sparse_hes.cpp%
|
||||
example/sparse/sparse_sub_hes.cpp
|
||||
%$$
|
||||
|
||||
$head Example$$
|
||||
The routine
|
||||
$cref sparse_hessian.cpp$$
|
||||
is examples and tests of $code sparse_hessian$$.
|
||||
It return $code true$$, if it succeeds and $code false$$ otherwise.
|
||||
|
||||
$head Subset Hessian$$
|
||||
The routine
|
||||
$cref sub_sparse_hes.cpp$$
|
||||
is an example and test that compute a sparse Hessian
|
||||
for a subset of the variables.
|
||||
It returns $code true$$, for success, and $code false$$ otherwise.
|
||||
|
||||
$end
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
# include <cppad/local/std_set.hpp>
|
||||
# include <cppad/local/color_general.hpp>
|
||||
# include <cppad/local/color_symmetric.hpp>
|
||||
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
\file sparse_hessian.hpp
|
||||
Sparse Hessian driver routine and helper functions.
|
||||
*/
|
||||
// ===========================================================================
|
||||
/*!
|
||||
class used by SparseHessian to hold information
|
||||
so it does not need to be recomputed.
|
||||
*/
|
||||
class sparse_hessian_work {
|
||||
public:
|
||||
/// Coloring method: "cppad", or "colpack"
|
||||
/// (this field is set by user)
|
||||
std::string color_method;
|
||||
/// row and column indicies for return values
|
||||
/// (some may be reflected by star coloring algorithm)
|
||||
CppAD::vector<size_t> row;
|
||||
CppAD::vector<size_t> col;
|
||||
/// indices that sort the user row and col arrays by color
|
||||
CppAD::vector<size_t> order;
|
||||
/// results of the coloring algorithm
|
||||
CppAD::vector<size_t> color;
|
||||
|
||||
/// constructor
|
||||
sparse_hessian_work(void) : color_method("cppad.symmetric")
|
||||
{ }
|
||||
/// inform CppAD that this information needs to be recomputed
|
||||
void clear(void)
|
||||
{ color_method = "cppad.symmetric";
|
||||
row.clear();
|
||||
col.clear();
|
||||
order.clear();
|
||||
color.clear();
|
||||
}
|
||||
};
|
||||
// ===========================================================================
|
||||
/*!
|
||||
Private helper function that does computation for all Sparse Hessian cases.
|
||||
|
||||
\tparam Base
|
||||
is the base type for the recording that is stored in this ADFun<Base object.
|
||||
|
||||
\tparam VectorBase
|
||||
is a simple vector class with elements of type \a Base.
|
||||
|
||||
\tparam VectorSet
|
||||
is a simple vector class with elements of type
|
||||
\c bool or \c std::set<size_t>.
|
||||
|
||||
\tparam VectorSize
|
||||
is sparse_pack or sparse_list.
|
||||
|
||||
\param x [in]
|
||||
is a vector specifing the point at which to compute the Hessian.
|
||||
|
||||
\param w [in]
|
||||
is the weighting vector that defines a scalar valued function by
|
||||
a weighted sum of the components of the vector valued function
|
||||
$latex F(x)$$.
|
||||
|
||||
\param sparsity [in]
|
||||
is the sparsity pattern for the Hessian that we are calculating.
|
||||
|
||||
\param user_row [in]
|
||||
is the vector of row indices for the returned Hessian values.
|
||||
|
||||
\param user_col [in]
|
||||
is the vector of columns indices for the returned Hessian values.
|
||||
It must have the same size as user_row.
|
||||
|
||||
\param hes [out]
|
||||
is the vector of Hessian values.
|
||||
It must have the same size as user_row.
|
||||
The return value <code>hes[k]</code> is the second partial of
|
||||
\f$ w^{\rm T} F(x)\f$ with respect to the
|
||||
<code>row[k]</code> and <code>col[k]</code> component of \f$ x\f$.
|
||||
|
||||
\param work
|
||||
This structure contains information that is computed by \c SparseHessianCompute.
|
||||
If the sparsity pattern, \c row vector, or \c col vectors
|
||||
are not the same between calls to \c SparseHessianCompute,
|
||||
\c work.clear() must be called to reinitialize \c work.
|
||||
|
||||
\return
|
||||
Is the number of first order forward sweeps used to compute the
|
||||
requested Hessian values.
|
||||
(This is also equal to the number of second order reverse sweeps.)
|
||||
The total work, not counting the zero order
|
||||
forward sweep, or the time to combine computations, is proportional to this
|
||||
return value.
|
||||
*/
|
||||
template<class Base>
|
||||
template <class VectorBase, class VectorSet, class VectorSize>
|
||||
size_t ADFun<Base>::SparseHessianCompute(
|
||||
const VectorBase& x ,
|
||||
const VectorBase& w ,
|
||||
VectorSet& sparsity ,
|
||||
const VectorSize& user_row ,
|
||||
const VectorSize& user_col ,
|
||||
VectorBase& hes ,
|
||||
sparse_hessian_work& work )
|
||||
{
|
||||
using CppAD::vectorBool;
|
||||
size_t i, k, ell;
|
||||
|
||||
CppAD::vector<size_t>& row(work.row);
|
||||
CppAD::vector<size_t>& col(work.col);
|
||||
CppAD::vector<size_t>& color(work.color);
|
||||
CppAD::vector<size_t>& order(work.order);
|
||||
|
||||
size_t n = Domain();
|
||||
|
||||
// some values
|
||||
const Base zero(0);
|
||||
const Base one(1);
|
||||
|
||||
// check VectorBase is Simple Vector class with Base type elements
|
||||
CheckSimpleVector<Base, VectorBase>();
|
||||
|
||||
// number of components of Hessian that are required
|
||||
size_t K = hes.size();
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( user_row.size() ) == K );
|
||||
CPPAD_ASSERT_UNKNOWN( size_t( user_col.size() ) == K );
|
||||
|
||||
CPPAD_ASSERT_UNKNOWN( size_t(x.size()) == n );
|
||||
CPPAD_ASSERT_UNKNOWN( color.size() == 0 || color.size() == n );
|
||||
CPPAD_ASSERT_UNKNOWN( row.size() == 0 || row.size() == K );
|
||||
CPPAD_ASSERT_UNKNOWN( col.size() == 0 || col.size() == K );
|
||||
|
||||
|
||||
// Point at which we are evaluating the Hessian
|
||||
Forward(0, x);
|
||||
|
||||
// check for case where nothing (except Forward above) to do
|
||||
if( K == 0 )
|
||||
return 0;
|
||||
|
||||
// Rows of the Hessian (i below) correspond to the forward mode index
|
||||
// and columns (j below) correspond to the reverse mode index.
|
||||
if( color.size() == 0 )
|
||||
{
|
||||
CPPAD_ASSERT_UNKNOWN( sparsity.n_set() == n );
|
||||
CPPAD_ASSERT_UNKNOWN( sparsity.end() == n );
|
||||
|
||||
// copy user rwo and col to work space
|
||||
row.resize(K);
|
||||
col.resize(K);
|
||||
for(k = 0; k < K; k++)
|
||||
{ row[k] = user_row[k];
|
||||
col[k] = user_col[k];
|
||||
}
|
||||
|
||||
// execute coloring algorithm
|
||||
color.resize(n);
|
||||
if( work.color_method == "cppad.general" )
|
||||
local::color_general_cppad(sparsity, row, col, color);
|
||||
else if( work.color_method == "cppad.symmetric" )
|
||||
local::color_symmetric_cppad(sparsity, row, col, color);
|
||||
else if( work.color_method == "colpack.general" )
|
||||
{
|
||||
# if CPPAD_HAS_COLPACK
|
||||
local::color_general_colpack(sparsity, row, col, color);
|
||||
# else
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"SparseHessian: work.color_method = colpack.general "
|
||||
"and colpack_prefix missing from cmake command line."
|
||||
);
|
||||
# endif
|
||||
}
|
||||
else if(
|
||||
work.color_method == "colpack.symmetric" ||
|
||||
work.color_method == "colpack.star"
|
||||
)
|
||||
{
|
||||
# if CPPAD_HAS_COLPACK
|
||||
local::color_symmetric_colpack(sparsity, row, col, color);
|
||||
# else
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"SparseHessian: work.color_method is "
|
||||
"colpack.symmetric or colpack.star\n"
|
||||
"and colpack_prefix missing from cmake command line."
|
||||
);
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"SparseHessian: work.color_method is not valid."
|
||||
);
|
||||
}
|
||||
|
||||
// put sorting indices in color order
|
||||
VectorSize key(K);
|
||||
order.resize(K);
|
||||
for(k = 0; k < K; k++)
|
||||
key[k] = color[ row[k] ];
|
||||
index_sort(key, order);
|
||||
|
||||
}
|
||||
size_t n_color = 1;
|
||||
for(ell = 0; ell < n; ell++) if( color[ell] < n )
|
||||
n_color = std::max(n_color, color[ell] + 1);
|
||||
|
||||
// direction vector for calls to forward (rows of the Hessian)
|
||||
VectorBase u(n);
|
||||
|
||||
// location for return values from reverse (columns of the Hessian)
|
||||
VectorBase ddw(2 * n);
|
||||
|
||||
// initialize the return value
|
||||
for(k = 0; k < K; k++)
|
||||
hes[k] = zero;
|
||||
|
||||
// loop over colors
|
||||
# ifndef NDEBUG
|
||||
const std::string& coloring = work.color_method;
|
||||
# endif
|
||||
k = 0;
|
||||
for(ell = 0; ell < n_color; ell++)
|
||||
if( k == K )
|
||||
{ // kludge because colpack returns colors that are not used
|
||||
// (it does not know about the subset corresponding to row, col)
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
coloring == "colpack.general" ||
|
||||
coloring == "colpack.symmetic" ||
|
||||
coloring == "colpack.star"
|
||||
);
|
||||
}
|
||||
else if( color[ row[ order[k] ] ] != ell )
|
||||
{ // kludge because colpack returns colors that are not used
|
||||
// (it does not know about the subset corresponding to row, col)
|
||||
CPPAD_ASSERT_UNKNOWN(
|
||||
coloring == "colpack.general" ||
|
||||
coloring == "colpack.symmetic" ||
|
||||
coloring == "colpack.star"
|
||||
);
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( color[ row[ order[k] ] ] == ell );
|
||||
|
||||
// combine all rows with this color
|
||||
for(i = 0; i < n; i++)
|
||||
{ u[i] = zero;
|
||||
if( color[i] == ell )
|
||||
u[i] = one;
|
||||
}
|
||||
// call forward mode for all these rows at once
|
||||
Forward(1, u);
|
||||
|
||||
// evaluate derivative of w^T * F'(x) * u
|
||||
ddw = Reverse(2, w);
|
||||
|
||||
// set the corresponding components of the result
|
||||
while( k < K && color[ row[ order[k] ] ] == ell )
|
||||
{ hes[ order[k] ] = ddw[ col[ order[k] ] * 2 + 1 ];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return n_color;
|
||||
}
|
||||
// ===========================================================================
|
||||
// Public Member Functions
|
||||
// ===========================================================================
|
||||
/*!
|
||||
Compute user specified subset of a sparse Hessian.
|
||||
|
||||
The C++ source code corresponding to this operation is
|
||||
\verbatim
|
||||
SparceHessian(x, w, p, row, col, hes, work)
|
||||
\endverbatim
|
||||
|
||||
\tparam Base
|
||||
is the base type for the recording that is stored in this ADFun<Base object.
|
||||
|
||||
\tparam VectorBase
|
||||
is a simple vector class with elements of type \a Base.
|
||||
|
||||
\tparam VectorSet
|
||||
is a simple vector class with elements of type
|
||||
\c bool or \c std::set<size_t>.
|
||||
|
||||
\tparam VectorSize
|
||||
is a simple vector class with elements of type \c size_t.
|
||||
|
||||
\param x [in]
|
||||
is a vector specifing the point at which to compute the Hessian.
|
||||
|
||||
\param w [in]
|
||||
is the weighting vector that defines a scalar valued function by
|
||||
a weighted sum of the components of the vector valued function
|
||||
$latex F(x)$$.
|
||||
|
||||
\param p [in]
|
||||
is the sparsity pattern for the Hessian that we are calculating.
|
||||
|
||||
\param row [in]
|
||||
is the vector of row indices for the returned Hessian values.
|
||||
|
||||
\param col [in]
|
||||
is the vector of columns indices for the returned Hessian values.
|
||||
It must have the same size are r.
|
||||
|
||||
\param hes [out]
|
||||
is the vector of Hessian values.
|
||||
It must have the same size are r.
|
||||
The return value <code>hes[k]</code> is the second partial of
|
||||
\f$ w^{\rm T} F(x)\f$ with respect to the
|
||||
<code>row[k]</code> and <code>col[k]</code> component of \f$ x\f$.
|
||||
|
||||
\param work
|
||||
This structure contains information that is computed by \c SparseHessianCompute.
|
||||
If the sparsity pattern, \c row vector, or \c col vectors
|
||||
are not the same between calls to \c SparseHessian,
|
||||
\c work.clear() must be called to reinitialize \c work.
|
||||
|
||||
\return
|
||||
Is the number of first order forward sweeps used to compute the
|
||||
requested Hessian values.
|
||||
(This is also equal to the number of second order reverse sweeps.)
|
||||
The total work, not counting the zero order
|
||||
forward sweep, or the time to combine computations, is proportional to this
|
||||
return value.
|
||||
*/
|
||||
template<class Base>
|
||||
template <class VectorBase, class VectorSet, class VectorSize>
|
||||
size_t ADFun<Base>::SparseHessian(
|
||||
const VectorBase& x ,
|
||||
const VectorBase& w ,
|
||||
const VectorSet& p ,
|
||||
const VectorSize& row ,
|
||||
const VectorSize& col ,
|
||||
VectorBase& hes ,
|
||||
sparse_hessian_work& work )
|
||||
{
|
||||
size_t n = Domain();
|
||||
size_t K = hes.size();
|
||||
# ifndef NDEBUG
|
||||
size_t k;
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(x.size()) == n ,
|
||||
"SparseHessian: size of x not equal domain dimension for f."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(row.size()) == K && size_t(col.size()) == K ,
|
||||
"SparseHessian: either r or c does not have the same size as ehs."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
work.color.size() == 0 || work.color.size() == n,
|
||||
"SparseHessian: invalid value in work."
|
||||
);
|
||||
for(k = 0; k < K; k++)
|
||||
{ CPPAD_ASSERT_KNOWN(
|
||||
row[k] < n,
|
||||
"SparseHessian: invalid value in r."
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
col[k] < n,
|
||||
"SparseHessian: invalid value in c."
|
||||
);
|
||||
}
|
||||
if( work.color.size() != 0 )
|
||||
for(size_t j = 0; j < n; j++) CPPAD_ASSERT_KNOWN(
|
||||
work.color[j] <= n,
|
||||
"SparseHessian: invalid value in work."
|
||||
);
|
||||
# endif
|
||||
// check for case where there is nothing to compute
|
||||
size_t n_sweep = 0;
|
||||
if( K == 0 )
|
||||
return n_sweep;
|
||||
|
||||
typedef typename VectorSet::value_type Set_type;
|
||||
typedef typename local::internal_sparsity<Set_type>::pattern_type Pattern_type;
|
||||
Pattern_type s;
|
||||
if( work.color.size() == 0 )
|
||||
{ bool transpose = false;
|
||||
const char* error_msg = "SparseHessian: sparsity pattern"
|
||||
" does not have proper row or column dimension";
|
||||
sparsity_user2internal(s, p, n, n, transpose, error_msg);
|
||||
}
|
||||
n_sweep = SparseHessianCompute(x, w, s, row, col, hes, work);
|
||||
return n_sweep;
|
||||
}
|
||||
/*!
|
||||
Compute a sparse Hessian.
|
||||
|
||||
The C++ source code coresponding to this operation is
|
||||
\verbatim
|
||||
hes = SparseHessian(x, w, p)
|
||||
\endverbatim
|
||||
|
||||
|
||||
\tparam Base
|
||||
is the base type for the recording that is stored in this
|
||||
ADFun<Base object.
|
||||
|
||||
\tparam VectorBase
|
||||
is a simple vector class with elements of the \a Base.
|
||||
|
||||
\tparam VectorSet
|
||||
is a simple vector class with elements of type
|
||||
\c bool or \c std::set<size_t>.
|
||||
|
||||
\param x [in]
|
||||
is a vector specifing the point at which to compute the Hessian.
|
||||
|
||||
\param w [in]
|
||||
The Hessian is computed for a weighted sum of the components
|
||||
of the function corresponding to this ADFun<Base> object.
|
||||
The argument \a w specifies the weights for each component.
|
||||
It must have size equal to the range dimension for this ADFun<Base> object.
|
||||
|
||||
\param p [in]
|
||||
is a sparsity pattern for the Hessian.
|
||||
|
||||
\return
|
||||
Will be a vector of size \c n * n containing the Hessian of
|
||||
at the point specified by \a x
|
||||
(where \c n is the domain dimension for this ADFun<Base> object).
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorBase, class VectorSet>
|
||||
VectorBase ADFun<Base>::SparseHessian(
|
||||
const VectorBase& x, const VectorBase& w, const VectorSet& p
|
||||
)
|
||||
{ size_t i, j, k;
|
||||
|
||||
size_t n = Domain();
|
||||
VectorBase hes(n * n);
|
||||
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
size_t(x.size()) == n,
|
||||
"SparseHessian: size of x not equal domain size for f."
|
||||
);
|
||||
|
||||
typedef typename VectorSet::value_type Set_type;
|
||||
typedef typename local::internal_sparsity<Set_type>::pattern_type Pattern_type;
|
||||
|
||||
// initialize the return value as zero
|
||||
Base zero(0);
|
||||
for(i = 0; i < n; i++)
|
||||
for(j = 0; j < n; j++)
|
||||
hes[i * n + j] = zero;
|
||||
|
||||
// arguments to SparseHessianCompute
|
||||
Pattern_type s;
|
||||
CppAD::vector<size_t> row;
|
||||
CppAD::vector<size_t> col;
|
||||
sparse_hessian_work work;
|
||||
bool transpose = false;
|
||||
const char* error_msg = "SparseHessian: sparsity pattern"
|
||||
" does not have proper row or column dimension";
|
||||
sparsity_user2internal(s, p, n, n, transpose, error_msg);
|
||||
k = 0;
|
||||
for(i = 0; i < n; i++)
|
||||
{ typename Pattern_type::const_iterator itr(s, i);
|
||||
j = *itr;
|
||||
while( j != s.end() )
|
||||
{ row.push_back(i);
|
||||
col.push_back(j);
|
||||
k++;
|
||||
j = *(++itr);
|
||||
}
|
||||
}
|
||||
size_t K = k;
|
||||
VectorBase H(K);
|
||||
|
||||
// now we have folded this into the following case
|
||||
SparseHessianCompute(x, w, s, row, col, H, work);
|
||||
|
||||
// now set the non-zero return values
|
||||
for(k = 0; k < K; k++)
|
||||
hes[ row[k] * n + col[k] ] = H[k];
|
||||
|
||||
return hes;
|
||||
}
|
||||
/*!
|
||||
Compute a sparse Hessian
|
||||
|
||||
The C++ source code coresponding to this operation is
|
||||
\verbatim
|
||||
hes = SparseHessian(x, w)
|
||||
\endverbatim
|
||||
|
||||
|
||||
\tparam Base
|
||||
is the base type for the recording that is stored in this
|
||||
ADFun<Base object.
|
||||
|
||||
\tparam VectorBase
|
||||
is a simple vector class with elements of the \a Base.
|
||||
|
||||
\param x [in]
|
||||
is a vector specifing the point at which to compute the Hessian.
|
||||
|
||||
\param w [in]
|
||||
The Hessian is computed for a weighted sum of the components
|
||||
of the function corresponding to this ADFun<Base> object.
|
||||
The argument \a w specifies the weights for each component.
|
||||
It must have size equal to the range dimension for this ADFun<Base> object.
|
||||
|
||||
\return
|
||||
Will be a vector of size \c n * n containing the Hessian of
|
||||
at the point specified by \a x
|
||||
(where \c n is the domain dimension for this ADFun<Base> object).
|
||||
*/
|
||||
template <class Base>
|
||||
template <class VectorBase>
|
||||
VectorBase ADFun<Base>::SparseHessian(const VectorBase &x, const VectorBase &w)
|
||||
{ size_t i, j, k;
|
||||
typedef CppAD::vectorBool VectorBool;
|
||||
|
||||
size_t m = Range();
|
||||
size_t n = Domain();
|
||||
|
||||
// determine the sparsity pattern p for Hessian of w^T F
|
||||
VectorBool r(n * n);
|
||||
for(j = 0; j < n; j++)
|
||||
{ for(k = 0; k < n; k++)
|
||||
r[j * n + k] = false;
|
||||
r[j * n + j] = true;
|
||||
}
|
||||
ForSparseJac(n, r);
|
||||
//
|
||||
VectorBool s(m);
|
||||
for(i = 0; i < m; i++)
|
||||
s[i] = w[i] != 0;
|
||||
VectorBool p = RevSparseHes(n, s);
|
||||
|
||||
// compute sparse Hessian
|
||||
return SparseHessian(x, w, p);
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+623
@@ -0,0 +1,623 @@
|
||||
# ifndef CPPAD_CORE_SPARSE_JAC_HPP
|
||||
# define CPPAD_CORE_SPARSE_JAC_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 sparse_jac$$
|
||||
$spell
|
||||
Jacobian
|
||||
Jacobians
|
||||
const
|
||||
jac
|
||||
Taylor
|
||||
rc
|
||||
rcv
|
||||
nr
|
||||
nc
|
||||
std
|
||||
Cppad
|
||||
Colpack
|
||||
cmake
|
||||
$$
|
||||
|
||||
$section Computing Sparse Jacobians$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%n_sweep% = %f%.sparse_jac_for(
|
||||
%group_max%, %x%, %subset%, %pattern%, %coloring%, %work%
|
||||
)
|
||||
%$$
|
||||
$icode%n_sweep% = %f%.sparse_jac_rev(
|
||||
%x%, %subset%, %pattern%, %coloring%, %work%
|
||||
)%$$
|
||||
|
||||
|
||||
$head Purpose$$
|
||||
We use $latex F : \B{R}^n \rightarrow \B{R}^m$$ to denote the
|
||||
function corresponding to $icode f$$.
|
||||
Here $icode n$$ is the $cref/domain/seq_property/Domain/$$ size,
|
||||
and $icode m$$ is the $cref/range/seq_property/Range/$$ size, or $icode f$$.
|
||||
The syntax above takes advantage of sparsity when computing the Jacobian
|
||||
$latex \[
|
||||
J(x) = F^{(1)} (x)
|
||||
\] $$
|
||||
In the sparse case, this should be faster and take less memory than
|
||||
$cref Jacobian$$.
|
||||
We use the notation $latex J_{i,j} (x)$$ to denote the partial of
|
||||
$latex F_i (x)$$ with respect to $latex x_j$$.
|
||||
|
||||
$head SizeVector$$
|
||||
The type $icode SizeVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
|
||||
$head BaseVector$$
|
||||
The type $icode BaseVector$$ is a $cref SimpleVector$$ class with
|
||||
$cref/elements of type/SimpleVector/Elements of Specified Type/$$
|
||||
$code size_t$$.
|
||||
|
||||
$head sparse_jac_for$$
|
||||
This function uses first order forward mode sweeps $cref forward_one$$
|
||||
to compute multiple columns of the Jacobian at the same time.
|
||||
|
||||
$head sparse_jac_rev$$
|
||||
This uses function first order reverse mode sweeps $cref reverse_one$$
|
||||
to compute multiple rows of the Jacobian at the same time.
|
||||
|
||||
$head f$$
|
||||
This object has prototype
|
||||
$codei%
|
||||
ADFun<%Base%> %f%
|
||||
%$$
|
||||
Note that the Taylor coefficients stored in $icode f$$ are affected
|
||||
by this operation; see
|
||||
$cref/uses forward/sparse_jac/Uses Forward/$$ below.
|
||||
|
||||
$head group_max$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
size_t %group_max%
|
||||
%$$
|
||||
and must be greater than zero.
|
||||
It specifies the maximum number of colors to group during
|
||||
a single forward sweep.
|
||||
If a single color is in a group,
|
||||
a single direction for of first order forward mode
|
||||
$cref forward_one$$ is used for each color.
|
||||
If multiple colors are in a group,
|
||||
the multiple direction for of first order forward mode
|
||||
$cref forward_dir$$ is used with one direction for each color.
|
||||
This uses separate memory for each direction (more memory),
|
||||
but my be significantly faster.
|
||||
|
||||
$head x$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
const %BaseVector%& %x%
|
||||
%$$
|
||||
and its size is $icode n$$.
|
||||
It specifies the point at which to evaluate the Jacobian
|
||||
$latex J(x)$$.
|
||||
|
||||
$head subset$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
sparse_rcv<%SizeVector%, %BaseVector%>& %subset%
|
||||
%$$
|
||||
Its row size is $icode%subset%.nr() == %m%$$,
|
||||
and its column size is $icode%subset%.nc() == %n%$$.
|
||||
It specifies which elements of the Jacobian are computed.
|
||||
The input value of its value vector
|
||||
$icode%subset%.val()%$$ does not matter.
|
||||
Upon return it contains the value of the corresponding elements
|
||||
of the Jacobian.
|
||||
All of the row, column pairs in $icode subset$$ must also appear in
|
||||
$icode pattern$$; i.e., they must be possibly non-zero.
|
||||
|
||||
$head pattern$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
const sparse_rc<%SizeVector%>& %pattern%
|
||||
%$$
|
||||
Its row size is $icode%pattern%.nr() == %m%$$,
|
||||
and its column size is $icode%pattern%.nc() == %n%$$.
|
||||
It is a sparsity pattern for the Jacobian $latex J(x)$$.
|
||||
This argument is not used (and need not satisfy any conditions),
|
||||
when $cref/work/sparse_jac/work/$$ is non-empty.
|
||||
|
||||
$head coloring$$
|
||||
The coloring algorithm determines which rows (reverse) or columns (forward)
|
||||
can be computed during the same sweep.
|
||||
This field has prototype
|
||||
$codei%
|
||||
const std::string& %coloring%
|
||||
%$$
|
||||
This value only matters when work is empty; i.e.,
|
||||
after the $icode work$$ constructor or $icode%work%.clear()%$$.
|
||||
|
||||
$subhead cppad$$
|
||||
This uses a general purpose coloring algorithm written for Cppad.
|
||||
|
||||
$subhead colpack$$
|
||||
If $cref colpack_prefix$$ is specified on the
|
||||
$cref/cmake command/cmake/CMake Command/$$ line,
|
||||
you can set $icode coloring$$ to $code colpack$$.
|
||||
This uses a general purpose coloring algorithm that is part of Colpack.
|
||||
|
||||
$head work$$
|
||||
This argument has prototype
|
||||
$codei%
|
||||
sparse_jac_work& %work%
|
||||
%$$
|
||||
We refer to its initial value,
|
||||
and its value after $icode%work%.clear()%$$, as empty.
|
||||
If it is empty, information is stored in $icode work$$.
|
||||
This can be used to reduce computation when
|
||||
a future call is for the same object $icode f$$,
|
||||
the same member function $code sparse_jac_for$$ or $code sparse_jac_rev$$,
|
||||
and the same subset of the Jacobian.
|
||||
If any of these values change, use $icode%work%.clear()%$$ to
|
||||
empty this structure.
|
||||
|
||||
$head n_sweep$$
|
||||
The return value $icode n_sweep$$ has prototype
|
||||
$codei%
|
||||
size_t %n_sweep%
|
||||
%$$
|
||||
If $code sparse_jac_for$$ ($code sparse_jac_rev$$) is used,
|
||||
$icode n_sweep$$ is the number of first order forward (reverse) sweeps
|
||||
used to compute the requested Jacobian values.
|
||||
It is also the number of colors determined by the coloring method
|
||||
mentioned above.
|
||||
This is proportional to the total computational work,
|
||||
not counting the zero order forward sweep,
|
||||
or combining multiple columns (rows) into a single sweep.
|
||||
|
||||
$head 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 sparse_jac_forward$$ or $code sparse_jac_rev$$,
|
||||
the zero order coefficients correspond to
|
||||
$codei%
|
||||
%f%.Forward(0, %x%)
|
||||
%$$
|
||||
All the other forward mode coefficients are unspecified.
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/sparse/sparse_jac_for.cpp%
|
||||
example/sparse/sparse_jac_rev.cpp
|
||||
%$$
|
||||
The files $cref sparse_jac_for.cpp$$ and $cref sparse_jac_rev.cpp$$
|
||||
are examples and tests of $code sparse_jac_for$$ and $code sparse_jac_rev$$.
|
||||
They return $code true$$, if they succeed, and $code false$$ otherwise.
|
||||
|
||||
$end
|
||||
*/
|
||||
# include <cppad/core/cppad_assert.hpp>
|
||||
# include <cppad/local/sparse_internal.hpp>
|
||||
# include <cppad/local/color_general.hpp>
|
||||
# include <cppad/utility/vector.hpp>
|
||||
|
||||
/*!
|
||||
\file sparse_jac.hpp
|
||||
Sparse Jacobian calculation routines.
|
||||
*/
|
||||
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||
/*!
|
||||
Class used to hold information used by Sparse Jacobian routines in this file,
|
||||
so they do not need to be recomputed every time.
|
||||
*/
|
||||
class sparse_jac_work {
|
||||
public:
|
||||
/// indices that sort the user row and col arrays by color
|
||||
CppAD::vector<size_t> order;
|
||||
/// results of the coloring algorithm
|
||||
CppAD::vector<size_t> color;
|
||||
//
|
||||
/// constructor
|
||||
sparse_jac_work(void)
|
||||
{ }
|
||||
/// reset work to empty.
|
||||
/// This informs CppAD that color and order need to be recomputed
|
||||
void clear(void)
|
||||
{ order.clear();
|
||||
color.clear();
|
||||
}
|
||||
};
|
||||
// ----------------------------------------------------------------------------
|
||||
/*!
|
||||
Calculate sparse Jacobains using forward mode
|
||||
|
||||
\tparam Base
|
||||
the base type for the recording that is stored in the ADFun object.
|
||||
|
||||
\tparam SizeVector
|
||||
a simple vector class with elements of type size_t.
|
||||
|
||||
\tparam BaseVector
|
||||
a simple vector class with elements of type Base.
|
||||
|
||||
\param group_max
|
||||
specifies the maximum number of colors to group during a single forward sweep.
|
||||
This must be greater than zero and group_max = 1 minimizes memory usage.
|
||||
|
||||
\param x
|
||||
a vector of length n, the number of independent variables in f
|
||||
(this ADFun object).
|
||||
|
||||
\param subset
|
||||
specifices the subset of the sparsity pattern where the Jacobian is evaluated.
|
||||
subset.nr() == m,
|
||||
subset.nc() == n.
|
||||
|
||||
\param pattern
|
||||
is a sparsity pattern for the Jacobian of f;
|
||||
pattern.nr() == m,
|
||||
pattern.nc() == n,
|
||||
where m is number of dependent variables in f.
|
||||
|
||||
\param coloring
|
||||
determines which coloring algorithm is used.
|
||||
This must be cppad or colpack.
|
||||
|
||||
\param work
|
||||
this structure must be empty, or contain the information stored
|
||||
by a previous call to sparse_jac_for.
|
||||
The previous call must be for the same ADFun object f
|
||||
and the same subset.
|
||||
|
||||
\return
|
||||
This is the number of first order forward sweeps used to compute
|
||||
the Jacobian.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class SizeVector, class BaseVector>
|
||||
size_t ADFun<Base>::sparse_jac_for(
|
||||
size_t group_max ,
|
||||
const BaseVector& x ,
|
||||
sparse_rcv<SizeVector, BaseVector>& subset ,
|
||||
const sparse_rc<SizeVector>& pattern ,
|
||||
const std::string& coloring ,
|
||||
sparse_jac_work& work )
|
||||
{ size_t m = Range();
|
||||
size_t n = Domain();
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
subset.nr() == m,
|
||||
"sparse_jac_for: subset.nr() not equal range dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
subset.nc() == n,
|
||||
"sparse_jac_for: subset.nc() not equal domain dimension for f"
|
||||
);
|
||||
//
|
||||
// row and column vectors in subset
|
||||
const SizeVector& row( subset.row() );
|
||||
const SizeVector& col( subset.col() );
|
||||
//
|
||||
vector<size_t>& color(work.color);
|
||||
vector<size_t>& order(work.order);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
color.size() == 0 || color.size() == n,
|
||||
"sparse_jac_for: work is non-empty and conditions have changed"
|
||||
);
|
||||
//
|
||||
// point at which we are evaluationg the Jacobian
|
||||
Forward(0, x);
|
||||
//
|
||||
// number of elements in the subset
|
||||
size_t K = subset.nnz();
|
||||
//
|
||||
// check for case were there is nothing to do
|
||||
// (except for call to Forward(0, x)
|
||||
if( K == 0 )
|
||||
return 0;
|
||||
//
|
||||
// check for case where input work is empty
|
||||
if( color.size() == 0 )
|
||||
{ // compute work color and order vectors
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
pattern.nr() == m,
|
||||
"sparse_jac_for: pattern.nr() not equal range dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
pattern.nc() == n,
|
||||
"sparse_jac_for: pattern.nc() not equal domain dimension for f"
|
||||
);
|
||||
//
|
||||
// convert pattern to an internal version of its transpose
|
||||
vector<size_t> internal_index(n);
|
||||
for(size_t j = 0; j < n; j++)
|
||||
internal_index[j] = j;
|
||||
bool transpose = true;
|
||||
bool zero_empty = false;
|
||||
bool input_empty = true;
|
||||
local::sparse_list pattern_transpose;
|
||||
pattern_transpose.resize(n, m);
|
||||
local::set_internal_sparsity(zero_empty, input_empty,
|
||||
transpose, internal_index, pattern_transpose, pattern
|
||||
);
|
||||
//
|
||||
// execute coloring algorithm
|
||||
// (we are using transpose because coloring groups rows, not columns).
|
||||
color.resize(n);
|
||||
if( coloring == "cppad" )
|
||||
local::color_general_cppad(pattern_transpose, col, row, color);
|
||||
else if( coloring == "colpack" )
|
||||
{
|
||||
# if CPPAD_HAS_COLPACK
|
||||
local::color_general_colpack(pattern_transpose, col, row, color);
|
||||
# else
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"sparse_jac_for: coloring = colpack "
|
||||
"and colpack_prefix missing from cmake command line."
|
||||
);
|
||||
# endif
|
||||
}
|
||||
else CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"sparse_jac_for: coloring is not valid."
|
||||
);
|
||||
//
|
||||
// put sorting indices in color order
|
||||
SizeVector key(K);
|
||||
order.resize(K);
|
||||
for(size_t k = 0; k < K; k++)
|
||||
key[k] = color[ col[k] ];
|
||||
index_sort(key, order);
|
||||
}
|
||||
// Base versions of zero and one
|
||||
Base one(1.0);
|
||||
Base zero(0.0);
|
||||
//
|
||||
size_t n_color = 1;
|
||||
for(size_t j = 0; j < n; j++) if( color[j] < n )
|
||||
n_color = std::max(n_color, color[j] + 1);
|
||||
//
|
||||
// initialize the return Jacobian values as zero
|
||||
for(size_t k = 0; k < K; k++)
|
||||
subset.set(k, zero);
|
||||
//
|
||||
// index in subset
|
||||
size_t k = 0;
|
||||
// number of colors computed so far
|
||||
size_t color_count = 0;
|
||||
//
|
||||
while( color_count < n_color )
|
||||
{ // number of colors that will be in this group
|
||||
size_t group_size = std::min(group_max, n_color - color_count);
|
||||
//
|
||||
// forward mode values for independent and dependent variables
|
||||
BaseVector dx(n * group_size), dy(m * group_size);
|
||||
//
|
||||
// set dx
|
||||
for(size_t ell = 0; ell < group_size; ell++)
|
||||
{ // combine all columns with this color
|
||||
for(size_t j = 0; j < n; j++)
|
||||
{ dx[j * group_size + ell] = zero;
|
||||
if( color[j] == ell + color_count )
|
||||
dx[j * group_size + ell] = one;
|
||||
}
|
||||
}
|
||||
if( group_size == 1 )
|
||||
dy = Forward(1, dx);
|
||||
else
|
||||
dy = Forward(1, group_size, dx);
|
||||
//
|
||||
// store results in subset
|
||||
for(size_t ell = 0; ell < group_size; ell++)
|
||||
{ // color with index ell + color_count is in this group
|
||||
while(k < K && color[ col[ order[k] ] ] == ell + color_count )
|
||||
{ // subset element with index order[k] is included in this color
|
||||
size_t r = row[ order[k] ];
|
||||
subset.set( order[k], dy[ r * group_size + ell ] );
|
||||
++k;
|
||||
}
|
||||
}
|
||||
// advance color count
|
||||
color_count += group_size;
|
||||
}
|
||||
CPPAD_ASSERT_UNKNOWN( color_count == n_color );
|
||||
//
|
||||
return n_color;
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
/*!
|
||||
Calculate sparse Jacobains using reverse mode
|
||||
|
||||
\tparam Base
|
||||
the base type for the recording that is stored in the ADFun object.
|
||||
|
||||
\tparam SizeVector
|
||||
a simple vector class with elements of type size_t.
|
||||
|
||||
\tparam BaseVector
|
||||
a simple vector class with elements of type Base.
|
||||
|
||||
\param x
|
||||
a vector of length n, the number of independent variables in f
|
||||
(this ADFun object).
|
||||
|
||||
\param subset
|
||||
specifices the subset of the sparsity pattern where the Jacobian is evaluated.
|
||||
subset.nr() == m,
|
||||
subset.nc() == n.
|
||||
|
||||
\param pattern
|
||||
is a sparsity pattern for the Jacobian of f;
|
||||
pattern.nr() == m,
|
||||
pattern.nc() == n,
|
||||
where m is number of dependent variables in f.
|
||||
|
||||
\param coloring
|
||||
determines which coloring algorithm is used.
|
||||
This must be cppad or colpack.
|
||||
|
||||
\param work
|
||||
this structure must be empty, or contain the information stored
|
||||
by a previous call to sparse_jac_rev.
|
||||
The previous call must be for the same ADFun object f
|
||||
and the same subset.
|
||||
|
||||
\return
|
||||
This is the number of first order reverse sweeps used to compute
|
||||
the Jacobian.
|
||||
*/
|
||||
template <class Base>
|
||||
template <class SizeVector, class BaseVector>
|
||||
size_t ADFun<Base>::sparse_jac_rev(
|
||||
const BaseVector& x ,
|
||||
sparse_rcv<SizeVector, BaseVector>& subset ,
|
||||
const sparse_rc<SizeVector>& pattern ,
|
||||
const std::string& coloring ,
|
||||
sparse_jac_work& work )
|
||||
{ size_t m = Range();
|
||||
size_t n = Domain();
|
||||
//
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
subset.nr() == m,
|
||||
"sparse_jac_rev: subset.nr() not equal range dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
subset.nc() == n,
|
||||
"sparse_jac_rev: subset.nc() not equal domain dimension for f"
|
||||
);
|
||||
//
|
||||
// row and column vectors in subset
|
||||
const SizeVector& row( subset.row() );
|
||||
const SizeVector& col( subset.col() );
|
||||
//
|
||||
vector<size_t>& color(work.color);
|
||||
vector<size_t>& order(work.order);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
color.size() == 0 || color.size() == m,
|
||||
"sparse_jac_rev: work is non-empty and conditions have changed"
|
||||
);
|
||||
//
|
||||
// point at which we are evaluationg the Jacobian
|
||||
Forward(0, x);
|
||||
//
|
||||
// number of elements in the subset
|
||||
size_t K = subset.nnz();
|
||||
//
|
||||
// check for case were there is nothing to do
|
||||
// (except for call to Forward(0, x)
|
||||
if( K == 0 )
|
||||
return 0;
|
||||
//
|
||||
// check for case where input work is empty
|
||||
if( color.size() == 0 )
|
||||
{ // compute work color and order vectors
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
pattern.nr() == m,
|
||||
"sparse_jac_rev: pattern.nr() not equal range dimension for f"
|
||||
);
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
pattern.nc() == n,
|
||||
"sparse_jac_rev: pattern.nc() not equal domain dimension for f"
|
||||
);
|
||||
//
|
||||
// convert pattern to an internal version
|
||||
vector<size_t> internal_index(m);
|
||||
for(size_t i = 0; i < m; i++)
|
||||
internal_index[i] = i;
|
||||
bool transpose = false;
|
||||
bool zero_empty = false;
|
||||
bool input_empty = true;
|
||||
local::sparse_list internal_pattern;
|
||||
internal_pattern.resize(m, n);
|
||||
local::set_internal_sparsity(zero_empty, input_empty,
|
||||
transpose, internal_index, internal_pattern, pattern
|
||||
);
|
||||
//
|
||||
// execute coloring algorithm
|
||||
color.resize(m);
|
||||
if( coloring == "cppad" )
|
||||
local::color_general_cppad(internal_pattern, row, col, color);
|
||||
else if( coloring == "colpack" )
|
||||
{
|
||||
# if CPPAD_HAS_COLPACK
|
||||
local::color_general_colpack(internal_pattern, row, col, color);
|
||||
# else
|
||||
CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"sparse_jac_rev: coloring = colpack "
|
||||
"and colpack_prefix missing from cmake command line."
|
||||
);
|
||||
# endif
|
||||
}
|
||||
else CPPAD_ASSERT_KNOWN(
|
||||
false,
|
||||
"sparse_jac_rev: coloring is not valid."
|
||||
);
|
||||
//
|
||||
// put sorting indices in color order
|
||||
SizeVector key(K);
|
||||
order.resize(K);
|
||||
for(size_t k = 0; k < K; k++)
|
||||
key[k] = color[ row[k] ];
|
||||
index_sort(key, order);
|
||||
}
|
||||
// Base versions of zero and one
|
||||
Base one(1.0);
|
||||
Base zero(0.0);
|
||||
//
|
||||
size_t n_color = 1;
|
||||
for(size_t i = 0; i < m; i++) if( color[i] < m )
|
||||
n_color = std::max(n_color, color[i] + 1);
|
||||
//
|
||||
// initialize the return Jacobian values as zero
|
||||
for(size_t k = 0; k < K; k++)
|
||||
subset.set(k, zero);
|
||||
//
|
||||
// weighting vector and return values for calls to Reverse
|
||||
BaseVector w(m), dw(n);
|
||||
//
|
||||
// loop over colors
|
||||
size_t k = 0;
|
||||
for(size_t ell = 0; ell < n_color; ell++)
|
||||
if( k == K )
|
||||
{ // kludge because colpack returns colors that are not used
|
||||
// (it does not know about the subset corresponding to row, col)
|
||||
CPPAD_ASSERT_UNKNOWN( coloring == "colpack" );
|
||||
}
|
||||
else if( color[ row[ order[k] ] ] != ell )
|
||||
{ // kludge because colpack returns colors that are not used
|
||||
// (it does not know about the subset corresponding to row, col)
|
||||
CPPAD_ASSERT_UNKNOWN( coloring == "colpack" );
|
||||
}
|
||||
else
|
||||
{ CPPAD_ASSERT_UNKNOWN( color[ row[ order[k] ] ] == ell );
|
||||
//
|
||||
// combine all rows with this color
|
||||
for(size_t i = 0; i < m; i++)
|
||||
{ w[i] = zero;
|
||||
if( color[i] == ell )
|
||||
w[i] = one;
|
||||
}
|
||||
// call reverse mode for all these rows at once
|
||||
dw = Reverse(1, w);
|
||||
//
|
||||
// set the corresponding components of the result
|
||||
while( k < K && color[ row[order[k]] ] == ell )
|
||||
{ subset.set(order[k], dw[col[order[k]]] );
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return n_color;
|
||||
}
|
||||
|
||||
} // END_CPPAD_NAMESPACE
|
||||
# endif
|
||||
+1086
File diff suppressed because it is too large
Load Diff
+132
@@ -0,0 +1,132 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_STANDARD_MATH_HPP
|
||||
# define CPPAD_CORE_STANDARD_MATH_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 unary_standard_math$$
|
||||
$spell
|
||||
const
|
||||
VecAD
|
||||
fabs
|
||||
$$
|
||||
|
||||
$section The Unary Standard Math Functions$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = %fun%(%x%)%$$
|
||||
|
||||
$head Purpose$$
|
||||
Evaluates the standard math function $icode fun$$.
|
||||
|
||||
$head Possible Types$$
|
||||
|
||||
$subhead Base$$
|
||||
If $icode Base$$ satisfies the
|
||||
$cref/base type requirements/base_require/$$
|
||||
and argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const %Base%& %x%
|
||||
%$$
|
||||
then the result $icode y$$ has prototype
|
||||
$codei%
|
||||
%Base% %y%
|
||||
%$$
|
||||
|
||||
$subhead AD<Base>$$
|
||||
If the argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const AD<%Base%>& %x%
|
||||
%$$
|
||||
then the result $icode y$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %y%
|
||||
%$$
|
||||
|
||||
$subhead VecAD<Base>$$
|
||||
If the argument $icode x$$ has prototype
|
||||
$codei%
|
||||
const VecAD<%Base%>::reference& %x%
|
||||
%$$
|
||||
then the result $icode y$$ has prototype
|
||||
$codei%
|
||||
AD<%Base%> %y%
|
||||
%$$
|
||||
|
||||
$children%cppad/core/std_math_98.hpp
|
||||
%cppad/core/abs.hpp
|
||||
%cppad/core/acosh.hpp
|
||||
%cppad/core/asinh.hpp
|
||||
%cppad/core/atanh.hpp
|
||||
%cppad/core/erf.hpp
|
||||
%cppad/core/expm1.hpp
|
||||
%cppad/core/log1p.hpp
|
||||
%cppad/core/sign.hpp
|
||||
%$$
|
||||
|
||||
$head fun$$
|
||||
The possible values for $icode fun$$ are
|
||||
$table
|
||||
$icode fun$$ $pre $$ $cnext Description $rnext
|
||||
$cref abs$$ $cnext $title abs$$ $rnext
|
||||
$cref acos$$ $cnext $title acos$$ $rnext
|
||||
$cref acosh$$ $cnext $title acosh$$ $rnext
|
||||
$cref asin$$ $cnext $title asin$$ $rnext
|
||||
$cref asinh$$ $cnext $title asinh$$ $rnext
|
||||
$cref atan$$ $cnext $title atan$$ $rnext
|
||||
$cref atanh$$ $cnext $title atanh$$ $rnext
|
||||
$cref cos$$ $cnext $title cos$$ $rnext
|
||||
$cref cosh$$ $cnext $title cosh$$ $rnext
|
||||
$cref erf$$ $cnext $title erf$$ $rnext
|
||||
$cref exp$$ $cnext $title exp$$ $rnext
|
||||
$cref expm1$$ $cnext $title expm1$$ $rnext
|
||||
$cref/fabs/abs/$$ $cnext $title abs$$ $rnext
|
||||
$cref log10$$ $cnext $title log10$$ $rnext
|
||||
$cref log1p$$ $cnext $title log1p$$ $rnext
|
||||
$cref log$$ $cnext $title log$$ $rnext
|
||||
$cref sign$$ $cnext $title sign$$ $rnext
|
||||
$cref sin$$ $cnext $title sin$$ $rnext
|
||||
$cref sinh$$ $cnext $title sinh$$ $rnext
|
||||
$cref sqrt$$ $cnext $title sqrt$$ $rnext
|
||||
$cref tan$$ $cnext $title tan$$ $rnext
|
||||
$cref tanh$$ $cnext $title tanh$$
|
||||
$tend
|
||||
|
||||
$end
|
||||
*/
|
||||
# include <cppad/core/abs.hpp>
|
||||
# include <cppad/core/acosh.hpp>
|
||||
# include <cppad/core/asinh.hpp>
|
||||
# include <cppad/core/atanh.hpp>
|
||||
# include <cppad/core/erf.hpp>
|
||||
# include <cppad/core/expm1.hpp>
|
||||
# include <cppad/core/log1p.hpp>
|
||||
# include <cppad/core/sign.hpp>
|
||||
# include <cppad/core/sign.hpp>
|
||||
|
||||
/*
|
||||
$begin binary_math$$
|
||||
|
||||
$section The Binary Math Functions$$
|
||||
|
||||
$childtable%cppad/core/atan2.hpp
|
||||
%cppad/core/pow.hpp
|
||||
%cppad/core/azmul.hpp
|
||||
%$$
|
||||
|
||||
$end
|
||||
*/
|
||||
# include <cppad/core/atan2.hpp>
|
||||
# include <cppad/core/pow.hpp>
|
||||
|
||||
# endif
|
||||
+600
@@ -0,0 +1,600 @@
|
||||
# ifndef CPPAD_CORE_STD_MATH_98_HPP
|
||||
# define CPPAD_CORE_STD_MATH_98_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 acos$$
|
||||
$spell
|
||||
acos
|
||||
$$
|
||||
|
||||
$section Inverse Sine Function: acos$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = acos(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{acos}^{(1)} (x) & = & - (1 - x * x)^{-1/2}
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/acos.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref acos.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin asin$$
|
||||
$spell
|
||||
asin
|
||||
$$
|
||||
|
||||
$section Inverse Sine Function: asin$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = asin(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{asin}^{(1)} (x) & = & (1 - x * x)^{-1/2}
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/asin.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref asin.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin atan$$
|
||||
$spell
|
||||
atan
|
||||
$$
|
||||
|
||||
$section Inverse Tangent Function: atan$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = atan(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{atan}^{(1)} (x) & = & \frac{1}{1 + x^2}
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/atan.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref atan.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin cos$$
|
||||
$spell
|
||||
cos
|
||||
$$
|
||||
|
||||
$section The Cosine Function: cos$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = cos(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{cos}^{(1)} (x) & = & - \sin(x)
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/cos.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref cos.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin cosh$$
|
||||
$spell
|
||||
cosh
|
||||
$$
|
||||
|
||||
$section The Hyperbolic Cosine Function: cosh$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = cosh(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{cosh}^{(1)} (x) & = & \sinh(x)
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/cosh.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref cosh.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin exp$$
|
||||
$spell
|
||||
exp
|
||||
$$
|
||||
|
||||
$section The Exponential Function: exp$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = exp(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{exp}^{(1)} (x) & = & \exp(x)
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/exp.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref exp.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin log$$
|
||||
$spell
|
||||
$$
|
||||
|
||||
$section The Exponential Function: log$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = log(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{log}^{(1)} (x) & = & \frac{1}{x}
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/log.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref log.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin log10$$
|
||||
$spell
|
||||
CppAD
|
||||
$$
|
||||
|
||||
$section The Base 10 Logarithm Function: log10$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = log10(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Method$$
|
||||
CppAD uses the representation
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
{\rm log10} (x) & = & \log(x) / \log(10)
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/log10.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref log10.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin sin$$
|
||||
$spell
|
||||
sin
|
||||
$$
|
||||
|
||||
$section The Sine Function: sin$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = sin(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{sin}^{(1)} (x) & = & \cos(x)
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/sin.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref sin.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin sinh$$
|
||||
$spell
|
||||
sinh
|
||||
$$
|
||||
|
||||
$section The Hyperbolic Sine Function: sinh$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = sinh(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{sinh}^{(1)} (x) & = & \cosh(x)
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/sinh.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref sinh.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin sqrt$$
|
||||
$spell
|
||||
sqrt
|
||||
$$
|
||||
|
||||
$section The Square Root Function: sqrt$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = sqrt(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{sqrt}^{(1)} (x) & = & \frac{1}{2 \R{sqrt} (x) }
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/sqrt.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref sqrt.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin tan$$
|
||||
$spell
|
||||
tan
|
||||
$$
|
||||
|
||||
$section The Tangent Function: tan$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = tan(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{tan}^{(1)} (x) & = & 1 + \tan (x)^2
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/tan.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref tan.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
$begin tanh$$
|
||||
$spell
|
||||
tanh
|
||||
$$
|
||||
|
||||
$section The Hyperbolic Tangent Function: tanh$$
|
||||
|
||||
$head Syntax$$
|
||||
$icode%y% = tanh(%x%)%$$
|
||||
|
||||
$head x, y$$
|
||||
See the $cref/possible types/unary_standard_math/Possible Types/$$
|
||||
for a unary standard math function.
|
||||
|
||||
$head Atomic$$
|
||||
This is an $cref/atomic operation/glossary/Operation/Atomic/$$.
|
||||
|
||||
$head Derivative$$
|
||||
$latex \[
|
||||
\begin{array}{lcr}
|
||||
\R{tanh}^{(1)} (x) & = & 1 - \tanh (x)^2
|
||||
\end{array}
|
||||
\] $$
|
||||
|
||||
$head Example$$
|
||||
$children%
|
||||
example/general/tanh.cpp
|
||||
%$$
|
||||
The file
|
||||
$cref tanh.cpp$$
|
||||
contains an example and test of this function.
|
||||
It returns true if it succeeds and false otherwise.
|
||||
|
||||
$end
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*!
|
||||
\file std_math_98.hpp
|
||||
Define AD<Base> standard math functions (using their Base versions)
|
||||
*/
|
||||
|
||||
/*!
|
||||
\def CPPAD_STANDARD_MATH_UNARY_AD(Name, Op)
|
||||
Defines function Name with argument type AD<Base> and tape operation Op
|
||||
|
||||
The macro defines the function x.Name() where x has type AD<Base>.
|
||||
It then uses this funciton to define Name(x) where x has type
|
||||
AD<Base> or VecAD_reference<Base>.
|
||||
|
||||
If x is a variable, the tape unary operator Op is used
|
||||
to record the operation and the result is identified as correspoding
|
||||
to this operation; i.e., Name(x).taddr_ idendifies the operation and
|
||||
Name(x).tape_id_ identifies the tape.
|
||||
|
||||
This macro is used to define AD<Base> versions of
|
||||
acos, asin, atan, cos, cosh, exp, fabs, log, sin, sinh, sqrt, tan, tanh.
|
||||
*/
|
||||
|
||||
# define CPPAD_STANDARD_MATH_UNARY_AD(Name, Op) \
|
||||
template <class Base> \
|
||||
inline AD<Base> Name(const AD<Base> &x) \
|
||||
{ return x.Name##_me(); } \
|
||||
template <class Base> \
|
||||
inline AD<Base> AD<Base>::Name##_me (void) const \
|
||||
{ \
|
||||
AD<Base> result; \
|
||||
result.value_ = CppAD::Name(value_); \
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) ); \
|
||||
\
|
||||
if( Variable(*this) ) \
|
||||
{ CPPAD_ASSERT_UNKNOWN( NumArg(Op) == 1 ); \
|
||||
local::ADTape<Base> *tape = tape_this(); \
|
||||
tape->Rec_.PutArg(taddr_); \
|
||||
result.taddr_ = tape->Rec_.PutOp(Op); \
|
||||
result.tape_id_ = tape->id_; \
|
||||
} \
|
||||
return result; \
|
||||
} \
|
||||
template <class Base> \
|
||||
inline AD<Base> Name(const VecAD_reference<Base> &x) \
|
||||
{ return x.ADBase().Name##_me(); }
|
||||
|
||||
// BEGIN CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(acos, local::AcosOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(asin, local::AsinOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(atan, local::AtanOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(cos, local::CosOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(cosh, local::CoshOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(exp, local::ExpOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(fabs, local::AbsOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(log, local::LogOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(sin, local::SinOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(sinh, local::SinhOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(sqrt, local::SqrtOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(tan, local::TanOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(tanh, local::TanhOp)
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(asinh, local::AsinhOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(acosh, local::AcoshOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(atanh, local::AtanhOp)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(expm1, local::Expm1Op)
|
||||
CPPAD_STANDARD_MATH_UNARY_AD(log1p, local::Log1pOp)
|
||||
# endif
|
||||
|
||||
# if CPPAD_USE_CPLUSPLUS_2011
|
||||
// Error function is a special case
|
||||
template <class Base>
|
||||
inline AD<Base> erf(const AD<Base> &x)
|
||||
{ return x.erf_me(); }
|
||||
template <class Base>
|
||||
inline AD<Base> AD<Base>::erf_me (void) const
|
||||
{
|
||||
AD<Base> result;
|
||||
result.value_ = CppAD::erf(value_);
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||
|
||||
if( Variable(*this) )
|
||||
{ CPPAD_ASSERT_UNKNOWN( local::NumArg(local::ErfOp) == 3 );
|
||||
local::ADTape<Base> *tape = tape_this();
|
||||
// arg[0] = argument to erf function
|
||||
tape->Rec_.PutArg(taddr_);
|
||||
// arg[1] = zero
|
||||
addr_t p = tape->Rec_.PutPar( Base(0.0) );
|
||||
tape->Rec_.PutArg(p);
|
||||
// arg[2] = 2 / sqrt(pi)
|
||||
p = tape->Rec_.PutPar(Base(
|
||||
1.0 / std::sqrt( std::atan(1.0) )
|
||||
));
|
||||
tape->Rec_.PutArg(p);
|
||||
//
|
||||
result.taddr_ = tape->Rec_.PutOp(local::ErfOp);
|
||||
result.tape_id_ = tape->id_;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
template <class Base>
|
||||
inline AD<Base> erf(const VecAD_reference<Base> &x)
|
||||
{ return x.ADBase().erf_me(); }
|
||||
# endif
|
||||
|
||||
/*!
|
||||
Compute the log of base 10 of x where has type AD<Base>
|
||||
|
||||
\tparam Base
|
||||
is the base type (different from base for log)
|
||||
for this AD type, see base_require.
|
||||
|
||||
\param x
|
||||
is the argument for the log10 function.
|
||||
|
||||
\result
|
||||
if the result is y, then \f$ x = 10^y \f$.
|
||||
*/
|
||||
template <class Base>
|
||||
inline AD<Base> log10(const AD<Base> &x)
|
||||
{ return CppAD::log(x) / CppAD::log( Base(10) ); }
|
||||
template <class Base>
|
||||
inline AD<Base> log10(const VecAD_reference<Base> &x)
|
||||
{ return CppAD::log(x.ADBase()) / CppAD::log( Base(10) ); }
|
||||
}
|
||||
|
||||
# undef CPPAD_STANDARD_MATH_UNARY_AD
|
||||
|
||||
# endif
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
// $Id$
|
||||
# ifndef CPPAD_CORE_SUB_HPP
|
||||
# define CPPAD_CORE_SUB_HPP
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-16 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 CppAD namespace
|
||||
namespace CppAD {
|
||||
|
||||
template <class Base>
|
||||
AD<Base> operator - (const AD<Base> &left , const AD<Base> &right)
|
||||
{
|
||||
// compute the Base part
|
||||
AD<Base> result;
|
||||
result.value_ = left.value_ - right.value_;
|
||||
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||
|
||||
// check if there is a recording in progress
|
||||
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||
if( tape == CPPAD_NULL )
|
||||
return result;
|
||||
tape_id_t tape_id = tape->id_;
|
||||
|
||||
// tape_id cannot match the default value for tape_id_; i.e., 0
|
||||
CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
|
||||
bool var_left = left.tape_id_ == tape_id;
|
||||
bool var_right = right.tape_id_ == tape_id;
|
||||
|
||||
if( var_left )
|
||||
{ if( var_right )
|
||||
{ // result = variable - variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubvvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubvvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::SubvvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
else if( IdenticalZero(right.value_) )
|
||||
{ // result = variable - 0
|
||||
result.make_variable(left.tape_id_, left.taddr_);
|
||||
}
|
||||
else
|
||||
{ // result = variable - parameter
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubvpOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubvpOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(right.value_);
|
||||
tape->Rec_.PutArg(left.taddr_, p);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::SubvpOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
}
|
||||
else if( var_right )
|
||||
{ // result = parameter - variable
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::SubpvOp) == 1 );
|
||||
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::SubpvOp) == 2 );
|
||||
|
||||
// put operand addresses in tape
|
||||
addr_t p = tape->Rec_.PutPar(left.value_);
|
||||
tape->Rec_.PutArg(p, right.taddr_);
|
||||
// put operator in the tape
|
||||
result.taddr_ = tape->Rec_.PutOp(local::SubpvOp);
|
||||
// make result a variable
|
||||
result.tape_id_ = tape_id;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// convert other cases into the case above
|
||||
CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(-)
|
||||
|
||||
} // END CppAD namespace
|
||||
|
||||
# endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user