/* ---------------------------------------------------------------------------- * 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 Expression.h * @date September 18, 2014 * @author Frank Dellaert * @author Paul Furgale * @brief Expressions for Block Automatic Differentiation */ #pragma once #include "Expression-inl.h" #include #include namespace gtsam { /** * Expression class that supports automatic differentiation */ template class Expression { private: // Paul's trick shared pointer, polymorphic root of entire expression tree boost::shared_ptr > root_; public: // Construct a constant expression Expression(const T& value) : root_(new ConstantExpression(value)) { } // Construct a leaf expression, with Key Expression(const Key& key) : root_(new LeafExpression(key)) { } // Construct a leaf expression, with Symbol Expression(const Symbol& symbol) : root_(new LeafExpression(symbol)) { } // Construct a leaf expression, creating Symbol Expression(unsigned char c, size_t j) : root_(new LeafExpression(Symbol(c, j))) { } /// Construct a nullary method expression template Expression(const Expression& expression, T (A::*method)(boost::optional) const) { root_.reset( new UnaryExpression(boost::bind(method, _1, _2), expression)); } /// Construct a unary function expression template Expression(typename UnaryExpression::Function function, const Expression& expression) { root_.reset(new UnaryExpression(function, expression)); } /// Construct a unary method expression template Expression(const Expression& expression1, T (A1::*method)(const A2&, boost::optional, boost::optional) const, const Expression& expression2) { root_.reset( new BinaryExpression(boost::bind(method, _1, _2, _3, _4), expression1, expression2)); } /// Construct a binary function expression template Expression(typename BinaryExpression::Function function, const Expression& expression1, const Expression& expression2) { root_.reset( new BinaryExpression(function, expression1, expression2)); } /// Construct a ternary function expression template Expression(typename TernaryExpression::Function function, const Expression& expression1, const Expression& expression2, const Expression& expression3) { root_.reset( new TernaryExpression(function, expression1, expression2, expression3)); } /// Return keys that play in this expression std::set keys() const { return root_->keys(); } /// Return value and optional derivatives T value(const Values& values) const { return root_->value(values); } /// Return value and derivatives Augmented augmented(const Values& values) const { return root_->augmented(values); } const boost::shared_ptr >& root() const { return root_; } }; // http://stackoverflow.com/questions/16260445/boost-bind-to-operator template struct apply_compose { typedef T result_type; T operator()(const T& x, const T& y, boost::optional H1, boost::optional H2) const { return x.compose(y, H1, H2); } }; /// Construct a product expression, assumes T::compose(T) -> T template Expression operator*(const Expression& expression1, const Expression& expression2) { return Expression(boost::bind(apply_compose(), _1, _2, _3, _4), expression1, expression2); } }