Je suis en train de modifier l'exemple ici:
# include <cppad/cppad.hpp>
namespace { // ---------------------------------------------------------
// define the template function JacobianCases<Vector> in empty namespace
template <typename Vector>
bool JacobianCases()
{ bool ok = true;
using CppAD::AD;
using CppAD::NearEqual;
double eps99 = 99.0 * std::numeric_limits<double>::epsilon();
using CppAD::exp;
using CppAD::sin;
using CppAD::cos;
// domain space vector
size_t n = 2;
CPPAD_TESTVECTOR(AD<double>) X(n);
X[0] = 1.;
X[1] = 2.;
// declare independent variables and starting recording
CppAD::Independent(X);
// a calculation between the domain and range values
AD<double> Square = X[0] * X[0];
// range space vector
size_t m = 3;
CPPAD_TESTVECTOR(AD<double>) Y(m);
Y[0] = Square * exp( X[1] );
Y[1] = Square * sin( X[1] );
Y[2] = Square * cos( X[1] );
// create f: X -> Y and stop tape recording
CppAD::ADFun<double> f(X, Y);
// new value for the independent variable vector
Vector x(n);
x[0] = 2.;
x[1] = 1.;
// compute the derivative at this x
Vector jac( m * n );
jac = f.Jacobian(x);
/*
F'(x) = [ 2 * x[0] * exp(x[1]) , x[0] * x[0] * exp(x[1]) ]
[ 2 * x[0] * sin(x[1]) , x[0] * x[0] * cos(x[1]) ]
[ 2 * x[0] * cos(x[1]) , -x[0] * x[0] * sin(x[i]) ]
*/
ok &= NearEqual( 2.*x[0]*exp(x[1]), jac[0*n+0], eps99, eps99);
ok &= NearEqual( 2.*x[0]*sin(x[1]), jac[1*n+0], eps99, eps99);
ok &= NearEqual( 2.*x[0]*cos(x[1]), jac[2*n+0], eps99, eps99);
ok &= NearEqual( x[0] * x[0] *exp(x[1]), jac[0*n+1], eps99, eps99);
ok &= NearEqual( x[0] * x[0] *cos(x[1]), jac[1*n+1], eps99, eps99);
ok &= NearEqual(-x[0] * x[0] *sin(x[1]), jac[2*n+1], eps99, eps99);
return ok;
}
} // End empty namespace
# include <vector>
# include <valarray>
bool Jacobian(void)
{ bool ok = true;
// Run with Vector equal to three different cases
// all of which are Simple Vectors with elements of type double.
ok &= JacobianCases< CppAD::vector <double> >();
ok &= JacobianCases< std::vector <double> >();
ok &= JacobianCases< std::valarray <double> >();
return ok;
}
Je suis en train de le modifier de la façon suivante:
Soit G le Jacobien jac
, qui est calculé dans cet exemple, dans la ligne:
jac = f.Jacobian(x);
et, comme dans l'exemple, laissez - X
être les variables indépendantes. Je voudrais construire une nouvelle fonction, H
, qui est une fonction de l' jac
, c'est à dire H(jacobian(X))
= quelque chose, de telle sorte que H est autodifferentiable. Un exemple peut être H(X) = jacobian( jacobian(X)[0])
, c'est à dire le jacobien du premier élément de jacobian(X)
w.r.t X
(la dérivée seconde de toutes sortes).
Le problème est qu' jac
comme écrit ici est de type Vector
, ce qui est un type paramétré sur un raw double
, pas un AD<double>
. À ma connaissance, cela signifie que la sortie n'est pas autodifferentiable.
Je suis à la recherche de quelques conseils sur si il est possible d'utiliser le Jacobien dans une grande opération, et de prendre le Jacobien de cette grande opération (qui ne ressemble à aucun opérateur arithmétique) ou si cela n'est pas possible.
EDIT: Cela a été mis en place pour une prime à la fois, mais je suis en train de mettre de nouveau pour voir si il y a une meilleure solution, car je pense que c'est important. Pour être un peu plus clair, les éléments qui la "bonne" réponse de besoins:
a) Un moyen de calcul de l'ordre arbitraire de produits dérivés.
b) Une façon intelligente de ne pas avoir à spécifier l'ordre des dérivés de l'a priori. Si le maximum de l'ordre de dérivation doit être connue au moment de la compilation, de l'ordre de la dérivée ne peut pas être déterminé de manière algorithmique. En outre, la spécification d'un très grand ordre que dans le courant de la réponse donnée conduira à la mémoire des questions de répartition et, j'imagine, des problèmes de performances.
c) en faisant Abstraction de la création de modèles de dérivés de l'ordre l'écart de l'utilisateur final. Ceci est important, car il peut être difficile de garder une trace de l'ordre de dérivés de besoin. C'est probablement quelque chose qui vient "gratuitement" si b) est résolu.
Si quelqu'un peut se fissurer, ce serait une formidable contribution et un outil très utile de l'opération.