191 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			191 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C++
		
	
	
/* ----------------------------------------------------------------------------
 | 
						|
 | 
						|
 * GTSAM Copyright 2010, Georgia Tech Research Corporation, 
 | 
						|
 * Atlanta, Georgia 30332-0415
 | 
						|
 * All Rights Reserved
 | 
						|
 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
 | 
						|
 | 
						|
 * See LICENSE for the license information
 | 
						|
 | 
						|
 * -------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/**
 | 
						|
 * @file CallRecord.h
 | 
						|
 * @date November 21, 2014
 | 
						|
 * @author Frank Dellaert
 | 
						|
 * @author Paul Furgale
 | 
						|
 * @author Hannes Sommer
 | 
						|
 * @brief Internals for Expression.h, not for general consumption
 | 
						|
 */
 | 
						|
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include <gtsam/base/VerticalBlockMatrix.h>
 | 
						|
#include <gtsam/base/FastVector.h>
 | 
						|
#include <gtsam/base/Matrix.h>
 | 
						|
 | 
						|
#include <boost/mpl/transform.hpp>
 | 
						|
 | 
						|
namespace gtsam {
 | 
						|
 | 
						|
class JacobianMap;
 | 
						|
// forward declaration
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
/**
 | 
						|
 * MaxVirtualStaticRows defines how many separate virtual reverseAD with specific
 | 
						|
 * static rows (1..MaxVirtualStaticRows) methods will be part of the CallRecord interface.
 | 
						|
 */
 | 
						|
const int MaxVirtualStaticRows = 4;
 | 
						|
 | 
						|
namespace internal {
 | 
						|
 | 
						|
/**
 | 
						|
 * ConvertToDynamicIf converts to a dense matrix with dynamic rows iff
 | 
						|
 * ConvertToDynamicRows (colums stay as they are) otherwise
 | 
						|
 * it just passes dense Eigen matrices through.
 | 
						|
 */
 | 
						|
template<bool ConvertToDynamicRows>
 | 
						|
struct ConvertToDynamicRowsIf {
 | 
						|
  template<typename Derived>
 | 
						|
  static Eigen::Matrix<double, Eigen::Dynamic, Derived::ColsAtCompileTime> convert(
 | 
						|
      const Eigen::MatrixBase<Derived> & x) {
 | 
						|
    return x;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct ConvertToDynamicRowsIf<false> {
 | 
						|
  template<int Rows, int Cols>
 | 
						|
  static const Eigen::Matrix<double, Rows, Cols> & convert(
 | 
						|
      const Eigen::Matrix<double, Rows, Cols> & x) {
 | 
						|
    return x;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Recursive definition of an interface having several purely
 | 
						|
 * virtual _reverseAD(const Eigen::Matrix<double, Rows, Cols> &, JacobianMap&)
 | 
						|
 * with Rows in 1..MaxSupportedStaticRows
 | 
						|
 */
 | 
						|
template<int MaxSupportedStaticRows, int Cols>
 | 
						|
struct ReverseADInterface: ReverseADInterface<MaxSupportedStaticRows - 1, Cols> {
 | 
						|
  using ReverseADInterface<MaxSupportedStaticRows - 1, Cols>::_reverseAD;
 | 
						|
  virtual void _reverseAD(
 | 
						|
      const Eigen::Matrix<double, MaxSupportedStaticRows, Cols> & dFdT,
 | 
						|
      JacobianMap& jacobians) const = 0;
 | 
						|
};
 | 
						|
 | 
						|
template<int Cols>
 | 
						|
struct ReverseADInterface<0, Cols> {
 | 
						|
  virtual void _reverseAD(
 | 
						|
      const Eigen::Matrix<double, Eigen::Dynamic, Cols> & dFdT,
 | 
						|
      JacobianMap& jacobians) const = 0;
 | 
						|
  virtual void _reverseAD(const Matrix & dFdT,
 | 
						|
      JacobianMap& jacobians) const = 0;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * ReverseADImplementor is a utility class used by CallRecordImplementor to
 | 
						|
 * implementing the recursive ReverseADInterface interface.
 | 
						|
 */
 | 
						|
template<typename Derived, int MaxSupportedStaticRows, int Cols>
 | 
						|
struct ReverseADImplementor: ReverseADImplementor<Derived,
 | 
						|
    MaxSupportedStaticRows - 1, Cols> {
 | 
						|
private:
 | 
						|
  using ReverseADImplementor<Derived, MaxSupportedStaticRows - 1, Cols>::_reverseAD;
 | 
						|
  virtual void _reverseAD(
 | 
						|
      const Eigen::Matrix<double, MaxSupportedStaticRows, Cols> & dFdT,
 | 
						|
      JacobianMap& jacobians) const {
 | 
						|
    static_cast<const Derived *>(this)->reverseAD(dFdT, jacobians);
 | 
						|
  }
 | 
						|
  friend struct internal::ReverseADImplementor<Derived,
 | 
						|
      MaxSupportedStaticRows + 1, Cols>;
 | 
						|
};
 | 
						|
 | 
						|
template<typename Derived, int Cols>
 | 
						|
struct ReverseADImplementor<Derived, 0, Cols> : virtual internal::ReverseADInterface<
 | 
						|
    MaxVirtualStaticRows, Cols> {
 | 
						|
private:
 | 
						|
  using internal::ReverseADInterface<MaxVirtualStaticRows, Cols>::_reverseAD;
 | 
						|
  const Derived & derived() const {
 | 
						|
    return static_cast<const Derived&>(*this);
 | 
						|
  }
 | 
						|
  virtual void _reverseAD(
 | 
						|
      const Eigen::Matrix<double, Eigen::Dynamic, Cols> & dFdT,
 | 
						|
      JacobianMap& jacobians) const {
 | 
						|
    derived().reverseAD(dFdT, jacobians);
 | 
						|
  }
 | 
						|
  virtual void _reverseAD(const Matrix & dFdT, JacobianMap& jacobians) const {
 | 
						|
    derived().reverseAD(dFdT, jacobians);
 | 
						|
  }
 | 
						|
  friend struct internal::ReverseADImplementor<Derived, 1, Cols>;
 | 
						|
};
 | 
						|
 | 
						|
} // namespace internal
 | 
						|
 | 
						|
/**
 | 
						|
 * The CallRecord class stores the Jacobians of applying a function
 | 
						|
 * with respect to each of its arguments. It also stores an execution trace
 | 
						|
 * (defined below) for each of its arguments.
 | 
						|
 *
 | 
						|
 * It is implemented in the function-style ExpressionNode's nested Record class below.
 | 
						|
 */
 | 
						|
template<int Cols>
 | 
						|
struct CallRecord: virtual private internal::ReverseADInterface<
 | 
						|
    MaxVirtualStaticRows, Cols> {
 | 
						|
 | 
						|
  inline void print(const std::string& indent) const {
 | 
						|
    _print(indent);
 | 
						|
  }
 | 
						|
 | 
						|
  inline void startReverseAD(JacobianMap& jacobians) const {
 | 
						|
    _startReverseAD(jacobians);
 | 
						|
  }
 | 
						|
 | 
						|
  template<int Rows>
 | 
						|
  inline void reverseAD(const Eigen::Matrix<double, Rows, Cols> & dFdT,
 | 
						|
      JacobianMap& jacobians) const {
 | 
						|
    _reverseAD(
 | 
						|
        internal::ConvertToDynamicRowsIf<(Rows > MaxVirtualStaticRows)>::convert(
 | 
						|
            dFdT), jacobians);
 | 
						|
  }
 | 
						|
 | 
						|
  inline void reverseAD(const Matrix & dFdT, JacobianMap& jacobians) const {
 | 
						|
    _reverseAD(dFdT, jacobians);
 | 
						|
  }
 | 
						|
 | 
						|
  virtual ~CallRecord() {
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  virtual void _print(const std::string& indent) const = 0;
 | 
						|
  virtual void _startReverseAD(JacobianMap& jacobians) const = 0;
 | 
						|
  using internal::ReverseADInterface<MaxVirtualStaticRows, Cols>::_reverseAD;
 | 
						|
};
 | 
						|
 | 
						|
namespace internal {
 | 
						|
/**
 | 
						|
 * The CallRecordImplementor implements the CallRecord interface for a Derived class by
 | 
						|
 * delegating to its corresponding (templated) non-virtual methods.
 | 
						|
 */
 | 
						|
template<typename Derived, int Cols>
 | 
						|
struct CallRecordImplementor: public CallRecord<Cols>,
 | 
						|
    private ReverseADImplementor<Derived, MaxVirtualStaticRows, Cols> {
 | 
						|
private:
 | 
						|
  const Derived & derived() const {
 | 
						|
    return static_cast<const Derived&>(*this);
 | 
						|
  }
 | 
						|
  virtual void _print(const std::string& indent) const {
 | 
						|
    derived().print(indent);
 | 
						|
  }
 | 
						|
  virtual void _startReverseAD(JacobianMap& jacobians) const {
 | 
						|
    derived().startReverseAD(jacobians);
 | 
						|
  }
 | 
						|
  template<typename D, int R, int C> friend struct ReverseADImplementor;
 | 
						|
};
 | 
						|
 | 
						|
} // namespace internal
 | 
						|
 | 
						|
} // gtsam
 |