Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/extern
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2013-12-29 14:59:15 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2014-01-01 20:32:47 +0400
commit5933b2455c409963580ea616047f2f2ee332ff71 (patch)
treea1206aa30665518d17aa5bce493cc85151b479f4 /extern
parent71f689843d13b86fad26ab07867ea70fed80c1e7 (diff)
Update Ceres to the latest upstream
Summary: This brings up much easier termination type usage, which for us means we might use: ceres::Summary::IsSolutionUsable() instead of doing manual funky enum values check. Reviewers: keir Differential Revision: https://developer.blender.org/D153
Diffstat (limited to 'extern')
-rw-r--r--extern/libmv/libmv-capi.cc4
-rw-r--r--extern/libmv/libmv/multiview/fundamental.cc4
-rw-r--r--extern/libmv/libmv/multiview/homography.cc4
-rw-r--r--extern/libmv/libmv/tracking/track_region.cc15
-rw-r--r--extern/libmv/libmv/tracking/track_region.h7
-rw-r--r--extern/libmv/third_party/ceres/ChangeLog289
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/solver.h9
-rw-r--r--extern/libmv/third_party/ceres/include/ceres/types.h59
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc19
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc16
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/lapack.cc14
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/lapack.h8
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc58
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/linear_solver.h5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/minimizer.cc2
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc5
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/program.cc30
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/program.h4
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver.cc95
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc175
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/solver_impl.h20
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc22
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc48
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/suitesparse.h22
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc81
-rw-r--r--extern/libmv/third_party/ceres/internal/ceres/types.cc11
26 files changed, 507 insertions, 519 deletions
diff --git a/extern/libmv/libmv-capi.cc b/extern/libmv/libmv-capi.cc
index 95ac2ff703a..474501afbcc 100644
--- a/extern/libmv/libmv-capi.cc
+++ b/extern/libmv/libmv-capi.cc
@@ -332,9 +332,7 @@ int libmv_trackRegion(const libmv_TrackRegionOptions *options,
}
/* TODO(keir): Update the termination string with failure details. */
- if (track_region_result.termination == libmv::TrackRegionResult::PARAMETER_TOLERANCE ||
- track_region_result.termination == libmv::TrackRegionResult::FUNCTION_TOLERANCE ||
- track_region_result.termination == libmv::TrackRegionResult::GRADIENT_TOLERANCE ||
+ if (track_region_result.termination == libmv::TrackRegionResult::CONVERGENCE ||
track_region_result.termination == libmv::TrackRegionResult::NO_CONVERGENCE)
{
tracking_result = true;
diff --git a/extern/libmv/libmv/multiview/fundamental.cc b/extern/libmv/libmv/multiview/fundamental.cc
index 7a1433c3419..ea8594c8cc0 100644
--- a/extern/libmv/libmv/multiview/fundamental.cc
+++ b/extern/libmv/libmv/multiview/fundamental.cc
@@ -538,9 +538,7 @@ bool EstimateFundamentalFromCorrespondences(
LG << "Final refined matrix:\n" << *F;
- return !(summary.termination_type == ceres::DID_NOT_RUN ||
- summary.termination_type == ceres::NUMERICAL_FAILURE ||
- summary.termination_type == ceres::USER_ABORT);
+ return summary.IsSolutionUsable();
}
} // namespace libmv
diff --git a/extern/libmv/libmv/multiview/homography.cc b/extern/libmv/libmv/multiview/homography.cc
index cbd3ec78a57..ce533a3ead2 100644
--- a/extern/libmv/libmv/multiview/homography.cc
+++ b/extern/libmv/libmv/multiview/homography.cc
@@ -330,9 +330,7 @@ bool EstimateHomography2DFromCorrespondences(
LG << "Final refined matrix:\n" << *H;
- return !(summary.termination_type == ceres::DID_NOT_RUN ||
- summary.termination_type == ceres::NUMERICAL_FAILURE ||
- summary.termination_type == ceres::USER_ABORT);
+ return summary.IsSolutionUsable();
}
/**
diff --git a/extern/libmv/libmv/tracking/track_region.cc b/extern/libmv/libmv/tracking/track_region.cc
index 9e0bf9a77da..ef6dac65236 100644
--- a/extern/libmv/libmv/tracking/track_region.cc
+++ b/extern/libmv/libmv/tracking/track_region.cc
@@ -1331,9 +1331,7 @@ void TemplatedTrackRegion(const FloatImage &image1,
// Of the things that can happen in the first pass, don't try the brute
// pass (and second attempt) if the error is one of the terminations below.
- if (result->termination == TrackRegionResult::PARAMETER_TOLERANCE ||
- result->termination == TrackRegionResult::FUNCTION_TOLERANCE ||
- result->termination == TrackRegionResult::GRADIENT_TOLERANCE ||
+ if (result->termination == TrackRegionResult::CONVERGENCE ||
result->termination == TrackRegionResult::SOURCE_OUT_OF_BOUNDS ||
result->termination == TrackRegionResult::DESTINATION_OUT_OF_BOUNDS ||
result->termination == TrackRegionResult::INSUFFICIENT_PATTERN_AREA) {
@@ -1488,7 +1486,7 @@ void TemplatedTrackRegion(const FloatImage &image1,
// TODO(keir): Update the result statistics.
// TODO(keir): Add a normalize-cross-correlation variant.
- if (summary.termination_type == ceres::USER_ABORT) {
+ if (summary.termination_type == ceres::USER_FAILURE) {
result->termination = TrackRegionResult::FELL_OUT_OF_BOUNDS;
return;
}
@@ -1500,8 +1498,7 @@ void TemplatedTrackRegion(const FloatImage &image1,
}
// Avoid computing correlation for tracking failures.
- HANDLE_TERMINATION(DID_NOT_RUN);
- HANDLE_TERMINATION(NUMERICAL_FAILURE);
+ HANDLE_TERMINATION(FAILURE);
// Otherwise, run a final correlation check.
if (options.minimum_correlation > 0.0) {
@@ -1520,13 +1517,11 @@ void TemplatedTrackRegion(const FloatImage &image1,
// than Ceres's parameter tolerance, which operates on the raw parameter
// values rather than the pixel shifts of the patch corners.
if (summary.termination_type == ceres::USER_SUCCESS) {
- result->termination = TrackRegionResult::PARAMETER_TOLERANCE;
+ result->termination = TrackRegionResult::CONVERGENCE;
return;
}
- HANDLE_TERMINATION(PARAMETER_TOLERANCE);
- HANDLE_TERMINATION(FUNCTION_TOLERANCE);
- HANDLE_TERMINATION(GRADIENT_TOLERANCE);
+ HANDLE_TERMINATION(CONVERGENCE);
HANDLE_TERMINATION(NO_CONVERGENCE);
#undef HANDLE_TERMINATION
};
diff --git a/extern/libmv/libmv/tracking/track_region.h b/extern/libmv/libmv/tracking/track_region.h
index 58742cab36c..2ced9dd6550 100644
--- a/extern/libmv/libmv/tracking/track_region.h
+++ b/extern/libmv/libmv/tracking/track_region.h
@@ -110,12 +110,9 @@ struct TrackRegionOptions {
struct TrackRegionResult {
enum Termination {
// Ceres termination types, duplicated; though, not the int values.
- PARAMETER_TOLERANCE,
- FUNCTION_TOLERANCE,
- GRADIENT_TOLERANCE,
+ CONVERGENCE,
NO_CONVERGENCE,
- DID_NOT_RUN,
- NUMERICAL_FAILURE,
+ FAILURE,
// Libmv specific errors.
SOURCE_OUT_OF_BOUNDS,
diff --git a/extern/libmv/third_party/ceres/ChangeLog b/extern/libmv/third_party/ceres/ChangeLog
index 2bd4206cf47..854712fe228 100644
--- a/extern/libmv/third_party/ceres/ChangeLog
+++ b/extern/libmv/third_party/ceres/ChangeLog
@@ -1,3 +1,147 @@
+commit 2b16b0080b6e673eaaf9ed478c9e971d9fcd65de
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Fri Dec 20 15:22:26 2013 -0800
+
+ CompressedRowSparseMatrix::AppendRows and DeleteRows bugfix.
+
+ CompressedRowSparseMatrix can store the row and column block structure
+ but the AppendRows and DeleteRows methods did not pay attention to them.
+ This meant that it was possible to get to a CompressedRowSparseMatrix
+ whose block structure did not match the contents of the matrix.
+
+ This change fixes this problem.
+
+ Change-Id: I1b3c807fc03d8c049ee20511e2bc62806d211b81
+
+commit 27bb4a8589c47a65b5ea2c01872a903043d0ef74
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Wed Dec 18 13:06:58 2013 -0800
+
+ Handle empty problems consistently.
+
+ Until now Ceres was inconsistent in the way it handled a solve
+ call on an "empty" Problem. If the problem did not contain
+ any residual or parameter blocks, it failed. However, if after
+ constructing the reduced program, the problem was found to not
+ contain any modifiable parameter blocks, it was considered a valid
+ problem which had a constant objective function value.
+
+ When creating problems automatically, it is often the case that
+ an empty problem is a corner case. This change makes handling this
+ corner case consistent with the rest of Ceres logic.
+
+ Change-Id: Ia9da09fbf5d5cd7eae6b39a92c1976b8645db9fe
+
+commit dcee120bac04911bf01d8365bddca87c74ce2af9
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Sat Dec 7 21:48:56 2013 -0800
+
+ Consolidate SolverTerminationType enum.
+
+ 1. Rename SolverTerminationType to TerminationType.
+ 2. Consolidate the enum as
+ a. CONVERGENCE - subsumes FUNCTION_TOLERANCE, PARAMETER_TOLERANCE and GRADIENT_TOLERANCE
+ b. NO_CONVERGENCE
+ c. FAILURE - captures all kinds of failures including DID_NOT_RUN.
+ d. USER_SUCCESS
+ e. USER_FAILURE
+ 3. Solver::Summary::error is renamed to be Solver::Summary::message, to both
+ reduce confusion as well as capture its true meaning.
+
+ Change-Id: I27a382e66e67f5a4750d0ee914d941f6b53c326d
+
+commit d1cf320bb4f032cb14b20114a29ce2d867307492
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Nov 28 23:11:11 2013 +0600
+
+ Made collections port compatible with MSVC2008
+
+ The issue was caused by the fact that in this version
+ of MSVC unordered_map class is defined in <unordered_map>
+ header file, but this file declares the class int std::tr1
+ namespace.
+
+ This confused existing assumption that if there's an
+ existing <unordered_map> file then class is declared
+ in std namespace.
+
+ Added an extra check to CMake which detects whether
+ it's std or std::tr1 which actually contains class
+ of unordered_map.
+
+ Change-Id: Ic5cf41913895a6ce8e791cc7602d7cf5492c34de
+
+commit 324eccb5f6ce2a1a0061ec9f3c40778a029a2d97
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Tue Dec 3 09:28:14 2013 -0800
+
+ Restore the state of the Problem after a call to Evaluate.
+
+ Calling Problem::Evaluate mutates the state of the parameter blocks.
+ In particular, depending on the set and order of parameter blocks
+ passed to the evaluate call, it will change the internal indexing
+ used by the Program object used by ProblemImpl. This needs to be
+ undone before Evaluate returns, otherwise the Problem object
+ is in an invalid state.
+
+ To help with testing and debugging in the future, a new method
+ Program::IsValid has been added which checks whether the problem
+ has its parameter and residual blocks in the right state.
+
+ Thanks to Stefan Leutenegger for reporting this.
+
+ Change-Id: I209b486a31433f0cbb58b570047649eca6d42b56
+
+commit 3b1ad31a1fe89fe0bd78e1fffdf22d47d43faaf5
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Dec 2 15:43:20 2013 -0800
+
+ Fix build breakage on old versions of SuiteSparse.
+
+ Change-Id: I2a061615fc374abef2ed323c298359002a6fc5f1
+
+commit 5fd480692b0a0c87e2af2f5a8754042a14f5f089
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Dec 2 12:16:53 2013 -0800
+
+ Add more documentation to the linear solver enums.
+
+ Change-Id: Id57f76f73fa38043c0b6729972b1de8578ad7ede
+
+commit d73acd035359886dfa1c5762b01c6f6449edcab8
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Mon Dec 2 12:02:03 2013 -0800
+
+ Lint cleanup from William Rucklidge.
+
+ Change-Id: I8abcfd369f41b895ce746a21a35f250fe05c39d1
+
+commit 3faac6a28cec4c99c41421d3f585f3786be443b3
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Thu Nov 28 07:13:26 2013 -0800
+
+ More lint cleanups and breakage fixes.
+
+ The previous CL was a premature submit due to lack of coffee.
+
+ Change-Id: Id425d0ef332f569a954f0413e6b1ae6087f40f30
+
+commit ed92366592a951041bd0367c24006101ef7b6286
+Author: Sameer Agarwal <sameeragarwal@google.com>
+Date: Thu Nov 28 06:50:43 2013 -0800
+
+ Lint cleanup from William Rucklidge.
+
+ Change-Id: I745810f5496a1b93263b20ff140f8883da61995e
+
+commit 34b6359f39884683f2bbf06c93040afd42ae135d
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date: Thu Nov 28 18:51:34 2013 +0600
+
+ Fix compilation error after recent enum rename in 33e01b9
+
+ Change-Id: I920aa4754df6b013e86f0e77c61338d7a80e7f45
+
commit 33e01b9c5e1416fe29c55ac0332cdca21c053c83
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Wed Nov 27 10:24:03 2013 -0800
@@ -537,148 +681,3 @@ Date: Sun Oct 27 21:38:13 2013 -0700
are not exposed. This would be done in a future change.
Change-Id: I7ddc36790943f24b19c7f08b10694ae9a822f5c9
-
-commit 5a161a2b9653489ee9040f054b24df971e6b9bbc
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Oct 29 22:08:15 2013 -0700
-
- Template specializations for PartitionedMatrixView.
-
- This speeds up the matrix vector products in the
- IterativeSchurSolver by upto 40%.
-
- Change-Id: Ib5e8d77c7269cf5ffdd2d161893734bb6d38215d
-
-commit e5ce1170bc9993085c81a788e16eb48f1b2fdb97
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Oct 29 07:40:51 2013 -0700
-
- Minor bug fix to autodiff.h
-
- Change-Id: Ib41050a2f2ba1898c71ff19d74f8eca2496212c0
-
-commit 9e9a7d6ca0e75727293f94452d602f02b56d10ba
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Tue Oct 29 06:54:44 2013 -0700
-
- Documentation update.
-
- Add documentation for the new methods added to Problem.
- Fix a bunch of ReST bugs.
-
- Change-Id: I8a79a84040cfa8a679cc5355baccbe6d69bc9e70
-
-commit c6bafdd02c33ec0ccb705578d83e4f601ddeedea
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Mon Oct 28 19:38:08 2013 -0700
-
- Comments from Jim Roseborough.
-
- 1. Fix the tolerance on the rotation matrix conversion test.
- 2. Fix some out of date comments.
-
- Change-Id: I65e80da1f96d7b4d9ac0630ad8cb708c41739840
-
-commit fda69b52130955479591e8f03f97b1cfceca369f
-Author: Keir Mierle <mierle@gmail.com>
-Date: Thu Oct 10 00:25:24 2013 -0700
-
- Export the structure of a problem to the public API
-
- This adds three new public methods to ceres::Problem:
-
- Problem::GetResidualBlocks()
- Problem::GetParameterBlocksForResidualBlock()
- Problem::GetResidualBlocksForParameterBlock()
-
- These permit access to the underlying graph structure of the problem.
-
- Change-Id: I55a4c7f0e5f325f140cb4830e7a7070554594650
-
-commit 63bcdffa7d188b8d8c5309a62c255ba33f061764
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun Oct 27 21:34:13 2013 -0700
-
- Add the 2_d_d SchurEliminator specialization.
-
- This occurs far too often in bundle adjustment problems to be ignored.
-
- Change-Id: Ib137f1566acf5fffa63e50a55fe8e78ea9eb1c14
-
-commit 602096c91363a0b9384f887a15c82e2dac1fb923
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Sun Oct 27 05:09:38 2013 -0700
-
- Move CERES_HASH_NAMESPACE macros to collections_port.h
-
- Now that we have a clearer understanding of the naming rules
- there is no need for these macro definitions to be done in
- the cmake file.
-
- This cleans up the compilation command line.
-
- Change-Id: Idc8fc7a7c9376e021dc4790af66e599105351917
-
-commit f6b67df54ad6daa7036f5b6619243f722d678892
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Oct 25 06:24:19 2013 -0700
-
- Fix handling of unordered_map/unordered_set on OSX 10.9.0.
-
- Depending on the compiler + standard library combination,
- unordered_map/set may or may not be available. If available
- they maybe in the std or the std::tr1 namespaces.
-
- Apple switched to using libc++ with 10.9.0 which places
- unordered_map in std, breaking our assumptions about the
- platform.
-
- This change refactors our logic for dealing with the namespace
- switching, making it a three state thing rather than two. There
- are three defines now, CERES_NO_UNORDERED_MAP, CERES_STD_UNORDERED_MAP
- and CERES_TR1_UNORDERED_MAP. Earlier the first two were conflated
- into one, leading to the breakage.
-
- Change-Id: I904fe8c49529169bdefa9f2ee6d629e7eab0b855
-
-commit 21d6a99fe68e99fa51db32d55f587b42ef9a476c
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Fri Oct 25 10:20:24 2013 -0700
-
- Fix AngleAxisToRotationMatrix near zero.
-
- The Taylor series approximation had its sign flipped and the
- tests did not catch it since we were switching exactly at zero,
- which was not getting triggered.
-
- This changes modifies the tolerance, adds a test that triggers
- and fixes the bug.
-
- Thanks to Michael Samples for reporting this.
-
- Change-Id: I6f92f6348e5d4421ffe194fba92c04285449484c
-
-commit 0e2743e24d013b25109396cfa0d8d0f1e8e84964
-Author: Sameer Agarwal <sameeragarwal@google.com>
-Date: Wed Oct 23 14:51:07 2013 -0700
-
- Add BlockRandomAccessDiagonalMatrix.
-
- This class is used in the SchurJacobiPreconditioner for
- storing the preconditioner matrix. Using it speeds up
- the computation of the preconditioner by ~15% due to
- the elimination of a hash table lookup.
-
- Change-Id: Iba2b34aad0d9eb9bcb7f6e6fad16aa416aac0d2a
-
-commit 6a2bcaa1d55d38bc10d043f1458657caac2be7a7
-Author: Alex Stewart <alexs.mac@gmail.com>
-Date: Wed Oct 23 14:06:44 2013 +0100
-
- Adding explicit link to libm for pure-C curve fitting example.
-
- - Any pure-C program #including <math.h> will need to link against
- libm, some compilers will let an indirect link slide (via Ceres in
- this case) but some won't.
-
- Change-Id: I6890702fa0d2c3fbb747f0f81fc3fa3631839de4
diff --git a/extern/libmv/third_party/ceres/include/ceres/solver.h b/extern/libmv/third_party/ceres/include/ceres/solver.h
index 7776c470eba..f0d5be60fa5 100644
--- a/extern/libmv/third_party/ceres/include/ceres/solver.h
+++ b/extern/libmv/third_party/ceres/include/ceres/solver.h
@@ -714,14 +714,15 @@ class Solver {
// termination.
string FullReport() const;
+ bool IsSolutionUsable() const;
+
// Minimizer summary -------------------------------------------------
MinimizerType minimizer_type;
- SolverTerminationType termination_type;
+ TerminationType termination_type;
- // If the solver did not run, or there was a failure, a
- // description of the error.
- string error;
+ // Reason why the solver terminated.
+ string message;
// Cost of the problem (value of the objective function) before
// the optimization.
diff --git a/extern/libmv/third_party/ceres/include/ceres/types.h b/extern/libmv/third_party/ceres/include/ceres/types.h
index 617bec0e1b6..600d226ab16 100644
--- a/extern/libmv/third_party/ceres/include/ceres/types.h
+++ b/extern/libmv/third_party/ceres/include/ceres/types.h
@@ -301,41 +301,42 @@ enum DoglegType {
SUBSPACE_DOGLEG
};
-enum SolverTerminationType {
- // The minimizer did not run at all; usually due to errors in the user's
- // Problem or the solver options.
- DID_NOT_RUN,
-
- // The solver ran for maximum number of iterations specified by the
- // user, but none of the convergence criterion specified by the user
- // were met.
- NO_CONVERGENCE,
-
- // Minimizer terminated because
- // (new_cost - old_cost) < function_tolerance * old_cost;
- FUNCTION_TOLERANCE,
-
- // Minimizer terminated because
- // max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i|
- GRADIENT_TOLERANCE,
+enum TerminationType {
+ // Minimizer terminated because one of the convergence criterion set
+ // by the user was satisfied.
+ //
+ // 1. (new_cost - old_cost) < function_tolerance * old_cost;
+ // 2. max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i|
+ // 3. |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance)
+ //
+ // The user's parameter blocks will be updated with the solution.
+ CONVERGENCE,
- // Minimized terminated because
- // |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance)
- PARAMETER_TOLERANCE,
+ // The solver ran for maximum number of iterations or maximum amount
+ // of time specified by the user, but none of the convergence
+ // criterion specified by the user were met. The user's parameter
+ // blocks will be updated with the solution found so far.
+ NO_CONVERGENCE,
- // The minimizer terminated because it encountered a numerical error
- // that it could not recover from.
- NUMERICAL_FAILURE,
+ // The minimizer terminated because of an error. The user's
+ // parameter blocks will not be updated.
+ FAILURE,
// Using an IterationCallback object, user code can control the
// minimizer. The following enums indicate that the user code was
// responsible for termination.
+ //
+ // Minimizer terminated successfully because a user
+ // IterationCallback returned SOLVER_TERMINATE_SUCCESSFULLY.
+ //
+ // The user's parameter blocks will be updated with the solution.
+ USER_SUCCESS,
- // User's IterationCallback returned SOLVER_ABORT.
- USER_ABORT,
-
- // User's IterationCallback returned SOLVER_TERMINATE_SUCCESSFULLY
- USER_SUCCESS
+ // Minimizer terminated because because a user IterationCallback
+ // returned SOLVER_ABORT.
+ //
+ // The user's parameter blocks will not be updated.
+ USER_FAILURE
};
// Enums used by the IterationCallback instances to indicate to the
@@ -459,7 +460,7 @@ bool StringToCovarianceAlgorithmType(
string value,
CovarianceAlgorithmType* type);
-const char* SolverTerminationTypeToString(SolverTerminationType type);
+const char* TerminationTypeToString(TerminationType type);
bool IsSchurType(LinearSolverType type);
bool IsSparseLinearAlgebraLibraryTypeAvailable(
diff --git a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc
index e200c928509..439270ed3bc 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/compressed_row_sparse_matrix.cc
@@ -31,6 +31,7 @@
#include "ceres/compressed_row_sparse_matrix.h"
#include <algorithm>
+#include <numeric>
#include <vector>
#include "ceres/crs_matrix.h"
#include "ceres/internal/port.h"
@@ -215,11 +216,28 @@ void CompressedRowSparseMatrix::DeleteRows(int delta_rows) {
num_rows_ -= delta_rows;
rows_.resize(num_rows_ + 1);
+
+ // Walk the list of row blocks untill we reach the new number of
+ // rows and then drop the rest of the row blocks.
+ int num_row_blocks = 0;
+ int num_rows = 0;
+ while (num_row_blocks < row_blocks_.size() && num_rows < num_rows_) {
+ num_rows += row_blocks_[num_row_blocks];
+ ++num_row_blocks;
+ }
+
+ row_blocks_.resize(num_row_blocks);
}
void CompressedRowSparseMatrix::AppendRows(const CompressedRowSparseMatrix& m) {
CHECK_EQ(m.num_cols(), num_cols_);
+ CHECK(row_blocks_.size() == 0 || m.row_blocks().size() !=0)
+ << "Cannot append a matrix with row blocks to one without and vice versa."
+ << "This matrix has : " << row_blocks_.size() << " row blocks."
+ << "The matrix being appended has: " << m.row_blocks().size()
+ << " row blocks.";
+
if (cols_.size() < num_nonzeros() + m.num_nonzeros()) {
cols_.resize(num_nonzeros() + m.num_nonzeros());
values_.resize(num_nonzeros() + m.num_nonzeros());
@@ -239,6 +257,7 @@ void CompressedRowSparseMatrix::AppendRows(const CompressedRowSparseMatrix& m) {
}
num_rows_ += m.num_rows();
+ row_blocks_.insert(row_blocks_.end(), m.row_blocks().begin(), m.row_blocks().end());
}
void CompressedRowSparseMatrix::ToTextFile(FILE* file) const {
diff --git a/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc
index 91f0393d966..75c80bf5687 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/covariance_impl.cc
@@ -441,23 +441,23 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSparseCholesky() {
cholmod_jacobian_view.sorted = 1;
cholmod_jacobian_view.packed = 1;
- string status;
- cholmod_factor* factor = ss.AnalyzeCholesky(&cholmod_jacobian_view, &status);
+ string message;
+ cholmod_factor* factor = ss.AnalyzeCholesky(&cholmod_jacobian_view, &message);
event_logger.AddEvent("Symbolic Factorization");
if (factor == NULL) {
LOG(ERROR) << "Covariance estimation failed. "
<< "CHOLMOD symbolic cholesky factorization returned with: "
- << status;
+ << message;
return false;
}
LinearSolverTerminationType termination_type =
- ss.Cholesky(&cholmod_jacobian_view, factor, &status);
+ ss.Cholesky(&cholmod_jacobian_view, factor, &message);
event_logger.AddEvent("Numeric Factorization");
if (termination_type != LINEAR_SOLVER_SUCCESS) {
LOG(ERROR) << "Covariance estimation failed. "
<< "CHOLMOD numeric cholesky factorization returned with: "
- << status;
+ << message;
ss.Free(factor);
return false;
}
@@ -470,7 +470,7 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSparseCholesky() {
LOG(ERROR) << "Cholesky factorization of J'J is not reliable. "
<< "Reciprocal condition number: "
<< reciprocal_condition_number << " "
- << "min_reciprocal_condition_number : "
+ << "min_reciprocal_condition_number: "
<< options_.min_reciprocal_condition_number;
ss.Free(factor);
return false;
@@ -506,7 +506,7 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSparseCholesky() {
}
rhs_x[r] = 1.0;
- cholmod_dense* solution = ss.Solve(factor, rhs);
+ cholmod_dense* solution = ss.Solve(factor, rhs, &message);
double* solution_x = reinterpret_cast<double*>(solution->x);
for (int idx = row_begin; idx < row_end; ++idx) {
const int c = cols[idx];
@@ -822,7 +822,7 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingDenseSVD() {
LOG(ERROR) << "Cholesky factorization of J'J is not reliable. "
<< "Reciprocal condition number: "
<< singular_value_ratio * singular_value_ratio << " "
- << "min_reciprocal_condition_number : "
+ << "min_reciprocal_condition_number: "
<< options_.min_reciprocal_condition_number;
return false;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/lapack.cc b/extern/libmv/third_party/ceres/internal/ceres/lapack.cc
index c4f9302515e..e124d757024 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/lapack.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/lapack.cc
@@ -70,7 +70,7 @@ LinearSolverTerminationType LAPACK::SolveInPlaceUsingCholesky(
int num_rows,
const double* in_lhs,
double* rhs_and_solution,
- string* status) {
+ string* message) {
#ifdef CERES_NO_LAPACK
LOG(FATAL) << "Ceres was built without a BLAS library.";
return LINEAR_SOLVER_FATAL_ERROR;
@@ -91,10 +91,10 @@ LinearSolverTerminationType LAPACK::SolveInPlaceUsingCholesky(
}
if (info > 0) {
- *status =
+ *message =
StringPrintf(
"LAPACK::dpotrf numerical failure. "
- "The leading minor of order %d is not positive definite.", info);
+ "The leading minor of order %d is not positive definite.", info);
return LINEAR_SOLVER_FAILURE;
}
@@ -107,7 +107,7 @@ LinearSolverTerminationType LAPACK::SolveInPlaceUsingCholesky(
return LINEAR_SOLVER_FATAL_ERROR;
}
- *status = "Success";
+ *message = "Success";
return LINEAR_SOLVER_SUCCESS;
#endif
};
@@ -138,7 +138,7 @@ int LAPACK::EstimateWorkSizeForQR(int num_rows, int num_cols) {
LOG(FATAL) << "Congratulations, you found a bug in Ceres."
<< "Please report it."
<< "LAPACK::dgels fatal error."
- << "Argument: " << info << " is invalid.";
+ << "Argument: " << -info << " is invalid.";
}
return static_cast<int>(work);
#endif
@@ -151,7 +151,7 @@ LinearSolverTerminationType LAPACK::SolveInPlaceUsingQR(
int work_size,
double* work,
double* rhs_and_solution,
- string* status) {
+ string* message) {
#ifdef CERES_NO_LAPACK
LOG(FATAL) << "Ceres was built without a LAPACK library.";
return LINEAR_SOLVER_FATAL_ERROR;
@@ -184,7 +184,7 @@ LinearSolverTerminationType LAPACK::SolveInPlaceUsingQR(
<< "Argument: " << -info << " is invalid.";
}
- *status = "Success.";
+ *message = "Success.";
return LINEAR_SOLVER_SUCCESS;
#endif
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/lapack.h b/extern/libmv/third_party/ceres/internal/ceres/lapack.h
index 53a33e1b19d..8933c2c8d83 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/lapack.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/lapack.h
@@ -51,14 +51,14 @@ class LAPACK {
//
// This function uses the LAPACK dpotrf and dpotrs routines.
//
- // The return value and the status string together describe whether
+ // The return value and the message string together describe whether
// the solver terminated successfully or not and if so, what was the
// reason for failure.
static LinearSolverTerminationType SolveInPlaceUsingCholesky(
int num_rows,
const double* lhs,
double* rhs_and_solution,
- string* status);
+ string* message);
// The SolveUsingQR function requires a buffer for its temporary
// computation. This function given the size of the lhs matrix will
@@ -81,7 +81,7 @@ class LAPACK {
//
// This function uses the LAPACK dgels routine.
//
- // The return value and the status string together describe whether
+ // The return value and the message string together describe whether
// the solver terminated successfully or not and if so, what was the
// reason for failure.
static LinearSolverTerminationType SolveInPlaceUsingQR(
@@ -91,7 +91,7 @@ class LAPACK {
int work_size,
double* work,
double* rhs_and_solution,
- string* status);
+ string* message);
};
} // namespace internal
diff --git a/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc
index 4590afedbed..339d2757bdb 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/line_search_minimizer.cc
@@ -126,9 +126,9 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
// Do initial cost and Jacobian evaluation.
if (!Evaluate(evaluator, x, &current_state)) {
- summary->error = "Terminating: Cost and gradient evaluation failed.";
- summary->termination_type = NUMERICAL_FAILURE;
- LOG_IF(WARNING, is_not_silent) << summary->error;
+ summary->message = "Terminating: Cost and gradient evaluation failed.";
+ summary->termination_type = FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->message;
return;
}
@@ -146,14 +146,14 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
options.gradient_tolerance * initial_gradient_max_norm;
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
- summary->error =
+ summary->message =
StringPrintf("Terminating: Gradient tolerance reached. "
"Relative gradient max norm: %e <= %e",
iteration_summary.gradient_max_norm /
initial_gradient_max_norm,
options.gradient_tolerance);
- summary->termination_type = GRADIENT_TOLERANCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ summary->termination_type = CONVERGENCE;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
@@ -198,10 +198,10 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
scoped_ptr<LineSearch>
line_search(LineSearch::Create(options.line_search_type,
line_search_options,
- &summary->error));
+ &summary->message));
if (line_search.get() == NULL) {
- summary->termination_type = DID_NOT_RUN;
- LOG_IF(ERROR, is_not_silent) << summary->error;
+ summary->termination_type = FAILURE;
+ LOG_IF(ERROR, is_not_silent) << summary->message;
return;
}
@@ -215,18 +215,18 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
iteration_start_time = WallTimeInSeconds();
if (iteration_summary.iteration >= options.max_num_iterations) {
- summary->error = "Terminating: Maximum number of iterations reached.";
+ summary->message = "Terminating: Maximum number of iterations reached.";
summary->termination_type = NO_CONVERGENCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ VLOG_IF(1, is_not_silent) << summary->message;
break;
}
const double total_solver_time = iteration_start_time - start_time +
summary->preprocessor_time_in_seconds;
if (total_solver_time >= options.max_solver_time_in_seconds) {
- summary->error = "Terminating: Maximum solver time reached.";
+ summary->message = "Terminating: Maximum solver time reached.";
summary->termination_type = NO_CONVERGENCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ VLOG_IF(1, is_not_silent) << summary->message;
break;
}
@@ -251,12 +251,12 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
// Line search direction failed to generate a new direction, and we
// have already reached our specified maximum number of restarts,
// terminate optimization.
- summary->error =
- StringPrintf("Termination: Line search direction failure: specified "
+ summary->message =
+ StringPrintf("Terminating: Line search direction failure: specified "
"max_num_line_search_direction_restarts: %d reached.",
options.max_num_line_search_direction_restarts);
- summary->termination_type = NUMERICAL_FAILURE;
- LOG_IF(WARNING, is_not_silent) << summary->error;
+ summary->termination_type = FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->message;
break;
} else if (!line_search_status) {
// Restart line search direction with gradient descent on first iteration
@@ -299,14 +299,14 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
// direction in a line search, most likely cause for this being violated
// would be a numerical failure in the line search direction calculation.
if (initial_step_size < 0.0) {
- summary->error =
+ summary->message =
StringPrintf("Numerical failure in line search, initial_step_size is "
"negative: %.5e, directional_derivative: %.5e, "
"(current_cost - previous_cost): %.5e",
initial_step_size, current_state.directional_derivative,
(current_state.cost - previous_state.cost));
- summary->termination_type = NUMERICAL_FAILURE;
- LOG_IF(WARNING, is_not_silent) << summary->error;
+ summary->termination_type = FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->message;
break;
}
@@ -315,15 +315,15 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
current_state.directional_derivative,
&line_search_summary);
if (!line_search_summary.success) {
- summary->error =
+ summary->message =
StringPrintf("Numerical failure in line search, failed to find "
"a valid step size, (did not run out of iterations) "
"using initial_step_size: %.5e, initial_cost: %.5e, "
"initial_gradient: %.5e.",
initial_step_size, current_state.cost,
current_state.directional_derivative);
- LOG_IF(WARNING, is_not_silent) << summary->error;
- summary->termination_type = NUMERICAL_FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->message;
+ summary->termination_type = FAILURE;
break;
}
@@ -355,14 +355,14 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.gradient_norm = sqrt(current_state.gradient_squared_norm);
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
- summary->error =
+ summary->message =
StringPrintf("Terminating: Gradient tolerance reached. "
"Relative gradient max norm: %e <= %e. ",
(iteration_summary.gradient_max_norm /
initial_gradient_max_norm),
options.gradient_tolerance);
- summary->termination_type = GRADIENT_TOLERANCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ summary->termination_type = CONVERGENCE;
+ VLOG_IF(1, is_not_silent) << summary->message;
break;
}
@@ -370,14 +370,14 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options,
const double absolute_function_tolerance =
options.function_tolerance * previous_state.cost;
if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) {
- summary->error =
+ summary->message =
StringPrintf("Terminating. Function tolerance reached. "
"|cost_change|/cost: %e <= %e",
fabs(iteration_summary.cost_change) /
previous_state.cost,
options.function_tolerance);
- summary->termination_type = FUNCTION_TOLERANCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ summary->termination_type = CONVERGENCE;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
index cb26356d203..8737c7cab53 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/linear_solver.h
@@ -62,7 +62,10 @@ enum LinearSolverTerminationType {
// the linear system being poorly conditioned.
LINEAR_SOLVER_FAILURE,
- // Solver failed with a fatal error that cannot be recovered from.
+ // Solver failed with a fatal error that cannot be recovered from,
+ // e.g. CHOLMOD ran out of memory when computing the symbolic or
+ // numeric factorization or an underlying library was called with
+ // the wrong arguments.
LINEAR_SOLVER_FATAL_ERROR
};
diff --git a/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc
index 2e2c15ac612..bdb6a118aca 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/minimizer.cc
@@ -54,7 +54,7 @@ bool Minimizer::RunCallbacks(const vector<IterationCallback*> callbacks,
VLOG(1) << "Terminating: User callback returned USER_SUCCESS.";
return false;
case SOLVER_ABORT:
- summary->termination_type = USER_ABORT;
+ summary->termination_type = USER_FAILURE;
VLOG(1) << "Terminating: User callback returned USER_ABORT.";
return false;
default:
diff --git a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
index ae87fcb0317..09eed9e614c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/problem_impl.cc
@@ -638,6 +638,9 @@ bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options,
for (int i = 0; i < variable_parameter_blocks.size(); ++i) {
variable_parameter_blocks[i]->SetVarying();
}
+
+ program_->SetParameterBlockStatePtrsToUserStatePtrs();
+ program_->SetParameterOffsetsAndIndex();
return false;
}
@@ -696,6 +699,8 @@ bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options,
}
}
+ program_->SetParameterBlockStatePtrsToUserStatePtrs();
+ program_->SetParameterOffsetsAndIndex();
return status;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.cc b/extern/libmv/third_party/ceres/internal/ceres/program.cc
index 82d76d39233..9e5c51bd696 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/program.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/program.cc
@@ -140,6 +140,36 @@ void Program::SetParameterOffsetsAndIndex() {
}
}
+bool Program::IsValid() const {
+ for (int i = 0; i < residual_blocks_.size(); ++i) {
+ const ResidualBlock* residual_block = residual_blocks_[i];
+ if (residual_block->index() != i) {
+ LOG(WARNING) << "Residual block: " << i
+ << " has incorrect index: " << residual_block->index();
+ return false;
+ }
+ }
+
+ int state_offset = 0;
+ int delta_offset = 0;
+ for (int i = 0; i < parameter_blocks_.size(); ++i) {
+ const ParameterBlock* parameter_block = parameter_blocks_[i];
+ if (parameter_block->index() != i ||
+ parameter_block->state_offset() != state_offset ||
+ parameter_block->delta_offset() != delta_offset) {
+ LOG(WARNING) << "Parameter block: " << i
+ << "has incorrect indexing information: "
+ << parameter_block->ToString();
+ return false;
+ }
+
+ state_offset += parameter_blocks_[i]->Size();
+ delta_offset += parameter_blocks_[i]->LocalSize();
+ }
+
+ return true;
+}
+
int Program::NumResidualBlocks() const {
return residual_blocks_.size();
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/program.h b/extern/libmv/third_party/ceres/internal/ceres/program.h
index 5002b7e752e..4288f609cf8 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/program.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/program.h
@@ -99,6 +99,10 @@ class Program {
// position of the parameter in the state and delta vector respectively.
void SetParameterOffsetsAndIndex();
+ // Check if the internal state of the program (the indexing and the
+ // offsets) are correct.
+ bool IsValid() const;
+
// See problem.h for what these do.
int NumParameterBlocks() const;
int NumParameters() const;
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver.cc b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
index 67e168cd2d4..da87de19f2c 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver.cc
@@ -85,8 +85,8 @@ Solver::Summary::Summary()
// Invalid values for most fields, to ensure that we are not
// accidentally reporting default values.
: minimizer_type(TRUST_REGION),
- termination_type(DID_NOT_RUN),
- error("ceres::Solve was not called."),
+ termination_type(FAILURE),
+ message("ceres::Solve was not called."),
initial_cost(-1.0),
final_cost(-1.0),
fixed_cost(-1.0),
@@ -131,64 +131,40 @@ Solver::Summary::Summary()
max_lbfgs_rank(-1) {
}
-string Solver::Summary::BriefReport() const {
- string report = "Ceres Solver Report: ";
- if (termination_type == DID_NOT_RUN) {
- return report + "Termination: DID_NOT_RUN, because " + error;
- }
-
- internal::StringAppendF(&report, "Iterations: %d",
- num_successful_steps + num_unsuccessful_steps);
- internal::StringAppendF(&report, ", Initial cost: %e", initial_cost);
-
- // If the solver failed or was aborted, then the final_cost has no
- // meaning.
- if (termination_type != NUMERICAL_FAILURE &&
- termination_type != USER_ABORT) {
- internal::StringAppendF(&report, ", Final cost: %e", final_cost);
- }
-
- internal::StringAppendF(&report, ", Termination: %s.",
- SolverTerminationTypeToString(termination_type));
- return report;
-};
-
using internal::StringAppendF;
using internal::StringPrintf;
+string Solver::Summary::BriefReport() const {
+ return StringPrintf("Ceres Solver Report: "
+ "Iterations: %d, "
+ "Initial cost: %e, "
+ "Final cost: %e, "
+ "Termination: %s",
+ num_successful_steps + num_unsuccessful_steps,
+ initial_cost,
+ final_cost,
+ TerminationTypeToString(termination_type));
+};
+
string Solver::Summary::FullReport() const {
string report =
"\n"
"Ceres Solver Report\n"
"-------------------\n";
- if (termination_type == DID_NOT_RUN) {
- StringAppendF(&report, " Original\n");
- StringAppendF(&report, "Parameter blocks % 10d\n", num_parameter_blocks);
- StringAppendF(&report, "Parameters % 10d\n", num_parameters);
- if (num_effective_parameters != num_parameters) {
- StringAppendF(&report, "Effective parameters% 10d\n", num_parameters);
- }
-
- StringAppendF(&report, "Residual blocks % 10d\n",
- num_residual_blocks);
- StringAppendF(&report, "Residuals % 10d\n\n",
- num_residuals);
- } else {
- StringAppendF(&report, "%45s %21s\n", "Original", "Reduced");
- StringAppendF(&report, "Parameter blocks % 25d% 25d\n",
- num_parameter_blocks, num_parameter_blocks_reduced);
- StringAppendF(&report, "Parameters % 25d% 25d\n",
- num_parameters, num_parameters_reduced);
- if (num_effective_parameters_reduced != num_parameters_reduced) {
- StringAppendF(&report, "Effective parameters% 25d% 25d\n",
- num_effective_parameters, num_effective_parameters_reduced);
- }
- StringAppendF(&report, "Residual blocks % 25d% 25d\n",
- num_residual_blocks, num_residual_blocks_reduced);
- StringAppendF(&report, "Residual % 25d% 25d\n",
- num_residuals, num_residuals_reduced);
+ StringAppendF(&report, "%45s %21s\n", "Original", "Reduced");
+ StringAppendF(&report, "Parameter blocks % 25d% 25d\n",
+ num_parameter_blocks, num_parameter_blocks_reduced);
+ StringAppendF(&report, "Parameters % 25d% 25d\n",
+ num_parameters, num_parameters_reduced);
+ if (num_effective_parameters_reduced != num_parameters_reduced) {
+ StringAppendF(&report, "Effective parameters% 25d% 25d\n",
+ num_effective_parameters, num_effective_parameters_reduced);
}
+ StringAppendF(&report, "Residual blocks % 25d% 25d\n",
+ num_residual_blocks, num_residual_blocks_reduced);
+ StringAppendF(&report, "Residual % 25d% 25d\n",
+ num_residuals, num_residuals_reduced);
if (minimizer_type == TRUST_REGION) {
// TRUST_SEARCH HEADER
@@ -314,17 +290,10 @@ string Solver::Summary::FullReport() const {
num_threads_given, num_threads_used);
}
- if (termination_type == DID_NOT_RUN) {
- StringAppendF(&report, "Termination: %20s\n",
- "DID_NOT_RUN");
- StringAppendF(&report, "Reason: %s\n", error.c_str());
- return report;
- }
-
StringAppendF(&report, "\nCost:\n");
StringAppendF(&report, "Initial % 30e\n", initial_cost);
- if (termination_type != NUMERICAL_FAILURE &&
- termination_type != USER_ABORT) {
+ if (termination_type != FAILURE &&
+ termination_type != USER_FAILURE) {
StringAppendF(&report, "Final % 30e\n", final_cost);
StringAppendF(&report, "Change % 30e\n",
initial_cost - final_cost);
@@ -376,8 +345,14 @@ string Solver::Summary::FullReport() const {
total_time_in_seconds);
StringAppendF(&report, "Termination: %25s\n",
- SolverTerminationTypeToString(termination_type));
+ TerminationTypeToString(termination_type));
return report;
};
+bool Solver::Summary::IsSolutionUsable() const {
+ return (termination_type == CONVERGENCE ||
+ termination_type == NO_CONVERGENCE ||
+ termination_type == USER_SUCCESS);
+}
+
} // namespace ceres
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
index 1ebf442131a..6c579a6098d 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.cc
@@ -208,6 +208,22 @@ void SummarizeOrdering(ParameterBlockOrdering* ordering,
}
}
+void SummarizeGivenProgram(const Program& program, Solver::Summary* summary) {
+ summary->num_parameter_blocks = program.NumParameterBlocks();
+ summary->num_parameters = program.NumParameters();
+ summary->num_effective_parameters = program.NumEffectiveParameters();
+ summary->num_residual_blocks = program.NumResidualBlocks();
+ summary->num_residuals = program.NumResiduals();
+}
+
+void SummarizeReducedProgram(const Program& program, Solver::Summary* summary) {
+ summary->num_parameter_blocks_reduced = program.NumParameterBlocks();
+ summary->num_parameters_reduced = program.NumParameters();
+ summary->num_effective_parameters_reduced = program.NumEffectiveParameters();
+ summary->num_residual_blocks_reduced = program.NumResidualBlocks();
+ summary->num_residuals_reduced = program.NumResiduals();
+}
+
} // namespace
void SolverImpl::TrustRegionMinimize(
@@ -351,29 +367,10 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
*CHECK_NOTNULL(summary) = Solver::Summary();
summary->minimizer_type = TRUST_REGION;
- summary->num_parameter_blocks = problem_impl->NumParameterBlocks();
- summary->num_parameters = problem_impl->NumParameters();
- summary->num_effective_parameters =
- original_program->NumEffectiveParameters();
- summary->num_residual_blocks = problem_impl->NumResidualBlocks();
- summary->num_residuals = problem_impl->NumResiduals();
-
- // Empty programs are usually a user error.
- if (summary->num_parameter_blocks == 0) {
- summary->error = "Problem contains no parameter blocks.";
- LOG(ERROR) << summary->error;
- return;
- }
-
- if (summary->num_residual_blocks == 0) {
- summary->error = "Problem contains no residual blocks.";
- LOG(ERROR) << summary->error;
- return;
- }
+ SummarizeGivenProgram(*original_program, summary);
SummarizeOrdering(original_options.linear_solver_ordering,
&(summary->linear_solver_ordering_given));
-
SummarizeOrdering(original_options.inner_iteration_ordering,
&(summary->inner_iteration_ordering_given));
@@ -404,9 +401,9 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
if (options.trust_region_minimizer_iterations_to_dump.size() > 0 &&
options.trust_region_problem_dump_format_type != CONSOLE &&
options.trust_region_problem_dump_directory.empty()) {
- summary->error =
+ summary->message =
"Solver::Options::trust_region_problem_dump_directory is empty.";
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
@@ -434,8 +431,8 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
}
if (original_options.linear_solver_ordering != NULL) {
- if (!IsOrderingValid(original_options, problem_impl, &summary->error)) {
- LOG(ERROR) << summary->error;
+ if (!IsOrderingValid(original_options, problem_impl, &summary->message)) {
+ LOG(ERROR) << summary->message;
return;
}
event_logger.AddEvent("CheckOrdering");
@@ -466,7 +463,7 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
scoped_ptr<Program> reduced_program(CreateReducedProgram(&options,
problem_impl,
&summary->fixed_cost,
- &summary->error));
+ &summary->message));
event_logger.AddEvent("CreateReducedProgram");
if (reduced_program == NULL) {
@@ -475,30 +472,23 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
SummarizeOrdering(options.linear_solver_ordering,
&(summary->linear_solver_ordering_used));
-
- summary->num_parameter_blocks_reduced = reduced_program->NumParameterBlocks();
- summary->num_parameters_reduced = reduced_program->NumParameters();
- summary->num_effective_parameters_reduced =
- reduced_program->NumEffectiveParameters();
- summary->num_residual_blocks_reduced = reduced_program->NumResidualBlocks();
- summary->num_residuals_reduced = reduced_program->NumResiduals();
+ SummarizeReducedProgram(*reduced_program, summary);
if (summary->num_parameter_blocks_reduced == 0) {
summary->preprocessor_time_in_seconds =
WallTimeInSeconds() - solver_start_time;
double post_process_start_time = WallTimeInSeconds();
- LOG(INFO) << "Terminating: FUNCTION_TOLERANCE reached. "
- << "No non-constant parameter blocks found.";
+
+ summary->message =
+ "Terminating: Function tolerance reached. "
+ "No non-constant parameter blocks found.";
+ summary->termination_type = CONVERGENCE;
+ VLOG(1) << summary->message;
summary->initial_cost = summary->fixed_cost;
summary->final_cost = summary->fixed_cost;
- // FUNCTION_TOLERANCE is the right convergence here, as we know
- // that the objective function is constant and cannot be changed
- // any further.
- summary->termination_type = FUNCTION_TOLERANCE;
-
// Ensure the program state is set to the user parameters on the way out.
original_program->SetParameterBlockStatePtrsToUserStatePtrs();
original_program->SetParameterOffsetsAndIndex();
@@ -509,7 +499,7 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
}
scoped_ptr<LinearSolver>
- linear_solver(CreateLinearSolver(&options, &summary->error));
+ linear_solver(CreateLinearSolver(&options, &summary->message));
event_logger.AddEvent("CreateLinearSolver");
if (linear_solver == NULL) {
return;
@@ -536,7 +526,7 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
scoped_ptr<Evaluator> evaluator(CreateEvaluator(options,
problem_impl->parameter_map(),
reduced_program.get(),
- &summary->error));
+ &summary->message));
event_logger.AddEvent("CreateEvaluator");
@@ -556,7 +546,7 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
problem_impl->parameter_map(),
summary));
if (inner_iteration_minimizer == NULL) {
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
}
@@ -590,8 +580,8 @@ void SolverImpl::TrustRegionSolve(const Solver::Options& original_options,
// If the user aborted mid-optimization or the optimization
// terminated because of a numerical failure, then return without
// updating user state.
- if (summary->termination_type == USER_ABORT ||
- summary->termination_type == NUMERICAL_FAILURE) {
+ if (summary->termination_type == USER_FAILURE ||
+ summary->termination_type == FAILURE) {
return;
}
@@ -642,6 +632,8 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
*CHECK_NOTNULL(summary) = Solver::Summary();
summary->minimizer_type = LINE_SEARCH;
+ SummarizeGivenProgram(*original_program, summary);
+
summary->line_search_direction_type =
original_options.line_search_direction_type;
summary->max_lbfgs_rank = original_options.max_lbfgs_rank;
@@ -651,56 +643,50 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
summary->nonlinear_conjugate_gradient_type =
original_options.nonlinear_conjugate_gradient_type;
- summary->num_parameter_blocks = original_program->NumParameterBlocks();
- summary->num_parameters = original_program->NumParameters();
- summary->num_residual_blocks = original_program->NumResidualBlocks();
- summary->num_residuals = original_program->NumResiduals();
- summary->num_effective_parameters =
- original_program->NumEffectiveParameters();
-
// Validate values for configuration parameters supplied by user.
if ((original_options.line_search_direction_type == ceres::BFGS ||
original_options.line_search_direction_type == ceres::LBFGS) &&
original_options.line_search_type != ceres::WOLFE) {
- summary->error =
+ summary->message =
string("Invalid configuration: require line_search_type == "
"ceres::WOLFE when using (L)BFGS to ensure that underlying "
"assumptions are guaranteed to be satisfied.");
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
if (original_options.max_lbfgs_rank <= 0) {
- summary->error =
+ summary->message =
string("Invalid configuration: require max_lbfgs_rank > 0");
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
if (original_options.min_line_search_step_size <= 0.0) {
- summary->error = "Invalid configuration: min_line_search_step_size <= 0.0.";
- LOG(ERROR) << summary->error;
+ summary->message =
+ "Invalid configuration: min_line_search_step_size <= 0.0.";
+ LOG(ERROR) << summary->message;
return;
}
if (original_options.line_search_sufficient_function_decrease <= 0.0) {
- summary->error =
+ summary->message =
string("Invalid configuration: require ") +
string("line_search_sufficient_function_decrease <= 0.0.");
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
if (original_options.max_line_search_step_contraction <= 0.0 ||
original_options.max_line_search_step_contraction >= 1.0) {
- summary->error = string("Invalid configuration: require ") +
+ summary->message = string("Invalid configuration: require ") +
string("0.0 < max_line_search_step_contraction < 1.0.");
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
if (original_options.min_line_search_step_contraction <=
original_options.max_line_search_step_contraction ||
original_options.min_line_search_step_contraction > 1.0) {
- summary->error = string("Invalid configuration: require ") +
+ summary->message = string("Invalid configuration: require ") +
string("max_line_search_step_contraction < ") +
string("min_line_search_step_contraction <= 1.0.");
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
// Warn user if they have requested BISECTION interpolation, but constraints
@@ -718,37 +704,24 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
<< original_options.min_line_search_step_contraction
<< ", prevent bisection (0.5) scaling, continuing with solve regardless.";
if (original_options.max_num_line_search_step_size_iterations <= 0) {
- summary->error = string("Invalid configuration: require ") +
+ summary->message = string("Invalid configuration: require ") +
string("max_num_line_search_step_size_iterations > 0.");
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
if (original_options.line_search_sufficient_curvature_decrease <=
original_options.line_search_sufficient_function_decrease ||
original_options.line_search_sufficient_curvature_decrease > 1.0) {
- summary->error = string("Invalid configuration: require ") +
+ summary->message = string("Invalid configuration: require ") +
string("line_search_sufficient_function_decrease < ") +
string("line_search_sufficient_curvature_decrease < 1.0.");
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
if (original_options.max_line_search_step_expansion <= 1.0) {
- summary->error = string("Invalid configuration: require ") +
+ summary->message = string("Invalid configuration: require ") +
string("max_line_search_step_expansion > 1.0.");
- LOG(ERROR) << summary->error;
- return;
- }
-
- // Empty programs are usually a user error.
- if (summary->num_parameter_blocks == 0) {
- summary->error = "Problem contains no parameter blocks.";
- LOG(ERROR) << summary->error;
- return;
- }
-
- if (summary->num_residual_blocks == 0) {
- summary->error = "Problem contains no residual blocks.";
- LOG(ERROR) << summary->error;
+ LOG(ERROR) << summary->message;
return;
}
@@ -759,7 +732,6 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
// refactored to deal with the various bits of cleanups related to
// line search.
options.linear_solver_type = CGNR;
-
options.linear_solver_ordering = NULL;
options.inner_iteration_ordering = NULL;
@@ -777,8 +749,8 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
summary->num_threads_used = options.num_threads;
if (original_options.linear_solver_ordering != NULL) {
- if (!IsOrderingValid(original_options, problem_impl, &summary->error)) {
- LOG(ERROR) << summary->error;
+ if (!IsOrderingValid(original_options, problem_impl, &summary->message)) {
+ LOG(ERROR) << summary->message;
return;
}
options.linear_solver_ordering =
@@ -819,32 +791,23 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
scoped_ptr<Program> reduced_program(CreateReducedProgram(&options,
problem_impl,
&summary->fixed_cost,
- &summary->error));
+ &summary->message));
if (reduced_program == NULL) {
return;
}
- summary->num_parameter_blocks_reduced = reduced_program->NumParameterBlocks();
- summary->num_parameters_reduced = reduced_program->NumParameters();
- summary->num_residual_blocks_reduced = reduced_program->NumResidualBlocks();
- summary->num_effective_parameters_reduced =
- reduced_program->NumEffectiveParameters();
- summary->num_residuals_reduced = reduced_program->NumResiduals();
-
+ SummarizeReducedProgram(*reduced_program, summary);
if (summary->num_parameter_blocks_reduced == 0) {
summary->preprocessor_time_in_seconds =
WallTimeInSeconds() - solver_start_time;
- LOG(INFO) << "Terminating: FUNCTION_TOLERANCE reached. "
- << "No non-constant parameter blocks found.";
-
- // FUNCTION_TOLERANCE is the right convergence here, as we know
- // that the objective function is constant and cannot be changed
- // any further.
- summary->termination_type = FUNCTION_TOLERANCE;
+ summary->message =
+ "Terminating: Function tolerance reached. "
+ "No non-constant parameter blocks found.";
+ summary->termination_type = CONVERGENCE;
+ VLOG(1) << summary->message;
const double post_process_start_time = WallTimeInSeconds();
-
SetSummaryFinalCost(summary);
// Ensure the program state is set to the user parameters on the way out.
@@ -859,7 +822,7 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
scoped_ptr<Evaluator> evaluator(CreateEvaluator(options,
problem_impl->parameter_map(),
reduced_program.get(),
- &summary->error));
+ &summary->message));
if (evaluator == NULL) {
return;
}
@@ -886,8 +849,8 @@ void SolverImpl::LineSearchSolve(const Solver::Options& original_options,
// If the user aborted mid-optimization or the optimization
// terminated because of a numerical failure, then return without
// updating user state.
- if (summary->termination_type == USER_ABORT ||
- summary->termination_type == NUMERICAL_FAILURE) {
+ if (summary->termination_type == USER_FAILURE ||
+ summary->termination_type == FAILURE) {
return;
}
@@ -1456,7 +1419,7 @@ CoordinateDescentMinimizer* SolverImpl::CreateInnerIterationMinimizer(
for ( ; it != group_to_elements.end(); ++it) {
if (!IsParameterBlockSetIndependent(it->second,
program.residual_blocks())) {
- summary->error =
+ summary->message =
StringPrintf("The user-provided "
"parameter_blocks_for_inner_iterations does not "
"form an independent set. Group Id: %d", it->first);
@@ -1469,7 +1432,7 @@ CoordinateDescentMinimizer* SolverImpl::CreateInnerIterationMinimizer(
if (!inner_iteration_minimizer->Init(program,
parameter_map,
*ordering_ptr,
- &summary->error)) {
+ &summary->message)) {
return NULL;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
index aef63b044dd..5191bc4d0c9 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/solver_impl.h
@@ -93,7 +93,7 @@ class SolverImpl {
static Program* CreateReducedProgram(Solver::Options* options,
ProblemImpl* problem_impl,
double* fixed_cost,
- string* error);
+ string* message);
// Create the appropriate linear solver, taking into account any
// config changes decided by CreateTransformedProgram(). The
@@ -101,7 +101,7 @@ class SolverImpl {
// selected; consider the case that the remaining elimininated
// blocks is zero after removing fixed blocks.
static LinearSolver* CreateLinearSolver(Solver::Options* options,
- string* error);
+ string* message);
// Reorder the residuals for program, if necessary, so that the
// residuals involving e block (i.e., the first num_eliminate_block
@@ -110,14 +110,14 @@ class SolverImpl {
static bool LexicographicallyOrderResidualBlocks(
const int num_eliminate_blocks,
Program* program,
- string* error);
+ string* message);
// Create the appropriate evaluator for the transformed program.
static Evaluator* CreateEvaluator(
const Solver::Options& options,
const ProblemImpl::ParameterMap& parameter_map,
Program* program,
- string* error);
+ string* message);
// Remove the fixed or unused parameter blocks and residuals
// depending only on fixed parameters from the program.
@@ -131,17 +131,17 @@ class SolverImpl {
// fixed_cost.
//
// If a failure is encountered, the function returns false with a
- // description of the failure in error.
+ // description of the failure in message.
static bool RemoveFixedBlocksFromProgram(
Program* program,
ParameterBlockOrdering* linear_solver_ordering,
ParameterBlockOrdering* inner_iteration_ordering,
double* fixed_cost,
- string* error);
+ string* message);
static bool IsOrderingValid(const Solver::Options& options,
const ProblemImpl* problem_impl,
- string* error);
+ string* message);
static bool IsParameterBlockSetIndependent(
const set<double*>& parameter_block_ptrs,
@@ -176,7 +176,7 @@ class SolverImpl {
const ProblemImpl::ParameterMap& parameter_map,
const ParameterBlockOrdering* parameter_block_ordering,
Program* program,
- string* error);
+ string* message);
// Sparse cholesky factorization routines when doing the sparse
// cholesky factorization of the Jacobian matrix, reorders its
@@ -192,7 +192,7 @@ class SolverImpl {
const SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type,
const ParameterBlockOrdering* parameter_block_ordering,
Program* program,
- string* error);
+ string* message);
// Schur type solvers require that all parameter blocks eliminated
// by the Schur eliminator occur before others and the residuals be
@@ -216,7 +216,7 @@ class SolverImpl {
const ProblemImpl::ParameterMap& parameter_map,
ParameterBlockOrdering* parameter_block_ordering,
Program* program,
- string* error);
+ string* message);
// array contains a list of (possibly repeating) non-negative
// integers. Let us assume that we have constructed another array
diff --git a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
index 1ead8f70ae2..b2dba440e10 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/sparse_normal_cholesky_solver.cc
@@ -112,8 +112,15 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingCXSparse(
if (per_solve_options.D != NULL) {
// Temporarily append a diagonal block to the A matrix, but undo
// it before returning the matrix to the user.
- CompressedRowSparseMatrix D(per_solve_options.D, num_cols);
- A->AppendRows(D);
+ scoped_ptr<CompressedRowSparseMatrix> regularizer;
+ if (A->col_blocks().size() > 0) {
+ regularizer.reset(CompressedRowSparseMatrix::CreateBlockDiagonalMatrix(
+ per_solve_options.D, A->col_blocks()));
+ } else {
+ regularizer.reset(new CompressedRowSparseMatrix(
+ per_solve_options.D, num_cols));
+ }
+ A->AppendRows(*regularizer);
}
VectorRef(x, num_cols).setZero();
@@ -196,8 +203,15 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImplUsingSuiteSparse(
if (per_solve_options.D != NULL) {
// Temporarily append a diagonal block to the A matrix, but undo
// it before returning the matrix to the user.
- CompressedRowSparseMatrix D(per_solve_options.D, num_cols);
- A->AppendRows(D);
+ scoped_ptr<CompressedRowSparseMatrix> regularizer;
+ if (A->col_blocks().size() > 0) {
+ regularizer.reset(CompressedRowSparseMatrix::CreateBlockDiagonalMatrix(
+ per_solve_options.D, A->col_blocks()));
+ } else {
+ regularizer.reset(new CompressedRowSparseMatrix(
+ per_solve_options.D, num_cols));
+ }
+ A->AppendRows(*regularizer);
}
VectorRef(x, num_cols).setZero();
diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
index 06cc0a8e6fa..8079bc16ebb 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.cc
@@ -122,7 +122,7 @@ cholmod_dense* SuiteSparse::CreateDenseVector(const double* x,
}
cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A,
- string* status) {
+ string* message) {
// Cholmod can try multiple re-ordering strategies to find a fill
// reducing ordering. Here we just tell it use AMD with automatic
// matrix dependence choice of supernodal versus simplicial
@@ -137,8 +137,8 @@ cholmod_factor* SuiteSparse::AnalyzeCholesky(cholmod_sparse* A,
}
if (cc_.status != CHOLMOD_OK) {
- *status = StringPrintf("cholmod_analyze failed. error code: %d",
- cc_.status);
+ *message = StringPrintf("cholmod_analyze failed. error code: %d",
+ cc_.status);
return NULL;
}
@@ -149,18 +149,18 @@ cholmod_factor* SuiteSparse::BlockAnalyzeCholesky(
cholmod_sparse* A,
const vector<int>& row_blocks,
const vector<int>& col_blocks,
- string* status) {
+ string* message) {
vector<int> ordering;
if (!BlockAMDOrdering(A, row_blocks, col_blocks, &ordering)) {
return NULL;
}
- return AnalyzeCholeskyWithUserOrdering(A, ordering, status);
+ return AnalyzeCholeskyWithUserOrdering(A, ordering, message);
}
cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(
cholmod_sparse* A,
const vector<int>& ordering,
- string* status) {
+ string* message) {
CHECK_EQ(ordering.size(), A->nrow);
cc_.nmethods = 1;
@@ -172,8 +172,8 @@ cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(
cholmod_print_common(const_cast<char*>("Symbolic Analysis"), &cc_);
}
if (cc_.status != CHOLMOD_OK) {
- *status = StringPrintf("cholmod_analyze failed. error code: %d",
- cc_.status);
+ *message = StringPrintf("cholmod_analyze failed. error code: %d",
+ cc_.status);
return NULL;
}
@@ -182,7 +182,7 @@ cholmod_factor* SuiteSparse::AnalyzeCholeskyWithUserOrdering(
cholmod_factor* SuiteSparse::AnalyzeCholeskyWithNaturalOrdering(
cholmod_sparse* A,
- string* status) {
+ string* message) {
cc_.nmethods = 1;
cc_.method[0].ordering = CHOLMOD_NATURAL;
cc_.postorder = 0;
@@ -192,8 +192,8 @@ cholmod_factor* SuiteSparse::AnalyzeCholeskyWithNaturalOrdering(
cholmod_print_common(const_cast<char*>("Symbolic Analysis"), &cc_);
}
if (cc_.status != CHOLMOD_OK) {
- *status = StringPrintf("cholmod_analyze failed. error code: %d",
- cc_.status);
+ *message = StringPrintf("cholmod_analyze failed. error code: %d",
+ cc_.status);
return NULL;
}
@@ -244,7 +244,7 @@ bool SuiteSparse::BlockAMDOrdering(const cholmod_sparse* A,
LinearSolverTerminationType SuiteSparse::Cholesky(cholmod_sparse* A,
cholmod_factor* L,
- string* status) {
+ string* message) {
CHECK_NOTNULL(A);
CHECK_NOTNULL(L);
@@ -268,22 +268,22 @@ LinearSolverTerminationType SuiteSparse::Cholesky(cholmod_sparse* A,
// (e.g. out of memory).
switch (cc_.status) {
case CHOLMOD_NOT_INSTALLED:
- *status = "CHOLMOD failure: Method not installed.";
+ *message = "CHOLMOD failure: Method not installed.";
return LINEAR_SOLVER_FATAL_ERROR;
case CHOLMOD_OUT_OF_MEMORY:
- *status = "CHOLMOD failure: Out of memory.";
+ *message = "CHOLMOD failure: Out of memory.";
return LINEAR_SOLVER_FATAL_ERROR;
case CHOLMOD_TOO_LARGE:
- *status = "CHOLMOD failure: Integer overflow occured.";
+ *message = "CHOLMOD failure: Integer overflow occured.";
return LINEAR_SOLVER_FATAL_ERROR;
case CHOLMOD_INVALID:
- *status = "CHOLMOD failure: Invalid input.";
+ *message = "CHOLMOD failure: Invalid input.";
return LINEAR_SOLVER_FATAL_ERROR;
case CHOLMOD_NOT_POSDEF:
- *status = "CHOLMOD warning: Matrix not positive definite.";
+ *message = "CHOLMOD warning: Matrix not positive definite.";
return LINEAR_SOLVER_FAILURE;
case CHOLMOD_DSMALL:
- *status = "CHOLMOD warning: D for LDL' or diag(L) or "
+ *message = "CHOLMOD warning: D for LDL' or diag(L) or "
"LL' has tiny absolute value.";
return LINEAR_SOLVER_FAILURE;
case CHOLMOD_OK:
@@ -291,12 +291,12 @@ LinearSolverTerminationType SuiteSparse::Cholesky(cholmod_sparse* A,
return LINEAR_SOLVER_SUCCESS;
}
- *status = "CHOLMOD failure: cholmod_factorize returned false "
- "but cholmod_common::status is CHOLMOD_OK."
- "Please report this to ceres-solver@googlegroups.com.";
+ *message = "CHOLMOD failure: cholmod_factorize returned false "
+ "but cholmod_common::status is CHOLMOD_OK."
+ "Please report this to ceres-solver@googlegroups.com.";
return LINEAR_SOLVER_FATAL_ERROR;
default:
- *status =
+ *message =
StringPrintf("Unknown cholmod return code: %d. "
"Please report this to ceres-solver@googlegroups.com.",
cc_.status);
@@ -308,9 +308,9 @@ LinearSolverTerminationType SuiteSparse::Cholesky(cholmod_sparse* A,
cholmod_dense* SuiteSparse::Solve(cholmod_factor* L,
cholmod_dense* b,
- string* status) {
+ string* message) {
if (cc_.status != CHOLMOD_OK) {
- *status = "cholmod_solve failed. CHOLMOD status is not CHOLMOD_OK";
+ *message = "cholmod_solve failed. CHOLMOD status is not CHOLMOD_OK";
return NULL;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
index 0604654f7c8..832f103b816 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
+++ b/extern/libmv/third_party/ceres/internal/ceres/suitesparse.h
@@ -139,15 +139,15 @@ class SuiteSparse {
// A is not modified, only the pattern of non-zeros of A is used,
// the actual numerical values in A are of no consequence.
//
- // status contains an explanation of the failures if any.
+ // message contains an explanation of the failures if any.
//
// Caller owns the result.
- cholmod_factor* AnalyzeCholesky(cholmod_sparse* A, string* status);
+ cholmod_factor* AnalyzeCholesky(cholmod_sparse* A, string* message);
cholmod_factor* BlockAnalyzeCholesky(cholmod_sparse* A,
const vector<int>& row_blocks,
const vector<int>& col_blocks,
- string* status);
+ string* message);
// If A is symmetric, then compute the symbolic Cholesky
// factorization of A(ordering, ordering). If A is unsymmetric, then
@@ -157,38 +157,38 @@ class SuiteSparse {
// A is not modified, only the pattern of non-zeros of A is used,
// the actual numerical values in A are of no consequence.
//
- // status contains an explanation of the failures if any.
+ // message contains an explanation of the failures if any.
//
// Caller owns the result.
cholmod_factor* AnalyzeCholeskyWithUserOrdering(cholmod_sparse* A,
const vector<int>& ordering,
- string* status);
+ string* message);
// Perform a symbolic factorization of A without re-ordering A. No
// postordering of the elimination tree is performed. This ensures
// that the symbolic factor does not introduce an extra permutation
// on the matrix. See the documentation for CHOLMOD for more details.
//
- // status contains an explanation of the failures if any.
+ // message contains an explanation of the failures if any.
cholmod_factor* AnalyzeCholeskyWithNaturalOrdering(cholmod_sparse* A,
- string* status);
+ string* message);
// Use the symbolic factorization in L, to find the numerical
// factorization for the matrix A or AA^T. Return true if
// successful, false otherwise. L contains the numeric factorization
// on return.
//
- // status contains an explanation of the failures if any.
+ // message contains an explanation of the failures if any.
LinearSolverTerminationType Cholesky(cholmod_sparse* A,
cholmod_factor* L,
- string* status);
+ string* message);
// Given a Cholesky factorization of a matrix A = LL^T, solve the
// linear system Ax = b, and return the result. If the Solve fails
// NULL is returned. Caller owns the result.
//
- // status contains an explanation of the failures if any.
- cholmod_dense* Solve(cholmod_factor* L, cholmod_dense* b, string* solve);
+ // message contains an explanation of the failures if any.
+ cholmod_dense* Solve(cholmod_factor* L, cholmod_dense* b, string* message);
// By virtue of the modeling layer in Ceres being block oriented,
// all the matrices used by Ceres are also block oriented. When
diff --git a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
index a613a655559..f9f14e0f76e 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/trust_region_minimizer.cc
@@ -128,9 +128,9 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
residuals.data(),
gradient.data(),
jacobian)) {
- summary->error = "Terminating: Residual and Jacobian evaluation failed.";
- summary->termination_type = NUMERICAL_FAILURE;
- LOG_IF(WARNING, is_not_silent) << summary->error;
+ summary->message = "Terminating: Residual and Jacobian evaluation failed.";
+ summary->termination_type = FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->message;
return;
}
@@ -154,13 +154,13 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
options_.gradient_tolerance * initial_gradient_max_norm;
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
- summary->error = StringPrintf("Terminating: Gradient tolerance reached. "
- "Relative gradient max norm: %e <= %e",
- (iteration_summary.gradient_max_norm /
- initial_gradient_max_norm),
- options_.gradient_tolerance);
- summary->termination_type = GRADIENT_TOLERANCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ summary->message = StringPrintf("Terminating: Gradient tolerance reached. "
+ "Relative gradient max norm: %e <= %e",
+ (iteration_summary.gradient_max_norm /
+ initial_gradient_max_norm),
+ options_.gradient_tolerance);
+ summary->termination_type = CONVERGENCE;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
@@ -188,18 +188,18 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_start_time = WallTimeInSeconds();
if (iteration_summary.iteration >= options_.max_num_iterations) {
- summary->error = "Terminating: Maximum number of iterations reached.";
+ summary->message = "Terminating: Maximum number of iterations reached.";
summary->termination_type = NO_CONVERGENCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
const double total_solver_time = iteration_start_time - start_time +
summary->preprocessor_time_in_seconds;
if (total_solver_time >= options_.max_solver_time_in_seconds) {
- summary->error = "Terminating: Maximum solver time reached.";
+ summary->message = "Terminating: Maximum solver time reached.";
summary->termination_type = NO_CONVERGENCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
@@ -228,11 +228,11 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
trust_region_step.data());
if (strategy_summary.termination_type == LINEAR_SOLVER_FATAL_ERROR) {
- summary->error =
+ summary->message =
"Terminating. Linear solver failed due to unrecoverable "
"non-numeric causes. Please see the error log for clues. ";
- summary->termination_type = NUMERICAL_FAILURE;
- LOG_IF(WARNING, is_not_silent) << summary->error;
+ summary->termination_type = FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->message;
return;
}
@@ -245,15 +245,6 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.step_is_valid = false;
iteration_summary.step_is_successful = false;
- if (strategy_summary.termination_type == LINEAR_SOLVER_FATAL_ERROR) {
- summary->error =
- "Terminating. Linear solver failed due to unrecoverable "
- "non-numeric causes. Please see the error log for clues. ";
- summary->termination_type = NUMERICAL_FAILURE;
- LOG_IF(WARNING, is_not_silent) << summary->error;
- return;
- }
-
double model_cost_change = 0.0;
if (strategy_summary.termination_type != LINEAR_SOLVER_FAILURE) {
// new_model_cost
@@ -281,15 +272,15 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
if (!iteration_summary.step_is_valid) {
// Invalid steps can happen due to a number of reasons, and we
// allow a limited number of successive failures, and return with
- // NUMERICAL_FAILURE if this limit is exceeded.
+ // FAILURE if this limit is exceeded.
if (++num_consecutive_invalid_steps >=
options_.max_num_consecutive_invalid_steps) {
- summary->error = StringPrintf(
+ summary->message = StringPrintf(
"Terminating. Number of successive invalid steps more "
"than Solver::Options::max_num_consecutive_invalid_steps: %d",
options_.max_num_consecutive_invalid_steps);
- summary->termination_type = NUMERICAL_FAILURE;
- LOG_IF(WARNING, is_not_silent) << summary->error;
+ summary->termination_type = FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->message;
return;
}
@@ -376,14 +367,14 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
const double step_size_tolerance = options_.parameter_tolerance *
(x_norm + options_.parameter_tolerance);
if (iteration_summary.step_norm <= step_size_tolerance) {
- summary->error =
+ summary->message =
StringPrintf("Terminating. Parameter tolerance reached. "
"relative step_norm: %e <= %e.",
(iteration_summary.step_norm /
(x_norm + options_.parameter_tolerance)),
options_.parameter_tolerance);
- summary->termination_type = PARAMETER_TOLERANCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ summary->termination_type = CONVERGENCE;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
@@ -391,13 +382,13 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
const double absolute_function_tolerance =
options_.function_tolerance * cost;
if (fabs(iteration_summary.cost_change) < absolute_function_tolerance) {
- summary->error =
+ summary->message =
StringPrintf("Terminating. Function tolerance reached. "
"|cost_change|/cost: %e <= %e",
fabs(iteration_summary.cost_change) / cost,
options_.function_tolerance);
- summary->termination_type = FUNCTION_TOLERANCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ summary->termination_type = CONVERGENCE;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
@@ -494,10 +485,10 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
residuals.data(),
gradient.data(),
jacobian)) {
- summary->error =
+ summary->message =
"Terminating: Residual and Jacobian evaluation failed.";
- summary->termination_type = NUMERICAL_FAILURE;
- LOG_IF(WARNING, is_not_silent) << summary->error;
+ summary->termination_type = FAILURE;
+ LOG_IF(WARNING, is_not_silent) << summary->message;
return;
}
@@ -505,14 +496,14 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.gradient_norm = gradient.norm();
if (iteration_summary.gradient_max_norm <= absolute_gradient_tolerance) {
- summary->error =
+ summary->message =
StringPrintf("Terminating: Gradient tolerance reached. "
"Relative gradient max norm: %e <= %e",
(iteration_summary.gradient_max_norm /
initial_gradient_max_norm),
options_.gradient_tolerance);
- summary->termination_type = GRADIENT_TOLERANCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ summary->termination_type = CONVERGENCE;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
@@ -575,9 +566,9 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options,
iteration_summary.trust_region_radius = strategy->Radius();
if (iteration_summary.trust_region_radius <
options_.min_trust_region_radius) {
- summary->error = "Termination. Minimum trust region radius reached.";
- summary->termination_type = PARAMETER_TOLERANCE;
- VLOG_IF(1, is_not_silent) << summary->error;
+ summary->message = "Termination. Minimum trust region radius reached.";
+ summary->termination_type = CONVERGENCE;
+ VLOG_IF(1, is_not_silent) << summary->message;
return;
}
diff --git a/extern/libmv/third_party/ceres/internal/ceres/types.cc b/extern/libmv/third_party/ceres/internal/ceres/types.cc
index 5f3455fdd41..5a344ea43d7 100644
--- a/extern/libmv/third_party/ceres/internal/ceres/types.cc
+++ b/extern/libmv/third_party/ceres/internal/ceres/types.cc
@@ -297,16 +297,13 @@ bool StringToVisibilityClusteringType(
return false;
}
-const char* SolverTerminationTypeToString(SolverTerminationType type) {
+const char* TerminationTypeToString(TerminationType type) {
switch (type) {
+ CASESTR(CONVERGENCE);
CASESTR(NO_CONVERGENCE);
- CASESTR(FUNCTION_TOLERANCE);
- CASESTR(GRADIENT_TOLERANCE);
- CASESTR(PARAMETER_TOLERANCE);
- CASESTR(NUMERICAL_FAILURE);
- CASESTR(USER_ABORT);
+ CASESTR(FAILURE);
CASESTR(USER_SUCCESS);
- CASESTR(DID_NOT_RUN);
+ CASESTR(USER_FAILURE);
default:
return "UNKNOWN";
}