38#include "../expressions/lhsExpressionInterface.hpp"
39#include "../misc/exceptions.hpp"
40#include "../tapes/misc/tapeParameters.hpp"
41#include "../traits/adjointVectorTraits.hpp"
42#include "../traits/gradientTraits.hpp"
43#include "data/dummy.hpp"
44#include "data/jacobian.hpp"
45#include "data/staticDummy.hpp"
68 template<
typename T_Type,
bool T_ActiveChecks = true>
77 using Tape =
typename Type::Tape;
79 using Real =
typename Type::Real;
95 if (inputs <= outputs) {
96 return EvaluationType::Forward;
98 return EvaluationType::Reverse;
141 template<
typename Jac,
bool keepState = true>
144 size_t const outputSize, Jac& jac,
148 tape.resizeAdjointVector();
149 tape.beginUseAdjointVector();
153 tape.getInternalAdjoints());
156 tape.endUseAdjointVector();
171 template<
typename Jac,
typename Adjo
intVector,
bool keepState = true>
173 Identifier const* input,
size_t const inputSize,
174 Identifier const* output,
size_t const outputSize, Jac& jac,
175 AdjointVector&& adjoints) {
180 size_t constexpr gradDim = CustomGT::dim;
183 if (EvaluationType::Forward == evalType) {
184 for (
size_t j = 0; j < inputSize; j += gradDim) {
185 setGradientOnIdentifierCustomAdjoints(tape, j, input, inputSize,
typename CustomGT::Real(1.0), adjoints);
188 tape.evaluateForwardKeepState(start, end, std::forward<AdjointVector>(adjoints));
190 tape.evaluateForward(start, end, std::forward<AdjointVector>(adjoints));
193 for (
size_t i = 0; i < outputSize; i += 1) {
194 for (
size_t curDim = 0; curDim < gradDim && j + curDim < inputSize; curDim += 1) {
195 jac(outputSize - i - 1, j + curDim) = CustomGT::at(adjoints[output[outputSize - i - 1]], curDim);
196 if (tape.isIdentifierActive(output[i])) {
197 CustomGT::at(adjoints[output[outputSize - i - 1]], curDim) =
typename GT::Real();
202 setGradientOnIdentifierCustomAdjoints(tape, j, input, inputSize,
typename CustomGT::Real(), adjoints);
205 tape.clearCustomAdjoints(end, start, std::forward<AdjointVector>(adjoints));
207 }
else if (EvaluationType::Reverse == evalType) {
208 for (
size_t i = 0; i < outputSize; i += gradDim) {
209 setGradientOnIdentifierCustomAdjoints(tape, i, output, outputSize,
typename CustomGT::Real(1.0), adjoints);
212 tape.evaluateKeepState(end, start, std::forward<AdjointVector>(adjoints));
214 tape.evaluate(end, start, std::forward<AdjointVector>(adjoints));
217 for (
size_t j = 0; j < inputSize; j += 1) {
218 for (
size_t curDim = 0; curDim < gradDim && i + curDim < outputSize; curDim += 1) {
219 jac(i + curDim, j) = CustomGT::at(adjoints[input[j]], curDim);
220 CustomGT::at(adjoints[input[j]], curDim) =
typename CustomGT::Real();
224 setGradientOnIdentifierCustomAdjoints(tape, i, output, outputSize,
typename CustomGT::Real(), adjoints);
227 tape.clearCustomAdjoints(end, start, std::forward<AdjointVector>(adjoints));
231 CODI_EXCEPTION(
"Evaluation mode not implemented. Mode is: %d.", (
int)evalType);
240 template<
typename Jac>
242 size_t const inputSize,
Identifier const* output,
size_t const outputSize,
245 computeJacobian(Type::getTape(), start, end, input, inputSize, output, outputSize, jac, adjointsManagement);
253 template<
typename Jac,
typename Adjo
intVector>
255 Identifier const* input,
size_t const inputSize,
256 Identifier const* output,
size_t const outputSize, Jac& jac,
257 AdjointVector&& adjoints) {
258 computeJacobianCustomAdjoints<Jac, AdjointVector>(Type::getTape(), start, end, input, inputSize, output,
259 outputSize, jac, std::forward<AdjointVector>(adjoints));
280 template<
typename Hes,
typename Jac = DummyJacobian>
282 Identifier const* input,
size_t const inputSize,
283 Identifier const* output,
size_t const outputSize, Hes& hes,
286 if (EvaluationType::Forward == evalType) {
288 }
else if (EvaluationType::Reverse == evalType) {
291 CODI_EXCEPTION(
"Evaluation mode not implemented. Mode is: %d.", (
int)evalType);
306 template<
typename Hes,
typename Jac = DummyJacobian>
309 size_t const inputSize,
Identifier const* output,
310 size_t const outputSize, Hes& hes,
313 size_t constexpr gradDim1st = GT1st::dim;
315 size_t constexpr gradDim2nd = GT2nd::dim;
318 tape.revertPrimals(start);
320 for (
size_t j = 0; j < inputSize; j += gradDim2nd) {
321 setGradient2ndOnIdentifier(tape, j, input, inputSize,
typename GT2nd::Real(1.0));
324 for (
size_t k = j; k < inputSize; k += gradDim1st) {
325 setGradientOnIdentifier(tape, k, input, inputSize,
typename GT1st::Real(1.0));
327 tape.evaluateForward(start, end);
329 for (
size_t i = 0; i < outputSize; i += 1) {
330 for (
size_t vecPos1st = 0; vecPos1st < gradDim1st && k + vecPos1st < inputSize; vecPos1st += 1) {
331 for (
size_t vecPos2nd = 0; vecPos2nd < gradDim2nd && j + vecPos2nd < inputSize; vecPos2nd += 1) {
332 hes(i, j + vecPos2nd, k + vecPos1st) =
333 GT2nd::at(GT1st::at(tape.getGradient(output[i]), vecPos1st).gradient(), vecPos2nd);
334 hes(i, k + vecPos1st, j + vecPos2nd) = hes(i, j + vecPos2nd, k + vecPos1st);
339 for (
size_t vecPos = 0; vecPos < gradDim1st && k + vecPos < inputSize; vecPos += 1) {
340 jac(i, k + vecPos) = GT1st::at(tape.getGradient(output[i]), vecPos).value();
345 setGradientOnIdentifier(tape, k, input, inputSize,
typename GT1st::Real());
348 setGradient2ndOnIdentifier(tape, j, input, inputSize,
typename GT2nd::Real());
363 template<
typename Hes,
typename Jac = DummyJacobian>
366 size_t const inputSize,
Identifier const* output,
367 size_t const outputSize, Hes& hes,
370 size_t constexpr gradDim1st = GT1st::dim;
372 size_t constexpr gradDim2nd = GT2nd::dim;
375 tape.revertPrimals(start);
377 for (
size_t j = 0; j < inputSize; j += gradDim2nd) {
378 setGradient2ndOnIdentifier(tape, j, input, inputSize,
typename GT2nd::Real(1.0));
381 tape.evaluatePrimal(start, end);
383 for (
size_t i = 0; i < outputSize; i += gradDim1st) {
384 setGradientOnIdentifier(tape, i, output, outputSize,
typename GT1st::Real(1.0));
387 tape.evaluateKeepState(end, start);
389 for (
size_t k = 0; k < inputSize; k += 1) {
390 for (
size_t vecPos1st = 0; vecPos1st < gradDim1st && i + vecPos1st < outputSize; vecPos1st += 1) {
391 for (
size_t vecPos2nd = 0; vecPos2nd < gradDim2nd && j + vecPos2nd < inputSize; vecPos2nd += 1) {
392 hes(i + vecPos1st, j + vecPos2nd, k) =
393 GT2nd::at(GT1st::at(tape.gradient(input[k]), vecPos1st).gradient(), vecPos2nd);
398 for (
size_t vecPos1st = 0; vecPos1st < gradDim1st && i + vecPos1st < outputSize; vecPos1st += 1) {
399 jac(i + vecPos1st, k) = GT1st::at(tape.getGradient(input[k]), vecPos1st).value();
403 tape.gradient(input[k]) =
Gradient();
406 setGradientOnIdentifier(tape, i, output, outputSize,
typename GT1st::Real());
409 tape.clearAdjoints(end, start);
413 setGradient2ndOnIdentifier(tape, j, input, inputSize,
typename GT2nd::Real());
415 if (j + gradDim2nd < inputSize) {
416 tape.revertPrimals(start);
438 template<
typename Func,
typename VecIn,
typename VecOut,
typename Hes,
typename Jac = DummyJacobian>
442 if (EvaluationType::Forward == evalType) {
444 }
else if (EvaluationType::Reverse == evalType) {
447 CODI_EXCEPTION(
"Evaluation mode not implemented. Mode is: %d.", (
int)evalType);
464 template<
typename Func,
typename VecIn,
typename VecOut,
typename Hes,
typename Jac = DummyJacobian>
468 size_t constexpr gradDim1st = GT1st::dim;
470 size_t constexpr gradDim2nd = GT2nd::dim;
472 Tape& tape = Type::getTape();
474 for (
size_t j = 0; j < input.size(); j += gradDim2nd) {
475 setGradient2ndOnCoDiValue(j, input.data(), input.size(),
typename GT2nd::Real(1.0));
478 recordTape(func, input, output);
481 for (
size_t k = j; k < input.size(); k += gradDim1st) {
482 setGradientOnCoDiValue(tape, k, input.data(), input.size(),
typename GT1st::Real(1.0));
485 tape.evaluateForwardKeepState(tape.getZeroPosition(), tape.getPosition());
487 for (
size_t i = 0; i < output.size(); i += 1) {
488 for (
size_t vecPos1st = 0; vecPos1st < gradDim1st && k + vecPos1st < input.size(); vecPos1st += 1) {
489 for (
size_t vecPos2nd = 0; vecPos2nd < gradDim2nd && j + vecPos2nd < input.size(); vecPos2nd += 1) {
490 hes(i, j + vecPos2nd, k + vecPos1st) = GT2nd::at(
491 GT1st::at(tape.getGradient(output[i].getIdentifier()), vecPos1st).gradient(), vecPos2nd);
492 hes(i, k + vecPos1st, j + vecPos2nd) = hes(i, j + vecPos2nd, k + vecPos1st);
497 for (
size_t vecPos = 0; vecPos < gradDim1st && k + vecPos < input.size(); vecPos += 1) {
498 jac(i, k + vecPos) = GT1st::at(tape.getGradient(output[i].getIdentifier()), vecPos).value();
503 setGradientOnCoDiValue(tape, k, input.data(), input.size(),
typename GT1st::Real());
506 setGradient2ndOnCoDiValue(j, input.data(), input.size(),
typename GT2nd::Real());
525 template<
typename Func,
typename VecIn,
typename VecOut,
typename Hes,
typename Jac = DummyJacobian>
529 size_t constexpr gradDim1st = GT1st::dim;
531 size_t constexpr gradDim2nd = GT2nd::dim;
533 Tape& tape = Type::getTape();
535 for (
size_t j = 0; j < input.size(); j += gradDim2nd) {
536 setGradient2ndOnCoDiValue(j, input.data(), input.size(),
typename GT2nd::Real(1.0));
539 recordTape(func, input, output);
541 for (
size_t i = 0; i < output.size(); i += gradDim1st) {
542 setGradientOnCoDiValue(tape, i, output.data(), output.size(),
typename GT1st::Real(1.0));
545 tape.evaluateKeepState(tape.getPosition(), tape.getZeroPosition());
547 for (
size_t k = 0; k < input.size(); k += 1) {
548 for (
size_t vecPos1st = 0; vecPos1st < gradDim1st && i + vecPos1st < output.size(); vecPos1st += 1) {
549 for (
size_t vecPos2nd = 0; vecPos2nd < gradDim2nd && j + vecPos2nd < input.size(); vecPos2nd += 1) {
550 hes(i + vecPos1st, j + vecPos2nd, k) =
551 GT2nd::at(GT1st::at(tape.gradient(input[k].getIdentifier()), vecPos1st).gradient(), vecPos2nd);
556 for (
size_t vecPos1st = 0; vecPos1st < gradDim1st && i + vecPos1st < output.size(); vecPos1st += 1) {
557 jac(i + vecPos1st, k) = GT1st::at(tape.getGradient(input[k].getIdentifier()), vecPos1st).value();
561 tape.gradient(input[k].getIdentifier()) =
Gradient();
564 setGradientOnCoDiValue(tape, i, output.data(), output.size(),
typename GT1st::Real());
567 tape.clearAdjoints(tape.getPosition(), tape.getZeroPosition());
571 setGradient2ndOnCoDiValue(j, input.data(), input.size(),
typename GT2nd::Real());
587 Tape& tape,
size_t const pos, Identifier
const* identifiers,
size_t const size, T value,
589 size_t constexpr gradDim =
GT::dim;
591 for (
size_t curDim = 0; curDim < gradDim && pos + curDim < size; curDim += 1) {
593 GT::at(tape.gradient(identifiers[pos + curDim], adjointsManagement), curDim) = value;
598 template<
typename T,
typename Adjo
ints>
599 static CODI_INLINE void setGradientOnIdentifierCustomAdjoints(Tape& tape,
size_t const pos,
600 Identifier
const* identifiers,
size_t const size,
601 T value, Adjoints& adjoints) {
602 size_t constexpr gradDim =
GT::dim;
604 for (
size_t curDim = 0; curDim < gradDim && pos + curDim < size; curDim += 1) {
606 GT::at(adjoints[identifiers[pos + curDim]], curDim) = value;
613 static CODI_INLINE void setGradient2ndOnIdentifier(Tape& tape,
size_t const pos, Identifier
const* identifiers,
614 size_t const size, T value) {
616 size_t constexpr gradDim2nd = GT2nd::dim;
618 for (
size_t curDim = 0; curDim < gradDim2nd && pos + curDim < size; curDim += 1) {
620 GT2nd::at(tape.primal(identifiers[pos + curDim]).gradient(), curDim) = value;
631 static CODI_INLINE void setGradientOnCoDiValue(Tape& tape,
size_t const pos,
Type* identifiers,
size_t const size,
633 size_t constexpr gradDim =
GT::dim;
635 for (
size_t curDim = 0; curDim < gradDim && pos + curDim < size; curDim += 1) {
637 GT::at(tape.gradient(identifiers[pos + curDim].getIdentifier()), curDim) = value;
644 static CODI_INLINE void setGradient2ndOnCoDiValue(
size_t const pos,
Type* identifiers,
size_t const size,
647 size_t constexpr gradDim2nd = GT2nd::dim;
649 for (
size_t curDim = 0; curDim < gradDim2nd && pos + curDim < size; curDim += 1) {
651 GT2nd::at(identifiers[pos + curDim].value().gradient(), curDim) = value;
656 template<
typename Func,
typename VecIn,
typename VecOut>
657 static CODI_INLINE void recordTape(Func func, VecIn& input, VecOut& output) {
658 Tape& tape = Type::getTape();
660 for (
size_t curIn = 0; curIn < input.size(); curIn += 1) {
661 tape.registerInput(input[curIn]);
666 for (
size_t curOut = 0; curOut < output.size(); curOut += 1) {
667 tape.registerOutput(output[curOut]);
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition config.h:457
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition macros.hpp:94
#define CODI_ENABLE_CHECK(option, condition)
Definition macros.hpp:53
typename GradientImplementation< AdjointVector >::Gradient Gradient
Deduce the entry type from an adjoint vector type, usually identical to the gradient type of a tape.
Definition adjointVectorTraits.hpp:92
bool constexpr ReversalZeroesAdjoints
With a linear index management, control if adjoints are set to zero during reversal.
Definition config.h:289
CoDiPack - Code Differentiation Package.
Definition codi.hpp:91
AdjointsManagement
Policies for management of the tape's interal adjoints.
Definition tapeParameters.hpp:98
@ Automatic
Manage internal adjoints automatically, including locking, bounds checking, and resizing.
typename Tape::Gradient Gradient
See LhsExpressionInterface.
Definition activeTypeBase.hpp:79
Basic algorithms for tape evaluation in CoDiPack.
Definition algorithms.hpp:69
typename Type::Gradient Gradient
See LhsExpressionInterface.
Definition algorithms.hpp:81
T_Type Type
See Algorithms.
Definition algorithms.hpp:73
EvaluationType
Evaluation modes for the derivative computation.
Definition algorithms.hpp:86
typename Tape::Position Position
See LhsExpressionInterface.
Definition algorithms.hpp:78
static void computeHessianPrimalValueTapeForward(Tape &tape, Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Hes &hes, Jac &jac=StaticDummy< DummyJacobian >::dummy)
Forward version of the Hessian computation.
Definition algorithms.hpp:307
static void computeJacobian(Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Jac &jac, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Compute the Jacobian with multiple tape sweeps. This method uses the global tape for the Jacobian...
Definition algorithms.hpp:241
static bool constexpr ActiveChecks
See Algorithms.
Definition algorithms.hpp:75
static void computeJacobianCustomAdjoints(Tape &tape, Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Jac &jac, AdjointVector &&adjoints)
Compute the Jacobian with multiple tape sweeps using a custom adjoint vector.
Definition algorithms.hpp:172
static void computeHessian(Func func, VecIn &input, VecOut &output, Hes &hes, Jac &jac=StaticDummy< DummyJacobian >::dummy)
Compute the Hessian with multiple tape recordings and sweeps.
Definition algorithms.hpp:439
typename Type::Tape Tape
See LhsExpressionInterface.
Definition algorithms.hpp:77
GradientTraits::TraitsImplementation< Gradient > GT
Shortcut for traits of gradient.
Definition algorithms.hpp:83
typename Type::Identifier Identifier
See LhsExpressionInterface.
Definition algorithms.hpp:80
static void computeHessianForward(Func func, VecIn &input, VecOut &output, Hes &hes, Jac &jac=StaticDummy< DummyJacobian >::dummy)
Forward version of the Hessian computation with a function object.
Definition algorithms.hpp:465
static void computeJacobianCustomAdjoints(Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Jac &jac, AdjointVector &&adjoints)
Compute the Jacobian with multiple tape sweeps using a custom adjoint vector. This method uses th...
Definition algorithms.hpp:254
static EvaluationType getEvaluationChoice(size_t const inputs, size_t const outputs)
Definition algorithms.hpp:94
typename Type::Real Real
See LhsExpressionInterface.
Definition algorithms.hpp:79
static void computeHessianPrimalValueTape(Tape &tape, Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Hes &hes, Jac &jac=StaticDummy< DummyJacobian >::dummy)
Compute the Hessian with multiple tape sweeps.
Definition algorithms.hpp:281
static void computeJacobian(Tape &tape, Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Jac &jac, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Compute the Jacobian with multiple tape sweeps.
Definition algorithms.hpp:142
static void computeHessianReverse(Func func, VecIn &input, VecOut &output, Hes &hes, Jac &jac=StaticDummy< DummyJacobian >::dummy)
Reverse version of the Hessian computation with a function object.
Definition algorithms.hpp:526
static void computeHessianPrimalValueTapeReverse(Tape &tape, Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Hes &hes, Jac &jac=StaticDummy< DummyJacobian >::dummy)
Reverse version of the Hessian computation.
Definition algorithms.hpp:364
Common traits for all types used as gradients.
Definition gradientTraits.hpp:64
static size_t constexpr dim
Number of dimensions this gradient value has.
Definition gradientTraits.hpp:70
static Real & at(Gradient &gradient, size_t dim)
Get the entry at the given index.
Definition gradientTraits.hpp:73
Gradient Real
The base value used in the gradient entries.
Definition gradientTraits.hpp:68
Static dummy objects for e.g. default reference arguments.
Definition staticDummy.hpp:42