@@ -347,6 +347,75 @@ GTSAM_EXPORT Matrix expm(const Matrix& A, size_t K=7);
347347
348348std::string formatMatrixIndented (const std::string& label, const Matrix& matrix, bool makeVectorHorizontal = false );
349349
350+ /* *
351+ * Functor that implements multiplication of a vector b with the inverse of a
352+ * matrix A. The derivatives are inspired by Mike Giles' "An extended collection
353+ * of matrix derivative results for forward and reverse mode algorithmic
354+ * differentiation", at https://people.maths.ox.ac.uk/gilesm/files/NA-08-01.pdf
355+ */
356+ template <int N>
357+ struct MultiplyWithInverse {
358+ typedef Eigen::Matrix<double , N, 1 > VectorN;
359+ typedef Eigen::Matrix<double , N, N> MatrixN;
360+
361+ // / A.inverse() * b, with optional derivatives
362+ VectorN operator ()(const MatrixN& A, const VectorN& b,
363+ OptionalJacobian<N, N* N> H1 = {},
364+ OptionalJacobian<N, N> H2 = {}) const {
365+ const MatrixN invA = A.inverse ();
366+ const VectorN c = invA * b;
367+ // The derivative in A is just -[c[0]*invA c[1]*invA ... c[N-1]*invA]
368+ if (H1)
369+ for (size_t j = 0 ; j < N; j++)
370+ H1->template middleCols <N>(N * j) = -c[j] * invA;
371+ // The derivative in b is easy, as invA*b is just a linear map:
372+ if (H2) *H2 = invA;
373+ return c;
374+ }
375+ };
376+
377+ /* *
378+ * Functor that implements multiplication with the inverse of a matrix, itself
379+ * the result of a function f. It turn out we only need the derivatives of the
380+ * operator phi(a): b -> f(a) * b
381+ */
382+ template <typename T, int N>
383+ struct MultiplyWithInverseFunction {
384+ inline constexpr static auto M = traits<T>::dimension;
385+ typedef Eigen::Matrix<double , N, 1 > VectorN;
386+ typedef Eigen::Matrix<double , N, N> MatrixN;
387+
388+ // The function phi should calculate f(a)*b, with derivatives in a and b.
389+ // Naturally, the derivative in b is f(a).
390+ typedef std::function<VectorN(
391+ const T&, const VectorN&, OptionalJacobian<N, M>, OptionalJacobian<N, N>)>
392+ Operator;
393+
394+ // / Construct with function as explained above
395+ MultiplyWithInverseFunction (const Operator& phi) : phi_(phi) {}
396+
397+ // / f(a).inverse() * b, with optional derivatives
398+ VectorN operator ()(const T& a, const VectorN& b,
399+ OptionalJacobian<N, M> H1 = {},
400+ OptionalJacobian<N, N> H2 = {}) const {
401+ MatrixN A;
402+ phi_ (a, b, {}, A); // get A = f(a) by calling f once
403+ const MatrixN invA = A.inverse ();
404+ const VectorN c = invA * b;
405+
406+ if (H1) {
407+ Eigen::Matrix<double , N, M> H;
408+ phi_ (a, c, H, {}); // get derivative H of forward mapping
409+ *H1 = -invA* H;
410+ }
411+ if (H2) *H2 = invA;
412+ return c;
413+ }
414+
415+ private:
416+ const Operator phi_;
417+ };
418+
350419GTSAM_EXPORT Matrix LLt (const Matrix& A);
351420
352421GTSAM_EXPORT Matrix RtR (const Matrix& A);
0 commit comments