build(CppAD): brought in CppAD for autodiff
we need an autodiff library at some point (or we need to roll our own but I do not think that makes sense). CppAD is well tested and header only and easy to include. It is also Liscene compatible with GPL v3.0. Here we bring it in as a dependency
This commit is contained in:
11
build-config/cppad/COPYING
Normal file
11
build-config/cppad/COPYING
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
-----------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
184
build-config/cppad/include/cppad/CMakeLists.txt
Normal file
184
build-config/cppad/include/cppad/CMakeLists.txt
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
#
|
||||||
|
# CppAD is distributed under the terms of the
|
||||||
|
# Eclipse Public License Version 2.0.
|
||||||
|
#
|
||||||
|
# This Source Code may also be made available under the following
|
||||||
|
# Secondary License when the conditions for such availability set forth
|
||||||
|
# in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
# GNU General Public License, Version 2.0 or later.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Configure the CppAD include file directory
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# check_match
|
||||||
|
MACRO(check_match match_variable match_constant output_variable)
|
||||||
|
STRING(COMPARE EQUAL ${${match_variable}} ${match_constant} match_flag )
|
||||||
|
IF( match_flag )
|
||||||
|
SET(${output_variable} 1)
|
||||||
|
ELSE( match_flag )
|
||||||
|
SET(${output_variable} 0)
|
||||||
|
ENDIF( match_flag )
|
||||||
|
print_variable(${output_variable})
|
||||||
|
ENDMACRO(check_match)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# compiler_has_conversion_warn
|
||||||
|
SET( clang_or_gnu 0 )
|
||||||
|
IF( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
SET(clang_or_gnu 1)
|
||||||
|
ENDIF( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||||
|
IF( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" )
|
||||||
|
SET(clang_or_gnu 1)
|
||||||
|
ENDIF( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" )
|
||||||
|
IF( clang_or_gnu )
|
||||||
|
SET(backup "${cppad_cxx_flags}")
|
||||||
|
SET(cppad_cxx_flags "${backup} -Wfloat-conversion -Wconversion -Werror")
|
||||||
|
#
|
||||||
|
SET(source "int main(void) { return 0; }")
|
||||||
|
run_source_test("${source}" compiler_has_conversion_warn )
|
||||||
|
#
|
||||||
|
SET(cppad_cxx_flags "${backup}")
|
||||||
|
ELSE( clang_or_gnu )
|
||||||
|
SET( compiler_has_conversion_warn 0 )
|
||||||
|
ENDIF( clang_or_gnu )
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# cppad_boostvector, cppad_cppadvector, cppad_eigenvector, cppad_stdvector
|
||||||
|
#
|
||||||
|
check_match(cppad_testvector boost cppad_boostvector)
|
||||||
|
check_match(cppad_testvector cppad cppad_cppadvector)
|
||||||
|
check_match(cppad_testvector eigen cppad_eigenvector)
|
||||||
|
check_match(cppad_testvector std cppad_stdvector)
|
||||||
|
IF( NOT cppad_boostvector )
|
||||||
|
IF( NOT cppad_cppadvector )
|
||||||
|
IF( NOT cppad_eigenvector )
|
||||||
|
IF( NOT cppad_stdvector )
|
||||||
|
MESSAGE(FATAL_ERROR
|
||||||
|
"cppad_testvector not one of following: boost, cppad, eigen, std."
|
||||||
|
"This should have been found earlier, please report this as a bug."
|
||||||
|
)
|
||||||
|
ENDIF( NOT cppad_stdvector )
|
||||||
|
ENDIF( NOT cppad_eigenvector )
|
||||||
|
ENDIF( NOT cppad_cppadvector )
|
||||||
|
ENDIF( NOT cppad_boostvector )
|
||||||
|
|
||||||
|
IF( cppad_boostvector )
|
||||||
|
# FIND_PACKAGE(Boost) done by ../CMakeLists.txt
|
||||||
|
IF( NOT Boost_FOUND )
|
||||||
|
MESSAGE(FATAL_ERROR
|
||||||
|
"cppad_testvector == boost but cannot find boost include files"
|
||||||
|
)
|
||||||
|
ENDIF( NOT Boost_FOUND )
|
||||||
|
ENDIF( cppad_boostvector )
|
||||||
|
#
|
||||||
|
IF( cppad_eigenvector )
|
||||||
|
IF( NOT include_eigen )
|
||||||
|
MESSAGE(FATAL_ERROR
|
||||||
|
"cppad_testvector == eigen but eigen_prefix is not specified"
|
||||||
|
)
|
||||||
|
ENDIF( NOT include_eigen )
|
||||||
|
ENDIF( cppad_eigenvector )
|
||||||
|
#
|
||||||
|
print_variable(cppad_cplusplus_201100_ok)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# cppad_has_gettimeofday
|
||||||
|
#
|
||||||
|
SET(source "
|
||||||
|
# include<sys/time.h>
|
||||||
|
int main(void)
|
||||||
|
{ struct timeval time;
|
||||||
|
gettimeofday(&time, 0);
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
)
|
||||||
|
run_source_test("${source}" cppad_has_gettimeofday)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# cppad_tape_addr_type, cppad_tape_id_type
|
||||||
|
#
|
||||||
|
FOREACH(cmake_var cppad_tape_id_type cppad_tape_addr_type )
|
||||||
|
SET(source "
|
||||||
|
# include <limits>
|
||||||
|
int main(void)
|
||||||
|
{ bool is_unsigned = ! std::numeric_limits<${${cmake_var}}>::is_signed;
|
||||||
|
return int(! is_unsigned);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
)
|
||||||
|
run_source_test("${source}" ${cmake_var}_is_unsigned)
|
||||||
|
IF( ${cmake_var}_is_unsigned STREQUAL 0 )
|
||||||
|
MESSAGE(STATUS
|
||||||
|
"Warning: using a signed ${cmake_var} is for CppAD developers only !"
|
||||||
|
)
|
||||||
|
ENDIF( ${cmake_var}_is_unsigned STREQUAL 0 )
|
||||||
|
ENDFOREACH( cmake_var )
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# check that cppad_max_num_threads is >= 4
|
||||||
|
#
|
||||||
|
SET(CMAKE_REQUIRED_DERINITIONS "")
|
||||||
|
SET(CMAKE_REQUIRED_INCLUDES "")
|
||||||
|
SET(CMAKE_REQUIRED_LIBRARIES "")
|
||||||
|
SET(CMAKE_REQUIRED_FLAGS "")
|
||||||
|
SET(source "
|
||||||
|
int main(void)
|
||||||
|
{ const char* number = \"${cppad_max_num_threads}\";
|
||||||
|
int value = 0;
|
||||||
|
while( *number == ' ' )
|
||||||
|
number++;
|
||||||
|
while( '0' <= *number && *number <= '9' )
|
||||||
|
{ value = 10 * value + (int)(*number - '0');
|
||||||
|
number++;
|
||||||
|
}
|
||||||
|
while( *number == ' ' )
|
||||||
|
number++;
|
||||||
|
if( *number != char(0) )
|
||||||
|
return 1;
|
||||||
|
if( value < 4 )
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" )
|
||||||
|
# Using CHECK_CXX_SOURCE_RUNS directly (instead of run_source_test).
|
||||||
|
IF( DEFINED cppad_max_num_threads_is_integer_ge_4 )
|
||||||
|
MESSAGE( ERROR
|
||||||
|
"cppad_max_num_threads_is_integer_ge_4 is defined before expected"
|
||||||
|
)
|
||||||
|
ENDIF( DEFINED cppad_max_num_threads_is_integer_ge_4 )
|
||||||
|
CHECK_CXX_SOURCE_RUNS("${source}" cppad_max_num_threads_is_integer_ge_4 )
|
||||||
|
IF( NOT cppad_max_num_threads_is_integer_ge_4 )
|
||||||
|
MESSAGE(FATAL_ERROR
|
||||||
|
"cppad_max_num_threads is not an integer greater than or equal 4"
|
||||||
|
)
|
||||||
|
ENDIF( NOT cppad_max_num_threads_is_integer_ge_4 )
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# cppad_has_mkstemp
|
||||||
|
#
|
||||||
|
SET(source "
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char pattern[] = \"/tmp/fileXXXXXX\";
|
||||||
|
int fd = mkstemp(pattern);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" )
|
||||||
|
run_source_test("${source}" cppad_has_mkstemp )
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# cppad_has_tmpname_s
|
||||||
|
#
|
||||||
|
SET(source "
|
||||||
|
# include <stdio.h>
|
||||||
|
int main(void)
|
||||||
|
{ char filename[L_tmpnam_s ];
|
||||||
|
if( tmpnam_s(filename, L_tmpnam_s ) != 0 )
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" )
|
||||||
|
run_source_test("${source}" cppad_has_tmpnam_s )
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# configure.hpp
|
||||||
|
CONFIGURE_FILE(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/configure.hpp.in
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/configure.hpp
|
||||||
|
)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
177
build-config/cppad/include/cppad/base_require.hpp
Normal file
177
build-config/cppad/include/cppad/base_require.hpp
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
# ifndef CPPAD_BASE_REQUIRE_HPP
|
||||||
|
# define CPPAD_BASE_REQUIRE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin base_require$$
|
||||||
|
$spell
|
||||||
|
azmul
|
||||||
|
ostream
|
||||||
|
alloc
|
||||||
|
eps
|
||||||
|
std
|
||||||
|
cppad.hpp
|
||||||
|
namespace
|
||||||
|
bool
|
||||||
|
const
|
||||||
|
CppAD
|
||||||
|
enum
|
||||||
|
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$$.
|
||||||
|
In the documentation, The notation $latex \B{R}$$ denotes
|
||||||
|
the field corresponding to the base type.
|
||||||
|
Multiplication must be commutative for this field,
|
||||||
|
but it need not be the reals; e.g., the complex numbers.
|
||||||
|
|
||||||
|
$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%
|
||||||
|
include/cppad/core/base_cond_exp.hpp%
|
||||||
|
omh/base_require/base_identical.omh%
|
||||||
|
omh/base_require/base_ordered.omh%
|
||||||
|
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%
|
||||||
|
omh/base_require/base_example.omh
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
|
||||||
|
// definitions that must come before base implementations
|
||||||
|
# include <cppad/utility/error_handler.hpp>
|
||||||
|
# include <cppad/local/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
|
||||||
238
build-config/cppad/include/cppad/configure.hpp
Normal file
238
build-config/cppad/include/cppad/configure.hpp
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
# ifndef CPPAD_CONFIGURE_HPP
|
||||||
|
# define CPPAD_CONFIGURE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
$begin configure.hpp$$
|
||||||
|
$spell
|
||||||
|
noexcept
|
||||||
|
pragmas
|
||||||
|
unreferenced
|
||||||
|
CppAD
|
||||||
|
cppad
|
||||||
|
yyyymmdd
|
||||||
|
yyyy
|
||||||
|
mm
|
||||||
|
dd
|
||||||
|
adolc
|
||||||
|
cmake
|
||||||
|
colpack
|
||||||
|
eigen
|
||||||
|
ipopt
|
||||||
|
gettimeofday
|
||||||
|
namespace
|
||||||
|
mkstemp
|
||||||
|
tmpnam
|
||||||
|
nullptr
|
||||||
|
sizeof
|
||||||
|
std
|
||||||
|
hpp
|
||||||
|
addr
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Preprocessor Symbols Set By CMake Command$$
|
||||||
|
|
||||||
|
$head CPPAD_COMPILER_HAS_CONVERSION_WARN$$
|
||||||
|
is the compiler a variant of g++ and has conversion warnings
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_COMPILER_HAS_CONVERSION_WARN 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_DISABLE_SOME_MICROSOFT_COMPILER_WARNINGS$$
|
||||||
|
This macro is only used to document the pragmas that disables the
|
||||||
|
follow warnings:
|
||||||
|
|
||||||
|
$subhead C4100$$
|
||||||
|
unreferenced formal parameter.
|
||||||
|
|
||||||
|
$subhead C4127$$
|
||||||
|
conditional expression is constant.
|
||||||
|
|
||||||
|
$srccode%hpp% */
|
||||||
|
# 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
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_USE_CPLUSPLUS_2011$$
|
||||||
|
Deprecated 2020-12-03:
|
||||||
|
Should CppAD use C++11 features. This is always 1 (for true).
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_USE_CPLUSPLUS_2011 1
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_PACKAGE_STRING$$
|
||||||
|
cppad-yyyymmdd as a C string where yyyy is year, mm is month, and dd is day.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_PACKAGE_STRING "cppad-20210000.8"
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_ADOLC$$
|
||||||
|
Was include_adolc=true on the cmake command line.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_ADOLC 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_COLPACK$$
|
||||||
|
Was a colpack_prefix specified on the cmake command line.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_COLPACK 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_EIGEN$$
|
||||||
|
Was include_eigen=true on the cmake command line.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_EIGEN 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_IPOPT$$
|
||||||
|
Was include_ipopt=true on the cmake command line.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_IPOPT 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_DEPRECATED$$
|
||||||
|
This symbol is not currently being used.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_DEPRECATED
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_BOOSTVECTOR 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_CPPADVECTOR 1
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_STDVECTOR 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_EIGENVECTOR 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_GETTIMEOFDAY$$
|
||||||
|
If this symbol is one, and _MSC_VER is not defined,
|
||||||
|
this system supports the gettimeofday function.
|
||||||
|
Otherwise, this symbol should be zero.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_GETTIMEOFDAY 1
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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 std::numeric_limits,
|
||||||
|
the <= operator,
|
||||||
|
and conversion to 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 addr_t in the CppAD namespace.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_TAPE_ADDR_TYPE unsigned int
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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 std::numeric_limits,
|
||||||
|
the <= operator,
|
||||||
|
and conversion to 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 tape_id_t in the CppAD namespace.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_TAPE_ID_TYPE unsigned int
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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,
|
||||||
|
$srccode%hpp% */
|
||||||
|
# ifndef CPPAD_MAX_NUM_THREADS
|
||||||
|
# define CPPAD_MAX_NUM_THREADS 48
|
||||||
|
# endif
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_MKSTEMP$$
|
||||||
|
It true, mkstemp works in C++ on this system.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_MKSTEMP 1
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_TMPNAM_S$$
|
||||||
|
It true, tmpnam_s works in C++ on this system.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_TMPNAM_S 0
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_NULL$$
|
||||||
|
Deprecated 2020-12-03:
|
||||||
|
This preprocessor symbol was used for a null pointer before c++11.
|
||||||
|
Replace it by $code nullptr$$.
|
||||||
|
|
||||||
|
$head CPPAD_NOEXCEPT$$
|
||||||
|
Deprecated 2020-12-03:
|
||||||
|
This preprocessor symbol was used for no exception before c++11,
|
||||||
|
replace it by $code noexcept$$.
|
||||||
|
|
||||||
|
$subhead CPPAD_NDEBUG_NOEXCEPT$$
|
||||||
|
This preprocessor symbol is
|
||||||
|
$code noexcept$$ when C++11 is available and $code NDEBUG$$ is defined.
|
||||||
|
Otherwise it is empty.
|
||||||
|
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
// -------------------------------------------------
|
||||||
|
# define CPPAD_NULL nullptr
|
||||||
|
# define CPPAD_NOEXCEPT noexcept
|
||||||
|
//
|
||||||
|
# ifdef NDEBUG
|
||||||
|
# define CPPAD_NDEBUG_NOEXCEPT noexcept
|
||||||
|
# else
|
||||||
|
# define CPPAD_NDEBUG_NOEXCEPT
|
||||||
|
# endif
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
# endif
|
||||||
238
build-config/cppad/include/cppad/configure.hpp.in
Normal file
238
build-config/cppad/include/cppad/configure.hpp.in
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
# ifndef CPPAD_CONFIGURE_HPP
|
||||||
|
# define CPPAD_CONFIGURE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
$begin configure.hpp$$
|
||||||
|
$spell
|
||||||
|
noexcept
|
||||||
|
pragmas
|
||||||
|
unreferenced
|
||||||
|
CppAD
|
||||||
|
cppad
|
||||||
|
yyyymmdd
|
||||||
|
yyyy
|
||||||
|
mm
|
||||||
|
dd
|
||||||
|
adolc
|
||||||
|
cmake
|
||||||
|
colpack
|
||||||
|
eigen
|
||||||
|
ipopt
|
||||||
|
gettimeofday
|
||||||
|
namespace
|
||||||
|
mkstemp
|
||||||
|
tmpnam
|
||||||
|
nullptr
|
||||||
|
sizeof
|
||||||
|
std
|
||||||
|
hpp
|
||||||
|
addr
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Preprocessor Symbols Set By CMake Command$$
|
||||||
|
|
||||||
|
$head CPPAD_COMPILER_HAS_CONVERSION_WARN$$
|
||||||
|
is the compiler a variant of g++ and has conversion warnings
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_COMPILER_HAS_CONVERSION_WARN @compiler_has_conversion_warn@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_DISABLE_SOME_MICROSOFT_COMPILER_WARNINGS$$
|
||||||
|
This macro is only used to document the pragmas that disables the
|
||||||
|
follow warnings:
|
||||||
|
|
||||||
|
$subhead C4100$$
|
||||||
|
unreferenced formal parameter.
|
||||||
|
|
||||||
|
$subhead C4127$$
|
||||||
|
conditional expression is constant.
|
||||||
|
|
||||||
|
$srccode%hpp% */
|
||||||
|
# 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
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_USE_CPLUSPLUS_2011$$
|
||||||
|
Deprecated 2020-12-03:
|
||||||
|
Should CppAD use C++11 features. This is always 1 (for true).
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_USE_CPLUSPLUS_2011 1
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_PACKAGE_STRING$$
|
||||||
|
cppad-yyyymmdd as a C string where yyyy is year, mm is month, and dd is day.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_PACKAGE_STRING "cppad-@cppad_version@"
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_ADOLC$$
|
||||||
|
Was include_adolc=true on the cmake command line.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_ADOLC @cppad_has_adolc@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_COLPACK$$
|
||||||
|
Was a colpack_prefix specified on the cmake command line.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_COLPACK @cppad_has_colpack@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_EIGEN$$
|
||||||
|
Was include_eigen=true on the cmake command line.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_EIGEN @cppad_has_eigen@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_IPOPT$$
|
||||||
|
Was include_ipopt=true on the cmake command line.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_IPOPT @cppad_has_ipopt@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_DEPRECATED$$
|
||||||
|
This symbol is not currently being used.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_DEPRECATED @cppad_deprecated_01@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_BOOSTVECTOR @cppad_boostvector@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_CPPADVECTOR @cppad_cppadvector@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_STDVECTOR @cppad_stdvector@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_EIGENVECTOR @cppad_eigenvector@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_GETTIMEOFDAY$$
|
||||||
|
If this symbol is one, and _MSC_VER is not defined,
|
||||||
|
this system supports the gettimeofday function.
|
||||||
|
Otherwise, this symbol should be zero.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_GETTIMEOFDAY @cppad_has_gettimeofday@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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 std::numeric_limits,
|
||||||
|
the <= operator,
|
||||||
|
and conversion to 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 addr_t in the CppAD namespace.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_TAPE_ADDR_TYPE @cppad_tape_addr_type@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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 std::numeric_limits,
|
||||||
|
the <= operator,
|
||||||
|
and conversion to 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 tape_id_t in the CppAD namespace.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_TAPE_ID_TYPE @cppad_tape_id_type@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head 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,
|
||||||
|
$srccode%hpp% */
|
||||||
|
# ifndef CPPAD_MAX_NUM_THREADS
|
||||||
|
# define CPPAD_MAX_NUM_THREADS @cppad_max_num_threads@
|
||||||
|
# endif
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_MKSTEMP$$
|
||||||
|
It true, mkstemp works in C++ on this system.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_MKSTEMP @cppad_has_mkstemp@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_HAS_TMPNAM_S$$
|
||||||
|
It true, tmpnam_s works in C++ on this system.
|
||||||
|
$srccode%hpp% */
|
||||||
|
# define CPPAD_HAS_TMPNAM_S @cppad_has_tmpnam_s@
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head CPPAD_NULL$$
|
||||||
|
Deprecated 2020-12-03:
|
||||||
|
This preprocessor symbol was used for a null pointer before c++11.
|
||||||
|
Replace it by $code nullptr$$.
|
||||||
|
|
||||||
|
$head CPPAD_NOEXCEPT$$
|
||||||
|
Deprecated 2020-12-03:
|
||||||
|
This preprocessor symbol was used for no exception before c++11,
|
||||||
|
replace it by $code noexcept$$.
|
||||||
|
|
||||||
|
$subhead CPPAD_NDEBUG_NOEXCEPT$$
|
||||||
|
This preprocessor symbol is
|
||||||
|
$code noexcept$$ when C++11 is available and $code NDEBUG$$ is defined.
|
||||||
|
Otherwise it is empty.
|
||||||
|
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
// -------------------------------------------------
|
||||||
|
# define CPPAD_NULL nullptr
|
||||||
|
# define CPPAD_NOEXCEPT noexcept
|
||||||
|
//
|
||||||
|
# ifdef NDEBUG
|
||||||
|
# define CPPAD_NDEBUG_NOEXCEPT noexcept
|
||||||
|
# else
|
||||||
|
# define CPPAD_NDEBUG_NOEXCEPT
|
||||||
|
# endif
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
# endif
|
||||||
58
build-config/cppad/include/cppad/core/abort_recording.hpp
Normal file
58
build-config/cppad/include/cppad/core/abort_recording.hpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# ifndef CPPAD_CORE_ABORT_RECORDING_HPP
|
||||||
|
# define CPPAD_CORE_ABORT_RECORDING_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin abort_recording$$
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Abort Recording of an Operation Sequence$$
|
||||||
|
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$end
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace CppAD {
|
||||||
|
template <class Base>
|
||||||
|
void AD<Base>::abort_recording(void)
|
||||||
|
{ local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape != nullptr )
|
||||||
|
AD<Base>::tape_manage(delete_tape_manage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
132
build-config/cppad/include/cppad/core/abs.hpp
Normal file
132
build-config/cppad/include/cppad/core/abs.hpp
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# ifndef CPPAD_CORE_ABS_HPP
|
||||||
|
# define CPPAD_CORE_ABS_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$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) );
|
||||||
|
|
||||||
|
// check if there is a recording in progress
|
||||||
|
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape == nullptr )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// check if operand is a constant parameter
|
||||||
|
if( tape_id_ != tape->id_ )
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if(ad_type_ == dynamic_enum)
|
||||||
|
{ // dynamic paramter argument
|
||||||
|
result.taddr_ = tape->Rec_.put_dyn_par(
|
||||||
|
result.value_, local::abs_dyn, taddr_
|
||||||
|
);
|
||||||
|
result.tape_id_ = tape_id_;
|
||||||
|
result.ad_type_ = dynamic_enum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // variable argument
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AbsOp) == 1 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AbsOp) == 1 );
|
||||||
|
|
||||||
|
// 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_;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
AD<Base> abs(const AD<Base> &x)
|
||||||
|
{ return x.abs_me(); }
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
AD<Base> abs(const VecAD_reference<Base> &x)
|
||||||
|
{ return x.ADBase().abs_me(); }
|
||||||
|
|
||||||
|
} // END CppAD namespace
|
||||||
|
|
||||||
|
# endif
|
||||||
959
build-config/cppad/include/cppad/core/abs_normal_fun.hpp
Normal file
959
build-config/cppad/include/cppad/core/abs_normal_fun.hpp
Normal file
@@ -0,0 +1,959 @@
|
|||||||
|
# ifndef CPPAD_CORE_ABS_NORMAL_FUN_HPP
|
||||||
|
# define CPPAD_CORE_ABS_NORMAL_FUN_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-21 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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%
|
||||||
|
const 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.
|
||||||
|
|
||||||
|
$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( x - \hat{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/example_abs_normal/Reference/$$.
|
||||||
|
|
||||||
|
$children%example/abs_normal/abs_normal.omh
|
||||||
|
%$$
|
||||||
|
$head Example$$
|
||||||
|
The file $cref abs_get_started.cpp$$ contains
|
||||||
|
an example and test using this operation.
|
||||||
|
The section $cref example_abs_normal$$
|
||||||
|
has a links to all the abs normal examples.
|
||||||
|
|
||||||
|
$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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# ifndef NDEBUG
|
||||||
|
# define CPPAD_J_PAR_EQUAL_REC j_par = (size_t) rec
|
||||||
|
# else
|
||||||
|
# define CPPAD_J_PAR_EQUAL_REC rec
|
||||||
|
# endif
|
||||||
|
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
void ADFun<Base,RecBase>::abs_normal_fun(ADFun& g, ADFun& a) const
|
||||||
|
{ 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 = nullptr; // arguments for this operator
|
||||||
|
size_t i_var; // variable index for this operator
|
||||||
|
local::play::const_sequential_iterator itr = play_.begin();
|
||||||
|
itr.op_info(op, arg, i_var);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( op == BeginOp );
|
||||||
|
//
|
||||||
|
bool more_operators = true;
|
||||||
|
while( op != EndOp )
|
||||||
|
{
|
||||||
|
// next op
|
||||||
|
(++itr).op_info(op, arg, 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;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Forward sweep to create new recording
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// dynamic parameter information in player
|
||||||
|
const pod_vector<bool>& dyn_par_is( play_.dyn_par_is() );
|
||||||
|
const pod_vector<opcode_t>& dyn_par_op( play_.dyn_par_op() );
|
||||||
|
const pod_vector<addr_t>& dyn_par_arg( play_.dyn_par_arg() );
|
||||||
|
//
|
||||||
|
// recorder for new operation sequence
|
||||||
|
recorder<Base> rec;
|
||||||
|
//
|
||||||
|
// number of parameters in both operation sequences
|
||||||
|
size_t num_par = play_.num_par_rec();
|
||||||
|
//
|
||||||
|
// number of independent dynamic parameters
|
||||||
|
size_t num_dynamic_ind = play_.num_dynamic_par();
|
||||||
|
rec.set_num_dynamic_ind(num_dynamic_ind);
|
||||||
|
//
|
||||||
|
// set all parameter to be exactly the same in rec as in play
|
||||||
|
size_t i_dyn = 0; // dynamic parameter index
|
||||||
|
size_t i_arg = 0; // dynamic parameter operator argument index
|
||||||
|
for(size_t i_par = 0; i_par < num_par; ++i_par)
|
||||||
|
{
|
||||||
|
# ifndef NDEBUG
|
||||||
|
size_t j_par = 0;
|
||||||
|
# endif
|
||||||
|
// value of this parameter
|
||||||
|
Base par = play_.GetPar(i_par);
|
||||||
|
if( ! dyn_par_is[i_par] )
|
||||||
|
CPPAD_J_PAR_EQUAL_REC.put_con_par(par);
|
||||||
|
else
|
||||||
|
{ // operator for this dynamic parameter
|
||||||
|
op_code_dyn op_dyn = op_code_dyn( dyn_par_op[i_dyn] );
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
op_dyn != local::atom_dyn,
|
||||||
|
"abs_normal_fun: not yet implemented for "
|
||||||
|
"atomic dynamic parameter functions"
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// number of arguments for this dynamic parameter
|
||||||
|
size_t n_arg = num_arg_dyn(op_dyn);
|
||||||
|
//
|
||||||
|
switch(n_arg)
|
||||||
|
{ case 0:
|
||||||
|
CPPAD_J_PAR_EQUAL_REC.put_dyn_par(par, op_dyn);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
CPPAD_J_PAR_EQUAL_REC.put_dyn_par(par, op_dyn,
|
||||||
|
dyn_par_arg[i_arg + 0]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
CPPAD_J_PAR_EQUAL_REC.put_dyn_par(par, op_dyn,
|
||||||
|
dyn_par_arg[i_arg + 0] ,
|
||||||
|
dyn_par_arg[i_arg + 1]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
CPPAD_J_PAR_EQUAL_REC.put_dyn_cond_exp(par,
|
||||||
|
CompareOp( dyn_par_arg[i_arg + 0] ) ,
|
||||||
|
dyn_par_arg[i_arg + 1] ,
|
||||||
|
dyn_par_arg[i_arg + 2] ,
|
||||||
|
dyn_par_arg[i_arg + 3] ,
|
||||||
|
dyn_par_arg[i_arg + 4]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
CPPAD_ASSERT_UNKNOWN(false);
|
||||||
|
}
|
||||||
|
++i_dyn;
|
||||||
|
i_arg += n_arg;
|
||||||
|
}
|
||||||
|
CPPAD_ASSERT_UNKNOWN( j_par == i_par );
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// 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(
|
||||||
|
size_t( (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
|
||||||
|
itr = play_.begin();
|
||||||
|
itr.op_info(op, arg, 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 )
|
||||||
|
(++itr).op_info(op, arg, 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];
|
||||||
|
//
|
||||||
|
// 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] = arg[0]; // parameter
|
||||||
|
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:
|
||||||
|
case ErfcOp:
|
||||||
|
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( arg[1] ); // parameter
|
||||||
|
rec.PutArg( arg[2] ); // parameter
|
||||||
|
f2g_var[i_var] = rec.PutOp(op);
|
||||||
|
break;
|
||||||
|
// --------------------------------------------------------------
|
||||||
|
// Binary operators, left variable, right parameter, one result
|
||||||
|
case SubvpOp:
|
||||||
|
case DivvpOp:
|
||||||
|
case PowvpOp:
|
||||||
|
case ZmulvpOp:
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( op == PowvpOp )
|
||||||
|
{ CPPAD_ASSERT_NARG_NRES(op, 2, 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[0] ] ) < num_var );
|
||||||
|
new_arg[0] = f2g_var[ arg[0] ];
|
||||||
|
new_arg[1] = arg[1]; // parameter
|
||||||
|
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:
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( op == PowpvOp )
|
||||||
|
{ CPPAD_ASSERT_NARG_NRES(op, 2, 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
CPPAD_ASSERT_UNKNOWN( size_t( f2g_var[ arg[1] ] ) < num_var );
|
||||||
|
new_arg[0] = arg[0]; // parameter
|
||||||
|
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 PowvvOp:
|
||||||
|
case ZmulvvOp:
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( op == PowvvOp )
|
||||||
|
{ CPPAD_ASSERT_NARG_NRES(op, 2, 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_NARG_NRES(op, 2, 1);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
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] = arg[i]; // parameter
|
||||||
|
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] = arg[0]; // parameter
|
||||||
|
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] = arg[1]; // parameter
|
||||||
|
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] = arg[1]; // parameter
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// 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] = arg[3]; // parameter
|
||||||
|
}
|
||||||
|
new_arg[2] = rec.PutTxt( play_.GetTxt(size_t(arg[2])) );
|
||||||
|
new_arg[4] = rec.PutTxt( play_.GetTxt(size_t(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]; // parameter
|
||||||
|
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] = arg[1]; // parameter
|
||||||
|
new_arg[2] = arg[2]; // parameter
|
||||||
|
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] = arg[2]; // parameter
|
||||||
|
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] = arg[1]; // parameter
|
||||||
|
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;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
// atomic function call operators
|
||||||
|
|
||||||
|
case AFunOp:
|
||||||
|
CPPAD_ASSERT_NARG_NRES(op, 4, 0);
|
||||||
|
// atom_index, atom_old, atom_n, atom_m
|
||||||
|
rec.PutArg(arg[0], arg[1], arg[2], arg[3]);
|
||||||
|
rec.PutOp(AFunOp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FunapOp:
|
||||||
|
CPPAD_ASSERT_NARG_NRES(op, 1, 0);
|
||||||
|
new_arg[0] = arg[0]; // parameter
|
||||||
|
rec.PutArg(new_arg[0]);
|
||||||
|
rec.PutOp(FunapOp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FunavOp:
|
||||||
|
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(FunavOp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FunrpOp:
|
||||||
|
CPPAD_ASSERT_NARG_NRES(op, 1, 0);
|
||||||
|
new_arg[0] = arg[0]; // parameter
|
||||||
|
rec.PutArg(new_arg[0]);
|
||||||
|
rec.PutOp(FunrpOp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FunrvOp:
|
||||||
|
CPPAD_ASSERT_NARG_NRES(op, 0, 1);
|
||||||
|
f2g_var[i_var] = rec.PutOp(FunrvOp);
|
||||||
|
break;
|
||||||
|
// ---------------------------------------------------
|
||||||
|
|
||||||
|
// all cases should be handled above
|
||||||
|
default:
|
||||||
|
CPPAD_ASSERT_UNKNOWN(false);
|
||||||
|
}
|
||||||
|
if( more_operators )
|
||||||
|
(++itr).op_info(op, arg, 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_var_load_rec() == play_.num_var_load_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_.resize( 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] = size_t( 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] = size_t( 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] = size_t( 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] = size_t( 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_.clear();
|
||||||
|
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_recording(rec, n + s);
|
||||||
|
|
||||||
|
// resize subgraph_info_
|
||||||
|
g.subgraph_info_.resize(
|
||||||
|
g.ind_taddr_.size(), // n_ind
|
||||||
|
g.dep_taddr_.size(), // n_dep
|
||||||
|
g.play_.num_op_rec(), // n_op
|
||||||
|
g.play_.num_var_rec() // n_var
|
||||||
|
);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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_.clear();
|
||||||
|
a.num_order_taylor_ = 0;
|
||||||
|
a.cap_order_taylor_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// preprocessor symbols that are local to this file
|
||||||
|
# undef CPPAD_J_PAR_EQUAL_REC
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
# endif
|
||||||
311
build-config/cppad/include/cppad/core/ad.hpp
Normal file
311
build-config/cppad/include/cppad/core/ad.hpp
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
# ifndef CPPAD_CORE_AD_HPP
|
||||||
|
# define CPPAD_CORE_AD_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// 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_dyn.hpp>
|
||||||
|
# include <cppad/local/op_code_var.hpp>
|
||||||
|
# include <cppad/core/ad_type.hpp>
|
||||||
|
# include <cppad/local/record/recorder.hpp>
|
||||||
|
# include <cppad/local/play/player.hpp>
|
||||||
|
# include <cppad/local/ad_tape.hpp>
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
// tape_manage_enum
|
||||||
|
typedef enum {
|
||||||
|
new_tape_manage,
|
||||||
|
delete_tape_manage
|
||||||
|
}
|
||||||
|
tape_manage_enum;
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
class AD {
|
||||||
|
private :
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Base type value for this object
|
||||||
|
Base value_;
|
||||||
|
//
|
||||||
|
// tape for this object
|
||||||
|
tape_id_t tape_id_;
|
||||||
|
//
|
||||||
|
// tape address for this object
|
||||||
|
// (when tape_id is current tape for AD<Base>)
|
||||||
|
addr_t taddr_;
|
||||||
|
//
|
||||||
|
// sub-type for this object
|
||||||
|
// (when tape_id is current tape for AD<Base>)
|
||||||
|
ad_type_enum ad_type_;
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 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 ADVector>
|
||||||
|
friend void Independent(
|
||||||
|
ADVector& x ,
|
||||||
|
size_t abort_op_index ,
|
||||||
|
bool record_compare ,
|
||||||
|
ADVector& dynamic
|
||||||
|
);
|
||||||
|
|
||||||
|
// one argument functions
|
||||||
|
friend bool Constant <Base> (const AD<Base> &u);
|
||||||
|
friend bool Constant <Base> (const VecAD<Base> &u);
|
||||||
|
//
|
||||||
|
friend bool Dynamic <Base> (const AD<Base> &u);
|
||||||
|
friend bool Dynamic <Base> (const VecAD<Base> &u);
|
||||||
|
//
|
||||||
|
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);
|
||||||
|
//
|
||||||
|
friend unsigned short hash_code <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 IdenticalCon <Base> (const AD<Base> &x);
|
||||||
|
friend bool IdenticalZero <Base> (const AD<Base> &x);
|
||||||
|
friend bool IdenticalOne <Base> (const AD<Base> &x);
|
||||||
|
friend bool IdenticalEqualCon <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 local::recorder<Base>;
|
||||||
|
friend class ADFun<Base>;
|
||||||
|
friend class atomic_base<Base>;
|
||||||
|
friend class atomic_three<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
|
||||||
|
AD(void);
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
~AD(void) { }
|
||||||
|
|
||||||
|
// use default implicit copy constructor
|
||||||
|
// AD(const AD &x);
|
||||||
|
|
||||||
|
# ifdef CPPAD_FOR_TMB
|
||||||
|
// TMB would rather have implicit construction from double,
|
||||||
|
// CppAD uses default constructor and assignment to double instead.
|
||||||
|
AD(const double &d);
|
||||||
|
# else
|
||||||
|
// implicit construction from base type
|
||||||
|
AD(const Base &b);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// implicit contructor from VecAD<Base>::reference
|
||||||
|
AD(const VecAD_reference<Base> &x);
|
||||||
|
|
||||||
|
// explicit construction from some other type (depricated)
|
||||||
|
template <class T> explicit AD(const T &t);
|
||||||
|
|
||||||
|
// conversion from AD to Base type
|
||||||
|
friend Base Value <Base> (const AD<Base> &x);
|
||||||
|
|
||||||
|
// use default assignment operator
|
||||||
|
// AD& operator=(const AD &x);
|
||||||
|
|
||||||
|
// assingment from base type
|
||||||
|
AD& operator=(const Base &b);
|
||||||
|
|
||||||
|
// assignment from VecAD<Base>::reference
|
||||||
|
AD& operator=(const VecAD_reference<Base> &x);
|
||||||
|
|
||||||
|
// assignment from some other type
|
||||||
|
template <class T> AD& operator=(const T &right);
|
||||||
|
|
||||||
|
// compound assignment operators
|
||||||
|
AD& operator += (const AD &right);
|
||||||
|
AD& operator -= (const AD &right);
|
||||||
|
AD& operator *= (const AD &right);
|
||||||
|
AD& operator /= (const AD &right);
|
||||||
|
|
||||||
|
// unary operators
|
||||||
|
AD operator +(void) const;
|
||||||
|
AD operator -(void) const;
|
||||||
|
|
||||||
|
// interface so these functions need not be friends
|
||||||
|
AD abs_me(void) const;
|
||||||
|
AD acos_me(void) const;
|
||||||
|
AD asin_me(void) const;
|
||||||
|
AD atan_me(void) const;
|
||||||
|
AD cos_me(void) const;
|
||||||
|
AD cosh_me(void) const;
|
||||||
|
AD exp_me(void) const;
|
||||||
|
AD fabs_me(void) const;
|
||||||
|
AD log_me(void) const;
|
||||||
|
AD sin_me(void) const;
|
||||||
|
AD sign_me(void) const;
|
||||||
|
AD sinh_me(void) const;
|
||||||
|
AD sqrt_me(void) const;
|
||||||
|
AD tan_me(void) const;
|
||||||
|
AD tanh_me(void) const;
|
||||||
|
AD asinh_me(void) const;
|
||||||
|
AD acosh_me(void) const;
|
||||||
|
AD atanh_me(void) const;
|
||||||
|
AD erf_me(bool complemnet) const;
|
||||||
|
AD expm1_me(void) const;
|
||||||
|
AD log1p_me(void) const;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// 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 bool UnaryBool(
|
||||||
|
bool FunName(const Base &x),
|
||||||
|
const AD<Base> &x
|
||||||
|
);
|
||||||
|
static bool BinaryBool(
|
||||||
|
bool FunName(const Base &x, const Base &y),
|
||||||
|
const AD<Base> &x , const AD<Base> &y
|
||||||
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// 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
|
||||||
|
|
||||||
|
tape_id_ = id;
|
||||||
|
taddr_ = taddr;
|
||||||
|
ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// tape linking functions
|
||||||
|
//
|
||||||
|
// not static
|
||||||
|
local::ADTape<Base>* tape_this(void) const;
|
||||||
|
//
|
||||||
|
// static
|
||||||
|
static tape_id_t* tape_id_ptr(size_t thread);
|
||||||
|
static local::ADTape<Base>** tape_handle(size_t thread);
|
||||||
|
static local::ADTape<Base>* tape_manage(tape_manage_enum job);
|
||||||
|
static local::ADTape<Base>* tape_ptr(void);
|
||||||
|
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
|
||||||
144
build-config/cppad/include/cppad/core/ad_assign.hpp
Normal file
144
build-config/cppad/include/cppad/core/ad_assign.hpp
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
# ifndef CPPAD_CORE_AD_ASSIGN_HPP
|
||||||
|
# define CPPAD_CORE_AD_ASSIGN_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
$begin ad_assign$$
|
||||||
|
$spell
|
||||||
|
Vec
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Assignment Operator$$
|
||||||
|
|
||||||
|
$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>
|
||||||
|
AD<Base>& AD<Base>::operator=(const AD<Base> &right)
|
||||||
|
{ value_ = right.value_;
|
||||||
|
tape_id_ = right.tape_id_;
|
||||||
|
taddr_ = right.taddr_;
|
||||||
|
ad_type_ = right.ad_type_;
|
||||||
|
|
||||||
|
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>
|
||||||
|
AD<Base>& AD<Base>::operator=(const Base &b)
|
||||||
|
{ value_ = b;
|
||||||
|
tape_id_ = 0;
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ! ( Variable(*this) | Dynamic(*this) ) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Assignment to an ADVec<Base> element drops the vector information.
|
||||||
|
|
||||||
|
\tparam Base
|
||||||
|
Base type for this AD object.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
AD<Base>& AD<Base>::operator=(const VecAD_reference<Base> &x)
|
||||||
|
{ *this = x.ADBase();
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ! Dynamic(*this) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
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>
|
||||||
|
AD<Base>& AD<Base>::operator=(const T &t)
|
||||||
|
{ *this = Base(t);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ! ( Variable(*this) | Dynamic(*this) ) );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
143
build-config/cppad/include/cppad/core/ad_binary.hpp
Normal file
143
build-config/cppad/include/cppad/core/ad_binary.hpp
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
# ifndef CPPAD_CORE_AD_BINARY_HPP
|
||||||
|
# define CPPAD_CORE_AD_BINARY_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$begin ad_binary$$
|
||||||
|
$spell
|
||||||
|
Op
|
||||||
|
VecAD
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section AD Binary Arithmetic Operators$$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$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_base/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
|
||||||
199
build-config/cppad/include/cppad/core/ad_ctor.hpp
Normal file
199
build-config/cppad/include/cppad/core/ad_ctor.hpp
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
# ifndef CPPAD_CORE_AD_CTOR_HPP
|
||||||
|
# define CPPAD_CORE_AD_CTOR_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
$begin ad_ctor$$
|
||||||
|
$spell
|
||||||
|
cppad
|
||||||
|
ctor
|
||||||
|
initializes
|
||||||
|
Vec
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Constructors $$
|
||||||
|
|
||||||
|
$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>
|
||||||
|
AD<Base>::AD(const AD &x)
|
||||||
|
{
|
||||||
|
value_ = x.value_;
|
||||||
|
tape_id_ = x.tape_id_;
|
||||||
|
taddr_ = x.taddr_;
|
||||||
|
ad_type_ = x.ad_type_;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Default Constructor.
|
||||||
|
|
||||||
|
\tparam Base
|
||||||
|
Base type for this AD object.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
AD<Base>::AD(void)
|
||||||
|
: value_()
|
||||||
|
, tape_id_(0)
|
||||||
|
, taddr_(0)
|
||||||
|
, ad_type_(constant_enum)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
# ifdef CPPAD_FOR_TMB
|
||||||
|
/*!
|
||||||
|
Constructor from double.
|
||||||
|
|
||||||
|
\param d
|
||||||
|
is value corresponding to this AD object.
|
||||||
|
The tape identifier will be an invalid tape identifier,
|
||||||
|
so this object is initially a parameter.
|
||||||
|
|
||||||
|
\par CPPAD_FOR_TMB
|
||||||
|
This constructor is defined when CPPAD_FOR_TMB is defined.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
AD<Base>::AD(const double &d)
|
||||||
|
: value_( Base(d) )
|
||||||
|
, tape_id_(0)
|
||||||
|
, taddr_(0)
|
||||||
|
, ad_type_(constant_enum)
|
||||||
|
{ // check that this is a parameter
|
||||||
|
CPPAD_ASSERT_UNKNOWN( Parameter(*this) );
|
||||||
|
}
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
# else
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
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.
|
||||||
|
|
||||||
|
\par CPPAD_FOR_TMB
|
||||||
|
This constructor is defined when CPPAD_FOR_TMB is not defined.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
AD<Base>::AD(const Base &b)
|
||||||
|
: value_(b)
|
||||||
|
, tape_id_(0)
|
||||||
|
, taddr_(0)
|
||||||
|
, ad_type_(constant_enum)
|
||||||
|
{ // check that this is a parameter
|
||||||
|
CPPAD_ASSERT_UNKNOWN( Parameter(*this) );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructor from an ADVec<Base> element drops the vector information.
|
||||||
|
|
||||||
|
\tparam Base
|
||||||
|
Base type for this AD object.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
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>
|
||||||
|
AD<Base>::AD(const T &t)
|
||||||
|
: value_(Base(t))
|
||||||
|
, tape_id_(0)
|
||||||
|
, taddr_(0)
|
||||||
|
, ad_type_(constant_enum)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
876
build-config/cppad/include/cppad/core/ad_fun.hpp
Normal file
876
build-config/cppad/include/cppad/core/ad_fun.hpp
Normal file
@@ -0,0 +1,876 @@
|
|||||||
|
# ifndef CPPAD_CORE_AD_FUN_HPP
|
||||||
|
# define CPPAD_CORE_AD_FUN_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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%
|
||||||
|
include/cppad/core/optimize.hpp%
|
||||||
|
include/cppad/core/fun_check.hpp%
|
||||||
|
include/cppad/core/check_for_nan.hpp
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
# include <cppad/core/graph/cpp_graph.hpp>
|
||||||
|
# include <cppad/local/subgraph/info.hpp>
|
||||||
|
# include <cppad/local/graph/cpp_graph_op.hpp>
|
||||||
|
|
||||||
|
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 Base operations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
class ADFun {
|
||||||
|
// ADFun<Base> must be a friend of ADFun< AD<Base> > for base2ad to work.
|
||||||
|
template <class Base2, class RecBase2> friend class ADFun;
|
||||||
|
private:
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Private member variables
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
/// name of this function (so far only json operations use this value)
|
||||||
|
std::string function_name_;
|
||||||
|
|
||||||
|
/// Did the previous optimzation exceed the collision limit
|
||||||
|
bool exceed_collision_limit_;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
local::pod_vector<size_t> ind_taddr_;
|
||||||
|
|
||||||
|
/// tape address and parameter flag for the dependent variables
|
||||||
|
local::pod_vector<size_t> dep_taddr_;
|
||||||
|
|
||||||
|
/// which dependent variables are actually parameters
|
||||||
|
local::pod_vector<bool> dep_parameter_;
|
||||||
|
|
||||||
|
/// 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_op2var_;
|
||||||
|
|
||||||
|
/// results of the forward mode calculations
|
||||||
|
local::pod_vector_maybe<Base> taylor_;
|
||||||
|
|
||||||
|
/// used for subgraph reverse mode calculations.
|
||||||
|
/// Declared here to avoid reallocation for each call to subgraph_reverse.
|
||||||
|
/// Not in subgraph_info_ because it depends on Base.
|
||||||
|
local::pod_vector_maybe<Base> subgraph_partial_;
|
||||||
|
|
||||||
|
/// the operation sequence corresponding to this object
|
||||||
|
local::player<Base> play_;
|
||||||
|
|
||||||
|
/// subgraph information for this object
|
||||||
|
local::subgraph::subgraph_info subgraph_info_;
|
||||||
|
|
||||||
|
/// 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_setvec 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_setvec for_jac_sparse_set_;
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Private member functions
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
/// change the operation sequence corresponding to this object
|
||||||
|
template <class ADvector>
|
||||||
|
void Dependent(local::ADTape<Base> *tape, const ADvector &y);
|
||||||
|
|
||||||
|
// vector of bool version of ForSparseJac
|
||||||
|
// (doxygen in cppad/core/for_sparse_jac.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
void ForSparseJacCase(
|
||||||
|
bool set_type ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency,
|
||||||
|
size_t q ,
|
||||||
|
const SetVector& r ,
|
||||||
|
SetVector& s
|
||||||
|
);
|
||||||
|
|
||||||
|
// vector of std::set<size_t> version of ForSparseJac
|
||||||
|
// (doxygen in cppad/core/for_sparse_jac.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
void ForSparseJacCase(
|
||||||
|
const std::set<size_t>& set_type ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency,
|
||||||
|
size_t q ,
|
||||||
|
const SetVector& r ,
|
||||||
|
SetVector& s
|
||||||
|
);
|
||||||
|
|
||||||
|
// vector of bool version of RevSparseJac
|
||||||
|
// (doxygen in cppad/core/rev_sparse_jac.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
void RevSparseJacCase(
|
||||||
|
bool set_type ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency,
|
||||||
|
size_t p ,
|
||||||
|
const SetVector& s ,
|
||||||
|
SetVector& r
|
||||||
|
);
|
||||||
|
|
||||||
|
// vector of std::set<size_t> version of RevSparseJac
|
||||||
|
// (doxygen in cppad/core/rev_sparse_jac.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
void RevSparseJacCase(
|
||||||
|
const std::set<size_t>& set_type ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency,
|
||||||
|
size_t p ,
|
||||||
|
const SetVector& s ,
|
||||||
|
SetVector& r
|
||||||
|
);
|
||||||
|
|
||||||
|
// vector of bool version of ForSparseHes
|
||||||
|
// (doxygen in cppad/core/for_sparse_hes.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
void ForSparseHesCase(
|
||||||
|
bool set_type ,
|
||||||
|
const SetVector& r ,
|
||||||
|
const SetVector& s ,
|
||||||
|
SetVector& h
|
||||||
|
);
|
||||||
|
|
||||||
|
// vector of std::set<size_t> version of ForSparseHes
|
||||||
|
// (doxygen in cppad/core/for_sparse_hes.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
void ForSparseHesCase(
|
||||||
|
const std::set<size_t>& set_type ,
|
||||||
|
const SetVector& r ,
|
||||||
|
const SetVector& s ,
|
||||||
|
SetVector& h
|
||||||
|
);
|
||||||
|
|
||||||
|
// vector of bool version of RevSparseHes
|
||||||
|
// (doxygen in cppad/core/rev_sparse_hes.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
void RevSparseHesCase(
|
||||||
|
bool set_type ,
|
||||||
|
bool transpose ,
|
||||||
|
size_t q ,
|
||||||
|
const SetVector& s ,
|
||||||
|
SetVector& h
|
||||||
|
);
|
||||||
|
|
||||||
|
// vector of std::set<size_t> version of RevSparseHes
|
||||||
|
// (doxygen in cppad/core/rev_sparse_hes.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
void RevSparseHesCase(
|
||||||
|
const std::set<size_t>& set_type ,
|
||||||
|
bool transpose ,
|
||||||
|
size_t q ,
|
||||||
|
const SetVector& s ,
|
||||||
|
SetVector& h
|
||||||
|
);
|
||||||
|
|
||||||
|
// Forward mode version of SparseJacobian
|
||||||
|
// (doxygen in cppad/core/sparse_jacobian.hpp)
|
||||||
|
template <class BaseVector, class SetVector, class SizeVector>
|
||||||
|
size_t SparseJacobianFor(
|
||||||
|
const BaseVector& x ,
|
||||||
|
SetVector& p_transpose ,
|
||||||
|
const SizeVector& row ,
|
||||||
|
const SizeVector& col ,
|
||||||
|
BaseVector& jac ,
|
||||||
|
sparse_jacobian_work& work
|
||||||
|
);
|
||||||
|
|
||||||
|
// Reverse mode version of SparseJacobian
|
||||||
|
// (doxygen in cppad/core/sparse_jacobian.hpp)
|
||||||
|
template <class BaseVector, class SetVector, class SizeVector>
|
||||||
|
size_t SparseJacobianRev(
|
||||||
|
const BaseVector& x ,
|
||||||
|
SetVector& p ,
|
||||||
|
const SizeVector& row ,
|
||||||
|
const SizeVector& col ,
|
||||||
|
BaseVector& jac ,
|
||||||
|
sparse_jacobian_work& work
|
||||||
|
);
|
||||||
|
|
||||||
|
// combined sparse_list and sparse_pack version of SparseHessian
|
||||||
|
// (doxygen in cppad/core/sparse_hessian.hpp)
|
||||||
|
template <class BaseVector, class SetVector, class SizeVector>
|
||||||
|
size_t SparseHessianCompute(
|
||||||
|
const BaseVector& x ,
|
||||||
|
const BaseVector& w ,
|
||||||
|
SetVector& sparsity ,
|
||||||
|
const SizeVector& row ,
|
||||||
|
const SizeVector& col ,
|
||||||
|
BaseVector& hes ,
|
||||||
|
sparse_hessian_work& work
|
||||||
|
);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// default constructor
|
||||||
|
ADFun(void);
|
||||||
|
|
||||||
|
/// copy constructor
|
||||||
|
ADFun(const ADFun& g) = delete;
|
||||||
|
|
||||||
|
// assignment operator
|
||||||
|
// (doxygen in cppad/core/fun_construct.hpp)
|
||||||
|
void operator=(const ADFun& f);
|
||||||
|
|
||||||
|
// swap
|
||||||
|
void swap(ADFun& f);
|
||||||
|
|
||||||
|
// move semenatics copy
|
||||||
|
ADFun(ADFun&& f);
|
||||||
|
|
||||||
|
// move semantics assignment
|
||||||
|
void operator=(ADFun&& f);
|
||||||
|
|
||||||
|
// create from Json or C++ AD graph
|
||||||
|
void from_json(const std::string& json);
|
||||||
|
void from_graph(const cpp_graph& graph_obj);
|
||||||
|
void from_graph(
|
||||||
|
const cpp_graph& graph_obj ,
|
||||||
|
const vector<bool>& dyn2var ,
|
||||||
|
const vector<bool>& var2dyn
|
||||||
|
);
|
||||||
|
|
||||||
|
// create a Json or C++ AD graph
|
||||||
|
std::string to_json(void);
|
||||||
|
void to_graph(cpp_graph& graph_obj);
|
||||||
|
|
||||||
|
// create ADFun< AD<Base> > from this ADFun<Base>
|
||||||
|
// (doxygen in cppad/core/base2ad.hpp)
|
||||||
|
ADFun< AD<Base>, RecBase > base2ad(void) const;
|
||||||
|
|
||||||
|
/// sequence constructor
|
||||||
|
template <class ADvector>
|
||||||
|
ADFun(const ADvector &x, const ADvector &y);
|
||||||
|
|
||||||
|
/// destructor
|
||||||
|
~ADFun(void);
|
||||||
|
|
||||||
|
/// set check_for_nan
|
||||||
|
void check_for_nan(bool value);
|
||||||
|
|
||||||
|
/// get check_for_nan
|
||||||
|
bool check_for_nan(void) const;
|
||||||
|
|
||||||
|
/// assign a new operation sequence
|
||||||
|
template <class ADvector>
|
||||||
|
void Dependent(const ADvector &x, const ADvector &y);
|
||||||
|
|
||||||
|
/// new_dynamic user API
|
||||||
|
template <class BaseVector>
|
||||||
|
void new_dynamic(const BaseVector& dynamic);
|
||||||
|
|
||||||
|
/// forward mode user API, one order multiple directions.
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector Forward(size_t q, size_t r, const BaseVector& x);
|
||||||
|
|
||||||
|
/// forward mode user API, multiple orders one direction.
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector Forward(
|
||||||
|
size_t q, const BaseVector& xq, std::ostream& s = std::cout
|
||||||
|
);
|
||||||
|
|
||||||
|
/// reverse mode sweep
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector Reverse(size_t p, const BaseVector &v);
|
||||||
|
|
||||||
|
// forward Jacobian sparsity pattern
|
||||||
|
// (doxygen in cppad/core/for_sparse_jac.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
SetVector ForSparseJac(
|
||||||
|
size_t q, const SetVector &r, bool transpose = false,
|
||||||
|
bool dependency = false
|
||||||
|
);
|
||||||
|
|
||||||
|
// reverse Jacobian sparsity pattern
|
||||||
|
// (doxygen in cppad/core/rev_sparse_jac.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
SetVector RevSparseJac(
|
||||||
|
size_t q, const SetVector &s, bool transpose = false,
|
||||||
|
bool dependency = false
|
||||||
|
);
|
||||||
|
|
||||||
|
// subgraph_reverse: select domain
|
||||||
|
// (doxygen in cppad/core/subgraph_reverse.hpp)
|
||||||
|
template <class BoolVector>
|
||||||
|
void subgraph_reverse(
|
||||||
|
const BoolVector& select_domain
|
||||||
|
);
|
||||||
|
|
||||||
|
// subgraph_reverse: compute derivative
|
||||||
|
// (doxygen in cppad/core/subgraph_reverse.hpp)
|
||||||
|
template <class Addr, class BaseVector, class SizeVector>
|
||||||
|
void subgraph_reverse_helper(
|
||||||
|
size_t q ,
|
||||||
|
size_t ell ,
|
||||||
|
SizeVector& col ,
|
||||||
|
BaseVector& dw
|
||||||
|
);
|
||||||
|
|
||||||
|
// subgraph_reverse: compute derivative
|
||||||
|
// (doxygen in cppad/core/subgraph_reverse.hpp)
|
||||||
|
template <class BaseVector, class SizeVector>
|
||||||
|
void subgraph_reverse(
|
||||||
|
size_t q ,
|
||||||
|
size_t ell ,
|
||||||
|
SizeVector& col ,
|
||||||
|
BaseVector& dw
|
||||||
|
);
|
||||||
|
|
||||||
|
// subgraph_jac_rev: compute Jacobian
|
||||||
|
// (doxygen in cppad/core/subgraph_jac_rev.hpp)
|
||||||
|
template <class SizeVector, class BaseVector>
|
||||||
|
void subgraph_jac_rev(
|
||||||
|
const BaseVector& x ,
|
||||||
|
sparse_rcv<SizeVector, BaseVector>& subset
|
||||||
|
);
|
||||||
|
|
||||||
|
// subgraph_jac_rev: compute Jacobian
|
||||||
|
// (doxygen missing in cppad/core/subgraph_jac_rev.hpp)
|
||||||
|
template <class BoolVector, class SizeVector, class BaseVector>
|
||||||
|
void subgraph_jac_rev(
|
||||||
|
const BoolVector& select_domain ,
|
||||||
|
const BoolVector& select_range ,
|
||||||
|
const BaseVector& x ,
|
||||||
|
sparse_rcv<SizeVector, BaseVector>& matrix_out
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// compute sparse Jacobian using forward mode
|
||||||
|
// (doxygen in cppad/core/sparse_jac.hpp)
|
||||||
|
template <class SizeVector, class 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
|
||||||
|
);
|
||||||
|
|
||||||
|
// compute sparse Jacobian using reverse mode
|
||||||
|
// (doxygen in cppad/core/sparse_jac.hpp)
|
||||||
|
template <class SizeVector, class 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
|
||||||
|
);
|
||||||
|
|
||||||
|
// compute sparse Hessian
|
||||||
|
// (doxygen in cppad/core/sparse_hes.hpp)
|
||||||
|
template <class SizeVector, class 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
|
||||||
|
);
|
||||||
|
|
||||||
|
// compute sparsity pattern using subgraphs
|
||||||
|
// (doxygen in cppad/core/subgraph_sparsity.hpp)
|
||||||
|
template <class BoolVector, class SizeVector>
|
||||||
|
void subgraph_sparsity(
|
||||||
|
const BoolVector& select_domain ,
|
||||||
|
const BoolVector& select_range ,
|
||||||
|
bool transpose ,
|
||||||
|
sparse_rc<SizeVector>& pattern_out
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// forward mode Jacobian sparsity pattern
|
||||||
|
// (doxygen in cppad/core/for_jac_sparsity.hpp)
|
||||||
|
template <class SizeVector>
|
||||||
|
void for_jac_sparsity(
|
||||||
|
const sparse_rc<SizeVector>& pattern_in ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency ,
|
||||||
|
bool internal_bool ,
|
||||||
|
sparse_rc<SizeVector>& pattern_out
|
||||||
|
);
|
||||||
|
|
||||||
|
// reverse mode Jacobian sparsity pattern
|
||||||
|
// (doxygen in cppad/core/for_jac_sparsity.hpp)
|
||||||
|
template <class SizeVector>
|
||||||
|
void rev_jac_sparsity(
|
||||||
|
const sparse_rc<SizeVector>& pattern_in ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency ,
|
||||||
|
bool internal_bool ,
|
||||||
|
sparse_rc<SizeVector>& pattern_out
|
||||||
|
);
|
||||||
|
|
||||||
|
// reverse mode Hessian sparsity pattern
|
||||||
|
// (doxygen in cppad/core/rev_hes_sparsity.hpp)
|
||||||
|
template <class BoolVector, class SizeVector>
|
||||||
|
void rev_hes_sparsity(
|
||||||
|
const BoolVector& select_range ,
|
||||||
|
bool transpose ,
|
||||||
|
bool internal_bool ,
|
||||||
|
sparse_rc<SizeVector>& pattern_out
|
||||||
|
);
|
||||||
|
|
||||||
|
// forward mode Hessian sparsity pattern
|
||||||
|
// (doxygen in cppad/core/for_hes_sparsity.hpp)
|
||||||
|
template <class BoolVector, class 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 pattern
|
||||||
|
// (see doxygen in cppad/core/for_sparse_hes.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
SetVector ForSparseHes(
|
||||||
|
const SetVector &r, const SetVector &s
|
||||||
|
);
|
||||||
|
|
||||||
|
// internal set sparsity version of ForSparseHes
|
||||||
|
// (used by checkpoint functions only)
|
||||||
|
void ForSparseHesCheckpoint(
|
||||||
|
vector<bool>& r ,
|
||||||
|
vector<bool>& s ,
|
||||||
|
local::sparse::list_setvec& h
|
||||||
|
);
|
||||||
|
|
||||||
|
// reverse mode Hessian sparsity pattern
|
||||||
|
// (see doxygen in cppad/core/rev_sparse_hes.hpp)
|
||||||
|
template <class SetVector>
|
||||||
|
SetVector RevSparseHes(
|
||||||
|
size_t q, const SetVector &s, bool transpose = false
|
||||||
|
);
|
||||||
|
|
||||||
|
// internal set sparsity version of RevSparseHes
|
||||||
|
// (doxygen in cppad/core/rev_sparse_hes.hpp)
|
||||||
|
// (used by checkpoint functions only)
|
||||||
|
void RevSparseHesCheckpoint(
|
||||||
|
size_t q ,
|
||||||
|
vector<bool>& s ,
|
||||||
|
bool transpose ,
|
||||||
|
local::sparse::list_setvec& h
|
||||||
|
);
|
||||||
|
|
||||||
|
// internal set sparsity version of RevSparseJac
|
||||||
|
// (doxygen in cppad/core/rev_sparse_jac.hpp)
|
||||||
|
// (used by checkpoint functions only)
|
||||||
|
void RevSparseJacCheckpoint(
|
||||||
|
size_t q ,
|
||||||
|
const local::sparse::list_setvec& r ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency ,
|
||||||
|
local::sparse::list_setvec& s
|
||||||
|
);
|
||||||
|
|
||||||
|
// internal set sparsity version of RevSparseJac
|
||||||
|
// (doxygen in cppad/core/for_sparse_jac.hpp)
|
||||||
|
// (used by checkpoint functions only)
|
||||||
|
void ForSparseJacCheckpoint(
|
||||||
|
size_t q ,
|
||||||
|
const local::sparse::list_setvec& r ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency ,
|
||||||
|
local::sparse::list_setvec& s
|
||||||
|
);
|
||||||
|
|
||||||
|
/// did previous optimization exceed the collision limit
|
||||||
|
bool exceed_collision_limit(void) const
|
||||||
|
{ return exceed_collision_limit_; }
|
||||||
|
|
||||||
|
/// 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_.size_op_seq(); }
|
||||||
|
|
||||||
|
/// amount of memory currently allocated for random access
|
||||||
|
/// of the operation sequence
|
||||||
|
size_t size_random(void) const
|
||||||
|
{ return play_.size_random(); }
|
||||||
|
|
||||||
|
/// number of parameters in the operation sequence
|
||||||
|
size_t size_par(void) const
|
||||||
|
{ return play_.num_par_rec(); }
|
||||||
|
|
||||||
|
/// number of independent dynamic parameters
|
||||||
|
size_t size_dyn_ind(void) const
|
||||||
|
{ return play_.num_dynamic_ind(); }
|
||||||
|
|
||||||
|
/// number of dynamic parameters
|
||||||
|
size_t size_dyn_par(void) const
|
||||||
|
{ return play_.num_dynamic_par(); }
|
||||||
|
|
||||||
|
/// number of dynamic parameters arguments
|
||||||
|
size_t size_dyn_arg(void) const
|
||||||
|
{ return play_.num_dynamic_arg(); }
|
||||||
|
|
||||||
|
/// 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_var_vecad_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 <class BaseVector>
|
||||||
|
BaseVector Jacobian(const BaseVector &x);
|
||||||
|
|
||||||
|
/// calculate Hessian for one component of f
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector Hessian(const BaseVector &x, const BaseVector &w);
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector Hessian(const BaseVector &x, size_t i);
|
||||||
|
|
||||||
|
/// forward mode calculation of partial w.r.t one domain component
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector ForOne(
|
||||||
|
const BaseVector &x ,
|
||||||
|
size_t j );
|
||||||
|
|
||||||
|
/// reverse mode calculation of derivative of one range component
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector RevOne(
|
||||||
|
const BaseVector &x ,
|
||||||
|
size_t i );
|
||||||
|
|
||||||
|
/// forward mode calculation of a subset of second order partials
|
||||||
|
template <class BaseVector, class SizeVector_t>
|
||||||
|
BaseVector ForTwo(
|
||||||
|
const BaseVector &x ,
|
||||||
|
const SizeVector_t &J ,
|
||||||
|
const SizeVector_t &K );
|
||||||
|
|
||||||
|
/// reverse mode calculation of a subset of second order partials
|
||||||
|
template <class BaseVector, class SizeVector_t>
|
||||||
|
BaseVector RevTwo(
|
||||||
|
const BaseVector &x ,
|
||||||
|
const SizeVector_t &I ,
|
||||||
|
const SizeVector_t &J );
|
||||||
|
|
||||||
|
/// calculate sparse Jacobians
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector SparseJacobian(
|
||||||
|
const BaseVector &x
|
||||||
|
);
|
||||||
|
template <class BaseVector, class SetVector>
|
||||||
|
BaseVector SparseJacobian(
|
||||||
|
const BaseVector &x ,
|
||||||
|
const SetVector &p
|
||||||
|
);
|
||||||
|
template <class BaseVector, class SetVector, class SizeVector>
|
||||||
|
size_t SparseJacobianForward(
|
||||||
|
const BaseVector& x ,
|
||||||
|
const SetVector& p ,
|
||||||
|
const SizeVector& r ,
|
||||||
|
const SizeVector& c ,
|
||||||
|
BaseVector& jac ,
|
||||||
|
sparse_jacobian_work& work
|
||||||
|
);
|
||||||
|
template <class BaseVector, class SetVector, class SizeVector>
|
||||||
|
size_t SparseJacobianReverse(
|
||||||
|
const BaseVector& x ,
|
||||||
|
const SetVector& p ,
|
||||||
|
const SizeVector& r ,
|
||||||
|
const SizeVector& c ,
|
||||||
|
BaseVector& jac ,
|
||||||
|
sparse_jacobian_work& work
|
||||||
|
);
|
||||||
|
|
||||||
|
/// calculate sparse Hessians
|
||||||
|
template <class BaseVector>
|
||||||
|
BaseVector SparseHessian(
|
||||||
|
const BaseVector& x ,
|
||||||
|
const BaseVector& w
|
||||||
|
);
|
||||||
|
template <class BaseVector, class BoolVector>
|
||||||
|
BaseVector SparseHessian(
|
||||||
|
const BaseVector& x ,
|
||||||
|
const BaseVector& w ,
|
||||||
|
const BoolVector& p
|
||||||
|
);
|
||||||
|
template <class BaseVector, class SetVector, class SizeVector>
|
||||||
|
size_t SparseHessian(
|
||||||
|
const BaseVector& x ,
|
||||||
|
const BaseVector& w ,
|
||||||
|
const SetVector& p ,
|
||||||
|
const SizeVector& r ,
|
||||||
|
const SizeVector& c ,
|
||||||
|
BaseVector& 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 ) const;
|
||||||
|
|
||||||
|
// clear all subgraph information
|
||||||
|
void clear_subgraph(void);
|
||||||
|
// ------------------- Deprecated -----------------------------
|
||||||
|
|
||||||
|
/// deprecated: assign a new operation sequence
|
||||||
|
template <class 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;
|
||||||
|
total += play_.size_op_seq();
|
||||||
|
total += play_.size_random();
|
||||||
|
total += subgraph_info_.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_var_vecad_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/sweep/forward0.hpp>
|
||||||
|
# include <cppad/local/sweep/forward1.hpp>
|
||||||
|
# include <cppad/local/sweep/forward2.hpp>
|
||||||
|
# include <cppad/local/sweep/reverse.hpp>
|
||||||
|
# include <cppad/local/sweep/for_jac.hpp>
|
||||||
|
# include <cppad/local/sweep/rev_jac.hpp>
|
||||||
|
# include <cppad/local/sweep/rev_hes.hpp>
|
||||||
|
# include <cppad/local/sweep/for_hes.hpp>
|
||||||
|
# include <cppad/core/graph/from_graph.hpp>
|
||||||
|
# include <cppad/core/graph/to_graph.hpp>
|
||||||
|
|
||||||
|
// user interfaces
|
||||||
|
# include <cppad/core/parallel_ad.hpp>
|
||||||
|
# include <cppad/core/independent/independent.hpp>
|
||||||
|
# include <cppad/core/dependent.hpp>
|
||||||
|
# include <cppad/core/fun_construct.hpp>
|
||||||
|
# include <cppad/core/base2ad.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>
|
||||||
|
# include <cppad/core/graph/from_json.hpp>
|
||||||
|
# include <cppad/core/graph/to_json.hpp>
|
||||||
|
|
||||||
|
# endif
|
||||||
220
build-config/cppad/include/cppad/core/ad_io.hpp
Normal file
220
build-config/cppad/include/cppad/core/ad_io.hpp
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
# ifndef CPPAD_CORE_AD_IO_HPP
|
||||||
|
# define CPPAD_CORE_AD_IO_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin ad_input$$
|
||||||
|
$spell
|
||||||
|
VecAD
|
||||||
|
std
|
||||||
|
istream
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Input Stream Operator$$
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$end
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin ad_output$$
|
||||||
|
$spell
|
||||||
|
VecAD
|
||||||
|
std
|
||||||
|
ostream
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Output Stream Operator$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%os% << %x%$$
|
||||||
|
|
||||||
|
$head See Also$$
|
||||||
|
$cref PrintFor$$
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$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
|
||||||
70
build-config/cppad/include/cppad/core/ad_to_string.hpp
Normal file
70
build-config/cppad/include/cppad/core/ad_to_string.hpp
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# 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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$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
|
||||||
59
build-config/cppad/include/cppad/core/ad_type.hpp
Normal file
59
build-config/cppad/include/cppad/core/ad_type.hpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# ifndef CPPAD_CORE_AD_TYPE_HPP
|
||||||
|
# define CPPAD_CORE_AD_TYPE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
# include <cppad/local/is_pod.hpp>
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*
|
||||||
|
$begin ad_type_enum$$
|
||||||
|
$spell
|
||||||
|
enum
|
||||||
|
typedef
|
||||||
|
CppAD
|
||||||
|
namespace
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Type of AD an Object$$
|
||||||
|
|
||||||
|
$head User API$$
|
||||||
|
The values $code constant_enum$$, $code dynamic_enum$$ and
|
||||||
|
$code variable_enum$$ are in the user API; see
|
||||||
|
$cref/ad_type/atomic_three/ad_type/$$ for $code atomic_three$$ functions.
|
||||||
|
|
||||||
|
$head typedef$$
|
||||||
|
This typedef is in the $code CppAD$$ namespace:
|
||||||
|
$srccode%hpp% */
|
||||||
|
typedef enum {
|
||||||
|
constant_enum, // constant parameter
|
||||||
|
dynamic_enum, // dynamic parameter
|
||||||
|
variable_enum, // variable
|
||||||
|
number_ad_type_enum // number of valid values for type_ad_enum
|
||||||
|
} ad_type_enum;
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$head is_pod$$
|
||||||
|
The following informs $cref is_pod$$ that this is plain old data.
|
||||||
|
$srccode%hpp% */
|
||||||
|
namespace local {
|
||||||
|
template <> inline bool
|
||||||
|
is_pod<ad_type_enum>(void) { return true; }
|
||||||
|
}
|
||||||
|
/* %$$
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
|
# endif
|
||||||
50
build-config/cppad/include/cppad/core/ad_valued.hpp
Normal file
50
build-config/cppad/include/cppad/core/ad_valued.hpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# ifndef CPPAD_CORE_AD_VALUED_HPP
|
||||||
|
# define CPPAD_CORE_AD_VALUED_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin ADValued$$
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Valued Operations and Functions$$
|
||||||
|
|
||||||
|
$comment atomic.omh includes atomic_two.hpp$$
|
||||||
|
$childtable%
|
||||||
|
include/cppad/core/arithmetic.hpp%
|
||||||
|
include/cppad/core/standard_math.hpp%
|
||||||
|
include/cppad/core/cond_exp.hpp%
|
||||||
|
include/cppad/core/discrete/user.omh%
|
||||||
|
include/cppad/core/numeric_limits.hpp%
|
||||||
|
include/cppad/core/atomic/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/discrete.hpp>
|
||||||
|
# include <cppad/core/atomic/atomic_three.hpp>
|
||||||
|
# include <cppad/core/chkpoint_two/chkpoint_two.hpp>
|
||||||
|
# include <cppad/core/atomic/atomic_two.hpp>
|
||||||
|
# include <cppad/core/atomic/atomic_one.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/chkpoint_one.hpp>
|
||||||
|
|
||||||
|
# endif
|
||||||
131
build-config/cppad/include/cppad/core/add.hpp
Normal file
131
build-config/cppad/include/cppad/core/add.hpp
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
# ifndef CPPAD_CORE_ADD_HPP
|
||||||
|
# define CPPAD_CORE_ADD_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// 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 == nullptr )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = left.tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (left.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (left.ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"Add: AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
else if( (! dyn_right) & 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 = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( var_right )
|
||||||
|
{ if( (! dyn_left) & 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 = left.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ addr_t arg0 = left.taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
// parameters with a dynamic parameter result
|
||||||
|
result.taddr_ = tape->Rec_.put_dyn_par(
|
||||||
|
result.value_, local::add_dyn, arg0, arg1
|
||||||
|
);
|
||||||
|
result.tape_id_ = tape_id;
|
||||||
|
result.ad_type_ = dynamic_enum;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert other cases into the case above
|
||||||
|
CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(+)
|
||||||
|
|
||||||
|
} // END CppAD namespace
|
||||||
|
|
||||||
|
# endif
|
||||||
128
build-config/cppad/include/cppad/core/add_eq.hpp
Normal file
128
build-config/cppad/include/cppad/core/add_eq.hpp
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
# ifndef CPPAD_CORE_ADD_EQ_HPP
|
||||||
|
# define CPPAD_CORE_ADD_EQ_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// 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 == nullptr )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"+= : AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
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);
|
||||||
|
// check that this is a variable
|
||||||
|
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);
|
||||||
|
}
|
||||||
|
else if( dyn_right | (! 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 = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(right.value_);
|
||||||
|
tape->Rec_.PutArg(p, taddr_);
|
||||||
|
// put operator in the tape
|
||||||
|
taddr_ = tape->Rec_.PutOp(local::AddpvOp);
|
||||||
|
// check that this is a variable
|
||||||
|
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( var_right )
|
||||||
|
{ if( (! dyn_left) & 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 = taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(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;
|
||||||
|
ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ addr_t arg0 = taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
// parameters with a dynamic parameter results
|
||||||
|
taddr_ = tape->Rec_.put_dyn_par(
|
||||||
|
value_, local::add_dyn, arg0, arg1
|
||||||
|
);
|
||||||
|
tape_id_ = tape_id;
|
||||||
|
ad_type_ = dynamic_enum;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPAD_FOLD_ASSIGNMENT_OPERATOR(+=)
|
||||||
|
|
||||||
|
} // END CppAD namespace
|
||||||
|
|
||||||
|
# endif
|
||||||
42
build-config/cppad/include/cppad/core/arithmetic.hpp
Normal file
42
build-config/cppad/include/cppad/core/arithmetic.hpp
Normal file
@@ -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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$begin Arithmetic$$
|
||||||
|
$spell
|
||||||
|
Op
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Arithmetic Operators and Compound Assignments$$
|
||||||
|
|
||||||
|
$childtable%
|
||||||
|
include/cppad/core/unary_plus.hpp%
|
||||||
|
include/cppad/core/unary_minus.hpp%
|
||||||
|
include/cppad/core/ad_binary.hpp%
|
||||||
|
include/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
|
||||||
152
build-config/cppad/include/cppad/core/atan2.hpp
Normal file
152
build-config/cppad/include/cppad/core/atan2.hpp
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATAN2_HPP
|
||||||
|
# define CPPAD_CORE_ATAN2_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-21 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$begin atan2$$
|
||||||
|
$spell
|
||||||
|
Vec
|
||||||
|
CppAD
|
||||||
|
namespace
|
||||||
|
std
|
||||||
|
atan
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Two Argument Inverse Tangent Function$$
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$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)
|
||||||
|
{ //
|
||||||
|
// zero, pi2, pi
|
||||||
|
AD<Base> zero(0.);
|
||||||
|
AD<Base> pi2(2. * atan(1.));
|
||||||
|
AD<Base> pi(2. * pi2);
|
||||||
|
//
|
||||||
|
// abs_x, abs_y
|
||||||
|
// Not using fabs because its derivative is zero at zero
|
||||||
|
AD<Base> abs_x = CondExpGe(x, zero, x, -x);
|
||||||
|
AD<Base> abs_y = CondExpGe(y, zero, y, -y);
|
||||||
|
//
|
||||||
|
// first
|
||||||
|
// This is the result for first quadrant: x >= 0 , y >= 0
|
||||||
|
AD<Base> alpha = atan(abs_y / abs_x);
|
||||||
|
AD<Base> beta = pi2 - atan(abs_x / abs_y);
|
||||||
|
AD<Base> first = CondExpGt(abs_x, abs_y, alpha, beta);
|
||||||
|
//
|
||||||
|
// second
|
||||||
|
// This is the result for second quadrant: x <= 0 , y >= 0
|
||||||
|
AD<Base> second = pi - first;
|
||||||
|
//
|
||||||
|
// third
|
||||||
|
// This is the result for third quadrant: x <= 0 , y <= 0
|
||||||
|
AD<Base> third = - pi + first;
|
||||||
|
//
|
||||||
|
// fourth
|
||||||
|
// This is the result for fourth quadrant: x >= 0 , y <= 0
|
||||||
|
AD<Base> fourth = - first;
|
||||||
|
//
|
||||||
|
// alpha
|
||||||
|
// This is the result for x >= 0
|
||||||
|
alpha = CondExpGe(y, zero, first, fourth);
|
||||||
|
//
|
||||||
|
// beta
|
||||||
|
// This is the result for x <= 0
|
||||||
|
beta = CondExpGe(y, zero, second, third);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
AD<Base> result = CondExpGe(x, zero, alpha, beta);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// END CondExp
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
AD<Base> atan2 (const VecAD_reference<Base> &y, const AD<Base> &x)
|
||||||
|
{ return atan2( y.ADBase() , x ); }
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
AD<Base> atan2 (const AD<Base> &y, const VecAD_reference<Base> &x)
|
||||||
|
{ return atan2( y , x.ADBase() ); }
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
AD<Base> atan2
|
||||||
|
(const VecAD_reference<Base> &y, const VecAD_reference<Base> &x)
|
||||||
|
{ return atan2( y.ADBase() , x.ADBase() ); }
|
||||||
|
|
||||||
|
} // END CppAD namespace
|
||||||
|
|
||||||
|
# endif
|
||||||
26
build-config/cppad/include/cppad/core/atomic/atomic.omh
Normal file
26
build-config/cppad/include/cppad/core/atomic/atomic.omh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
-------------------------------------------------------------------------- */
|
||||||
|
$begin atomic$$
|
||||||
|
|
||||||
|
$section Atomic AD Functions$$
|
||||||
|
|
||||||
|
$childtable%
|
||||||
|
include/cppad/core/atomic/atomic_three.hpp%
|
||||||
|
include/cppad/core/chkpoint_two/chkpoint_two.hpp
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Deprecated Atomic Function$$
|
||||||
|
$cref atomic_one$$,
|
||||||
|
$cref atomic_two$$,
|
||||||
|
$cref chkpoint_one$$.
|
||||||
|
|
||||||
|
$end
|
||||||
1058
build-config/cppad/include/cppad/core/atomic/atomic_one.hpp
Normal file
1058
build-config/cppad/include/cppad/core/atomic/atomic_one.hpp
Normal file
File diff suppressed because it is too large
Load Diff
486
build-config/cppad/include/cppad/core/atomic/atomic_three.hpp
Normal file
486
build-config/cppad/include/cppad/core/atomic/atomic_three.hpp
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_ATOMIC_THREE_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_ATOMIC_THREE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three$$
|
||||||
|
$spell
|
||||||
|
taylor
|
||||||
|
ctor
|
||||||
|
afun
|
||||||
|
arg
|
||||||
|
jac
|
||||||
|
hes
|
||||||
|
CppAD
|
||||||
|
enum
|
||||||
|
mul
|
||||||
|
hpp
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Defining Atomic Functions: Third Generation$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
|
||||||
|
$subhead Define Class$$
|
||||||
|
$codei%class %atomic_user% : public CppAD::atomic_three<%Base%> {
|
||||||
|
%...%
|
||||||
|
};%$$
|
||||||
|
|
||||||
|
$subhead Construct Atomic Function$$
|
||||||
|
$icode%atomic_user% %afun%(%ctor_arg_list%)%$$
|
||||||
|
|
||||||
|
$subhead Use Atomic Function$$
|
||||||
|
$icode%afun%(%ax%, %ay%)%$$
|
||||||
|
|
||||||
|
$subhead Class Member Callbacks$$
|
||||||
|
$icode%ok% = %afun%.for_type(
|
||||||
|
%parameter_x%, %type_x%, %type_y%
|
||||||
|
)
|
||||||
|
%ok% = %afun%.forward(
|
||||||
|
%parameter_x%, %type_x%,
|
||||||
|
%need_y%, %order_low%, %order_up%, %taylor_x%, %taylor_y%
|
||||||
|
)
|
||||||
|
%ok% = %afun%.reverse(
|
||||||
|
%parameter_x%, %type_x%,
|
||||||
|
%order_up%, %taylor_x%, %taylor_y%, %partial_x%, %partial_y%
|
||||||
|
)
|
||||||
|
%ok% = %afun%.jac_sparsity(
|
||||||
|
%parameter_x%, %type_x%, %dependency%, %select_x% %select_y%, %pattern_out%
|
||||||
|
)
|
||||||
|
%ok% = %afun%.hes_sparsity(
|
||||||
|
%parameter_x%, %type_x%, %select_x% %select_y%, %pattern_out%
|
||||||
|
)
|
||||||
|
%ok% = %afun%.rev_depend(
|
||||||
|
%parameter_x%, %type_x%, %depend_x%, %depend_y%
|
||||||
|
)%$$
|
||||||
|
|
||||||
|
$head See Also$$
|
||||||
|
$cref chkpoint_two$$, $cref atomic_two$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
|
||||||
|
$subhead Speed$$
|
||||||
|
In some cases, it is possible to compute derivatives of a function
|
||||||
|
$latex \[
|
||||||
|
y = g(x) \; {\rm where} \; g : \B{R}^n \rightarrow \B{R}^m
|
||||||
|
\] $$
|
||||||
|
more efficiently than by coding it using $codei%AD<%Base%>%$$
|
||||||
|
$cref/atomic/glossary/Operation/Atomic/$$ operations
|
||||||
|
and letting CppAD do the rest.
|
||||||
|
The class $codei%atomic_three%<%Base%>%$$ is used to
|
||||||
|
create a new atomic operation corresponding to a function $latex g(x)$$
|
||||||
|
where the user specifies how to compute the derivatives
|
||||||
|
and sparsity patterns for $latex g(x)$$.
|
||||||
|
|
||||||
|
$subhead Reduce Memory$$
|
||||||
|
If the function $latex g(x)$$ is many times during the recording
|
||||||
|
of an $cref ADFun$$ object,
|
||||||
|
using an atomic version of $latex g(x)$$ removed the need for repeated
|
||||||
|
copies of the corresponding $codei%AD<%Base%>%$$ operations and variables
|
||||||
|
in the recording.
|
||||||
|
|
||||||
|
$head ad_type$$
|
||||||
|
The type $code CppAD::ad_type_enum$$
|
||||||
|
is used to specify if an AD object is a
|
||||||
|
$cref/constant parameter/glossary/Parameter/Constant/$$
|
||||||
|
$cref/dynamic parameter/glossary/Parameter/Dynamic/$$
|
||||||
|
or $cref/variable/glossary/Variable/$$.
|
||||||
|
It has the following possible values:
|
||||||
|
$center
|
||||||
|
$table
|
||||||
|
$icode ad_type_enum$$ $pre $$ $cnext Meaning $rnext
|
||||||
|
$code constant_enum$$ $pre $$ $cnext constant parameter $rnext
|
||||||
|
$code dynamic_enum$$ $pre $$ $cnext dynamic parameter $rnext
|
||||||
|
$code variable_enum$$ $pre $$ $cnext variable
|
||||||
|
$tend
|
||||||
|
$$
|
||||||
|
In addition,
|
||||||
|
$code constant_enum < dynamic_enum < variable_enum$$.
|
||||||
|
|
||||||
|
$head Virtual Functions$$
|
||||||
|
The $cref/callback functions/atomic_three/Syntax/Class Member Callbacks/$$
|
||||||
|
are implemented by defining the virtual functions in the
|
||||||
|
$icode atomic_user$$ class.
|
||||||
|
These functions compute derivatives,
|
||||||
|
sparsity patterns, and dependency relations.
|
||||||
|
Each virtual function has a default implementation
|
||||||
|
that returns $icode%ok% == false%$$.
|
||||||
|
The $cref/for_type/atomic_three_for_type/$$
|
||||||
|
and $cref/forward/atomic_three_forward/$$ function
|
||||||
|
(for the case $icode%order_up% == 0%$$) must be implemented.
|
||||||
|
Otherwise, only those functions and orders
|
||||||
|
required by the your calculations need to be implemented.
|
||||||
|
For example,
|
||||||
|
$icode forward$$ for the case $icode%order_up% == 2%$$ can just return
|
||||||
|
$icode%ok% == false%$$ unless you require
|
||||||
|
forward mode calculation of second derivatives.
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
This is the type of the elements of
|
||||||
|
$cref/ax/atomic_three_afun/ax/$$ and $cref/ay/atomic_three_afun/ay/$$
|
||||||
|
in the corresponding $icode%afun%(%ax%, %ay%)%$$ call.
|
||||||
|
|
||||||
|
$head parameter_x$$
|
||||||
|
All the virtual functions include this argument which has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%> %parameter_x%
|
||||||
|
%$$
|
||||||
|
Its size is equal to $icode%n% = %ax%.size()%$$
|
||||||
|
in corresponding $icode%afun%(%ax%, %ay%)%$$ call.
|
||||||
|
|
||||||
|
$subhead Constant$$
|
||||||
|
For $icode%j% =0,%...%,%n%-1%$$,
|
||||||
|
if $icode%ax%[%j%]%$$ is a $cref/constant/con_dyn_var/Constant/$$ parameter,
|
||||||
|
$codei%
|
||||||
|
%parameter_x%[%j%] == %ax%[%j%]
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$subhead Dynamic$$
|
||||||
|
If $icode%ax%[%j%]%$$ is a $cref/dynamic/con_dyn_var/Dynamic/$$ parameter,
|
||||||
|
$icode%parameter_x%[%j%]%$$ value of $icode%ax%[%j%]%$$ corresponding to the
|
||||||
|
previous call to $cref new_dynamic$$ for the corresponding function object.
|
||||||
|
|
||||||
|
$subhead Variable$$
|
||||||
|
If $icode%ax%[%j%]%$$ is a variable,
|
||||||
|
the value of $icode%parameter_x%[%j%]%$$ is not specified.
|
||||||
|
See the
|
||||||
|
$cref/atomic_three_mat_mul.hpp/atomic_three_mat_mul.hpp/Purpose/parameter_x/$$
|
||||||
|
for an example using $icode parameter_x$$.
|
||||||
|
|
||||||
|
$head type_x$$
|
||||||
|
All the virtual functions include this argument.
|
||||||
|
Its size is equal to $icode%n% = %ax%.size()%$$
|
||||||
|
in corresponding $icode%afun%(%ax%, %ay%)%$$ call.
|
||||||
|
For $icode%j% =0,%...%,%n%-1%$$,
|
||||||
|
if $icode%ax%[%j%]%$$ is a constant parameter,
|
||||||
|
$codei%
|
||||||
|
%type_x%[%j%] == CppAD::constant_enum
|
||||||
|
%$$
|
||||||
|
if $icode%ax%[%j%]%$$ is a dynamic parameter,
|
||||||
|
$codei%
|
||||||
|
%type_x%[%j%] == CppAD::dynamic_enum
|
||||||
|
%$$
|
||||||
|
if $icode%ax%[%j%]%$$ is a variable,
|
||||||
|
$codei%
|
||||||
|
%type_x%[%j%] == CppAD::variable_enum
|
||||||
|
%$$
|
||||||
|
See the
|
||||||
|
$cref/atomic_three_mat_mul.hpp/atomic_three_mat_mul.hpp/Purpose/type_x/$$
|
||||||
|
for an example using $icode type_x$$.
|
||||||
|
|
||||||
|
|
||||||
|
$childtable%include/cppad/core/atomic/three_ctor.hpp
|
||||||
|
%include/cppad/core/atomic/three_afun.hpp
|
||||||
|
%include/cppad/core/atomic/three_for_type.hpp
|
||||||
|
%include/cppad/core/atomic/three_forward.hpp
|
||||||
|
%include/cppad/core/atomic/three_reverse.hpp
|
||||||
|
%include/cppad/core/atomic/three_jac_sparsity.hpp
|
||||||
|
%include/cppad/core/atomic/three_hes_sparsity.hpp
|
||||||
|
%include/cppad/core/atomic/three_rev_depend.hpp
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$end
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$begin atomic_three_example$$
|
||||||
|
|
||||||
|
$section Example Defining Atomic Functions: Third Generation$$
|
||||||
|
|
||||||
|
$childtable%example/atomic_three/get_started.cpp
|
||||||
|
%example/atomic_three/norm_sq.cpp
|
||||||
|
%example/atomic_three/tangent.cpp
|
||||||
|
%example/atomic_three/base2ad.cpp
|
||||||
|
%example/atomic_three/reciprocal.cpp
|
||||||
|
%example/atomic_three/mat_mul.cpp
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$end
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include <set>
|
||||||
|
# include <cppad/core/cppad_assert.hpp>
|
||||||
|
# include <cppad/local/atomic_index.hpp>
|
||||||
|
|
||||||
|
// needed before one can use in_parallel
|
||||||
|
# include <cppad/utility/thread_alloc.hpp>
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic_three.hpp
|
||||||
|
Base class for atomic function operations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
class atomic_three {
|
||||||
|
// ===================================================================
|
||||||
|
private:
|
||||||
|
// ------------------------------------------------------
|
||||||
|
// constants
|
||||||
|
//
|
||||||
|
/// index of this object in lcal::atomic_index
|
||||||
|
/// (set by constructor and not changed; i.e., effectively const)
|
||||||
|
size_t index_;
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------
|
||||||
|
//
|
||||||
|
/// temporary work space used by member functions, declared here to avoid
|
||||||
|
// memory allocation/deallocation for each usage
|
||||||
|
struct work_struct {
|
||||||
|
vector<ad_type_enum> type_x;
|
||||||
|
vector<ad_type_enum> type_y;
|
||||||
|
//
|
||||||
|
vector<Base> taylor_x;
|
||||||
|
vector<Base> taylor_y;
|
||||||
|
//
|
||||||
|
vector< AD<Base> > ataylor_x;
|
||||||
|
vector< AD<Base> > ataylor_y;
|
||||||
|
//
|
||||||
|
sparse_rc< vector<size_t> > pattern;
|
||||||
|
};
|
||||||
|
// Use pointers, to avoid false sharing between threads.
|
||||||
|
// Not using: vector<work_struct*> work_;
|
||||||
|
// so that deprecated atomic examples do not result in a memory leak.
|
||||||
|
work_struct* work_[CPPAD_MAX_NUM_THREADS];
|
||||||
|
// -----------------------------------------------------
|
||||||
|
public:
|
||||||
|
// =====================================================================
|
||||||
|
// In User API
|
||||||
|
// =====================================================================
|
||||||
|
//
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// ctor: doxygen in atomic/three_ctor.hpp
|
||||||
|
atomic_three(void);
|
||||||
|
atomic_three(const std::string& name);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// operator(): see doxygen in atomic_three/afun.hpp
|
||||||
|
template <class ADVector>
|
||||||
|
void operator()(
|
||||||
|
const ADVector& ax ,
|
||||||
|
ADVector& ay
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// type: doxygen in atomic/three_for_type.hpp
|
||||||
|
virtual bool for_type(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<ad_type_enum>& type_y
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// type: doxygen in atomic/three_rev_depend.hpp
|
||||||
|
virtual bool rev_depend(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<bool>& depend_x ,
|
||||||
|
const vector<bool>& depend_y
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// forward: see docygen in atomic/three_forward.hpp
|
||||||
|
virtual bool forward(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t need_y ,
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
vector<Base>& taylor_y
|
||||||
|
);
|
||||||
|
virtual bool forward(
|
||||||
|
const vector< AD<Base> >& aparameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t need_y ,
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
vector< AD<Base> >& ataylor_y
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// reverse: see docygen in atomic/three_reverse.hpp
|
||||||
|
virtual bool reverse(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
const vector<Base>& taylor_y ,
|
||||||
|
vector<Base>& partial_x ,
|
||||||
|
const vector<Base>& partial_y
|
||||||
|
);
|
||||||
|
virtual bool reverse(
|
||||||
|
const vector< AD<Base> >& aparameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
const vector< AD<Base> >& ataylor_y ,
|
||||||
|
vector< AD<Base> >& apartial_x ,
|
||||||
|
const vector< AD<Base> >& apartial_y
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// jac_sparsity: see doxygen in atomic/three_jac_sparsity.hpp
|
||||||
|
virtual bool jac_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
bool dependency ,
|
||||||
|
const vector<bool>& select_x ,
|
||||||
|
const vector<bool>& select_y ,
|
||||||
|
sparse_rc< vector<size_t> >& pattern_out
|
||||||
|
);
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool for_jac_sparsity(
|
||||||
|
bool dependency ,
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
InternalSparsity& var_sparsity
|
||||||
|
);
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool rev_jac_sparsity(
|
||||||
|
bool dependency ,
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
InternalSparsity& var_sparsity
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// hes_sparsity: see doxygen in atomic/three_jac_sparsity.hpp
|
||||||
|
virtual bool hes_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const vector<bool>& select_x ,
|
||||||
|
const vector<bool>& select_y ,
|
||||||
|
sparse_rc< vector<size_t> >& pattern_out
|
||||||
|
);
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool for_hes_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
size_t np1 ,
|
||||||
|
size_t numvar ,
|
||||||
|
const InternalSparsity& rev_jac_sparsity ,
|
||||||
|
InternalSparsity& for_sparsity
|
||||||
|
);
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool rev_hes_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
const InternalSparsity& for_jac_pattern ,
|
||||||
|
bool* rev_jac_flag ,
|
||||||
|
InternalSparsity& hes_sparsity
|
||||||
|
);
|
||||||
|
|
||||||
|
// =====================================================================
|
||||||
|
// Not in User API
|
||||||
|
// =====================================================================
|
||||||
|
|
||||||
|
/// Name corresponding to a atomic_three object
|
||||||
|
const std::string atomic_name(void) const
|
||||||
|
{ bool set_null = false;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string name;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
local::atomic_index<Base>(set_null, index_, type, &name, v_ptr);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type == 3 );
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
/// destructor informs CppAD that this atomic function with this index
|
||||||
|
/// has dropped out of scope by setting its pointer to null
|
||||||
|
virtual ~atomic_three(void)
|
||||||
|
{ // change object pointer to null, but leave name for error reporting
|
||||||
|
bool set_null = true;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string* name = nullptr;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
local::atomic_index<Base>(set_null, index_, type, name, v_ptr);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type == 3 );
|
||||||
|
//
|
||||||
|
// free temporary work memory
|
||||||
|
for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)
|
||||||
|
free_work(thread);
|
||||||
|
}
|
||||||
|
/// allocates work_ for a specified thread
|
||||||
|
void allocate_work(size_t thread)
|
||||||
|
{ if( work_[thread] == nullptr )
|
||||||
|
{ // allocate the raw memory
|
||||||
|
size_t min_bytes = sizeof(work_struct);
|
||||||
|
size_t num_bytes;
|
||||||
|
void* v_ptr = thread_alloc::get_memory(min_bytes, num_bytes);
|
||||||
|
// save in work_
|
||||||
|
work_[thread] = reinterpret_cast<work_struct*>( v_ptr );
|
||||||
|
// call constructor
|
||||||
|
new( work_[thread] ) work_struct;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/// frees work_ for a specified thread
|
||||||
|
void free_work(size_t thread)
|
||||||
|
{ if( work_[thread] != nullptr )
|
||||||
|
{ // call destructor
|
||||||
|
work_[thread]->~work_struct();
|
||||||
|
// return memory to avialable pool for this thread
|
||||||
|
thread_alloc::return_memory(
|
||||||
|
reinterpret_cast<void*>(work_[thread])
|
||||||
|
);
|
||||||
|
// mark this thread as not allocated
|
||||||
|
work_[thread] = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/// atomic_three function object corresponding to a certain index
|
||||||
|
static atomic_three* class_object(size_t index)
|
||||||
|
{ bool set_null = false;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string* name = nullptr;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
local::atomic_index<Base>(set_null, index, type, name, v_ptr);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type == 3 );
|
||||||
|
return reinterpret_cast<atomic_three*>( v_ptr );
|
||||||
|
}
|
||||||
|
/// atomic_three function name corresponding to a certain index
|
||||||
|
static const std::string class_name(size_t index)
|
||||||
|
{ bool set_null = false;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string name;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
local::atomic_index<Base>(set_null, index, type, &name, v_ptr);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type == 3 );
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Set value of id (used by deprecated atomic_one class)
|
||||||
|
|
||||||
|
This function is called just before calling any of the virtual function
|
||||||
|
and has the corresponding id of the corresponding virtual call.
|
||||||
|
*/
|
||||||
|
virtual void set_old(size_t id)
|
||||||
|
{ }
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
};
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
// member functions
|
||||||
|
# include <cppad/core/atomic/three_ctor.hpp>
|
||||||
|
# include <cppad/core/atomic/three_afun.hpp>
|
||||||
|
# include <cppad/core/atomic/three_for_type.hpp>
|
||||||
|
# include <cppad/core/atomic/three_rev_depend.hpp>
|
||||||
|
# include <cppad/core/atomic/three_forward.hpp>
|
||||||
|
# include <cppad/core/atomic/three_reverse.hpp>
|
||||||
|
# include <cppad/core/atomic/three_jac_sparsity.hpp>
|
||||||
|
# include <cppad/core/atomic/three_hes_sparsity.hpp>
|
||||||
|
|
||||||
|
# endif
|
||||||
613
build-config/cppad/include/cppad/core/atomic/atomic_two.hpp
Normal file
613
build-config/cppad/include/cppad/core/atomic/atomic_two.hpp
Normal file
@@ -0,0 +1,613 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_ATOMIC_TWO_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_ATOMIC_TWO_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two$$
|
||||||
|
$spell
|
||||||
|
ctor
|
||||||
|
afun
|
||||||
|
arg
|
||||||
|
vx
|
||||||
|
vy
|
||||||
|
tx
|
||||||
|
ty
|
||||||
|
px
|
||||||
|
py
|
||||||
|
jac
|
||||||
|
hes
|
||||||
|
CppAD
|
||||||
|
checkpointing
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Defining Atomic Functions: Second Generation$$
|
||||||
|
|
||||||
|
$head Deprecated 2019-01-01$$
|
||||||
|
Using the $code atomic_base$$ class has been deprecated.
|
||||||
|
Use $cref atomic_three$$ instead.
|
||||||
|
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
|
||||||
|
$codei%
|
||||||
|
%atomic_user% %afun%(%ctor_arg_list%)
|
||||||
|
%afun%(%ax%, %ay%)
|
||||||
|
%ok% = %afun%.forward(%p%, %q%, %vx%, %vy%, %tx%, %ty%)
|
||||||
|
%ok% = %afun%.reverse(%q%, %tx%, %ty%, %px%, %py%)
|
||||||
|
%ok% = %afun%.for_sparse_jac(%q%, %r%, %s%, %x%)
|
||||||
|
%ok% = %afun%.rev_sparse_jac(%q%, %r%, %s%, %x%)
|
||||||
|
%ok% = %afun%.for_sparse_hes(%vx%, %r%, %s%, %h%, %x%)
|
||||||
|
%ok% = %afun%.rev_sparse_hes(%vx%, %s%, %t%, %q%, %r%, %u%, %v%, %x%)
|
||||||
|
atomic_base<%Base%>::clear()%$$
|
||||||
|
|
||||||
|
$head See Also$$
|
||||||
|
$cref/checkpoint/chkpoint_one/$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
|
||||||
|
$subhead Speed$$
|
||||||
|
In some cases, the user knows how to compute derivatives of a function
|
||||||
|
$latex \[
|
||||||
|
y = f(x) \; {\rm where} \; f : \B{R}^n \rightarrow \B{R}^m
|
||||||
|
\] $$
|
||||||
|
more efficiently than by coding it using $codei%AD<%Base%>%$$
|
||||||
|
$cref/atomic_base/glossary/Operation/Atomic/$$ operations
|
||||||
|
and letting CppAD do the rest.
|
||||||
|
In this case $codei%atomic_base%<%Base%>%$$ can use
|
||||||
|
the user code for $latex f(x)$$, and its derivatives,
|
||||||
|
as $codei%AD<%Base%>%$$ atomic operations.
|
||||||
|
|
||||||
|
$subhead Reduce Memory$$
|
||||||
|
If the function $latex f(x)$$ is used often,
|
||||||
|
using an atomic version of $latex f(x)$$ remove the need for repeated
|
||||||
|
copies of the corresponding $codei%AD<%Base%>%$$ operations.
|
||||||
|
|
||||||
|
$head Virtual Functions$$
|
||||||
|
User defined derivatives are implemented by defining the
|
||||||
|
following virtual functions in the $icode atomic_base$$ class:
|
||||||
|
$cref/forward/atomic_two_forward/$$,
|
||||||
|
$cref/reverse/atomic_two_reverse/$$,
|
||||||
|
$cref/for_sparse_jac/atomic_two_for_sparse_jac/$$,
|
||||||
|
$cref/rev_sparse_jac/atomic_two_rev_sparse_jac/$$, and
|
||||||
|
$cref/rev_sparse_hes/atomic_two_rev_sparse_hes/$$.
|
||||||
|
These virtual functions have a default implementation
|
||||||
|
that returns $icode%ok% == false%$$.
|
||||||
|
The $code forward$$ function,
|
||||||
|
for the case $icode%q% == 0%$$, must be implemented.
|
||||||
|
Otherwise, only those functions
|
||||||
|
required by the your calculations need to be implemented.
|
||||||
|
For example,
|
||||||
|
$icode forward$$ for the case $icode%q% == 2%$$ can just return
|
||||||
|
$icode%ok% == false%$$ unless you require
|
||||||
|
forward mode calculation of second derivatives.
|
||||||
|
|
||||||
|
$head Examples$$
|
||||||
|
See $cref atomic_two_example$$.
|
||||||
|
|
||||||
|
$childtable%
|
||||||
|
include/cppad/core/atomic/two_ctor.hpp%
|
||||||
|
include/cppad/core/atomic/two_option.hpp%
|
||||||
|
include/cppad/core/atomic/two_afun.hpp%
|
||||||
|
include/cppad/core/atomic/two_forward.hpp%
|
||||||
|
include/cppad/core/atomic/two_reverse.hpp%
|
||||||
|
include/cppad/core/atomic/two_for_sparse_jac.hpp%
|
||||||
|
include/cppad/core/atomic/two_rev_sparse_jac.hpp%
|
||||||
|
include/cppad/core/atomic/two_for_sparse_hes.hpp%
|
||||||
|
include/cppad/core/atomic/two_rev_sparse_hes.hpp%
|
||||||
|
include/cppad/core/atomic/two_clear.hpp
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$end
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$begin atomic_two_example$$
|
||||||
|
|
||||||
|
$section Example Defining Atomic Functions: Second Generation$$
|
||||||
|
|
||||||
|
$head Getting Started$$
|
||||||
|
that shows the minimal amount of information required to create
|
||||||
|
a user defined atomic operation.
|
||||||
|
|
||||||
|
$head Scalar Function$$
|
||||||
|
where the user provides the code for computing derivatives.
|
||||||
|
This example is simple because the domain and range are scalars.
|
||||||
|
|
||||||
|
$head Vector Range$$
|
||||||
|
where the user provides the code for computing derivatives.
|
||||||
|
This example is more complex because the range has two components.
|
||||||
|
|
||||||
|
$head Hessian Sparsity Patterns$$
|
||||||
|
where the user provides the code for computing Hessian sparsity patterns.
|
||||||
|
|
||||||
|
$childtable%
|
||||||
|
example/atomic_two/eigen_mat_mul.cpp%
|
||||||
|
example/atomic_two/eigen_mat_inv.cpp%
|
||||||
|
example/atomic_two/eigen_cholesky.cpp
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$end
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include <set>
|
||||||
|
# include <cppad/core/cppad_assert.hpp>
|
||||||
|
# include <cppad/local/sparse/internal.hpp>
|
||||||
|
# include <cppad/local/atomic_index.hpp>
|
||||||
|
|
||||||
|
// needed before one can use in_parallel
|
||||||
|
# include <cppad/utility/thread_alloc.hpp>
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic_two.hpp
|
||||||
|
Base class for atomic function operations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
class atomic_base {
|
||||||
|
// ===================================================================
|
||||||
|
public:
|
||||||
|
enum option_enum {
|
||||||
|
pack_sparsity_enum ,
|
||||||
|
bool_sparsity_enum ,
|
||||||
|
set_sparsity_enum
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
// ------------------------------------------------------
|
||||||
|
// constants
|
||||||
|
//
|
||||||
|
/// index of this object in local::atomic_index
|
||||||
|
/// (set by constructor and not changed; i.e., effectively const)
|
||||||
|
size_t index_;
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// variables
|
||||||
|
//
|
||||||
|
/// sparsity pattern this object is currently using
|
||||||
|
/// (set by constructor and option member functions)
|
||||||
|
option_enum sparsity_;
|
||||||
|
//
|
||||||
|
/// temporary work space used by member functions, declared here to avoid
|
||||||
|
// memory allocation/deallocation for each usage
|
||||||
|
struct work_struct {
|
||||||
|
vector<bool> vx;
|
||||||
|
vector<bool> vy;
|
||||||
|
//
|
||||||
|
vector<Base> tx;
|
||||||
|
vector<Base> ty;
|
||||||
|
//
|
||||||
|
vector< AD<Base> > atx;
|
||||||
|
vector< AD<Base> > aty;
|
||||||
|
//
|
||||||
|
vector<bool> bool_t;
|
||||||
|
//
|
||||||
|
vectorBool pack_h;
|
||||||
|
vectorBool pack_r;
|
||||||
|
vectorBool pack_s;
|
||||||
|
vectorBool pack_u;
|
||||||
|
//
|
||||||
|
vector<bool> bool_h;
|
||||||
|
vector<bool> bool_r;
|
||||||
|
vector<bool> bool_s;
|
||||||
|
vector<bool> bool_u;
|
||||||
|
//
|
||||||
|
vector< std::set<size_t> > set_h;
|
||||||
|
vector< std::set<size_t> > set_r;
|
||||||
|
vector< std::set<size_t> > set_s;
|
||||||
|
vector< std::set<size_t> > set_u;
|
||||||
|
};
|
||||||
|
// Use pointers, to avoid false sharing between threads.
|
||||||
|
// Not using: vector<work_struct*> work_;
|
||||||
|
// so that deprecated atomic examples do not result in a memory leak.
|
||||||
|
work_struct* work_[CPPAD_MAX_NUM_THREADS];
|
||||||
|
public:
|
||||||
|
// =====================================================================
|
||||||
|
// In User API
|
||||||
|
// =====================================================================
|
||||||
|
//
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// ctor: doxygen in atomic_base/ctor.hpp
|
||||||
|
atomic_base(void);
|
||||||
|
atomic_base(
|
||||||
|
const std::string& name,
|
||||||
|
option_enum sparsity = bool_sparsity_enum
|
||||||
|
);
|
||||||
|
|
||||||
|
// option: see doxygen in atomic_base/option.hpp
|
||||||
|
void option(enum option_enum option_value);
|
||||||
|
|
||||||
|
// operator(): see doxygen in atomic_base/afun.hpp
|
||||||
|
template <class ADVector>
|
||||||
|
void operator()(
|
||||||
|
const ADVector& ax ,
|
||||||
|
ADVector& ay ,
|
||||||
|
size_t id = 0
|
||||||
|
);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// base_two version of forward
|
||||||
|
virtual bool forward(
|
||||||
|
size_t p ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
vector<bool>& vy ,
|
||||||
|
const vector<Base>& tx ,
|
||||||
|
vector<Base>& ty
|
||||||
|
);
|
||||||
|
virtual bool forward(
|
||||||
|
size_t p ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
vector<bool>& vy ,
|
||||||
|
const vector< AD<Base> >& atx ,
|
||||||
|
vector< AD<Base> >& aty
|
||||||
|
);
|
||||||
|
// base_three version of forward
|
||||||
|
bool forward(
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<ad_type_enum>& type_y ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
vector<Base>& taylor_y
|
||||||
|
);
|
||||||
|
bool forward(
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<ad_type_enum>& type_y ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
vector< AD<Base> >& ataylor_y
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// reverse: see doxygen in atomic_base/reverse.hpp
|
||||||
|
virtual bool reverse(
|
||||||
|
size_t q ,
|
||||||
|
const vector<Base>& tx ,
|
||||||
|
const vector<Base>& ty ,
|
||||||
|
vector<Base>& px ,
|
||||||
|
const vector<Base>& py
|
||||||
|
);
|
||||||
|
virtual bool reverse(
|
||||||
|
size_t q ,
|
||||||
|
const vector< AD<Base> >& atx ,
|
||||||
|
const vector< AD<Base> >& aty ,
|
||||||
|
vector< AD<Base> >& apx ,
|
||||||
|
const vector< AD<Base> >& apy
|
||||||
|
);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// for_sparse_jac: see doxygen in atomic_base/for_sparse_jac.hpp
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
vector< std::set<size_t> >& s ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
vector<bool>& s ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
vectorBool& s ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool for_sparse_jac(
|
||||||
|
const vector<Base>& x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
InternalSparsity& var_sparsity
|
||||||
|
);
|
||||||
|
// deprecated versions
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
vector< std::set<size_t> >& s
|
||||||
|
);
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
vector<bool>& s
|
||||||
|
);
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
vectorBool& s
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// rev_sparse_jac: see doxygen in atomic_base/rev_sparse_jac.hpp
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& rt ,
|
||||||
|
vector< std::set<size_t> >& st ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& rt ,
|
||||||
|
vector<bool>& st ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& rt ,
|
||||||
|
vectorBool& st ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool rev_sparse_jac(
|
||||||
|
const vector<Base>& x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
InternalSparsity& var_sparsity
|
||||||
|
);
|
||||||
|
// deprecated versions
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& rt ,
|
||||||
|
vector< std::set<size_t> >& st
|
||||||
|
);
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& rt ,
|
||||||
|
vector<bool>& st
|
||||||
|
);
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& rt ,
|
||||||
|
vectorBool& st
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// for_sparse_hes: see doxygen in atomic_base/for_sparse_hes.hpp
|
||||||
|
virtual bool for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector< std::set<size_t> >& h ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
virtual bool for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& h ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
virtual bool for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vectorBool& h ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool for_sparse_hes(
|
||||||
|
const vector<Base>& x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
size_t np1 ,
|
||||||
|
size_t numvar ,
|
||||||
|
const InternalSparsity& rev_jac_sparsity ,
|
||||||
|
InternalSparsity& for_sparsity
|
||||||
|
);
|
||||||
|
// deprecated versions
|
||||||
|
virtual bool for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector< std::set<size_t> >& h
|
||||||
|
);
|
||||||
|
virtual bool for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& h
|
||||||
|
);
|
||||||
|
virtual bool for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vectorBool& h
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// rev_sparse_hes: see doxygen in atomic_base/rev_sparse_hes.hpp
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
const vector< std::set<size_t> >& u ,
|
||||||
|
vector< std::set<size_t> >& v ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& u ,
|
||||||
|
vector<bool>& v ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
const vectorBool& u ,
|
||||||
|
vectorBool& v ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool rev_sparse_hes(
|
||||||
|
const vector<Base>& x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
const InternalSparsity& for_jac_sparsity ,
|
||||||
|
bool* rev_jac_flag ,
|
||||||
|
InternalSparsity& rev_hes_sparsity
|
||||||
|
);
|
||||||
|
// deprecated
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
const vector< std::set<size_t> >& u ,
|
||||||
|
vector< std::set<size_t> >& v
|
||||||
|
);
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& u ,
|
||||||
|
vector<bool>& v
|
||||||
|
);
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
const vectorBool& u ,
|
||||||
|
vectorBool& v
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// atomic_three like interface for reverse dependency analysis
|
||||||
|
bool rev_depend(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<bool>& depend_x ,
|
||||||
|
const vector<bool>& depend_y
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// clear: see doxygen in atomic_base/clear.hpp
|
||||||
|
static void clear(void);
|
||||||
|
|
||||||
|
// =====================================================================
|
||||||
|
// Not in User API
|
||||||
|
// =====================================================================
|
||||||
|
|
||||||
|
/// current sparsity setting
|
||||||
|
option_enum sparsity(void) const
|
||||||
|
{ return sparsity_; }
|
||||||
|
|
||||||
|
/// Name corresponding to a atomic_base object
|
||||||
|
const std::string atomic_name(void) const
|
||||||
|
{ bool set_null = false;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string name;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
local::atomic_index<Base>(set_null, index_, type, &name, v_ptr);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type == 2 );
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
/// destructor informs CppAD that this atomic function with this index
|
||||||
|
/// has dropped out of scope by setting its pointer to null
|
||||||
|
virtual ~atomic_base(void)
|
||||||
|
{ // change object pointer to null, but leave name for error reporting
|
||||||
|
bool set_null = true;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string* name = nullptr;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
local::atomic_index<Base>(set_null, index_, type, name, v_ptr);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type == 2 );
|
||||||
|
//
|
||||||
|
// free temporary work memory
|
||||||
|
for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)
|
||||||
|
free_work(thread);
|
||||||
|
}
|
||||||
|
/// allocates work_ for a specified thread
|
||||||
|
void allocate_work(size_t thread)
|
||||||
|
{ if( work_[thread] == nullptr )
|
||||||
|
{ // allocate the raw memory
|
||||||
|
size_t min_bytes = sizeof(work_struct);
|
||||||
|
size_t num_bytes;
|
||||||
|
void* v_ptr = thread_alloc::get_memory(min_bytes, num_bytes);
|
||||||
|
// save in work_
|
||||||
|
work_[thread] = reinterpret_cast<work_struct*>( v_ptr );
|
||||||
|
// call constructor
|
||||||
|
new( work_[thread] ) work_struct;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/// frees work_ for a specified thread
|
||||||
|
void free_work(size_t thread)
|
||||||
|
{ if( work_[thread] != nullptr )
|
||||||
|
{ // call destructor
|
||||||
|
work_[thread]->~work_struct();
|
||||||
|
// return memory to avialable pool for this thread
|
||||||
|
thread_alloc::return_memory(
|
||||||
|
reinterpret_cast<void*>(work_[thread])
|
||||||
|
);
|
||||||
|
// mark this thread as not allocated
|
||||||
|
work_[thread] = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/// atomic_base function object corresponding to a certain index
|
||||||
|
static atomic_base* class_object(size_t index)
|
||||||
|
{ bool set_null = false;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string* name = nullptr;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
local::atomic_index<Base>(set_null, index, type, name, v_ptr);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type == 2 );
|
||||||
|
return reinterpret_cast<atomic_base*>( v_ptr );
|
||||||
|
}
|
||||||
|
/// atomic_base function name corresponding to a certain index
|
||||||
|
static const std::string class_name(size_t index)
|
||||||
|
{ bool set_null = false;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string name;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
local::atomic_index<Base>(set_null, index, type, &name, v_ptr);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type == 2 );
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Set value of id (used by deprecated atomic_one class)
|
||||||
|
|
||||||
|
This function is called just before calling any of the virtual function
|
||||||
|
and has the corresponding id of the corresponding virtual call.
|
||||||
|
*/
|
||||||
|
virtual void set_old(size_t id)
|
||||||
|
{ }
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
};
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
// functitons implemented in cppad/core/atomic_base files
|
||||||
|
# include <cppad/core/atomic/two_ctor.hpp>
|
||||||
|
# include <cppad/core/atomic/two_option.hpp>
|
||||||
|
# include <cppad/core/atomic/two_afun.hpp>
|
||||||
|
# include <cppad/core/atomic/two_forward.hpp>
|
||||||
|
# include <cppad/core/atomic/two_reverse.hpp>
|
||||||
|
# include <cppad/core/atomic/two_for_sparse_jac.hpp>
|
||||||
|
# include <cppad/core/atomic/two_rev_sparse_jac.hpp>
|
||||||
|
# include <cppad/core/atomic/two_for_sparse_hes.hpp>
|
||||||
|
# include <cppad/core/atomic/two_rev_sparse_hes.hpp>
|
||||||
|
# include <cppad/core/atomic/two_rev_depend.hpp>
|
||||||
|
# include <cppad/core/atomic/two_clear.hpp>
|
||||||
|
|
||||||
|
# endif
|
||||||
248
build-config/cppad/include/cppad/core/atomic/three_afun.hpp
Normal file
248
build-config/cppad/include/cppad/core/atomic/three_afun.hpp
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_THREE_AFUN_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_THREE_AFUN_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three_afun$$
|
||||||
|
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul
|
||||||
|
afun
|
||||||
|
const
|
||||||
|
CppAD
|
||||||
|
mat_mul.cpp
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Using AD Version of an Atomic Function$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%afun%(%ax%, %ay%)%$$
|
||||||
|
|
||||||
|
$head Prototype$$
|
||||||
|
$srcthisfile%
|
||||||
|
0%// BEGIN_PROTOTYPE%// END_PROTOTYPE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
Given $icode ax$$, this call computes the corresponding value of $icode ay$$.
|
||||||
|
If $codei%AD<%Base%>%$$ operations are being recorded,
|
||||||
|
it enters the computation as an atomic operation in the recording;
|
||||||
|
see $cref/start recording/Independent/Start Recording/$$.
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
This is the $icode Base$$ type of the elements of $icode ax$$ and $icode ay$$
|
||||||
|
in the call to the $icode afun$$ atomic operation.
|
||||||
|
To be specific, the elements of $icode ax$$ and $icode ay$$ have type
|
||||||
|
$codei%AD%<%Base%>%$$.
|
||||||
|
|
||||||
|
$head ADVector$$
|
||||||
|
The type $icode ADVector$$ must be a
|
||||||
|
$cref/simple vector class/SimpleVector/$$ with elements of type
|
||||||
|
$codei%AD<%Base%>%$$.
|
||||||
|
|
||||||
|
$head afun$$
|
||||||
|
is a $cref/atomic_user/atomic_three_ctor/atomic_user/$$ object
|
||||||
|
and this $icode afun$$ function call is implemented by the
|
||||||
|
$cref/atomic_three/atomic_three_ctor/atomic_three/$$ class.
|
||||||
|
|
||||||
|
$head ax$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const %ADVector%& %ax%
|
||||||
|
%$$
|
||||||
|
and size must be equal to $icode n$$.
|
||||||
|
It specifies vector $latex x \in \B{R}^n$$
|
||||||
|
at which an $codei%AD<%Base%>%$$ version of
|
||||||
|
$latex y = g(x)$$ is to be evaluated; see
|
||||||
|
$cref/Base/atomic_three_ctor/atomic_three/Base/$$.
|
||||||
|
|
||||||
|
$head ay$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
%ADVector%& %ay%
|
||||||
|
%$$
|
||||||
|
and size must be equal to $icode m$$.
|
||||||
|
The input values of its elements
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, it is an $codei%AD<%Base%>%$$ version of
|
||||||
|
$latex y = g(x)$$.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/three_afun.hpp
|
||||||
|
Implement user call to an atomic_three function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Implement the user call to afun(ax, ay)
|
||||||
|
|
||||||
|
\tparam ADVector
|
||||||
|
A simple vector class with elements of type AD<Base>.
|
||||||
|
|
||||||
|
\param ax
|
||||||
|
is the argument vector for this call,
|
||||||
|
ax.size() determines the number of arguments.
|
||||||
|
|
||||||
|
\param ay
|
||||||
|
is the result vector for this call,
|
||||||
|
ay.size() determines the number of results.
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
template <class ADVector>
|
||||||
|
void atomic_three<Base>::operator()(
|
||||||
|
const ADVector& ax ,
|
||||||
|
ADVector& ay )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{
|
||||||
|
|
||||||
|
size_t n = ax.size();
|
||||||
|
size_t m = ay.size();
|
||||||
|
# ifndef NDEBUG
|
||||||
|
bool ok = true;
|
||||||
|
std::string msg = "atomic_three: " + atomic_name() + ".eval: ";
|
||||||
|
if( (n == 0) | (m == 0) )
|
||||||
|
{ msg += "ax.size() or ay.size() is zero";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_work(thread);
|
||||||
|
vector<Base>& taylor_x = work_[thread]->taylor_x;
|
||||||
|
vector<Base>& taylor_y = work_[thread]->taylor_y;
|
||||||
|
vector<ad_type_enum>& type_x = work_[thread]->type_x;
|
||||||
|
vector<ad_type_enum>& type_y = work_[thread]->type_y;
|
||||||
|
//
|
||||||
|
type_x.resize(n);
|
||||||
|
taylor_x.resize(n);
|
||||||
|
//
|
||||||
|
type_y.resize(m);
|
||||||
|
taylor_y.resize(m);
|
||||||
|
//
|
||||||
|
// Determine tape corresponding to variables in ax
|
||||||
|
tape_id_t tape_id = 0;
|
||||||
|
local::ADTape<Base>* tape = nullptr;
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ taylor_x[j] = ax[j].value_;
|
||||||
|
if( Constant( ax[j] ) )
|
||||||
|
type_x[j] = constant_enum;
|
||||||
|
else
|
||||||
|
{ type_x[j] = ax[j].ad_type_;
|
||||||
|
if( tape_id == 0 )
|
||||||
|
{ tape = ax[j].tape_this();
|
||||||
|
tape_id = ax[j].tape_id_;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( tape != nullptr );
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( Dynamic( ax[j] ) )
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( type_x[j] == dynamic_enum );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( Variable( ax[j] ) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type_x[j] == variable_enum );
|
||||||
|
}
|
||||||
|
if( tape_id != ax[j].tape_id_ )
|
||||||
|
{ msg += atomic_name() +
|
||||||
|
": ax contains non-constant values from different threads.";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Use zero order forward mode to compute all the components of y
|
||||||
|
size_t need_y = size_t(variable_enum) + 1;
|
||||||
|
size_t order_low = 0;
|
||||||
|
size_t order_up = 0;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( need_y > size_t(variable_enum) );
|
||||||
|
# ifdef NDEBUG
|
||||||
|
forward(taylor_x, type_x, need_y, order_low, order_up, taylor_x, taylor_y);
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
if( type_x[j] == variable_enum )
|
||||||
|
taylor_x[j] = CppAD::numeric_limits<Base>::quiet_NaN();
|
||||||
|
for_type(taylor_x, type_x, type_y);
|
||||||
|
# else
|
||||||
|
ok &= forward(
|
||||||
|
taylor_x, type_x, need_y, order_low, order_up, taylor_x, taylor_y
|
||||||
|
);
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
if( type_x[j] == variable_enum )
|
||||||
|
taylor_x[j] = CppAD::numeric_limits<Base>::quiet_NaN();
|
||||||
|
ok &= for_type(taylor_x, type_x, type_y);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg += atomic_name() + ": ok is false for "
|
||||||
|
"type or zero order forward mode calculation.";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
bool record_dynamic = false;
|
||||||
|
bool record_variable = false;
|
||||||
|
//
|
||||||
|
// set ay to be vector of constant parameters with correct value
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ // pass back values
|
||||||
|
ay[i].value_ = taylor_y[i];
|
||||||
|
|
||||||
|
// initialize entire vector as constants
|
||||||
|
ay[i].tape_id_ = 0;
|
||||||
|
ay[i].taddr_ = 0;
|
||||||
|
|
||||||
|
// we need to record this operation if
|
||||||
|
// any of the elemnts of ay are dynamics or variables,
|
||||||
|
record_dynamic |= type_y[i] == dynamic_enum;
|
||||||
|
record_variable |= type_y[i] == variable_enum;
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( (record_dynamic || record_variable) && tape == nullptr )
|
||||||
|
{ msg +=
|
||||||
|
"all elements of x are constants but y contains a non-constant";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
if( record_dynamic)
|
||||||
|
{ tape->Rec_.put_dyn_atomic(tape_id, index_, type_x, type_y, ax, ay);
|
||||||
|
}
|
||||||
|
// case where result contains a variable
|
||||||
|
if( record_variable )
|
||||||
|
{ tape->Rec_.put_var_atomic(tape_id, index_, type_x, type_y, ax, ay);
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
for(size_t i = 0; i < m; ++i) switch( type_y[i] )
|
||||||
|
{ //
|
||||||
|
case constant_enum:
|
||||||
|
CPPAD_ASSERT_UNKNOWN( Constant( ay[i] ) );
|
||||||
|
break;
|
||||||
|
//
|
||||||
|
case dynamic_enum:
|
||||||
|
CPPAD_ASSERT_UNKNOWN( Dynamic( ay[i] ) );
|
||||||
|
break;
|
||||||
|
//
|
||||||
|
case variable_enum:
|
||||||
|
CPPAD_ASSERT_UNKNOWN( Variable( ay[i] ) );
|
||||||
|
break;
|
||||||
|
//
|
||||||
|
default:
|
||||||
|
CPPAD_ASSERT_KNOWN( false,
|
||||||
|
"atomic_three: for_type: type_y[i]: is not a valid type"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
165
build-config/cppad/include/cppad/core/atomic/three_ctor.hpp
Normal file
165
build-config/cppad/include/cppad/core/atomic/three_ctor.hpp
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_THREE_CTOR_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_THREE_CTOR_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three_ctor$$
|
||||||
|
$spell
|
||||||
|
enum
|
||||||
|
sq
|
||||||
|
std
|
||||||
|
afun
|
||||||
|
arg
|
||||||
|
CppAD
|
||||||
|
bool
|
||||||
|
ctor
|
||||||
|
const
|
||||||
|
mat_mul_xam.cpp
|
||||||
|
hpp
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Function Constructor$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$codei%class %atomic_user% : public CppAD::atomic_three<%Base%> {
|
||||||
|
public:
|
||||||
|
%atomic_user%(%ctor_arg_list%) : CppAD::atomic_three<%Base%>(%name%)
|
||||||
|
%...%
|
||||||
|
};
|
||||||
|
%$$
|
||||||
|
$icode%atomic_user afun%(%ctor_arg_list%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Prototype$$
|
||||||
|
$srcthisfile%
|
||||||
|
0%// BEGIN_PROTOTYPE%// END_PROTOTYPE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head atomic_user$$
|
||||||
|
|
||||||
|
$subhead ctor_arg_list$$
|
||||||
|
Is a list of arguments for the $icode atomic_user$$ constructor.
|
||||||
|
|
||||||
|
$subhead afun$$
|
||||||
|
The object $icode afun$$ must stay in scope for as long
|
||||||
|
as the corresponding atomic function is used.
|
||||||
|
This includes use by any $cref/ADFun<Base>/ADFun/$$ that
|
||||||
|
has this $icode atomic_user$$ operation in its
|
||||||
|
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||||
|
|
||||||
|
$subhead Implementation$$
|
||||||
|
The user defined $icode atomic_user$$ class is a publicly derived class of
|
||||||
|
$codei%atomic_three<%Base%>%$$.
|
||||||
|
It should be declared as follows:
|
||||||
|
$codei%
|
||||||
|
class %atomic_user% : public CppAD::atomic_three<%Base%> {
|
||||||
|
public:
|
||||||
|
%atomic_user%(%ctor_arg_list%) : atomic_three<%Base%>(%name%)
|
||||||
|
%...%
|
||||||
|
};
|
||||||
|
%$$
|
||||||
|
where $icode ...$$
|
||||||
|
denotes the rest of the implementation of the derived class.
|
||||||
|
This includes completing the constructor and
|
||||||
|
all the virtual functions that have their
|
||||||
|
$code atomic_three$$ implementations replaced by
|
||||||
|
$icode atomic_user$$ implementations.
|
||||||
|
|
||||||
|
$head atomic_three$$
|
||||||
|
|
||||||
|
$subhead Restrictions$$
|
||||||
|
The $code atomic_three$$ constructor and destructor cannot be called in
|
||||||
|
$cref/parallel/ta_in_parallel/$$ mode.
|
||||||
|
|
||||||
|
$subhead Base$$
|
||||||
|
The template parameter determines the
|
||||||
|
$cref/Base/atomic_three_afun/Base/$$
|
||||||
|
type for this $codei%AD<%Base%>%$$ atomic operation.
|
||||||
|
|
||||||
|
$subhead name$$
|
||||||
|
This $code atomic_three$$ constructor argument has the following prototype
|
||||||
|
$codei%
|
||||||
|
const std::string& %name%
|
||||||
|
%$$
|
||||||
|
It is the name for this atomic function and is used for error reporting.
|
||||||
|
The suggested value for $icode name$$ is $icode afun$$ or $icode atomic_user$$,
|
||||||
|
i.e., the name of the corresponding atomic object or class.
|
||||||
|
|
||||||
|
$head Example$$
|
||||||
|
|
||||||
|
$subhead Define Constructor$$
|
||||||
|
The following is an example of a atomic function constructor definition:
|
||||||
|
$cref%get_started.cpp%atomic_three_get_started.cpp%Constructor%$$.
|
||||||
|
|
||||||
|
$subhead Use Constructor$$
|
||||||
|
The following is an example using a atomic function constructor:
|
||||||
|
$cref%get_started.cpp
|
||||||
|
%atomic_three_get_started.cpp
|
||||||
|
%Use Atomic Function%Constructor
|
||||||
|
%$$.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/three_ctor.hpp
|
||||||
|
Constructors for atomic_three class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Base class for atomic_atomic functions.
|
||||||
|
|
||||||
|
\tparam Base
|
||||||
|
This class is used for defining an AD<Base> atomic operation y = g(x).
|
||||||
|
|
||||||
|
\par
|
||||||
|
make sure user does not invoke the default constructor
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
atomic_three<Base>::atomic_three(void)
|
||||||
|
{ CPPAD_ASSERT_KNOWN(false,
|
||||||
|
"Attempt to use the atomic_three default constructor"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
Constructor
|
||||||
|
|
||||||
|
\param name
|
||||||
|
name used for error reporting
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
atomic_three<Base>::atomic_three(const std::string& name )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ CPPAD_ASSERT_KNOWN(
|
||||||
|
! thread_alloc::in_parallel() ,
|
||||||
|
"atomic_three: constructor cannot be called in parallel mode."
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// atomic_index
|
||||||
|
bool set_null = false;
|
||||||
|
size_t index = 0;
|
||||||
|
size_t type = 3;
|
||||||
|
std::string copy_name = name;
|
||||||
|
void* copy_this = reinterpret_cast<void*>( this );
|
||||||
|
index_ = local::atomic_index<Base>(
|
||||||
|
set_null, index, type, ©_name, copy_this
|
||||||
|
);
|
||||||
|
// initialize work pointers as null;
|
||||||
|
for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)
|
||||||
|
work_[thread] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
117
build-config/cppad/include/cppad/core/atomic/three_for_type.hpp
Normal file
117
build-config/cppad/include/cppad/core/atomic/three_for_type.hpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_THREE_FOR_TYPE_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_THREE_FOR_TYPE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three_for_type$$
|
||||||
|
$spell
|
||||||
|
afun
|
||||||
|
enum
|
||||||
|
cpp
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Function Forward Type Calculation$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ok% = %afun%.for_type(%parameter_x%, %type_x%, %type_y%)%$$
|
||||||
|
|
||||||
|
$subhead Prototype$$
|
||||||
|
$srcthisfile%0%// BEGIN_PROTOTYPE%// END_PROTOTYPE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Dependency Analysis$$
|
||||||
|
This calculation is sometimes referred to as a forward dependency analysis.
|
||||||
|
|
||||||
|
$head Usage$$
|
||||||
|
This syntax and prototype are used by
|
||||||
|
$codei%
|
||||||
|
%afun%(%ax%, %ay%)
|
||||||
|
%$$
|
||||||
|
where $cref/afun/atomic_three_ctor/atomic_user/afun/$$
|
||||||
|
is a user defined atomic function.
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
This virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_three_ctor/atomic_user/$$ class.
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
See $cref/Base/atomic_three/Base/$$.
|
||||||
|
|
||||||
|
$head parameter_x$$
|
||||||
|
See $cref/parameter_x/atomic_three/parameter_x/$$.
|
||||||
|
|
||||||
|
$head type_x$$
|
||||||
|
See $cref/type_x/atomic_three/type_x/$$.
|
||||||
|
|
||||||
|
$head type_y$$
|
||||||
|
This vector has size equal to the number of results for this atomic function;
|
||||||
|
i.e. $icode%m%=%ay%.size()%$$.
|
||||||
|
The input values of the elements of $icode type_y$$
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, for $latex i = 0 , \ldots , m-1$$,
|
||||||
|
$icode%type_y%[%i%]%$$ is set to one of the following values:
|
||||||
|
$list number$$
|
||||||
|
It is $code constant_enum$$ if $icode%ay%[%i%]%$$ only depends on
|
||||||
|
the arguments that are constants.
|
||||||
|
$lnext
|
||||||
|
It is $code dynamic_enum$$ if $icode%ay%[%i%]%$$ depends on
|
||||||
|
a dynamic parameter and does not depend on any variables.
|
||||||
|
$lnext
|
||||||
|
It is $code variable_enum$$ if $icode%ay%[%i%]%$$ depends on
|
||||||
|
a variable.
|
||||||
|
$lend
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
If this calculation succeeded, $icode ok$$ is true.
|
||||||
|
Otherwise, it is false.
|
||||||
|
|
||||||
|
$head Example$$
|
||||||
|
The following is an example of a atomic function $code for_type$$ definition:
|
||||||
|
$cref%get_started.cpp%atomic_three_get_started.cpp%for_type%$$.
|
||||||
|
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/three_for_type.hpp
|
||||||
|
Third generation atomic type computation.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from atomic_three to type calculation
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
is the value of the parameters in the corresponding function call
|
||||||
|
afun(ax, ay).
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
specifies which components of x are
|
||||||
|
constants, dynamics, and variables
|
||||||
|
|
||||||
|
\param type_y [out]
|
||||||
|
specifies which components of y are
|
||||||
|
constants, dynamics, and variables
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_three<Base>::for_type(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<ad_type_enum>& type_y )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
# endif
|
||||||
346
build-config/cppad/include/cppad/core/atomic/three_forward.hpp
Normal file
346
build-config/cppad/include/cppad/core/atomic/three_forward.hpp
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_THREE_FORWARD_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_THREE_FORWARD_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three_forward$$
|
||||||
|
$spell
|
||||||
|
taylor
|
||||||
|
ataylor
|
||||||
|
af
|
||||||
|
afun
|
||||||
|
enum
|
||||||
|
CppAD
|
||||||
|
aparameter
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Function Forward Mode$$
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
This syntax and prototype are used by
|
||||||
|
$cref/afun(ax, ay)/atomic_three_afun/$$; see
|
||||||
|
$cref/Base/atomic_three_afun/Base/$$.
|
||||||
|
They are also used by
|
||||||
|
$icode%f%.Forward%$$ and $icode%f%.new_dynamic%$$
|
||||||
|
where $icode f$$ has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun<%Base%> %f%
|
||||||
|
%$$
|
||||||
|
and $icode afun$$ is used during the recording of $icode f$$.
|
||||||
|
|
||||||
|
$subhead Syntax$$
|
||||||
|
$icode%ok% = %afun%.forward(
|
||||||
|
%parameter_x%, %type_x%,
|
||||||
|
%need_y%, %order_low%, %order_up%, %type_x%, %taylor_x%, %taylor_y%
|
||||||
|
)%$$
|
||||||
|
|
||||||
|
$subhead Prototype$$
|
||||||
|
$srcthisfile%0%// BEGIN_PROTOTYPE_BASE%// END_PROTOTYPE_BASE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head AD<Base>$$
|
||||||
|
This syntax and prototype are used by
|
||||||
|
$icode%af%.Forward%$$ and $icode%af%.new_dynamic%$$
|
||||||
|
where $icode af$$ has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun< AD<%Base%> , %Base% > %af%
|
||||||
|
%$$
|
||||||
|
and $icode afun$$ is used in $icode af$$ (see $cref base2ad$$).
|
||||||
|
|
||||||
|
$subhead Syntax$$
|
||||||
|
$icode%ok% = %afun%.forward(
|
||||||
|
%parameter_x%, %type_x%,
|
||||||
|
%need_y%, %order_low%, %order_up%, %type_x%, %ataylor_x%, %ataylor_y%
|
||||||
|
)%$$
|
||||||
|
|
||||||
|
$subhead Prototype$$
|
||||||
|
$srcthisfile%0%// BEGIN_PROTOTYPE_AD_BASE%// END_PROTOTYPE_AD_BASE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
The $icode taylor_x$$, $icode taylor_y$$ version of this function
|
||||||
|
must be defined by the
|
||||||
|
$cref/atomic_user/atomic_three_ctor/atomic_user/$$ class.
|
||||||
|
It can just return $icode%ok% == false%$$
|
||||||
|
(and not compute anything) for values
|
||||||
|
of $icode%order_up%$$ that are greater than those used by your
|
||||||
|
$cref/forward/Forward/$$ mode calculations
|
||||||
|
(order zero must be implemented).
|
||||||
|
|
||||||
|
$head parameter_x$$
|
||||||
|
See $cref/parameter_x/atomic_three/parameter_x/$$.
|
||||||
|
|
||||||
|
$head aparameter_x$$
|
||||||
|
The specifications for $icode aparameter_x$$
|
||||||
|
is the same as for $cref/parameter_x/atomic_three/parameter_x/$$
|
||||||
|
(only the type of $icode ataylor_x$$ is different).
|
||||||
|
|
||||||
|
$head type_x$$
|
||||||
|
See $cref/type_x/atomic_three/type_x/$$.
|
||||||
|
|
||||||
|
$head need_y$$
|
||||||
|
One can ignore this argument and compute all the $icode taylor_y$$
|
||||||
|
Taylor coefficient.
|
||||||
|
Often, this is not necessary and $icode need_y$$ is used to specify this.
|
||||||
|
The value $cref/type_y/atomic_three_for_type/type_y/$$ is used
|
||||||
|
to determine which coefficients are necessary as follows:
|
||||||
|
|
||||||
|
$subhead Constant Parameters$$
|
||||||
|
If $icode%need_y% == size_t(constant_enum)%$$,
|
||||||
|
then only the taylor coefficients
|
||||||
|
for $latex Y_i (t)$$ where $icode%type_y%[%i%] == constant_enum%$$
|
||||||
|
are necessary.
|
||||||
|
This is the case during a $cref from_json$$ operation.
|
||||||
|
|
||||||
|
$subhead Dynamic Parameters$$
|
||||||
|
If $icode%need_y% == size_t(dynamic_enum)%$$,
|
||||||
|
then only the taylor coefficients
|
||||||
|
for $latex Y_i (t)$$ where $icode%type_y%[%i%] == dynamic_enum%$$
|
||||||
|
are necessary.
|
||||||
|
This is the case during an $cref new_dynamic$$ operation.
|
||||||
|
|
||||||
|
$subhead Variables$$
|
||||||
|
If $icode%need_y% == size_t(variable_enum)%$$,
|
||||||
|
If $codei%ad_type_enum(%need_y%)% == variable_enum%$$,
|
||||||
|
then only the taylor coefficients
|
||||||
|
for $latex Y_i (t)$$ where $icode%type_y%[%i%] == variable_enum%$$
|
||||||
|
are necessary.
|
||||||
|
This is the case during a $cref/f.Forward/Forward/$$ operation.
|
||||||
|
T
|
||||||
|
|
||||||
|
$subhead All$$
|
||||||
|
If $icode%need_y > size_t(variable_enum)%$$,
|
||||||
|
then the taylor coefficients for all $latex Y_i (t)$$ are necessary.
|
||||||
|
This is the case during an $icode%afun%(%ax%, %ay%)%$$ operation.
|
||||||
|
|
||||||
|
|
||||||
|
$head order_low$$
|
||||||
|
This argument
|
||||||
|
specifies the lowest order Taylor coefficient that we are computing.
|
||||||
|
|
||||||
|
$subhead p$$
|
||||||
|
We sometimes use the notation $icode%p% = %order_low%$$ below.
|
||||||
|
|
||||||
|
$head order_up$$
|
||||||
|
This argument
|
||||||
|
specifies the highest order Taylor coefficient that we are computing
|
||||||
|
($icode%order_low% <= %order_up%$$).
|
||||||
|
|
||||||
|
$subhead q$$
|
||||||
|
We sometimes use the notation $icode%q% = %order_up%$$ below.
|
||||||
|
|
||||||
|
$head taylor_x$$
|
||||||
|
The size of $icode taylor_x$$ is $codei%(%q%+1)*%n%$$.
|
||||||
|
For $latex j = 0 , \ldots , n-1$$ and $latex k = 0 , \ldots , q$$,
|
||||||
|
we use the Taylor coefficient notation
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
x_j^k & = & \R{taylor\_x} [ j * ( q + 1 ) + k ]
|
||||||
|
\\
|
||||||
|
X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
Note that superscripts represent an index for $latex x_j^k$$
|
||||||
|
and an exponent for $latex t^k$$.
|
||||||
|
Also note that the Taylor coefficients for $latex X(t)$$ correspond
|
||||||
|
to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way:
|
||||||
|
$latex \[
|
||||||
|
x_j^k = \frac{1}{ k ! } X_j^{(k)} (0)
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$subhead parameters$$
|
||||||
|
If the $th j$$ component of $icode x$$ corresponds to a parameter,
|
||||||
|
$codei%
|
||||||
|
%type_x%[%j%] < CppAD::variable_enum
|
||||||
|
%$$
|
||||||
|
In this case,
|
||||||
|
the $th j$$ component of $icode parameter_x$$ is equal to $latex x_j^0$$;
|
||||||
|
i.e.,
|
||||||
|
$codei%
|
||||||
|
%parameter_x%[%j%] == %taylor_x%[ %j% * ( %q% + 1 ) + 0 ]
|
||||||
|
%$$
|
||||||
|
Furthermore, for $icode%k% > 0%$$,
|
||||||
|
$codei%
|
||||||
|
%taylor_x%[ %j% * ( %q% + 1 ) + %k% ] == 0
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head ataylor_x$$
|
||||||
|
The specifications for $icode ataylor_x$$ is the same as for $icode taylor_x$$
|
||||||
|
(only the type of $icode ataylor_x$$ is different).
|
||||||
|
|
||||||
|
$head taylor_y$$
|
||||||
|
The size of $icode taylor_y$$ is $codei%(%q%+1)*%m%$$.
|
||||||
|
Upon return,
|
||||||
|
For $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , q$$,
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
Y_i (t) & = & g_i [ X(t) ]
|
||||||
|
\\
|
||||||
|
Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q )
|
||||||
|
\\
|
||||||
|
\R{taylor\_y} [ i * ( q + 1 ) + k ] & = & y_i^k
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
where $latex o( t^q ) / t^q \rightarrow 0$$ as $latex t \rightarrow 0$$.
|
||||||
|
Note that superscripts represent an index for $latex y_j^k$$
|
||||||
|
and an exponent for $latex t^k$$.
|
||||||
|
Also note that the Taylor coefficients for $latex Y(t)$$ correspond
|
||||||
|
to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way:
|
||||||
|
$latex \[
|
||||||
|
y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0)
|
||||||
|
\] $$
|
||||||
|
If $latex p > 0$$,
|
||||||
|
for $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , p-1$$,
|
||||||
|
the input of $icode taylor_y$$ satisfies
|
||||||
|
$latex \[
|
||||||
|
\R{taylor\_y} [ i * ( q + 1 ) + k ] = y_i^k
|
||||||
|
\]$$
|
||||||
|
These values do not need to be recalculated
|
||||||
|
and can be used during the computation of the higher order coefficients.
|
||||||
|
|
||||||
|
$head ataylor_y$$
|
||||||
|
The specifications for $icode ataylor_y$$ is the same as for $icode taylor_y$$
|
||||||
|
(only the type of $icode ataylor_y$$ is different).
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
If this calculation succeeded, $icode ok$$ is true.
|
||||||
|
Otherwise, it is false.
|
||||||
|
|
||||||
|
$head Discussion$$
|
||||||
|
For example, suppose that $icode%order_up% == 2%$$,
|
||||||
|
and you know how to compute the function $latex g(x)$$,
|
||||||
|
its first derivative $latex f^{(1)} (x)$$,
|
||||||
|
and it component wise Hessian $latex g_i^{(2)} (x)$$.
|
||||||
|
Then you can compute $icode taylor_x$$ using the following formulas:
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
y_i^0 & = & Y(0)
|
||||||
|
= g_i ( x^0 )
|
||||||
|
\\
|
||||||
|
y_i^1 & = & Y^{(1)} ( 0 )
|
||||||
|
= g_i^{(1)} ( x^0 ) X^{(1)} ( 0 )
|
||||||
|
= g_i^{(1)} ( x^0 ) x^1
|
||||||
|
\\
|
||||||
|
y_i^2
|
||||||
|
& = & \frac{1}{2 !} Y^{(2)} (0)
|
||||||
|
\\
|
||||||
|
& = & \frac{1}{2} X^{(1)} (0)^\R{T} g_i^{(2)} ( x^0 ) X^{(1)} ( 0 )
|
||||||
|
+ \frac{1}{2} g_i^{(1)} ( x^0 ) X^{(2)} ( 0 )
|
||||||
|
\\
|
||||||
|
& = & \frac{1}{2} (x^1)^\R{T} g_i^{(2)} ( x^0 ) x^1
|
||||||
|
+ g_i^{(1)} ( x^0 ) x^2
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
For $latex i = 0 , \ldots , m-1$$, and $latex k = 0 , 1 , 2$$,
|
||||||
|
$latex \[
|
||||||
|
\R{taylor\_y} [ i * (q + 1) + k ] = y_i^k
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$children%
|
||||||
|
example/atomic_three/forward.cpp%
|
||||||
|
example/atomic_three/dynamic.cpp
|
||||||
|
%$$
|
||||||
|
$head Examples$$
|
||||||
|
The files
|
||||||
|
$cref atomic_three_forward.cpp$$ and $cref atomic_three_dynamic.cpp$$
|
||||||
|
contain examples and tests that uses this routine.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/three_forward.hpp
|
||||||
|
Third generation atomic forward mode.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from atomic_three to forward mode
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
contains the values, in afun(ax, ay), for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param need_y [in]
|
||||||
|
specifies which components of taylor_y are needed,
|
||||||
|
|
||||||
|
\param order_low [in]
|
||||||
|
lowerest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param taylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param taylor_y [out]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
See the forward mode in user's documentation for atomic_three
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE_BASE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_three<Base>::forward(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t need_y ,
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
vector<Base>& taylor_y )
|
||||||
|
// END_PROTOTYPE_BASE
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Link from atomic_three to forward mode
|
||||||
|
|
||||||
|
\param aparameter_x [in]
|
||||||
|
contains the values, in afun(ax, ay), for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param need_y [in]
|
||||||
|
specifies which components of taylor_y are needed,
|
||||||
|
|
||||||
|
\param order_low [in]
|
||||||
|
lowerest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param ataylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param ataylor_y [out]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
See the forward mode in user's documentation for base_three
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE_AD_BASE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_three<Base>::forward(
|
||||||
|
const vector< AD<Base> >& aparameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t need_y ,
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
vector< AD<Base> >& ataylor_y )
|
||||||
|
// END_PROTOTYPE_AD_BASE
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,412 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_THREE_HES_SPARSITY_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_THREE_HES_SPARSITY_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three_hes_sparsity$$
|
||||||
|
$spell
|
||||||
|
Hessian
|
||||||
|
afun
|
||||||
|
hes
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Function Hessian Sparsity Patterns$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ok% = %afun%.hes_sparsity(
|
||||||
|
%parameter_x%, %type_x%, %select_x%, %select_y%, %pattern_out%
|
||||||
|
)%$$
|
||||||
|
|
||||||
|
$head Prototype$$
|
||||||
|
$srcthisfile%0%// BEGIN_PROTOTYPE%// END_PROTOTYPE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
This function must be defined if
|
||||||
|
$cref/afun/atomic_three_ctor/atomic_user/afun/$$ is
|
||||||
|
used to define an $cref ADFun$$ object $icode f$$,
|
||||||
|
and Hessian sparsity patterns are computed for $icode f$$.
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
See $cref/Base/atomic_three_afun/Base/$$.
|
||||||
|
|
||||||
|
$head parameter_x$$
|
||||||
|
See $cref/parameter_x/atomic_three/parameter_x/$$.
|
||||||
|
|
||||||
|
$head type_x$$
|
||||||
|
See $cref/type_x/atomic_three/type_x/$$.
|
||||||
|
|
||||||
|
$head select_x$$
|
||||||
|
This argument has size equal to the number of arguments to this
|
||||||
|
atomic function; i.e. the size of $icode ax$$.
|
||||||
|
It specifies which domain components are included in
|
||||||
|
the calculation of $icode pattern_out$$.
|
||||||
|
If $icode%select_x%[%j%]%$$ is false, then there will be no indices
|
||||||
|
$icode k$$ such that either of the following hold:
|
||||||
|
$codei%
|
||||||
|
%pattern_out%.row()[%k%] == %j%
|
||||||
|
%pattern_out%.col()[%k%] == %j%
|
||||||
|
%$$.
|
||||||
|
|
||||||
|
$head select_y$$
|
||||||
|
This argument has size equal to the number of results to this
|
||||||
|
atomic function; i.e. the size of $icode ay$$.
|
||||||
|
It specifies which range component functions $latex g_i (x)$$ are included in
|
||||||
|
of $icode pattern_out$$.
|
||||||
|
|
||||||
|
$head pattern_out$$
|
||||||
|
This input value of $icode pattern_out$$ does not matter.
|
||||||
|
Upon return it is the union,
|
||||||
|
with respect to $icode i$$ such that $icode%select_y%[%i%]%$$ is true,
|
||||||
|
of the sparsity pattern for Hessian of $latex g_i (x)$$.
|
||||||
|
To be specific, there are non-negative indices
|
||||||
|
$icode i$$, $icode r$$, $icode c$$, and $icode k$$ such that
|
||||||
|
$codei%
|
||||||
|
%pattern_out%.row()[%k%] == %r%
|
||||||
|
%pattern_out%.col()[%k%] == %c%
|
||||||
|
%$$
|
||||||
|
if and only if
|
||||||
|
$icode%select_y%[%i%]%$$ is true,
|
||||||
|
$icode%select_x%[%r%]%$$ is true,
|
||||||
|
$icode%select_x%[%c%]%$$ is true,
|
||||||
|
and
|
||||||
|
$latex \[
|
||||||
|
\partial_{x(r)} \partial_{x(c)} g_i(x)
|
||||||
|
\] $$
|
||||||
|
is possibly non-zero.
|
||||||
|
Note that the sparsity pattern should be symmetric.
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
If this calculation succeeded, $icode ok$$ is true.
|
||||||
|
Otherwise it is false.
|
||||||
|
|
||||||
|
$children%
|
||||||
|
example/atomic_three/hes_sparsity.cpp
|
||||||
|
%$$
|
||||||
|
$head Examples$$
|
||||||
|
The file $cref atomic_three_hes_sparsity.cpp$$ contains an example and test
|
||||||
|
that uses this routine.
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/three_hes_sparsity.hpp
|
||||||
|
Third generation atomic Hessian dependency and sparsity patterns.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
atomic_three to Hessian dependency and sparsity calculations.
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
contains the values for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param select_x [in]
|
||||||
|
which domain components to include in the dependency or sparsity pattern.
|
||||||
|
|
||||||
|
\param select_y [in]
|
||||||
|
which range components to include in the dependency or sparsity pattern.
|
||||||
|
|
||||||
|
\param pattern_out [out]
|
||||||
|
is the sparsity pattern for Hessian.
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_three<Base>::hes_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const vector<bool>& select_x ,
|
||||||
|
const vector<bool>& select_y ,
|
||||||
|
sparse_rc< vector<size_t> >& pattern_out )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ return false; }
|
||||||
|
/*!
|
||||||
|
Link from forward Hessian sweep to atomic_three.
|
||||||
|
2DO: move this functiton outside this file so can change
|
||||||
|
developer documentation to omhelp formating.
|
||||||
|
|
||||||
|
\tparam InternalSparsity
|
||||||
|
Is the used internaly for sparsity calculations; i.e.,
|
||||||
|
sparse_pack or sparse_list.
|
||||||
|
|
||||||
|
\param parameter_x
|
||||||
|
is parameter arguments to the function, other components are nan.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param x_index
|
||||||
|
is the variable index, on the tape, for the arguments to this function.
|
||||||
|
This size of x_index is n, the number of arguments to this function.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param y_index
|
||||||
|
is the variable index, on the tape, for the results for this function.
|
||||||
|
This size of y_index is m, the number of results for this function.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param for_jac_sparsity
|
||||||
|
On input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
is the forward Jacobian sparsity for the j-th argument to this atomic function.
|
||||||
|
|
||||||
|
\param rev_jac_pattern
|
||||||
|
On input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],
|
||||||
|
is the reverse Jacobian sparsity for the i-th result to this atomic function.
|
||||||
|
This shows which components of the result affect the function we are
|
||||||
|
computing the Hessian of.
|
||||||
|
|
||||||
|
\param hes_sparsity_for
|
||||||
|
This is the sparsity pattern for the Hessian. On input, the non-linear
|
||||||
|
terms in the atomic fuction have not been included. Upon return, they
|
||||||
|
have been included.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool atomic_three<Base>::for_hes_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
size_t np1 ,
|
||||||
|
size_t numvar ,
|
||||||
|
const InternalSparsity& rev_jac_pattern ,
|
||||||
|
InternalSparsity& for_sparsity )
|
||||||
|
{ typedef typename InternalSparsity::const_iterator const_iterator;
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( rev_jac_pattern.end() == 1 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( for_sparsity.end() == np1 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( for_sparsity.n_set() == np1 + numvar );
|
||||||
|
size_t n = x_index.size();
|
||||||
|
size_t m = y_index.size();
|
||||||
|
//
|
||||||
|
// select_x
|
||||||
|
vector<bool> select_x(n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ // check if should compute pattern w.r.t x[j]
|
||||||
|
select_x[j] = for_sparsity.number_elements(np1 + x_index[j]) > 0;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bool select_y
|
||||||
|
vector<bool> select_y(m);
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ // check if we should include y[i]
|
||||||
|
select_y[i] = rev_jac_pattern.number_elements(y_index[i]) > 0;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// call user's version of atomic function for Jacobian
|
||||||
|
sparse_rc< vector<size_t> > pattern_out;
|
||||||
|
bool dependency = false;
|
||||||
|
bool ok = jac_sparsity(
|
||||||
|
parameter_x, type_x, dependency, select_x, select_y, pattern_out
|
||||||
|
);
|
||||||
|
if( ! ok )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// transfer sparsity patterns from pattern_out to var_sparsity
|
||||||
|
size_t nnz = pattern_out.nnz();
|
||||||
|
const vector<size_t>& row( pattern_out.row() );
|
||||||
|
const vector<size_t>& col( pattern_out.col() );
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
select_y[i] & select_x[j],
|
||||||
|
"atomic: jac_sparsity: pattern_out not in "
|
||||||
|
"select_x or select_y range"
|
||||||
|
);
|
||||||
|
const_iterator itr(for_sparsity, np1 + x_index[j]);
|
||||||
|
size_t ell = *itr;
|
||||||
|
while( ell < np1 )
|
||||||
|
{ for_sparsity.post_element(np1 + y_index[i], ell );
|
||||||
|
ell = *(++itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < m; ++i)
|
||||||
|
for_sparsity.process_post( np1 + y_index[i] );
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// call user's version of atomic function for Hessian
|
||||||
|
ok = hes_sparsity(
|
||||||
|
parameter_x, type_x, select_x, select_y, pattern_out
|
||||||
|
);
|
||||||
|
if( ! ok )
|
||||||
|
return ok;
|
||||||
|
//
|
||||||
|
// add new elements to Hessian sparisty in calling routine
|
||||||
|
nnz = pattern_out.nnz();
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t r = row[k];
|
||||||
|
size_t c = col[k];
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
select_x[r] & select_x[c],
|
||||||
|
"atomic: hes_sparsity: pattern_out not in select_x range"
|
||||||
|
);
|
||||||
|
const_iterator itr_1(for_sparsity, np1 + x_index[r]);
|
||||||
|
size_t v1 = *itr_1;
|
||||||
|
while( v1 < np1 )
|
||||||
|
{ for_sparsity.binary_union(
|
||||||
|
v1, v1, np1 + x_index[c], for_sparsity
|
||||||
|
);
|
||||||
|
v1 = *(++itr_1);
|
||||||
|
}
|
||||||
|
// no need to add same elements twice
|
||||||
|
if( c != r )
|
||||||
|
{ const_iterator itr_2(for_sparsity, np1 + x_index[c]);
|
||||||
|
size_t v2 = *itr_2;
|
||||||
|
while( v2 < np1 )
|
||||||
|
{ for_sparsity.binary_union(
|
||||||
|
v2, v2, np1 + x_index[r], for_sparsity
|
||||||
|
);
|
||||||
|
v2 = *(++itr_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
Link from for_reverse Hessian sweep to atomic_three.
|
||||||
|
|
||||||
|
\tparam InternalSparsity
|
||||||
|
Is the used internaly for sparsity calculations; i.e.,
|
||||||
|
sparse_pack or sparse_list.
|
||||||
|
|
||||||
|
\param parameter_x
|
||||||
|
is parameter arguments to the function, other components are nan.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param x_index
|
||||||
|
is the variable index, on the tape, for the arguments to this function.
|
||||||
|
This size of x_index is n, the number of arguments to this function.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param y_index
|
||||||
|
is the variable index, on the tape, for the results for this function.
|
||||||
|
This size of y_index is m, the number of results for this function.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param for_jac_pattern
|
||||||
|
On input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
is the forward Jacobian pattern for the j-th argument to this atomic function.
|
||||||
|
|
||||||
|
\param rev_jac_flag
|
||||||
|
On input, for i = 0, ... , m-1, rev_jac_flag[ y_index[i] ] is true
|
||||||
|
if the function we are computing the Hessian of has possibly non-zero Jacobian
|
||||||
|
w.r.t varialbe y_index[i].
|
||||||
|
On output, for j = 0, ... , n, rev_jac_flag[ x_index[j] ] is set to true
|
||||||
|
if the varialbe with index x_index[j] has possible non-zero Jacobian
|
||||||
|
with repect to one of the true y_index[i] cases.
|
||||||
|
Otherwise, rev_jac_flag [ x_inde[j] ] is not changed.
|
||||||
|
|
||||||
|
\param hes_sparsity_rev
|
||||||
|
Is the reverse mode sparsity pattern for the Hessian. On input, the non-linear
|
||||||
|
terms in the atomic fuction have not been included. Upon return, they
|
||||||
|
have been included.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool atomic_three<Base>::rev_hes_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
const InternalSparsity& for_jac_pattern ,
|
||||||
|
bool* rev_jac_flag ,
|
||||||
|
InternalSparsity& hes_sparsity_rev )
|
||||||
|
{ typedef typename InternalSparsity::const_iterator const_iterator;
|
||||||
|
size_t n = x_index.size();
|
||||||
|
size_t m = y_index.size();
|
||||||
|
//
|
||||||
|
// select_x
|
||||||
|
vector<bool> select_x(n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ // check if should compute pattern w.r.t x[j]
|
||||||
|
const_iterator itr(for_jac_pattern, x_index[j]);
|
||||||
|
size_t i = *itr;
|
||||||
|
select_x[j] = i < for_jac_pattern.end();
|
||||||
|
CPPAD_ASSERT_UNKNOWN( x_index[j] > 0 || ! select_x[j] );
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bool select_y
|
||||||
|
vector<bool> select_y(m);
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ // check if we should include y[i]
|
||||||
|
select_y[i] = rev_jac_flag[ y_index[i] ];
|
||||||
|
CPPAD_ASSERT_UNKNOWN( y_index[i] > 0 || ! select_y[i] );
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// call atomic function for Jacobain sparsity
|
||||||
|
bool dependency = false;
|
||||||
|
sparse_rc< vector<size_t> > pattern_jac;
|
||||||
|
bool ok = jac_sparsity(
|
||||||
|
parameter_x, type_x, dependency, select_x, select_y, pattern_jac
|
||||||
|
);
|
||||||
|
const vector<size_t>& row_jac( pattern_jac.row() );
|
||||||
|
const vector<size_t>& col_jac( pattern_jac.col() );
|
||||||
|
size_t nnz_jac = pattern_jac.nnz();
|
||||||
|
if( ! ok )
|
||||||
|
return ok;
|
||||||
|
//
|
||||||
|
// call atomic function for Hessian sparsity
|
||||||
|
sparse_rc< vector<size_t> > pattern_hes;
|
||||||
|
ok = hes_sparsity(parameter_x, type_x, select_x, select_y, pattern_hes);
|
||||||
|
const vector<size_t>& row_hes( pattern_hes.row() );
|
||||||
|
const vector<size_t>& col_hes( pattern_hes.col() );
|
||||||
|
size_t nnz_hes = pattern_hes.nnz();
|
||||||
|
if( ! ok )
|
||||||
|
return ok;
|
||||||
|
//
|
||||||
|
// propagate Hessian sparsity through the Jacobian
|
||||||
|
for(size_t k = 0; k < nnz_jac; ++k)
|
||||||
|
{ size_t i = row_jac[k];
|
||||||
|
size_t j = col_jac[k];
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
select_y[i] & select_x[j] ,
|
||||||
|
"atomic: jac_sparsity: pattern_out not in "
|
||||||
|
"select_x or select_y range"
|
||||||
|
);
|
||||||
|
// from y_index[i] to x_index[j]
|
||||||
|
hes_sparsity_rev.binary_union(
|
||||||
|
x_index[j], x_index[j], y_index[i], hes_sparsity_rev
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// propagate rev_jac_flag through the Jacobian
|
||||||
|
// (seems OK to exclude variables with zero forward jacobian)
|
||||||
|
for(size_t k = 0; k < nnz_jac; ++k)
|
||||||
|
{ size_t j = col_jac[k];
|
||||||
|
rev_jac_flag[ x_index[j] ] = true;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// new hessian sparsity terms between y and x
|
||||||
|
for(size_t k = 0; k < nnz_hes; ++k)
|
||||||
|
{ size_t r = row_hes[k];
|
||||||
|
size_t c = col_hes[k];
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
select_x[r] & select_x[c] ,
|
||||||
|
"atomic: hes_sparsity: pattern_out not in select_x range"
|
||||||
|
);
|
||||||
|
hes_sparsity_rev.binary_union(
|
||||||
|
x_index[r], x_index[r], x_index[c], for_jac_pattern
|
||||||
|
);
|
||||||
|
hes_sparsity_rev.binary_union(
|
||||||
|
x_index[c], x_index[c], x_index[r], for_jac_pattern
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,355 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_THREE_JAC_SPARSITY_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_THREE_JAC_SPARSITY_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three_jac_sparsity$$
|
||||||
|
$spell
|
||||||
|
Jacobian
|
||||||
|
afun
|
||||||
|
jac
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Function Jacobian Sparsity Patterns$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ok% = %afun%.jac_sparsity(
|
||||||
|
%parameter_x%, %type_x%, %dependency%, %select_x%, %select_y%, %pattern_out%
|
||||||
|
)%$$
|
||||||
|
|
||||||
|
$head Prototype$$
|
||||||
|
$srcthisfile%0%// BEGIN_PROTOTYPE%// END_PROTOTYPE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
This function must be defined if
|
||||||
|
$cref/afun/atomic_three_ctor/atomic_user/afun/$$ is
|
||||||
|
used to define an $cref ADFun$$ object $icode f$$,
|
||||||
|
and Jacobian sparsity patterns are computed for $icode f$$.
|
||||||
|
(Computing Hessian sparsity patterns and optimizing
|
||||||
|
requires Jacobian sparsity patterns.)
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
See $cref/Base/atomic_three_afun/Base/$$.
|
||||||
|
|
||||||
|
$head parameter_x$$
|
||||||
|
See $cref/parameter_x/atomic_three/parameter_x/$$.
|
||||||
|
|
||||||
|
$head type_x$$
|
||||||
|
See $cref/type_x/atomic_three/type_x/$$.
|
||||||
|
|
||||||
|
$head dependency$$
|
||||||
|
If $icode dependency$$ is true,
|
||||||
|
then $icode pattern_out$$ is a
|
||||||
|
$cref/dependency pattern/dependency.cpp/Dependency Pattern/$$
|
||||||
|
for this atomic function.
|
||||||
|
Otherwise it is a
|
||||||
|
$cref/sparsity pattern/glossary/Sparsity Pattern/$$ for the
|
||||||
|
derivative of the atomic function.
|
||||||
|
|
||||||
|
$head select_x$$
|
||||||
|
This argument has size equal to the number of arguments to this
|
||||||
|
atomic function; i.e. the size of $icode ax$$.
|
||||||
|
It specifies which domain components are included in
|
||||||
|
the calculation of $icode pattern_out$$.
|
||||||
|
If $icode%select_x%[%j%]%$$ is false, then there will be no indices
|
||||||
|
$icode k$$ such that
|
||||||
|
$codei%
|
||||||
|
%pattern_out%.col()[%k%] == %j%
|
||||||
|
%$$.
|
||||||
|
|
||||||
|
$head select_y$$
|
||||||
|
This argument has size equal to the number of results to this
|
||||||
|
atomic function; i.e. the size of $icode ay$$.
|
||||||
|
It specifies which range components are included in
|
||||||
|
the calculation of $icode pattern_out$$.
|
||||||
|
If $icode%select_y%[%i%]%$$ is false, then there will be no indices
|
||||||
|
$icode k$$ such that
|
||||||
|
$codei%
|
||||||
|
%pattern_out%.row()[%k%] == %i%
|
||||||
|
%$$.
|
||||||
|
|
||||||
|
$head pattern_out$$
|
||||||
|
This input value of $icode pattern_out$$ does not matter.
|
||||||
|
Upon return it is a
|
||||||
|
dependency or sparsity pattern for the Jacobian of $latex g(x)$$,
|
||||||
|
the function corresponding to
|
||||||
|
$cref/afun/atomic_three_ctor/atomic_user/afun/$$;
|
||||||
|
$icode dependency$$ above.
|
||||||
|
To be specific, there are non-negative indices
|
||||||
|
$icode i$$, $icode j$$, $icode k$$ such that
|
||||||
|
$codei%
|
||||||
|
%pattern_out%.row()[%k%] == %i%
|
||||||
|
%pattern_out%.col()[%k%] == %j%
|
||||||
|
%$$
|
||||||
|
if and only if
|
||||||
|
$icode%select_x%[%j%]%$$ is true,
|
||||||
|
$icode%select_y%[%j%]%$$ is true,
|
||||||
|
and $latex g_i(x)$$ depends on the value of $latex x_j$$
|
||||||
|
(and the partial of $latex g_i(x)$$ with respect to
|
||||||
|
$latex x_j$$ is possibly non-zero).
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
If this calculation succeeded, $icode ok$$ is true.
|
||||||
|
Otherwise it is false.
|
||||||
|
|
||||||
|
|
||||||
|
$children%
|
||||||
|
example/atomic_three/jac_sparsity.cpp
|
||||||
|
%$$
|
||||||
|
$head Examples$$
|
||||||
|
The file $cref atomic_three_jac_sparsity.cpp$$ contains an example and test
|
||||||
|
that uses this routine.
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/three_jac_sparsity.hpp
|
||||||
|
Third generation atomic Jacobian dependency and sparsity patterns.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
atomic_three to Jacobian dependency and sparsity calculations.
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
contains the values for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param dependency [in]
|
||||||
|
if true, calculate dependency pattern,
|
||||||
|
otherwise calcuate sparsity pattern.
|
||||||
|
|
||||||
|
\param select_x [in]
|
||||||
|
which domain components to include in the dependency or sparsity pattern.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param select_y [in]
|
||||||
|
which range components to include in the dependency or sparsity pattern.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param pattern_out [out]
|
||||||
|
is the dependency or sparsity pattern.
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_three<Base>::jac_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
bool dependency ,
|
||||||
|
const vector<bool>& select_x ,
|
||||||
|
const vector<bool>& select_y ,
|
||||||
|
sparse_rc< vector<size_t> >& pattern_out )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ return false; }
|
||||||
|
/*!
|
||||||
|
Link from forward Jacobian sparsity calcuations to atomic_three
|
||||||
|
|
||||||
|
\tparam InternalSparsity
|
||||||
|
Is the type used for internal sparsity calculations; i.e.,
|
||||||
|
sparse_pack or sparse_list.
|
||||||
|
|
||||||
|
\param dependency
|
||||||
|
if true, calcuate dependency pattern,
|
||||||
|
otherwise calcuate sparsity pattern.
|
||||||
|
|
||||||
|
\param parameter_x
|
||||||
|
is parameter arguments to the function, other components are nan.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param x_index
|
||||||
|
is the variable index, on the tape, for the arguments to this atomic function.
|
||||||
|
This size of x_index is n, the number of arguments to this atomic function.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param y_index
|
||||||
|
is the variable index, on the tape, for the results for this atomic function.
|
||||||
|
This size of y_index is m, the number of results for this atomic function.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param var_sparsity
|
||||||
|
On input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
is the sparsity for the j-th argument to this atomic function.
|
||||||
|
On output, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],
|
||||||
|
is the sparsity for the i-th result for this atomic function.
|
||||||
|
|
||||||
|
\return
|
||||||
|
is true if the computation succeeds.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool atomic_three<Base>::for_jac_sparsity(
|
||||||
|
bool dependency ,
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
InternalSparsity& var_sparsity )
|
||||||
|
{ typedef typename InternalSparsity::const_iterator iterator;
|
||||||
|
|
||||||
|
// number of arguments and resutls for this atomic function
|
||||||
|
size_t n = x_index.size();
|
||||||
|
size_t m = y_index.size();
|
||||||
|
|
||||||
|
// select_y
|
||||||
|
vector<bool> select_y(m);
|
||||||
|
for(size_t i = 0; i < m; ++i)
|
||||||
|
select_y[i] = y_index[i] != 0;
|
||||||
|
|
||||||
|
// determine select_x
|
||||||
|
vector<bool> select_x(n);
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
{ // check if x_j depends on any previous variable
|
||||||
|
iterator itr(var_sparsity, x_index[j]);
|
||||||
|
size_t ell = *itr;
|
||||||
|
select_x[j] = ell < var_sparsity.end();
|
||||||
|
CPPAD_ASSERT_UNKNOWN( x_index[j] > 0 || ! select_x[j] );
|
||||||
|
}
|
||||||
|
sparse_rc< vector<size_t> > pattern_out;
|
||||||
|
bool ok = jac_sparsity(
|
||||||
|
parameter_x, type_x, dependency, select_x, select_y, pattern_out
|
||||||
|
);
|
||||||
|
if( ! ok )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// transfer sparsity patterns from pattern_out to var_sparsity
|
||||||
|
size_t nnz = pattern_out.nnz();
|
||||||
|
const vector<size_t>& row( pattern_out.row() );
|
||||||
|
const vector<size_t>& col( pattern_out.col() );
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
select_y[i] & select_x[j],
|
||||||
|
"atomic: jac_sparsity: pattern_out not in "
|
||||||
|
"select_x or select_y range"
|
||||||
|
);
|
||||||
|
iterator itr(var_sparsity, x_index[j]);
|
||||||
|
size_t ell = *itr;
|
||||||
|
while( ell < var_sparsity.end() )
|
||||||
|
{ var_sparsity.post_element( y_index[i], ell );
|
||||||
|
ell = *(++itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < m; ++i)
|
||||||
|
var_sparsity.process_post( y_index[i] );
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
Link from reverse Jacobian sparsity calcuations to atomic_three
|
||||||
|
|
||||||
|
\tparam InternalSparsity
|
||||||
|
Is the type used for internal sparsity calculations; i.e.,
|
||||||
|
sparse_pack or sparse_list.
|
||||||
|
|
||||||
|
\param dependency
|
||||||
|
if true, calcuate dependency pattern,
|
||||||
|
otherwise calcuate sparsity pattern.
|
||||||
|
|
||||||
|
\param parameter_x
|
||||||
|
is parameter arguments to the function, other components are nan.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param x_index
|
||||||
|
is the variable index, on the tape, for the arguments to this atomic function.
|
||||||
|
This size of x_index is n, the number of arguments to this atomic function.
|
||||||
|
|
||||||
|
\param y_index
|
||||||
|
is the variable index, on the tape, for the results for this atomic function.
|
||||||
|
This size of y_index is m, the number of results for this atomic function.
|
||||||
|
|
||||||
|
\param var_sparsity
|
||||||
|
On input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],
|
||||||
|
is the sparsity of the outter function with respect to the i-th
|
||||||
|
result for this atomic function.
|
||||||
|
On input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
is the sparsity for the outter function with repsect to the j-th
|
||||||
|
argument to this atomic function.
|
||||||
|
On output, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
is the sparsity for the outter function with repsect to the j-th
|
||||||
|
argument to this atomic function with the atomic function results
|
||||||
|
removed as arguments to the outter function.
|
||||||
|
|
||||||
|
\return
|
||||||
|
is true if the computation succeeds.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool atomic_three<Base>::rev_jac_sparsity(
|
||||||
|
bool dependency ,
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
InternalSparsity& var_sparsity )
|
||||||
|
{ typedef typename InternalSparsity::const_iterator iterator;
|
||||||
|
|
||||||
|
// number of arguments and resutls for this atomic function
|
||||||
|
size_t n = x_index.size();
|
||||||
|
size_t m = y_index.size();
|
||||||
|
|
||||||
|
// selection vectors
|
||||||
|
vector<bool> select_x(n), select_y(m);
|
||||||
|
|
||||||
|
// 2DO: perhaps we could use for_type(type_x, type_y)
|
||||||
|
// to reduce the true components in select_x
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
select_x[j] = true;
|
||||||
|
|
||||||
|
// determine select_y
|
||||||
|
for(size_t i = 0; i < m; ++i)
|
||||||
|
{ // check if y_i has sparsity is non-empty
|
||||||
|
iterator itr(var_sparsity, y_index[i]);
|
||||||
|
size_t ell = *itr;
|
||||||
|
select_y[i] = ell < var_sparsity.end();
|
||||||
|
}
|
||||||
|
sparse_rc< vector<size_t> > pattern_out;
|
||||||
|
bool ok = jac_sparsity(
|
||||||
|
parameter_x, type_x, dependency, select_x, select_y, pattern_out
|
||||||
|
);
|
||||||
|
if( ! ok )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
// transfer sparsity patterns from pattern_out to var_sparsity
|
||||||
|
size_t nnz = pattern_out.nnz();
|
||||||
|
const vector<size_t>& row( pattern_out.row() );
|
||||||
|
const vector<size_t>& col( pattern_out.col() );
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
select_y[i] & select_x[j],
|
||||||
|
"atomic: jac_sparsity: pattern_out not in "
|
||||||
|
"select_x or select_y range"
|
||||||
|
);
|
||||||
|
iterator itr(var_sparsity, y_index[i]);
|
||||||
|
size_t ell = *itr;
|
||||||
|
while( ell < var_sparsity.end() )
|
||||||
|
{ var_sparsity.post_element( x_index[j], ell );
|
||||||
|
ell = *(++itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
var_sparsity.process_post( x_index[j] );
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_THREE_REV_DEPEND_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_THREE_REV_DEPEND_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three_rev_depend$$
|
||||||
|
$spell
|
||||||
|
afun
|
||||||
|
enum
|
||||||
|
cpp
|
||||||
|
taylor.hpp
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Function Reverse Dependency Calculation$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ok% = %afun%.rev_depend(
|
||||||
|
%parameter_x%, %type_x%, %depend_x%, %depend_y%
|
||||||
|
)%$$
|
||||||
|
|
||||||
|
$subhead Prototype$$
|
||||||
|
$srcthisfile%0%// BEGIN_PROTOTYPE%// END_PROTOTYPE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Dependency Analysis$$
|
||||||
|
This calculation is sometimes referred to as a reverse dependency analysis.
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
This function must be defined if
|
||||||
|
$cref/afun/atomic_three_ctor/atomic_user/afun/$$ is
|
||||||
|
used to define an $cref ADFun$$ object $icode f$$,
|
||||||
|
and $cref/f.optimize()/optimize/$$ is used.
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
See $cref/Base/atomic_three_afun/Base/$$.
|
||||||
|
|
||||||
|
$head parameter_x$$
|
||||||
|
See $cref/parameter_x/atomic_three/parameter_x/$$.
|
||||||
|
|
||||||
|
$head type_x$$
|
||||||
|
See $cref/type_x/atomic_three/type_x/$$.
|
||||||
|
|
||||||
|
$head depend_x$$
|
||||||
|
This vector has size equal to the number of arguments for this atomic function;
|
||||||
|
i.e. $icode%n%=%ax%.size()%$$.
|
||||||
|
The input values of the elements of $icode depend_x$$
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, for $latex j = 0 , \ldots , n-1$$,
|
||||||
|
$icode%depend_x%[%j%]%$$ is true if the values of interest depend
|
||||||
|
on the value of $cref/ax[j]/atomic_three_afun/ax/$$ in the corresponding
|
||||||
|
$icode%afun%(%ax%, %ay%)%$$ call.
|
||||||
|
Note that parameters and variables,
|
||||||
|
that the values of interest do not depend on,
|
||||||
|
may get removed by $cref/optimization/optimize/$$.
|
||||||
|
The corresponding values in $cref/parameter_x/atomic_three/parameter_x/$$,
|
||||||
|
and $cref/taylor_x/atomic_three_forward/taylor_x/$$
|
||||||
|
(after optimization has removed them) are not specified.
|
||||||
|
|
||||||
|
$head depend_y$$
|
||||||
|
This vector has size equal to the number of results for this atomic function;
|
||||||
|
i.e. $icode%m%=%ay%.size()%$$.
|
||||||
|
For $latex i = 0 , \ldots , m-1$$,
|
||||||
|
$icode%depend_y%[%i%]%$$ is true if the values of interest depend
|
||||||
|
on the value of $cref/ay[i]/atomic_three_afun/ay/$$ in the corresponding
|
||||||
|
$icode%afun%(%ax%, %ay%)%$$ call.
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
If this calculation succeeded, $icode ok$$ is true.
|
||||||
|
Otherwise, it is false.
|
||||||
|
|
||||||
|
$childtable%
|
||||||
|
example/atomic_three/rev_depend.cpp
|
||||||
|
%$$
|
||||||
|
$head Example$$
|
||||||
|
The following is an example of a atomic function $code rev_depend$$ definition:
|
||||||
|
$cref atomic_three_rev_depend.cpp$$.
|
||||||
|
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/three_rev_depend.hpp
|
||||||
|
Third generation atomic type computation.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from atomic_three to reverse dependency calculation
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
is the value of the parameters in the corresponding function call
|
||||||
|
afun(ax, ay).
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
is the value for each of the components of x.
|
||||||
|
|
||||||
|
\param depend_x [out]
|
||||||
|
specifies which components of x affect values of interest.
|
||||||
|
|
||||||
|
\param depend_y [in]
|
||||||
|
specifies which components of y affect values of interest.
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_three<Base>::rev_depend(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<bool>& depend_x ,
|
||||||
|
const vector<bool>& depend_y )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
# endif
|
||||||
354
build-config/cppad/include/cppad/core/atomic/three_reverse.hpp
Normal file
354
build-config/cppad/include/cppad/core/atomic/three_reverse.hpp
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_THREE_REVERSE_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_THREE_REVERSE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_three_reverse$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul.hpp
|
||||||
|
afun
|
||||||
|
ty
|
||||||
|
px
|
||||||
|
py
|
||||||
|
Taylor
|
||||||
|
const
|
||||||
|
CppAD
|
||||||
|
atx
|
||||||
|
aty
|
||||||
|
apx
|
||||||
|
apy
|
||||||
|
af
|
||||||
|
aparameter
|
||||||
|
enum
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Function Reverse Mode$$
|
||||||
|
$spell
|
||||||
|
ataylor
|
||||||
|
apartial
|
||||||
|
$$
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
This syntax is used by $icode%f%.Reverse%$$ where $icode f$$ has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun<%Base%> %f%
|
||||||
|
%$$
|
||||||
|
and $icode afun$$ is used in $icode f$$;
|
||||||
|
see $cref/Base/atomic_three_afun/Base/$$.
|
||||||
|
|
||||||
|
$subhead Syntax$$
|
||||||
|
$icode%ok% = %afun%.reverse(
|
||||||
|
%parameter_x%, %type_x%,
|
||||||
|
%order_up%, %taylor_x%, %taylor_y%, %partial_x%, %partial_y%
|
||||||
|
)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$subhead Prototype$$
|
||||||
|
$srcthisfile%0%// BEGIN_PROTOTYPE_BASE%// END_PROTOTYPE_BASE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head AD<Base>$$
|
||||||
|
This syntax is used by $icode%af%.Reverse%$$ where $icode af$$ has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun< AD<%Base%> , %Base% > %af%
|
||||||
|
%$$
|
||||||
|
and $icode afun$$ is used in $icode af$$ (see $cref base2ad$$).
|
||||||
|
|
||||||
|
$subhead Syntax$$
|
||||||
|
$icode%ok% = %afun%.reverse(
|
||||||
|
%aparameter_x%, %type_x%,
|
||||||
|
%order_up%, %ataylor_x%, %ataylor_y%, %apartial_x%, %apartial_y%
|
||||||
|
)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$subhead Prototype$$
|
||||||
|
$srcthisfile%0%// BEGIN_PROTOTYPE_AD_BASE%// END_PROTOTYPE_AD_BASE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
This function must be defined if
|
||||||
|
$cref/afun/atomic_three_ctor/atomic_user/afun/$$ is
|
||||||
|
used to define an $cref ADFun$$ object $icode f$$,
|
||||||
|
and reverse mode derivatives are computed for $icode f$$.
|
||||||
|
It can return $icode%ok% == false%$$
|
||||||
|
(and not compute anything) for values
|
||||||
|
of $icode order_up$$ that are greater than those used by your
|
||||||
|
$cref/reverse/Reverse/$$ mode calculations.
|
||||||
|
|
||||||
|
$head parameter_x$$
|
||||||
|
See $cref/parameter_x/atomic_three/parameter_x/$$.
|
||||||
|
|
||||||
|
$head aparameter_x$$
|
||||||
|
The specifications for $icode aparameter_x$$
|
||||||
|
is the same as for $cref/parameter_x/atomic_three/parameter_x/$$
|
||||||
|
(only the type of $icode ataylor_x$$ is different).
|
||||||
|
|
||||||
|
$head type_x$$
|
||||||
|
See $cref/type_x/atomic_three/type_x/$$.
|
||||||
|
|
||||||
|
$head order_up$$
|
||||||
|
This argument specifies the highest order Taylor coefficient that
|
||||||
|
computing the derivative of.
|
||||||
|
|
||||||
|
$head taylor_x$$
|
||||||
|
The size of $icode taylor_x$$ is $codei%(%q%+1)*%n%$$.
|
||||||
|
For $latex j = 0 , \ldots , n-1$$ and $latex k = 0 , \ldots , q$$,
|
||||||
|
we use the Taylor coefficient notation
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
x_j^k & = & \R{taylor\_x} [ j * ( q + 1 ) + k ]
|
||||||
|
\\
|
||||||
|
X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
Note that superscripts represent an index for $latex x_j^k$$
|
||||||
|
and an exponent for $latex t^k$$.
|
||||||
|
Also note that the Taylor coefficients for $latex X(t)$$ correspond
|
||||||
|
to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way:
|
||||||
|
$latex \[
|
||||||
|
x_j^k = \frac{1}{ k ! } X_j^{(k)} (0)
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$subhead parameters$$
|
||||||
|
If the $th j$$ component of $icode x$$ corresponds to a parameter,
|
||||||
|
$codei%
|
||||||
|
%type_x%[%j%] < CppAD::variable_enum
|
||||||
|
%$$
|
||||||
|
In this case,
|
||||||
|
the $th j$$ component of $icode parameter_x$$ is equal to $latex x_j^0$$;
|
||||||
|
i.e.,
|
||||||
|
$codei%
|
||||||
|
%parameter_x%[%j%] == %taylor_x%[ %j% * ( %q% + 1 ) + 0 ]
|
||||||
|
%$$
|
||||||
|
Furthermore, for $icode%k% > 0%$$,
|
||||||
|
$codei%
|
||||||
|
%taylor_x%[ %j% * ( %q% + 1 ) + %k% ] == 0
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head ataylor_x$$
|
||||||
|
The specifications for $icode ataylor_x$$ is the same as for $icode taylor_x$$
|
||||||
|
(only the type of $icode ataylor_x$$ is different).
|
||||||
|
|
||||||
|
$head taylor_y$$
|
||||||
|
The size of $icode taylor_y$$ is $codei%(%q%+1)*%m%$$.
|
||||||
|
Upon return,
|
||||||
|
For $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , q$$,
|
||||||
|
we use the Taylor coefficient notation
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
Y_i (t) & = & g_i [ X(t) ]
|
||||||
|
\\
|
||||||
|
Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q )
|
||||||
|
\\
|
||||||
|
y_i^k & = & \R{taylor\_y} [ i * ( q + 1 ) + k ]
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
where $latex o( t^q ) / t^q \rightarrow 0$$ as $latex t \rightarrow 0$$.
|
||||||
|
Note that superscripts represent an index for $latex y_j^k$$
|
||||||
|
and an exponent for $latex t^k$$.
|
||||||
|
Also note that the Taylor coefficients for $latex Y(t)$$ correspond
|
||||||
|
to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way:
|
||||||
|
$latex \[
|
||||||
|
y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0)
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head ataylor_y$$
|
||||||
|
The specifications for $icode ataylor_y$$ is the same as for $icode taylor_y$$
|
||||||
|
(only the type of $icode ataylor_y$$ is different).
|
||||||
|
|
||||||
|
$head F$$
|
||||||
|
We use the notation $latex \{ x_j^k \} \in \B{R}^{n \times (q+1)}$$ for
|
||||||
|
$latex \[
|
||||||
|
\{ x_j^k \W{:} j = 0 , \ldots , n-1, k = 0 , \ldots , q \}
|
||||||
|
\]$$
|
||||||
|
We use the notation $latex \{ y_i^k \} \in \B{R}^{m \times (q+1)}$$ for
|
||||||
|
$latex \[
|
||||||
|
\{ y_i^k \W{:} i = 0 , \ldots , m-1, k = 0 , \ldots , q \}
|
||||||
|
\]$$
|
||||||
|
We define the function
|
||||||
|
$latex F : \B{R}^{n \times (q+1)} \rightarrow \B{R}^{m \times (q+1)}$$ by
|
||||||
|
$latex \[
|
||||||
|
y_i^k = F_i^k [ \{ x_j^k \} ]
|
||||||
|
\] $$
|
||||||
|
Note that
|
||||||
|
$latex \[
|
||||||
|
F_i^0 ( \{ x_j^k \} ) = g_i ( X(0) ) = g_i ( x^0 )
|
||||||
|
\] $$
|
||||||
|
We also note that
|
||||||
|
$latex F_i^\ell ( \{ x_j^k \} )$$ is a function of
|
||||||
|
$latex x^0 , \ldots , x^\ell$$
|
||||||
|
and is determined by the derivatives of $latex g_i (x)$$
|
||||||
|
up to order $latex \ell$$.
|
||||||
|
|
||||||
|
$head G, H$$
|
||||||
|
We use $latex G : \B{R}^{m \times (q+1)} \rightarrow \B{R}$$
|
||||||
|
to denote an arbitrary scalar valued function of $latex \{ y_i^k \}$$.
|
||||||
|
We use $latex H : \B{R}^{n \times (q+1)} \rightarrow \B{R}$$
|
||||||
|
defined by
|
||||||
|
$latex \[
|
||||||
|
H ( \{ x_j^k \} ) = G[ F( \{ x_j^k \} ) ]
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head partial_y$$
|
||||||
|
The size of $icode partial_y$$ is $codei%(%q%+1)*%m%%$$.
|
||||||
|
For $latex i = 0 , \ldots , m-1$$, $latex k = 0 , \ldots , q$$,
|
||||||
|
$latex \[
|
||||||
|
\R{partial\_y} [ i * (q + 1 ) + k ] = \partial G / \partial y_i^k
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head apartial_y$$
|
||||||
|
The specifications for $icode apartial_y$$ is the same as for
|
||||||
|
$icode partial_y$$ (only the type of $icode apartial_y$$ is different).
|
||||||
|
|
||||||
|
$head partial_x$$
|
||||||
|
The size of $icode partial_x$$ is $codei%(%q%+1)*%n%%$$.
|
||||||
|
The input values of the elements of $icode partial_x$$
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return,
|
||||||
|
for $latex j = 0 , \ldots , n-1$$ and $latex \ell = 0 , \ldots , q$$,
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
\R{partial\_x} [ j * (q + 1) + \ell ] & = & \partial H / \partial x_j^\ell
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
( \partial G / \partial \{ y_i^k \} ) \cdot
|
||||||
|
( \partial \{ y_i^k \} / \partial x_j^\ell )
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
\sum_{k=0}^q
|
||||||
|
\sum_{i=0}^{m-1}
|
||||||
|
( \partial G / \partial y_i^k ) ( \partial y_i^k / \partial x_j^\ell )
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
\sum_{k=\ell}^q
|
||||||
|
\sum_{i=0}^{m-1}
|
||||||
|
\R{partial\_y}[ i * (q + 1 ) + k ] ( \partial F_i^k / \partial x_j^\ell )
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
Note that we have used the fact that for $latex k < \ell$$,
|
||||||
|
$latex \partial F_i^k / \partial x_j^\ell = 0$$.
|
||||||
|
|
||||||
|
$subhead Short Circuit Operations$$
|
||||||
|
Note that if
|
||||||
|
$codei%IdenticalZero(%partial_y%[%i%*(%q%+1)+%k%])%$$ is true,
|
||||||
|
one does not need to compute $latex ( \partial F_i^k / \partial x_j^\ell )$$;
|
||||||
|
see $cref base_identical$$.
|
||||||
|
This can be used,
|
||||||
|
in a similar way to $cref/need_y/atomic_three_forward/need_y/$$,
|
||||||
|
to avoid unnecessary operations.
|
||||||
|
|
||||||
|
$head apartial_x$$
|
||||||
|
The specifications for $icode apartial_x$$ is the same as for
|
||||||
|
$icode partial_x$$ (only the type of $icode apartial_x$$ is different).
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
If this calculation succeeded, $icode ok$$ is true.
|
||||||
|
Otherwise it is false.
|
||||||
|
|
||||||
|
$children%
|
||||||
|
example/atomic_three/reverse.cpp
|
||||||
|
%$$
|
||||||
|
$head Examples$$
|
||||||
|
The file $cref atomic_three_reverse.cpp$$ contains an example and test
|
||||||
|
that uses this routine.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/three_reverse.hpp
|
||||||
|
Third Generation Atomic reverse mode.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from reverse mode sweep to users routine.
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
contains the values, in afun(ax, ay), for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order for this reverse mode calculation.
|
||||||
|
|
||||||
|
\param taylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param taylor_y [in]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
\param partial_x [out]
|
||||||
|
Partials w.r.t. the x Taylor coefficients.
|
||||||
|
|
||||||
|
\param partial_y [in]
|
||||||
|
Partials w.r.t. the y Taylor coefficients.
|
||||||
|
|
||||||
|
See atomic_three_reverse mode use documentation
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE_BASE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_three<Base>::reverse(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
const vector<Base>& taylor_y ,
|
||||||
|
vector<Base>& partial_x ,
|
||||||
|
const vector<Base>& partial_y )
|
||||||
|
// END_PROTOTYPE_BASE
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Link from reverse mode sweep to users routine.
|
||||||
|
|
||||||
|
\param aparameter_x [in]
|
||||||
|
contains the values, in afun(ax, ay), for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order for this reverse mode calculation.
|
||||||
|
|
||||||
|
\param ataylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param ataylor_y [in]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
\param apartial_x [out]
|
||||||
|
Partials w.r.t. the x Taylor coefficients.
|
||||||
|
|
||||||
|
\param apartial_y [in]
|
||||||
|
Partials w.r.t. the y Taylor coefficients.
|
||||||
|
|
||||||
|
See atomic_three_reverse mode use documentation
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE_AD_BASE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_three<Base>::reverse(
|
||||||
|
const vector< AD<Base> >& aparameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
const vector< AD<Base> >& ataylor_y ,
|
||||||
|
vector< AD<Base> >& apartial_x ,
|
||||||
|
const vector< AD<Base> >& apartial_y )
|
||||||
|
// END_PROTOTYPE_AD_BASE
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
258
build-config/cppad/include/cppad/core/atomic/two_afun.hpp
Normal file
258
build-config/cppad/include/cppad/core/atomic/two_afun.hpp
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_AFUN_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_AFUN_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_afun$$
|
||||||
|
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul
|
||||||
|
afun
|
||||||
|
const
|
||||||
|
CppAD
|
||||||
|
mat_mul.cpp
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Using AD Version of Atomic Function$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%afun%(%ax%, %ay%)%$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
Given $icode ax$$,
|
||||||
|
this call computes the corresponding value of $icode ay$$.
|
||||||
|
If $codei%AD<%Base%>%$$ operations are being recorded,
|
||||||
|
it enters the computation as an atomic operation in the recording;
|
||||||
|
see $cref/start recording/Independent/Start Recording/$$.
|
||||||
|
|
||||||
|
$head ADVector$$
|
||||||
|
The type $icode ADVector$$ must be a
|
||||||
|
$cref/simple vector class/SimpleVector/$$ with elements of type
|
||||||
|
$codei%AD<%Base%>%$$; see $cref/Base/atomic_two_ctor/atomic_base/Base/$$.
|
||||||
|
|
||||||
|
$head afun$$
|
||||||
|
is a $cref/atomic_user/atomic_two_ctor/atomic_user/$$ object
|
||||||
|
and this $icode afun$$ function call is implemented by the
|
||||||
|
$cref/atomic/atomic_two_ctor/atomic_base/$$ class.
|
||||||
|
|
||||||
|
$head ax$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const %ADVector%& %ax%
|
||||||
|
%$$
|
||||||
|
and size must be equal to $icode n$$.
|
||||||
|
It specifies vector $latex x \in \B{R}^n$$
|
||||||
|
at which an $codei%AD<%Base%>%$$ version of
|
||||||
|
$latex y = f(x)$$ is to be evaluated; see
|
||||||
|
$cref/Base/atomic_two_ctor/atomic_base/Base/$$.
|
||||||
|
|
||||||
|
$head ay$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
%ADVector%& %ay%
|
||||||
|
%$$
|
||||||
|
and size must be equal to $icode m$$.
|
||||||
|
The input values of its elements
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, it is an $codei%AD<%Base%>%$$ version of
|
||||||
|
$latex y = f(x)$$.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_afun.hpp
|
||||||
|
Implement user call to an atomic_two function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Implement the user call to afun(ax, ay) and atomic_one call to
|
||||||
|
afun(ax, ay, id).
|
||||||
|
|
||||||
|
\tparam ADVector
|
||||||
|
A simple vector class with elements of type <code>AD<Base></code>.
|
||||||
|
|
||||||
|
\param id
|
||||||
|
optional extra information vector that is just passed through by CppAD,
|
||||||
|
and used by atomic_one derived class (not other derived classes).
|
||||||
|
This is an extra parameter to the virtual callbacks for atomic_one;
|
||||||
|
see the set_old member function.
|
||||||
|
|
||||||
|
\param ax
|
||||||
|
is the argument vector for this call,
|
||||||
|
<tt>ax.size()</tt> determines the number of arguments.
|
||||||
|
|
||||||
|
\param ay
|
||||||
|
is the result vector for this call,
|
||||||
|
<tt>ay.size()</tt> determines the number of results.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class ADVector>
|
||||||
|
void atomic_base<Base>::operator()(
|
||||||
|
const ADVector& ax ,
|
||||||
|
ADVector& ay ,
|
||||||
|
size_t id )
|
||||||
|
{ size_t i, j;
|
||||||
|
size_t n = ax.size();
|
||||||
|
size_t m = ay.size();
|
||||||
|
# ifndef NDEBUG
|
||||||
|
bool ok;
|
||||||
|
std::string msg = "atomic_base: " + atomic_name() + ".eval: ";
|
||||||
|
if( (n == 0) | (m == 0) )
|
||||||
|
{ msg += "ax.size() or ay.size() is zero";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_work(thread);
|
||||||
|
vector <Base>& tx = work_[thread]->tx;
|
||||||
|
vector <Base>& ty = work_[thread]->ty;
|
||||||
|
vector <bool>& vx = work_[thread]->vx;
|
||||||
|
vector <bool>& vy = work_[thread]->vy;
|
||||||
|
//
|
||||||
|
if( vx.size() != n )
|
||||||
|
{ vx.resize(n);
|
||||||
|
tx.resize(n);
|
||||||
|
}
|
||||||
|
if( vy.size() != m )
|
||||||
|
{ vy.resize(m);
|
||||||
|
ty.resize(m);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Determine tape corresponding to variables in ax
|
||||||
|
tape_id_t tape_id = 0;
|
||||||
|
local::ADTape<Base>* tape = nullptr;
|
||||||
|
for(j = 0; j < n; j++)
|
||||||
|
{ tx[j] = ax[j].value_;
|
||||||
|
vx[j] = ! Constant( ax[j] );
|
||||||
|
if( vx[j] )
|
||||||
|
{
|
||||||
|
if( tape_id == 0 )
|
||||||
|
{ tape = ax[j].tape_this();
|
||||||
|
tape_id = ax[j].tape_id_;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( tape != nullptr );
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( tape_id != ax[j].tape_id_ )
|
||||||
|
{ msg += atomic_name() +
|
||||||
|
": ax contains variables from different threads.";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Use zero order forward mode to compute values
|
||||||
|
size_t p = 0, q = 0;
|
||||||
|
set_old(id);
|
||||||
|
# ifdef NDEBUG
|
||||||
|
forward(p, q, vx, vy, tx, ty);
|
||||||
|
# else
|
||||||
|
ok = forward(p, q, vx, vy, tx, ty);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg += atomic_name() + ": ok is false for "
|
||||||
|
"zero order forward mode calculation.";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
bool record_operation = false;
|
||||||
|
for(i = 0; i < m; i++)
|
||||||
|
{
|
||||||
|
// pass back values
|
||||||
|
ay[i].value_ = ty[i];
|
||||||
|
|
||||||
|
// initialize entire vector parameters (not in tape)
|
||||||
|
ay[i].tape_id_ = 0;
|
||||||
|
ay[i].taddr_ = 0;
|
||||||
|
|
||||||
|
// we need to record this operation if
|
||||||
|
// any of the elemnts of ay are variables,
|
||||||
|
record_operation |= vy[i];
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( record_operation & (tape == nullptr) )
|
||||||
|
{ msg +=
|
||||||
|
"all elements of vx are false but vy contains a true element";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
// if tape is not null, ay is on the tape
|
||||||
|
if( record_operation )
|
||||||
|
{
|
||||||
|
// Operator that marks beginning of this atomic operation
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::AFunOp) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::AFunOp) == 4 );
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
size_t( std::numeric_limits<addr_t>::max() ) >=
|
||||||
|
std::max( std::max( std::max(index_, id), n), m ),
|
||||||
|
"atomic_base: cppad_tape_addr_type maximum not large enough"
|
||||||
|
);
|
||||||
|
tape->Rec_.PutArg(addr_t(index_), addr_t(id), addr_t(n), addr_t(m));
|
||||||
|
tape->Rec_.PutOp(local::AFunOp);
|
||||||
|
|
||||||
|
// Now put n operators, one for each element of argument vector
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::FunavOp) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::FunapOp) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::FunavOp) == 1 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::FunapOp) == 1 );
|
||||||
|
for(j = 0; j < n; j++)
|
||||||
|
{ if( Variable(ax[j]) )
|
||||||
|
{ // information for an argument that is a variable
|
||||||
|
tape->Rec_.PutArg(ax[j].taddr_);
|
||||||
|
tape->Rec_.PutOp(local::FunavOp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // information for an argument that is parameter
|
||||||
|
addr_t par = ax[j].taddr_;
|
||||||
|
if( ! Dynamic( ax[j] ) )
|
||||||
|
par = tape->Rec_.put_con_par(ax[j].value_);
|
||||||
|
tape->Rec_.PutArg(par);
|
||||||
|
tape->Rec_.PutOp(local::FunapOp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now put m operators, one for each element of result vector
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::FunrpOp) == 1 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::FunrpOp) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::FunrvOp) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::FunrvOp) == 1 );
|
||||||
|
for(i = 0; i < m; i++)
|
||||||
|
{ if( vy[i] )
|
||||||
|
{ ay[i].taddr_ = tape->Rec_.PutOp(local::FunrvOp);
|
||||||
|
ay[i].tape_id_ = tape_id;
|
||||||
|
ay[i].ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( ! Dynamic( ay[i] ) );
|
||||||
|
addr_t par = tape->Rec_.put_con_par(ay[i].value_);
|
||||||
|
tape->Rec_.PutArg(par);
|
||||||
|
tape->Rec_.PutOp(local::FunrpOp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put a duplicate AFunOp at end of AFunOp sequence
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
size_t( std::numeric_limits<addr_t>::max() ) >=
|
||||||
|
std::max( std::max( std::max(index_, id), n), m ),
|
||||||
|
"atomic_base: cppad_tape_addr_type maximum not large enough"
|
||||||
|
);
|
||||||
|
tape->Rec_.PutArg(addr_t(index_), addr_t(id), addr_t(n), addr_t(m));
|
||||||
|
tape->Rec_.PutOp(local::AFunOp);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
91
build-config/cppad/include/cppad/core/atomic/two_clear.hpp
Normal file
91
build-config/cppad/include/cppad/core/atomic/two_clear.hpp
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_CLEAR_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_CLEAR_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_clear$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
alloc
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Free Static Variables$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$codei%atomic_base<%Base%>::clear()%$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
Each $code atomic_base$$ objects holds onto work space in order to
|
||||||
|
avoid repeated memory allocation calls and thereby increase speed
|
||||||
|
(until it is deleted).
|
||||||
|
If an the $code atomic_base$$ object is global or static because,
|
||||||
|
the it does not get deleted.
|
||||||
|
This is a problem when using
|
||||||
|
$code thread_alloc$$ $cref/free_all/ta_free_all/$$
|
||||||
|
to check that all allocated memory has been freed.
|
||||||
|
Calling this $code clear$$ function will free all the
|
||||||
|
memory currently being held onto by the
|
||||||
|
$codei%atomic_base<%Base%>%$$ class.
|
||||||
|
|
||||||
|
$head Future Use$$
|
||||||
|
If there is future use of an $code atomic_base$$ object,
|
||||||
|
after a call to $code clear$$,
|
||||||
|
the work space will be reallocated and held onto.
|
||||||
|
|
||||||
|
$head Restriction$$
|
||||||
|
This routine cannot be called
|
||||||
|
while in $cref/parallel/ta_in_parallel/$$ execution mode.
|
||||||
|
|
||||||
|
$end
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_clear.hpp
|
||||||
|
Free static variables in atomic_base class.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Free all thread_alloc static memory held by atomic_base (avoids reallocations).
|
||||||
|
(This does not include class_object() which is an std::vector.)
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
void atomic_base<Base>::clear(void)
|
||||||
|
{ CPPAD_ASSERT_KNOWN(
|
||||||
|
! thread_alloc::in_parallel() ,
|
||||||
|
"cannot use atomic_base clear during parallel execution"
|
||||||
|
);
|
||||||
|
bool set_null = true;
|
||||||
|
size_t index = 0;
|
||||||
|
size_t type = 0; // set to avoid warning
|
||||||
|
std::string* name = nullptr;
|
||||||
|
void* v_ptr = nullptr; // set to avoid warning
|
||||||
|
size_t n_atomic = local::atomic_index<Base>(
|
||||||
|
set_null, index, type, name, v_ptr
|
||||||
|
);
|
||||||
|
//
|
||||||
|
set_null = false;
|
||||||
|
for(index = 1; index <= n_atomic; ++index)
|
||||||
|
{ local::atomic_index<Base>(set_null, index, type, name, v_ptr);
|
||||||
|
if( type == 2 )
|
||||||
|
{ atomic_base* op = reinterpret_cast<atomic_base*>(v_ptr);
|
||||||
|
if( op != nullptr )
|
||||||
|
{ for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)
|
||||||
|
op->free_work(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
173
build-config/cppad/include/cppad/core/atomic/two_ctor.hpp
Normal file
173
build-config/cppad/include/cppad/core/atomic/two_ctor.hpp
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_CTOR_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_CTOR_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_ctor$$
|
||||||
|
$spell
|
||||||
|
enum
|
||||||
|
sq
|
||||||
|
std
|
||||||
|
afun
|
||||||
|
arg
|
||||||
|
CppAD
|
||||||
|
bool
|
||||||
|
ctor
|
||||||
|
const
|
||||||
|
mat_mul_xam.cpp
|
||||||
|
hpp
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Function Constructor$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%atomic_user afun%(%ctor_arg_list%)
|
||||||
|
%$$
|
||||||
|
$codei%atomic_base<%Base%>(%name%, %sparsity%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head atomic_user$$
|
||||||
|
|
||||||
|
$subhead ctor_arg_list$$
|
||||||
|
Is a list of arguments for the $icode atomic_user$$ constructor.
|
||||||
|
|
||||||
|
$subhead afun$$
|
||||||
|
The object $icode afun$$ must stay in scope for as long
|
||||||
|
as the corresponding atomic function is used.
|
||||||
|
This includes use by any $cref/ADFun<Base>/ADFun/$$ that
|
||||||
|
has this $icode atomic_user$$ operation in its
|
||||||
|
$cref/operation sequence/glossary/Operation/Sequence/$$.
|
||||||
|
|
||||||
|
$subhead Implementation$$
|
||||||
|
The user defined $icode atomic_user$$ class is a publicly derived class of
|
||||||
|
$codei%atomic_base<%Base%>%$$.
|
||||||
|
It should be declared as follows:
|
||||||
|
$codei%
|
||||||
|
class %atomic_user% : public CppAD::atomic_base<%Base%> {
|
||||||
|
public:
|
||||||
|
%atomic_user%(%ctor_arg_list%) : atomic_base<%Base%>(%name%, %sparsity%)
|
||||||
|
%...%
|
||||||
|
};
|
||||||
|
%$$
|
||||||
|
where $icode ...$$
|
||||||
|
denotes the rest of the implementation of the derived class.
|
||||||
|
This includes completing the constructor and
|
||||||
|
all the virtual functions that have their
|
||||||
|
$code atomic_base$$ implementations replaced by
|
||||||
|
$icode atomic_user$$ implementations.
|
||||||
|
|
||||||
|
$head atomic_base$$
|
||||||
|
|
||||||
|
$subhead Restrictions$$
|
||||||
|
The $code atomic_base$$ constructor and destructor cannot be called in
|
||||||
|
$cref/parallel/ta_in_parallel/$$ mode.
|
||||||
|
|
||||||
|
$subhead Base$$
|
||||||
|
The template parameter determines the
|
||||||
|
$icode Base$$ type for this $codei%AD<%Base%>%$$ atomic operation.
|
||||||
|
|
||||||
|
$subhead name$$
|
||||||
|
This $code atomic_base$$ constructor argument has the following prototype
|
||||||
|
$codei%
|
||||||
|
const std::string& %name%
|
||||||
|
%$$
|
||||||
|
It is the name for this atomic function and is used for error reporting.
|
||||||
|
The suggested value for $icode name$$ is $icode afun$$ or $icode atomic_user$$,
|
||||||
|
i.e., the name of the corresponding atomic object or class.
|
||||||
|
|
||||||
|
$subhead sparsity$$
|
||||||
|
This $code atomic_base$$ constructor argument has prototype
|
||||||
|
$codei%
|
||||||
|
atomic_base<%Base%>::option_enum %sparsity%
|
||||||
|
%$$
|
||||||
|
The current $icode sparsity$$ for an $code atomic_base$$ object
|
||||||
|
determines which type of sparsity patterns it uses
|
||||||
|
and its value is one of the following:
|
||||||
|
$table
|
||||||
|
$icode sparsity$$ $cnext sparsity patterns $rnext
|
||||||
|
$codei%atomic_base<%Base%>::pack_sparsity_enum%$$ $pre $$ $cnext
|
||||||
|
$cref/vectorBool/CppAD_vector/vectorBool/$$
|
||||||
|
$rnext
|
||||||
|
$codei%atomic_base<%Base%>::bool_sparsity_enum%$$ $pre $$ $cnext
|
||||||
|
$cref/vector/CppAD_vector/$$$code <bool>$$
|
||||||
|
$rnext
|
||||||
|
$codei%atomic_base<%Base%>::set_sparsity_enum%$$ $pre $$ $cnext
|
||||||
|
$cref/vector/CppAD_vector/$$$code <std::set<std::size_t> >$$
|
||||||
|
$tend
|
||||||
|
There is a default value for $icode sparsity$$ if it is not
|
||||||
|
included in the constructor (which may be either the bool or set option).
|
||||||
|
|
||||||
|
$end
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_ctor.hpp
|
||||||
|
Constructors for atomic_base class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Base class for atomic_atomic functions.
|
||||||
|
|
||||||
|
\tparam Base
|
||||||
|
This class is used for defining an AD<Base> atomic operation y = f(x).
|
||||||
|
|
||||||
|
\par
|
||||||
|
make sure user does not invoke the default constructor
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
atomic_base<Base>::atomic_base(void)
|
||||||
|
{ CPPAD_ASSERT_KNOWN(false,
|
||||||
|
"Attempt to use the atomic_base default constructor"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
Constructor
|
||||||
|
|
||||||
|
\param name
|
||||||
|
name used for error reporting
|
||||||
|
|
||||||
|
\param sparsity [in]
|
||||||
|
what type of sparsity patterns are computed by this function,
|
||||||
|
bool_sparsity_enum or set_sparsity_enum. Default value is
|
||||||
|
bool sparsity patterns.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
atomic_base<Base>::atomic_base(
|
||||||
|
const std::string& name,
|
||||||
|
option_enum sparsity
|
||||||
|
) :
|
||||||
|
sparsity_( sparsity )
|
||||||
|
{ CPPAD_ASSERT_KNOWN(
|
||||||
|
! thread_alloc::in_parallel() ,
|
||||||
|
"atomic_base: constructor cannot be called in parallel mode."
|
||||||
|
);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( constant_enum < dynamic_enum );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( dynamic_enum < variable_enum );
|
||||||
|
//
|
||||||
|
// atomic_index
|
||||||
|
bool set_null = false;
|
||||||
|
size_t index = 0;
|
||||||
|
size_t type = 2;
|
||||||
|
std::string copy_name = name;
|
||||||
|
void* copy_this = reinterpret_cast<void*>( this );
|
||||||
|
index_ = local::atomic_index<Base>(
|
||||||
|
set_null, index, type, ©_name, copy_this
|
||||||
|
);
|
||||||
|
// initialize work pointers as null;
|
||||||
|
for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)
|
||||||
|
work_[thread] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_FOR_SPARSE_HES_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_FOR_SPARSE_HES_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_for_sparse_hes$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul.hpp
|
||||||
|
vx
|
||||||
|
afun
|
||||||
|
Jacobian
|
||||||
|
jac
|
||||||
|
CppAD
|
||||||
|
std
|
||||||
|
bool
|
||||||
|
hes
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Forward Hessian Sparsity Patterns$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ok% = %afun%.for_sparse_hes(%vx%, %r%, %s%, %h%, %x%)%$$
|
||||||
|
|
||||||
|
$head Deprecated 2016-06-27$$
|
||||||
|
$icode%ok% = %afun%.for_sparse_hes(%vx%, %r%, %s%, %h%)%$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
This function is used by $cref ForSparseHes$$ to compute
|
||||||
|
Hessian sparsity patterns.
|
||||||
|
If you are using $cref ForSparseHes$$,
|
||||||
|
one of the versions of this
|
||||||
|
virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
$pre
|
||||||
|
|
||||||
|
$$
|
||||||
|
Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for
|
||||||
|
a diagonal matrix $latex R \in \B{R}^{n \times n}$$, and
|
||||||
|
a row vector $latex S \in \B{R}^{1 \times m}$$,
|
||||||
|
this routine computes the sparsity pattern for
|
||||||
|
$latex \[
|
||||||
|
H(x) = R^\R{T} \cdot (S \cdot f)^{(2)}( x ) \cdot R
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
If you are using and $cref ForSparseHes$$,
|
||||||
|
this virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
|
||||||
|
$subhead vx$$
|
||||||
|
The argument $icode vx$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD:vector<bool>& %vx%
|
||||||
|
%$$
|
||||||
|
$icode%vx%.size() == %n%$$, and
|
||||||
|
for $latex j = 0 , \ldots , n-1$$,
|
||||||
|
$icode%vx%[%j%]%$$ is true if and only if
|
||||||
|
$icode%ax%[%j%]%$$ is a $cref/variable/glossary/Variable/$$
|
||||||
|
or $cref/dynamic parameter/glossary/Parameter/Dynamic/$$
|
||||||
|
in the corresponding call to
|
||||||
|
$codei%
|
||||||
|
%afun%(%ax%, %ay%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$subhead r$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD:vector<bool>& %r%
|
||||||
|
%$$
|
||||||
|
and is a $cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
the diagonal of $latex R \in \B{R}^{n \times n}$$.
|
||||||
|
|
||||||
|
$subhead s$$
|
||||||
|
The argument $icode s$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD:vector<bool>& %s%
|
||||||
|
%$$
|
||||||
|
and its size is $icode m$$.
|
||||||
|
It is a sparsity pattern for $latex S \in \B{R}^{1 \times m}$$.
|
||||||
|
|
||||||
|
$subhead h$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
%atomic_sparsity%& %h%
|
||||||
|
%$$
|
||||||
|
The input value of its elements
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, $icode h$$ is a
|
||||||
|
$cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
$latex H(x) \in \B{R}^{n \times n}$$ which is defined above.
|
||||||
|
|
||||||
|
$subhead x$$
|
||||||
|
$index deprecated$$
|
||||||
|
The argument has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%>& %x%
|
||||||
|
%$$
|
||||||
|
and size is equal to the $icode n$$.
|
||||||
|
This is the $cref Value$$ value corresponding to the parameters in the
|
||||||
|
vector $cref/ax/atomic_two_afun/ax/$$ (when the atomic function was called).
|
||||||
|
To be specific, if
|
||||||
|
$codei%
|
||||||
|
if( Parameter(%ax%[%i%]) == true )
|
||||||
|
%x%[%i%] = Value( %ax%[%i%] );
|
||||||
|
else
|
||||||
|
%x%[%i%] = CppAD::numeric_limits<%Base%>::quiet_NaN();
|
||||||
|
%$$
|
||||||
|
The version of this function with out the $icode x$$ argument is deprecated;
|
||||||
|
i.e., you should include the argument even if you do not use it.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_for_sparse_hes.hpp
|
||||||
|
Atomic forward mode Hessian sparsity patterns.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link, after case split, from for_hes_sweep to atomic_base.
|
||||||
|
|
||||||
|
\param vx [in]
|
||||||
|
which componens of x are variables.
|
||||||
|
|
||||||
|
\param r [in]
|
||||||
|
is the forward Jacobian sparsity pattern w.r.t the argument vector x.
|
||||||
|
|
||||||
|
\param s [in]
|
||||||
|
is the reverse Jacobian sparsity pattern w.r.t the result vector y.
|
||||||
|
|
||||||
|
\param h [out]
|
||||||
|
is the Hessian sparsity pattern w.r.t the argument vector x.
|
||||||
|
|
||||||
|
\param x
|
||||||
|
is the integer value of the x arguments that are parameters.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector< std::set<size_t> >& h ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& h ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vectorBool& h ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
// deprecated versions
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector< std::set<size_t> >& h )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& h )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vectorBool& h )
|
||||||
|
{ return false; }
|
||||||
|
/*!
|
||||||
|
Link, before case split, from for_hes_sweep to atomic_base.
|
||||||
|
2DO: move this functiton outside this file so can change
|
||||||
|
developer documentation to omhelp formating.
|
||||||
|
|
||||||
|
\tparam InternalSparsity
|
||||||
|
Is the used internaly for sparsity calculations; i.e.,
|
||||||
|
sparse_pack or sparse_list.
|
||||||
|
|
||||||
|
\param x
|
||||||
|
is parameter arguments to the function, other components are nan.
|
||||||
|
|
||||||
|
\param x_index
|
||||||
|
is the variable index, on the tape, for the arguments to this function.
|
||||||
|
This size of x_index is n, the number of arguments to this function.
|
||||||
|
|
||||||
|
\param y_index
|
||||||
|
is the variable index, on the tape, for the results for this function.
|
||||||
|
This size of y_index is m, the number of results for this function.
|
||||||
|
|
||||||
|
\param for_jac_sparsity
|
||||||
|
On input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
is the forward Jacobian sparsity for the j-th argument to this atomic function.
|
||||||
|
|
||||||
|
\param rev_jac_sparsity
|
||||||
|
On input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],
|
||||||
|
is the reverse Jacobian sparsity for the i-th result to this atomic function.
|
||||||
|
This shows which components of the result affect the function we are
|
||||||
|
computing the Hessian of.
|
||||||
|
|
||||||
|
\param for_hes_sparsity
|
||||||
|
This is the sparsity pattern for the Hessian. On input, the non-linear
|
||||||
|
terms in the atomic fuction have not been included. Upon return, they
|
||||||
|
have been included.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool atomic_base<Base>::for_sparse_hes(
|
||||||
|
const vector<Base>& x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
size_t np1 ,
|
||||||
|
size_t numvar ,
|
||||||
|
const InternalSparsity& rev_jac_sparsity ,
|
||||||
|
InternalSparsity& for_sparsity )
|
||||||
|
{ typedef typename InternalSparsity::const_iterator const_iterator;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( rev_jac_sparsity.end() == 1 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( for_sparsity.end() == np1 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( for_sparsity.n_set() == np1 + numvar );
|
||||||
|
size_t n = x_index.size();
|
||||||
|
size_t m = y_index.size();
|
||||||
|
bool ok = false;
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_work(thread);
|
||||||
|
//
|
||||||
|
// vx
|
||||||
|
vector<bool> vx(n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
vx[j] = x_index[j] != 0;
|
||||||
|
//
|
||||||
|
// bool_r
|
||||||
|
vector<bool>& bool_r( work_[thread]->bool_r );
|
||||||
|
bool_r.resize(n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ // check if we must compute row and column j of h
|
||||||
|
const_iterator itr(for_sparsity, np1 + x_index[j]);
|
||||||
|
size_t i = *itr;
|
||||||
|
bool_r[j] = i < np1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bool s
|
||||||
|
vector<bool>& bool_s( work_[thread]->bool_s );
|
||||||
|
bool_s.resize(m);
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ // check if row i of result is included in h
|
||||||
|
bool_s[i] = rev_jac_sparsity.is_element(y_index[i], 0);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// h
|
||||||
|
vectorBool& pack_h( work_[thread]->pack_h );
|
||||||
|
vector<bool>& bool_h( work_[thread]->bool_h );
|
||||||
|
vector< std::set<size_t> >& set_h( work_[thread]->set_h );
|
||||||
|
//
|
||||||
|
// call user's version of atomic function
|
||||||
|
std::string msg = ": atomic_base.for_sparse_hes: returned false";
|
||||||
|
if( sparsity_ == pack_sparsity_enum )
|
||||||
|
{ pack_h.resize(n * n);
|
||||||
|
ok = for_sparse_hes(vx, bool_r, bool_s, pack_h, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = for_sparse_hes(vx, bool_r, bool_s, pack_h);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = pack_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( sparsity_ == bool_sparsity_enum )
|
||||||
|
{ bool_h.resize(n * n);
|
||||||
|
ok = for_sparse_hes(vx, bool_r, bool_s, bool_h, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = for_sparse_hes(vx, bool_r, bool_s, bool_h);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = bool_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum )
|
||||||
|
set_h.resize(n);
|
||||||
|
ok = for_sparse_hes(vx, bool_r, bool_s, set_h, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = for_sparse_hes(vx, bool_r, bool_s, set_h);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = set_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ok );
|
||||||
|
//
|
||||||
|
// modify hessian in calling routine
|
||||||
|
for(size_t i = 0; i < n; i++)
|
||||||
|
{ for(size_t j = 0; j < n; j++)
|
||||||
|
{ if( (x_index[i] > 0) & (x_index[j] > 0) )
|
||||||
|
{ bool flag = false;
|
||||||
|
switch( sparsity_ )
|
||||||
|
{ case pack_sparsity_enum:
|
||||||
|
flag = pack_h[i * n + j];
|
||||||
|
break;
|
||||||
|
//
|
||||||
|
case bool_sparsity_enum:
|
||||||
|
flag = bool_h[i * n + j];
|
||||||
|
break;
|
||||||
|
//
|
||||||
|
case set_sparsity_enum:
|
||||||
|
flag = set_h[i].find(j) != set_h[i].end();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( flag )
|
||||||
|
{ const_iterator itr_i(for_sparsity, np1 + x_index[i]);
|
||||||
|
size_t i_x = *itr_i;
|
||||||
|
while( i_x < np1 )
|
||||||
|
{ for_sparsity.binary_union(
|
||||||
|
i_x, i_x, np1 + x_index[j], for_sparsity
|
||||||
|
);
|
||||||
|
i_x = *(++itr_i);
|
||||||
|
}
|
||||||
|
const_iterator itr_j(for_sparsity, np1 + x_index[j]);
|
||||||
|
size_t j_x = *itr_j;
|
||||||
|
while( j_x < np1 )
|
||||||
|
{ for_sparsity.binary_union(
|
||||||
|
j_x, j_x, np1 + x_index[i], for_sparsity
|
||||||
|
);
|
||||||
|
j_x = *(++itr_j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,283 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_FOR_SPARSE_JAC_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_FOR_SPARSE_JAC_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_for_sparse_jac$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul.hpp
|
||||||
|
afun
|
||||||
|
Jacobian
|
||||||
|
jac
|
||||||
|
const
|
||||||
|
CppAD
|
||||||
|
std
|
||||||
|
bool
|
||||||
|
std
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Forward Jacobian Sparsity Patterns$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ok% = %afun%.for_sparse_jac(%q%, %r%, %s%, %x%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Deprecated 2016-06-27$$
|
||||||
|
$icode%ok% = %afun%.for_sparse_jac(%q%, %r%, %s%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
This function is used by $cref ForSparseJac$$ to compute
|
||||||
|
Jacobian sparsity patterns.
|
||||||
|
For a fixed matrix $latex R \in \B{R}^{n \times q}$$,
|
||||||
|
the Jacobian of $latex f( x + R * u)$$ with respect to $latex u \in \B{R}^q$$ is
|
||||||
|
$latex \[
|
||||||
|
S(x) = f^{(1)} (x) * R
|
||||||
|
\] $$
|
||||||
|
Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$,
|
||||||
|
$code for_sparse_jac$$ computes a sparsity pattern for $latex S(x)$$.
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
If you are using
|
||||||
|
$cref ForSparseJac$$,
|
||||||
|
$cref ForSparseHes$$, or
|
||||||
|
$cref RevSparseHes$$,
|
||||||
|
one of the versions of this
|
||||||
|
virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
|
||||||
|
$subhead 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 Jacobian
|
||||||
|
$latex S(x) \in \B{R}^{m \times q}$$.
|
||||||
|
|
||||||
|
$subhead r$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const %atomic_sparsity%& %r%
|
||||||
|
%$$
|
||||||
|
and is a $cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
$latex R \in \B{R}^{n \times q}$$.
|
||||||
|
|
||||||
|
$subhead s$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
%atomic_sparsity%& %s%
|
||||||
|
%$$
|
||||||
|
The input values of its elements
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, $icode s$$ is a
|
||||||
|
$cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
$latex S(x) \in \B{R}^{m \times q}$$.
|
||||||
|
|
||||||
|
$subhead x$$
|
||||||
|
$index deprecated$$
|
||||||
|
The argument has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%>& %x%
|
||||||
|
%$$
|
||||||
|
and size is equal to the $icode n$$.
|
||||||
|
This is the $cref Value$$ value corresponding to the parameters in the
|
||||||
|
vector $cref/ax/atomic_two_afun/ax/$$ (when the atomic function was called).
|
||||||
|
To be specific, if
|
||||||
|
$codei%
|
||||||
|
if( Parameter(%ax%[%i%]) == true )
|
||||||
|
%x%[%i%] = Value( %ax%[%i%] );
|
||||||
|
else
|
||||||
|
%x%[%i%] = CppAD::numeric_limits<%Base%>::quiet_NaN();
|
||||||
|
%$$
|
||||||
|
The version of this function with out the $icode x$$ argument is deprecated;
|
||||||
|
i.e., you should include the argument even if you do not use it.
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
The return value $icode ok$$ has prototype
|
||||||
|
$codei%
|
||||||
|
bool %ok%
|
||||||
|
%$$
|
||||||
|
If it is $code true$$, the corresponding evaluation succeeded,
|
||||||
|
otherwise it failed.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_for_sparse_jac.hpp
|
||||||
|
Atomic forward Jacobian sparsity pattern.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link, after case split, from for_jac_sweep to atomic_base.
|
||||||
|
|
||||||
|
\param q
|
||||||
|
is the column dimension for the Jacobian sparsity partterns.
|
||||||
|
|
||||||
|
\param r
|
||||||
|
is the Jacobian sparsity pattern for the argument vector x
|
||||||
|
|
||||||
|
\param s
|
||||||
|
is the Jacobian sparsity pattern for the result vector y
|
||||||
|
|
||||||
|
\param x
|
||||||
|
is the integer value for x arguments that are parameters.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
vector< std::set<size_t> >& s ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
vector<bool>& s ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
vectorBool& s ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
// deprecated versions
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
vector< std::set<size_t> >& s )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
vector<bool>& s )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
vectorBool& s )
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Link, before case split, from for_jac_sweep to atomic_base.
|
||||||
|
|
||||||
|
\tparam InternalSparsity
|
||||||
|
Is the type used for internal sparsity calculations; i.e.,
|
||||||
|
sparse_pack or sparse_list.
|
||||||
|
|
||||||
|
\param x
|
||||||
|
is parameter arguments to the function, other components are nan.
|
||||||
|
|
||||||
|
\param x_index
|
||||||
|
is the variable index, on the tape, for the arguments to this function.
|
||||||
|
This size of x_index is n, the number of arguments to this function.
|
||||||
|
|
||||||
|
\param y_index
|
||||||
|
is the variable index, on the tape, for the results for this function.
|
||||||
|
This size of y_index is m, the number of results for this function.
|
||||||
|
|
||||||
|
\param var_sparsity
|
||||||
|
On input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
is the sparsity for the j-th argument to this atomic function.
|
||||||
|
On output, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],
|
||||||
|
is the sparsity for the i-th result for this atomic function.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool atomic_base<Base>::for_sparse_jac(
|
||||||
|
const vector<Base>& x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
InternalSparsity& var_sparsity )
|
||||||
|
{
|
||||||
|
// intial results are empty during forward mode
|
||||||
|
size_t q = var_sparsity.end();
|
||||||
|
bool input_empty = true;
|
||||||
|
bool zero_empty = true;
|
||||||
|
bool transpose = false;
|
||||||
|
size_t m = y_index.size();
|
||||||
|
bool ok = false;
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_work(thread);
|
||||||
|
//
|
||||||
|
std::string msg = ": atomic_base.for_sparse_jac: returned false";
|
||||||
|
if( sparsity_ == pack_sparsity_enum )
|
||||||
|
{ vectorBool& pack_r ( work_[thread]->pack_r );
|
||||||
|
vectorBool& pack_s ( work_[thread]->pack_s );
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, x_index, var_sparsity, pack_r
|
||||||
|
);
|
||||||
|
//
|
||||||
|
pack_s.resize(m * q );
|
||||||
|
ok = for_sparse_jac(q, pack_r, pack_s, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = for_sparse_jac(q, pack_r, pack_s);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = pack_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, y_index, var_sparsity, pack_s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if( sparsity_ == bool_sparsity_enum )
|
||||||
|
{ vector<bool>& bool_r ( work_[thread]->bool_r );
|
||||||
|
vector<bool>& bool_s ( work_[thread]->bool_s );
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, x_index, var_sparsity, bool_r
|
||||||
|
);
|
||||||
|
bool_s.resize(m * q );
|
||||||
|
ok = for_sparse_jac(q, bool_r, bool_s, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = for_sparse_jac(q, bool_r, bool_s);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = bool_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, y_index, var_sparsity, bool_s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );
|
||||||
|
vector< std::set<size_t> >& set_r ( work_[thread]->set_r );
|
||||||
|
vector< std::set<size_t> >& set_s ( work_[thread]->set_s );
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, x_index, var_sparsity, set_r
|
||||||
|
);
|
||||||
|
//
|
||||||
|
set_s.resize(m);
|
||||||
|
ok = for_sparse_jac(q, set_r, set_s, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = for_sparse_jac(q, set_r, set_s);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = set_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, y_index, var_sparsity, set_s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
402
build-config/cppad/include/cppad/core/atomic/two_forward.hpp
Normal file
402
build-config/cppad/include/cppad/core/atomic/two_forward.hpp
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_FORWARD_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_FORWARD_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_forward$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul.hpp
|
||||||
|
hes
|
||||||
|
afun
|
||||||
|
vx
|
||||||
|
vy
|
||||||
|
ty
|
||||||
|
Taylor
|
||||||
|
const
|
||||||
|
CppAD
|
||||||
|
bool
|
||||||
|
atx
|
||||||
|
aty
|
||||||
|
af
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Forward Mode$$
|
||||||
|
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
|
||||||
|
$subhead Base$$
|
||||||
|
$icode%ok% = %afun%.forward(%p%, %q%, %vx%, %vy%, %tx%, %ty%)
|
||||||
|
%$$
|
||||||
|
This syntax is used by $icode%f%.Forward%$$ where $icode f$$ has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun<%Base%> %f%
|
||||||
|
%$$
|
||||||
|
and $icode afun$$ is used in $icode f$$.
|
||||||
|
|
||||||
|
$subhead AD<Base>$$
|
||||||
|
$icode%ok% = %afun%.forward(%p%, %q%, %vx%, %vy%, %atx%, %aty%)
|
||||||
|
%$$
|
||||||
|
This syntax is used by $icode%af%.Forward%$$ where $icode af$$ has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun< AD<%Base%> , %Base% > %af%
|
||||||
|
%$$
|
||||||
|
and $icode afun$$ is used in $icode af$$ (see $cref base2ad$$).
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
This virtual function is used by $cref atomic_two_afun$$
|
||||||
|
to evaluate function values.
|
||||||
|
It is also used buy
|
||||||
|
$cref/f.Forward/Forward/$$ (and $icode%af%.Forward%$$)
|
||||||
|
to compute function vales and derivatives.
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
This virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
It can just return $icode%ok% == false%$$
|
||||||
|
(and not compute anything) for values
|
||||||
|
of $icode%q% > 0%$$ that are greater than those used by your
|
||||||
|
$cref/forward/Forward/$$ mode calculations.
|
||||||
|
|
||||||
|
$head p$$
|
||||||
|
The argument $icode p$$ has prototype
|
||||||
|
$codei%
|
||||||
|
size_t %p%
|
||||||
|
%$$
|
||||||
|
It specifies the lowest order Taylor coefficient that we are evaluating.
|
||||||
|
During calls to $cref atomic_two_afun$$, $icode%p% == 0%$$.
|
||||||
|
|
||||||
|
$head q$$
|
||||||
|
The argument $icode q$$ has prototype
|
||||||
|
$codei%
|
||||||
|
size_t %q%
|
||||||
|
%$$
|
||||||
|
It specifies the highest order Taylor coefficient that we are evaluating.
|
||||||
|
During calls to $cref atomic_two_afun$$, $icode%q% == 0%$$.
|
||||||
|
|
||||||
|
$head vx$$
|
||||||
|
The $code forward$$ argument $icode vx$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<bool>& %vx%
|
||||||
|
%$$
|
||||||
|
The case $icode%vx%.size() > 0%$$ only occurs while evaluating a call to
|
||||||
|
$cref atomic_two_afun$$.
|
||||||
|
In this case,
|
||||||
|
$icode%p% == %q% == 0%$$,
|
||||||
|
$icode%vx%.size() == %n%$$, and
|
||||||
|
for $latex j = 0 , \ldots , n-1$$,
|
||||||
|
$icode%vx%[%j%]%$$ is true if and only if
|
||||||
|
$icode%ax%[%j%]%$$ is a $cref/variable/glossary/Variable/$$
|
||||||
|
or $cref/dynamic parameter/glossary/Parameter/Dynamic/$$
|
||||||
|
in the corresponding call to
|
||||||
|
$codei%
|
||||||
|
%afun%(%ax%, %ay%)
|
||||||
|
%$$
|
||||||
|
If $icode%vx%.size() == 0%$$,
|
||||||
|
then $icode%vy%.size() == 0%$$ and neither of these vectors
|
||||||
|
should be used.
|
||||||
|
|
||||||
|
$head vy$$
|
||||||
|
The $code forward$$ argument $icode vy$$ has prototype
|
||||||
|
$codei%
|
||||||
|
CppAD::vector<bool>& %vy%
|
||||||
|
%$$
|
||||||
|
If $icode%vy%.size() == 0%$$, it should not be used.
|
||||||
|
Otherwise,
|
||||||
|
$icode%q% == 0%$$ and $icode%vy%.size() == %m%$$.
|
||||||
|
The input values of the elements of $icode vy$$
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, for $latex j = 0 , \ldots , m-1$$,
|
||||||
|
$icode%vy%[%i%]%$$ is true if and only if
|
||||||
|
$icode%ay%[%i%]%$$ is a variable
|
||||||
|
or dynamic parameter
|
||||||
|
(CppAD uses $icode vy$$ to reduce the necessary computations).
|
||||||
|
|
||||||
|
$head tx$$
|
||||||
|
The argument $icode tx$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%>& %tx%
|
||||||
|
%$$
|
||||||
|
and $icode%tx%.size() == (%q%+1)*%n%$$.
|
||||||
|
It is used by $icode%f%.Forward%$$ where $icode f$$ has type
|
||||||
|
$codei%ADFun<%Base%> %f%$$ and $icode afun$$ is used in $icode f$$.
|
||||||
|
For $latex j = 0 , \ldots , n-1$$ and $latex k = 0 , \ldots , q$$,
|
||||||
|
we use the Taylor coefficient notation
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
x_j^k & = & tx [ j * ( q + 1 ) + k ]
|
||||||
|
\\
|
||||||
|
X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
Note that superscripts represent an index for $latex x_j^k$$
|
||||||
|
and an exponent for $latex t^k$$.
|
||||||
|
Also note that the Taylor coefficients for $latex X(t)$$ correspond
|
||||||
|
to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way:
|
||||||
|
$latex \[
|
||||||
|
x_j^k = \frac{1}{ k ! } X_j^{(k)} (0)
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head atx$$
|
||||||
|
The argument $icode atx$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector< AD<%Base%> >& %atx%
|
||||||
|
%$$
|
||||||
|
Otherwise, $icode atx$$ specifications are the same as for $icode tx$$.
|
||||||
|
|
||||||
|
$head ty$$
|
||||||
|
The argument $icode ty$$ has prototype
|
||||||
|
$codei%
|
||||||
|
CppAD::vector<%Base%>& %ty%
|
||||||
|
%$$
|
||||||
|
and $icode%tx%.size() == (%q%+1)*%m%$$.
|
||||||
|
It is set by $icode%f%.Forward%$$ where $icode f$$ has type
|
||||||
|
$codei%ADFun<%Base%> %f%$$ and $icode afun$$ is used in $icode f$$.
|
||||||
|
Upon return,
|
||||||
|
For $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , q$$,
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
Y_i (t) & = & f_i [ X(t) ]
|
||||||
|
\\
|
||||||
|
Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q )
|
||||||
|
\\
|
||||||
|
ty [ i * ( q + 1 ) + k ] & = & y_i^k
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
where $latex o( t^q ) / t^q \rightarrow 0$$ as $latex t \rightarrow 0$$.
|
||||||
|
Note that superscripts represent an index for $latex y_j^k$$
|
||||||
|
and an exponent for $latex t^k$$.
|
||||||
|
Also note that the Taylor coefficients for $latex Y(t)$$ correspond
|
||||||
|
to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way:
|
||||||
|
$latex \[
|
||||||
|
y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0)
|
||||||
|
\] $$
|
||||||
|
If $latex p > 0$$,
|
||||||
|
for $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , p-1$$,
|
||||||
|
the input of $icode ty$$ satisfies
|
||||||
|
$latex \[
|
||||||
|
ty [ i * ( q + 1 ) + k ] = y_i^k
|
||||||
|
\]$$
|
||||||
|
and hence the corresponding elements need not be recalculated.
|
||||||
|
|
||||||
|
$head aty$$
|
||||||
|
The argument $icode aty$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector< AD<%Base%> >& %aty%
|
||||||
|
%$$
|
||||||
|
Otherwise, $icode aty$$ specifications are the same as for $icode ty$$.
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
If the required results are calculated, $icode ok$$ should be true.
|
||||||
|
Otherwise, it should be false.
|
||||||
|
|
||||||
|
$head Discussion$$
|
||||||
|
For example, suppose that $icode%q% == 2%$$,
|
||||||
|
and you know how to compute the function $latex f(x)$$,
|
||||||
|
its first derivative $latex f^{(1)} (x)$$,
|
||||||
|
and it component wise Hessian $latex f_i^{(2)} (x)$$.
|
||||||
|
Then you can compute $icode ty$$ using the following formulas:
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
y_i^0 & = & Y(0)
|
||||||
|
= f_i ( x^0 )
|
||||||
|
\\
|
||||||
|
y_i^1 & = & Y^{(1)} ( 0 )
|
||||||
|
= f_i^{(1)} ( x^0 ) X^{(1)} ( 0 )
|
||||||
|
= f_i^{(1)} ( x^0 ) x^1
|
||||||
|
\\
|
||||||
|
y_i^2
|
||||||
|
& = & \frac{1}{2 !} Y^{(2)} (0)
|
||||||
|
\\
|
||||||
|
& = & \frac{1}{2} X^{(1)} (0)^\R{T} f_i^{(2)} ( x^0 ) X^{(1)} ( 0 )
|
||||||
|
+ \frac{1}{2} f_i^{(1)} ( x^0 ) X^{(2)} ( 0 )
|
||||||
|
\\
|
||||||
|
& = & \frac{1}{2} (x^1)^\R{T} f_i^{(2)} ( x^0 ) x^1
|
||||||
|
+ f_i^{(1)} ( x^0 ) x^2
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
For $latex i = 0 , \ldots , m-1$$, and $latex k = 0 , 1 , 2$$,
|
||||||
|
$latex \[
|
||||||
|
ty [ i * (q + 1) + k ] = y_i^k
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_forward.hpp
|
||||||
|
Atomic forward mode
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from atomic_base to forward mode (for replacement by derived class)
|
||||||
|
|
||||||
|
\param p [in]
|
||||||
|
lowerest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param q [in]
|
||||||
|
highest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param vx [in]
|
||||||
|
if size not zero, which components of x are variables
|
||||||
|
|
||||||
|
\param vy [out]
|
||||||
|
if size not zero, which components of y are variables
|
||||||
|
|
||||||
|
\param tx [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param ty [out]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
See the forward mode in user's documentation for atomic_two
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::forward(
|
||||||
|
size_t p ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
vector<bool>& vy ,
|
||||||
|
const vector<Base>& tx ,
|
||||||
|
vector<Base>& ty )
|
||||||
|
{ return false; }
|
||||||
|
/*!
|
||||||
|
Link from atomic_base to forward mode (for replacement by derived class)
|
||||||
|
|
||||||
|
\param p [in]
|
||||||
|
lowerest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param q [in]
|
||||||
|
highest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param vx [in]
|
||||||
|
if size not zero, which components of x are variables
|
||||||
|
|
||||||
|
\param vy [out]
|
||||||
|
if size not zero, which components of y are variables
|
||||||
|
|
||||||
|
\param atx [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param aty [out]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
See the forward mode in user's documentation for atomic_two
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::forward(
|
||||||
|
size_t p ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
vector<bool>& vy ,
|
||||||
|
const vector< AD<Base> >& atx ,
|
||||||
|
vector< AD<Base> >& aty )
|
||||||
|
{ return false; }
|
||||||
|
/*!
|
||||||
|
Convert atomic_three interface to atomic_two interface
|
||||||
|
|
||||||
|
\param order_low [in]
|
||||||
|
lowerest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
if size not zero, which components of x are variables
|
||||||
|
|
||||||
|
\param type_y [out]
|
||||||
|
if size not zero, which components of y are variables
|
||||||
|
|
||||||
|
\param taylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param taylor_y [out]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
See the forward mode in user's documentation for atomic_three
|
||||||
|
*/
|
||||||
|
# define CPPAD_ATOMIC_BASE_MUSTDO 0
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::forward(
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<ad_type_enum>& type_y ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
vector<Base>& taylor_y )
|
||||||
|
{ //
|
||||||
|
// atomic_base::afun(ax, ay) calls bool version directly
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type_x.size() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type_y.size() == 0 );
|
||||||
|
//
|
||||||
|
# if CPPAD_ATOMIC_BASE_MUSTDO
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_work(thread);
|
||||||
|
vector <bool>& vx = work_[thread]->vx;
|
||||||
|
vector <bool>& vy = work_[thread]->vy;
|
||||||
|
vx.resize(type_x.size());
|
||||||
|
vy.resize(type_y.size());
|
||||||
|
# else
|
||||||
|
vector<bool> vx, vy;
|
||||||
|
# endif
|
||||||
|
//
|
||||||
|
bool ok = forward(order_low, order_up, vx, vy, taylor_x, taylor_y);
|
||||||
|
//
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
# undef CPPAD_ATOMIC_BASE_MUSTDO
|
||||||
|
/*!
|
||||||
|
Convert atomic_three interface to atomic_two interface
|
||||||
|
|
||||||
|
\param order_low [in]
|
||||||
|
lowerest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
if size not zero, which components of x are variables
|
||||||
|
|
||||||
|
\param type_y [out]
|
||||||
|
if size not zero, which components of y are variables
|
||||||
|
|
||||||
|
\param ataylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param ataylor_y [out]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
See the forward mode in user's documentation for atomic_three
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::forward(
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<ad_type_enum>& type_y ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
vector< AD<Base> >& ataylor_y )
|
||||||
|
{ //
|
||||||
|
// atomic_base::afun(ax, ay) calls bool version directly
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type_x.size() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( type_y.size() == 0 );
|
||||||
|
//
|
||||||
|
vector<bool> vx, vy;
|
||||||
|
bool ok = forward(order_low, order_up, vx, vy, ataylor_x, ataylor_y);
|
||||||
|
//
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
113
build-config/cppad/include/cppad/core/atomic/two_option.hpp
Normal file
113
build-config/cppad/include/cppad/core/atomic/two_option.hpp
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_OPTION_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_OPTION_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_option$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
enum
|
||||||
|
afun
|
||||||
|
bool
|
||||||
|
CppAD
|
||||||
|
std
|
||||||
|
typedef
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Set Atomic Function Options$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%afun%.option(%option_value%)%$$
|
||||||
|
|
||||||
|
$head Scope$$
|
||||||
|
These settings do not apply to individual $icode afun$$ calls,
|
||||||
|
but rather all subsequent uses of the corresponding atomic operation
|
||||||
|
in an $cref ADFun$$ object.
|
||||||
|
|
||||||
|
$head atomic_sparsity$$
|
||||||
|
Note that, if you use $cref optimize$$, these sparsity patterns are used
|
||||||
|
to determine the $cref/dependency/dependency.cpp/$$ relationship between
|
||||||
|
argument and result variables.
|
||||||
|
|
||||||
|
$subhead pack_sparsity_enum$$
|
||||||
|
If $icode option_value$$ is $codei%atomic_base<%Base%>::pack_sparsity_enum%$$,
|
||||||
|
then the type used by $icode afun$$ for
|
||||||
|
$cref/sparsity patterns/glossary/Sparsity Pattern/$$,
|
||||||
|
(after the option is set) will be
|
||||||
|
$codei%
|
||||||
|
typedef CppAD::vectorBool %atomic_sparsity%
|
||||||
|
%$$
|
||||||
|
If $icode r$$ is a sparsity pattern
|
||||||
|
for a matrix $latex R \in \B{R}^{p \times q}$$:
|
||||||
|
$icode%r%.size() == %p% * %q%$$.
|
||||||
|
|
||||||
|
$subhead bool_sparsity_enum$$
|
||||||
|
If $icode option_value$$ is $codei%atomic_base<%Base%>::bool_sparsity_enum%$$,
|
||||||
|
then the type used by $icode afun$$ for
|
||||||
|
$cref/sparsity patterns/glossary/Sparsity Pattern/$$,
|
||||||
|
(after the option is set) will be
|
||||||
|
$codei%
|
||||||
|
typedef CppAD::vector<bool> %atomic_sparsity%
|
||||||
|
%$$
|
||||||
|
If $icode r$$ is a sparsity pattern
|
||||||
|
for a matrix $latex R \in \B{R}^{p \times q}$$:
|
||||||
|
$icode%r%.size() == %p% * %q%$$.
|
||||||
|
|
||||||
|
$subhead set_sparsity_enum$$
|
||||||
|
If $icode option_value$$ is $icode%atomic_base<%Base%>::set_sparsity_enum%$$,
|
||||||
|
then the type used by $icode afun$$ for
|
||||||
|
$cref/sparsity patterns/glossary/Sparsity Pattern/$$,
|
||||||
|
(after the option is set) will be
|
||||||
|
$codei%
|
||||||
|
typedef CppAD::vector< std::set<size_t> > %atomic_sparsity%
|
||||||
|
%$$
|
||||||
|
If $icode r$$ is a sparsity pattern
|
||||||
|
for a matrix $latex R \in \B{R}^{p \times q}$$:
|
||||||
|
$icode%r%.size() == %p%$$, and for $latex i = 0 , \ldots , p-1$$,
|
||||||
|
the elements of $icode%r%[%i%]%$$ are between zero and $latex q-1$$ inclusive.
|
||||||
|
|
||||||
|
$end
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_option.hpp
|
||||||
|
Setting atomic_base options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Setting atomic_base options.
|
||||||
|
|
||||||
|
\param option_value
|
||||||
|
new option value.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
void atomic_base<Base>::option(enum option_enum option_value)
|
||||||
|
{ switch( option_value )
|
||||||
|
{ case pack_sparsity_enum:
|
||||||
|
case bool_sparsity_enum:
|
||||||
|
case set_sparsity_enum:
|
||||||
|
sparsity_ = option_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
false,
|
||||||
|
"atoic_base::option: option_value is not valid"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_REV_DEPEND_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_REV_DEPEND_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_rev_depend.hpp
|
||||||
|
Third generation atomic type computation.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from atomic_two to reverse dependency calculation
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
is the value of the parameters in the corresponding function call
|
||||||
|
afun(ax, ay).
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
is the type for each component of ax in the corresponding function call
|
||||||
|
afun(ax, ay).
|
||||||
|
|
||||||
|
\param depend_x [out]
|
||||||
|
specifies which components of x affect values of interest.
|
||||||
|
|
||||||
|
\param depend_y [in]
|
||||||
|
specifies which components of y affect values of interest.
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_depend(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<bool>& depend_x ,
|
||||||
|
const vector<bool>& depend_y )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ bool ok = true;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( depend_x.size() == parameter_x.size() );
|
||||||
|
size_t n = depend_x.size();
|
||||||
|
size_t m = depend_y.size();
|
||||||
|
//
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_work(thread);
|
||||||
|
//
|
||||||
|
if( sparsity_ == pack_sparsity_enum )
|
||||||
|
{ vectorBool& rt ( work_[thread]->pack_r );
|
||||||
|
vectorBool& st ( work_[thread]->pack_s );
|
||||||
|
//
|
||||||
|
st.resize(n * 1 );
|
||||||
|
rt.resize(m * 1 );
|
||||||
|
for(size_t i = 0; i < m; ++i)
|
||||||
|
rt[i] = depend_y[i];
|
||||||
|
ok = rev_sparse_jac(1, rt, st, parameter_x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_jac(1, rt, st);
|
||||||
|
if( ! ok )
|
||||||
|
return false;
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
depend_x[j] = st[j];
|
||||||
|
}
|
||||||
|
else if( sparsity_ == bool_sparsity_enum )
|
||||||
|
{
|
||||||
|
ok = rev_sparse_jac(1, depend_y, depend_x, parameter_x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_jac(m, depend_y, depend_x);
|
||||||
|
if( ! ok )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );
|
||||||
|
vector< std::set<size_t> >& rt ( work_[thread]->set_r );
|
||||||
|
vector< std::set<size_t> >& st ( work_[thread]->set_s );
|
||||||
|
rt.resize(m);
|
||||||
|
st.resize(n);
|
||||||
|
for(size_t i = 0; i < m; ++i)
|
||||||
|
{ if( depend_y[i] )
|
||||||
|
rt[i].insert(0);
|
||||||
|
}
|
||||||
|
ok = rev_sparse_jac(m, rt, st, parameter_x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_jac(m, rt, st);
|
||||||
|
if( ! ok )
|
||||||
|
return false;
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
depend_x[j] = ! st[j].empty();
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,451 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_REV_SPARSE_HES_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_REV_SPARSE_HES_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_rev_sparse_hes$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul.hpp
|
||||||
|
vx
|
||||||
|
afun
|
||||||
|
Jacobian
|
||||||
|
jac
|
||||||
|
CppAD
|
||||||
|
std
|
||||||
|
bool
|
||||||
|
hes
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Reverse Hessian Sparsity Patterns$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ok% = %afun%.rev_sparse_hes(%vx%, %s%, %t%, %q%, %r%, %u%, %v%, %x%)%$$
|
||||||
|
|
||||||
|
$head Deprecated 2016-06-27$$
|
||||||
|
$icode%ok% = %afun%.rev_sparse_hes(%vx%, %s%, %t%, %q%, %r%, %u%, %v%)%$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
This function is used by $cref RevSparseHes$$ to compute
|
||||||
|
Hessian sparsity patterns.
|
||||||
|
If you are using $cref RevSparseHes$$ to compute
|
||||||
|
one of the versions of this
|
||||||
|
virtual function muse be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
$pre
|
||||||
|
|
||||||
|
$$
|
||||||
|
There is an unspecified scalar valued function
|
||||||
|
$latex g : \B{R}^m \rightarrow \B{R}$$.
|
||||||
|
Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for
|
||||||
|
$latex R \in \B{R}^{n \times q}$$,
|
||||||
|
and information about the function $latex z = g(y)$$,
|
||||||
|
this routine computes the sparsity pattern for
|
||||||
|
$latex \[
|
||||||
|
V(x) = (g \circ f)^{(2)}( x ) R
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
If you are using and $cref RevSparseHes$$,
|
||||||
|
this virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
|
||||||
|
$subhead vx$$
|
||||||
|
The argument $icode vx$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD:vector<bool>& %vx%
|
||||||
|
%$$
|
||||||
|
$icode%vx%.size() == %n%$$, and
|
||||||
|
for $latex j = 0 , \ldots , n-1$$,
|
||||||
|
$icode%vx%[%j%]%$$ is true if and only if
|
||||||
|
$icode%ax%[%j%]%$$ is a $cref/variable/glossary/Variable/$$
|
||||||
|
or $cref/dynamic parameter/glossary/Parameter/Dynamic/$$
|
||||||
|
in the corresponding call to
|
||||||
|
$codei%
|
||||||
|
%afun%(%ax%, %ay%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$subhead s$$
|
||||||
|
The argument $icode s$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD:vector<bool>& %s%
|
||||||
|
%$$
|
||||||
|
and its size is $icode m$$.
|
||||||
|
It is a sparsity pattern for
|
||||||
|
$latex S(x) = g^{(1)} [ f(x) ] \in \B{R}^{1 \times m}$$.
|
||||||
|
|
||||||
|
$subhead t$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
CppAD:vector<bool>& %t%
|
||||||
|
%$$
|
||||||
|
and its size is $icode m$$.
|
||||||
|
The input values of its elements
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, $icode t$$ is a
|
||||||
|
sparsity pattern for
|
||||||
|
$latex T(x) \in \B{R}^{1 \times n}$$ where
|
||||||
|
$latex \[
|
||||||
|
T(x) = (g \circ f)^{(1)} (x) = S(x) * f^{(1)} (x)
|
||||||
|
\]$$
|
||||||
|
|
||||||
|
$subhead 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}$$,
|
||||||
|
$latex U(x) \in \B{R}^{m \times q}$$, and
|
||||||
|
$latex V(x) \in \B{R}^{n \times q}$$.
|
||||||
|
|
||||||
|
$subhead r$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const %atomic_sparsity%& %r%
|
||||||
|
%$$
|
||||||
|
and is a $cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
$latex R \in \B{R}^{n \times q}$$.
|
||||||
|
|
||||||
|
$head u$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const %atomic_sparsity%& %u%
|
||||||
|
%$$
|
||||||
|
and is a $cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
$latex U(x) \in \B{R}^{m \times q}$$ which is defined by
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
U(x)
|
||||||
|
& = &
|
||||||
|
\{ \partial_u \{ \partial_y g[ y + f^{(1)} (x) R u ] \}_{y=f(x)} \}_{u=0}
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
\partial_u \{ g^{(1)} [ f(x) + f^{(1)} (x) R u ] \}_{u=0}
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
g^{(2)} [ f(x) ] f^{(1)} (x) R
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$subhead v$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
%atomic_sparsity%& %v%
|
||||||
|
%$$
|
||||||
|
The input value of its elements
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, $icode v$$ is a
|
||||||
|
$cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
$latex V(x) \in \B{R}^{n \times q}$$ which is defined by
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
V(x)
|
||||||
|
& = &
|
||||||
|
\partial_u [ \partial_x (g \circ f) ( x + R u ) ]_{u=0}
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
\partial_u [ (g \circ f)^{(1)}( x + R u ) ]_{u=0}
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
(g \circ f)^{(2)}( x ) R
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
f^{(1)} (x)^\R{T} g^{(2)} [ f(x) ] f^{(1)} (x) R
|
||||||
|
+
|
||||||
|
\sum_{i=1}^m g_i^{(1)} [ f(x) ] \; f_i^{(2)} (x) R
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
f^{(1)} (x)^\R{T} U(x)
|
||||||
|
+
|
||||||
|
\sum_{i=1}^m S_i (x) \; f_i^{(2)} (x) R
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$subhead x$$
|
||||||
|
$index deprecated$$
|
||||||
|
The argument has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%>& %x%
|
||||||
|
%$$
|
||||||
|
and size is equal to the $icode n$$.
|
||||||
|
This is the $cref Value$$ value corresponding to the parameters in the
|
||||||
|
vector $cref/ax/atomic_two_afun/ax/$$ (when the atomic function was called).
|
||||||
|
To be specific, if
|
||||||
|
$codei%
|
||||||
|
if( Parameter(%ax%[%i%]) == true )
|
||||||
|
%x%[%i%] = Value( %ax%[%i%] );
|
||||||
|
else
|
||||||
|
%x%[%i%] = CppAD::numeric_limits<%Base%>::quiet_NaN();
|
||||||
|
%$$
|
||||||
|
The version of this function with out the $icode x$$ argument is deprecated;
|
||||||
|
i.e., you should include the argument even if you do not use it.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_rev_sparse_hes.hpp
|
||||||
|
Atomic reverse mode Hessian sparsity patterns.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from reverse Hessian sparsity sweep to atomic_base
|
||||||
|
|
||||||
|
\param vx [in]
|
||||||
|
which componens of x are variables.
|
||||||
|
|
||||||
|
\param s [in]
|
||||||
|
is the reverse Jacobian sparsity pattern w.r.t the result vector y.
|
||||||
|
|
||||||
|
\param t [out]
|
||||||
|
is the reverse Jacobian sparsity pattern w.r.t the argument vector x.
|
||||||
|
|
||||||
|
\param q [in]
|
||||||
|
is the column dimension for the sparsity partterns.
|
||||||
|
|
||||||
|
\param r [in]
|
||||||
|
is the forward Jacobian sparsity pattern w.r.t the argument vector x
|
||||||
|
|
||||||
|
\param u [in]
|
||||||
|
is the Hessian sparsity pattern w.r.t the result vector y.
|
||||||
|
|
||||||
|
\param v [out]
|
||||||
|
is the Hessian sparsity pattern w.r.t the argument vector x.
|
||||||
|
|
||||||
|
\param x [in]
|
||||||
|
is the integer value of the x arguments that are parameters.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
const vector< std::set<size_t> >& u ,
|
||||||
|
vector< std::set<size_t> >& v ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& u ,
|
||||||
|
vector<bool>& v ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
const vectorBool& u ,
|
||||||
|
vectorBool& v ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
// deprecated
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
const vector< std::set<size_t> >& u ,
|
||||||
|
vector< std::set<size_t> >& v )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& u ,
|
||||||
|
vector<bool>& v )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
const vectorBool& u ,
|
||||||
|
vectorBool& v )
|
||||||
|
{ return false; }
|
||||||
|
/*!
|
||||||
|
Link, before case split, from rev_hes_sweep to atomic_base.
|
||||||
|
|
||||||
|
\tparam InternalSparsity
|
||||||
|
Is the used internaly for sparsity calculations; i.e.,
|
||||||
|
sparse_pack or sparse_list.
|
||||||
|
|
||||||
|
\param x
|
||||||
|
is parameter arguments to the function, other components are nan.
|
||||||
|
|
||||||
|
\param x_index
|
||||||
|
is the variable index, on the tape, for the arguments to this function.
|
||||||
|
This size of x_index is n, the number of arguments to this function.
|
||||||
|
|
||||||
|
\param y_index
|
||||||
|
is the variable index, on the tape, for the results for this function.
|
||||||
|
This size of y_index is m, the number of results for this function.
|
||||||
|
|
||||||
|
\param for_jac_sparsity
|
||||||
|
On input, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
is the forward Jacobian sparsity for the j-th argument to this atomic function.
|
||||||
|
|
||||||
|
\param rev_jac_flag
|
||||||
|
This shows which variables affect the function we are
|
||||||
|
computing the Hessian of.
|
||||||
|
On input, for i = 0, ... , m-1, the rev_jac_flag[ y_index[i] ] is true
|
||||||
|
if the Jacobian of function (we are computing sparsity for) is no-zero.
|
||||||
|
Upon return, for j = 0, ... , n-1, rev_jac_flag [ x_index[j] ]
|
||||||
|
as been adjusted to accound removing this atomic function.
|
||||||
|
|
||||||
|
\param rev_hes_sparsity
|
||||||
|
This is the sparsity pattern for the Hessian.
|
||||||
|
On input, for i = 0, ... , m-1, row y_index[i] is the reverse Hessian sparsity
|
||||||
|
with one of the partials with respect to to y_index[i].
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool atomic_base<Base>::rev_sparse_hes(
|
||||||
|
const vector<Base>& x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
const InternalSparsity& for_jac_sparsity ,
|
||||||
|
bool* rev_jac_flag ,
|
||||||
|
InternalSparsity& rev_hes_sparsity )
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( for_jac_sparsity.end() == rev_hes_sparsity.end() );
|
||||||
|
size_t q = rev_hes_sparsity.end();
|
||||||
|
size_t n = x_index.size();
|
||||||
|
size_t m = y_index.size();
|
||||||
|
bool ok = false;
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_work(thread);
|
||||||
|
bool zero_empty = true;
|
||||||
|
bool input_empty = false;
|
||||||
|
bool transpose = false;
|
||||||
|
//
|
||||||
|
// vx
|
||||||
|
vector<bool> vx(n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
vx[j] = x_index[j] != 0;
|
||||||
|
//
|
||||||
|
// note that s and t are vectors so transpose does not matter for bool case
|
||||||
|
vector<bool> bool_s( work_[thread]->bool_s );
|
||||||
|
vector<bool> bool_t( work_[thread]->bool_t );
|
||||||
|
//
|
||||||
|
bool_s.resize(m);
|
||||||
|
bool_t.resize(n);
|
||||||
|
//
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ if( y_index[i] > 0 )
|
||||||
|
bool_s[i] = rev_jac_flag[ y_index[i] ];
|
||||||
|
}
|
||||||
|
//
|
||||||
|
std::string msg = ": atomic_base.rev_sparse_hes: returned false";
|
||||||
|
if( sparsity_ == pack_sparsity_enum )
|
||||||
|
{ vectorBool& pack_r( work_[thread]->pack_r );
|
||||||
|
vectorBool& pack_u( work_[thread]->pack_u );
|
||||||
|
vectorBool& pack_v( work_[thread]->pack_h );
|
||||||
|
//
|
||||||
|
pack_v.resize(n * q);
|
||||||
|
//
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, x_index, for_jac_sparsity, pack_r
|
||||||
|
);
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, y_index, rev_hes_sparsity, pack_u
|
||||||
|
);
|
||||||
|
//
|
||||||
|
ok = rev_sparse_hes(vx, bool_s, bool_t, q, pack_r, pack_u, pack_v, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_hes(vx, bool_s, bool_t, q, pack_r, pack_u, pack_v);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = pack_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, x_index, rev_hes_sparsity, pack_v
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if( sparsity_ == bool_sparsity_enum )
|
||||||
|
{ vector<bool>& bool_r( work_[thread]->bool_r );
|
||||||
|
vector<bool>& bool_u( work_[thread]->bool_u );
|
||||||
|
vector<bool>& bool_v( work_[thread]->bool_h );
|
||||||
|
//
|
||||||
|
bool_v.resize(n * q);
|
||||||
|
//
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, x_index, for_jac_sparsity, bool_r
|
||||||
|
);
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, y_index, rev_hes_sparsity, bool_u
|
||||||
|
);
|
||||||
|
//
|
||||||
|
ok = rev_sparse_hes(vx, bool_s, bool_t, q, bool_r, bool_u, bool_v, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_hes(vx, bool_s, bool_t, q, bool_r, bool_u, bool_v);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = bool_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, x_index, rev_hes_sparsity, bool_v
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );
|
||||||
|
vector< std::set<size_t> >& set_r( work_[thread]->set_r );
|
||||||
|
vector< std::set<size_t> >& set_u( work_[thread]->set_u );
|
||||||
|
vector< std::set<size_t> >& set_v( work_[thread]->set_h );
|
||||||
|
//
|
||||||
|
set_v.resize(n);
|
||||||
|
//
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, x_index, for_jac_sparsity, set_r
|
||||||
|
);
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, y_index, rev_hes_sparsity, set_u
|
||||||
|
);
|
||||||
|
//
|
||||||
|
ok = rev_sparse_hes(vx, bool_s, bool_t, q, set_r, set_u, set_v, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_hes(vx, bool_s, bool_t, q, set_r, set_u, set_v);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = set_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, x_index, rev_hes_sparsity, set_v
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ if( x_index[j] > 0 )
|
||||||
|
rev_jac_flag[ x_index[j] ] |= bool_t[j];
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_REV_SPARSE_JAC_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_REV_SPARSE_JAC_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_rev_sparse_jac$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul.hpp
|
||||||
|
rt
|
||||||
|
afun
|
||||||
|
Jacobian
|
||||||
|
jac
|
||||||
|
CppAD
|
||||||
|
std
|
||||||
|
bool
|
||||||
|
const
|
||||||
|
hes
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Reverse Jacobian Sparsity Patterns$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ok% = %afun%.rev_sparse_jac(%q%, %rt%, %st%, %x%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Deprecated 2016-06-27$$
|
||||||
|
$icode%ok% = %afun%.rev_sparse_jac(%q%, %rt%, %st%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
This function is used by
|
||||||
|
$cref RevSparseJac$$ to compute
|
||||||
|
Jacobian sparsity patterns.
|
||||||
|
If you are using $cref RevSparseJac$$,
|
||||||
|
one of the versions of this
|
||||||
|
virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
$pre
|
||||||
|
|
||||||
|
$$
|
||||||
|
For a fixed matrix $latex R \in \B{R}^{q \times m}$$,
|
||||||
|
the Jacobian of $latex R * f( x )$$ with respect to $latex x \in \B{R}^n$$ is
|
||||||
|
$latex \[
|
||||||
|
S(x) = R * f^{(1)} (x)
|
||||||
|
\] $$
|
||||||
|
Given a $cref/sparsity pattern/glossary/Sparsity Pattern/$$ for $latex R$$,
|
||||||
|
$code rev_sparse_jac$$ computes a sparsity pattern for $latex S(x)$$.
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
If you are using
|
||||||
|
$cref RevSparseJac$$ or $cref ForSparseHes$$,
|
||||||
|
this virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
|
||||||
|
$subhead q$$
|
||||||
|
The argument $icode q$$ has prototype
|
||||||
|
$codei%
|
||||||
|
size_t %q%
|
||||||
|
%$$
|
||||||
|
It specifies the number of rows in
|
||||||
|
$latex R \in \B{R}^{q \times m}$$ and the Jacobian
|
||||||
|
$latex S(x) \in \B{R}^{q \times n}$$.
|
||||||
|
|
||||||
|
$subhead rt$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const %atomic_sparsity%& %rt%
|
||||||
|
%$$
|
||||||
|
and is a
|
||||||
|
$cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
$latex R^\R{T} \in \B{R}^{m \times q}$$.
|
||||||
|
|
||||||
|
$subhead st$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
%atomic_sparsity%& %st%
|
||||||
|
%$$
|
||||||
|
The input value of its elements
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return, $icode s$$ is a
|
||||||
|
$cref/atomic_sparsity/atomic_two_option/atomic_sparsity/$$ pattern for
|
||||||
|
$latex S(x)^\R{T} \in \B{R}^{n \times q}$$.
|
||||||
|
|
||||||
|
$subhead x$$
|
||||||
|
$index deprecated$$
|
||||||
|
The argument has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%>& %x%
|
||||||
|
%$$
|
||||||
|
and size is equal to the $icode n$$.
|
||||||
|
This is the $cref Value$$ corresponding to the parameters in the
|
||||||
|
vector $cref/ax/atomic_two_afun/ax/$$ (when the atomic function was called).
|
||||||
|
To be specific, if
|
||||||
|
$codei%
|
||||||
|
if( Parameter(%ax%[%i%]) == true )
|
||||||
|
%x%[%i%] = Value( %ax%[%i%] );
|
||||||
|
else
|
||||||
|
%x%[%i%] = CppAD::numeric_limits<%Base%>::quiet_NaN();
|
||||||
|
%$$
|
||||||
|
The version of this function with out the $icode x$$ argument is deprecated;
|
||||||
|
i.e., you should include the argument even if you do not use it.
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
The return value $icode ok$$ has prototype
|
||||||
|
$codei%
|
||||||
|
bool %ok%
|
||||||
|
%$$
|
||||||
|
If it is $code true$$, the corresponding evaluation succeeded,
|
||||||
|
otherwise it failed.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_rev_sparse_jac.hpp
|
||||||
|
Atomic reverse mode Jacobian sparsity patterns.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link, after case split, from rev_jac_sweep to atomic_base
|
||||||
|
|
||||||
|
\param q [in]
|
||||||
|
is the row dimension for the Jacobian sparsity partterns
|
||||||
|
|
||||||
|
\param rt [out]
|
||||||
|
is the tansposed Jacobian sparsity pattern w.r.t to range variables y
|
||||||
|
|
||||||
|
\param st [in]
|
||||||
|
is the tansposed Jacobian sparsity pattern for the argument variables x
|
||||||
|
|
||||||
|
\param x
|
||||||
|
is the integer value for x arguments that are parameters.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& rt ,
|
||||||
|
vector< std::set<size_t> >& st ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& rt ,
|
||||||
|
vector<bool>& st ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& rt ,
|
||||||
|
vectorBool& st ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ return false; }
|
||||||
|
// deprecated versions
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& rt ,
|
||||||
|
vector< std::set<size_t> >& st )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& rt ,
|
||||||
|
vector<bool>& st )
|
||||||
|
{ return false; }
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& rt ,
|
||||||
|
vectorBool& st )
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Link, before case split, from rev_jac_sweep to atomic_base.
|
||||||
|
|
||||||
|
\tparam InternalSparsity
|
||||||
|
Is the used internaly for sparsity calculations; i.e.,
|
||||||
|
sparse_pack or sparse_list.
|
||||||
|
|
||||||
|
\param x
|
||||||
|
is parameter arguments to the function, other components are nan.
|
||||||
|
|
||||||
|
\param x_index
|
||||||
|
is the variable index, on the tape, for the arguments to this function.
|
||||||
|
This size of x_index is n, the number of arguments to this function.
|
||||||
|
|
||||||
|
\param y_index
|
||||||
|
is the variable index, on the tape, for the results for this function.
|
||||||
|
This size of y_index is m, the number of results for this function.
|
||||||
|
|
||||||
|
\param var_sparsity
|
||||||
|
On input, for i = 0, ... , m-1, the sparsity pattern with index y_index[i],
|
||||||
|
is the sparsity for the i-th argument to this atomic function.
|
||||||
|
On output, for j = 0, ... , n-1, the sparsity pattern with index x_index[j],
|
||||||
|
the sparsity has been updated to remove y as a function of x.
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
template <class InternalSparsity>
|
||||||
|
bool atomic_base<Base>::rev_sparse_jac(
|
||||||
|
const vector<Base>& x ,
|
||||||
|
const local::pod_vector<size_t>& x_index ,
|
||||||
|
const local::pod_vector<size_t>& y_index ,
|
||||||
|
InternalSparsity& var_sparsity )
|
||||||
|
{
|
||||||
|
// initial results may be non-empty during reverse mode
|
||||||
|
size_t q = var_sparsity.end();
|
||||||
|
bool input_empty = false;
|
||||||
|
bool zero_empty = true;
|
||||||
|
bool transpose = false;
|
||||||
|
size_t n = x_index.size();
|
||||||
|
bool ok = false;
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_work(thread);
|
||||||
|
//
|
||||||
|
std::string msg = ": atomic_base.rev_sparse_jac: returned false";
|
||||||
|
if( sparsity_ == pack_sparsity_enum )
|
||||||
|
{ vectorBool& pack_rt ( work_[thread]->pack_r );
|
||||||
|
vectorBool& pack_st ( work_[thread]->pack_s );
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, y_index, var_sparsity, pack_rt
|
||||||
|
);
|
||||||
|
//
|
||||||
|
pack_st.resize(n * q );
|
||||||
|
ok = rev_sparse_jac(q, pack_rt, pack_st, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_jac(q, pack_rt, pack_st);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = pack_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, x_index, var_sparsity, pack_st
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if( sparsity_ == bool_sparsity_enum )
|
||||||
|
{ vector<bool>& bool_rt ( work_[thread]->bool_r );
|
||||||
|
vector<bool>& bool_st ( work_[thread]->bool_s );
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, y_index, var_sparsity, bool_rt
|
||||||
|
);
|
||||||
|
bool_st.resize(n * q );
|
||||||
|
ok = rev_sparse_jac(q, bool_rt, bool_st, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_jac(q, bool_rt, bool_st);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = bool_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, x_index, var_sparsity, bool_st
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( sparsity_ == set_sparsity_enum );
|
||||||
|
vector< std::set<size_t> >& set_rt ( work_[thread]->set_r );
|
||||||
|
vector< std::set<size_t> >& set_st ( work_[thread]->set_s );
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, y_index, var_sparsity, set_rt
|
||||||
|
);
|
||||||
|
set_st.resize(n);
|
||||||
|
ok = rev_sparse_jac(q, set_rt, set_st, x);
|
||||||
|
if( ! ok )
|
||||||
|
ok = rev_sparse_jac(q, set_rt, set_st);
|
||||||
|
if( ! ok )
|
||||||
|
{ msg = atomic_name() + msg + " sparsity = set_sparsity_enum";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str());
|
||||||
|
}
|
||||||
|
local::sparse::set_internal_pattern(zero_empty, input_empty,
|
||||||
|
transpose, x_index, var_sparsity, set_st
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
291
build-config/cppad/include/cppad/core/atomic/two_reverse.hpp
Normal file
291
build-config/cppad/include/cppad/core/atomic/two_reverse.hpp
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
# ifndef CPPAD_CORE_ATOMIC_TWO_REVERSE_HPP
|
||||||
|
# define CPPAD_CORE_ATOMIC_TWO_REVERSE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin atomic_two_reverse$$
|
||||||
|
$spell
|
||||||
|
sq
|
||||||
|
mul.hpp
|
||||||
|
afun
|
||||||
|
ty
|
||||||
|
px
|
||||||
|
py
|
||||||
|
Taylor
|
||||||
|
const
|
||||||
|
CppAD
|
||||||
|
atx
|
||||||
|
aty
|
||||||
|
apx
|
||||||
|
apy
|
||||||
|
af
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Atomic Reverse Mode$$
|
||||||
|
$spell
|
||||||
|
bool
|
||||||
|
$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
|
||||||
|
$subhead Base$$
|
||||||
|
$icode%ok% = %afun%.reverse(%q%, %tx%, %ty%, %px%, %py%)
|
||||||
|
%$$
|
||||||
|
This syntax is used by $icode%f%.Forward%$$ where $icode f$$ has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun<%Base%> %f%
|
||||||
|
%$$
|
||||||
|
and $icode afun$$ is used in $icode f$$.
|
||||||
|
|
||||||
|
$subhead AD<Base>$$
|
||||||
|
$icode%ok% = %afun%.reverse(%q%, %atx%, %aty%, %apx%, %apy%)
|
||||||
|
%$$
|
||||||
|
This syntax is used by $icode%af%.Forward%$$ where $icode af$$ has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun< AD<%Base%> , %Base% > %af%
|
||||||
|
%$$
|
||||||
|
and $icode afun$$ is used in $icode af$$ (see $cref base2ad$$).
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
This function is used by $cref/reverse/Reverse/$$
|
||||||
|
to compute derivatives.
|
||||||
|
|
||||||
|
$head Implementation$$
|
||||||
|
If you are using
|
||||||
|
$cref/reverse/Reverse/$$ mode,
|
||||||
|
this virtual function must be defined by the
|
||||||
|
$cref/atomic_user/atomic_two_ctor/atomic_user/$$ class.
|
||||||
|
It can just return $icode%ok% == false%$$
|
||||||
|
(and not compute anything) for values
|
||||||
|
of $icode q$$ that are greater than those used by your
|
||||||
|
$cref/reverse/Reverse/$$ mode calculations.
|
||||||
|
|
||||||
|
$head q$$
|
||||||
|
The argument $icode q$$ has prototype
|
||||||
|
$codei%
|
||||||
|
size_t %q%
|
||||||
|
%$$
|
||||||
|
It specifies the highest order Taylor coefficient that
|
||||||
|
computing the derivative of.
|
||||||
|
|
||||||
|
$head tx$$
|
||||||
|
The argument $icode tx$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%>& %tx%
|
||||||
|
%$$
|
||||||
|
and $icode%tx%.size() == (%q%+1)*%n%$$.
|
||||||
|
For $latex j = 0 , \ldots , n-1$$ and $latex k = 0 , \ldots , q$$,
|
||||||
|
we use the Taylor coefficient notation
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
x_j^k & = & tx [ j * ( q + 1 ) + k ]
|
||||||
|
\\
|
||||||
|
X_j (t) & = & x_j^0 + x_j^1 t^1 + \cdots + x_j^q t^q
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
Note that superscripts represent an index for $latex x_j^k$$
|
||||||
|
and an exponent for $latex t^k$$.
|
||||||
|
Also note that the Taylor coefficients for $latex X(t)$$ correspond
|
||||||
|
to the derivatives of $latex X(t)$$ at $latex t = 0$$ in the following way:
|
||||||
|
$latex \[
|
||||||
|
x_j^k = \frac{1}{ k ! } X_j^{(k)} (0)
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head atx$$
|
||||||
|
The argument $icode atx$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector< AD<%Base%> >& %atx%
|
||||||
|
%$$
|
||||||
|
Otherwise, $icode atx$$ specifications are the same as for $icode tx$$.
|
||||||
|
|
||||||
|
$head ty$$
|
||||||
|
The argument $icode ty$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%>& %ty%
|
||||||
|
%$$
|
||||||
|
and $icode%tx%.size() == (%q%+1)*%m%$$.
|
||||||
|
For $latex i = 0 , \ldots , m-1$$ and $latex k = 0 , \ldots , q$$,
|
||||||
|
we use the Taylor coefficient notation
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
Y_i (t) & = & f_i [ X(t) ]
|
||||||
|
\\
|
||||||
|
Y_i (t) & = & y_i^0 + y_i^1 t^1 + \cdots + y_i^q t^q + o ( t^q )
|
||||||
|
\\
|
||||||
|
y_i^k & = & ty [ i * ( q + 1 ) + k ]
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
where $latex o( t^q ) / t^q \rightarrow 0$$ as $latex t \rightarrow 0$$.
|
||||||
|
Note that superscripts represent an index for $latex y_j^k$$
|
||||||
|
and an exponent for $latex t^k$$.
|
||||||
|
Also note that the Taylor coefficients for $latex Y(t)$$ correspond
|
||||||
|
to the derivatives of $latex Y(t)$$ at $latex t = 0$$ in the following way:
|
||||||
|
$latex \[
|
||||||
|
y_j^k = \frac{1}{ k ! } Y_j^{(k)} (0)
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head aty$$
|
||||||
|
The argument $icode aty$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector< AD<%Base%> >& %aty%
|
||||||
|
%$$
|
||||||
|
Otherwise, $icode aty$$ specifications are the same as for $icode ty$$.
|
||||||
|
|
||||||
|
|
||||||
|
$head F$$
|
||||||
|
We use the notation $latex \{ x_j^k \} \in \B{R}^{n \times (q+1)}$$ for
|
||||||
|
$latex \[
|
||||||
|
\{ x_j^k \W{:} j = 0 , \ldots , n-1, k = 0 , \ldots , q \}
|
||||||
|
\]$$
|
||||||
|
We use the notation $latex \{ y_i^k \} \in \B{R}^{m \times (q+1)}$$ for
|
||||||
|
$latex \[
|
||||||
|
\{ y_i^k \W{:} i = 0 , \ldots , m-1, k = 0 , \ldots , q \}
|
||||||
|
\]$$
|
||||||
|
We define the function
|
||||||
|
$latex F : \B{R}^{n \times (q+1)} \rightarrow \B{R}^{m \times (q+1)}$$ by
|
||||||
|
$latex \[
|
||||||
|
y_i^k = F_i^k [ \{ x_j^k \} ]
|
||||||
|
\] $$
|
||||||
|
Note that
|
||||||
|
$latex \[
|
||||||
|
F_i^0 ( \{ x_j^k \} ) = f_i ( X(0) ) = f_i ( x^0 )
|
||||||
|
\] $$
|
||||||
|
We also note that
|
||||||
|
$latex F_i^\ell ( \{ x_j^k \} )$$ is a function of
|
||||||
|
$latex x^0 , \ldots , x^\ell$$
|
||||||
|
and is determined by the derivatives of $latex f_i (x)$$
|
||||||
|
up to order $latex \ell$$.
|
||||||
|
|
||||||
|
|
||||||
|
$head G, H$$
|
||||||
|
We use $latex G : \B{R}^{m \times (q+1)} \rightarrow \B{R}$$
|
||||||
|
to denote an arbitrary scalar valued function of $latex \{ y_i^k \}$$.
|
||||||
|
We use $latex H : \B{R}^{n \times (q+1)} \rightarrow \B{R}$$
|
||||||
|
defined by
|
||||||
|
$latex \[
|
||||||
|
H ( \{ x_j^k \} ) = G[ F( \{ x_j^k \} ) ]
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head py$$
|
||||||
|
The argument $icode py$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector<%Base%>& %py%
|
||||||
|
%$$
|
||||||
|
and $icode%py%.size() == m * (%q%+1)%$$.
|
||||||
|
For $latex i = 0 , \ldots , m-1$$, $latex k = 0 , \ldots , q$$,
|
||||||
|
$latex \[
|
||||||
|
py[ i * (q + 1 ) + k ] = \partial G / \partial y_i^k
|
||||||
|
\] $$
|
||||||
|
|
||||||
|
$head apy$$
|
||||||
|
The argument $icode apy$$ has prototype
|
||||||
|
$codei%
|
||||||
|
const CppAD::vector< AD<%Base%> >& %apy%
|
||||||
|
%$$
|
||||||
|
Otherwise, $icode apy$$ specifications are the same as for $icode py$$.
|
||||||
|
|
||||||
|
$subhead px$$
|
||||||
|
The $icode px$$ has prototype
|
||||||
|
$codei%
|
||||||
|
CppAD::vector<%Base%>& %px%
|
||||||
|
%$$
|
||||||
|
and $icode%px%.size() == n * (%q%+1)%$$.
|
||||||
|
The input values of the elements of $icode px$$
|
||||||
|
are not specified (must not matter).
|
||||||
|
Upon return,
|
||||||
|
for $latex j = 0 , \ldots , n-1$$ and $latex \ell = 0 , \ldots , q$$,
|
||||||
|
$latex \[
|
||||||
|
\begin{array}{rcl}
|
||||||
|
px [ j * (q + 1) + \ell ] & = & \partial H / \partial x_j^\ell
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
( \partial G / \partial \{ y_i^k \} ) \cdot
|
||||||
|
( \partial \{ y_i^k \} / \partial x_j^\ell )
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
\sum_{k=0}^q
|
||||||
|
\sum_{i=0}^{m-1}
|
||||||
|
( \partial G / \partial y_i^k ) ( \partial y_i^k / \partial x_j^\ell )
|
||||||
|
\\
|
||||||
|
& = &
|
||||||
|
\sum_{k=\ell}^q
|
||||||
|
\sum_{i=0}^{m-1}
|
||||||
|
py[ i * (q + 1 ) + k ] ( \partial F_i^k / \partial x_j^\ell )
|
||||||
|
\end{array}
|
||||||
|
\] $$
|
||||||
|
Note that we have used the fact that for $latex k < \ell$$,
|
||||||
|
$latex \partial F_i^k / \partial x_j^\ell = 0$$.
|
||||||
|
|
||||||
|
$head apx$$
|
||||||
|
The argument $icode apx$$ has prototype
|
||||||
|
$codei%
|
||||||
|
CppAD::vector< AD<%Base%> >& %apx%
|
||||||
|
%$$
|
||||||
|
Otherwise, $icode apx$$ specifications are the same as for $icode px$$.
|
||||||
|
|
||||||
|
$head ok$$
|
||||||
|
The return value $icode ok$$ has prototype
|
||||||
|
$codei%
|
||||||
|
bool %ok%
|
||||||
|
%$$
|
||||||
|
If it is $code true$$, the corresponding evaluation succeeded,
|
||||||
|
otherwise it failed.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file atomic/two_reverse.hpp
|
||||||
|
Atomic reverse mode.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from reverse mode sweep to users routine.
|
||||||
|
|
||||||
|
\param q [in]
|
||||||
|
highest order for this reverse mode calculation.
|
||||||
|
|
||||||
|
\param tx [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param ty [in]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
\param px [out]
|
||||||
|
Partials w.r.t. the x Taylor coefficients.
|
||||||
|
|
||||||
|
\param py [in]
|
||||||
|
Partials w.r.t. the y Taylor coefficients.
|
||||||
|
|
||||||
|
See atomic_reverse mode use documentation
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::reverse(
|
||||||
|
size_t q ,
|
||||||
|
const vector<Base>& tx ,
|
||||||
|
const vector<Base>& ty ,
|
||||||
|
vector<Base>& px ,
|
||||||
|
const vector<Base>& py )
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
bool atomic_base<Base>::reverse(
|
||||||
|
size_t q ,
|
||||||
|
const vector< AD<Base> >& atx ,
|
||||||
|
const vector< AD<Base> >& aty ,
|
||||||
|
vector< AD<Base> >& apx ,
|
||||||
|
const vector< AD<Base> >& apy )
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
247
build-config/cppad/include/cppad/core/azmul.hpp
Normal file
247
build-config/cppad/include/cppad/core/azmul.hpp
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
# ifndef CPPAD_CORE_AZMUL_HPP
|
||||||
|
# define CPPAD_CORE_AZMUL_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$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 == nullptr )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if x and y tapes match
|
||||||
|
bool match_x = x.tape_id_ == tape_id;
|
||||||
|
bool match_y = y.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if x and y are dynamic parameters
|
||||||
|
bool dyn_x = match_x & (x.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_y = match_y & (y.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if x and y are variables
|
||||||
|
bool var_x = match_x & (x.ad_type_ != dynamic_enum);
|
||||||
|
bool var_y = match_y & (y.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
x.tape_id_ == y.tape_id_ || ! match_x || ! match_y ,
|
||||||
|
"azmul: AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
else if( ( ! dyn_y ) & IdenticalZero( y.value_ ) )
|
||||||
|
{ // result = variable * 0
|
||||||
|
}
|
||||||
|
else if( ( ! dyn_y ) & 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 = y.taddr_;
|
||||||
|
if( ! dyn_y )
|
||||||
|
p = tape->Rec_.put_con_par(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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( var_y )
|
||||||
|
{ if( ( ! dyn_x ) & IdenticalZero(x.value_) )
|
||||||
|
{ // result = 0 * variable
|
||||||
|
}
|
||||||
|
else if( ( ! dyn_x ) & 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 = x.taddr_;
|
||||||
|
if( ! dyn_x )
|
||||||
|
p = tape->Rec_.put_con_par(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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_x | dyn_y )
|
||||||
|
{ addr_t arg0 = x.taddr_;
|
||||||
|
addr_t arg1 = y.taddr_;
|
||||||
|
if( ! dyn_x )
|
||||||
|
arg0 = tape->Rec_.put_con_par(x.value_);
|
||||||
|
if( ! dyn_y )
|
||||||
|
arg1 = tape->Rec_.put_con_par(y.value_);
|
||||||
|
//
|
||||||
|
// parameters with a dynamic parameter result
|
||||||
|
result.taddr_ = tape->Rec_.put_dyn_par(
|
||||||
|
result.value_, local::zmul_dyn, arg0, arg1
|
||||||
|
);
|
||||||
|
result.tape_id_ = tape_id;
|
||||||
|
result.ad_type_ = dynamic_enum;
|
||||||
|
}
|
||||||
|
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
|
||||||
117
build-config/cppad/include/cppad/core/base2ad.hpp
Normal file
117
build-config/cppad/include/cppad/core/base2ad.hpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# ifndef CPPAD_CORE_BASE2AD_HPP
|
||||||
|
# define CPPAD_CORE_BASE2AD_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin base2ad$$
|
||||||
|
$spell
|
||||||
|
af
|
||||||
|
Taylor
|
||||||
|
$$
|
||||||
|
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Create an AD<Base> Function From a Base Function$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%af% = %f%.base2ad()%$$
|
||||||
|
|
||||||
|
$head See Also$$
|
||||||
|
$cref mul_level$$
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
This is the base type used to recorded the operation sequence in $icode f$$
|
||||||
|
and $icode af$$; i.e., the type $codei%AD<%Base%>%$$ was used to record
|
||||||
|
the operation sequence.
|
||||||
|
|
||||||
|
$head f$$
|
||||||
|
This object has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun<%Base%> %f%
|
||||||
|
%$$
|
||||||
|
It does it's derivative calculations using the type $icode Base$$.
|
||||||
|
|
||||||
|
$head af$$
|
||||||
|
This object has prototype
|
||||||
|
$codei%
|
||||||
|
ADFun< AD<%Base%> , %Base% > %af%
|
||||||
|
%$$
|
||||||
|
It has the same operation sequence as $icode f$$,
|
||||||
|
but it does it's derivative calculations using the type
|
||||||
|
$codei%AD<%Base>%$$.
|
||||||
|
This enables one to record new functions that are defined
|
||||||
|
using derivatives of the function $icode f$$.
|
||||||
|
Initially, there are no Taylor coefficients stored in $icode af$$ and
|
||||||
|
$cref%af.size_order()%size_order%$$ is zero.
|
||||||
|
|
||||||
|
$children%
|
||||||
|
example/general/base2ad.cpp
|
||||||
|
%$$
|
||||||
|
$head Example$$
|
||||||
|
The file $cref base2ad.cpp$$
|
||||||
|
contains an example and test of this operation.
|
||||||
|
|
||||||
|
$end
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file base2ad.hpp
|
||||||
|
*/
|
||||||
|
/// Create an ADFun< AD<Base>, Base > from this ADFun<Base>
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
ADFun< AD<Base>, RecBase > ADFun<Base,RecBase>::base2ad(void) const
|
||||||
|
{ ADFun< AD<Base>, RecBase > fun;
|
||||||
|
//
|
||||||
|
// bool values
|
||||||
|
fun.has_been_optimized_ = has_been_optimized_;
|
||||||
|
fun.check_for_nan_ = check_for_nan_;
|
||||||
|
//
|
||||||
|
// size_t values
|
||||||
|
fun.compare_change_count_ = compare_change_count_;
|
||||||
|
fun.compare_change_number_ = compare_change_number_;
|
||||||
|
fun.compare_change_op_index_ = compare_change_op_index_;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( fun.num_order_taylor_ == 0 ) ;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( fun.cap_order_taylor_ == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( fun.num_direction_taylor_ == 0 );
|
||||||
|
fun.num_var_tape_ = num_var_tape_;
|
||||||
|
//
|
||||||
|
// pod_vector objects
|
||||||
|
fun.ind_taddr_ = ind_taddr_;
|
||||||
|
fun.dep_taddr_ = dep_taddr_;
|
||||||
|
fun.dep_parameter_ = dep_parameter_;
|
||||||
|
fun.cskip_op_ = cskip_op_;
|
||||||
|
fun.load_op2var_ = load_op2var_;
|
||||||
|
//
|
||||||
|
// pod_maybe_vector< AD<Base> > = pod_maybe_vector<Base>
|
||||||
|
CPPAD_ASSERT_UNKNOWN( fun.taylor_.size() == 0 );
|
||||||
|
//
|
||||||
|
// player
|
||||||
|
// (uses move semantics)
|
||||||
|
fun.play_ = play_.base2ad();
|
||||||
|
//
|
||||||
|
// subgraph
|
||||||
|
fun.subgraph_info_ = subgraph_info_;
|
||||||
|
//
|
||||||
|
// sparse_pack
|
||||||
|
fun.for_jac_sparse_pack_ = for_jac_sparse_pack_;
|
||||||
|
//
|
||||||
|
// sparse_list
|
||||||
|
fun.for_jac_sparse_set_ = for_jac_sparse_set_;
|
||||||
|
//
|
||||||
|
return fun;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
384
build-config/cppad/include/cppad/core/base_complex.hpp
Normal file
384
build-config/cppad/include/cppad/core/base_complex.hpp
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
# ifndef CPPAD_CORE_BASE_COMPLEX_HPP
|
||||||
|
# define CPPAD_CORE_BASE_COMPLEX_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
# 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
|
||||||
|
erfc
|
||||||
|
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.
|
||||||
|
|
||||||
|
$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 IdenticalCon(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 IdenticalEqualCon(
|
||||||
|
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)
|
||||||
|
CPPAD_USER_MACRO(asinh)
|
||||||
|
CPPAD_USER_MACRO(acosh)
|
||||||
|
CPPAD_USER_MACRO(atanh)
|
||||||
|
CPPAD_USER_MACRO(erf)
|
||||||
|
CPPAD_USER_MACRO(erfc)
|
||||||
|
CPPAD_USER_MACRO(expm1)
|
||||||
|
CPPAD_USER_MACRO(log1p)
|
||||||
|
}
|
||||||
|
/* %$$
|
||||||
|
|
||||||
|
$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 IdenticalCon(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 IdenticalEqualCon(
|
||||||
|
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
|
||||||
284
build-config/cppad/include/cppad/core/base_cond_exp.hpp
Normal file
284
build-config/cppad/include/cppad/core/base_cond_exp.hpp
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
# ifndef CPPAD_CORE_BASE_COND_EXP_HPP
|
||||||
|
# define CPPAD_CORE_BASE_COND_EXP_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$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$$
|
||||||
|
|
||||||
|
$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 Type is the Base type for this base require operation.
|
||||||
|
The argument Rel is one of Lt, Le, Eq, Ge, Gt.
|
||||||
|
The argument Op is the corresponding 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 Type is the 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 comparison operators.
|
||||||
|
|
||||||
|
\tparam CompareType
|
||||||
|
is the type of the left and right operands to the comparison operator.
|
||||||
|
|
||||||
|
\tparam ResultType
|
||||||
|
is the type of the result, which is the same as CompareType except
|
||||||
|
during forward and reverse mode sparese calculations.
|
||||||
|
|
||||||
|
\param cop
|
||||||
|
specifices which comparison to use; i.e.,
|
||||||
|
$code <$$,
|
||||||
|
$code <=$$,
|
||||||
|
$code ==$$,
|
||||||
|
$code >=$$,
|
||||||
|
$code >$$, or
|
||||||
|
$code !=$$.
|
||||||
|
|
||||||
|
\param left
|
||||||
|
is the left operand to the comparison operator.
|
||||||
|
|
||||||
|
\param right
|
||||||
|
is the right operand to the comparison operator.
|
||||||
|
|
||||||
|
\param exp_if_true
|
||||||
|
is the return value is the comparison results in true.
|
||||||
|
|
||||||
|
\param exp_if_false
|
||||||
|
is the return value is the comparison results in false.
|
||||||
|
|
||||||
|
\return
|
||||||
|
see exp_if_true and 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
build-config/cppad/include/cppad/core/base_double.hpp
Normal file
229
build-config/cppad/include/cppad/core/base_double.hpp
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
# ifndef CPPAD_CORE_BASE_DOUBLE_HPP
|
||||||
|
# define CPPAD_CORE_BASE_DOUBLE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
# include <cppad/configure.hpp>
|
||||||
|
# include <limits>
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin base_double.hpp$$
|
||||||
|
$spell
|
||||||
|
namespaces
|
||||||
|
cppad
|
||||||
|
hpp
|
||||||
|
azmul
|
||||||
|
expm1
|
||||||
|
atanh
|
||||||
|
acosh
|
||||||
|
asinh
|
||||||
|
erf
|
||||||
|
erfc
|
||||||
|
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 IdenticalCon(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 IdenticalEqualCon(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;
|
||||||
|
using std::asinh;
|
||||||
|
using std::acosh;
|
||||||
|
using std::atanh;
|
||||||
|
using std::erf;
|
||||||
|
using std::erfc;
|
||||||
|
using std::expm1;
|
||||||
|
using std::log1p;
|
||||||
|
}
|
||||||
|
/* %$$
|
||||||
|
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
build-config/cppad/include/cppad/core/base_float.hpp
Normal file
230
build-config/cppad/include/cppad/core/base_float.hpp
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
# ifndef CPPAD_CORE_BASE_FLOAT_HPP
|
||||||
|
# define CPPAD_CORE_BASE_FLOAT_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
# include <cppad/configure.hpp>
|
||||||
|
# include <limits>
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin base_float.hpp$$
|
||||||
|
$spell
|
||||||
|
namespaces
|
||||||
|
cppad
|
||||||
|
hpp
|
||||||
|
azmul
|
||||||
|
expm1
|
||||||
|
atanh
|
||||||
|
acosh
|
||||||
|
asinh
|
||||||
|
erf
|
||||||
|
erfc
|
||||||
|
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 IdenticalCon(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 IdenticalEqualCon(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;
|
||||||
|
using std::asinh;
|
||||||
|
using std::acosh;
|
||||||
|
using std::atanh;
|
||||||
|
using std::erf;
|
||||||
|
using std::erfc;
|
||||||
|
using std::expm1;
|
||||||
|
using std::log1p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* %$$
|
||||||
|
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
build-config/cppad/include/cppad/core/base_hash.hpp
Normal file
84
build-config/cppad/include/cppad/core/base_hash.hpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# ifndef CPPAD_CORE_BASE_HASH_HPP
|
||||||
|
# define CPPAD_CORE_BASE_HASH_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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/con_dyn_var/Parameter/$$.
|
||||||
|
|
||||||
|
$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
|
||||||
67
build-config/cppad/include/cppad/core/base_limits.hpp
Normal file
67
build-config/cppad/include/cppad/core/base_limits.hpp
Normal file
@@ -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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$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
|
||||||
171
build-config/cppad/include/cppad/core/base_std_math.hpp
Normal file
171
build-config/cppad/include/cppad/core/base_std_math.hpp
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
# ifndef CPPAD_CORE_BASE_STD_MATH_HPP
|
||||||
|
# define CPPAD_CORE_BASE_STD_MATH_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin base_std_math$$
|
||||||
|
$spell
|
||||||
|
expm1
|
||||||
|
atanh
|
||||||
|
acosh
|
||||||
|
asinh
|
||||||
|
inline
|
||||||
|
fabs
|
||||||
|
isnan
|
||||||
|
alloc
|
||||||
|
std
|
||||||
|
acos
|
||||||
|
asin
|
||||||
|
atan
|
||||||
|
cos
|
||||||
|
exp
|
||||||
|
sqrt
|
||||||
|
const
|
||||||
|
CppAD
|
||||||
|
namespace
|
||||||
|
erf
|
||||||
|
erfc
|
||||||
|
$$
|
||||||
|
|
||||||
|
$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% = acosh(%x%)%$$ $cnext inverse hyperbolic cosine $rnext
|
||||||
|
$icode%y% = asin(%x%)%$$ $cnext inverse sine $rnext
|
||||||
|
$icode%y% = asinh(%x%)%$$ $cnext inverse hyperbolic sin $rnext
|
||||||
|
$icode%y% = atan(%x%)%$$ $cnext inverse tangent $rnext
|
||||||
|
$icode%y% = atanh(%x%)%$$ $cnext inverse hyperbolic tangent $rnext
|
||||||
|
$icode%y% = cos(%x%)%$$ $cnext cosine $rnext
|
||||||
|
$icode%y% = cosh(%x%)%$$ $cnext hyperbolic cosine $rnext
|
||||||
|
$icode%y% = erf(%x%)%$$ $cnext error function $rnext
|
||||||
|
$icode%y% = erfc(%x%)%$$ $cnext complementary error function $rnext
|
||||||
|
$icode%y% = exp(%x%)%$$ $cnext exponential $rnext
|
||||||
|
$icode%y% = expm1(%x%)%$$ $cnext exponential of x minus one $rnext
|
||||||
|
$icode%y% = fabs(%x%)%$$ $cnext absolute value $rnext
|
||||||
|
$icode%y% = log(%x%)%$$ $cnext natural logarithm $rnext
|
||||||
|
$icode%y% = log1p(%x%)%$$ $cnext logarithm of one plus x $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 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 x and return value y have type 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
|
||||||
65
build-config/cppad/include/cppad/core/base_to_string.hpp
Normal file
65
build-config/cppad/include/cppad/core/base_to_string.hpp
Normal file
@@ -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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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
|
||||||
402
build-config/cppad/include/cppad/core/bender_quad.hpp
Normal file
402
build-config/cppad/include/cppad/core/bender_quad.hpp
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
# 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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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$$
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
|
||||||
|
$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
|
||||||
241
build-config/cppad/include/cppad/core/bool_fun.hpp
Normal file
241
build-config/cppad/include/cppad/core/bool_fun.hpp
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
# 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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin BoolFun$$
|
||||||
|
$spell
|
||||||
|
namespace
|
||||||
|
bool
|
||||||
|
CppAD
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Boolean Functions$$
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$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., 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>
|
||||||
|
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., 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>
|
||||||
|
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
|
||||||
49
build-config/cppad/include/cppad/core/bool_valued.hpp
Normal file
49
build-config/cppad/include/cppad/core/bool_valued.hpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# ifndef CPPAD_CORE_BOOL_VALUED_HPP
|
||||||
|
# define CPPAD_CORE_BOOL_VALUED_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin BoolValued$$
|
||||||
|
$spell
|
||||||
|
Bool
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section Bool Valued Operations and Functions with AD Arguments$$
|
||||||
|
|
||||||
|
$children%
|
||||||
|
include/cppad/core/compare.hpp%
|
||||||
|
include/cppad/core/near_equal_ext.hpp%
|
||||||
|
include/cppad/core/bool_fun.hpp%
|
||||||
|
include/cppad/core/con_dyn_var.hpp%
|
||||||
|
include/cppad/core/equal_op_seq.hpp
|
||||||
|
%$$
|
||||||
|
$table
|
||||||
|
$rref Compare$$
|
||||||
|
$rref NearEqualExt$$
|
||||||
|
$rref BoolFun$$
|
||||||
|
$rref con_dyn_var$$
|
||||||
|
$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/con_dyn_var.hpp>
|
||||||
|
# include <cppad/core/equal_op_seq.hpp>
|
||||||
|
|
||||||
|
# endif
|
||||||
256
build-config/cppad/include/cppad/core/capacity_order.hpp
Normal file
256
build-config/cppad/include/cppad/core/capacity_order.hpp
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
# ifndef CPPAD_CORE_CAPACITY_ORDER_HPP
|
||||||
|
# define CPPAD_CORE_CAPACITY_ORDER_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin capacity_order$$
|
||||||
|
$spell
|
||||||
|
var
|
||||||
|
taylor_
|
||||||
|
xq
|
||||||
|
yq
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section Controlling Taylor Coefficients Memory Allocation$$
|
||||||
|
|
||||||
|
$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 $icode%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.
|
||||||
|
|
||||||
|
$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 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_.clear() is called.
|
||||||
|
|
||||||
|
\param r
|
||||||
|
is the number of directions to allocate memory for.
|
||||||
|
If <code>c == 1</code> then 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 r.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
void ADFun<Base,RecBase>::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_.clear();
|
||||||
|
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_maybe<Base> new_taylor(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_.clear() 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 is zero (one), num_direction_taylor_ is set to zero (one).
|
||||||
|
Otherwise, if num_direction_taylor_ is zero, it is set to one.
|
||||||
|
Othwerwise, num_direction_taylor_ is not modified.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
void ADFun<Base,RecBase>::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
|
||||||
244
build-config/cppad/include/cppad/core/check_for_nan.hpp
Normal file
244
build-config/cppad/include/cppad/core/check_for_nan.hpp
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHECK_FOR_NAN_HPP
|
||||||
|
# define CPPAD_CORE_CHECK_FOR_NAN_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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%
|
||||||
|
%$$
|
||||||
|
If $icode b$$ is true (false),
|
||||||
|
future calls to $icode%f%.Forward%$$ will (will not) check for $code nan$$.
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$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
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Set check_for_nan
|
||||||
|
|
||||||
|
\param value
|
||||||
|
new value for this flag.
|
||||||
|
*/
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
void ADFun<Base,RecBase>::check_for_nan(bool value)
|
||||||
|
{ check_for_nan_ = value; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Get check_for_nan
|
||||||
|
|
||||||
|
\return
|
||||||
|
current value of check_for_nan_.
|
||||||
|
*/
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
bool ADFun<Base,RecBase>::check_for_nan(void) const
|
||||||
|
{ return check_for_nan_; }
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Stores a vector in a file when nans occur.
|
||||||
|
|
||||||
|
\param vec [in]
|
||||||
|
is the vector that is stored.
|
||||||
|
|
||||||
|
\param [out] file_name
|
||||||
|
is the file where the vector is stored
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
// 2DO: add vec.data() to C11 tests and use it when C11 true
|
||||||
|
// const char* char_ptr = reinterpret_cast<const char*>( vec.data() );
|
||||||
|
const char* char_ptr = reinterpret_cast<const char*>( &vec[0] );
|
||||||
|
|
||||||
|
# if CPPAD_HAS_MKSTEMP
|
||||||
|
char pattern[] = "/tmp/fileXXXXXX";
|
||||||
|
int fd = mkstemp(pattern);
|
||||||
|
file_name = pattern;
|
||||||
|
ssize_t flag = write(fd, char_ptr, char_size);
|
||||||
|
if( flag < 0 )
|
||||||
|
{ std::cerr << "put_check_nan: write error\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
# else
|
||||||
|
# if CPPAD_HAS_TMPNAM_S
|
||||||
|
std::vector<char> name(L_tmpnam_s);
|
||||||
|
// if( tmpnam_s( name.data(), L_tmpnam_s ) != 0 )
|
||||||
|
if( tmpnam_s( &name[0], L_tmpnam_s ) != 0 )
|
||||||
|
{ CPPAD_ASSERT_KNOWN(
|
||||||
|
false,
|
||||||
|
"Cannot create a temporary file name"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// file_name = name.data();
|
||||||
|
file_name = &name[0];
|
||||||
|
# else
|
||||||
|
file_name = tmpnam( nullptr );
|
||||||
|
# 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Gets a vector that was stored by put_check_for_nan.
|
||||||
|
|
||||||
|
\param vec [out]
|
||||||
|
is the vector that is stored.
|
||||||
|
|
||||||
|
\param file_name [in]
|
||||||
|
is the file where the vector is stored
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
void get_check_for_nan(CppAD::vector<Base>& vec, const std::string& file_name)
|
||||||
|
{ //
|
||||||
|
std::streamsize char_size = std::streamsize( sizeof(Base) * vec.size() );
|
||||||
|
// char* char_ptr = reinterpret_cast<char*>( vec.data() );
|
||||||
|
char* char_ptr = reinterpret_cast<char*>( &vec[0] );
|
||||||
|
//
|
||||||
|
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
|
||||||
@@ -0,0 +1,621 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_CHKPOINT_ONE_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_CHKPOINT_ONE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
# include <cppad/local/sparse/list_setvec.hpp>
|
||||||
|
# include <cppad/local/sparse/pack_setvec.hpp>
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_one.hpp
|
||||||
|
First generation checkpoint functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin chkpoint_one$$
|
||||||
|
$spell
|
||||||
|
mul
|
||||||
|
chkpoint
|
||||||
|
alloc
|
||||||
|
inuse
|
||||||
|
sv
|
||||||
|
var
|
||||||
|
cppad.hpp
|
||||||
|
CppAD
|
||||||
|
checkpoint
|
||||||
|
checkpointing
|
||||||
|
algo
|
||||||
|
atom_fun
|
||||||
|
const
|
||||||
|
enum
|
||||||
|
bool
|
||||||
|
recomputed
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Checkpoint Functions: First Generation$$
|
||||||
|
|
||||||
|
$head Deprecated 2019-01-14$$
|
||||||
|
Using the $code checkpoint$$ class has been deprecated.
|
||||||
|
Use $cref chkpoint_two$$ instead.
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$codei%checkpoint<%Base%> %atom_fun%(
|
||||||
|
%name%, %algo%, %ax%, %ay%, %sparsity%, %optimize%
|
||||||
|
)
|
||||||
|
%sv% = %atom_fun%.size_var()
|
||||||
|
%atom_fun%.option(%option_value%)
|
||||||
|
%algo%(%ax%, %ay%)
|
||||||
|
%atom_fun%(%ax%, %ay%)
|
||||||
|
checkpoint<%Base%>::clear()%$$
|
||||||
|
|
||||||
|
$head See Also$$
|
||||||
|
$cref atomic_two$$, $cref rev_checkpoint.cpp$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
|
||||||
|
$subhead Reduce Memory$$
|
||||||
|
You can reduce the size of the tape and memory required for AD by
|
||||||
|
checkpointing functions of the form $latex y = f(x)$$ where
|
||||||
|
$latex f : \B{R}^n \rightarrow \B{R}^m$$.
|
||||||
|
|
||||||
|
$subhead Faster Recording$$
|
||||||
|
It may also reduce the time to make a recording the same function
|
||||||
|
for different values of the independent variable.
|
||||||
|
Note that the operation sequence for a recording that uses $latex f(x)$$
|
||||||
|
may depend on its independent variables.
|
||||||
|
|
||||||
|
$subhead Repeating Forward$$
|
||||||
|
Normally, CppAD store $cref forward$$ mode results until they freed
|
||||||
|
using $cref capacity_order$$ or the corresponding $cref ADFun$$ object is
|
||||||
|
deleted. This is not true for checkpoint functions because a checkpoint
|
||||||
|
function may be used repeatedly with different arguments in the same tape.
|
||||||
|
Thus, forward mode results are recomputed each time a checkpoint function
|
||||||
|
is used during a forward or reverse mode sweep.
|
||||||
|
|
||||||
|
$subhead Restriction$$
|
||||||
|
The $cref/operation sequence/glossary/Operation/Sequence/$$
|
||||||
|
representing $latex f(x)$$ cannot depend on the value of $latex x$$.
|
||||||
|
The approach in the $cref rev_checkpoint.cpp$$ example case be applied
|
||||||
|
when the operation sequence depends on $latex x$$.
|
||||||
|
|
||||||
|
$subhead Multiple Level AD$$
|
||||||
|
If $icode Base$$ is an AD type, it is possible to record $icode Base$$
|
||||||
|
operations.
|
||||||
|
Note that $icode atom_fun$$ will treat $icode algo$$ as an atomic
|
||||||
|
operation while recording $codei%AD%<%Base%>%$$ operations, but not while
|
||||||
|
recording $icode Base$$ operations.
|
||||||
|
See the $code chkpoint_one_mul_level.cpp$$ example.
|
||||||
|
|
||||||
|
|
||||||
|
$head Method$$
|
||||||
|
The $code checkpoint$$ class is derived from $code atomic_base$$
|
||||||
|
and makes this easy.
|
||||||
|
It implements all the $code atomic_base$$
|
||||||
|
$cref/virtual functions/atomic_two/Virtual Functions/$$
|
||||||
|
and hence its source code $code cppad/core/chkpoint_one/chkpoint_one.hpp$$
|
||||||
|
provides an example implementation of $cref atomic_two$$.
|
||||||
|
The difference is that $code chkpoint_one.hpp$$ uses AD
|
||||||
|
instead of user provided derivatives.
|
||||||
|
|
||||||
|
$head constructor$$
|
||||||
|
The syntax for the checkpoint constructor is
|
||||||
|
$codei%
|
||||||
|
checkpoint<%Base%> %atom_fun%(%name%, %algo%, %ax%, %ay%)
|
||||||
|
%$$
|
||||||
|
$list number$$
|
||||||
|
This constructor cannot be called in $cref/parallel/ta_in_parallel/$$ mode.
|
||||||
|
$lnext
|
||||||
|
You cannot currently be recording
|
||||||
|
$codei%AD<%Base%>%$$ operations when the constructor is called.
|
||||||
|
$lnext
|
||||||
|
This object $icode atom_fun$$ must not be destructed for as long
|
||||||
|
as any $codei%ADFun<%Base%>%$$ object uses its atomic operation.
|
||||||
|
$lnext
|
||||||
|
This class is implemented as a derived class of
|
||||||
|
$cref/atomic/atomic_two_ctor/atomic_base/$$ and hence
|
||||||
|
some of its error message will refer to $code atomic_base$$.
|
||||||
|
$lend
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
The type $icode Base$$ specifies the base type for AD operations.
|
||||||
|
|
||||||
|
$head ADVector$$
|
||||||
|
The type $icode ADVector$$ must be a
|
||||||
|
$cref/simple vector class/SimpleVector/$$ with elements of type
|
||||||
|
$codei%AD<%Base%>%$$.
|
||||||
|
|
||||||
|
$head name$$
|
||||||
|
This $icode checkpoint$$ constructor argument has prototype
|
||||||
|
$codei%
|
||||||
|
const char* %name%
|
||||||
|
%$$
|
||||||
|
It is the name used for error reporting.
|
||||||
|
The suggested value for $icode name$$ is $icode atom_fun$$; i.e.,
|
||||||
|
the same name as used for the object being constructed.
|
||||||
|
|
||||||
|
$head ax$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const %ADVector%& %ax%
|
||||||
|
%$$
|
||||||
|
and size must be equal to $icode n$$.
|
||||||
|
It specifies vector $latex x \in \B{R}^n$$
|
||||||
|
at which an $codei%AD<%Base%>%$$ version of
|
||||||
|
$latex y = f(x)$$ is to be evaluated.
|
||||||
|
|
||||||
|
$head ay$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
%ADVector%& %ay%
|
||||||
|
%$$
|
||||||
|
Its input size must be equal to $icode m$$ and does not change.
|
||||||
|
The input values of its elements do not matter.
|
||||||
|
Upon return, it is an $codei%AD<%Base%>%$$ version of
|
||||||
|
$latex y = f(x)$$.
|
||||||
|
|
||||||
|
$head sparsity$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
atomic_base<%Base%>::option_enum %sparsity%
|
||||||
|
%$$
|
||||||
|
It specifies $cref/sparsity/atomic_two_ctor/atomic_base/sparsity/$$
|
||||||
|
in the $code atomic_base$$ constructor and must be either
|
||||||
|
$codei%atomic_base<%Base%>::pack_sparsity_enum%$$,
|
||||||
|
$codei%atomic_base<%Base%>::bool_sparsity_enum%$$, or
|
||||||
|
$codei%atomic_base<%Base%>::set_sparsity_enum%$$.
|
||||||
|
This argument is optional and its default value is unspecified.
|
||||||
|
|
||||||
|
$head optimize$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
bool %optimize%
|
||||||
|
%$$
|
||||||
|
It specifies if the recording corresponding to the atomic function
|
||||||
|
should be $cref/optimized/optimize/$$.
|
||||||
|
One expects to use a checkpoint function many times, so it should
|
||||||
|
be worth the time to optimize its operation sequence.
|
||||||
|
For debugging purposes, it may be useful to use the
|
||||||
|
original operation sequence (before optimization)
|
||||||
|
because it corresponds more closely to $icode algo$$.
|
||||||
|
This argument is optional and its default value is true.
|
||||||
|
|
||||||
|
|
||||||
|
$head size_var$$
|
||||||
|
This $code size_var$$ member function return value has prototype
|
||||||
|
$codei%
|
||||||
|
size_t %sv%
|
||||||
|
%$$
|
||||||
|
It is the $cref/size_var/seq_property/size_var/$$ for the
|
||||||
|
$codei%ADFun<%Base%>%$$ object is used to store the operation sequence
|
||||||
|
corresponding to $icode algo$$.
|
||||||
|
|
||||||
|
$head option$$
|
||||||
|
The $code option$$ syntax can be used to set the type of sparsity
|
||||||
|
pattern used by $icode atom_fun$$.
|
||||||
|
This is an $codei%atomic_base<%Base%>%$$ function and its documentation
|
||||||
|
can be found at $cref atomic_two_option$$.
|
||||||
|
|
||||||
|
$head algo$$
|
||||||
|
The type of $icode algo$$ is arbitrary, except for the fact that
|
||||||
|
the syntax
|
||||||
|
$codei%
|
||||||
|
%algo%(%ax%, %ay%)
|
||||||
|
%$$
|
||||||
|
must evaluate the function $latex y = f(x)$$ using
|
||||||
|
$codei%AD<%Base%>%$$ operations.
|
||||||
|
In addition, we assume that the
|
||||||
|
$cref/operation sequence/glossary/Operation/Sequence/$$
|
||||||
|
does not depend on the value of $icode ax$$.
|
||||||
|
|
||||||
|
$head atom_fun$$
|
||||||
|
Given $icode ax$$ it computes the corresponding value of $icode ay$$
|
||||||
|
using the operation sequence corresponding to $icode algo$$.
|
||||||
|
If $codei%AD<%Base%>%$$ operations are being recorded,
|
||||||
|
it enters the computation as single operation in the recording
|
||||||
|
see $cref/start recording/Independent/Start Recording/$$.
|
||||||
|
(Currently each use of $icode atom_fun$$ actually corresponds to
|
||||||
|
$icode%m%+%n%+2%$$ operations and creates $icode m$$ new variables,
|
||||||
|
but this is not part of the CppAD specifications and my change.)
|
||||||
|
|
||||||
|
$head Memory$$
|
||||||
|
|
||||||
|
$subhead Restriction$$
|
||||||
|
The $code clear$$ routine cannot be called
|
||||||
|
while in $cref/parallel/ta_in_parallel/$$ execution mode.
|
||||||
|
|
||||||
|
$head Parallel Mode$$
|
||||||
|
The CppAD checkpoint function delays the caching of certain calculations
|
||||||
|
until they are needed.
|
||||||
|
In $cref/parallel model/ta_parallel_setup/$$,
|
||||||
|
this may result in $cref/thread_alloc::inuse(thread)/ta_inuse/$$
|
||||||
|
being non-zero even though the specified thread is no longer active.
|
||||||
|
This memory will be freed when the checkpoint object is deleted.
|
||||||
|
|
||||||
|
$subhead clear$$
|
||||||
|
The $code atomic_base$$ class holds onto static work space
|
||||||
|
that is not connected to a particular object
|
||||||
|
(in order to increase speed by avoiding system memory allocation calls).
|
||||||
|
This call makes to work space $cref/available/ta_available/$$ to
|
||||||
|
for other uses by the same thread.
|
||||||
|
This should be called when you are done using the
|
||||||
|
atomic functions for a specific value of $icode Base$$.
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
class checkpoint : public atomic_base<Base> {
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
/// same as option_enum in base class
|
||||||
|
typedef typename atomic_base<Base>::option_enum option_enum;
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// member_
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// same checkpoint object can be used by multiple threads
|
||||||
|
struct member_struct {
|
||||||
|
//
|
||||||
|
/// AD function corresponding to this checkpoint object
|
||||||
|
ADFun<Base> f_;
|
||||||
|
ADFun< AD<Base>, Base > af_;
|
||||||
|
//
|
||||||
|
/// sparsity for entire Jacobian f(x)^{(1)}
|
||||||
|
/// does not change so can cache it
|
||||||
|
local::sparse::list_setvec jac_sparse_set_;
|
||||||
|
vectorBool jac_sparse_bool_;
|
||||||
|
//
|
||||||
|
/// sparsity for sum_i f_i(x)^{(2)} does not change so can cache it
|
||||||
|
local::sparse::list_setvec hes_sparse_set_;
|
||||||
|
vectorBool hes_sparse_bool_;
|
||||||
|
};
|
||||||
|
/// This version of work is const except during constructor
|
||||||
|
member_struct const_member_;
|
||||||
|
|
||||||
|
/// use pointers and allocate memory to avoid false sharing
|
||||||
|
member_struct* member_[CPPAD_MAX_NUM_THREADS];
|
||||||
|
//
|
||||||
|
/// allocate member_ for this thread
|
||||||
|
void allocate_member(size_t thread)
|
||||||
|
{ if( member_[thread] == nullptr )
|
||||||
|
{ member_[thread] = new member_struct;
|
||||||
|
// The function is recorded in sequential mode and placed in
|
||||||
|
// const_member_.f_, other threads have copy.
|
||||||
|
member_[thread]->f_ = const_member_.f_;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
/// free member_ for this thread
|
||||||
|
void free_member(size_t thread)
|
||||||
|
{ if( member_[thread] != nullptr )
|
||||||
|
{ delete member_[thread];
|
||||||
|
member_[thread] = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
option_enum sparsity(void)
|
||||||
|
{ return static_cast< atomic_base<Base>* >(this)->sparsity(); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/// set jac_sparse_set_
|
||||||
|
void set_jac_sparse_set(void);
|
||||||
|
/// set jac_sparse_bool_
|
||||||
|
void set_jac_sparse_bool(void);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/// set hes_sparse_set_
|
||||||
|
void set_hes_sparse_set(void);
|
||||||
|
/// set hes_sparse_bool_
|
||||||
|
void set_hes_sparse_bool(void);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to forward sparse Jacobian pack and bool
|
||||||
|
|
||||||
|
\copydetails atomic_base::for_sparse_jac
|
||||||
|
*/
|
||||||
|
template <class sparsity_type>
|
||||||
|
bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const sparsity_type& r ,
|
||||||
|
sparsity_type& s ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse sparse Jacobian pack and bool
|
||||||
|
|
||||||
|
\copydetails atomic_base::rev_sparse_jac
|
||||||
|
*/
|
||||||
|
template <class sparsity_type>
|
||||||
|
bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const sparsity_type& rt ,
|
||||||
|
sparsity_type& st ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse sparse Hessian bools
|
||||||
|
|
||||||
|
\copydetails atomic_base::rev_sparse_hes
|
||||||
|
*/
|
||||||
|
template <class sparsity_type>
|
||||||
|
bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const sparsity_type& r ,
|
||||||
|
const sparsity_type& u ,
|
||||||
|
sparsity_type& v ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
public:
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Constructor of a checkpoint object
|
||||||
|
|
||||||
|
\param name [in]
|
||||||
|
is the user's name for the AD version of this atomic operation.
|
||||||
|
|
||||||
|
\param algo [in/out]
|
||||||
|
user routine that compute AD function values
|
||||||
|
(not const because state may change during evaluation).
|
||||||
|
|
||||||
|
\param ax [in]
|
||||||
|
argument value where algo operation sequence is taped.
|
||||||
|
|
||||||
|
\param ay [out]
|
||||||
|
function value at specified argument value.
|
||||||
|
|
||||||
|
\param sparsity [in]
|
||||||
|
what type of sparsity patterns are computed by this function,
|
||||||
|
pack_sparsity_enum bool_sparsity_enum, or set_sparsity_enum.
|
||||||
|
The default value is unspecified.
|
||||||
|
|
||||||
|
\param optimize [in]
|
||||||
|
should the operation sequence corresponding to the algo be optimized.
|
||||||
|
The default value is true, but it is
|
||||||
|
sometimes useful to use false for debugging purposes.
|
||||||
|
*/
|
||||||
|
template <class Algo, class ADVector>
|
||||||
|
checkpoint(
|
||||||
|
const char* name ,
|
||||||
|
Algo& algo ,
|
||||||
|
const ADVector& ax ,
|
||||||
|
ADVector& ay ,
|
||||||
|
option_enum sparsity =
|
||||||
|
atomic_base<Base>::pack_sparsity_enum ,
|
||||||
|
bool optimize = true
|
||||||
|
);
|
||||||
|
/// destructor
|
||||||
|
~checkpoint(void)
|
||||||
|
{
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( thread_alloc::in_parallel() )
|
||||||
|
{ std::string msg = atomic_base<Base>::atomic_name();
|
||||||
|
msg += ": checkpoint destructor called in parallel mode.";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)
|
||||||
|
free_member(thread);
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Implement the user call to atom_fun.size_var().
|
||||||
|
*/
|
||||||
|
size_t size_var(void)
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
return member_[thread]->f_.size_var();
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Implement the user call to atom_fun(ax, ay).
|
||||||
|
|
||||||
|
\tparam ADVector
|
||||||
|
A simple vector class with elements of type AD<Base>.
|
||||||
|
|
||||||
|
\param id
|
||||||
|
optional parameter which must be zero if present.
|
||||||
|
|
||||||
|
\param ax
|
||||||
|
is the argument vector for this call,
|
||||||
|
ax.size() determines the number of arguments.
|
||||||
|
|
||||||
|
\param ay
|
||||||
|
is the result vector for this call,
|
||||||
|
ay.size() determines the number of results.
|
||||||
|
*/
|
||||||
|
template <class ADVector>
|
||||||
|
void operator()(const ADVector& ax, ADVector& ay, size_t id = 0)
|
||||||
|
{ CPPAD_ASSERT_KNOWN(
|
||||||
|
id == 0,
|
||||||
|
"checkpoint: id is non-zero in atom_fun(ax, ay, id)"
|
||||||
|
);
|
||||||
|
this->atomic_base<Base>::operator()(ax, ay, id);
|
||||||
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to forward mode
|
||||||
|
|
||||||
|
\copydetails atomic_base::forward
|
||||||
|
*/
|
||||||
|
virtual bool forward(
|
||||||
|
size_t p ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
vector<bool>& vy ,
|
||||||
|
const vector<Base>& tx ,
|
||||||
|
vector<Base>& ty
|
||||||
|
);
|
||||||
|
virtual bool forward(
|
||||||
|
size_t p ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
vector<bool>& vy ,
|
||||||
|
const vector< AD<Base> >& atx ,
|
||||||
|
vector< AD<Base> >& aty
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse mode
|
||||||
|
|
||||||
|
\copydetails atomic_base::reverse
|
||||||
|
*/
|
||||||
|
virtual bool reverse(
|
||||||
|
size_t q ,
|
||||||
|
const vector<Base>& tx ,
|
||||||
|
const vector<Base>& ty ,
|
||||||
|
vector<Base>& px ,
|
||||||
|
const vector<Base>& py
|
||||||
|
);
|
||||||
|
virtual bool reverse(
|
||||||
|
size_t q ,
|
||||||
|
const vector< AD<Base> >& atx ,
|
||||||
|
const vector< AD<Base> >& aty ,
|
||||||
|
vector< AD<Base> >& apx ,
|
||||||
|
const vector< AD<Base> >& apy
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to forward sparse Jacobian pack
|
||||||
|
|
||||||
|
\copydetails atomic_base::for_sparse_jac
|
||||||
|
*/
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
vectorBool& s ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to forward sparse Jacobian bool
|
||||||
|
|
||||||
|
\copydetails atomic_base::for_sparse_jac
|
||||||
|
*/
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
vector<bool>& s ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to forward sparse Jacobian sets
|
||||||
|
|
||||||
|
\copydetails atomic_base::for_sparse_jac
|
||||||
|
*/
|
||||||
|
virtual bool for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
vector< std::set<size_t> >& s ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse sparse Jacobian pack
|
||||||
|
|
||||||
|
\copydetails atomic_base::rev_sparse_jac
|
||||||
|
*/
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& rt ,
|
||||||
|
vectorBool& st ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse sparse Jacobian bool
|
||||||
|
|
||||||
|
\copydetails atomic_base::rev_sparse_jac
|
||||||
|
*/
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& rt ,
|
||||||
|
vector<bool>& st ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse Jacobian sets
|
||||||
|
|
||||||
|
\copydetails atomic_base::rev_sparse_jac
|
||||||
|
*/
|
||||||
|
virtual bool rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& rt ,
|
||||||
|
vector< std::set<size_t> >& st ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse sparse Hessian pack
|
||||||
|
|
||||||
|
\copydetails atomic_base::rev_sparse_hes
|
||||||
|
*/
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
const vectorBool& u ,
|
||||||
|
vectorBool& v ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse sparse Hessian bool
|
||||||
|
|
||||||
|
\copydetails atomic_base::rev_sparse_hes
|
||||||
|
*/
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& u ,
|
||||||
|
vector<bool>& v ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
/*!
|
||||||
|
Link from user_atomic to reverse sparse Hessian sets
|
||||||
|
|
||||||
|
\copydetails atomic_base::rev_sparse_hes
|
||||||
|
*/
|
||||||
|
virtual bool rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
const vector< std::set<size_t> >& u ,
|
||||||
|
vector< std::set<size_t> >& v ,
|
||||||
|
const vector<Base>& x
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
// functions implemented in cppad/core/checkpoint files
|
||||||
|
# include <cppad/core/chkpoint_one/ctor.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/reverse.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/forward.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/rev_sparse_hes.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/rev_sparse_jac.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/for_sparse_jac.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/set_hes_sparse_bool.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/set_hes_sparse_set.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/set_jac_sparse_bool.hpp>
|
||||||
|
# include <cppad/core/chkpoint_one/set_jac_sparse_set.hpp>
|
||||||
|
|
||||||
|
# endif
|
||||||
62
build-config/cppad/include/cppad/core/chkpoint_one/ctor.hpp
Normal file
62
build-config/cppad/include/cppad/core/chkpoint_one/ctor.hpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_CTOR_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_CTOR_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
template <class Algo, class ADVector>
|
||||||
|
checkpoint<Base>::checkpoint(
|
||||||
|
const char* name ,
|
||||||
|
Algo& algo ,
|
||||||
|
const ADVector& ax ,
|
||||||
|
ADVector& ay ,
|
||||||
|
option_enum sparsity ,
|
||||||
|
bool optimize
|
||||||
|
) : atomic_base<Base>(name, sparsity)
|
||||||
|
{
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( thread_alloc::in_parallel() )
|
||||||
|
{ std::string msg = name;
|
||||||
|
msg += ": checkpoint constructor called in parallel mode.";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)
|
||||||
|
member_[thread] = nullptr;
|
||||||
|
//
|
||||||
|
CheckSimpleVector< CppAD::AD<Base> , ADVector>();
|
||||||
|
//
|
||||||
|
// make a copy of ax because Independent modifies AD information
|
||||||
|
ADVector x_tmp(ax);
|
||||||
|
// delcare x_tmp as the independent variables
|
||||||
|
Independent(x_tmp);
|
||||||
|
// record mapping from x_tmp to ay
|
||||||
|
algo(x_tmp, ay);
|
||||||
|
// create function f_ : x -> y
|
||||||
|
const_member_.f_.Dependent(ay);
|
||||||
|
if( optimize )
|
||||||
|
{ // suppress checking for nan in f_ results
|
||||||
|
// (see optimize documentation for atomic functions)
|
||||||
|
const_member_.f_.check_for_nan(false);
|
||||||
|
//
|
||||||
|
// now optimize
|
||||||
|
const_member_.f_.optimize();
|
||||||
|
}
|
||||||
|
// now disable checking of comparison operations
|
||||||
|
// 2DO: add a debugging mode that checks for changes and aborts
|
||||||
|
const_member_.f_.compare_change_count(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_FOR_SPARSE_JAC_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_FOR_SPARSE_JAC_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
template <class sparsity_type>
|
||||||
|
bool checkpoint<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const sparsity_type& r ,
|
||||||
|
sparsity_type& s ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
// during user sparsity calculations
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
if( member_[thread]->jac_sparse_bool_.size() == 0 )
|
||||||
|
set_jac_sparse_bool();
|
||||||
|
if( member_[thread]->jac_sparse_set_.n_set() != 0 )
|
||||||
|
member_[thread]->jac_sparse_set_.resize(0, 0);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == m * n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( r.size() == n * q );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( s.size() == m * q );
|
||||||
|
//
|
||||||
|
bool ok = true;
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ for(size_t k = 0; k < q; k++)
|
||||||
|
s[i * q + k] = false;
|
||||||
|
}
|
||||||
|
// sparsity for s = jac_sparse_bool_ * r
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ for(size_t k = 0; k < q; k++)
|
||||||
|
{ // initialize sparsity for S(i,k)
|
||||||
|
bool s_ik = false;
|
||||||
|
// S(i,k) = sum_j J(i,j) * R(j,k)
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ bool J_ij = member_[thread]->jac_sparse_bool_[ i * n + j];
|
||||||
|
bool R_jk = r[j * q + k ];
|
||||||
|
s_ik |= ( J_ij & R_jk );
|
||||||
|
}
|
||||||
|
s[i * q + k] = s_ik;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
vectorBool& s ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
return for_sparse_jac< vectorBool >(q, r, s, x);
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
vector<bool>& s ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
return for_sparse_jac< vector<bool> >(q, r, s, x);
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::for_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
vector< std::set<size_t> >& s ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
// during user sparsity calculations
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
if( member_[thread]->jac_sparse_bool_.size() != 0 )
|
||||||
|
member_[thread]->jac_sparse_bool_.clear();
|
||||||
|
if( member_[thread]->jac_sparse_set_.n_set() == 0 )
|
||||||
|
set_jac_sparse_set();
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == m );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.end() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( r.size() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( s.size() == m );
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
s[i].clear();
|
||||||
|
|
||||||
|
// sparsity for s = jac_sparse_set_ * r
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ // compute row i of the return pattern
|
||||||
|
local::sparse::list_setvec::const_iterator set_itr(
|
||||||
|
member_[thread]->jac_sparse_set_, i
|
||||||
|
);
|
||||||
|
size_t j = *set_itr;
|
||||||
|
while(j < n )
|
||||||
|
{ std::set<size_t>::const_iterator itr_j;
|
||||||
|
const std::set<size_t>& r_j( r[j] );
|
||||||
|
for(itr_j = r_j.begin(); itr_j != r_j.end(); itr_j++)
|
||||||
|
{ size_t k = *itr_j;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( k < q );
|
||||||
|
s[i].insert(k);
|
||||||
|
}
|
||||||
|
j = *(++set_itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
170
build-config/cppad/include/cppad/core/chkpoint_one/forward.hpp
Normal file
170
build-config/cppad/include/cppad/core/chkpoint_one/forward.hpp
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_FORWARD_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_FORWARD_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::forward(
|
||||||
|
size_t p ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
vector<bool>& vy ,
|
||||||
|
const vector<Base>& tx ,
|
||||||
|
vector<Base>& ty )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_var() > 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( n == tx.size() / (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( m == ty.size() / (q+1) );
|
||||||
|
bool ok = true;
|
||||||
|
//
|
||||||
|
if( vx.size() == 0 )
|
||||||
|
{ // during user forward mode
|
||||||
|
if( member_[thread]->jac_sparse_set_.n_set() != 0 )
|
||||||
|
member_[thread]->jac_sparse_set_.resize(0,0);
|
||||||
|
if( member_[thread]->jac_sparse_bool_.size() != 0 )
|
||||||
|
member_[thread]->jac_sparse_bool_.clear();
|
||||||
|
//
|
||||||
|
if( member_[thread]->hes_sparse_set_.n_set() != 0 )
|
||||||
|
member_[thread]->hes_sparse_set_.resize(0,0);
|
||||||
|
if( member_[thread]->hes_sparse_bool_.size() != 0 )
|
||||||
|
member_[thread]->hes_sparse_bool_.clear();
|
||||||
|
}
|
||||||
|
if( vx.size() > 0 )
|
||||||
|
{ // need Jacobian sparsity pattern to determine variable relation
|
||||||
|
// during user recording using checkpoint functions
|
||||||
|
if( sparsity() == atomic_base<Base>::set_sparsity_enum )
|
||||||
|
{ if( member_[thread]->jac_sparse_set_.n_set() == 0 )
|
||||||
|
set_jac_sparse_set();
|
||||||
|
CPPAD_ASSERT_UNKNOWN(
|
||||||
|
member_[thread]->jac_sparse_set_.n_set() == m
|
||||||
|
);
|
||||||
|
CPPAD_ASSERT_UNKNOWN(
|
||||||
|
member_[thread]->jac_sparse_set_.end() == n
|
||||||
|
);
|
||||||
|
//
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ vy[i] = false;
|
||||||
|
local::sparse::list_setvec::const_iterator set_itr(
|
||||||
|
member_[thread]->jac_sparse_set_, i
|
||||||
|
);
|
||||||
|
size_t j = *set_itr;
|
||||||
|
while(j < n )
|
||||||
|
{ // y[i] depends on the value of x[j]
|
||||||
|
// cast avoid Microsoft warning (should not be needed)
|
||||||
|
vy[i] |= static_cast<bool>( vx[j] );
|
||||||
|
j = *(++set_itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ if( member_[thread]->jac_sparse_set_.n_set() != 0 )
|
||||||
|
member_[thread]->jac_sparse_set_.resize(0, 0);
|
||||||
|
if( member_[thread]->jac_sparse_bool_.size() == 0 )
|
||||||
|
set_jac_sparse_bool();
|
||||||
|
CPPAD_ASSERT_UNKNOWN(
|
||||||
|
member_[thread]->jac_sparse_set_.n_set() == 0
|
||||||
|
);
|
||||||
|
CPPAD_ASSERT_UNKNOWN(
|
||||||
|
member_[thread]->jac_sparse_bool_.size() == m * n
|
||||||
|
);
|
||||||
|
//
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ vy[i] = false;
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ if( member_[thread]->jac_sparse_bool_[ i * n + j ] )
|
||||||
|
{ // y[i] depends on the value of x[j]
|
||||||
|
// cast avoid Microsoft warning
|
||||||
|
vy[i] |= static_cast<bool>( vx[j] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// compute forward results for orders zero through q
|
||||||
|
ty = member_[thread]->f_.Forward(q, tx);
|
||||||
|
|
||||||
|
// no longer need the Taylor coefficients in f_
|
||||||
|
// (have to reconstruct them every time)
|
||||||
|
// Hold onto sparsity pattern because it is always good.
|
||||||
|
size_t c = 0;
|
||||||
|
size_t r = 0;
|
||||||
|
member_[thread]->f_.capacity_order(c, r);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::forward(
|
||||||
|
size_t p ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
vector<bool>& vy ,
|
||||||
|
const vector< AD<Base> >& atx ,
|
||||||
|
vector< AD<Base> >& aty )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
// make sure af_ is defined
|
||||||
|
if( member_[thread]->af_.size_var() == 0 )
|
||||||
|
member_[thread]->af_ = member_[thread]->f_.base2ad();
|
||||||
|
//
|
||||||
|
# ifndef NDEBUG
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
# endif
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_var() > 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( atx.size() % (q+1) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( aty.size() % (q+1) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( n == atx.size() / (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( m == aty.size() / (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( vx.size() == 0 )
|
||||||
|
bool ok = true;
|
||||||
|
//
|
||||||
|
// during user forward mode
|
||||||
|
if( member_[thread]->jac_sparse_set_.n_set() != 0 )
|
||||||
|
member_[thread]->jac_sparse_set_.resize(0,0);
|
||||||
|
if( member_[thread]->jac_sparse_bool_.size() != 0 )
|
||||||
|
member_[thread]->jac_sparse_bool_.clear();
|
||||||
|
//
|
||||||
|
if( member_[thread]->hes_sparse_set_.n_set() != 0 )
|
||||||
|
member_[thread]->hes_sparse_set_.resize(0,0);
|
||||||
|
if( member_[thread]->hes_sparse_bool_.size() != 0 )
|
||||||
|
member_[thread]->hes_sparse_bool_.clear();
|
||||||
|
//
|
||||||
|
// compute forward results for orders zero through q
|
||||||
|
aty = member_[thread]->af_.Forward(q, atx);
|
||||||
|
|
||||||
|
// no longer need the Taylor coefficients in af_
|
||||||
|
// (have to reconstruct them every time)
|
||||||
|
// Hold onto sparsity pattern because it is always good.
|
||||||
|
size_t c = 0;
|
||||||
|
size_t r = 0;
|
||||||
|
member_[thread]->af_.capacity_order(c, r);
|
||||||
|
//
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_REV_SPARSE_HES_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_REV_SPARSE_HES_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
template <class sparsity_type>
|
||||||
|
bool checkpoint<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const sparsity_type& r ,
|
||||||
|
const sparsity_type& u ,
|
||||||
|
sparsity_type& v ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
# ifndef NDEBUG
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
# endif
|
||||||
|
CPPAD_ASSERT_UNKNOWN( vx.size() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( s.size() == m );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( t.size() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( r.size() == n * q );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( u.size() == m * q );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( v.size() == n * q );
|
||||||
|
//
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// make sure hes_sparse_bool_ has been set
|
||||||
|
if( member_[thread]->hes_sparse_bool_.size() == 0 )
|
||||||
|
set_hes_sparse_bool();
|
||||||
|
if( member_[thread]->hes_sparse_set_.n_set() != 0 )
|
||||||
|
member_[thread]->hes_sparse_set_.resize(0, 0);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_bool_.size() == n * n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.n_set() == 0 );
|
||||||
|
|
||||||
|
|
||||||
|
// compute sparsity pattern for T(x) = S(x) * f'(x)
|
||||||
|
t = member_[thread]->f_.RevSparseJac(1, s);
|
||||||
|
# ifndef NDEBUG
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
CPPAD_ASSERT_UNKNOWN( vx[j] || ! t[j] )
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// V(x) = f'(x)^T * g''(y) * f'(x) * R + g'(y) * f''(x) * R
|
||||||
|
// U(x) = g''(y) * f'(x) * R
|
||||||
|
// S(x) = g'(y)
|
||||||
|
|
||||||
|
// compute sparsity pattern for A(x) = f'(x)^T * U(x)
|
||||||
|
bool transpose = true;
|
||||||
|
sparsity_type a(n * q);
|
||||||
|
a = member_[thread]->f_.RevSparseJac(q, u, transpose);
|
||||||
|
|
||||||
|
// Need sparsity pattern for H(x) = (S(x) * f(x))''(x) * R,
|
||||||
|
// but use less efficient sparsity for f(x)''(x) * R so that
|
||||||
|
// hes_sparse_set_ can be used every time this is needed.
|
||||||
|
for(size_t i = 0; i < n; i++)
|
||||||
|
{ for(size_t k = 0; k < q; k++)
|
||||||
|
{ // initialize sparsity pattern for H(i,k)
|
||||||
|
bool h_ik = false;
|
||||||
|
// H(i,k) = sum_j f''(i,j) * R(j,k)
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ bool f_ij = member_[thread]->hes_sparse_bool_[i * n + j];
|
||||||
|
bool r_jk = r[j * q + k];
|
||||||
|
h_ik |= ( f_ij & r_jk );
|
||||||
|
}
|
||||||
|
// sparsity for H(i,k)
|
||||||
|
v[i * q + k] = h_ik;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sparsity pattern for V(x) = A(x) + H(x)
|
||||||
|
for(size_t i = 0; i < n; i++)
|
||||||
|
{ for(size_t k = 0; k < q; k++)
|
||||||
|
// v[ i * q + k ] |= a[ i * q + k];
|
||||||
|
v[ i * q + k ] = bool(v[ i * q + k]) | bool(a[ i * q + k]);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& r ,
|
||||||
|
const vectorBool& u ,
|
||||||
|
vectorBool& v ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
return rev_sparse_hes< vectorBool >(vx, s, t, q, r, u, v, x);
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& r ,
|
||||||
|
const vector<bool>& u ,
|
||||||
|
vector<bool>& v ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
return rev_sparse_hes< vector<bool> >(vx, s, t, q, r, u, v, x);
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::rev_sparse_hes(
|
||||||
|
const vector<bool>& vx ,
|
||||||
|
const vector<bool>& s ,
|
||||||
|
vector<bool>& t ,
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& r ,
|
||||||
|
const vector< std::set<size_t> >& u ,
|
||||||
|
vector< std::set<size_t> >& v ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
# ifndef NDEBUG
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
# endif
|
||||||
|
CPPAD_ASSERT_UNKNOWN( vx.size() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( s.size() == m );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( t.size() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( r.size() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( u.size() == m );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( v.size() == n );
|
||||||
|
//
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// make sure hes_sparse_set_ has been set
|
||||||
|
if( member_[thread]->hes_sparse_bool_.size() != 0 )
|
||||||
|
member_[thread]->hes_sparse_bool_.clear();
|
||||||
|
if( member_[thread]->hes_sparse_set_.n_set() == 0 )
|
||||||
|
set_hes_sparse_set();
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_bool_.size() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.n_set() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.end() == n );
|
||||||
|
|
||||||
|
// compute sparsity pattern for T(x) = S(x) * f'(x)
|
||||||
|
t = member_[thread]->f_.RevSparseJac(1, s);
|
||||||
|
# ifndef NDEBUG
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
CPPAD_ASSERT_UNKNOWN( vx[j] || ! t[j] )
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// V(x) = f'(x)^T * g''(y) * f'(x) * R + g'(y) * f''(x) * R
|
||||||
|
// U(x) = g''(y) * f'(x) * R
|
||||||
|
// S(x) = g'(y)
|
||||||
|
|
||||||
|
// compute sparsity pattern for A(x) = f'(x)^T * U(x)
|
||||||
|
// 2DO: change a to use INTERNAL_SPARSE_SET
|
||||||
|
bool transpose = true;
|
||||||
|
vector< std::set<size_t> > a(n);
|
||||||
|
a = member_[thread]->f_.RevSparseJac(q, u, transpose);
|
||||||
|
|
||||||
|
// Need sparsity pattern for H(x) = (S(x) * f(x))''(x) * R,
|
||||||
|
// but use less efficient sparsity for f(x)''(x) * R so that
|
||||||
|
// hes_sparse_set_ can be used every time this is needed.
|
||||||
|
for(size_t i = 0; i < n; i++)
|
||||||
|
{ v[i].clear();
|
||||||
|
local::sparse::list_setvec::const_iterator set_itr(
|
||||||
|
member_[thread]->hes_sparse_set_, i
|
||||||
|
);
|
||||||
|
size_t j = *set_itr;
|
||||||
|
while( j < n )
|
||||||
|
{ std::set<size_t>::const_iterator itr_j;
|
||||||
|
const std::set<size_t>& r_j( r[j] );
|
||||||
|
for(itr_j = r_j.begin(); itr_j != r_j.end(); itr_j++)
|
||||||
|
{ size_t k = *itr_j;
|
||||||
|
v[i].insert(k);
|
||||||
|
}
|
||||||
|
j = *(++set_itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// compute sparsity pattern for V(x) = A(x) + H(x)
|
||||||
|
std::set<size_t>::const_iterator itr;
|
||||||
|
for(size_t i = 0; i < n; i++)
|
||||||
|
{ for(itr = a[i].begin(); itr != a[i].end(); itr++)
|
||||||
|
{ size_t j = *itr;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( j < q );
|
||||||
|
v[i].insert(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_REV_SPARSE_JAC_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_REV_SPARSE_JAC_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
template <class sparsity_type>
|
||||||
|
bool checkpoint<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const sparsity_type& rt ,
|
||||||
|
sparsity_type& st ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
// during user sparsity calculations
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
if( member_[thread]->jac_sparse_bool_.size() == 0 )
|
||||||
|
set_jac_sparse_bool();
|
||||||
|
if( member_[thread]->jac_sparse_set_.n_set() != 0 )
|
||||||
|
member_[thread]->jac_sparse_set_.resize(0, 0);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == m * n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( rt.size() == m * q );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( st.size() == n * q );
|
||||||
|
bool ok = true;
|
||||||
|
//
|
||||||
|
// S = R * J where J is jacobian
|
||||||
|
for(size_t i = 0; i < q; i++)
|
||||||
|
{ for(size_t j = 0; j < n; j++)
|
||||||
|
{ // initialize sparsity for S(i,j)
|
||||||
|
bool s_ij = false;
|
||||||
|
// S(i,j) = sum_k R(i,k) * J(k,j)
|
||||||
|
for(size_t k = 0; k < m; k++)
|
||||||
|
{ // sparsity for R(i, k)
|
||||||
|
bool R_ik = rt[ k * q + i ];
|
||||||
|
bool J_kj = member_[thread]->jac_sparse_bool_[ k * n + j ];
|
||||||
|
s_ij |= (R_ik & J_kj);
|
||||||
|
}
|
||||||
|
// set sparsity for S^T
|
||||||
|
st[ j * q + i ] = s_ij;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vectorBool& rt ,
|
||||||
|
vectorBool& st ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
return rev_sparse_jac< vectorBool >(q, rt, st, x);
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector<bool>& rt ,
|
||||||
|
vector<bool>& st ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
return rev_sparse_jac< vector<bool> >(q, rt, st, x);
|
||||||
|
}
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::rev_sparse_jac(
|
||||||
|
size_t q ,
|
||||||
|
const vector< std::set<size_t> >& rt ,
|
||||||
|
vector< std::set<size_t> >& st ,
|
||||||
|
const vector<Base>& x )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
// during user sparsity calculations
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
if( member_[thread]->jac_sparse_bool_.size() != 0 )
|
||||||
|
member_[thread]->jac_sparse_bool_.clear();
|
||||||
|
if( member_[thread]->jac_sparse_set_.n_set() == 0 )
|
||||||
|
set_jac_sparse_set();
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == m );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.end() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( rt.size() == m );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( st.size() == n );
|
||||||
|
//
|
||||||
|
bool ok = true;
|
||||||
|
//
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
st[j].clear();
|
||||||
|
//
|
||||||
|
// sparsity for s = r * jac_sparse_set_
|
||||||
|
// s^T = jac_sparse_set_^T * r^T
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ // i is the row index in r^T
|
||||||
|
std::set<size_t>::const_iterator itr_i;
|
||||||
|
const std::set<size_t>& r_i( rt[i] );
|
||||||
|
for(itr_i = r_i.begin(); itr_i != r_i.end(); itr_i++)
|
||||||
|
{ // k is the column index in r^T
|
||||||
|
size_t k = *itr_i;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( k < q );
|
||||||
|
//
|
||||||
|
// i is column index in jac_sparse_set^T
|
||||||
|
local::sparse::list_setvec::const_iterator set_itr(
|
||||||
|
member_[thread]->jac_sparse_set_, i
|
||||||
|
);
|
||||||
|
size_t j = *set_itr;
|
||||||
|
while( j < n )
|
||||||
|
{ // j is row index in jac_sparse_set^T
|
||||||
|
st[j].insert(k);
|
||||||
|
j = *(++set_itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
125
build-config/cppad/include/cppad/core/chkpoint_one/reverse.hpp
Normal file
125
build-config/cppad/include/cppad/core/chkpoint_one/reverse.hpp
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_REVERSE_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_REVERSE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::reverse(
|
||||||
|
size_t q ,
|
||||||
|
const vector<Base>& tx ,
|
||||||
|
const vector<Base>& ty ,
|
||||||
|
vector<Base>& px ,
|
||||||
|
const vector<Base>& py )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
|
||||||
|
# ifndef NDEBUG
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
# endif
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_var() > 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( n == tx.size() / (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( m == ty.size() / (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( tx.size() % (q+1) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ty.size() % (q+1) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( px.size() == n * (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( py.size() == m * (q+1) );
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// put proper forward mode coefficients in f_
|
||||||
|
# ifdef NDEBUG
|
||||||
|
// compute forward results for orders zero through q
|
||||||
|
member_[thread]->f_.Forward(q, tx);
|
||||||
|
# else
|
||||||
|
size_t i, j, k;
|
||||||
|
//
|
||||||
|
// compute forward results for orders zero through q
|
||||||
|
vector<Base> check_ty = member_[thread]->f_.Forward(q, tx);
|
||||||
|
for(i = 0; i < m; i++)
|
||||||
|
{ for(k = 0; k <= q; k++)
|
||||||
|
{ j = i * (q+1) + k;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( check_ty[j] == ty[j] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
// now can run reverse mode
|
||||||
|
px = member_[thread]->f_.Reverse(q+1, py);
|
||||||
|
|
||||||
|
// no longer need the Taylor coefficients in f_
|
||||||
|
// (have to reconstruct them every time)
|
||||||
|
size_t c = 0;
|
||||||
|
size_t r = 0;
|
||||||
|
member_[thread]->f_.capacity_order(c, r);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
template <class Base>
|
||||||
|
bool checkpoint<Base>::reverse(
|
||||||
|
size_t q ,
|
||||||
|
const vector< AD<Base> >& atx ,
|
||||||
|
const vector< AD<Base> >& aty ,
|
||||||
|
vector< AD<Base> >& apx ,
|
||||||
|
const vector< AD<Base> >& apy )
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
// make sure af_ is defined
|
||||||
|
if( member_[thread]->af_.size_var() == 0 )
|
||||||
|
member_[thread]->af_ = member_[thread]->f_.base2ad();
|
||||||
|
# ifndef NDEBUG
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
# endif
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_var() > 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( n == atx.size() / (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( m == aty.size() / (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( atx.size() % (q+1) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( aty.size() % (q+1) == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( apx.size() == n * (q+1) );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( apy.size() == m * (q+1) );
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// put proper forward mode coefficients in f_
|
||||||
|
# ifdef NDEBUG
|
||||||
|
// compute forward results for orders zero through q
|
||||||
|
member_[thread]->af_.Forward(q, atx);
|
||||||
|
# else
|
||||||
|
size_t i, j, k;
|
||||||
|
//
|
||||||
|
// compute forward results for orders zero through q
|
||||||
|
vector< AD<Base> > check_aty = member_[thread]->af_.Forward(q, atx);
|
||||||
|
for(i = 0; i < m; i++)
|
||||||
|
{ for(k = 0; k <= q; k++)
|
||||||
|
{ j = i * (q+1) + k;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( check_aty[j] == aty[j] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
// now can run reverse mode
|
||||||
|
apx = member_[thread]->af_.Reverse(q+1, apy);
|
||||||
|
|
||||||
|
// no longer need the Taylor coefficients in f_
|
||||||
|
// (have to reconstruct them every time)
|
||||||
|
size_t c = 0;
|
||||||
|
size_t r = 0;
|
||||||
|
member_[thread]->af_.capacity_order(c, r);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_SET_HES_SPARSE_BOOL_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_SET_HES_SPARSE_BOOL_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
void checkpoint<Base>::set_hes_sparse_bool(void)
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_bool_.size() == 0 );
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
//
|
||||||
|
// set version of sparsity for vector of all ones
|
||||||
|
vectorBool all_one(m);
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
all_one[i] = true;
|
||||||
|
|
||||||
|
// set version of sparsity for n by n idendity matrix
|
||||||
|
vectorBool identity(n * n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ for(size_t i = 0; i < n; i++)
|
||||||
|
identity[ i * n + j ] = (i == j);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sparsity pattern for H(x) = sum_i f_i(x)^{(2)}
|
||||||
|
bool transpose = false;
|
||||||
|
bool dependency = false;
|
||||||
|
member_[thread]->f_.ForSparseJac(n, identity, transpose, dependency);
|
||||||
|
member_[thread]->hes_sparse_bool_ = member_[thread]->f_.RevSparseHes(n, all_one, transpose);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_bool_.size() == n * n );
|
||||||
|
//
|
||||||
|
// drop the forward sparsity results from f_
|
||||||
|
member_[thread]->f_.size_forward_bool(0);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_bool() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_set() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_SET_HES_SPARSE_SET_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_SET_HES_SPARSE_SET_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
void checkpoint<Base>::set_hes_sparse_set(void)
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.n_set() == 0 );
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
//
|
||||||
|
// set version of sparsity for vector of all ones
|
||||||
|
vector<bool> all_one(m);
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
all_one[i] = true;
|
||||||
|
|
||||||
|
// set version of sparsity for n by n idendity matrix
|
||||||
|
local::sparse::list_setvec identity;
|
||||||
|
identity.resize(n, n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ // Not using post_element because only adding one element per set
|
||||||
|
identity.add_element(j, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sparsity pattern for H(x) = sum_i f_i(x)^{(2)}
|
||||||
|
bool transpose = false;
|
||||||
|
bool dependency = false;
|
||||||
|
member_[thread]->f_.ForSparseJacCheckpoint(
|
||||||
|
n, identity, transpose, dependency, member_[thread]->jac_sparse_set_
|
||||||
|
);
|
||||||
|
member_[thread]->f_.RevSparseHesCheckpoint(
|
||||||
|
n, all_one, transpose, member_[thread]->hes_sparse_set_
|
||||||
|
);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.n_set() == n );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->hes_sparse_set_.end() == n );
|
||||||
|
//
|
||||||
|
// drop the forward sparsity results from f_
|
||||||
|
member_[thread]->f_.size_forward_set(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_SET_JAC_SPARSE_BOOL_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_SET_JAC_SPARSE_BOOL_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
void checkpoint<Base>::set_jac_sparse_bool(void)
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_bool_.size() == 0 );
|
||||||
|
bool transpose = false;
|
||||||
|
bool dependency = true;
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
// Use the choice for forward / reverse that results in smaller
|
||||||
|
// size for the sparsity pattern of all variables in the tape.
|
||||||
|
if( n <= m )
|
||||||
|
{ vectorBool identity(n * n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ for(size_t i = 0; i < n; i++)
|
||||||
|
identity[ i * n + j ] = (i == j);
|
||||||
|
}
|
||||||
|
member_[thread]->jac_sparse_bool_ = member_[thread]->f_.ForSparseJac(
|
||||||
|
n, identity, transpose, dependency
|
||||||
|
);
|
||||||
|
member_[thread]->f_.size_forward_bool(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ vectorBool identity(m * m);
|
||||||
|
for(size_t j = 0; j < m; j++)
|
||||||
|
{ for(size_t i = 0; i < m; i++)
|
||||||
|
identity[ i * m + j ] = (i == j);
|
||||||
|
}
|
||||||
|
member_[thread]->jac_sparse_bool_ = member_[thread]->f_.RevSparseJac(
|
||||||
|
m, identity, transpose, dependency
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_bool() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_set() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_ONE_SET_JAC_SPARSE_SET_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_ONE_SET_JAC_SPARSE_SET_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
void checkpoint<Base>::set_jac_sparse_set(void)
|
||||||
|
{ // make sure member_ is allocated for this thread
|
||||||
|
size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->jac_sparse_set_.n_set() == 0 );
|
||||||
|
bool transpose = false;
|
||||||
|
bool dependency = true;
|
||||||
|
size_t n = member_[thread]->f_.Domain();
|
||||||
|
size_t m = member_[thread]->f_.Range();
|
||||||
|
// Use the choice for forward / reverse that results in smaller
|
||||||
|
// size for the sparsity pattern of all variables in the tape.
|
||||||
|
if( n <= m )
|
||||||
|
{ local::sparse::list_setvec identity;
|
||||||
|
identity.resize(n, n);
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
{ // Not using post_element because only adding one element per set
|
||||||
|
identity.add_element(j, j);
|
||||||
|
}
|
||||||
|
member_[thread]->f_.ForSparseJacCheckpoint(
|
||||||
|
n, identity, transpose, dependency, member_[thread]->jac_sparse_set_
|
||||||
|
);
|
||||||
|
member_[thread]->f_.size_forward_set(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ local::sparse::list_setvec identity;
|
||||||
|
identity.resize(m, m);
|
||||||
|
for(size_t i = 0; i < m; i++)
|
||||||
|
{ // Not using post_element because only adding one element per set
|
||||||
|
identity.add_element(i, i);
|
||||||
|
}
|
||||||
|
member_[thread]->f_.RevSparseJacCheckpoint(
|
||||||
|
m, identity, transpose, dependency, member_[thread]->jac_sparse_set_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_set() == 0 );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( member_[thread]->f_.size_forward_bool() == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
-------------------------------------------------------------------------- */
|
||||||
|
$begin chkpoint_two_chk_fun$$
|
||||||
|
|
||||||
|
$spell
|
||||||
|
const
|
||||||
|
chk
|
||||||
|
chkpoint
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Using Checkpoint Functions$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%chk_fun%(%ax%, %ay%)%$$
|
||||||
|
|
||||||
|
$head Purpose$$
|
||||||
|
Given $icode ax$$,
|
||||||
|
this call computes the corresponding value of $icode ay$$.
|
||||||
|
If $codei%AD<%Base%>%$$ operations are being recorded,
|
||||||
|
it enters the computation as an $cref atomic_three$$
|
||||||
|
operation in the recording;
|
||||||
|
see $cref/start recording/Independent/Start Recording/$$.
|
||||||
|
|
||||||
|
$head chk_fun$$
|
||||||
|
This object must have been created using the
|
||||||
|
$cref/chkpoint_two/chkpoint_two_ctor/chk_fun/$$ constructor.
|
||||||
|
|
||||||
|
$head ADVector$$
|
||||||
|
The type $icode ADVector$$ must be a
|
||||||
|
$cref/simple vector class/SimpleVector/$$ with elements of type
|
||||||
|
$codei%AD<%Base%>%$$.
|
||||||
|
|
||||||
|
$head ax$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
const %ADVector%& ax
|
||||||
|
%$$
|
||||||
|
and its size equal to $icode%n% = %fun%.Domain()%$$
|
||||||
|
where $cref/fun/chkpoint_two_ctor/fun/$$ is the $codei%ADFun<%Base%>%$$
|
||||||
|
function in used the constructor for $icode chk_fun$$.
|
||||||
|
It specifies vector $latex x \in \B{R}^n$$
|
||||||
|
at which we are computing an $codei%AD<%Base%>%$$ version of
|
||||||
|
$latex y = g(x)$$.
|
||||||
|
|
||||||
|
$head ay$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
%ADVector%& ay
|
||||||
|
%$$
|
||||||
|
and its size must be equal to $icode%m% = %fun%.Range()%$$.
|
||||||
|
The input values of its elements do not matter.
|
||||||
|
Upon return, it is an $codei%AD<%Base%>%$$ version of
|
||||||
|
$latex y = g(x)$$.
|
||||||
|
|
||||||
|
|
||||||
|
$end
|
||||||
@@ -0,0 +1,311 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_CHKPOINT_TWO_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_CHKPOINT_TWO_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two.hpp
|
||||||
|
Second generation checkpoint functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin chkpoint_two$$
|
||||||
|
$spell
|
||||||
|
CppAD
|
||||||
|
chk
|
||||||
|
chkpoint
|
||||||
|
hpp
|
||||||
|
cppad
|
||||||
|
bool
|
||||||
|
hes
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Checkpoint Functions: Second Generation$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
|
||||||
|
$subhead Constructor$$
|
||||||
|
$codei%chkpoint_two<%Base%> %chk_fun%( %fun%, %name%,
|
||||||
|
%internal_bool%, %use_hes_sparsity%, %use_base2ad%, %use_in_parallel%
|
||||||
|
)%$$
|
||||||
|
|
||||||
|
$subhead Use Checkpoint Function$$
|
||||||
|
$codei% %chk_fun%(%ax%, %ay%)%$$
|
||||||
|
|
||||||
|
$subhead new_dynamic$$
|
||||||
|
$icode%chk_fun%.new_dynamic(%dynamic%)%$$
|
||||||
|
|
||||||
|
$head Reduce Memory$$
|
||||||
|
You can reduce the size of the tape and memory required for AD
|
||||||
|
using a checkpoint representation of a function
|
||||||
|
$latex g : \B{R}^n \rightarrow \B{R}^m$$.
|
||||||
|
|
||||||
|
$head Faster Recording$$
|
||||||
|
It may also reduce the time to make a recording if the same $latex g(x)$$
|
||||||
|
is used many times (with different values) during the
|
||||||
|
recording of an $codei%ADFun<%Base%>%$$ object.
|
||||||
|
|
||||||
|
$head Repeating Forward$$
|
||||||
|
Normally, CppAD stores $cref forward$$ mode results,
|
||||||
|
until they freed using $cref capacity_order$$,
|
||||||
|
or the corresponding $cref ADFun$$ object is deleted.
|
||||||
|
This is not true for $code chkpoint_two$$ functions
|
||||||
|
because the same checkpoint function may be used repeatedly
|
||||||
|
with different arguments during a single forward mode operation.
|
||||||
|
Thus, forward mode results are computed for each use of $icode chk_fun$$
|
||||||
|
in a forward mode sweep.
|
||||||
|
|
||||||
|
$head Operation Sequence$$
|
||||||
|
The $cref/operation sequence/glossary/Operation/Sequence/$$
|
||||||
|
representing $latex g(x)$$ is fixed; i.e.,
|
||||||
|
it cannot depend on the value of $latex x$$.
|
||||||
|
|
||||||
|
$head atomic_three$$
|
||||||
|
The $code chkpoint_two$$ class is derived from $code atomic_three$$,
|
||||||
|
hence some of its error message will refer to atomic operations.
|
||||||
|
The $code chkpoint_two$$ class implements all the
|
||||||
|
$cref/virtual functions/atomic_three/Virtual Functions/$$
|
||||||
|
and hence its source code,
|
||||||
|
$codei%
|
||||||
|
include/cppad/core/chkpoint_two/chkpoint_two.hpp
|
||||||
|
%$$
|
||||||
|
provides an example for $cref atomic_three$$ operations.
|
||||||
|
The difference is that $code chkpoint_two.hpp$$ uses AD
|
||||||
|
instead of user provided derivatives.
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
The type $icode Base$$ specifies the base type for AD operations;
|
||||||
|
i.e., $icode chk_fun$$ can be used during the recording of
|
||||||
|
$codei%AD<%Base%>%$$ operations.
|
||||||
|
|
||||||
|
|
||||||
|
$childtable%include/cppad/core/chkpoint_two/ctor.hpp
|
||||||
|
%include/cppad/core/chkpoint_two/chk_fun.omh
|
||||||
|
%include/cppad/core/chkpoint_two/dynamic.hpp
|
||||||
|
%example/chkpoint_two/get_started.cpp
|
||||||
|
%example/chkpoint_two/compare.cpp
|
||||||
|
%example/chkpoint_two/base2ad.cpp
|
||||||
|
%example/chkpoint_two/dynamic.cpp
|
||||||
|
%example/chkpoint_two/ode.cpp
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
class chkpoint_two : public atomic_three<Base> {
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
private:
|
||||||
|
/// are sparsity calculations using bools or sets of integers
|
||||||
|
const bool internal_bool_;
|
||||||
|
//
|
||||||
|
/// can this checkpoint function calculate Hessian sparsity patterns
|
||||||
|
const bool use_hes_sparsity_;
|
||||||
|
//
|
||||||
|
/// can this checkpoint function be used in base2ad recordings
|
||||||
|
const bool use_base2ad_;
|
||||||
|
//
|
||||||
|
/// can this checkpoint function be used in parallel mode
|
||||||
|
const bool use_in_parallel_;
|
||||||
|
//
|
||||||
|
/// Jacobian sparsity for g(x) with dependncy true.
|
||||||
|
/// This is set by the constructor and constant after that.
|
||||||
|
sparse_rc< vector<size_t> > jac_sparsity_;
|
||||||
|
//
|
||||||
|
/// Hessian sparsity for g(x). If use_hes_sparsity_ is true,
|
||||||
|
/// This is set by the constructor and constant after that.
|
||||||
|
sparse_rc< vector<size_t> > hes_sparsity_;
|
||||||
|
//
|
||||||
|
/// Function corresponding to this checkpoint object.
|
||||||
|
/// If use_in_parallel_, this is constant after the constructor.
|
||||||
|
ADFun<Base> g_;
|
||||||
|
//
|
||||||
|
/// AD version of function corresponding to this checkpoint object
|
||||||
|
/// If use_in_parallel_, this is constant after the constructor.
|
||||||
|
ADFun< AD<Base>, Base> ag_;
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// member_
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/// If use_in_parallel_ is true, must have a separate copy member data
|
||||||
|
/// that is not constant.
|
||||||
|
struct member_struct {
|
||||||
|
//
|
||||||
|
/// function corresponding to this checkpoint object
|
||||||
|
ADFun<Base> g_;
|
||||||
|
//
|
||||||
|
/// AD version of this function object
|
||||||
|
ADFun< AD<Base>, Base > ag_;
|
||||||
|
//
|
||||||
|
};
|
||||||
|
/// use pointers and allocate memory to avoid false sharing
|
||||||
|
/// (initialized to null by constructor)
|
||||||
|
member_struct* member_[CPPAD_MAX_NUM_THREADS];
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/// allocate member_ for this thread
|
||||||
|
void allocate_member(size_t thread)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( use_in_parallel_ );
|
||||||
|
if( member_[thread] == nullptr )
|
||||||
|
{ // allocaate raw memory
|
||||||
|
size_t min_bytes = sizeof(member_struct);
|
||||||
|
size_t num_bytes;
|
||||||
|
void* v_ptr = thread_alloc::get_memory(min_bytes, num_bytes);
|
||||||
|
// convert to member_struct*
|
||||||
|
member_[thread] = reinterpret_cast<member_struct*>(v_ptr);
|
||||||
|
// call member_struct constructor
|
||||||
|
new( member_[thread] ) member_struct;
|
||||||
|
//
|
||||||
|
// The thread has a copy of corresponding informaiton.
|
||||||
|
member_[thread]->g_ = g_;
|
||||||
|
member_[thread]->ag_ = ag_;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/// free member_ for this thread
|
||||||
|
void free_member(size_t thread)
|
||||||
|
{ if( member_[thread] != nullptr )
|
||||||
|
{ // call destructor
|
||||||
|
member_[thread]->~member_struct();
|
||||||
|
// return raw m,emory to available pool for this thread
|
||||||
|
void* v_ptr = reinterpret_cast<void*>(member_[thread]);
|
||||||
|
thread_alloc::return_memory(v_ptr);
|
||||||
|
// mark member for this thread as not allocated
|
||||||
|
member_[thread] = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// atomic_three virtual functions
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// type
|
||||||
|
virtual bool for_type(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<ad_type_enum>& type_y
|
||||||
|
);
|
||||||
|
// forward
|
||||||
|
virtual bool forward(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t need_y ,
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
vector<Base>& taylor_y
|
||||||
|
);
|
||||||
|
// AD forward
|
||||||
|
virtual bool forward(
|
||||||
|
const vector< AD<Base> >& aparameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t need_y ,
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
vector< AD<Base> >& ataylor_y
|
||||||
|
);
|
||||||
|
// reverse
|
||||||
|
virtual bool reverse(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
const vector<Base>& taylor_y ,
|
||||||
|
vector<Base>& partial_x ,
|
||||||
|
const vector<Base>& partial_y
|
||||||
|
);
|
||||||
|
// AD reverse
|
||||||
|
virtual bool reverse(
|
||||||
|
const vector< AD<Base> >& aparameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
const vector< AD<Base> >& ataylor_y ,
|
||||||
|
vector< AD<Base> >& apartial_x ,
|
||||||
|
const vector< AD<Base> >& apartial_y
|
||||||
|
);
|
||||||
|
// jac_sparsity
|
||||||
|
virtual bool jac_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
bool dependency ,
|
||||||
|
const vector<bool>& select_x ,
|
||||||
|
const vector<bool>& select_y ,
|
||||||
|
sparse_rc< vector<size_t> >& pattern_out
|
||||||
|
);
|
||||||
|
// hes_sparsity
|
||||||
|
virtual bool hes_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const vector<bool>& select_x ,
|
||||||
|
const vector<bool>& select_y ,
|
||||||
|
sparse_rc< vector<size_t> >& pattern_out
|
||||||
|
);
|
||||||
|
// rev_depend
|
||||||
|
virtual bool rev_depend(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<bool>& depend_x ,
|
||||||
|
const vector<bool>& depend_y
|
||||||
|
);
|
||||||
|
public:
|
||||||
|
// ctor
|
||||||
|
chkpoint_two(
|
||||||
|
const ADFun<Base>& fun ,
|
||||||
|
const std::string& name ,
|
||||||
|
bool internal_bool ,
|
||||||
|
bool use_hes_sparsity ,
|
||||||
|
bool use_base2ad ,
|
||||||
|
bool use_in_parallel
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// destructor
|
||||||
|
~chkpoint_two(void);
|
||||||
|
//
|
||||||
|
// assignment operator
|
||||||
|
void operator=(const chkpoint_two& other)
|
||||||
|
{ CPPAD_ASSERT_KNOWN(false,
|
||||||
|
"cannot use chkpoint_two assignment operator"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// copy constructor
|
||||||
|
chkpoint_two(const chkpoint_two& other)
|
||||||
|
:
|
||||||
|
internal_bool_ ( other.internal_bool_ ) ,
|
||||||
|
use_hes_sparsity_ ( other.use_hes_sparsity_ ) ,
|
||||||
|
use_base2ad_ ( other.use_base2ad_ ) ,
|
||||||
|
use_in_parallel_ ( other.use_in_parallel_ ) ,
|
||||||
|
jac_sparsity_ ( other.jac_sparsity_ ) ,
|
||||||
|
hes_sparsity_ ( other.hes_sparsity_ )
|
||||||
|
{ g_ = other.g_;
|
||||||
|
ag_ = other.ag_;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// new_dynamic
|
||||||
|
template <class BaseVector>
|
||||||
|
void new_dynamic(const BaseVector& dynamic);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
# include <cppad/core/chkpoint_two/ctor.hpp>
|
||||||
|
# include <cppad/core/chkpoint_two/dynamic.hpp>
|
||||||
|
# include <cppad/core/chkpoint_two/for_type.hpp>
|
||||||
|
# include <cppad/core/chkpoint_two/forward.hpp>
|
||||||
|
# include <cppad/core/chkpoint_two/reverse.hpp>
|
||||||
|
# include <cppad/core/chkpoint_two/jac_sparsity.hpp>
|
||||||
|
# include <cppad/core/chkpoint_two/hes_sparsity.hpp>
|
||||||
|
# include <cppad/core/chkpoint_two/rev_depend.hpp>
|
||||||
|
|
||||||
|
# endif
|
||||||
222
build-config/cppad/include/cppad/core/chkpoint_two/ctor.hpp
Normal file
222
build-config/cppad/include/cppad/core/chkpoint_two/ctor.hpp
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_CTOR_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_CTOR_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin chkpoint_two_ctor$$
|
||||||
|
$spell
|
||||||
|
chkpoint
|
||||||
|
chk
|
||||||
|
bool
|
||||||
|
hes
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Checkpoint Function Constructor$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$codei%chkpoint_two<%Base%> %chk_fun%( %fun%, %name%,
|
||||||
|
%internal_bool%, %use_hes_sparsity%, %use_base2ad%, %use_in_parallel%
|
||||||
|
)%$$
|
||||||
|
|
||||||
|
$head Prototype$$
|
||||||
|
$srcthisfile%
|
||||||
|
0%// BEGIN_PROTOTYPE%// END_PROTOTYPE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Parallel$$
|
||||||
|
This constructor, and its corresponding destructor, must not be called in
|
||||||
|
$cref/parallel/ta_in_parallel/$$ mode.
|
||||||
|
The object $icode chk_fun$$ should not be destructed for as long as there is
|
||||||
|
an $codei%ADFun<%Base%>%$$ object the has $icode chk_fun$$ in its recording.
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
The type $icode Base$$ specifies the base type for AD operations.
|
||||||
|
|
||||||
|
$head fun$$
|
||||||
|
This specifies the function $latex g(x)$$.
|
||||||
|
Note that $icode fun$$ may or may not have been
|
||||||
|
$cref/optimized/optimize/$$ before calling the constructor.
|
||||||
|
This will determine if the internal representation for $icode g(x)$$
|
||||||
|
is optimized.
|
||||||
|
|
||||||
|
$head name$$
|
||||||
|
is the name used for reporting errors using this checkpoint function.
|
||||||
|
|
||||||
|
$head internal_bool$$
|
||||||
|
If true, sparsity calculations are done with sets represented
|
||||||
|
by vectors of boolean values.
|
||||||
|
Otherwise, vectors of sets are used for sparsity patterns.
|
||||||
|
|
||||||
|
$head use_hes_sparsity$$
|
||||||
|
If true, Hessian sparsity patterns can be calculated for
|
||||||
|
$codei%ADFun<%Base%>%$$ objects that have uses of $icode chk_fun$$
|
||||||
|
in their recording.
|
||||||
|
This requires some extra memory and extra computation during the constructor.
|
||||||
|
|
||||||
|
$head use_base2ad$$
|
||||||
|
If this is true, $icode chk_fun$$ can be used during the recording
|
||||||
|
of $codei%ADFun<%Base%>%$$ objects that get converted to
|
||||||
|
$codei%ADFun< AD<%Base%> >%$$ objects using $cref base2ad$$.
|
||||||
|
This requires some extra memory and extra computation during the constructor.
|
||||||
|
|
||||||
|
$head use_in_parallel$$
|
||||||
|
If this is true, $icode chk_fun$$ can be used
|
||||||
|
$cref/in_parallel/ta_parallel_setup/in_parallel/$$.
|
||||||
|
This requires some extra memory for a constant copy of the $icode fun$$
|
||||||
|
information and a separate copy (that changes) for each thread.
|
||||||
|
|
||||||
|
$head chk_fun$$
|
||||||
|
This is a checkpoint function representation of $latex g(x)$$
|
||||||
|
that can be used during the recording of $codei%AD<%Base%>%$$ operations.
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two/ctor.hpp
|
||||||
|
Constructor for chkpoint_two class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructor
|
||||||
|
|
||||||
|
\tparam Base
|
||||||
|
base class for recording AD<Base> operations using this checkpoint object.
|
||||||
|
|
||||||
|
\param fun
|
||||||
|
is the function g(x) corresponding to this checkpoint object.
|
||||||
|
|
||||||
|
\param name
|
||||||
|
is the name used for error reporting.
|
||||||
|
|
||||||
|
\param internal_bool
|
||||||
|
should sparisity calculations be done using bools (or sets).
|
||||||
|
|
||||||
|
\param use_hes_sparsity
|
||||||
|
will this checkpoint function be used with Hessian sparsity calculations.
|
||||||
|
|
||||||
|
\param use_base2ad
|
||||||
|
will this checkpoint function be used with base2ad.
|
||||||
|
|
||||||
|
\param use_in_parallel
|
||||||
|
will this checkpoint function be used in parallel mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
chkpoint_two<Base>::chkpoint_two(
|
||||||
|
const ADFun<Base>& fun ,
|
||||||
|
const std::string& name ,
|
||||||
|
bool internal_bool ,
|
||||||
|
bool use_hes_sparsity ,
|
||||||
|
bool use_base2ad ,
|
||||||
|
bool use_in_parallel )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
:
|
||||||
|
atomic_three<Base>(name) ,
|
||||||
|
internal_bool_( internal_bool ) ,
|
||||||
|
use_hes_sparsity_( use_hes_sparsity ) ,
|
||||||
|
use_base2ad_ ( use_base2ad ) ,
|
||||||
|
use_in_parallel_ ( use_in_parallel )
|
||||||
|
{ CPPAD_ASSERT_KNOWN(
|
||||||
|
! thread_alloc::in_parallel() ,
|
||||||
|
"chkpoint_two: constructor cannot be called in parallel mode."
|
||||||
|
);
|
||||||
|
// initialize member pointers as null;
|
||||||
|
for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; thread++)
|
||||||
|
member_[thread] = nullptr;
|
||||||
|
//
|
||||||
|
// g_
|
||||||
|
g_ = fun;
|
||||||
|
//
|
||||||
|
// suppress check for nan because chkpoint_two object can be used in a
|
||||||
|
// function that gets optimized and some checkpoint results may not matter.
|
||||||
|
g_.check_for_nan(false);
|
||||||
|
//
|
||||||
|
// ag_
|
||||||
|
if( use_base2ad )
|
||||||
|
ag_ = g_.base2ad();
|
||||||
|
//
|
||||||
|
// jac_sparsity__
|
||||||
|
size_t n = g_.Domain();
|
||||||
|
size_t m = g_.Range();
|
||||||
|
sparse_rc< vector<size_t> > pattern_in;
|
||||||
|
bool transpose = false;
|
||||||
|
bool dependency = true;
|
||||||
|
if( n <= m || use_hes_sparsity )
|
||||||
|
{ // use forward mode
|
||||||
|
pattern_in.resize(n, n, n);
|
||||||
|
for(size_t k = 0; k < n; ++k)
|
||||||
|
pattern_in.set(k, k, k);
|
||||||
|
g_.for_jac_sparsity(
|
||||||
|
pattern_in,
|
||||||
|
transpose,
|
||||||
|
dependency,
|
||||||
|
internal_bool,
|
||||||
|
jac_sparsity_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // use reverse mode
|
||||||
|
pattern_in.resize(m, m, m);
|
||||||
|
for(size_t k = 0; k < m; ++k)
|
||||||
|
pattern_in.set(k, k, k);
|
||||||
|
g_.rev_jac_sparsity(
|
||||||
|
pattern_in,
|
||||||
|
transpose,
|
||||||
|
dependency,
|
||||||
|
internal_bool,
|
||||||
|
jac_sparsity_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// hes_sparsity_
|
||||||
|
if( use_hes_sparsity )
|
||||||
|
{ vector<bool> select_y(m), select_x(n);
|
||||||
|
for(size_t i = 0; i < m; ++i)
|
||||||
|
select_y[i] = true;
|
||||||
|
if( n <= m )
|
||||||
|
{ for(size_t j = 0; j < n; ++j)
|
||||||
|
select_x[j] = true;
|
||||||
|
g_.for_hes_sparsity(
|
||||||
|
select_x, select_y, internal_bool, hes_sparsity_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // forward jacobian sparsity is stored in g_
|
||||||
|
g_.rev_hes_sparsity(
|
||||||
|
select_y, transpose, internal_bool, hes_sparsity_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// free memory holding forward Jacobian sparsity
|
||||||
|
if( internal_bool )
|
||||||
|
g_.size_forward_bool(0);
|
||||||
|
else
|
||||||
|
g_.size_forward_set(0);
|
||||||
|
}
|
||||||
|
/// destructor
|
||||||
|
template <class Base>
|
||||||
|
chkpoint_two<Base>::~chkpoint_two(void)
|
||||||
|
{
|
||||||
|
# ifndef NDEBUG
|
||||||
|
if( thread_alloc::in_parallel() )
|
||||||
|
{ std::string msg = atomic_three<Base>::atomic_name();
|
||||||
|
msg += ": chkpoint_two destructor called in parallel mode.";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
for(size_t thread = 0; thread < CPPAD_MAX_NUM_THREADS; ++thread)
|
||||||
|
free_member(thread);
|
||||||
|
}
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
102
build-config/cppad/include/cppad/core/chkpoint_two/dynamic.hpp
Normal file
102
build-config/cppad/include/cppad/core/chkpoint_two/dynamic.hpp
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_DYNAMIC_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_DYNAMIC_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin chkpoint_two_dynamic$$
|
||||||
|
$spell
|
||||||
|
chk
|
||||||
|
chkpoint
|
||||||
|
dyn_ind
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Dynamic Parameters in Checkpoint Functions$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%chk_fun%.new_dynamic(%dynamic%)%$$
|
||||||
|
|
||||||
|
$head Prototype$$
|
||||||
|
$srcthisfile%
|
||||||
|
0%// BEGIN_PROTOTYPE%// END_PROTOTYPE%1
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head chk_fun$$
|
||||||
|
This object must have been created using the
|
||||||
|
$cref/chkpoint_two/chkpoint_two_ctor/chk_fun/$$ constructor.
|
||||||
|
|
||||||
|
$subhead Base$$
|
||||||
|
This is the $cref/Base/chkpoint_two_ctor/Base/$$ type
|
||||||
|
in the $icode chk_fun$$ constructor.
|
||||||
|
|
||||||
|
$subhead fun$$
|
||||||
|
This is the function $cref/fun/chkpoint_two_ctor/fun/$$
|
||||||
|
in the $icode chk_fun$$ constructor.
|
||||||
|
|
||||||
|
$head BaseVector$$
|
||||||
|
This must be a $cref SimpleVector$$ with elements of type $icode Base$$.
|
||||||
|
|
||||||
|
$head dynamic$$
|
||||||
|
This is a vector with new values for the dynamic parameters
|
||||||
|
in the function $icode fun$$.
|
||||||
|
Is size must be equal to
|
||||||
|
$cref/fun.size_dyn_ind()/seq_property/size_dyn_par/$$.
|
||||||
|
This only affects the copy of $icode fun$$ used by $icode chk_fun$$.
|
||||||
|
|
||||||
|
$head Multi-Threading$$
|
||||||
|
If one is using $cref/in_parallel/ta_in_parallel/$$,
|
||||||
|
there is a separate copy of $icode fun$$ for each thread.
|
||||||
|
In this case, only the dynamic parameters in the copy for the current
|
||||||
|
$cref/thread number/ta_thread_num/$$ are changed.
|
||||||
|
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two/dynamic.hpp
|
||||||
|
Change the dynnamic parameter in a checkpoint function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructor
|
||||||
|
|
||||||
|
\tparam Base
|
||||||
|
base class for recording AD<Base> operations using this checkpoint object.
|
||||||
|
|
||||||
|
\param dynamic
|
||||||
|
is the new values for the dynamic parameters in the function
|
||||||
|
defining this checkpoint object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
template <class BaseVector>
|
||||||
|
void chkpoint_two<Base>::new_dynamic(const BaseVector& dynamic)
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ ADFun<Base>* g_ptr = &g_;
|
||||||
|
if( use_in_parallel_ )
|
||||||
|
{ size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
g_ptr = &(member_[thread]->g_);
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
else if( thread_alloc::in_parallel() )
|
||||||
|
{ std::string msg = atomic_three<Base>::atomic_name();
|
||||||
|
msg += ": use_in_parallel is false and in_parallel() is true";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
g_ptr->new_dynamic(dynamic);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_FOR_TYPE_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_FOR_TYPE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two/for_type.hpp
|
||||||
|
Second generation checkpoint type computation.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from atomic_three to type calculation
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
is the value of the parameters in the corresponding function call
|
||||||
|
afun(ax, ay).
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
specifies which components of x are
|
||||||
|
constants, dynamics, and variables
|
||||||
|
|
||||||
|
\param type_y [out]
|
||||||
|
specifies which components of y are
|
||||||
|
constants, dynamics, and variables
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool chkpoint_two<Base>::for_type(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<ad_type_enum>& type_y )
|
||||||
|
{ size_t nr = jac_sparsity_.nr();
|
||||||
|
size_t nnz = jac_sparsity_.nnz();
|
||||||
|
const vector<size_t>& row( jac_sparsity_.row() );
|
||||||
|
const vector<size_t>& col( jac_sparsity_.col() );
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nr() == type_y.size() );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nc() == type_x.size() );
|
||||||
|
//
|
||||||
|
// initialize type_y as constant_enum
|
||||||
|
for(size_t i = 0; i < nr; ++i)
|
||||||
|
type_y[i] = constant_enum;
|
||||||
|
//
|
||||||
|
// loop over entries in Dependency pattern
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
type_y[i] = std::max(type_y[i], type_x[j]);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
# endif
|
||||||
130
build-config/cppad/include/cppad/core/chkpoint_two/forward.hpp
Normal file
130
build-config/cppad/include/cppad/core/chkpoint_two/forward.hpp
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_FORWARD_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_FORWARD_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two/forward.hpp
|
||||||
|
Second generation checkpoint forward mode.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from chkpoint_two to forward mode
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
contains the values, in afun(ax, ay), for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param need_y [in]
|
||||||
|
specifies which components of taylor_y are needed,
|
||||||
|
|
||||||
|
\param order_low [in]
|
||||||
|
lowerest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param taylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param taylor_y [out]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
See the forward mode in user's documentation for atomic_three
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool chkpoint_two<Base>::forward(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t need_y ,
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
vector<Base>& taylor_y )
|
||||||
|
{ ADFun<Base>* g_ptr = &g_;
|
||||||
|
if( use_in_parallel_ )
|
||||||
|
{ size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
g_ptr = &(member_[thread]->g_);
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
else if( thread_alloc::in_parallel() )
|
||||||
|
{ std::string msg = atomic_three<Base>::atomic_name();
|
||||||
|
msg += ": use_in_parallel is false and in_parallel() is true";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
// compute forward mode results for all values and orders
|
||||||
|
taylor_y = g_ptr->Forward(order_up, taylor_x);
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
Link from chkpoint_two to AD forward mode
|
||||||
|
|
||||||
|
\param aparameter_x [in]
|
||||||
|
contains the values, in afun(ax, ay), for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param need_y [in]
|
||||||
|
specifies which components of taylor_y are needed,
|
||||||
|
|
||||||
|
\param order_low [in]
|
||||||
|
lowerest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order for this forward mode calculation.
|
||||||
|
|
||||||
|
\param ataylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param ataylor_y [out]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
See the forward mode in user's documentation for atomic_three
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool chkpoint_two<Base>::forward(
|
||||||
|
const vector< AD<Base> >& aparameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t need_y ,
|
||||||
|
size_t order_low ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
vector< AD<Base> >& ataylor_y )
|
||||||
|
{ if( ! use_base2ad_ )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
ADFun< AD<Base>, Base >* ag_ptr = &ag_;
|
||||||
|
if( use_in_parallel_ )
|
||||||
|
{ size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
ag_ptr = &(member_[thread]->ag_);
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
else if( thread_alloc::in_parallel() )
|
||||||
|
{ std::string msg = atomic_three<Base>::atomic_name();
|
||||||
|
msg += ": use_in_parallel is false and in_parallel() is true";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
// compute forward mode results for all values and orders
|
||||||
|
ataylor_y = ag_ptr->Forward(order_up, ataylor_x);
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_HES_SPARSITY_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_HES_SPARSITY_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two/hes_sparsity.hpp
|
||||||
|
Second generation checkpoint Jacobian sparsity patterns.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
chkpoint_two to Hessian sparsity calculations.
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
contains the values for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param select_x [in]
|
||||||
|
which domain components to include in the dependency or sparsity pattern.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param select_y [in]
|
||||||
|
which range components to include in the dependency or sparsity pattern.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
This argument is ignored because the sparsity pattern corresponding to
|
||||||
|
all components true is computed during the construction and used for all cases.
|
||||||
|
This errors on the side of caution for the sake of speed.
|
||||||
|
|
||||||
|
|
||||||
|
\param pattern_out [out]
|
||||||
|
is the dependency or sparsity pattern.
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
bool chkpoint_two<Base>::hes_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
const vector<bool>& select_x ,
|
||||||
|
const vector<bool>& select_y ,
|
||||||
|
sparse_rc< vector<size_t> >& pattern_out )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( hes_sparsity_.nr() == select_x.size() );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( hes_sparsity_.nc() == select_x.size() );
|
||||||
|
if( ! use_hes_sparsity_ )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// count number of non-zeros
|
||||||
|
size_t nnz = hes_sparsity_.nnz();
|
||||||
|
size_t nr = hes_sparsity_.nr();
|
||||||
|
size_t nc = hes_sparsity_.nc();
|
||||||
|
const vector<size_t>& row = hes_sparsity_.row();
|
||||||
|
const vector<size_t>& col = hes_sparsity_.col();
|
||||||
|
size_t nnz_out = 0;
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
if( select_x[j] & select_x[i] )
|
||||||
|
++nnz_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the output sparsity pattern
|
||||||
|
pattern_out.resize(nr, nc, nnz_out);
|
||||||
|
size_t ell = 0;
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
if( select_x[j] & select_x[i] )
|
||||||
|
pattern_out.set(ell++, i, j);
|
||||||
|
}
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ell == nnz_out );
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_JAC_SPARSITY_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_JAC_SPARSITY_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two/jac_sparsity.hpp
|
||||||
|
Second generation checkpoint Jacobian sparsity patterns.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
chkpoint_two to Jacobian sparsity calculations.
|
||||||
|
|
||||||
|
\param dependency [in]
|
||||||
|
This argument is ignored.
|
||||||
|
The return pattern is always a dependency pattern which is a correct,
|
||||||
|
but possibly not efficient, sparsity pattern.
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
contains the values for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param select_x [in]
|
||||||
|
which domain components to include in the dependency or sparsity pattern.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param select_y [in]
|
||||||
|
which range components to include in the dependency or sparsity pattern.
|
||||||
|
The index zero is used for parameters.
|
||||||
|
|
||||||
|
\param pattern_out [out]
|
||||||
|
is the dependency or sparsity pattern.
|
||||||
|
*/
|
||||||
|
// BEGIN_PROTOTYPE
|
||||||
|
template <class Base>
|
||||||
|
bool chkpoint_two<Base>::jac_sparsity(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
bool dependency ,
|
||||||
|
const vector<bool>& select_x ,
|
||||||
|
const vector<bool>& select_y ,
|
||||||
|
sparse_rc< vector<size_t> >& pattern_out )
|
||||||
|
// END_PROTOTYPE
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nr() == select_y.size() );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nc() == select_x.size() );
|
||||||
|
|
||||||
|
// count number of non-zeros
|
||||||
|
size_t nnz = jac_sparsity_.nnz();
|
||||||
|
size_t nr = jac_sparsity_.nr();
|
||||||
|
size_t nc = jac_sparsity_.nc();
|
||||||
|
const vector<size_t>& row = jac_sparsity_.row();
|
||||||
|
const vector<size_t>& col = jac_sparsity_.col();
|
||||||
|
size_t nnz_out = 0;
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
if( select_x[j] & select_y[i] )
|
||||||
|
++nnz_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the output sparsity pattern
|
||||||
|
pattern_out.resize(nr, nc, nnz_out);
|
||||||
|
size_t ell = 0;
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
if( select_x[j] & select_y[i] )
|
||||||
|
pattern_out.set(ell++, i, j);
|
||||||
|
}
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ell == nnz_out );
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_REV_DEPEND_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_REV_DEPEND_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two/rev_depend.hpp
|
||||||
|
Second generation checkpoint type computation.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from atomic_three to dependency calculation
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
is the value of the parameters in the corresponding function call
|
||||||
|
afun(ax, ay).
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
is the AD type for ax in the corresponding afun(ax, ay) call.
|
||||||
|
|
||||||
|
\param depend_x [out]
|
||||||
|
specifies which components of x affect the values of interest
|
||||||
|
|
||||||
|
\param depend_y [in]
|
||||||
|
specifies which components of y affect the vlaues of interest
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool chkpoint_two<Base>::rev_depend(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
vector<bool>& depend_x ,
|
||||||
|
const vector<bool>& depend_y )
|
||||||
|
{ size_t nc = jac_sparsity_.nc();
|
||||||
|
size_t nnz = jac_sparsity_.nnz();
|
||||||
|
const vector<size_t>& row( jac_sparsity_.row() );
|
||||||
|
const vector<size_t>& col( jac_sparsity_.col() );
|
||||||
|
//
|
||||||
|
CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nr() == depend_y.size() );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( jac_sparsity_.nc() == depend_x.size() );
|
||||||
|
//
|
||||||
|
// initialize depend_x as false
|
||||||
|
for(size_t j = 0; j < nc; ++j)
|
||||||
|
depend_x[j] = false;
|
||||||
|
//
|
||||||
|
// loop over entries in Dependency pattern
|
||||||
|
for(size_t k = 0; k < nnz; ++k)
|
||||||
|
{ size_t i = row[k];
|
||||||
|
size_t j = col[k];
|
||||||
|
if( depend_y[i] )
|
||||||
|
depend_x[j] = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
|
||||||
|
# endif
|
||||||
139
build-config/cppad/include/cppad/core/chkpoint_two/reverse.hpp
Normal file
139
build-config/cppad/include/cppad/core/chkpoint_two/reverse.hpp
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
# ifndef CPPAD_CORE_CHKPOINT_TWO_REVERSE_HPP
|
||||||
|
# define CPPAD_CORE_CHKPOINT_TWO_REVERSE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file chkpoint_two/reverse.hpp
|
||||||
|
Second generation checkpoint reverse mode.
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
Link from chkpoint_two to reverse mode
|
||||||
|
|
||||||
|
\param parameter_x [in]
|
||||||
|
contains the values, in afun(ax, ay), for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order Taylor coefficient aht we are computing derivative of
|
||||||
|
|
||||||
|
\param taylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param taylor_y [in]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
\param partial_x [out]
|
||||||
|
Partials w.r.t. the x Taylor coefficients.
|
||||||
|
|
||||||
|
\param partial_y [in]
|
||||||
|
Partials w.r.t. the y Taylor coefficients.
|
||||||
|
|
||||||
|
See the reverse mode in user's documentation for atomic_three
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool chkpoint_two<Base>::reverse(
|
||||||
|
const vector<Base>& parameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector<Base>& taylor_x ,
|
||||||
|
const vector<Base>& taylor_y ,
|
||||||
|
vector<Base>& partial_x ,
|
||||||
|
const vector<Base>& partial_y )
|
||||||
|
|
||||||
|
{ ADFun<Base>* g_ptr = &g_;
|
||||||
|
if( use_in_parallel_ )
|
||||||
|
{ size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
g_ptr = &(member_[thread]->g_);
|
||||||
|
}
|
||||||
|
# ifndef NDEBUG
|
||||||
|
else if( thread_alloc::in_parallel() )
|
||||||
|
{ std::string msg = atomic_three<Base>::atomic_name();
|
||||||
|
msg += ": use_in_parallel is false and in_parallel() is true";
|
||||||
|
CPPAD_ASSERT_KNOWN(false, msg.c_str() );
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
// compute forward mode Taylor coefficient orders 0 through order_up
|
||||||
|
# ifdef NDEBUG
|
||||||
|
g_ptr->Forward(order_up, taylor_x);
|
||||||
|
# else
|
||||||
|
vector<Base> check = g_ptr->Forward(order_up, taylor_x);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( taylor_y.size() == check.size() )
|
||||||
|
for(size_t i = 0; i < taylor_y.size(); ++i)
|
||||||
|
CPPAD_ASSERT_UNKNOWN( taylor_y[i] == check[i] );
|
||||||
|
# endif
|
||||||
|
// now can run reverse mode
|
||||||
|
partial_x = g_ptr->Reverse(order_up+1, partial_y);
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
Link from chkpoint_two to AD reverse mode
|
||||||
|
|
||||||
|
\param aparameter_x [in]
|
||||||
|
contains the values, in afun(ax, ay), for arguments that are parameters.
|
||||||
|
|
||||||
|
\param type_x [in]
|
||||||
|
what is the type, in afun(ax, ay), for each component of x.
|
||||||
|
|
||||||
|
\param order_up [in]
|
||||||
|
highest order Taylor coefficient aht we are computing derivative of
|
||||||
|
|
||||||
|
\param ataylor_x [in]
|
||||||
|
Taylor coefficients corresponding to x for this calculation.
|
||||||
|
|
||||||
|
\param ataylor_y [in]
|
||||||
|
Taylor coefficient corresponding to y for this calculation
|
||||||
|
|
||||||
|
\param apartial_x [out]
|
||||||
|
Partials w.r.t. the x Taylor coefficients.
|
||||||
|
|
||||||
|
\param apartial_y [in]
|
||||||
|
Partials w.r.t. the y Taylor coefficients.
|
||||||
|
|
||||||
|
See the reverse mode in user's documentation for atomic_three
|
||||||
|
*/
|
||||||
|
template <class Base>
|
||||||
|
bool chkpoint_two<Base>::reverse(
|
||||||
|
const vector< AD<Base> >& aparameter_x ,
|
||||||
|
const vector<ad_type_enum>& type_x ,
|
||||||
|
size_t order_up ,
|
||||||
|
const vector< AD<Base> >& ataylor_x ,
|
||||||
|
const vector< AD<Base> >& ataylor_y ,
|
||||||
|
vector< AD<Base> >& apartial_x ,
|
||||||
|
const vector< AD<Base> >& apartial_y )
|
||||||
|
{ ADFun< AD<Base>, Base >* ag_ptr = &ag_;
|
||||||
|
if( use_in_parallel_ )
|
||||||
|
{ size_t thread = thread_alloc::thread_num();
|
||||||
|
allocate_member(thread);
|
||||||
|
ag_ptr = &(member_[thread]->ag_);
|
||||||
|
}
|
||||||
|
// compute forward mode Taylor coefficient orders 0 through order_up
|
||||||
|
# ifdef NDEBUG
|
||||||
|
ag_ptr->Forward(order_up, ataylor_x);
|
||||||
|
# else
|
||||||
|
vector< AD<Base> > acheck = ag_ptr->Forward(order_up, ataylor_x);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ataylor_y.size() == acheck.size() )
|
||||||
|
for(size_t i = 0; i < ataylor_y.size(); ++i)
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ataylor_y[i] == acheck[i] );
|
||||||
|
# endif
|
||||||
|
// now can run reverse mode
|
||||||
|
apartial_x = ag_ptr->Reverse(order_up+1, apartial_y);
|
||||||
|
//
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
635
build-config/cppad/include/cppad/core/compare.hpp
Normal file
635
build-config/cppad/include/cppad/core/compare.hpp
Normal file
@@ -0,0 +1,635 @@
|
|||||||
|
# ifndef CPPAD_CORE_COMPARE_HPP
|
||||||
|
# define CPPAD_CORE_COMPARE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$begin Compare$$
|
||||||
|
$spell
|
||||||
|
cos
|
||||||
|
Op
|
||||||
|
bool
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Binary Comparison Operators$$
|
||||||
|
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$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_);
|
||||||
|
//
|
||||||
|
// check if we are recording compare operators
|
||||||
|
local::ADTape<Base> *tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape == nullptr )
|
||||||
|
return result;
|
||||||
|
if( ! tape->Rec_.get_record_compare() )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = left.tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (left.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (left.ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"< : AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
if( var_left )
|
||||||
|
{ if( var_right )
|
||||||
|
{ // variable < variable
|
||||||
|
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
|
||||||
|
{ // variable < parameter
|
||||||
|
addr_t p = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(right.value_);
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LtvpOp);
|
||||||
|
tape->Rec_.PutArg(left.taddr_, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LepvOp);
|
||||||
|
tape->Rec_.PutArg(p, left.taddr_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( var_right )
|
||||||
|
{ // parameter < variable
|
||||||
|
addr_t p = left.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LtpvOp);
|
||||||
|
tape->Rec_.PutArg(p, right.taddr_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LevpOp);
|
||||||
|
tape->Rec_.PutArg(right.taddr_, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ // parameter < parameter
|
||||||
|
addr_t arg0 = left.taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LtppOp);
|
||||||
|
tape->Rec_.PutArg(arg0, arg1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LeppOp);
|
||||||
|
tape->Rec_.PutArg(arg1, 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_);
|
||||||
|
//
|
||||||
|
// check if we are recording compare operators
|
||||||
|
local::ADTape<Base> *tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape == nullptr )
|
||||||
|
return result;
|
||||||
|
if( ! tape->Rec_.get_record_compare() )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = left.tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (left.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (left.ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"<= : AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
if( var_left )
|
||||||
|
{ if( var_right )
|
||||||
|
{ // variable <= variable
|
||||||
|
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
|
||||||
|
{ // variable <= parameter
|
||||||
|
addr_t p = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(right.value_);
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LevpOp);
|
||||||
|
tape->Rec_.PutArg(left.taddr_, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LtpvOp);
|
||||||
|
tape->Rec_.PutArg(p, left.taddr_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( var_right )
|
||||||
|
{ // parameter <= variable
|
||||||
|
addr_t p = left.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LepvOp);
|
||||||
|
tape->Rec_.PutArg(p, right.taddr_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LtvpOp);
|
||||||
|
tape->Rec_.PutArg(right.taddr_, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ // parameter <= parameter
|
||||||
|
addr_t arg0 = left.taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LeppOp);
|
||||||
|
tape->Rec_.PutArg(arg0, arg1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LtppOp);
|
||||||
|
tape->Rec_.PutArg(arg1, 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_);
|
||||||
|
//
|
||||||
|
// check if we are recording compare operators
|
||||||
|
local::ADTape<Base> *tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape == nullptr )
|
||||||
|
return result;
|
||||||
|
if( ! tape->Rec_.get_record_compare() )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = left.tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (left.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (left.ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"> : AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
if( var_left )
|
||||||
|
{ if( var_right )
|
||||||
|
{ // variable > variable
|
||||||
|
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
|
||||||
|
{ // variable > parameter
|
||||||
|
addr_t p = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(right.value_);
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LtpvOp);
|
||||||
|
tape->Rec_.PutArg(p, left.taddr_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LevpOp);
|
||||||
|
tape->Rec_.PutArg(left.taddr_, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( var_right )
|
||||||
|
{ // parameter > variable
|
||||||
|
addr_t p = left.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LtvpOp);
|
||||||
|
tape->Rec_.PutArg(right.taddr_, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LepvOp);
|
||||||
|
tape->Rec_.PutArg(p, right.taddr_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ // parameter > parameter
|
||||||
|
addr_t arg0 = left.taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LtppOp);
|
||||||
|
tape->Rec_.PutArg(arg1, arg0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LeppOp);
|
||||||
|
tape->Rec_.PutArg(arg0, arg1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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_);
|
||||||
|
//
|
||||||
|
// check if we are recording compare operators
|
||||||
|
local::ADTape<Base> *tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape == nullptr )
|
||||||
|
return result;
|
||||||
|
if( ! tape->Rec_.get_record_compare() )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = left.tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (left.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (left.ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
">= : AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
if( var_left )
|
||||||
|
{ if( var_right )
|
||||||
|
{ // variable >= variable
|
||||||
|
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
|
||||||
|
{ // variable >= parameter
|
||||||
|
addr_t p = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(right.value_);
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LepvOp);
|
||||||
|
tape->Rec_.PutArg(p, left.taddr_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LtvpOp);
|
||||||
|
tape->Rec_.PutArg(left.taddr_, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( var_right )
|
||||||
|
{ // parameter >= variable
|
||||||
|
addr_t p = left.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LevpOp);
|
||||||
|
tape->Rec_.PutArg(right.taddr_, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LtpvOp);
|
||||||
|
tape->Rec_.PutArg(p, right.taddr_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ // parameter >= parameter
|
||||||
|
addr_t arg0 = left.taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
if( result )
|
||||||
|
{ tape->Rec_.PutOp(local::LeppOp);
|
||||||
|
tape->Rec_.PutArg(arg1, arg0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ tape->Rec_.PutOp(local::LtppOp);
|
||||||
|
tape->Rec_.PutArg(arg0, arg1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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_);
|
||||||
|
//
|
||||||
|
// check if we are recording compare operators
|
||||||
|
local::ADTape<Base> *tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape == nullptr )
|
||||||
|
return result;
|
||||||
|
if( ! tape->Rec_.get_record_compare() )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = left.tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (left.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (left.ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"==: AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
//
|
||||||
|
tape->Rec_.comp_eq(
|
||||||
|
var_left, var_right, dyn_left, dyn_right, left, right, result
|
||||||
|
);
|
||||||
|
//
|
||||||
|
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_);
|
||||||
|
//
|
||||||
|
// check if we are recording compare operators
|
||||||
|
local::ADTape<Base> *tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape == nullptr )
|
||||||
|
return result;
|
||||||
|
if( ! tape->Rec_.get_record_compare() )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = left.tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (left.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (left.ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"!=: AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
if( var_left )
|
||||||
|
{ if( var_right )
|
||||||
|
{ // variable == variable
|
||||||
|
tape->Rec_.PutArg(left.taddr_, right.taddr_);
|
||||||
|
if( result )
|
||||||
|
tape->Rec_.PutOp(local::NevvOp);
|
||||||
|
else
|
||||||
|
tape->Rec_.PutOp(local::EqvvOp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // variable == parameter
|
||||||
|
addr_t p = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(right.value_);
|
||||||
|
tape->Rec_.PutArg(p, left.taddr_);
|
||||||
|
if( result )
|
||||||
|
tape->Rec_.PutOp(local::NepvOp);
|
||||||
|
else
|
||||||
|
tape->Rec_.PutOp(local::EqpvOp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( var_right )
|
||||||
|
{ // parameter == variable
|
||||||
|
addr_t p = left.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(left.value_);
|
||||||
|
tape->Rec_.PutArg(p, right.taddr_);
|
||||||
|
if( result )
|
||||||
|
tape->Rec_.PutOp(local::NepvOp);
|
||||||
|
else
|
||||||
|
tape->Rec_.PutOp(local::EqpvOp);
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ // parameter == parameter
|
||||||
|
addr_t arg0 = left.taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
tape->Rec_.PutArg(arg0, arg1);
|
||||||
|
if( result )
|
||||||
|
tape->Rec_.PutOp(local::NeppOp);
|
||||||
|
else
|
||||||
|
tape->Rec_.PutOp(local::EqppOp);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
// convert other cases into the case above
|
||||||
|
CPPAD_FOLD_BOOL_VALUED_BINARY_OPERATOR(!=)
|
||||||
|
|
||||||
|
} // END CppAD namespace
|
||||||
|
|
||||||
|
# endif
|
||||||
141
build-config/cppad/include/cppad/core/compound_assign.hpp
Normal file
141
build-config/cppad/include/cppad/core/compound_assign.hpp
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
# ifndef CPPAD_CORE_COMPOUND_ASSIGN_HPP
|
||||||
|
# define CPPAD_CORE_COMPOUND_ASSIGN_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$begin compound_assign$$
|
||||||
|
$spell
|
||||||
|
Op
|
||||||
|
VecAD
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section AD Compound Assignment Operators$$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$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_base/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
|
||||||
186
build-config/cppad/include/cppad/core/con_dyn_var.hpp
Normal file
186
build-config/cppad/include/cppad/core/con_dyn_var.hpp
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
# ifndef CPPAD_CORE_CON_DYN_VAR_HPP
|
||||||
|
# define CPPAD_CORE_CON_DYN_VAR_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
$begin con_dyn_var$$
|
||||||
|
$spell
|
||||||
|
VecAD
|
||||||
|
const
|
||||||
|
bool
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Constant, Dynamic, Parameter, and Variable$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%b% = Constant(%x%)
|
||||||
|
%$$
|
||||||
|
$icode%b% = Dynamic(%x%)
|
||||||
|
%$$
|
||||||
|
$icode%b% = Parameter(%x%)
|
||||||
|
%$$
|
||||||
|
$icode%b% = Variable(%x%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$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%
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Constant$$
|
||||||
|
The return value for $code Constant$$ is true
|
||||||
|
is true if and only if $icode x$$ is
|
||||||
|
a $cref/constant/glossary/Parameter/Constant/$$ parameter.
|
||||||
|
A $cref/VecAD<Base>/VecAD/$$ object is a constant parameter
|
||||||
|
if no element of the vector depends on the independent variables.
|
||||||
|
|
||||||
|
$head Dynamic$$
|
||||||
|
The return value for $code Dynamic$$ is true
|
||||||
|
is true if and only if $icode x$$ is
|
||||||
|
a $cref/dynamic/glossary/Parameter/Dynamic/$$ parameter.
|
||||||
|
No element of a $cref/VecAD<Base>/VecAD/$$ object
|
||||||
|
can depend on the dynamic parameters and this function returns false
|
||||||
|
for these objects.
|
||||||
|
|
||||||
|
$head Parameter$$
|
||||||
|
The return value for $code Parameter$$ is true
|
||||||
|
is true if and only if $icode x$$ is
|
||||||
|
a $cref/parameter/glossary/Parameter/$$.
|
||||||
|
A $cref/VecAD<Base>/VecAD/$$ object is a parameter
|
||||||
|
if no element of the vector depends on the independent variables.
|
||||||
|
|
||||||
|
$head Variable$$
|
||||||
|
The return value for $code Variable$$ is true
|
||||||
|
is true if and only if $icode x$$ is
|
||||||
|
a $cref/variable/glossary/Variable/$$.
|
||||||
|
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/con_dyn_var.cpp
|
||||||
|
%$$
|
||||||
|
The file
|
||||||
|
$cref con_dyn_var.cpp$$
|
||||||
|
contains an example and test of these functions.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CppAD {
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Constant
|
||||||
|
template <class Base>
|
||||||
|
bool Constant(const AD<Base> &x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( x.tape_id_== 0 || x.ad_type_ != constant_enum );
|
||||||
|
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>
|
||||||
|
bool Constant(const VecAD<Base> &x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( x.tape_id_== 0 || x.ad_type_ != constant_enum );
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Dynamic
|
||||||
|
template <class Base>
|
||||||
|
bool Dynamic(const AD<Base> &x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( x.tape_id_ == 0 || x.ad_type_ != constant_enum );
|
||||||
|
if( (x.tape_id_ == 0) | (x.ad_type_ != dynamic_enum) )
|
||||||
|
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>
|
||||||
|
bool Dynamic(const VecAD<Base> &x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( x.tape_id_ == 0 || x.ad_type_ != constant_enum );
|
||||||
|
if( (x.tape_id_ == 0) | (x.ad_type_ != dynamic_enum) )
|
||||||
|
return false;
|
||||||
|
//
|
||||||
|
size_t thread = size_t(x.tape_id_ % CPPAD_MAX_NUM_THREADS);
|
||||||
|
return x.tape_id_ == *AD<Base>::tape_id_ptr(thread);
|
||||||
|
}
|
||||||
|
// -----------------------------------------------------------------------
|
||||||
|
// Parameter
|
||||||
|
template <class Base>
|
||||||
|
bool Parameter(const AD<Base> &x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( x.tape_id_ == 0 || x.ad_type_ != constant_enum );
|
||||||
|
if( (x.tape_id_ == 0) | (x.ad_type_ == dynamic_enum) )
|
||||||
|
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>
|
||||||
|
bool Parameter(const VecAD<Base> &x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( x.tape_id_ == 0 || x.ad_type_ != constant_enum );
|
||||||
|
if( (x.tape_id_ == 0) | (x.ad_type_ == dynamic_enum) )
|
||||||
|
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>
|
||||||
|
bool Variable(const AD<Base> &x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( x.tape_id_ == 0 || x.ad_type_ != constant_enum );
|
||||||
|
if( (x.tape_id_ == 0) | (x.ad_type_ != variable_enum) )
|
||||||
|
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>
|
||||||
|
bool Variable(const VecAD<Base> &x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN( x.tape_id_ == 0 || x.ad_type_ != constant_enum );
|
||||||
|
if( (x.tape_id_ == 0) | (x.ad_type_ != variable_enum) )
|
||||||
|
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
|
||||||
276
build-config/cppad/include/cppad/core/cond_exp.hpp
Normal file
276
build-config/cppad/include/cppad/core/cond_exp.hpp
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
# ifndef CPPAD_CORE_COND_EXP_HPP
|
||||||
|
# define CPPAD_CORE_COND_EXP_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
$begin CondExp$$
|
||||||
|
$spell
|
||||||
|
Atan2
|
||||||
|
CondExp
|
||||||
|
Taylor
|
||||||
|
std
|
||||||
|
Cpp
|
||||||
|
namespace
|
||||||
|
inline
|
||||||
|
const
|
||||||
|
abs
|
||||||
|
Rel
|
||||||
|
bool
|
||||||
|
Lt
|
||||||
|
Le
|
||||||
|
Eq
|
||||||
|
Ge
|
||||||
|
Gt
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section AD Conditional Expressions$$
|
||||||
|
|
||||||
|
$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.
|
||||||
|
|
||||||
|
$head Atan2$$
|
||||||
|
The following implementation of the
|
||||||
|
AD $cref atan2$$ function is a more complex
|
||||||
|
example of using conditional expressions:
|
||||||
|
$srcfile%include/cppad/core/atan2.hpp%0%BEGIN CondExp%// END CondExp%$$
|
||||||
|
|
||||||
|
|
||||||
|
$end
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
// BEGIN CppAD namespace
|
||||||
|
namespace CppAD {
|
||||||
|
|
||||||
|
template <class Base>
|
||||||
|
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> result;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( Parameter(result) );
|
||||||
|
|
||||||
|
// check first case where do not need to tape
|
||||||
|
if( IdenticalCon(left) & IdenticalCon(right) )
|
||||||
|
{ switch( cop )
|
||||||
|
{
|
||||||
|
case CompareLt:
|
||||||
|
if( left.value_ < right.value_ )
|
||||||
|
result = if_true;
|
||||||
|
else
|
||||||
|
result = if_false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CompareLe:
|
||||||
|
if( left.value_ <= right.value_ )
|
||||||
|
result = if_true;
|
||||||
|
else
|
||||||
|
result = if_false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CompareEq:
|
||||||
|
if( left.value_ == right.value_ )
|
||||||
|
result = if_true;
|
||||||
|
else
|
||||||
|
result = if_false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CompareGe:
|
||||||
|
if( left.value_ >= right.value_ )
|
||||||
|
result = if_true;
|
||||||
|
else
|
||||||
|
result = if_false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CompareGt:
|
||||||
|
if( left.value_ > right.value_ )
|
||||||
|
result = if_true;
|
||||||
|
else
|
||||||
|
result = if_false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
CPPAD_ASSERT_UNKNOWN(0);
|
||||||
|
result = if_true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must use CondExp in case Base is an AD type and recording
|
||||||
|
result.value_ = CondExpOp(cop,
|
||||||
|
left.value_, right.value_, if_true.value_, if_false.value_);
|
||||||
|
|
||||||
|
local::ADTape<Base> *tape = AD<Base>::tape_ptr();
|
||||||
|
|
||||||
|
// add this operation to the tape
|
||||||
|
if( tape != nullptr ) tape->Rec_.cond_exp(
|
||||||
|
tape->id_, cop, result, left, right, if_true, if_false
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------ 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
|
||||||
50
build-config/cppad/include/cppad/core/convert.hpp
Normal file
50
build-config/cppad/include/cppad/core/convert.hpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# 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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin Convert$$
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section Conversion and I/O of AD Objects$$
|
||||||
|
|
||||||
|
$children%
|
||||||
|
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
|
||||||
|
%$$
|
||||||
|
$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
|
||||||
188
build-config/cppad/include/cppad/core/cppad_assert.hpp
Normal file
188
build-config/cppad/include/cppad/core/cppad_assert.hpp
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
# ifndef CPPAD_CORE_CPPAD_ASSERT_HPP
|
||||||
|
# define CPPAD_CORE_CPPAD_ASSERT_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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$$
|
||||||
|
|
||||||
|
$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 exp is true, if not print msg and terminate execution.
|
||||||
|
|
||||||
|
The C++ expression exp is expected to be true.
|
||||||
|
If it is false,
|
||||||
|
the CppAD use has made an error that is described by msg.
|
||||||
|
If the preprocessor symbol NDEBUG is not defined,
|
||||||
|
and 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 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 exp is true, if not terminate execution.
|
||||||
|
|
||||||
|
The C++ expression 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 NDEBUG is not defined,
|
||||||
|
and 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 op has the specified number of of arguments and results.
|
||||||
|
|
||||||
|
If 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 NDEBUG is defined, this macro has no effect
|
||||||
|
(not even the definition of (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
|
||||||
|
|
||||||
|
# endif
|
||||||
334
build-config/cppad/include/cppad/core/dependent.hpp
Normal file
334
build-config/cppad/include/cppad/core/dependent.hpp
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
# ifndef CPPAD_CORE_DEPENDENT_HPP
|
||||||
|
# define CPPAD_CORE_DEPENDENT_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$begin Dependent$$
|
||||||
|
$spell
|
||||||
|
alloc
|
||||||
|
num
|
||||||
|
taylor_
|
||||||
|
ADvector
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Stop Recording and Store Operation Sequence$$
|
||||||
|
|
||||||
|
|
||||||
|
$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{R}^n \rightarrow \B{R}^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.
|
||||||
|
|
||||||
|
$end
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// BEGIN CppAD namespace
|
||||||
|
namespace CppAD {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file dependent.hpp
|
||||||
|
Different versions of Dependent function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Determine the 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 <class Base, class RecBase>
|
||||||
|
template <class ADvector>
|
||||||
|
void ADFun<Base,RecBase>::Dependent(const ADvector &y)
|
||||||
|
{ local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
tape != nullptr,
|
||||||
|
"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 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 <class Base, class RecBase>
|
||||||
|
template <class ADvector>
|
||||||
|
void ADFun<Base,RecBase>::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 <class Base, class RecBase>
|
||||||
|
template <class ADvector>
|
||||||
|
void ADFun<Base,RecBase>::Dependent(local::ADTape<Base> *tape, const ADvector &y)
|
||||||
|
{
|
||||||
|
size_t m = y.size();
|
||||||
|
size_t n = tape->size_independent_;
|
||||||
|
|
||||||
|
// 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(size_t i = 0; i < m; i++)
|
||||||
|
{ dep_parameter_[i] = CppAD::Parameter(y[i]);
|
||||||
|
addr_t y_taddr;
|
||||||
|
if( dep_parameter_[i] )
|
||||||
|
{ // make a tape copy of dependent variables that are parameters,
|
||||||
|
y_taddr = tape->RecordParOp( y[i] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
y_taddr = y[i].taddr_;
|
||||||
|
|
||||||
|
CPPAD_ASSERT_UNKNOWN( y_taddr > 0 );
|
||||||
|
dep_taddr_[i] = size_t( y_taddr );
|
||||||
|
}
|
||||||
|
|
||||||
|
// put an EndOp at the end of the tape
|
||||||
|
tape->Rec_.PutOp(local::EndOp);
|
||||||
|
|
||||||
|
// bool values in this object except check_for_nan_
|
||||||
|
has_been_optimized_ = false;
|
||||||
|
//
|
||||||
|
// size_t values in this object
|
||||||
|
compare_change_count_ = 1;
|
||||||
|
compare_change_number_ = 0;
|
||||||
|
compare_change_op_index_ = 0;
|
||||||
|
num_order_taylor_ = 0;
|
||||||
|
cap_order_taylor_ = 0;
|
||||||
|
num_direction_taylor_ = 0;
|
||||||
|
num_var_tape_ = tape->Rec_.num_var_rec();
|
||||||
|
|
||||||
|
// taylor_
|
||||||
|
taylor_.resize(0);
|
||||||
|
|
||||||
|
// cskip_op_
|
||||||
|
cskip_op_.resize( tape->Rec_.num_op_rec() );
|
||||||
|
|
||||||
|
// load_op2var_
|
||||||
|
load_op2var_.resize( tape->Rec_.num_var_load_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 recording; i.e. ERASE Rec_.
|
||||||
|
play_.get_recording(tape->Rec_, n);
|
||||||
|
|
||||||
|
// 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(size_t 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);
|
||||||
|
|
||||||
|
// resize subgraph_info_
|
||||||
|
subgraph_info_.resize(
|
||||||
|
ind_taddr_.size(), // n_dep
|
||||||
|
dep_taddr_.size(), // n_ind
|
||||||
|
play_.num_op_rec(), // n_op
|
||||||
|
play_.num_var_rec() // n_var
|
||||||
|
);
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// End set ad_fun.hpp private member data
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
// now we can delete the tape
|
||||||
|
AD<Base>::tape_manage(delete_tape_manage);
|
||||||
|
|
||||||
|
// 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
|
||||||
22
build-config/cppad/include/cppad/core/discrete/devel.omh
Normal file
22
build-config/cppad/include/cppad/core/discrete/devel.omh
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
$begin devel_discrete$$
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Developer Documentation for Discrete Function$$
|
||||||
|
|
||||||
|
$childtable%
|
||||||
|
include/cppad/core/discrete/discrete.hpp
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$end
|
||||||
334
build-config/cppad/include/cppad/core/discrete/discrete.hpp
Normal file
334
build-config/cppad/include/cppad/core/discrete/discrete.hpp
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
# ifndef CPPAD_CORE_DISCRETE_DISCRETE_HPP
|
||||||
|
# define CPPAD_CORE_DISCRETE_DISCRETE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
# 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
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin discrete_create$$
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
$section Create a Discrete AD Function$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$codei%CPPAD_DISCRETE_FUNCTION(%Base%, %name%)
|
||||||
|
%$$
|
||||||
|
$icode%name(%ax%, %ay%)
|
||||||
|
%$$
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
is the base type for the discrete function.
|
||||||
|
|
||||||
|
$head name$$
|
||||||
|
is the name of the user defined function that corresponding to this operation.
|
||||||
|
|
||||||
|
$head ax$$
|
||||||
|
Is a $codei%AD<%Base%>%$$ corresponding to the argument for the function.
|
||||||
|
|
||||||
|
$head ay$$
|
||||||
|
Is a $codei%AD<%Base%>%$$ corresponding to the result for the function.
|
||||||
|
|
||||||
|
$head fun$$
|
||||||
|
The local object $code fun$$ is a member of the $code discrete$$ class.
|
||||||
|
|
||||||
|
$head Source Code$$
|
||||||
|
$srccode%hpp% */
|
||||||
|
# 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
|
||||||
|
/* %$$
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
$begin discrete_class$$
|
||||||
|
|
||||||
|
$section Declare discrete Class and Member Data$$
|
||||||
|
|
||||||
|
$head parallel_ad$$
|
||||||
|
is a friend of this class so it can call List to initialize
|
||||||
|
its static data.
|
||||||
|
|
||||||
|
$head F$$
|
||||||
|
is the type for the user routine that computes $icode Base$$ function values.
|
||||||
|
|
||||||
|
$head name_$$
|
||||||
|
name of this user defined discrete function.
|
||||||
|
|
||||||
|
$head f_$$
|
||||||
|
user routine that computes $icode Base$$ function values.
|
||||||
|
|
||||||
|
$head index_$$
|
||||||
|
index of this object in $cref discrete_list$$ for this $icode Base$$.
|
||||||
|
|
||||||
|
$head Source Code$$
|
||||||
|
$srccode%hpp% */
|
||||||
|
template <class Base>
|
||||||
|
class discrete {
|
||||||
|
private:
|
||||||
|
template <class Type> friend void parallel_ad(void);
|
||||||
|
typedef Base (*F) (const Base& x);
|
||||||
|
const std::string name_;
|
||||||
|
const F f_;
|
||||||
|
const size_t index_;
|
||||||
|
/* %$$
|
||||||
|
$end
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin discrete_list$$
|
||||||
|
$spell
|
||||||
|
alloc
|
||||||
|
std
|
||||||
|
CppAD
|
||||||
|
$$
|
||||||
|
$section List of all objects in the discrete class$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%list% = discrete<%Base%>::List()%$$
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
Is the $cref/Base/discrete_create/Base/$$
|
||||||
|
type for this list of discrete functions.
|
||||||
|
|
||||||
|
$head list$$
|
||||||
|
is a reference to the list of all the
|
||||||
|
$code discrete$$ object currently defined.
|
||||||
|
|
||||||
|
$subhead std::vector$$
|
||||||
|
We use $code std::vector$$ instead of $code CppAD::vector$$
|
||||||
|
so it does not appear that there is a $cref memory_leak$$
|
||||||
|
this list is not destroyed before
|
||||||
|
$cref/thread_alloc::free_all/ta_free_all/$$ is called by testing routines.
|
||||||
|
|
||||||
|
$head Source Code$$
|
||||||
|
$srccode%hpp% */
|
||||||
|
private:
|
||||||
|
static std::vector<discrete *>& List(void)
|
||||||
|
{ CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
|
||||||
|
static std::vector<discrete *> list;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
/* %$$
|
||||||
|
$end
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin discrete_list_size$$
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
$section Size of the Discrete Function List$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%size% = discrete<%Base%>::list_size()%$$
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
Is the $cref/Base/discrete_create/Base/$$
|
||||||
|
type for this list of discrete functions.
|
||||||
|
|
||||||
|
$head size$$
|
||||||
|
is the number of discrete functions for this $icode Base$$ type.
|
||||||
|
|
||||||
|
$head Source Code$$
|
||||||
|
$srccode%hpp% */
|
||||||
|
public:
|
||||||
|
static size_t list_size(void)
|
||||||
|
{ return List().size(); }
|
||||||
|
/* %$$
|
||||||
|
$end
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin discrete_ctor$$
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
$section Constructor Called by each Use of CPPAD_DISCRETE_FUNCTION$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$codei%discrete<%Base%> %fun%(%name%, %f%)%$$
|
||||||
|
|
||||||
|
$head name$$
|
||||||
|
is the name of this function.
|
||||||
|
|
||||||
|
$head f$$
|
||||||
|
user routine that implements this function for Base class.
|
||||||
|
|
||||||
|
$head fun$$
|
||||||
|
is the $code discrete$$ object created by this call to the constructor.
|
||||||
|
|
||||||
|
$subhead name_$$
|
||||||
|
is set equal to $icode name$$.
|
||||||
|
|
||||||
|
$subhead f_$$
|
||||||
|
is set equal to $icode f$$.
|
||||||
|
|
||||||
|
$subhead index_$$
|
||||||
|
This object is put at the end of $cref discrete_list$$ and $code index_$$
|
||||||
|
is set to the index of this object in the discrete list.
|
||||||
|
|
||||||
|
$head Parallel$$
|
||||||
|
This constructor cannot be used in parallel mode because it changes
|
||||||
|
the static object returned by $cref discrete_list$$.
|
||||||
|
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
public:
|
||||||
|
discrete(const char* name, F f) :
|
||||||
|
name_(name), f_(f) , index_( List().size() )
|
||||||
|
{ std::string msg = "discrete: first call to the discrete function ";
|
||||||
|
msg += name;
|
||||||
|
msg += " is in parallel mode.";
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
! thread_alloc::in_parallel() ,
|
||||||
|
msg.c_str()
|
||||||
|
);
|
||||||
|
List().push_back(this);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin discrete_ad$$
|
||||||
|
$spell
|
||||||
|
$$
|
||||||
|
$section Implement AD Version of a Discrete Function$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%ay% = %fun%.ad(%ax)%$$
|
||||||
|
|
||||||
|
$head ax$$
|
||||||
|
is the argument for the AD version of this function.
|
||||||
|
|
||||||
|
$head ay$$
|
||||||
|
is the return value for the AD version of this function.
|
||||||
|
|
||||||
|
$head Prototype$$
|
||||||
|
$srccode%hpp% */
|
||||||
|
AD<Base> ad(const AD<Base> &ax) const
|
||||||
|
/* %$$
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
size_t( std::numeric_limits<addr_t>::max() ) >= index_,
|
||||||
|
"discrete: cppad_tape_addr_type maximum not large enough"
|
||||||
|
);
|
||||||
|
//
|
||||||
|
AD<Base> ay;
|
||||||
|
ay.value_ = f_(ax.value_);
|
||||||
|
//
|
||||||
|
// check if there is a recording in progress
|
||||||
|
local::ADTape<Base>* tape = AD<Base>::tape_ptr();
|
||||||
|
if( tape == nullptr )
|
||||||
|
return ay;
|
||||||
|
//
|
||||||
|
// check if argument is a constant parameter
|
||||||
|
if( ax.tape_id_ != tape->id_ )
|
||||||
|
return ay;
|
||||||
|
//
|
||||||
|
if( ax.ad_type_ == dynamic_enum )
|
||||||
|
{
|
||||||
|
// tape dynamic paramter operation
|
||||||
|
ay.taddr_ = tape->Rec_.put_dyn_par(
|
||||||
|
ay.value_, local::dis_dyn, addr_t(index_), ax.taddr_
|
||||||
|
);
|
||||||
|
ay.tape_id_ = ax.tape_id_;
|
||||||
|
ay.ad_type_ = dynamic_enum;
|
||||||
|
|
||||||
|
// make result a dynamic parameter
|
||||||
|
ay.tape_id_ = tape->id_;
|
||||||
|
ay.ad_type_ = dynamic_enum;
|
||||||
|
|
||||||
|
CPPAD_ASSERT_UNKNOWN( Dynamic(ay) );
|
||||||
|
}
|
||||||
|
else if( ax.ad_type_ == variable_enum )
|
||||||
|
{
|
||||||
|
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(
|
||||||
|
size_t( 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_;
|
||||||
|
ay.ad_type_ = variable_enum;
|
||||||
|
|
||||||
|
CPPAD_ASSERT_UNKNOWN( Variable(ay) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // other types not yet being used and should have this tape id
|
||||||
|
CPPAD_ASSERT_UNKNOWN(false);
|
||||||
|
}
|
||||||
|
return ay;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin discrete_name$$
|
||||||
|
|
||||||
|
$section Name Corresponding to a discrete Function$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$codei%discrete<%Base%>::name(%index%)%$$
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
Is the $cref/Base/discrete_create/Base/$$
|
||||||
|
type for this list of discrete functions.
|
||||||
|
|
||||||
|
$head index$$
|
||||||
|
Is the index, in the list, for this discrete function.
|
||||||
|
|
||||||
|
$head Source Code$$
|
||||||
|
$srccode%hpp% */
|
||||||
|
static const char* name(size_t index)
|
||||||
|
{ return List()[index]->name_.c_str(); }
|
||||||
|
/* %$$
|
||||||
|
$end
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin discrete_eval$$
|
||||||
|
$spell
|
||||||
|
eval
|
||||||
|
$$
|
||||||
|
$section Link From Forward Mode Sweep to Users Routine$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%y% = discrete<%Base%>::eval(%index%, %x%)%$$
|
||||||
|
|
||||||
|
$head Base$$
|
||||||
|
Is the $cref/Base/discrete_create/Base/$$
|
||||||
|
type for this list of discrete functions.
|
||||||
|
|
||||||
|
$head index$$
|
||||||
|
index for this function in $cref discrete_list$$.
|
||||||
|
|
||||||
|
$head x$$
|
||||||
|
argument at which to evaluate $icode Base$$ version of this function.
|
||||||
|
|
||||||
|
$head y$$
|
||||||
|
result for the $icode Base$$ version of this function.
|
||||||
|
|
||||||
|
$head Source Code$$
|
||||||
|
$srccode%hpp% */
|
||||||
|
static Base eval(size_t index, const Base& x)
|
||||||
|
{ CPPAD_ASSERT_UNKNOWN(index < List().size() );
|
||||||
|
return List()[index]->f_(x);
|
||||||
|
}
|
||||||
|
/* %$$
|
||||||
|
$end
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
146
build-config/cppad/include/cppad/core/discrete/user.omh
Normal file
146
build-config/cppad/include/cppad/core/discrete/user.omh
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin Discrete$$
|
||||||
|
$spell
|
||||||
|
retaping
|
||||||
|
namespace
|
||||||
|
std
|
||||||
|
Eq
|
||||||
|
Cpp
|
||||||
|
const
|
||||||
|
inline
|
||||||
|
Geq
|
||||||
|
$$
|
||||||
|
|
||||||
|
$section Discrete AD Functions$$
|
||||||
|
|
||||||
|
|
||||||
|
$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%
|
||||||
|
%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
|
||||||
130
build-config/cppad/include/cppad/core/div.hpp
Normal file
130
build-config/cppad/include/cppad/core/div.hpp
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
# ifndef CPPAD_CORE_DIV_HPP
|
||||||
|
# define CPPAD_CORE_DIV_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// 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 == nullptr )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = left.tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (left.ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (left.ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"Divide: AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
if( var_left )
|
||||||
|
{ if( var_right )
|
||||||
|
{ // result = 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(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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
else if( (! dyn_right) & 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 = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( var_right )
|
||||||
|
{ if( (! dyn_left) & 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 = left.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(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;
|
||||||
|
result.ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ addr_t arg0 = left.taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left.value_);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
// parameters with a dynamic parameter result
|
||||||
|
result.taddr_ = tape->Rec_.put_dyn_par(
|
||||||
|
result.value_, local::div_dyn, arg0, arg1
|
||||||
|
);
|
||||||
|
result.tape_id_ = tape_id;
|
||||||
|
result.ad_type_ = dynamic_enum;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert other cases into the case above
|
||||||
|
CPPAD_FOLD_AD_VALUED_BINARY_OPERATOR(/)
|
||||||
|
|
||||||
|
|
||||||
|
} // END CppAD namespace
|
||||||
|
|
||||||
|
# endif
|
||||||
129
build-config/cppad/include/cppad/core/div_eq.hpp
Normal file
129
build-config/cppad/include/cppad/core/div_eq.hpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# ifndef CPPAD_CORE_DIV_EQ_HPP
|
||||||
|
# define CPPAD_CORE_DIV_EQ_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-20 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// 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 == nullptr )
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// check if left and right tapes match
|
||||||
|
bool match_left = tape_id_ == tape_id;
|
||||||
|
bool match_right = right.tape_id_ == tape_id;
|
||||||
|
|
||||||
|
// check if left and right are dynamic parameters
|
||||||
|
bool dyn_left = match_left & (ad_type_ == dynamic_enum);
|
||||||
|
bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);
|
||||||
|
|
||||||
|
// check if left and right are variables
|
||||||
|
bool var_left = match_left & (ad_type_ != dynamic_enum);
|
||||||
|
bool var_right = match_right & (right.ad_type_ != dynamic_enum);
|
||||||
|
|
||||||
|
CPPAD_ASSERT_KNOWN(
|
||||||
|
tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
|
||||||
|
"/= : AD variables or dynamic parameters on different threads."
|
||||||
|
);
|
||||||
|
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);
|
||||||
|
// check that this is a variable
|
||||||
|
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);
|
||||||
|
}
|
||||||
|
else if( (! dyn_right) & 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 = right.taddr_;
|
||||||
|
if( ! dyn_right )
|
||||||
|
p = tape->Rec_.put_con_par(right.value_);
|
||||||
|
tape->Rec_.PutArg(taddr_, p);
|
||||||
|
// put operator in the tape
|
||||||
|
taddr_ = tape->Rec_.PutOp(local::DivvpOp);
|
||||||
|
// check that this is a variable
|
||||||
|
CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ad_type_ == variable_enum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( var_right )
|
||||||
|
{ if( (! dyn_left) & 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 = taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
p = tape->Rec_.put_con_par(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;
|
||||||
|
ad_type_ = variable_enum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( dyn_left | dyn_right )
|
||||||
|
{ addr_t arg0 = taddr_;
|
||||||
|
addr_t arg1 = right.taddr_;
|
||||||
|
if( ! dyn_left )
|
||||||
|
arg0 = tape->Rec_.put_con_par(left);
|
||||||
|
if( ! dyn_right )
|
||||||
|
arg1 = tape->Rec_.put_con_par(right.value_);
|
||||||
|
//
|
||||||
|
// parameters with a dynamic parameter results
|
||||||
|
taddr_ = tape->Rec_.put_dyn_par(
|
||||||
|
value_, local::div_dyn, arg0, arg1
|
||||||
|
);
|
||||||
|
tape_id_ = tape_id;
|
||||||
|
ad_type_ = dynamic_enum;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPPAD_FOLD_ASSIGNMENT_OPERATOR(/=)
|
||||||
|
|
||||||
|
} // END CppAD namespace
|
||||||
|
|
||||||
|
# endif
|
||||||
22
build-config/cppad/include/cppad/core/drivers.hpp
Normal file
22
build-config/cppad/include/cppad/core/drivers.hpp
Normal file
@@ -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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
# 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
build-config/cppad/include/cppad/core/epsilon.hpp
Normal file
60
build-config/cppad/include/cppad/core/epsilon.hpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# 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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$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
|
||||||
118
build-config/cppad/include/cppad/core/equal_op_seq.hpp
Normal file
118
build-config/cppad/include/cppad/core/equal_op_seq.hpp
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# 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 the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
$begin EqualOpSeq$$
|
||||||
|
$spell
|
||||||
|
Op
|
||||||
|
const
|
||||||
|
bool
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
$section Check if Two Value are Identically Equal$$
|
||||||
|
|
||||||
|
$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$$.
|
||||||
|
|
||||||
|
|
||||||
|
$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
|
||||||
287
build-config/cppad/include/cppad/core/for_hes_sparsity.hpp
Normal file
287
build-config/cppad/include/cppad/core/for_hes_sparsity.hpp
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
# ifndef CPPAD_CORE_FOR_HES_SPARSITY_HPP
|
||||||
|
# define CPPAD_CORE_FOR_HES_SPARSITY_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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 select_domain$$ 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.
|
||||||
|
|
||||||
|
$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, class RecBase>
|
||||||
|
template <class BoolVector, class SizeVector>
|
||||||
|
void ADFun<Base,RecBase>::for_hes_sparsity(
|
||||||
|
const BoolVector& select_domain ,
|
||||||
|
const BoolVector& select_range ,
|
||||||
|
bool internal_bool ,
|
||||||
|
sparse_rc<SizeVector>& pattern_out )
|
||||||
|
{
|
||||||
|
// used to identify the RecBase type in calls to sweeps
|
||||||
|
RecBase not_used_rec_base(0.0);
|
||||||
|
//
|
||||||
|
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;
|
||||||
|
//
|
||||||
|
local::pod_vector<bool> select_domain_pod_vector(n);
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
select_domain_pod_vector[j] = select_domain[j];
|
||||||
|
//
|
||||||
|
sparse_rc<SizeVector> pattern_tmp;
|
||||||
|
if( internal_bool )
|
||||||
|
{
|
||||||
|
// reverse Jacobian sparsity pattern for select_range
|
||||||
|
local::sparse::pack_setvec 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_ );
|
||||||
|
// Not using post_element because only adding one element per set
|
||||||
|
internal_rev_jac.add_element( dep_taddr_[i] , 0 );
|
||||||
|
}
|
||||||
|
// reverse Jacobian sparsity for all variables on tape
|
||||||
|
local::sweep::rev_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
internal_rev_jac,
|
||||||
|
not_used_rec_base
|
||||||
|
);
|
||||||
|
// internal vector of sets that will hold Hessian
|
||||||
|
local::sparse::pack_setvec internal_for_hes;
|
||||||
|
internal_for_hes.resize(n + 1 + num_var_tape_, n + 1);
|
||||||
|
//
|
||||||
|
// compute forward Hessian sparsity pattern
|
||||||
|
local::sweep::for_hes<addr_t>(
|
||||||
|
&play_,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
select_domain_pod_vector,
|
||||||
|
internal_rev_jac,
|
||||||
|
internal_for_hes,
|
||||||
|
not_used_rec_base
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// put the result in pattern_tmp
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, ind_taddr_, internal_for_hes, pattern_tmp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// reverse Jacobian sparsity pattern for select_range
|
||||||
|
// (corresponds to s)
|
||||||
|
local::sparse::list_setvec 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_ );
|
||||||
|
// Not using post_element because only adding one element per set
|
||||||
|
internal_rev_jac.add_element( dep_taddr_[i] , 0 );
|
||||||
|
}
|
||||||
|
// reverse Jacobian sparsity for all variables on tape
|
||||||
|
local::sweep::rev_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
internal_rev_jac,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
// internal vector of sets that will hold Hessian
|
||||||
|
local::sparse::list_setvec internal_for_hes;
|
||||||
|
internal_for_hes.resize(n + 1 + num_var_tape_, n + 1);
|
||||||
|
//
|
||||||
|
// compute forward Hessian sparsity pattern
|
||||||
|
local::sweep::for_hes<addr_t>(
|
||||||
|
&play_,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
select_domain_pod_vector,
|
||||||
|
internal_rev_jac,
|
||||||
|
internal_for_hes,
|
||||||
|
not_used_rec_base
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// put the result in pattern_tmp
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
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
|
||||||
305
build-config/cppad/include/cppad/core/for_jac_sparsity.hpp
Normal file
305
build-config/cppad/include/cppad/core/for_jac_sparsity.hpp
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
# ifndef CPPAD_CORE_FOR_JAC_SPARSITY_HPP
|
||||||
|
# define CPPAD_CORE_FOR_JAC_SPARSITY_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
/*
|
||||||
|
$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$$
|
||||||
|
This argument has prototype
|
||||||
|
$codei%
|
||||||
|
bool %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.
|
||||||
|
|
||||||
|
$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, class RecBase>
|
||||||
|
template <class SizeVector>
|
||||||
|
void ADFun<Base,RecBase>::for_jac_sparsity(
|
||||||
|
const sparse_rc<SizeVector>& pattern_in ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency ,
|
||||||
|
bool internal_bool ,
|
||||||
|
sparse_rc<SizeVector>& pattern_out )
|
||||||
|
{
|
||||||
|
// used to identify the RecBase type in calls to sweeps
|
||||||
|
RecBase not_used_rec_base(0.0);
|
||||||
|
//
|
||||||
|
// 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::sparse::set_internal_pattern(
|
||||||
|
zero_empty ,
|
||||||
|
input_empty ,
|
||||||
|
transpose ,
|
||||||
|
ind_taddr_ ,
|
||||||
|
for_jac_sparse_pack_ ,
|
||||||
|
pattern_in
|
||||||
|
);
|
||||||
|
|
||||||
|
// compute sparsity for other variables
|
||||||
|
local::sweep::for_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
for_jac_sparse_pack_,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
// set the output pattern
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
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::sparse::set_internal_pattern(
|
||||||
|
zero_empty ,
|
||||||
|
input_empty ,
|
||||||
|
transpose ,
|
||||||
|
ind_taddr_ ,
|
||||||
|
for_jac_sparse_set_ ,
|
||||||
|
pattern_in
|
||||||
|
);
|
||||||
|
|
||||||
|
// compute sparsity for other variables
|
||||||
|
local::sweep::for_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
for_jac_sparse_set_,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
// get the ouput pattern
|
||||||
|
local::sparse::get_internal_pattern(
|
||||||
|
transpose, dep_taddr_, for_jac_sparse_set_, pattern_out
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
163
build-config/cppad/include/cppad/core/for_one.hpp
Normal file
163
build-config/cppad/include/cppad/core/for_one.hpp
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
# ifndef CPPAD_CORE_FOR_ONE_HPP
|
||||||
|
# define CPPAD_CORE_FOR_ONE_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-18 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$begin ForOne$$
|
||||||
|
$spell
|
||||||
|
dy
|
||||||
|
typename
|
||||||
|
Taylor
|
||||||
|
const
|
||||||
|
$$
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$section First Order Partial Derivative: Driver Routine$$
|
||||||
|
|
||||||
|
$head Syntax$$
|
||||||
|
$icode%dy% = %f%.ForOne(%x%, %j%)%$$
|
||||||
|
|
||||||
|
|
||||||
|
$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$$.
|
||||||
|
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 <class Base, class RecBase>
|
||||||
|
template <class Vector>
|
||||||
|
Vector ADFun<Base,RecBase>::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
|
||||||
566
build-config/cppad/include/cppad/core/for_sparse_hes.hpp
Normal file
566
build-config/cppad/include/cppad/core/for_sparse_hes.hpp
Normal file
@@ -0,0 +1,566 @@
|
|||||||
|
# ifndef CPPAD_CORE_FOR_SPARSE_HES_HPP
|
||||||
|
# define CPPAD_CORE_FOR_SPARSE_HES_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$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{R}^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 %SetVector%& %r%
|
||||||
|
%$$
|
||||||
|
(see $cref/SetVector/ForSparseHes/SetVector/$$ 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 %SetVector%& %s%
|
||||||
|
%$$
|
||||||
|
(see $cref/SetVector/ForSparseHes/SetVector/$$ 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%
|
||||||
|
%SetVector%& %h%
|
||||||
|
%$$
|
||||||
|
(see $cref/SetVector/ForSparseHes/SetVector/$$ 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 SetVector$$
|
||||||
|
The type $icode SetVector$$ 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/SetVector/ForSparseHes/SetVector/$$ 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.
|
||||||
|
|
||||||
|
$end
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
# include <algorithm>
|
||||||
|
# include <cppad/local/pod_vector.hpp>
|
||||||
|
# include <cppad/local/std_set.hpp>
|
||||||
|
|
||||||
|
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
|
||||||
|
/*!
|
||||||
|
\file core/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 bool value. This argument is used to dispatch to the proper source
|
||||||
|
code depending on the vlaue of SetVector::value_type.
|
||||||
|
|
||||||
|
\param r
|
||||||
|
See ForSparseHes(r, s).
|
||||||
|
|
||||||
|
\param s
|
||||||
|
See ForSparseHes(r, s).
|
||||||
|
|
||||||
|
\param h
|
||||||
|
is the return value for the corresponging call to ForSparseJac(q, s).
|
||||||
|
*/
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
template <class SetVector>
|
||||||
|
void ADFun<Base,RecBase>::ForSparseHesCase(
|
||||||
|
bool set_type ,
|
||||||
|
const SetVector& r ,
|
||||||
|
const SetVector& s ,
|
||||||
|
SetVector& h )
|
||||||
|
{
|
||||||
|
// used to identify the RecBase type in calls to sweeps
|
||||||
|
RecBase not_used_rec_base(0.0);
|
||||||
|
//
|
||||||
|
size_t n = Domain();
|
||||||
|
size_t m = Range();
|
||||||
|
//
|
||||||
|
// check Vector is Simple SetVector class with bool elements
|
||||||
|
CheckSimpleVector<bool, SetVector>();
|
||||||
|
//
|
||||||
|
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."
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// select_domain corresponding to r
|
||||||
|
local::pod_vector<bool> select_domain(n);
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
{ select_domain[j] = r[j];
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( play_.GetOp(j + 1) == local::InvOp );
|
||||||
|
}
|
||||||
|
// sparsity pattern correspnding to s
|
||||||
|
local::sparse::pack_setvec 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_ );
|
||||||
|
//
|
||||||
|
// Not using post_element because only adding one element per set
|
||||||
|
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)
|
||||||
|
bool dependency = false;
|
||||||
|
local::sweep::rev_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
rev_jac_pattern,
|
||||||
|
not_used_rec_base
|
||||||
|
);
|
||||||
|
// vector of sets that will hold the forward Hessain values
|
||||||
|
local::sparse::pack_setvec for_hes_pattern;
|
||||||
|
for_hes_pattern.resize(n+1+num_var_tape_, n+1);
|
||||||
|
//
|
||||||
|
// compute the Hessian sparsity patterns
|
||||||
|
local::sweep::for_hes<addr_t>(
|
||||||
|
&play_,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
select_domain,
|
||||||
|
rev_jac_pattern,
|
||||||
|
for_hes_pattern,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
// 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_setvec::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 std::set<size_t> value.
|
||||||
|
This argument is used to dispatch to the proper source
|
||||||
|
code depending on the vlaue of SetVector::value_type.
|
||||||
|
|
||||||
|
\param r
|
||||||
|
See ForSparseHes(r, s).
|
||||||
|
|
||||||
|
\param s
|
||||||
|
See ForSparseHes(q, s).
|
||||||
|
|
||||||
|
\param h
|
||||||
|
is the return value for the corresponging call to ForSparseJac(q, s).
|
||||||
|
*/
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
template <class SetVector>
|
||||||
|
void ADFun<Base,RecBase>::ForSparseHesCase(
|
||||||
|
const std::set<size_t>& set_type ,
|
||||||
|
const SetVector& r ,
|
||||||
|
const SetVector& s ,
|
||||||
|
SetVector& h )
|
||||||
|
{
|
||||||
|
// used to identify the RecBase type in calls to sweeps
|
||||||
|
RecBase not_used_rec_base(0.0);
|
||||||
|
//
|
||||||
|
size_t n = Domain();
|
||||||
|
# ifndef NDEBUG
|
||||||
|
size_t m = Range();
|
||||||
|
# endif
|
||||||
|
std::set<size_t>::const_iterator itr_1;
|
||||||
|
//
|
||||||
|
// check SetVector is Simple Vector class with sets for elements
|
||||||
|
CheckSimpleVector<std::set<size_t>, SetVector>(
|
||||||
|
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."
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// select_domain corresponding to r
|
||||||
|
local::pod_vector<bool> select_domain(n);
|
||||||
|
for(size_t j = 0; j < n; ++j)
|
||||||
|
{ select_domain[j] = false;
|
||||||
|
CPPAD_ASSERT_UNKNOWN( ind_taddr_[j] == j + 1);
|
||||||
|
CPPAD_ASSERT_UNKNOWN( play_.GetOp(j + 1) == local::InvOp );
|
||||||
|
}
|
||||||
|
itr_1 = r[0].begin();
|
||||||
|
while( itr_1 != r[0].end() )
|
||||||
|
{ size_t j = *itr_1++;
|
||||||
|
select_domain[j] = true;
|
||||||
|
}
|
||||||
|
// sparsity pattern correspnding to s
|
||||||
|
local::sparse::list_setvec 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_ );
|
||||||
|
//
|
||||||
|
// Not using post_element because only adding one element per set
|
||||||
|
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)
|
||||||
|
bool dependency = false;
|
||||||
|
local::sweep::rev_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
rev_jac_pattern,
|
||||||
|
not_used_rec_base
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// vector of sets that will hold reverse Hessain values
|
||||||
|
local::sparse::list_setvec for_hes_pattern;
|
||||||
|
for_hes_pattern.resize(n+1+num_var_tape_, n+1);
|
||||||
|
//
|
||||||
|
// compute the Hessian sparsity patterns
|
||||||
|
local::sweep::for_hes<addr_t>(
|
||||||
|
&play_,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
select_domain,
|
||||||
|
rev_jac_pattern,
|
||||||
|
for_hes_pattern,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
// 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_setvec::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 SetVector
|
||||||
|
is a simple vector with elements of type bool
|
||||||
|
or std::set<size_t>.
|
||||||
|
|
||||||
|
\param r
|
||||||
|
is a vector with size n that specifies the sparsity pattern
|
||||||
|
for the diagonal of the matrix \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.
|
||||||
|
|
||||||
|
\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 x is any argument value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
template <class SetVector>
|
||||||
|
SetVector ADFun<Base,RecBase>::ForSparseHes(
|
||||||
|
const SetVector& r, const SetVector& s
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SetVector h;
|
||||||
|
typedef typename SetVector::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, class RecBase>
|
||||||
|
void ADFun<Base,RecBase>::ForSparseHesCheckpoint(
|
||||||
|
vector<bool>& r ,
|
||||||
|
vector<bool>& s ,
|
||||||
|
local::sparse::list_setvec& h )
|
||||||
|
{
|
||||||
|
// used to identify the RecBase type in calls to sweeps
|
||||||
|
RecBase not_used_rec_base(0.0);
|
||||||
|
//
|
||||||
|
|
||||||
|
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(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_setvec for_hes_pattern;
|
||||||
|
for_hes_pattern.resize(n+1+num_var_tape_, n+1);
|
||||||
|
|
||||||
|
// compute Hessian sparsity pattern for all variables
|
||||||
|
local::sweep::for_hes<addr_t>(
|
||||||
|
&play_,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
for_jac_sparse_set_,
|
||||||
|
RevJac.data(),
|
||||||
|
for_hes_pattern,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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_setvec::const_iterator itr(for_hes_pattern, .j + 1);
|
||||||
|
size_t i = *itr;
|
||||||
|
while( i < q )
|
||||||
|
{ if( transpose )
|
||||||
|
h.post_element(j, i);
|
||||||
|
else
|
||||||
|
h.post_element(i, j);
|
||||||
|
i = *(++itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// process posts
|
||||||
|
for(size_t i = 0; i < n; ++i)
|
||||||
|
h.process_post(i);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
} // END_CPPAD_NAMESPACE
|
||||||
|
# endif
|
||||||
764
build-config/cppad/include/cppad/core/for_sparse_jac.hpp
Normal file
764
build-config/cppad/include/cppad/core/for_sparse_jac.hpp
Normal file
@@ -0,0 +1,764 @@
|
|||||||
|
# ifndef CPPAD_CORE_FOR_SPARSE_JAC_HPP
|
||||||
|
# define CPPAD_CORE_FOR_SPARSE_JAC_HPP
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-19 Bradley M. Bell
|
||||||
|
|
||||||
|
CppAD is distributed under the terms of the
|
||||||
|
Eclipse Public License Version 2.0.
|
||||||
|
|
||||||
|
This Source Code may also be made available under the following
|
||||||
|
Secondary License when the conditions for such availability set forth
|
||||||
|
in the Eclipse Public License, Version 2.0 are satisfied:
|
||||||
|
GNU General Public License, Version 2.0 or later.
|
||||||
|
---------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
$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{R}^n \rightarrow \B{R}^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/SetVector/ForSparseJac/SetVector/$$ 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{R}^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 Jacobian
|
||||||
|
$latex S(x) \in \B{R}^{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 %SetVector%& %r%
|
||||||
|
%$$
|
||||||
|
see $cref/SetVector/ForSparseJac/SetVector/$$ 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{R}^{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{R}^{q \times n}$$.
|
||||||
|
|
||||||
|
$head s$$
|
||||||
|
The return value $icode s$$ has prototype
|
||||||
|
$codei%
|
||||||
|
%SetVector% %s%
|
||||||
|
%$$
|
||||||
|
see $cref/SetVector/ForSparseJac/SetVector/$$ 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{R}^{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{R}^{q \times m}$$.
|
||||||
|
|
||||||
|
$head SetVector$$
|
||||||
|
The type $icode SetVector$$ 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.
|
||||||
|
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 core/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 bool value. This argument is used to dispatch to the proper source
|
||||||
|
code depending on the value of SetVector::value_type.
|
||||||
|
|
||||||
|
\param transpose
|
||||||
|
See ForSparseJac(q, r, transpose, dependency).
|
||||||
|
|
||||||
|
\param dependency
|
||||||
|
See ForSparseJac(q, r, transpose, dependency).
|
||||||
|
|
||||||
|
\param q
|
||||||
|
See ForSparseJac(q, r, transpose, dependency).
|
||||||
|
|
||||||
|
\param r
|
||||||
|
See ForSparseJac(q, r, transpose, dependency).
|
||||||
|
|
||||||
|
\param s
|
||||||
|
is the return value for the corresponding call to ForSparseJac(q, r).
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
template <class SetVector>
|
||||||
|
void ADFun<Base,RecBase>::ForSparseJacCase(
|
||||||
|
bool set_type ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency ,
|
||||||
|
size_t q ,
|
||||||
|
const SetVector& r ,
|
||||||
|
SetVector& s )
|
||||||
|
{
|
||||||
|
// used to identify the RecBase type in calls to sweeps
|
||||||
|
RecBase not_used_rec_base(0.0);
|
||||||
|
//
|
||||||
|
size_t m = Range();
|
||||||
|
size_t n = Domain();
|
||||||
|
|
||||||
|
// check SetVector is Simple Vector class with bool elements
|
||||||
|
CheckSimpleVector<bool, SetVector>();
|
||||||
|
|
||||||
|
// dimension size of result vector
|
||||||
|
s.resize( m * q );
|
||||||
|
|
||||||
|
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(size_t 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(size_t j = 0; j < q; j++) if( r[ j * n + i ] )
|
||||||
|
for_jac_sparse_pack_.post_element( ind_taddr_[i], j);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ for(size_t j = 0; j < q; j++) if( r[ i * q + j ] )
|
||||||
|
for_jac_sparse_pack_.post_element( ind_taddr_[i], j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// process posts
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
for_jac_sparse_pack_.process_post( ind_taddr_[j] );
|
||||||
|
|
||||||
|
// evaluate the sparsity patterns
|
||||||
|
local::sweep::for_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
for_jac_sparse_pack_,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
// return values corresponding to dependent variables
|
||||||
|
CPPAD_ASSERT_UNKNOWN( size_t(s.size()) == m * q );
|
||||||
|
for(size_t 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(size_t j = 0; j < q; j++)
|
||||||
|
s[ j * m + i ] = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ for(size_t j = 0; j < q; j++)
|
||||||
|
s[ i * q + j ] = false;
|
||||||
|
}
|
||||||
|
CPPAD_ASSERT_UNKNOWN( for_jac_sparse_pack_.end() == q );
|
||||||
|
local::sparse::pack_setvec::const_iterator
|
||||||
|
itr(for_jac_sparse_pack_, dep_taddr_[i] );
|
||||||
|
size_t j = *itr;
|
||||||
|
while( j < q )
|
||||||
|
{ if( transpose )
|
||||||
|
s[j * m + i] = true;
|
||||||
|
else
|
||||||
|
s[i * q + j] = true;
|
||||||
|
j = *(++itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
/*!
|
||||||
|
Private helper function for ForSparseJac(q, r) set sparsity.
|
||||||
|
|
||||||
|
All of the description in the public member function ForSparseJac(q, r)
|
||||||
|
applies.
|
||||||
|
|
||||||
|
\param set_type
|
||||||
|
is a std::set<size_t> object.
|
||||||
|
This argument is used to dispatch to the proper source
|
||||||
|
code depending on the value of SetVector::value_type.
|
||||||
|
|
||||||
|
\param transpose
|
||||||
|
See ForSparseJac(q, r, transpose, dependency).
|
||||||
|
|
||||||
|
\param dependency
|
||||||
|
See ForSparseJac(q, r, transpose, dependency).
|
||||||
|
|
||||||
|
\param q
|
||||||
|
See ForSparseJac(q, r, transpose, dependency).
|
||||||
|
|
||||||
|
\param r
|
||||||
|
See ForSparseJac(q, r, transpose, dependency).
|
||||||
|
|
||||||
|
\param s
|
||||||
|
is the return value for the corresponding call to ForSparseJac(q, r).
|
||||||
|
*/
|
||||||
|
template <class Base, class RecBase>
|
||||||
|
template <class SetVector>
|
||||||
|
void ADFun<Base,RecBase>::ForSparseJacCase(
|
||||||
|
const std::set<size_t>& set_type ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency ,
|
||||||
|
size_t q ,
|
||||||
|
const SetVector& r ,
|
||||||
|
SetVector& s )
|
||||||
|
{
|
||||||
|
// used to identify the RecBase type in calls to sweeps
|
||||||
|
RecBase not_used_rec_base(0.0);
|
||||||
|
//
|
||||||
|
size_t m = Range();
|
||||||
|
size_t n = Domain();
|
||||||
|
|
||||||
|
// check SetVector is Simple Vector class with sets for elements
|
||||||
|
CheckSimpleVector<std::set<size_t>, SetVector>(
|
||||||
|
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 iterator
|
||||||
|
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(size_t i = 0; i < q; i++)
|
||||||
|
{ // add the elements that are present
|
||||||
|
itr_1 = r[i].begin();
|
||||||
|
while( itr_1 != r[i].end() )
|
||||||
|
{ size_t 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_.post_element( ind_taddr_[j], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ for(size_t 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() )
|
||||||
|
{ size_t 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_.post_element( ind_taddr_[i], j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// process posts
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
for_jac_sparse_set_.process_post( ind_taddr_[j] );
|
||||||
|
|
||||||
|
// evaluate the sparsity patterns
|
||||||
|
local::sweep::for_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
for_jac_sparse_set_,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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(size_t 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_setvec::const_iterator
|
||||||
|
itr_2(for_jac_sparse_set_, dep_taddr_[i] );
|
||||||
|
size_t 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 SetVector
|
||||||
|
is a simple vector with elements of type bool
|
||||||
|
or 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 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 x is any argument value.
|
||||||
|
If SetVector::value_type is bool,
|
||||||
|
the return value has size \f$ m * q \f$ (\f$ q * m \f$).
|
||||||
|
where m is the number of dependent variables
|
||||||
|
corresponding to the operation sequence stored in f.
|
||||||
|
If SetVector::value_type is 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 SetVector::value_type is bool,
|
||||||
|
the forward sparsity pattern for all of the variables on the
|
||||||
|
tape is stored in 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 SetVector::value_type is std::set<size_t>,
|
||||||
|
the forward sparsity pattern for all of the variables on the
|
||||||
|
tape is stored in 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, class RecBase>
|
||||||
|
template <class SetVector>
|
||||||
|
SetVector ADFun<Base,RecBase>::ForSparseJac(
|
||||||
|
size_t q ,
|
||||||
|
const SetVector& r ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency )
|
||||||
|
{
|
||||||
|
SetVector s;
|
||||||
|
typedef typename SetVector::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 SetVector::value_type is bool,
|
||||||
|
the forward sparsity pattern for all of the variables on the
|
||||||
|
tape is stored in 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 SetVector::value_type is std::set<size_t>,
|
||||||
|
the forward sparsity pattern for all of the variables on the
|
||||||
|
tape is stored in 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, class RecBase>
|
||||||
|
void ADFun<Base,RecBase>::ForSparseJacCheckpoint(
|
||||||
|
size_t q ,
|
||||||
|
const local::sparse::list_setvec& r ,
|
||||||
|
bool transpose ,
|
||||||
|
bool dependency ,
|
||||||
|
local::sparse::list_setvec& s )
|
||||||
|
{
|
||||||
|
// used to identify the RecBase type in calls to sweeps
|
||||||
|
RecBase not_used_rec_base(0.0);
|
||||||
|
//
|
||||||
|
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_setvec::const_iterator itr(r, i);
|
||||||
|
size_t j = *itr;
|
||||||
|
while( j < n )
|
||||||
|
{ for_jac_sparse_set_.post_element( ind_taddr_[j], i );
|
||||||
|
j = *(++itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ for(size_t j = 0; j < n; j++)
|
||||||
|
{ local::sparse::list_setvec::const_iterator itr(r, j);
|
||||||
|
size_t i = *itr;
|
||||||
|
while( i < q )
|
||||||
|
{ for_jac_sparse_set_.post_element( ind_taddr_[j], i );
|
||||||
|
i = *(++itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// process posts
|
||||||
|
for(size_t j = 0; j < n; j++)
|
||||||
|
for_jac_sparse_set_.process_post( ind_taddr_[j] );
|
||||||
|
|
||||||
|
// evaluate the sparsity pattern for all variables
|
||||||
|
local::sweep::for_jac<addr_t>(
|
||||||
|
&play_,
|
||||||
|
dependency,
|
||||||
|
n,
|
||||||
|
num_var_tape_,
|
||||||
|
for_jac_sparse_set_,
|
||||||
|
not_used_rec_base
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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_setvec::const_iterator
|
||||||
|
itr(for_jac_sparse_set_, dep_taddr_[i] );
|
||||||
|
size_t j = *itr;
|
||||||
|
while( j < q )
|
||||||
|
{ if( transpose )
|
||||||
|
s.post_element(j, i);
|
||||||
|
else
|
||||||
|
s.post_element(i, j);
|
||||||
|
j = *(++itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// process posts
|
||||||
|
for(size_t i = 0; i < s.n_set(); ++i)
|
||||||
|
s.process_post(i);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // 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