/* ---------------------------------------------------------------------------- * 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 NonlinearOptimizer.h * @brief Base class and parameters for nonlinear optimization algorithms * @author Richard Roberts * @date Sep 7, 2009 */ #pragma once #include #include namespace gtsam { namespace internal { struct NonlinearOptimizerState; } /** * This is the abstract interface for classes that can optimize for the * maximum-likelihood estimate of a NonlinearFactorGraph. * * To use a class derived from this interface, construct the class with a * NonlinearFactorGraph and an initial Values variable assignment. Next, call the * optimize() method which returns the optimized variable assignment. * * Simple and compact example: * \code // One-liner to do full optimization and use the result. Values result = DoglegOptimizer(graph, initialValues).optimize(); \endcode * * Example exposing more functionality and details: * \code // Create initial optimizer DoglegOptimizer optimizer(graph, initialValues); // Run full optimization until convergence. Values result = optimizer->optimize(); // The new optimizer has results and statistics cout << "Converged in " << optimizer.iterations() << " iterations " "with final error " << optimizer.error() << endl; \endcode * * Example of setting parameters before optimization: * \code // Each derived optimizer type has its own parameters class, which inherits from NonlinearOptimizerParams DoglegParams params; params.factorization = DoglegParams::QR; params.relativeErrorTol = 1e-3; params.absoluteErrorTol = 1e-3; // Optimize Values result = DoglegOptimizer(graph, initialValues, params).optimize(); \endcode * * This interface also exposes an iterate() method, which performs one * iteration. The optimize() method simply calls iterate() multiple times, * until the error changes less than a threshold. We expose iterate() so that * you can easily control what happens between iterations, such as drawing or * printing, moving points from behind the camera to in front, etc. * * For more flexibility you may override virtual methods in your own derived class. */ class GTSAM_EXPORT NonlinearOptimizer { protected: NonlinearFactorGraph graph_; ///< The graph with nonlinear factors std::unique_ptr state_; ///< PIMPL'd state public: /** A shared pointer to this class */ using shared_ptr = boost::shared_ptr; /// @name Standard interface /// @{ /** * Optimize for the maximum-likelihood estimate, returning a the optimized * variable assignments. * * This function simply calls iterate() in a loop, checking for convergence * with check_convergence(). For fine-grain control over the optimization * process, you may call iterate() and check_convergence() yourself, and if * needed modify the optimization state between iterations. */ virtual const Values& optimize() { defaultOptimize(); return values(); } /** * Optimize, but return empty result if any uncaught exception is thrown * Intended for MATLAB. In C++, use above and catch exceptions. * No message is printed: it is up to the caller to check the result * @param optimizer a non-linear optimizer */ const Values& optimizeSafely(); /// return error in current optimizer state double error() const; /// return number of iterations in current optimizer state size_t iterations() const; /// return values in current optimizer state const Values &values() const; /// return the graph with nonlinear factors const NonlinearFactorGraph &graph() const { return graph_; } /// @} /// @name Advanced interface /// @{ /** Virtual destructor */ virtual ~NonlinearOptimizer(); /** Default function to do linear solve, i.e. optimize a GaussianFactorGraph */ virtual VectorValues solve(const GaussianFactorGraph &gfg, const NonlinearOptimizerParams& params) const; /** * Perform a single iteration, returning GaussianFactorGraph corresponding to * the linearized factor graph. */ virtual GaussianFactorGraph::shared_ptr iterate() = 0; /// @} protected: /** A default implementation of the optimization loop, which calls iterate() * until checkConvergence returns true. */ void defaultOptimize(); virtual const NonlinearOptimizerParams& _params() const = 0; /** Constructor for initial construction of base classes. Takes ownership of state. */ NonlinearOptimizer(const NonlinearFactorGraph& graph, std::unique_ptr state); }; /** Check whether the relative error decrease is less than relativeErrorTreshold, * the absolute error decrease is less than absoluteErrorTreshold, or * the error itself is less than errorThreshold. */ GTSAM_EXPORT bool checkConvergence(double relativeErrorTreshold, double absoluteErrorTreshold, double errorThreshold, double currentError, double newError, NonlinearOptimizerParams::Verbosity verbosity = NonlinearOptimizerParams::SILENT); GTSAM_EXPORT bool checkConvergence(const NonlinearOptimizerParams& params, double currentError, double newError); } // gtsam