1 // Ceres Solver - A fast non-linear least squares minimizer
2 // Copyright 2015 Google Inc. All rights reserved.
3 // 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 
34 #include "ceres/cost_function.h"
35 #include "ceres/internal/port.h"
36 #include "ceres/sized_cost_function.h"
37 #include "ceres/types.h"
38 
39 namespace ceres {
40 namespace internal {
41 
42 // Noise factor for randomized cost function.
43 static constexpr double kNoiseFactor = 0.01;
44 
45 // Default random seed for randomized cost function.
46 static constexpr unsigned int kRandomSeed = 1234;
47 
48 // y1 = x1'x2      -> dy1/dx1 = x2,               dy1/dx2 = x1
49 // y2 = (x1'x2)^2  -> dy2/dx1 = 2 * x2 * (x1'x2), dy2/dx2 = 2 * x1 * (x1'x2)
50 // y3 = x2'x2      -> dy3/dx1 = 0,                dy3/dx2 = 2 * x2
51 class CERES_EXPORT_INTERNAL EasyFunctor {
52  public:
53   bool operator()(const double* x1, const double* x2, double* residuals) const;
54   void ExpectCostFunctionEvaluationIsNearlyCorrect(
55       const CostFunction& cost_function, NumericDiffMethodType method) const;
56 };
57 
58 class EasyCostFunction : public SizedCostFunction<3, 5, 5> {
59  public:
Evaluate(double const * const * parameters,double * residuals,double **)60   bool Evaluate(double const* const* parameters,
61                 double* residuals,
62                 double** /* not used */) const final {
63     return functor_(parameters[0], parameters[1], residuals);
64   }
65 
66  private:
67   EasyFunctor functor_;
68 };
69 
70 // y1 = sin(x1'x2)
71 // y2 = exp(-x1'x2 / 10)
72 //
73 // dy1/dx1 =  x2 * cos(x1'x2),            dy1/dx2 =  x1 * cos(x1'x2)
74 // dy2/dx1 = -x2 * exp(-x1'x2 / 10) / 10, dy2/dx2 = -x2 * exp(-x1'x2 / 10) / 10
75 class CERES_EXPORT TranscendentalFunctor {
76  public:
77   bool operator()(const double* x1, const double* x2, double* residuals) const;
78   void ExpectCostFunctionEvaluationIsNearlyCorrect(
79       const CostFunction& cost_function, NumericDiffMethodType method) const;
80 };
81 
82 class CERES_EXPORT_INTERNAL TranscendentalCostFunction
83     : public SizedCostFunction<2, 5, 5> {
84  public:
Evaluate(double const * const * parameters,double * residuals,double **)85   bool Evaluate(double const* const* parameters,
86                 double* residuals,
87                 double** /* not used */) const final {
88     return functor_(parameters[0], parameters[1], residuals);
89   }
90 
91  private:
92   TranscendentalFunctor functor_;
93 };
94 
95 // y = exp(x), dy/dx = exp(x)
96 class CERES_EXPORT_INTERNAL ExponentialFunctor {
97  public:
98   bool operator()(const double* x1, double* residuals) const;
99   void ExpectCostFunctionEvaluationIsNearlyCorrect(
100       const CostFunction& cost_function) const;
101 };
102 
103 class ExponentialCostFunction : public SizedCostFunction<1, 1> {
104  public:
Evaluate(double const * const * parameters,double * residuals,double **)105   bool Evaluate(double const* const* parameters,
106                 double* residuals,
107                 double** /* not used */) const final {
108     return functor_(parameters[0], residuals);
109   }
110 
111  private:
112   ExponentialFunctor functor_;
113 };
114 
115 // Test adaptive numeric differentiation by synthetically adding random noise
116 // to a functor.
117 // y = x^2 + [random noise], dy/dx ~ 2x
118 class CERES_EXPORT_INTERNAL RandomizedFunctor {
119  public:
RandomizedFunctor(double noise_factor,unsigned int random_seed)120   RandomizedFunctor(double noise_factor, unsigned int random_seed)
121       : noise_factor_(noise_factor), random_seed_(random_seed) {}
122 
123   bool operator()(const double* x1, double* residuals) const;
124   void ExpectCostFunctionEvaluationIsNearlyCorrect(
125       const CostFunction& cost_function) const;
126 
127  private:
128   double noise_factor_;
129   unsigned int random_seed_;
130 };
131 
132 class CERES_EXPORT_INTERNAL RandomizedCostFunction
133     : public SizedCostFunction<1, 1> {
134  public:
RandomizedCostFunction(double noise_factor,unsigned int random_seed)135   RandomizedCostFunction(double noise_factor, unsigned int random_seed)
136       : functor_(noise_factor, random_seed) {}
137 
Evaluate(double const * const * parameters,double * residuals,double **)138   bool Evaluate(double const* const* parameters,
139                 double* residuals,
140                 double** /* not used */) const final {
141     return functor_(parameters[0], residuals);
142   }
143 
144  private:
145   RandomizedFunctor functor_;
146 };
147 
148 }  // namespace internal
149 }  // namespace ceres
150 
151 #endif  // CERES_INTERNAL_NUMERIC_DIFF_TEST_UTILS_H_
152