Merged in feature/BAD_addressIssue151 (pull request #38)
first proposal to address issue #151release/4.3a0
commit
22fa6d3f70
106
.cproject
106
.cproject
|
@ -600,6 +600,7 @@
|
|||
</target>
|
||||
<target name="tests/testBayesTree.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>tests/testBayesTree.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -607,6 +608,7 @@
|
|||
</target>
|
||||
<target name="testBinaryBayesNet.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testBinaryBayesNet.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -654,6 +656,7 @@
|
|||
</target>
|
||||
<target name="testSymbolicBayesNet.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testSymbolicBayesNet.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -661,6 +664,7 @@
|
|||
</target>
|
||||
<target name="tests/testSymbolicFactor.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>tests/testSymbolicFactor.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -668,6 +672,7 @@
|
|||
</target>
|
||||
<target name="testSymbolicFactorGraph.run" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testSymbolicFactorGraph.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -683,6 +688,7 @@
|
|||
</target>
|
||||
<target name="tests/testBayesTree" path="inference" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>tests/testBayesTree</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -1114,6 +1120,7 @@
|
|||
</target>
|
||||
<target name="testErrors.run" path="linear" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testErrors.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -1343,6 +1350,46 @@
|
|||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testBTree.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testBTree.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testDSF.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testDSF.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testDSFMap.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testDSFMap.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testDSFVector.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testDSFVector.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testFixedVector.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testFixedVector.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="all" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j2</buildArguments>
|
||||
|
@ -1425,7 +1472,6 @@
|
|||
</target>
|
||||
<target name="testSimulated2DOriented.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testSimulated2DOriented.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -1465,7 +1511,6 @@
|
|||
</target>
|
||||
<target name="testSimulated2D.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testSimulated2D.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -1473,7 +1518,6 @@
|
|||
</target>
|
||||
<target name="testSimulated3D.run" path="slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testSimulated3D.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -1487,46 +1531,6 @@
|
|||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testBTree.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testBTree.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testDSF.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testDSF.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testDSFMap.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testDSFMap.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testDSFVector.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testDSFVector.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testFixedVector.run" path="build/gtsam_unstable/base/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testFixedVector.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testEliminationTree.run" path="build/gtsam/inference/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
|
@ -1784,6 +1788,7 @@
|
|||
</target>
|
||||
<target name="Generate DEB Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>cpack</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>-G DEB</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -1791,6 +1796,7 @@
|
|||
</target>
|
||||
<target name="Generate RPM Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>cpack</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>-G RPM</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -1798,6 +1804,7 @@
|
|||
</target>
|
||||
<target name="Generate TGZ Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>cpack</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>-G TGZ</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -1805,6 +1812,7 @@
|
|||
</target>
|
||||
<target name="Generate TGZ Source Package" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>cpack</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>--config CPackSourceConfig.cmake</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -2619,6 +2627,7 @@
|
|||
</target>
|
||||
<target name="testGraph.run" path="build/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testGraph.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -2626,6 +2635,7 @@
|
|||
</target>
|
||||
<target name="testJunctionTree.run" path="build/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testJunctionTree.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -2633,6 +2643,7 @@
|
|||
</target>
|
||||
<target name="testSymbolicBayesNetB.run" path="build/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>testSymbolicBayesNetB.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
@ -2742,6 +2753,14 @@
|
|||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testCallRecord.run" path="build/gtsam_unstable/nonlinear/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j5</buildArguments>
|
||||
<buildTarget>testCallRecord.run</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>true</useDefaultCommand>
|
||||
<runAllBuilders>true</runAllBuilders>
|
||||
</target>
|
||||
<target name="testGaussianFactor.run" path="build/linear/tests" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments>-j2</buildArguments>
|
||||
|
@ -3152,7 +3171,6 @@
|
|||
</target>
|
||||
<target name="tests/testGaussianISAM2" path="build/slam" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||
<buildCommand>make</buildCommand>
|
||||
<buildArguments/>
|
||||
<buildTarget>tests/testGaussianISAM2</buildTarget>
|
||||
<stopOnError>true</stopOnError>
|
||||
<useDefaultCommand>false</useDefaultCommand>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file Pose2SLAMExample.cpp
|
||||
* @file Pose2SLAMExampleExpressions.cpp
|
||||
* @brief Expressions version of Pose2SLAMExample.cpp
|
||||
* @date Oct 2, 2014
|
||||
* @author Frank Dellaert
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
|
@ -19,29 +19,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <gtsam_unstable/nonlinear/CallRecord.h>
|
||||
#include <gtsam/nonlinear/Values.h>
|
||||
#include <gtsam/base/Matrix.h>
|
||||
#include <gtsam/base/Testable.h>
|
||||
#include <gtsam/base/Manifold.h>
|
||||
#include <gtsam/base/VerticalBlockMatrix.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
// template meta-programming headers
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/plus.hpp>
|
||||
#include <boost/mpl/front.hpp>
|
||||
#include <boost/mpl/pop_front.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/empty_base.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
namespace MPL = boost::mpl::placeholders;
|
||||
|
||||
#include <new> // for placement new
|
||||
#include <map>
|
||||
|
||||
class ExpressionFactorBinaryTest;
|
||||
// Forward declare for testing
|
||||
|
||||
|
@ -71,29 +63,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* The CallRecord class stores the Jacobians of applying a function
|
||||
* with respect to each of its arguments. It also stores an executation trace
|
||||
* (defined below) for each of its arguments.
|
||||
*
|
||||
* It is sub-classed in the function-style ExpressionNode sub-classes below.
|
||||
*/
|
||||
template<int COLS>
|
||||
struct CallRecord {
|
||||
static size_t const N = 0;
|
||||
virtual void print(const std::string& indent) const {
|
||||
}
|
||||
virtual void startReverseAD(JacobianMap& jacobians) const {
|
||||
}
|
||||
virtual void reverseAD(const Matrix& dFdT, JacobianMap& jacobians) const {
|
||||
}
|
||||
typedef Eigen::Matrix<double, 2, COLS> Jacobian2T;
|
||||
virtual void reverseAD2(const Jacobian2T& dFdT,
|
||||
JacobianMap& jacobians) const {
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/// Handle Leaf Case: reverseAD ends here, by writing a matrix into Jacobians
|
||||
template<int ROWS, int COLS>
|
||||
|
@ -101,10 +70,10 @@ void handleLeafCase(const Eigen::Matrix<double, ROWS, COLS>& dTdA,
|
|||
JacobianMap& jacobians, Key key) {
|
||||
jacobians(key).block<ROWS, COLS>(0, 0) += dTdA; // block makes HUGE difference
|
||||
}
|
||||
/// Handle Leaf Case for Dynamic Matrix type (slower)
|
||||
template<>
|
||||
/// Handle Leaf Case for Dynamic ROWS Matrix type (slower)
|
||||
template<int COLS>
|
||||
inline void handleLeafCase(
|
||||
const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>& dTdA,
|
||||
const Eigen::Matrix<double, Eigen::Dynamic, COLS>& dTdA,
|
||||
JacobianMap& jacobians, Key key) {
|
||||
jacobians(key) += dTdA;
|
||||
}
|
||||
|
@ -193,45 +162,19 @@ public:
|
|||
content.ptr->startReverseAD(jacobians);
|
||||
}
|
||||
// Either add to Jacobians (Leaf) or propagate (Function)
|
||||
void reverseAD(const Matrix& dTdA, JacobianMap& jacobians) const {
|
||||
template<typename DerivedMatrix>
|
||||
void reverseAD(const Eigen::MatrixBase<DerivedMatrix> & dTdA,
|
||||
JacobianMap& jacobians) const {
|
||||
if (kind == Leaf)
|
||||
handleLeafCase(dTdA, jacobians, content.key);
|
||||
handleLeafCase(dTdA.eval(), jacobians, content.key);
|
||||
else if (kind == Function)
|
||||
content.ptr->reverseAD(dTdA, jacobians);
|
||||
}
|
||||
// Either add to Jacobians (Leaf) or propagate (Function)
|
||||
typedef Eigen::Matrix<double, 2, Dim> Jacobian2T;
|
||||
void reverseAD2(const Jacobian2T& dTdA, JacobianMap& jacobians) const {
|
||||
if (kind == Leaf)
|
||||
handleLeafCase(dTdA, jacobians, content.key);
|
||||
else if (kind == Function)
|
||||
content.ptr->reverseAD2(dTdA, jacobians);
|
||||
content.ptr->reverseAD(dTdA.eval(), jacobians);
|
||||
}
|
||||
|
||||
/// Define type so we can apply it as a meta-function
|
||||
typedef ExecutionTrace<T> type;
|
||||
};
|
||||
|
||||
/// Primary template calls the generic Matrix reverseAD pipeline
|
||||
template<size_t ROWS, class A>
|
||||
struct Select {
|
||||
typedef Eigen::Matrix<double, ROWS, traits::dimension<A>::value> Jacobian;
|
||||
static void reverseAD(const ExecutionTrace<A>& trace, const Jacobian& dTdA,
|
||||
JacobianMap& jacobians) {
|
||||
trace.reverseAD(dTdA, jacobians);
|
||||
}
|
||||
};
|
||||
|
||||
/// Partially specialized template calls the 2-dimensional output version
|
||||
template<class A>
|
||||
struct Select<2, A> {
|
||||
typedef Eigen::Matrix<double, 2, traits::dimension<A>::value> Jacobian;
|
||||
static void reverseAD(const ExecutionTrace<A>& trace, const Jacobian& dTdA,
|
||||
JacobianMap& jacobians) {
|
||||
trace.reverseAD2(dTdA, jacobians);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* Expression node. The superclass for objects that do the heavy lifting
|
||||
|
@ -479,8 +422,15 @@ template<class T>
|
|||
struct FunctionalBase: ExpressionNode<T> {
|
||||
static size_t const N = 0; // number of arguments
|
||||
|
||||
typedef CallRecord<traits::dimension<T>::value> Record;
|
||||
|
||||
struct Record {
|
||||
void print(const std::string& indent) const {
|
||||
}
|
||||
void startReverseAD(JacobianMap& jacobians) const {
|
||||
}
|
||||
template<typename SomeMatrix>
|
||||
void reverseAD(const SomeMatrix & dFdT, JacobianMap& jacobians) const {
|
||||
}
|
||||
};
|
||||
/// Construct an execution trace for reverse AD
|
||||
void trace(const Values& values, Record* record, char*& raw) const {
|
||||
// base case: does not do anything
|
||||
|
@ -539,7 +489,7 @@ struct GenerateFunctionalNode: Argument<T, A, Base::N + 1>, Base {
|
|||
typedef JacobianTrace<T, A, N> This;
|
||||
|
||||
/// Print to std::cout
|
||||
virtual void print(const std::string& indent) const {
|
||||
void print(const std::string& indent) const {
|
||||
Base::Record::print(indent);
|
||||
static const Eigen::IOFormat matlab(0, 1, " ", "; ", "", "", "[", "]");
|
||||
std::cout << This::dTdA.format(matlab) << std::endl;
|
||||
|
@ -547,25 +497,18 @@ struct GenerateFunctionalNode: Argument<T, A, Base::N + 1>, Base {
|
|||
}
|
||||
|
||||
/// Start the reverse AD process
|
||||
virtual void startReverseAD(JacobianMap& jacobians) const {
|
||||
void startReverseAD(JacobianMap& jacobians) const {
|
||||
Base::Record::startReverseAD(jacobians);
|
||||
Select<traits::dimension<T>::value, A>::reverseAD(This::trace, This::dTdA,
|
||||
jacobians);
|
||||
This::trace.reverseAD(This::dTdA, jacobians);
|
||||
}
|
||||
|
||||
/// Given df/dT, multiply in dT/dA and continue reverse AD process
|
||||
virtual void reverseAD(const Matrix& dFdT, JacobianMap& jacobians) const {
|
||||
template<int Rows, int Cols>
|
||||
void reverseAD(const Eigen::Matrix<double, Rows, Cols> & dFdT,
|
||||
JacobianMap& jacobians) const {
|
||||
Base::Record::reverseAD(dFdT, jacobians);
|
||||
This::trace.reverseAD(dFdT * This::dTdA, jacobians);
|
||||
}
|
||||
|
||||
/// Version specialized to 2-dimensional output
|
||||
typedef Eigen::Matrix<double, 2, traits::dimension<T>::value> Jacobian2T;
|
||||
virtual void reverseAD2(const Jacobian2T& dFdT,
|
||||
JacobianMap& jacobians) const {
|
||||
Base::Record::reverseAD2(dFdT, jacobians);
|
||||
This::trace.reverseAD2(dFdT * This::dTdA, jacobians);
|
||||
}
|
||||
};
|
||||
|
||||
/// Construct an execution trace for reverse AD
|
||||
|
@ -619,8 +562,16 @@ struct FunctionalNode {
|
|||
return static_cast<Argument<T, A, N> const &>(*this).expression;
|
||||
}
|
||||
|
||||
/// Provide convenience access to Record storage
|
||||
struct Record: public Base::Record {
|
||||
/// Provide convenience access to Record storage and implement
|
||||
/// the virtual function based interface of CallRecord using the CallRecordImplementor
|
||||
struct Record: public internal::CallRecordImplementor<Record,
|
||||
traits::dimension<T>::value>, public Base::Record {
|
||||
using Base::Record::print;
|
||||
using Base::Record::startReverseAD;
|
||||
using Base::Record::reverseAD;
|
||||
|
||||
virtual ~Record() {
|
||||
}
|
||||
|
||||
/// Access Value
|
||||
template<class A, size_t N>
|
||||
|
@ -633,7 +584,6 @@ struct FunctionalNode {
|
|||
typename Jacobian<T, A>::type& jacobian() {
|
||||
return static_cast<JacobianTrace<T, A, N>&>(*this).dTdA;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// Construct an execution trace for reverse AD
|
||||
|
|
|
@ -116,7 +116,7 @@ public:
|
|||
return root_->traceSize();
|
||||
}
|
||||
|
||||
/// trace execution, very unsafe, for testing purposes only
|
||||
/// trace execution, very unsafe, for testing purposes only //TODO this is not only used for testing, but in value() below!
|
||||
T traceExecution(const Values& values, ExecutionTrace<T>& trace,
|
||||
char* raw) const {
|
||||
return root_->traceExecution(values, trace, raw);
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* 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
|
||||
|
||||
* -------------------------------1------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file testCallRecord.cpp
|
||||
* @date November 21, 2014
|
||||
* @author Frank Dellaert
|
||||
* @author Paul Furgale
|
||||
* @author Hannes Sommer
|
||||
* @brief unit tests for CallRecord class
|
||||
*/
|
||||
|
||||
#include <gtsam_unstable/nonlinear/CallRecord.h>
|
||||
|
||||
#include <CppUnitLite/TestHarness.h>
|
||||
|
||||
#include <gtsam/base/Matrix.h>
|
||||
#include <gtsam/base/Testable.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace gtsam;
|
||||
|
||||
/* ************************************************************************* */
|
||||
static const int Cols = 3;
|
||||
|
||||
|
||||
int dynamicIfAboveMax(int i){
|
||||
if(i > MaxVirtualStaticRows){
|
||||
return Eigen::Dynamic;
|
||||
}
|
||||
else return i;
|
||||
}
|
||||
struct CallConfig {
|
||||
int compTimeRows;
|
||||
int compTimeCols;
|
||||
int runTimeRows;
|
||||
int runTimeCols;
|
||||
CallConfig() {}
|
||||
CallConfig(int rows, int cols):
|
||||
compTimeRows(dynamicIfAboveMax(rows)),
|
||||
compTimeCols(cols),
|
||||
runTimeRows(rows),
|
||||
runTimeCols(cols)
|
||||
{
|
||||
}
|
||||
CallConfig(int compTimeRows, int compTimeCols, int runTimeRows, int runTimeCols):
|
||||
compTimeRows(compTimeRows),
|
||||
compTimeCols(compTimeCols),
|
||||
runTimeRows(runTimeRows),
|
||||
runTimeCols(runTimeCols)
|
||||
{
|
||||
}
|
||||
|
||||
bool equals(const CallConfig & c, double /*tol*/) const {
|
||||
return
|
||||
this->compTimeRows == c.compTimeRows &&
|
||||
this->compTimeCols == c.compTimeCols &&
|
||||
this->runTimeRows == c.runTimeRows &&
|
||||
this->runTimeCols == c.runTimeCols;
|
||||
}
|
||||
void print(const std::string & prefix) const {
|
||||
std::cout << prefix << "{" << compTimeRows << ", " << compTimeCols << ", " << runTimeRows << ", " << runTimeCols << "}\n" ;
|
||||
}
|
||||
};
|
||||
|
||||
struct Record: public internal::CallRecordImplementor<Record, Cols> {
|
||||
virtual ~Record() {
|
||||
}
|
||||
void print(const std::string& indent) const {
|
||||
}
|
||||
void startReverseAD(JacobianMap& jacobians) const {
|
||||
}
|
||||
|
||||
mutable CallConfig cc;
|
||||
private:
|
||||
template<typename SomeMatrix>
|
||||
void reverseAD(const SomeMatrix & dFdT, JacobianMap& jacobians) const {
|
||||
cc.compTimeRows = SomeMatrix::RowsAtCompileTime;
|
||||
cc.compTimeCols = SomeMatrix::ColsAtCompileTime;
|
||||
cc.runTimeRows = dFdT.rows();
|
||||
cc.runTimeCols = dFdT.cols();
|
||||
}
|
||||
|
||||
template<typename Derived, int Rows, int OtherCols>
|
||||
friend struct internal::ReverseADImplementor;
|
||||
};
|
||||
|
||||
JacobianMap & NJM= *static_cast<JacobianMap *>(NULL);
|
||||
|
||||
/* ************************************************************************* */
|
||||
typedef Eigen::Matrix<double, Eigen::Dynamic, Cols> DynRowMat;
|
||||
|
||||
TEST(CallRecord, virtualReverseAdDispatching) {
|
||||
Record record;
|
||||
{
|
||||
const int Rows = 1;
|
||||
record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols))));
|
||||
record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols))));
|
||||
record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols))));
|
||||
}
|
||||
{
|
||||
const int Rows = 2;
|
||||
record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols))));
|
||||
record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols))));
|
||||
record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols))));
|
||||
}
|
||||
{
|
||||
const int Rows = 3;
|
||||
record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols))));
|
||||
record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols))));
|
||||
record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols))));
|
||||
}
|
||||
{
|
||||
const int Rows = MaxVirtualStaticRows;
|
||||
record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols))));
|
||||
record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols))));
|
||||
record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols))));
|
||||
}
|
||||
{
|
||||
const int Rows = MaxVirtualStaticRows + 1;
|
||||
record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols))));
|
||||
record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols))));
|
||||
record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols))));
|
||||
}
|
||||
{
|
||||
const int Rows = MaxVirtualStaticRows + 2;
|
||||
record.CallRecord::reverseAD(Eigen::Matrix<double, Rows, Cols>(), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Rows, Cols))));
|
||||
record.CallRecord::reverseAD(DynRowMat(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Cols, Rows, Cols))));
|
||||
record.CallRecord::reverseAD(Eigen::MatrixXd(Rows, Cols), NJM);
|
||||
EXPECT((assert_equal(record.cc, CallConfig(Eigen::Dynamic, Eigen::Dynamic, Rows, Cols))));
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
int main() {
|
||||
TestResult tr;
|
||||
return TestRegistry::runAllTests(tr);
|
||||
}
|
||||
/* ************************************************************************* */
|
||||
|
|
@ -38,7 +38,6 @@ template<class T> struct Incomplete;
|
|||
typedef mpl::vector<Pose3, Point3> MyTypes;
|
||||
typedef FunctionalNode<Point2, MyTypes>::type Generated;
|
||||
//Incomplete<Generated> incomplete;
|
||||
BOOST_MPL_ASSERT((boost::is_same< Matrix2, Generated::Record::Jacobian2T >));
|
||||
|
||||
// Try generating vectors of ExecutionTrace
|
||||
typedef mpl::vector<ExecutionTrace<Pose3>, ExecutionTrace<Point3> > ExpectedTraces;
|
||||
|
|
Loading…
Reference in New Issue