~ubuntu-branches/ubuntu/raring/ceres-solver/raring

« back to all changes in this revision

Viewing changes to internal/ceres/levenberg_marquardt.cc

  • Committer: Package Import Robot
  • Author(s): Koichi Akabe
  • Date: 2012-06-04 07:15:43 UTC
  • Revision ID: package-import@ubuntu.com-20120604071543-zx6uthupvmtqn3k2
Tags: upstream-1.1.1
ImportĀ upstreamĀ versionĀ 1.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Ceres Solver - A fast non-linear least squares minimizer
 
2
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
 
3
// http://code.google.com/p/ceres-solver/
 
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
// Implementation of a simple LM algorithm which uses the step sizing
 
32
// rule of "Methods for Nonlinear Least Squares" by K. Madsen,
 
33
// H.B. Nielsen and O. Tingleff. Available to download from
 
34
//
 
35
// http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
 
36
//
 
37
// The basic algorithm described in this note is an exact step
 
38
// algorithm that depends on the Newton(LM) step being solved exactly
 
39
// in each iteration. When a suitable iterative solver is available to
 
40
// solve the Newton(LM) step, the algorithm will automatically switch
 
41
// to an inexact step solution method. This trades some slowdown in
 
42
// convergence for significant savings in solve time and memory
 
43
// usage. Our implementation of the Truncated Newton algorithm follows
 
44
// the discussion and recommendataions in "Stephen G. Nash, A Survey
 
45
// of Truncated Newton Methods, Journal of Computational and Applied
 
46
// Mathematics, 124(1-2), 45-59, 2000.
 
47
 
 
48
#include "ceres/levenberg_marquardt.h"
 
49
 
 
50
#include <algorithm>
 
51
#include <cstdlib>
 
52
#include <cmath>
 
53
#include <cstring>
 
54
#include <string>
 
55
#include <vector>
 
56
 
 
57
#include <glog/logging.h>
 
58
#include "Eigen/Core"
 
59
#include "ceres/array_utils.h"
 
60
#include "ceres/evaluator.h"
 
61
#include "ceres/file.h"
 
62
#include "ceres/linear_least_squares_problems.h"
 
63
#include "ceres/linear_solver.h"
 
64
#include "ceres/matrix_proto.h"
 
65
#include "ceres/sparse_matrix.h"
 
66
#include "ceres/stringprintf.h"
 
67
#include "ceres/internal/eigen.h"
 
68
#include "ceres/internal/scoped_ptr.h"
 
69
#include "ceres/types.h"
 
70
 
 
71
namespace ceres {
 
72
namespace internal {
 
73
namespace {
 
74
 
 
75
// Numbers for clamping the size of the LM diagonal. The size of these
 
76
// numbers is heuristic. We will probably be adjusting them in the
 
77
// future based on more numerical experience. With jacobi scaling
 
78
// enabled, these numbers should be all but redundant.
 
79
const double kMinLevenbergMarquardtDiagonal = 1e-6;
 
80
const double kMaxLevenbergMarquardtDiagonal = 1e32;
 
81
 
 
82
// Small constant for various floating point issues.
 
83
const double kEpsilon = 1e-12;
 
84
 
 
85
// Number of times the linear solver should be retried in case of
 
86
// numerical failure. The retries are done by exponentially scaling up
 
87
// mu at each retry. This leads to stronger and stronger
 
88
// regularization making the linear least squares problem better
 
89
// conditioned at each retry.
 
90
const int kMaxLinearSolverRetries = 5;
 
91
 
 
92
// D = 1/sqrt(diag(J^T * J))
 
93
void EstimateScale(const SparseMatrix& jacobian, double* D) {
 
94
  CHECK_NOTNULL(D);
 
95
  jacobian.SquaredColumnNorm(D);
 
96
  for (int i = 0; i < jacobian.num_cols(); ++i) {
 
97
    D[i] = 1.0 / (kEpsilon + sqrt(D[i]));
 
98
  }
 
99
}
 
100
 
 
101
// D = diag(J^T * J)
 
102
void LevenbergMarquardtDiagonal(const SparseMatrix& jacobian,
 
103
                                double* D) {
 
104
  CHECK_NOTNULL(D);
 
105
  jacobian.SquaredColumnNorm(D);
 
106
  for (int i = 0; i < jacobian.num_cols(); ++i) {
 
107
    D[i] = min(max(D[i], kMinLevenbergMarquardtDiagonal),
 
108
               kMaxLevenbergMarquardtDiagonal);
 
109
  }
 
110
}
 
111
 
 
112
bool RunCallback(IterationCallback* callback,
 
113
                 const IterationSummary& iteration_summary,
 
114
                 Solver::Summary* summary) {
 
115
  const CallbackReturnType status = (*callback)(iteration_summary);
 
116
  switch (status) {
 
117
    case SOLVER_TERMINATE_SUCCESSFULLY:
 
118
      summary->termination_type = USER_SUCCESS;
 
119
      VLOG(1) << "Terminating on USER_SUCCESS.";
 
120
      return false;
 
121
    case SOLVER_ABORT:
 
122
      summary->termination_type = USER_ABORT;
 
123
      VLOG(1) << "Terminating on USER_ABORT.";
 
124
      return false;
 
125
    case SOLVER_CONTINUE:
 
126
      return true;
 
127
    default:
 
128
      LOG(FATAL) << "Unknown status returned by callback: "
 
129
                 << status;
 
130
  }
 
131
}
 
132
 
 
133
}  // namespace
 
134
 
 
135
LevenbergMarquardt::~LevenbergMarquardt() {}
 
136
 
 
137
void LevenbergMarquardt::Minimize(const Minimizer::Options& options,
 
138
                                  Evaluator* evaluator,
 
139
                                  LinearSolver* linear_solver,
 
140
                                  const double* initial_parameters,
 
141
                                  double* final_parameters,
 
142
                                  Solver::Summary* summary) {
 
143
  time_t start_time = time(NULL);
 
144
  const int num_parameters = evaluator->NumParameters();
 
145
  const int num_effective_parameters = evaluator->NumEffectiveParameters();
 
146
  const int num_residuals = evaluator->NumResiduals();
 
147
 
 
148
  summary->termination_type = NO_CONVERGENCE;
 
149
  summary->num_successful_steps = 0;
 
150
  summary->num_unsuccessful_steps = 0;
 
151
 
 
152
  // Allocate the various vectors needed by the algorithm.
 
153
  memcpy(final_parameters, initial_parameters,
 
154
         num_parameters * sizeof(*initial_parameters));
 
155
 
 
156
  VectorRef x(final_parameters, num_parameters);
 
157
  Vector x_new(num_parameters);
 
158
 
 
159
  Vector lm_step(num_effective_parameters);
 
160
  Vector gradient(num_effective_parameters);
 
161
  Vector scaled_gradient(num_effective_parameters);
 
162
  // Jacobi scaling vector
 
163
  Vector scale(num_effective_parameters);
 
164
 
 
165
  Vector f_model(num_residuals);
 
166
  Vector f(num_residuals);
 
167
  Vector f_new(num_residuals);
 
168
  Vector D(num_parameters);
 
169
  Vector muD(num_parameters);
 
170
 
 
171
  // Ask the Evaluator to create the jacobian matrix. The sparsity
 
172
  // pattern of this matrix is going to remain constant, so we only do
 
173
  // this once and then re-use this matrix for all subsequent Jacobian
 
174
  // computations.
 
175
  scoped_ptr<SparseMatrix> jacobian(evaluator->CreateJacobian());
 
176
 
 
177
  double x_norm  = x.norm();
 
178
 
 
179
  double cost = 0.0;
 
180
  D.setOnes();
 
181
  f.setZero();
 
182
 
 
183
  // Do initial cost and Jacobian evaluation.
 
184
  if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) {
 
185
    LOG(WARNING) << "Failed to compute residuals and Jacobian. "
 
186
                 << "Terminating.";
 
187
    summary->termination_type = NUMERICAL_FAILURE;
 
188
    return;
 
189
  }
 
190
 
 
191
  if (options.jacobi_scaling) {
 
192
    EstimateScale(*jacobian, scale.data());
 
193
    jacobian->ScaleColumns(scale.data());
 
194
  } else {
 
195
    scale.setOnes();
 
196
  }
 
197
 
 
198
  // This is a poor way to do this computation. Even if fixed_cost is
 
199
  // zero, because we are subtracting two possibly large numbers, we
 
200
  // are depending on exact cancellation to give us a zero here. But
 
201
  // initial_cost and cost have been computed by two different
 
202
  // evaluators. One which runs on the whole problem (in
 
203
  // solver_impl.cc) in single threaded mode and another which runs
 
204
  // here on the reduced problem, so fixed_cost can (and does) contain
 
205
  // some numerical garbage with a relative magnitude of 1e-14.
 
206
  //
 
207
  // The right way to do this, would be to compute the fixed cost on
 
208
  // just the set of residual blocks which are held constant and were
 
209
  // removed from the original problem when the reduced problem was
 
210
  // constructed.
 
211
  summary->fixed_cost = summary->initial_cost - cost;
 
212
 
 
213
  double model_cost = f.squaredNorm() / 2.0;
 
214
  double total_cost = summary->fixed_cost + cost;
 
215
 
 
216
  scaled_gradient.setZero();
 
217
  jacobian->LeftMultiply(f.data(), scaled_gradient.data());
 
218
  gradient = scaled_gradient.array() / scale.array();
 
219
 
 
220
  double gradient_max_norm = gradient.lpNorm<Eigen::Infinity>();
 
221
  // We need the max here to guard againt the gradient being zero.
 
222
  const double gradient_max_norm_0 = max(gradient_max_norm, kEpsilon);
 
223
  double gradient_tolerance = options.gradient_tolerance * gradient_max_norm_0;
 
224
 
 
225
  double mu = options.tau;
 
226
  double nu = 2.0;
 
227
  int iteration = 0;
 
228
  double actual_cost_change = 0.0;
 
229
  double step_norm = 0.0;
 
230
  double relative_decrease = 0.0;
 
231
 
 
232
  // Insane steps are steps which are not sane, i.e. there is some
 
233
  // numerical kookiness going on with them. There are various reasons
 
234
  // for this kookiness, some easier to diagnose then others. From the
 
235
  // point of view of the non-linear solver, they are steps which
 
236
  // cannot be used. We return with NUMERICAL_FAILURE after
 
237
  // kMaxLinearSolverRetries consecutive insane steps.
 
238
  bool step_is_sane = false;
 
239
  int num_consecutive_insane_steps = 0;
 
240
 
 
241
  // Whether the step resulted in a sufficient decrease in the
 
242
  // objective function when compared to the decrease in the value of
 
243
  // the lineariztion.
 
244
  bool step_is_successful = false;
 
245
 
 
246
  // Parse the iterations for which to dump the linear problem.
 
247
  vector<int> iterations_to_dump = options.lsqp_iterations_to_dump;
 
248
  sort(iterations_to_dump.begin(), iterations_to_dump.end());
 
249
 
 
250
  IterationSummary iteration_summary;
 
251
  iteration_summary.iteration = iteration;
 
252
  iteration_summary.step_is_successful = false;
 
253
  iteration_summary.cost = total_cost;
 
254
  iteration_summary.cost_change = actual_cost_change;
 
255
  iteration_summary.gradient_max_norm = gradient_max_norm;
 
256
  iteration_summary.step_norm = step_norm;
 
257
  iteration_summary.relative_decrease = relative_decrease;
 
258
  iteration_summary.mu = mu;
 
259
  iteration_summary.eta = options.eta;
 
260
  iteration_summary.linear_solver_iterations = 0;
 
261
  iteration_summary.linear_solver_time_sec = 0.0;
 
262
  iteration_summary.iteration_time_sec = (time(NULL) - start_time);
 
263
  if (options.logging_type >= PER_MINIMIZER_ITERATION) {
 
264
    summary->iterations.push_back(iteration_summary);
 
265
  }
 
266
 
 
267
  // Check if the starting point is an optimum.
 
268
  VLOG(2) << "Gradient max norm: " << gradient_max_norm
 
269
          << " tolerance: " << gradient_tolerance
 
270
          << " ratio: " << gradient_max_norm / gradient_max_norm_0
 
271
          << " tolerance: " << options.gradient_tolerance;
 
272
  if (gradient_max_norm <= gradient_tolerance) {
 
273
    summary->termination_type = GRADIENT_TOLERANCE;
 
274
    VLOG(1) << "Terminating on GRADIENT_TOLERANCE. "
 
275
            << "Relative gradient max norm: "
 
276
            << gradient_max_norm / gradient_max_norm_0
 
277
            << " <= " << options.gradient_tolerance;
 
278
    return;
 
279
  }
 
280
 
 
281
  // Call the various callbacks.
 
282
  for (int i = 0; i < options.callbacks.size(); ++i) {
 
283
    if (!RunCallback(options.callbacks[i], iteration_summary, summary)) {
 
284
      return;
 
285
    }
 
286
  }
 
287
 
 
288
  // We only need the LM diagonal if we are actually going to do at
 
289
  // least one iteration of the optimization. So we wait to do it
 
290
  // until now.
 
291
  LevenbergMarquardtDiagonal(*jacobian, D.data());
 
292
 
 
293
  while ((iteration < options.max_num_iterations) &&
 
294
         (time(NULL) - start_time) <= options.max_solver_time_sec) {
 
295
    time_t iteration_start_time = time(NULL);
 
296
    step_is_sane = false;
 
297
    step_is_successful = false;
 
298
 
 
299
    IterationSummary iteration_summary;
 
300
    // The while loop here is just to provide an easily breakable
 
301
    // control structure. We are guaranteed to always exit this loop
 
302
    // at the end of one iteration or before.
 
303
    while (1) {
 
304
      muD = (mu * D).array().sqrt();
 
305
      LinearSolver::PerSolveOptions solve_options;
 
306
      solve_options.D = muD.data();
 
307
      solve_options.q_tolerance = options.eta;
 
308
      // Disable r_tolerance checking. Since we only care about
 
309
      // termination via the q_tolerance. As Nash and Sofer show,
 
310
      // r_tolerance based termination is essentially useless in
 
311
      // Truncated Newton methods.
 
312
      solve_options.r_tolerance = -1.0;
 
313
 
 
314
      // Invalidate the output array lm_step, so that we can detect if
 
315
      // the linear solver generated numerical garbage.  This is known
 
316
      // to happen for the DENSE_QR and then DENSE_SCHUR solver when
 
317
      // the Jacobin is severly rank deficient and mu is too small.
 
318
      InvalidateArray(num_effective_parameters, lm_step.data());
 
319
      const time_t linear_solver_start_time = time(NULL);
 
320
      LinearSolver::Summary linear_solver_summary =
 
321
          linear_solver->Solve(jacobian.get(),
 
322
                               f.data(),
 
323
                               solve_options,
 
324
                               lm_step.data());
 
325
      iteration_summary.linear_solver_time_sec =
 
326
          (time(NULL) - linear_solver_start_time);
 
327
      iteration_summary.linear_solver_iterations =
 
328
          linear_solver_summary.num_iterations;
 
329
 
 
330
      if (binary_search(iterations_to_dump.begin(),
 
331
                        iterations_to_dump.end(),
 
332
                        iteration)) {
 
333
        CHECK(DumpLinearLeastSquaresProblem(options.lsqp_dump_directory,
 
334
                                            iteration,
 
335
                                            options.lsqp_dump_format_type,
 
336
                                            jacobian.get(),
 
337
                                            muD.data(),
 
338
                                            f.data(),
 
339
                                            lm_step.data(),
 
340
                                            options.num_eliminate_blocks))
 
341
            << "Tried writing linear least squares problem: " 
 
342
            << options.lsqp_dump_directory
 
343
            << " but failed.";
 
344
      }
 
345
 
 
346
      // We ignore the case where the linear solver did not converge,
 
347
      // since the partial solution computed by it still maybe of use,
 
348
      // and there is no reason to ignore it, especially since we
 
349
      // spent so much time computing it.
 
350
      if ((linear_solver_summary.termination_type != TOLERANCE) &&
 
351
          (linear_solver_summary.termination_type != MAX_ITERATIONS)) {
 
352
        VLOG(1) << "Linear solver failure: retrying with a higher mu";
 
353
        break;
 
354
      }
 
355
 
 
356
      if (!IsArrayValid(num_effective_parameters, lm_step.data())) {
 
357
        LOG(WARNING) << "Linear solver failure. Failed to compute a finite "
 
358
                     << "step. Terminating. Please report this to the Ceres "
 
359
                     << "Solver developers.";
 
360
        summary->termination_type = NUMERICAL_FAILURE;
 
361
        return;
 
362
      }
 
363
 
 
364
      step_norm = (lm_step.array() * scale.array()).matrix().norm();
 
365
 
 
366
      // Check step length based convergence. If the step length is
 
367
      // too small, then we are done.
 
368
      const double step_size_tolerance =  options.parameter_tolerance *
 
369
          (x_norm + options.parameter_tolerance);
 
370
 
 
371
      VLOG(2) << "Step size: " << step_norm
 
372
              << " tolerance: " <<  step_size_tolerance
 
373
              << " ratio: " << step_norm / step_size_tolerance
 
374
              << " tolerance: " << options.parameter_tolerance;
 
375
      if (step_norm <= options.parameter_tolerance *
 
376
          (x_norm + options.parameter_tolerance)) {
 
377
        summary->termination_type = PARAMETER_TOLERANCE;
 
378
        VLOG(1) << "Terminating on PARAMETER_TOLERANCE."
 
379
                << "Relative step size: " << step_norm / step_size_tolerance
 
380
            << " <= " << options.parameter_tolerance;
 
381
        return;
 
382
      }
 
383
 
 
384
      Vector delta =  -(lm_step.array() * scale.array()).matrix();
 
385
      if (!evaluator->Plus(x.data(), delta.data(), x_new.data())) {
 
386
        LOG(WARNING) << "Failed to compute Plus(x, delta, x_plus_delta). "
 
387
                     << "Terminating.";
 
388
        summary->termination_type = NUMERICAL_FAILURE;
 
389
        return;
 
390
      }
 
391
 
 
392
      double cost_new = 0.0;
 
393
      if (!evaluator->Evaluate(x_new.data(), &cost_new, NULL, NULL)) {
 
394
        LOG(WARNING) << "Failed to compute the value of the objective "
 
395
                     << "function. Terminating.";
 
396
        summary->termination_type = NUMERICAL_FAILURE;
 
397
        return;
 
398
      }
 
399
 
 
400
      f_model.setZero();
 
401
      jacobian->RightMultiply(lm_step.data(), f_model.data());
 
402
      const double model_cost_new =
 
403
          (f.segment(0, num_residuals) - f_model).squaredNorm() / 2;
 
404
 
 
405
      actual_cost_change = cost - cost_new;
 
406
      double model_cost_change = model_cost - model_cost_new;
 
407
 
 
408
      VLOG(2) << "[Model cost] current: " << model_cost
 
409
              << " new : " << model_cost_new
 
410
              << " change: " << model_cost_change;
 
411
 
 
412
      VLOG(2) << "[Nonlinear cost] current: " << cost
 
413
              << " new : " << cost_new
 
414
              << " change: " << actual_cost_change
 
415
              << " relative change: " << fabs(actual_cost_change) / cost
 
416
              << " tolerance: " << options.function_tolerance;
 
417
 
 
418
      // In exact arithmetic model_cost_change should never be
 
419
      // negative. But due to numerical precision issues, we may end up
 
420
      // with a small negative number. model_cost_change which are
 
421
      // negative and large in absolute value are indicative of a
 
422
      // numerical failure in the solver.
 
423
      if (model_cost_change < -kEpsilon) {
 
424
        VLOG(1) << "Model cost change is negative.\n"
 
425
                << "Current : " << model_cost
 
426
                << " new : " << model_cost_new
 
427
                << " change: " << model_cost_change << "\n";
 
428
        break;
 
429
      }
 
430
 
 
431
      // If we have reached this far, then we are willing to trust the
 
432
      // numerical quality of the step.
 
433
      step_is_sane = true;
 
434
      num_consecutive_insane_steps = 0;
 
435
 
 
436
      // Check function value based convergence.
 
437
      if (fabs(actual_cost_change) < options.function_tolerance * cost) {
 
438
        VLOG(1) << "Termination on FUNCTION_TOLERANCE."
 
439
                << " Relative cost change: " << fabs(actual_cost_change) / cost
 
440
                << " tolerance: " << options.function_tolerance;
 
441
        summary->termination_type = FUNCTION_TOLERANCE;
 
442
        return;
 
443
      }
 
444
 
 
445
      // Clamp model_cost_change at kEpsilon from below.
 
446
      if (model_cost_change < kEpsilon) {
 
447
        VLOG(1) << "Clamping model cost change " << model_cost_change
 
448
                << " to " << kEpsilon;
 
449
        model_cost_change = kEpsilon;
 
450
      }
 
451
 
 
452
      relative_decrease = actual_cost_change / model_cost_change;
 
453
      VLOG(2) << "actual_cost_change / model_cost_change = "
 
454
              << relative_decrease;
 
455
 
 
456
      if (relative_decrease < options.min_relative_decrease) {
 
457
        VLOG(2) << "Unsuccessful step.";
 
458
        break;
 
459
      }
 
460
 
 
461
      VLOG(2) << "Successful step.";
 
462
 
 
463
      ++summary->num_successful_steps;
 
464
      x = x_new;
 
465
      x_norm = x.norm();
 
466
 
 
467
      if (!evaluator->Evaluate(x.data(), &cost, f.data(), jacobian.get())) {
 
468
        LOG(WARNING) << "Failed to compute residuals and jacobian. "
 
469
                     << "Terminating.";
 
470
        summary->termination_type = NUMERICAL_FAILURE;
 
471
        return;
 
472
      }
 
473
 
 
474
      if (options.jacobi_scaling) {
 
475
        jacobian->ScaleColumns(scale.data());
 
476
      }
 
477
 
 
478
      model_cost = f.squaredNorm() / 2.0;
 
479
      LevenbergMarquardtDiagonal(*jacobian, D.data());
 
480
      scaled_gradient.setZero();
 
481
      jacobian->LeftMultiply(f.data(), scaled_gradient.data());
 
482
      gradient = scaled_gradient.array() / scale.array();
 
483
      gradient_max_norm = gradient.lpNorm<Eigen::Infinity>();
 
484
 
 
485
      // Check gradient based convergence.
 
486
      VLOG(2) << "Gradient max norm: " << gradient_max_norm
 
487
              << " tolerance: " << gradient_tolerance
 
488
              << " ratio: " << gradient_max_norm / gradient_max_norm_0
 
489
              << " tolerance: " << options.gradient_tolerance;
 
490
      if (gradient_max_norm <= gradient_tolerance) {
 
491
        summary->termination_type = GRADIENT_TOLERANCE;
 
492
        VLOG(1) << "Terminating on GRADIENT_TOLERANCE. "
 
493
                << "Relative gradient max norm: "
 
494
                << gradient_max_norm / gradient_max_norm_0
 
495
                << " <= " << options.gradient_tolerance
 
496
                << " (tolerance).";
 
497
        return;
 
498
      }
 
499
 
 
500
      mu = mu * max(1.0 / 3.0, 1 - pow(2 * relative_decrease - 1, 3));
 
501
      mu = std::max(options.min_mu, mu);
 
502
      nu = 2.0;
 
503
      step_is_successful = true;
 
504
      break;
 
505
    }
 
506
 
 
507
    if (!step_is_sane) {
 
508
      ++num_consecutive_insane_steps;
 
509
    }
 
510
 
 
511
    if (num_consecutive_insane_steps == kMaxLinearSolverRetries) {
 
512
      summary->termination_type = NUMERICAL_FAILURE;
 
513
      VLOG(1) << "Too many consecutive retries; ending with numerical fail.";
 
514
 
 
515
      if (!options.crash_and_dump_lsqp_on_failure) {
 
516
        return;
 
517
      }
 
518
 
 
519
      // Dump debugging information to disk.
 
520
      CHECK(options.lsqp_dump_format_type == TEXTFILE ||
 
521
            options.lsqp_dump_format_type == PROTOBUF)
 
522
          << "Dumping the linear least squares problem on crash "
 
523
          << "requires Solver::Options::lsqp_dump_format_type to be "
 
524
          << "PROTOBUF or TEXTFILE.";
 
525
 
 
526
      if (DumpLinearLeastSquaresProblem(options.lsqp_dump_directory,
 
527
                                        iteration,
 
528
                                        options.lsqp_dump_format_type,
 
529
                                        jacobian.get(),
 
530
                                        muD.data(),
 
531
                                        f.data(),
 
532
                                        lm_step.data(),
 
533
                                        options.num_eliminate_blocks)) {
 
534
        LOG(FATAL) << "Linear least squares problem saved to: " 
 
535
                   << options.lsqp_dump_directory
 
536
                   << ". Please provide this to the Ceres developers for "
 
537
                   << " debugging along with the v=2 log.";
 
538
      } else {
 
539
        LOG(FATAL) << "Tried writing linear least squares problem: " 
 
540
                   << options.lsqp_dump_directory
 
541
                   << " but failed.";
 
542
      }
 
543
    }
 
544
 
 
545
    if (!step_is_successful) {
 
546
      // Either the step did not lead to a decrease in cost or there
 
547
      // was numerical failure. In either case we will scale mu up and
 
548
      // retry. If it was a numerical failure, we hope that the
 
549
      // stronger regularization will make the linear system better
 
550
      // conditioned. If it was numerically sane, but there was no
 
551
      // decrease in cost, then increasing mu reduces the size of the
 
552
      // trust region and we look for a decrease closer to the
 
553
      // linearization point.
 
554
      ++summary->num_unsuccessful_steps;
 
555
      mu = mu * nu;
 
556
      nu = 2 * nu;
 
557
    }
 
558
 
 
559
    ++iteration;
 
560
 
 
561
    total_cost = summary->fixed_cost + cost;
 
562
 
 
563
    iteration_summary.iteration = iteration;
 
564
    iteration_summary.step_is_successful = step_is_successful;
 
565
    iteration_summary.cost = total_cost;
 
566
    iteration_summary.cost_change = actual_cost_change;
 
567
    iteration_summary.gradient_max_norm = gradient_max_norm;
 
568
    iteration_summary.step_norm = step_norm;
 
569
    iteration_summary.relative_decrease = relative_decrease;
 
570
    iteration_summary.mu = mu;
 
571
    iteration_summary.eta = options.eta;
 
572
    iteration_summary.iteration_time_sec = (time(NULL) - iteration_start_time);
 
573
 
 
574
    if (options.logging_type >= PER_MINIMIZER_ITERATION) {
 
575
      summary->iterations.push_back(iteration_summary);
 
576
    }
 
577
 
 
578
    // Call the various callbacks.
 
579
    for (int i = 0; i < options.callbacks.size(); ++i) {
 
580
      if (!RunCallback(options.callbacks[i], iteration_summary, summary)) {
 
581
        return;
 
582
      }
 
583
    }
 
584
  }
 
585
}
 
586
 
 
587
}  // namespace internal
 
588
}  // namespace ceres