From 5933b2455c409963580ea616047f2f2ee332ff71 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 29 Dec 2013 16:59:15 +0600 Subject: 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 --- extern/libmv/libmv-capi.cc | 4 +- extern/libmv/libmv/multiview/fundamental.cc | 4 +- extern/libmv/libmv/multiview/homography.cc | 4 +- extern/libmv/libmv/tracking/track_region.cc | 15 +- extern/libmv/libmv/tracking/track_region.h | 7 +- extern/libmv/third_party/ceres/ChangeLog | 289 ++++++++++----------- .../libmv/third_party/ceres/include/ceres/solver.h | 9 +- .../libmv/third_party/ceres/include/ceres/types.h | 59 ++--- .../internal/ceres/compressed_row_sparse_matrix.cc | 19 ++ .../ceres/internal/ceres/covariance_impl.cc | 16 +- .../third_party/ceres/internal/ceres/lapack.cc | 14 +- .../third_party/ceres/internal/ceres/lapack.h | 8 +- .../ceres/internal/ceres/line_search_minimizer.cc | 58 ++--- .../ceres/internal/ceres/linear_solver.h | 5 +- .../third_party/ceres/internal/ceres/minimizer.cc | 2 +- .../ceres/internal/ceres/problem_impl.cc | 5 + .../third_party/ceres/internal/ceres/program.cc | 30 +++ .../third_party/ceres/internal/ceres/program.h | 4 + .../third_party/ceres/internal/ceres/solver.cc | 95 +++---- .../ceres/internal/ceres/solver_impl.cc | 175 +++++-------- .../third_party/ceres/internal/ceres/solver_impl.h | 20 +- .../ceres/sparse_normal_cholesky_solver.cc | 22 +- .../ceres/internal/ceres/suitesparse.cc | 48 ++-- .../third_party/ceres/internal/ceres/suitesparse.h | 22 +- .../ceres/internal/ceres/trust_region_minimizer.cc | 81 +++--- .../third_party/ceres/internal/ceres/types.cc | 11 +- 26 files changed, 507 insertions(+), 519 deletions(-) (limited to 'extern') 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 +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 +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 +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 +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 + header file, but this file declares the class int std::tr1 + namespace. + + This confused existing assumption that if there's an + existing 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 +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 +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 +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 +Date: Mon Dec 2 12:02:03 2013 -0800 + + Lint cleanup from William Rucklidge. + + Change-Id: I8abcfd369f41b895ce746a21a35f250fe05c39d1 + +commit 3faac6a28cec4c99c41421d3f585f3786be443b3 +Author: Sameer Agarwal +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 +Date: Thu Nov 28 06:50:43 2013 -0800 + + Lint cleanup from William Rucklidge. + + Change-Id: I745810f5496a1b93263b20ff140f8883da61995e + +commit 34b6359f39884683f2bbf06c93040afd42ae135d +Author: Sergey Sharybin +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 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 -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 -Date: Tue Oct 29 07:40:51 2013 -0700 - - Minor bug fix to autodiff.h - - Change-Id: Ib41050a2f2ba1898c71ff19d74f8eca2496212c0 - -commit 9e9a7d6ca0e75727293f94452d602f02b56d10ba -Author: Sameer Agarwal -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 -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 -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 -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 -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 -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 -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 -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 -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 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 +#include #include #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(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(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, ¤t_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 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 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 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 - 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(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 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(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& 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 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 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& row_blocks, const vector& col_blocks, - string* status) { + string* message) { vector 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& 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("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("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& row_blocks, const vector& 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& 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"; } -- cgit v1.2.3