blob: 77f2c8e182ebf35004ffff4010e0dc82ad6a1df6 [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
Austin Schuh3de38b02024-06-25 18:25:10 -07002// Copyright 2023 Google Inc. All rights reserved.
Austin Schuh70cc9552019-01-21 19:46:48 -08003// http://ceres-solver.org/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
Austin Schuh3de38b02024-06-25 18:25:10 -070028// Copyright 2023 Google Inc. All Rights Reserved.
Austin Schuh70cc9552019-01-21 19:46:48 -080029//
30// Authors: wjr@google.com (William Rucklidge),
31// keir@google.com (Keir Mierle),
32// dgossow@google.com (David Gossow)
33
34#ifndef CERES_PUBLIC_GRADIENT_CHECKER_H_
35#define CERES_PUBLIC_GRADIENT_CHECKER_H_
36
37#include <memory>
38#include <string>
39#include <vector>
40
41#include "ceres/cost_function.h"
42#include "ceres/dynamic_numeric_diff_cost_function.h"
Austin Schuh3de38b02024-06-25 18:25:10 -070043#include "ceres/internal/disable_warnings.h"
Austin Schuh70cc9552019-01-21 19:46:48 -080044#include "ceres/internal/eigen.h"
Austin Schuh3de38b02024-06-25 18:25:10 -070045#include "ceres/internal/export.h"
Austin Schuh70cc9552019-01-21 19:46:48 -080046#include "ceres/internal/fixed_array.h"
Austin Schuh3de38b02024-06-25 18:25:10 -070047#include "ceres/manifold.h"
Austin Schuh70cc9552019-01-21 19:46:48 -080048#include "glog/logging.h"
49
50namespace ceres {
51
52// GradientChecker compares the Jacobians returned by a cost function against
53// derivatives estimated using finite differencing.
54//
55// The condition enforced is that
56//
57// (J_actual(i, j) - J_numeric(i, j))
58// ------------------------------------ < relative_precision
59// max(J_actual(i, j), J_numeric(i, j))
60//
Austin Schuh3de38b02024-06-25 18:25:10 -070061// where J_actual(i, j) is the Jacobian as computed by the supplied cost
62// function (by the user) multiplied by the manifold Jacobian and J_numeric is
63// the Jacobian as computed by finite differences, multiplied by the manifold
64// Jacobian as well.
Austin Schuh70cc9552019-01-21 19:46:48 -080065//
66// How to use: Fill in an array of pointers to parameter blocks for your
67// CostFunction, and then call Probe(). Check that the return value is 'true'.
68class CERES_EXPORT GradientChecker {
69 public:
Austin Schuh3de38b02024-06-25 18:25:10 -070070 // This will not take ownership of the cost function or manifolds.
Austin Schuh70cc9552019-01-21 19:46:48 -080071 //
72 // function: The cost function to probe.
Austin Schuh3de38b02024-06-25 18:25:10 -070073 //
74 // manifolds: A vector of manifolds for each parameter. May be nullptr or
75 // contain nullptrs to indicate that the respective parameter blocks are
76 // Euclidean.
77 //
Austin Schuh70cc9552019-01-21 19:46:48 -080078 // options: Options to use for numerical differentiation.
Austin Schuh3de38b02024-06-25 18:25:10 -070079 GradientChecker(const CostFunction* function,
80 const std::vector<const Manifold*>* manifolds,
81 const NumericDiffOptions& options);
Austin Schuh70cc9552019-01-21 19:46:48 -080082
83 // Contains results from a call to Probe for later inspection.
84 struct CERES_EXPORT ProbeResults {
85 // The return value of the cost function.
86 bool return_value;
87
88 // Computed residual vector.
89 Vector residuals;
90
91 // The sizes of the Jacobians below are dictated by the cost function's
Austin Schuh3de38b02024-06-25 18:25:10 -070092 // parameter block size and residual block sizes. If a parameter block has a
93 // manifold associated with it, the size of the "local" Jacobian will be
94 // determined by the dimension of the manifold (which is the same as the
95 // dimension of the tangent space) and residual block size, otherwise it
96 // will be identical to the regular Jacobian.
Austin Schuh70cc9552019-01-21 19:46:48 -080097
98 // Derivatives as computed by the cost function.
99 std::vector<Matrix> jacobians;
100
101 // Derivatives as computed by the cost function in local space.
102 std::vector<Matrix> local_jacobians;
103
104 // Derivatives as computed by numerical differentiation in local space.
105 std::vector<Matrix> numeric_jacobians;
106
107 // Derivatives as computed by numerical differentiation in local space.
108 std::vector<Matrix> local_numeric_jacobians;
109
110 // Contains the maximum relative error found in the local Jacobians.
111 double maximum_relative_error;
112
113 // If an error was detected, this will contain a detailed description of
114 // that error.
115 std::string error_log;
116 };
117
118 // Call the cost function, compute alternative Jacobians using finite
Austin Schuh3de38b02024-06-25 18:25:10 -0700119 // differencing and compare results. If manifolds are given, the Jacobians
120 // will be multiplied by the manifold Jacobians before performing the check,
121 // which effectively means that all errors along the null space of the
122 // manifold will be ignored. Returns false if the Jacobians don't match, the
123 // cost function return false, or if a cost function returns a different
124 // residual when called with a Jacobian output argument vs. calling it
125 // without. Otherwise returns true.
Austin Schuh70cc9552019-01-21 19:46:48 -0800126 //
127 // parameters: The parameter values at which to probe.
128 // relative_precision: A threshold for the relative difference between the
129 // Jacobians. If the Jacobians differ by more than this amount, then the
130 // probe fails.
131 // results: On return, the Jacobians (and other information) will be stored
Austin Schuh3de38b02024-06-25 18:25:10 -0700132 // here. May be nullptr.
Austin Schuh70cc9552019-01-21 19:46:48 -0800133 //
134 // Returns true if no problems are detected and the difference between the
135 // Jacobians is less than error_tolerance.
136 bool Probe(double const* const* parameters,
137 double relative_precision,
138 ProbeResults* results) const;
139
140 private:
141 GradientChecker() = delete;
142 GradientChecker(const GradientChecker&) = delete;
143 void operator=(const GradientChecker&) = delete;
144
Austin Schuh3de38b02024-06-25 18:25:10 -0700145 std::vector<const Manifold*> manifolds_;
Austin Schuh70cc9552019-01-21 19:46:48 -0800146 const CostFunction* function_;
147 std::unique_ptr<CostFunction> finite_diff_cost_function_;
148};
149
150} // namespace ceres
151
Austin Schuh3de38b02024-06-25 18:25:10 -0700152#include "ceres/internal/reenable_warnings.h"
153
Austin Schuh70cc9552019-01-21 19:46:48 -0800154#endif // CERES_PUBLIC_GRADIENT_CHECKER_H_