1

I have been using Eigen's AutoDiffScalar with much success and would now like to go over to the AutoDiffJacobian instead of doing this over by myself. Hence I created a learning example after have studied the AutoDiffJacobian.h, but something is wrong.

Functor:

template <typename Scalar>
struct adFunctor
{
  typedef Eigen::Matrix<Scalar, 3, 1> InputType;
  typedef Eigen::Matrix<Scalar, 2, 1> ValueType;
  typedef Eigen::Matrix<Scalar,
                        ValueType::RowsAtCompileTime,
                        InputType::RowsAtCompileTime> JacobianType;

  enum {
    InputsAtCompileTime = InputType::RowsAtCompileTime,
    ValuesAtCompileTime = ValueType::RowsAtCompileTime
  };

  adFunctor() {}

  size_t inputs() const { return InputsAtCompileTime; }

  void operator() (const InputType &input,
                   ValueType *output) const
  {
    Scalar s1 = Scalar(0), s2 = Scalar(0);

    /* Some operations to test the AD. */
    for (int i = 0; i < 3; i++)
    {
      s1 += log(input(i));
      s2 += sqrt(input(i));
    }

    (*output)(0) = s1;
    (*output)(1) = s2;
  }
};

Usage:

Eigen::Matrix<double, 3, 1> in;
in << 1,2,3;
Eigen::Matrix<double, 2, 1> out;
Eigen::AutoDiffJacobian< adFunctor<double> > adjac;
adjac(in, &out);

The error that is received from this as is follows:

/usr/include/eigen3/unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h: In instantiation of ‘void Eigen::AutoDiffJacobian<Functor>::operator()(const InputType&, Eigen::AutoDiffJacobian<Functor>::ValueType*, Eigen::AutoDiffJacobian<Functor>::JacobianType*) const [with Functor = adFunctor<double>; Eigen::AutoDiffJacobian<Functor>::InputType = Eigen::Matrix<double, 3, 1>; Eigen::AutoDiffJacobian<Functor>::ValueType = Eigen::Matrix<double, 2, 1>; Eigen::AutoDiffJacobian<Functor>::JacobianType = Eigen::Matrix<double, 2, 3, 0, 2, 3>]’:
/home/emifre/Git/autodiff-test/src/autodiff_test.cpp:55:17:   required from here
/usr/include/eigen3/unsupported/Eigen/src/AutoDiff/AutoDiffJacobian.h:69:24: error: no matching function for call to ‘Eigen::AutoDiffJacobian<adFunctor<double> >::operator()(Eigen::AutoDiffJacobian<adFunctor<double> >::ActiveInput&, Eigen::AutoDiffJacobian<adFunctor<double> >::ActiveValue*) const’
     Functor::operator()(ax, &av);
     ~~~~~~~~~~~~~~~~~~~^~~~~~~~~
/home/emifre/Git/autodiff-test/src/autodiff_test.cpp:27:8: note: candidate: void adFunctor<Scalar>::operator()(const InputType&, adFunctor<Scalar>::ValueType*) const [with Scalar = double; adFunctor<Scalar>::InputType = Eigen::Matrix<double, 3, 1>; adFunctor<Scalar>::ValueType = Eigen::Matrix<double, 2, 1>]
   void operator() (const InputType &input,
        ^~~~~~~~
/home/emifre/Git/autodiff-test/src/autodiff_test.cpp:27:8: note:   no known conversion for argument 2 from ‘Eigen::AutoDiffJacobian<adFunctor<double> >::ActiveValue* {aka Eigen::Matrix<Eigen::AutoDiffScalar<Eigen::Matrix<double, 3, 1> >, 2, 1, 0, 2, 1>*}’ to ‘adFunctor<double>::ValueType* {aka Eigen::Matrix<double, 2, 1>*}’

From this error it seems that I am somehow not having the correct types for my functor for the second call to the functor in AutoDiffJacobian.h, but the first call to it works. I hope someone here has an idea why and can help, maybe I have just misunderstood the usage.

EDIT: A compilable example that shows the problem:

#include <Eigen/Dense>
#include <unsupported/Eigen/AutoDiff>

/*
 * Testing differentiation that will produce a Jacobian, using functors and the
 * AutoDiffJacobian helper.
 */

template <typename Scalar>
struct adFunctor
{
  typedef Eigen::Matrix<Scalar, 3, 1> InputType;
  typedef Eigen::Matrix<Scalar, 2, 1> ValueType;
  typedef Eigen::Matrix<Scalar,
                        ValueType::RowsAtCompileTime,
                        InputType::RowsAtCompileTime> JacobianType;

  enum {
    InputsAtCompileTime = InputType::RowsAtCompileTime,
    ValuesAtCompileTime = ValueType::RowsAtCompileTime
  };

  adFunctor() {}

  size_t inputs() const { return InputsAtCompileTime; }

  void operator() (const InputType &input,
                   ValueType *output) const
  {
    Scalar s1 = Scalar(0), s2 = Scalar(0);

    /* Some operations to test the AD. */
    for (int i = 0; i < 3; i++)
    {
      s1 += log(input(i));
      s2 += sqrt(input(i));
    }

    (*output)(0) = s1;
    (*output)(1) = s2;
  }
};



int main(int argc, char *argv[])
{
  Eigen::Matrix<double, 3, 1> in;
  in << 1,2,3;
  Eigen::Matrix<double, 2, 1> out;
  Eigen::AutoDiffJacobian< adFunctor<double> > adjac;
  adjac(in, &out);

  return 0;
}
Korken
  • 101
  • 7
  • Solve compiler errors one by one, these are pretty clear, Don't ask here for doing that for you. At least post a [MCVE] that reproduces the problem please. – πάντα ῥεῖ Sep 11 '16 at 10:46
  • I have added a full example. – Korken Sep 11 '16 at 11:19
  • I was able to solve the first one, my Google-fu was not on top. But one error remains that eludes me, the second call to the functor by AutoDiffJacobian says that the type of the functor does not match, but the first call goes through without a problem. There must be a usage pattern that I am missing, but I cannot figure out what. – Korken Sep 11 '16 at 11:59

2 Answers2

3

Okey, after a lot of testing I got it to work. It was just me misunderstanding the error from the compiler that said it straight out, I was missing the template for the operator itself.

It just needs to be changed to:

template <typename T1, typename T2>
void operator() (const T1 &input, T2 *output) const

Now it works like a treat! I hope someone more than me has usage of this.

Korken
  • 101
  • 7
0

Maybe that is too late for a reply. I post my solution here. The reason why compile failed is that inside AutoDiffScalar template class, it requires the custom function to implement the operator() with arguments are Vectors with ActiveScalar as scalars. Calling custom function inside AutoDiffJacobian - ActiveType overload The ActiveScalar is a AutoDiffScalar<...> type.

Therefore, the custom class must provide an overload of operators () that accept such arguments. Besides, they also require an overload that accepts raw InputType/ValueType. Calling custom function inside AutoDiffJacobian - OriginalType overload

Then, to have both of them, it is better to have a template implementation, e.g.,

template<typename T>
void operator()(const Eigen::Matrix<T, InputsAtCompileTime, 1>& x,
                Eigen::Matrix<T, ValuesAtCompileTime,1>* v) const{
 // Computation codes here ...
}

This is better than the solution from @Korken which accepts any type.

Wei
  • 1
  • 1
  • 2