Suppose . This function takes a point
as input and produces the vector
as output. Then the Jacobian matrix of
is defined to be an m×n matrix, denoted by
, whose
entry is:
or explicitly:
The Hessian matrix
of f is a square
matrix, usually defined and arranged as follows:
We can approximation Hessian Matrix by
Example: suppose you have the following function:
In the next you will see how can we compute the Jacobian matrix with Automatic Differentiation
and Numerical Differentiation
Refs: 1
First let's create a generic functor,
template<typename _Scalar, int NX = Eigen::Dynamic, int NY = Eigen::Dynamic>
struct VectorFunction {
typedef _Scalar Scalar;
enum
{
InputsAtCompileTime = NX,
ValuesAtCompileTime = NY
};
// Also needed by Eigen
typedef Eigen::Matrix<Scalar, NX, 1> InputType;
typedef Eigen::Matrix<Scalar, NY, 1> ValueType;
// Vector function
template <typename Scalar>
void operator()(const Eigen::Matrix<Scalar, NX, 1>& x, Eigen::Matrix<Scalar, NY, 1>* y ) const
{
(*y)(0,0) = 10.0*pow(x(0,0)+3.0,2) +pow(x(1,0)-5.0,2) ;
(*y)(1,0) = (x(0,0)+1)*x(1,0);
(*y)(2,0) = sin(x(0,0))*x(1,0);
}
};
Now lets prepare the input and out matrices and compute the jacobian:
Eigen::Matrix<double, 2, 1> x;
Eigen::Matrix<double, 3, 1> y;
Eigen::Matrix<double, 3,2> fjac;
Eigen::AutoDiffJacobian< VectorFunction<double,2, 3> > JacobianDerivatives;
// Set values in x, y and fjac...
x(0,0)=2.0;
x(1,0)=3.0;
JacobianDerivatives(x, &y, &fjac);
std::cout << "jacobian of matrix at "<< x(0,0)<<","<<x(1,0) <<" is:\n " << fjac << std::endl;
Full source code here
First let's create a generic functor,
// Generic functor
template<typename _Scalar, int NX = Eigen::Dynamic, int NY = Eigen::Dynamic>
struct Functor
{
// Information that tells the caller the numeric type (eg. double) and size (input / output dim)
typedef _Scalar Scalar;
enum {
InputsAtCompileTime = NX,
ValuesAtCompileTime = NY
};
// Tell the caller the matrix sizes associated with the input, output, and jacobian
typedef Eigen::Matrix<Scalar,InputsAtCompileTime,1> InputType;
typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;
// Local copy of the number of inputs
int m_inputs, m_values;
// Two constructors:
Functor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
Functor(int inputs, int values) : m_inputs(inputs), m_values(values) {}
// Get methods for users to determine function input and output dimensions
int inputs() const { return m_inputs; }
int values() const { return m_values; }
};
Then inherit from the above generic functor and override the operator()
and implement your function:
struct simpleFunctor : Functor<double>
{
simpleFunctor(void): Functor<double>(2,3)
{
}
// Implementation of the objective function
// y0 = 10*(x0+3)^2 + (x1-5)^2
// y1 = (x0+1)*x1
// y2 = sin(x0)*x1
int operator()(const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const
{
fvec(0) = 10.0*pow(x(0)+3.0,2) +pow(x(1)-5.0,2) ;
fvec(1) = (x(0)+1)*x(1);
fvec(2) = sin(x(0))*x(1);
return 0;
}
};
Now you can easily use it:
simpleFunctor functor;
Eigen::NumericalDiff<simpleFunctor,Eigen::NumericalDiffMode::Central> numDiff(functor);
Eigen::MatrixXd fjac(3,2);
Eigen::VectorXd x(2);
x(0) = 2.0;
x(1) = 3.0;
numDiff.df(x,fjac);
std::cout << "jacobian of matrix at "<< x(0)<<","<<x(1) <<" is:\n " << fjac << std::endl;
Full source code: here