179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Ceres Solver - A fast non-linear least squares minimizer
279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Copyright 2014 Google Inc. All rights reserved.
379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// http://code.google.com/p/ceres-solver/
479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Redistribution and use in source and binary forms, with or without
679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// modification, are permitted provided that the following conditions are met:
779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// * Redistributions of source code must retain the above copyright notice,
979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//   this list of conditions and the following disclaimer.
1079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// * Redistributions in binary form must reproduce the above copyright notice,
1179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//   this list of conditions and the following disclaimer in the documentation
1279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//   and/or other materials provided with the distribution.
1379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// * Neither the name of Google Inc. nor the names of its contributors may be
1479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//   used to endorse or promote products derived from this software without
1579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//   specific prior written permission.
1679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
1779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// POSSIBILITY OF SUCH DAMAGE.
2879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
2979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Author: sameeragarwal@google.com (Sameer Agarwal)
3079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
3179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Bounds constrained test problems from the paper
3279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
3379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Testing Unconstrained Optimization Software
3479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Jorge J. More, Burton S. Garbow and Kenneth E. Hillstrom
3579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// ACM Transactions on Mathematical Software, 7(1), pp. 17-41, 1981
3679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
3779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// A subset of these problems were augmented with bounds and used for
3879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// testing bounds constrained optimization algorithms by
3979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
4079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// A Trust Region Approach to Linearly Constrained Optimization
4179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// David M. Gay
4279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Numerical Analysis (Griffiths, D.F., ed.), pp. 72-105
4379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Lecture Notes in Mathematics 1066, Springer Verlag, 1984.
4479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
4579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// The latter paper is behind a paywall. We obtained the bounds on the
4679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// variables and the function values at the global minimums from
4779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
4879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// http://www.mat.univie.ac.at/~neum/glopt/bounds.html
4979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez//
5079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// A problem is considered solved if of the log relative error of its
5179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// objective function is at least 5.
5279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
5379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
5479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#include <cmath>
5579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#include <iostream>  // NOLINT
5679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#include "ceres/ceres.h"
5779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#include "gflags/gflags.h"
5879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#include "glog/logging.h"
5979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
6079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandeznamespace ceres {
6179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandeznamespace examples {
6279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
6379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double kDoubleMax = std::numeric_limits<double>::max();
6479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
6579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#define BEGIN_MGH_PROBLEM(name, num_parameters, num_residuals)          \
6679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  struct name {                                                         \
6779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    static const int kNumParameters = num_parameters;                   \
6879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    static const double initial_x[kNumParameters];                      \
6979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    static const double lower_bounds[kNumParameters];                   \
7079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    static const double upper_bounds[kNumParameters];                   \
7179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    static const double constrained_optimal_cost;                       \
7279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    static const double unconstrained_optimal_cost;                     \
7379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    static CostFunction* Create() {                                     \
7479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez      return new AutoDiffCostFunction<name,                             \
7579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez                                      num_residuals,                    \
7679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez                                      num_parameters>(new name);        \
7779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    }                                                                   \
7879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    template <typename T>                                               \
7979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    bool operator()(const T* const x, T* residual) const {
8079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
8179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#define END_MGH_PROBLEM return true; } };  // NOLINT
8279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
8379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Rosenbrock function.
8479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem1, 2, 2)
8579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
8679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
8779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[0] = T(10.0) * (x2 - x1 * x1);
8879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[1] = T(1.0) - x1;
8979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
9079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
9179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem1::initial_x[] = {-1.2, 1.0};
9279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem1::lower_bounds[] = {-kDoubleMax, -kDoubleMax};
9379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem1::upper_bounds[] = {kDoubleMax, kDoubleMax};
9479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem1::constrained_optimal_cost =
9579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    std::numeric_limits<double>::quiet_NaN();
9679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem1::unconstrained_optimal_cost = 0.0;
9779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
9879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Freudenstein and Roth function.
9979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem2, 2, 2)
10079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
10179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
10279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[0] = T(-13.0) + x1 + ((T(5.0) - x2) * x2 - T(2.0)) * x2;
10379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[1] = T(-29.0) + x1 + ((x2 + T(1.0)) * x2 - T(14.0)) * x2;
10479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
10579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
10679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem2::initial_x[] = {0.5, -2.0};
10779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem2::lower_bounds[] = {-kDoubleMax, -kDoubleMax};
10879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem2::upper_bounds[] = {kDoubleMax, kDoubleMax};
10979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem2::constrained_optimal_cost =
11079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    std::numeric_limits<double>::quiet_NaN();
11179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem2::unconstrained_optimal_cost = 0.0;
11279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
11379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Powell badly scaled function.
11479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem3, 2, 2)
11579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
11679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
11779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[0] = T(10000.0) * x1 * x2 - T(1.0);
11879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[1] = exp(-x1) + exp(-x2) - T(1.0001);
11979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
12079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
12179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem3::initial_x[] = {0.0, 1.0};
12279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem3::lower_bounds[] = {0.0, 1.0};
12379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem3::upper_bounds[] = {1.0, 9.0};
12479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem3::constrained_optimal_cost = 0.15125900e-9;
12579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem3::unconstrained_optimal_cost = 0.0;
12679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
12779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Brown badly scaled function.
12879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem4, 2, 3)
12979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
13079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
13179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[0] = x1  - T(1000000.0);
13279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[1] = x2 - T(0.000002);
13379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[2] = x1 * x2 - T(2.0);
13479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
13579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
13679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem4::initial_x[] = {1.0, 1.0};
13779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem4::lower_bounds[] = {0.0, 0.00003};
13879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem4::upper_bounds[] = {1000000.0, 100.0};
13979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem4::constrained_optimal_cost = 0.78400000e3;
14079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem4::unconstrained_optimal_cost = 0.0;
14179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
14279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Beale function.
14379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem5, 2, 3)
14479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
14579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
14679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[0] = T(1.5) - x1 * (T(1.0) - x2);
14779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[1] = T(2.25) - x1 * (T(1.0) - x2 * x2);
14879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[2] = T(2.625) - x1 * (T(1.0) - x2 * x2 * x2);
14979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
15079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
15179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem5::initial_x[] = {1.0, 1.0};
15279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem5::lower_bounds[] = {0.6, 0.5};
15379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem5::upper_bounds[] = {10.0, 100.0};
15479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem5::constrained_optimal_cost = 0.0;
15579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem5::unconstrained_optimal_cost = 0.0;
15679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
15779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Jennrich and Sampson function.
15879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem6, 2, 10)
15979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
16079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
16179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  for (int i = 1; i <= 10; ++i) {
16279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    residual[i - 1] = T(2.0) + T(2.0 * i) -
16379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez        exp(T(static_cast<double>(i)) * x1) -
16479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez        exp(T(static_cast<double>(i) * x2));
16579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  }
16679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
16779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
16879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem6::initial_x[] = {1.0, 1.0};
16979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem6::lower_bounds[] = {-kDoubleMax, -kDoubleMax};
17079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem6::upper_bounds[] = {kDoubleMax, kDoubleMax};
17179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem6::constrained_optimal_cost =
17279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    std::numeric_limits<double>::quiet_NaN();
17379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem6::unconstrained_optimal_cost = 124.362;
17479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
17579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Helical valley function.
17679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem7, 3, 3)
17779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
17879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
17979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x3 = x[2];
18079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T theta = T(0.5 / M_PI)  * atan(x2 / x1) + (x1 > 0.0 ? T(0.0) : T(0.5));
18179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
18279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[0] = T(10.0) * (x3 - T(10.0) * theta);
18379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[1] = T(10.0) * (sqrt(x1 * x1 + x2 * x2) - T(1.0));
18479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  residual[2] = x3;
18579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
18679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
18779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem7::initial_x[] = {-1.0, 0.0, 0.0};
18879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem7::lower_bounds[] = {-100.0, -1.0, -1.0};
18979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem7::upper_bounds[] = {0.8, 1.0, 1.0};
19079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem7::constrained_optimal_cost = 0.99042212;
19179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem7::unconstrained_optimal_cost = 0.0;
19279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
19379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Bard function
19479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem8, 3, 15)
19579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
19679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
19779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x3 = x[2];
19879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
19979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  double y[] = {0.14, 0.18, 0.22, 0.25,
20079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez                0.29, 0.32, 0.35, 0.39, 0.37, 0.58,
20179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez                0.73, 0.96, 1.34, 2.10, 4.39};
20279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
20379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  for (int i = 1; i <=15; ++i) {
20479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    const T u = T(static_cast<double>(i));
20579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    const T v = T(static_cast<double>(16 - i));
20679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    const T w = T(static_cast<double>(std::min(i, 16 - i)));
20779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    residual[i - 1] = T(y[i - 1]) - x1 + u / (v * x2 + w * x3);
20879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  }
20979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
21079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
21179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem8::initial_x[] = {1.0, 1.0, 1.0};
21279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem8::lower_bounds[] = {
21379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  -kDoubleMax, -kDoubleMax, -kDoubleMax};
21479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem8::upper_bounds[] = {
21579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  kDoubleMax, kDoubleMax, kDoubleMax};
21679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem8::constrained_optimal_cost =
21779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    std::numeric_limits<double>::quiet_NaN();
21879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem8::unconstrained_optimal_cost = 8.21487e-3;
21979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
22079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Gaussian function.
22179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem9, 3, 15)
22279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
22379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
22479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x3 = x[2];
22579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
22679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const double y[] = {0.0009, 0.0044, 0.0175, 0.0540, 0.1295, 0.2420, 0.3521,
22779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez                      0.3989,
22879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez                      0.3521, 0.2420, 0.1295, 0.0540, 0.0175, 0.0044, 0.0009};
22979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  for (int i = 0; i < 15; ++i) {
23079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    const T t_i = T((8.0 - i - 1.0) / 2.0);
23179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    const T y_i = T(y[i]);
23279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    residual[i] = x1 * exp(-x2 * (t_i - x3) * (t_i - x3) / T(2.0)) - y_i;
23379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  }
23479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM;
23579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
23679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem9::initial_x[] = {0.4, 1.0, 0.0};
23779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem9::lower_bounds[] = {0.398, 1.0, -0.5};
23879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem9::upper_bounds[] = {4.2, 2.0, 0.1};
23979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem9::constrained_optimal_cost = 0.11279300e-7;
24079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem9::unconstrained_optimal_cost = 0.112793e-7;
24179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
24279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez// Meyer function.
24379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezBEGIN_MGH_PROBLEM(TestProblem10, 3, 16)
24479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x1 = x[0];
24579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x2 = x[1];
24679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const T x3 = x[2];
24779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
24879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const double y[] = {34780, 28610, 23650, 19630, 16370, 13720, 11540, 9744,
24979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez                      8261, 7030, 6005, 5147, 4427, 3820, 3307, 2872};
25079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
25179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  for (int i = 0; i < 16; ++i) {
25279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    T t = T(45 + 5.0 * (i + 1));
25379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    residual[i] = x1 * exp(x2 / (t + x3)) - y[i];
25479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  }
25579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos HernandezEND_MGH_PROBLEM
25679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
25779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
25879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem10::initial_x[] = {0.02, 4000, 250};
25979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem10::lower_bounds[] ={
26079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  -kDoubleMax, -kDoubleMax, -kDoubleMax};
26179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem10::upper_bounds[] ={
26279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  kDoubleMax, kDoubleMax, kDoubleMax};
26379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem10::constrained_optimal_cost =
26479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    std::numeric_limits<double>::quiet_NaN();
26579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezconst double TestProblem10::unconstrained_optimal_cost = 87.9458;
26679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
26779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#undef BEGIN_MGH_PROBLEM
26879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#undef END_MGH_PROBLEM
26979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
27079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandeztemplate<typename TestProblem> string ConstrainedSolve() {
27179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  double x[TestProblem::kNumParameters];
27279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  std::copy(TestProblem::initial_x,
27379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez            TestProblem::initial_x + TestProblem::kNumParameters,
27479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez            x);
27579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
27679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  Problem problem;
27779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  problem.AddResidualBlock(TestProblem::Create(), NULL, x);
27879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  for (int i = 0; i < TestProblem::kNumParameters; ++i) {
27979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    problem.SetParameterLowerBound(x, i, TestProblem::lower_bounds[i]);
28079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez    problem.SetParameterUpperBound(x, i, TestProblem::upper_bounds[i]);
28179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  }
28279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
28379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  Solver::Options options;
28479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.parameter_tolerance = 1e-18;
28579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.function_tolerance = 1e-18;
28679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.gradient_tolerance = 1e-18;
28779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.max_num_iterations = 1000;
28879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.linear_solver_type = DENSE_QR;
28979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  Solver::Summary summary;
29079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  Solve(options, &problem, &summary);
29179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
29279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const double kMinLogRelativeError = 5.0;
29379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const double log_relative_error = -std::log10(
29479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez      std::abs(2.0 * summary.final_cost -
29579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez               TestProblem::constrained_optimal_cost) /
29679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez      (TestProblem::constrained_optimal_cost > 0.0
29779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez       ? TestProblem::constrained_optimal_cost
29879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez       : 1.0));
29979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
30079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  return (log_relative_error >= kMinLogRelativeError
30179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez          ? "Success\n"
30279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez          : "Failure\n");
30379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez}
30479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
30579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandeztemplate<typename TestProblem> string UnconstrainedSolve() {
30679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  double x[TestProblem::kNumParameters];
30779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  std::copy(TestProblem::initial_x,
30879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez            TestProblem::initial_x + TestProblem::kNumParameters,
30979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez            x);
31079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
31179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  Problem problem;
31279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  problem.AddResidualBlock(TestProblem::Create(), NULL, x);
31379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
31479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  Solver::Options options;
31579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.parameter_tolerance = 1e-18;
31679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.function_tolerance = 0.0;
31779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.gradient_tolerance = 1e-18;
31879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.max_num_iterations = 1000;
31979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  options.linear_solver_type = DENSE_QR;
32079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  Solver::Summary summary;
32179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  Solve(options, &problem, &summary);
32279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
32379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const double kMinLogRelativeError = 5.0;
32479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  const double log_relative_error = -std::log10(
32579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez      std::abs(2.0 * summary.final_cost -
32679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez               TestProblem::unconstrained_optimal_cost) /
32779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez      (TestProblem::unconstrained_optimal_cost > 0.0
32879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez       ? TestProblem::unconstrained_optimal_cost
32979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez       : 1.0));
33079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
33179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  return (log_relative_error >= kMinLogRelativeError
33279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez          ? "Success\n"
33379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez          : "Failure\n");
33479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez}
33579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
33679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez}  // namespace examples
33779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez}  // namespace ceres
33879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
33979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandezint main(int argc, char** argv) {
34079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  google::ParseCommandLineFlags(&argc, &argv, true);
34179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  google::InitGoogleLogging(argv[0]);
34279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
34379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  using ceres::examples::UnconstrainedSolve;
34479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  using ceres::examples::ConstrainedSolve;
34579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
34679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#define UNCONSTRAINED_SOLVE(n)                                          \
34779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  std::cout << "Problem " << n << " : "                                 \
34879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez            << UnconstrainedSolve<ceres::examples::TestProblem##n>();
34979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
35079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez#define CONSTRAINED_SOLVE(n)                                            \
35179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  std::cout << "Problem " << n << " : "                                 \
35279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez            << ConstrainedSolve<ceres::examples::TestProblem##n>();
35379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
35479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  std::cout << "Unconstrained problems\n";
35579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(1);
35679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(2);
35779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(3);
35879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(4);
35979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(5);
36079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(6);
36179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(7);
36279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(8);
36379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(9);
36479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  UNCONSTRAINED_SOLVE(10);
36579397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
36679397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  std::cout << "\nConstrained problems\n";
36779397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  CONSTRAINED_SOLVE(3);
36879397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  CONSTRAINED_SOLVE(4);
36979397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  CONSTRAINED_SOLVE(5);
37079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  CONSTRAINED_SOLVE(7);
37179397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  CONSTRAINED_SOLVE(9);
37279397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez
37379397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  return 0;
37479397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez}
375