blob: e258ceba3a8a71487b5b2ac1eb7c7f3772ea41bd [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.
28//
29// Author: sameeragarwal@google.com (Sameer Agarwal)
30
31#ifndef CERES_INTERNAL_NUMERIC_DIFF_TEST_UTILS_H_
32#define CERES_INTERNAL_NUMERIC_DIFF_TEST_UTILS_H_
33
Austin Schuh3de38b02024-06-25 18:25:10 -070034#include <random>
35
Austin Schuh70cc9552019-01-21 19:46:48 -080036#include "ceres/cost_function.h"
Austin Schuh3de38b02024-06-25 18:25:10 -070037#include "ceres/internal/export.h"
Austin Schuh70cc9552019-01-21 19:46:48 -080038#include "ceres/sized_cost_function.h"
39#include "ceres/types.h"
40
Austin Schuh3de38b02024-06-25 18:25:10 -070041namespace ceres::internal {
Austin Schuh70cc9552019-01-21 19:46:48 -080042
43// Noise factor for randomized cost function.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080044static constexpr double kNoiseFactor = 0.01;
Austin Schuh70cc9552019-01-21 19:46:48 -080045
46// Default random seed for randomized cost function.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080047static constexpr unsigned int kRandomSeed = 1234;
Austin Schuh70cc9552019-01-21 19:46:48 -080048
49// y1 = x1'x2 -> dy1/dx1 = x2, dy1/dx2 = x1
50// y2 = (x1'x2)^2 -> dy2/dx1 = 2 * x2 * (x1'x2), dy2/dx2 = 2 * x1 * (x1'x2)
51// y3 = x2'x2 -> dy3/dx1 = 0, dy3/dx2 = 2 * x2
Austin Schuh3de38b02024-06-25 18:25:10 -070052class CERES_NO_EXPORT EasyFunctor {
Austin Schuh70cc9552019-01-21 19:46:48 -080053 public:
54 bool operator()(const double* x1, const double* x2, double* residuals) const;
55 void ExpectCostFunctionEvaluationIsNearlyCorrect(
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080056 const CostFunction& cost_function, NumericDiffMethodType method) const;
Austin Schuh70cc9552019-01-21 19:46:48 -080057};
58
59class EasyCostFunction : public SizedCostFunction<3, 5, 5> {
60 public:
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080061 bool Evaluate(double const* const* parameters,
62 double* residuals,
63 double** /* not used */) const final {
Austin Schuh70cc9552019-01-21 19:46:48 -080064 return functor_(parameters[0], parameters[1], residuals);
65 }
66
67 private:
68 EasyFunctor functor_;
69};
70
71// y1 = sin(x1'x2)
72// y2 = exp(-x1'x2 / 10)
73//
74// dy1/dx1 = x2 * cos(x1'x2), dy1/dx2 = x1 * cos(x1'x2)
75// dy2/dx1 = -x2 * exp(-x1'x2 / 10) / 10, dy2/dx2 = -x2 * exp(-x1'x2 / 10) / 10
Austin Schuh3de38b02024-06-25 18:25:10 -070076class CERES_NO_EXPORT TranscendentalFunctor {
Austin Schuh70cc9552019-01-21 19:46:48 -080077 public:
78 bool operator()(const double* x1, const double* x2, double* residuals) const;
79 void ExpectCostFunctionEvaluationIsNearlyCorrect(
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080080 const CostFunction& cost_function, NumericDiffMethodType method) const;
Austin Schuh70cc9552019-01-21 19:46:48 -080081};
82
Austin Schuh3de38b02024-06-25 18:25:10 -070083class CERES_NO_EXPORT TranscendentalCostFunction
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080084 : public SizedCostFunction<2, 5, 5> {
Austin Schuh70cc9552019-01-21 19:46:48 -080085 public:
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080086 bool Evaluate(double const* const* parameters,
87 double* residuals,
88 double** /* not used */) const final {
Austin Schuh70cc9552019-01-21 19:46:48 -080089 return functor_(parameters[0], parameters[1], residuals);
90 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080091
Austin Schuh70cc9552019-01-21 19:46:48 -080092 private:
93 TranscendentalFunctor functor_;
94};
95
96// y = exp(x), dy/dx = exp(x)
Austin Schuh3de38b02024-06-25 18:25:10 -070097class CERES_NO_EXPORT ExponentialFunctor {
Austin Schuh70cc9552019-01-21 19:46:48 -080098 public:
99 bool operator()(const double* x1, double* residuals) const;
100 void ExpectCostFunctionEvaluationIsNearlyCorrect(
101 const CostFunction& cost_function) const;
102};
103
104class ExponentialCostFunction : public SizedCostFunction<1, 1> {
105 public:
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800106 bool Evaluate(double const* const* parameters,
107 double* residuals,
108 double** /* not used */) const final {
Austin Schuh70cc9552019-01-21 19:46:48 -0800109 return functor_(parameters[0], residuals);
110 }
111
112 private:
113 ExponentialFunctor functor_;
114};
115
116// Test adaptive numeric differentiation by synthetically adding random noise
117// to a functor.
118// y = x^2 + [random noise], dy/dx ~ 2x
Austin Schuh3de38b02024-06-25 18:25:10 -0700119class CERES_NO_EXPORT RandomizedFunctor {
Austin Schuh70cc9552019-01-21 19:46:48 -0800120 public:
Austin Schuh3de38b02024-06-25 18:25:10 -0700121 RandomizedFunctor(double noise_factor, std::mt19937& prng)
122 : noise_factor_(noise_factor),
123 prng_(&prng),
124 uniform_distribution_{-noise_factor, noise_factor} {}
Austin Schuh70cc9552019-01-21 19:46:48 -0800125
126 bool operator()(const double* x1, double* residuals) const;
127 void ExpectCostFunctionEvaluationIsNearlyCorrect(
128 const CostFunction& cost_function) const;
129
130 private:
131 double noise_factor_;
Austin Schuh3de38b02024-06-25 18:25:10 -0700132 // Store the generator as a pointer to be able to modify the instance the
133 // pointer is pointing to.
134 std::mt19937* prng_;
135 mutable std::uniform_real_distribution<> uniform_distribution_;
Austin Schuh70cc9552019-01-21 19:46:48 -0800136};
137
Austin Schuh3de38b02024-06-25 18:25:10 -0700138class CERES_NO_EXPORT RandomizedCostFunction : public SizedCostFunction<1, 1> {
Austin Schuh70cc9552019-01-21 19:46:48 -0800139 public:
Austin Schuh3de38b02024-06-25 18:25:10 -0700140 RandomizedCostFunction(double noise_factor, std::mt19937& prng)
141 : functor_(noise_factor, prng) {}
Austin Schuh70cc9552019-01-21 19:46:48 -0800142
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800143 bool Evaluate(double const* const* parameters,
144 double* residuals,
145 double** /* not used */) const final {
Austin Schuh70cc9552019-01-21 19:46:48 -0800146 return functor_(parameters[0], residuals);
147 }
148
149 private:
150 RandomizedFunctor functor_;
151};
152
Austin Schuh3de38b02024-06-25 18:25:10 -0700153} // namespace ceres::internal
Austin Schuh70cc9552019-01-21 19:46:48 -0800154
155#endif // CERES_INTERNAL_NUMERIC_DIFF_TEST_UTILS_H_