gtsam/gtsam/linear/SubgraphSolver.h

139 lines
4.5 KiB
C
Raw Normal View History

2012-06-09 00:45:16 +08:00
/* ----------------------------------------------------------------------------
* 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 SubgraphSolver.h
* @brief Subgraph Solver from IROS 2010
* @date 2010
* @author Frank Dellaert
* @author Yong Dian Jian
*/
2012-06-09 00:45:16 +08:00
#pragma once
2012-06-09 00:45:16 +08:00
#include <gtsam/linear/ConjugateGradientSolver.h>
#include <gtsam/linear/SubgraphBuilder.h>
#include <map>
#include <utility> // pair
2012-06-09 00:45:16 +08:00
namespace gtsam {
// Forward declarations
class GaussianFactorGraph;
class GaussianBayesNet;
class SubgraphPreconditioner;
2013-08-06 06:31:05 +08:00
struct GTSAM_EXPORT SubgraphSolverParameters
2019-04-04 21:23:02 +08:00
: public ConjugateGradientParameters {
SubgraphBuilderParameters builderParams;
explicit SubgraphSolverParameters(const SubgraphBuilderParameters &p = SubgraphBuilderParameters())
: builderParams(p) {}
2019-04-04 21:23:02 +08:00
void print() const { Base::print(); }
void print(std::ostream &os) const override {
Base::print(os);
}
2012-06-09 10:42:45 +08:00
};
2012-06-09 00:45:16 +08:00
/**
2019-04-04 21:23:02 +08:00
* This class implements the linear SPCG solver presented in Dellaert et al in
* IROS'10.
*
2019-04-04 21:23:02 +08:00
* Given a linear least-squares problem \f$ f(x) = |A x - b|^2 \f$. We split the
* problem into \f$ f(x) = |A_t - b_t|^2 + |A_c - b_c|^2 \f$ where \f$ A_t \f$
* denotes the "tree" part, and \f$ A_c \f$ denotes the "constraint" part.
*
2019-04-04 21:23:02 +08:00
* \f$A_t \f$ is factorized into \f$ Q_t R_t \f$, and we compute
* \f$ c_t = Q_t^{-1} b_t \f$, and \f$ x_t = R_t^{-1} c_t \f$ accordingly.
*
* Then we solve a reparametrized problem
* \f$ f(y) = |y|^2 + |A_c R_t^{-1} y -\bar{b_y}|^2 \f$,
* where \f$ y = R_t(x - x_t) \f$, and \f$ \bar{b_y} = (b_c - A_c x_t) \f$
*
* In the matrix form, it is equivalent to solving
* \f$ [A_c R_t^{-1} ; I ] y = [\bar{b_y} ; 0] \f$.
* We can solve it with the least-squares variation of the conjugate gradient
* method.
*
* To use it in nonlinear optimization, please see the following example
*
* LevenbergMarquardtParams parameters;
* parameters.linearSolverType = NonlinearOptimizerParams::CONJUGATE_GRADIENT;
* parameters.iterativeParams = std::make_shared<SubgraphSolverParameters>();
* LevenbergMarquardtOptimizer optimizer(graph, initialEstimate, parameters);
* Values result = optimizer.optimize();
*
* \nosubgrouping
2012-06-09 00:45:16 +08:00
*/
2019-04-04 21:23:02 +08:00
class GTSAM_EXPORT SubgraphSolver : public IterativeSolver {
public:
2012-06-09 10:42:45 +08:00
typedef SubgraphSolverParameters Parameters;
2012-06-09 00:45:16 +08:00
2019-04-04 21:23:02 +08:00
protected:
Parameters parameters_;
std::shared_ptr<SubgraphPreconditioner> pc_; ///< preconditioner object
2019-04-04 21:23:02 +08:00
public:
/// @name Constructors
/// @{
/**
2019-04-04 21:23:02 +08:00
* Given a gaussian factor graph, split it into a spanning tree (A1) + others
* (A2) for SPCG Will throw exception if there are ternary factors or higher
* arity, as we use Kruskal's algorithm to split the graph, treating binary
* factors as edges.
*/
SubgraphSolver(const GaussianFactorGraph &A, const Parameters &parameters,
2019-04-04 21:23:02 +08:00
const Ordering &ordering);
/**
* The user specifies the subgraph part and the constraints part.
2019-04-04 21:23:02 +08:00
* May throw exception if A1 is underdetermined. An ordering is required to
* eliminate Ab1. We take Ab1 as a const reference, as it will be transformed
* into Rc1, but take Ab2 as a shared pointer as we need to keep it around.
*/
SubgraphSolver(const GaussianFactorGraph &Ab1, const GaussianFactorGraph &Ab2,
2019-04-04 21:23:02 +08:00
const Parameters &parameters, const Ordering &ordering);
/**
* The same as above, but we assume A1 was solved by caller.
* We take two shared pointers as we keep both around.
*/
SubgraphSolver(const GaussianBayesNet &Rc1, const GaussianFactorGraph &Ab2,
2019-04-04 21:23:02 +08:00
const Parameters &parameters);
/// Destructor
~SubgraphSolver() override {}
2012-06-09 00:45:16 +08:00
2019-04-04 21:23:02 +08:00
/// @}
/// @name Implement interface
/// @{
2019-04-04 21:23:02 +08:00
/// Optimize from zero
VectorValues optimize() const;
2019-04-04 21:23:02 +08:00
/// Interface that IterativeSolver subclasses have to implement
VectorValues optimize(const GaussianFactorGraph &gfg,
const KeyInfo &keyInfo,
const std::map<Key, Vector> &lambda,
const VectorValues &initial) override;
/// @}
/// @name Implement interface
/// @{
/// Split graph using Kruskal algorithm, treating binary factors as edges.
std::pair<GaussianFactorGraph, GaussianFactorGraph> splitGraph(
const GaussianFactorGraph &gfg);
2019-04-04 21:23:02 +08:00
/// @}
2012-06-09 00:45:16 +08:00
};
2019-04-04 21:23:02 +08:00
} // namespace gtsam