/** * @file GaussianFactor.h * @brief Linear Factor....A Gaussian * @brief linearFactor * @author Christian Potthast */ // \callgraph #pragma once #include #include #include #include #include #include "Factor.h" #include "Matrix.h" #include "VectorConfig.h" #include "SharedDiagonal.h" #include "SymbolMap.h" namespace gtsam { class GaussianConditional; class Ordering; /** * Base Class for a linear factor. * GaussianFactor is non-mutable (all methods const!). * The factor value is exp(-0.5*||Ax-b||^2) */ class GaussianFactor: boost::noncopyable, public Factor { public: typedef boost::shared_ptr shared_ptr; typedef SymbolMap::iterator iterator; typedef SymbolMap::const_iterator const_iterator; protected: SharedDiagonal model_; // Gaussian noise model with diagonal covariance matrix SymbolMap As_; // linear matrices Vector b_; // right-hand-side public: // TODO: eradicate, as implies non-const GaussianFactor() { } /** Construct Null factor */ GaussianFactor(const Vector& b_in) : b_(b_in) { } /** Construct unary factor */ GaussianFactor(const Symbol& key1, const Matrix& A1, const Vector& b, const SharedDiagonal& model) : b_(b), model_(model) { As_.insert(make_pair(key1, A1)); } /** Construct binary factor */ GaussianFactor(const Symbol& key1, const Matrix& A1, const Symbol& key2, const Matrix& A2, const Vector& b, const SharedDiagonal& model) : b_(b), model_(model) { As_.insert(make_pair(key1, A1)); As_.insert(make_pair(key2, A2)); } /** Construct ternary factor */ GaussianFactor(const Symbol& key1, const Matrix& A1, const Symbol& key2, const Matrix& A2, const Symbol& key3, const Matrix& A3, const Vector& b, const SharedDiagonal& model) : b_(b), model_(model) { As_.insert(make_pair(key1, A1)); As_.insert(make_pair(key2, A2)); As_.insert(make_pair(key3, A3)); } /** Construct an n-ary factor */ GaussianFactor(const std::vector > &terms, const Vector &b, const SharedDiagonal& model) : b_(b), model_(model) { for(unsigned int i=0; i& cg); /** * Constructor that combines a set of factors * @param factors Set of factors to combine */ GaussianFactor(const std::vector & factors); // Implementing Testable virtual functions void print(const std::string& s = "") const; bool equals(const Factor& lf, double tol = 1e-9) const; // Implementing Factor virtual functions Vector unweighted_error(const VectorConfig& c) const; /** (A*x-b) */ Vector error_vector(const VectorConfig& c) const; /** (A*x-b)/sigma */ double error(const VectorConfig& c) const; /** 0.5*(A*x-b)'*D*(A*x-b) */ std::size_t size() const { return As_.size();} /** STL like, return the iterator pointing to the first node */ const_iterator const begin() const { return As_.begin();} /** STL like, return the iterator pointing to the last node */ const_iterator const end() const { return As_.end(); } /** check if empty */ bool empty() const { return b_.size() == 0;} /** get a copy of b */ const Vector& get_b() const { return b_; } /** get a copy of sigmas */ const Vector& get_sigmas() const { return model_->sigmas(); } /** get a copy of model */ const SharedDiagonal& get_model() const { return model_; } /** * get a copy of the A matrix from a specific node * O(log n) */ const Matrix& get_A(const Symbol& key) const { return As_.at(key); } /** operator[] syntax for get */ inline const Matrix& operator[](const Symbol& name) const { return get_A(name); } /** Check if factor involves variable with key */ bool involves(const Symbol& key) const { const_iterator it = As_.find(key); return (it != As_.end()); } /** * return the number of rows from the b vector * @return a integer with the number of rows from the b vector */ int numberOfRows() const { return b_.size();} /** * Find all variables * @return The set of all variable keys */ std::list keys() const; /** * return the first key * @return The set of all variable keys */ Symbol key1() const { return As_.begin()->first; } /** * return the first key * @return The set of all variable keys */ Symbol key2() const { if (As_.size() < 2) throw std::invalid_argument("GaussianFactor: less than 2 keys!"); return (++(As_.begin()))->first; } /** * Find all variables and their dimensions * @return The set of all variable/dimension pairs */ Dimensions dimensions() const; /** * Get the dimension of a particular variable * @param key is the name of the variable * @return the size of the variable */ size_t getDim(const Symbol& key) const; /** * Add to separator set if this factor involves key, but don't add key itself * @param key * @param separator set to add to */ void tally_separator(const Symbol& key, std::set& separator) const; /** * Return A*x */ Vector operator*(const VectorConfig& x) const; /** * Return A^x */ VectorConfig operator^(const Vector& e) const; /** * Return (dense) matrix associated with factor * @param ordering of variables needed for matrix column order * @param set weight to true to bake in the weights */ std::pair matrix(const Ordering& ordering, bool weight = true) const; /** * Return (dense) matrix associated with factor * The returned system is an augmented matrix: [A b] * @param ordering of variables needed for matrix column order * @param set weight to use whitening to bake in weights */ Matrix matrix_augmented(const Ordering& ordering, bool weight = true) const; /** * Return vectors i, j, and s to generate an m-by-n sparse matrix * such that S(i(k),j(k)) = s(k), which can be given to MATLAB's sparse. * As above, the standard deviations are baked into A and b * @param first column index for each variable */ boost::tuple, std::list, std::list > sparse(const Dimensions& columnIndices) const; /** * Create a GaussianFactor on one variable 'alpha' (step size), in direction d * @param x: starting point for search * @param d: search direction */ shared_ptr alphaFactor(const Symbol& key, const VectorConfig& x, const VectorConfig& d) const; /* ************************************************************************* */ // MUTABLE functions. FD:on the path to being eradicated /* ************************************************************************* */ /** insert, copies A */ void insert(const Symbol& key, const Matrix& A) { As_.insert(std::make_pair(key, A)); } /** set RHS, copies b */ void set_b(const Vector& b) { this->b_ = b; } // set A matrices for the linear factor, same as insert ? inline void set_A(const Symbol& key, const Matrix &A) { insert(key, A); } /** * Current Implementation: Full QR factorization * eliminate (in place!) one of the variables connected to this factor * @param key the key of the node to be eliminated * @return a new factor and a conditional gaussian on the eliminated variable */ std::pair, shared_ptr> eliminate(const Symbol& key) const; /** * Take the factor f, and append to current matrices. Not very general. * @param f linear factor graph * @param m final number of rows of f, needs to be known in advance * @param pos where to insert in the m-sized matrices */ void append_factor(GaussianFactor::shared_ptr f, size_t m, size_t pos); }; // GaussianFactor /* ************************************************************************* */ /** * creates a C++ string a la "x3", "m768" * @param c the base character * @param index the integer to be added * @return a C++ string */ std::string symbol(char c, int index); } // namespace gtsam