Sparse Cholesky factorization is not rank revealing. Therefore
this algorithm cannot reliably tell when the Jacobian matrix is
rank deficient or so poorly conditioned that the covariance matrix
cannot be estimated.
Making things worse, this algorithm works on the normal equations,
which makes the conditioning problem much worse.
This change, deletes the SPARSE_CHOLESKY algorithm in the covariance
estimation code. Also to make the naming consistent, it renames
SPARSE_QR -> SUITE_SPARSE_QR
so that it parallels EIGEN_SPARSE_QR.
Also, since we now have EIGEN_SPARSE_QR, we can default to using
it when SuiteSparse is not available instead of DENSE_SVD, which
generally speaking should only be used by folks who are dealing
with small rank deficient jacobians.
Change-Id: I8b134c7e8a2e86ca374371f185b19f1c3e74349c
For smaller problems Eigen is faster than SuiteSparseQR. This has been
tested with Eigen 3.2.1. Below are detailed timings. Problem 1 is the
smallest and problem 3 is the largest. The timings below are:
mean +- standard deviation.
Problem 1:
Eigen 0.0009218 +- 0.0002755
SuiteSparse 0.001406 +- 0.001610
Problem 2:
Eigen 0.002338 +- 0.001005
SuiteSparse 0.001910 +- 0.0004513
Problem 3:
Eigen 0.005455 +- 0.001759
SuiteSparse 0.002411 +- 0.0004974
Detailed problem descriptions:
Problem 1 size:
Original Reduced
Parameter blocks 533 54
Parameters 368 104
Effective parameters 1201 94
Residual blocks 233 77
Residual 1194 258
Problem 2 size:
Original Reduced
Parameter blocks 573 84
Parameters 1458 184
Effective parameters 1281 164
Residual blocks 263 107
Residual 1314 378
Problem 3 size:
Original Reduced
Parameter blocks 613 114
Parameters 1548 264
Effective parameters 1361 234
Residual blocks 293 137
Residual 1434 498
Change-Id: I884a67e2f728fe2992812148d82ccf5f27864fd7
This replaces the broken CERES_VERSION and CERES_ABI_VERSION
defines with a different set, including integer versions for
MAJOR/MINOR/etc.
This also adds the Ceres version to Solver::FullReport().
Example report from powell:
Ceres Solver v1.10.0 Solve Report
----------------------------------
Original Reduced
Parameter blocks 4 4
Parameters 4 4
Residual blocks 4 4
Residual 4 4
Minimizer TRUST_REGION
Dense linear algebra library EIGEN
Trust region strategy LEVENBERG_MARQUARDT
Given Used
Linear solver DENSE_QR DENSE_QR
Threads 1 1
Linear solver threads 1 1
Cost:
Initial 1.075000e+02
Final 1.791438e-14
Change 1.075000e+02
Minimizer iterations 14
Successful steps 14
Unsuccessful steps 0
Time (in seconds):
Preprocessor 0.001
Residual evaluation 0.000
Jacobian evaluation 0.000
Linear solver 0.000
Minimizer 0.001
Postprocessor 0.000
Total 0.003
Change-Id: I5bf0e8023693e9195276b1f1e881b13121ba1196
Termination: CONVERGENCE (Gradient tolerance reached. Gradient max norm: 3.642190e-11 <= 1.000000e-10)
1. Add the ability to bulk remove elements.
2. Add accessor for elements_to_group.
3. Early exit in Remove if there are no elements.
Change-Id: I3df1f00de05338a42e9907423b674469a022d3bc
- Previously we overwrote the default (empty) config.h in the source
tree with a configured config.h, generated using the current compile
options.
- This was undesirable as it could lead to inadvertant commits of the
generated config.h.
- This patch moves the default config.h to <src>/config/ceres/internal,
separate from the other headers, thus if Ceres is compiled without
CMake this directory will now also have to be included. This
directory is _not_ added to the CMake include directories for Ceres
(thus the default config.h is never used when compiling with CMake).
- When using CMake, the generated config.h is now placed in
<build>/config/ceres/internal, which is in turn added to the include
directories for Ceres when it is compiled, and the resulting config.h
is copied to ceres/internal when installed.
Change-Id: Ib1ba45e66e383ade2ebb08603af9165c1df616f2
- Previously we passed all compile options to Ceres via add_definitions
in CMake. This was fine for private definitions (used only by Ceres)
but required additional work for public definitions to ensure they
were correctly propagated to clients via CMake using
target_compile_definitions() (>= 2.8.11) or add_definitions().
- A drawback to these approaches is that they did not work for chained
dependencies on Ceres, as in if in the users project B <- A <- Ceres,
then although the required Ceres public compile definitions would
be used when compiling A, they would not be propagated to B.
- This patch replaces the addition of compile definitions via
add_definitions() with an autogenerated config.h header which
is installed with Ceres and defines all of the enabled Ceres compile
options.
- This removes the need for the user to propagate any compile
definitions in their projects, and additionally allows post-install
inspect of the options with which Ceres was compiled.
Change-Id: Idbdb6abdad0eb31e7540370e301afe87a07f2260
1. Update version history.
2. Minor changes to the tutorial to reflect the bounds constrained
problem.
3. Added static factory methods to the SnavelyReprojectionError.
4. Removed relative gradient tolerance from types.h as it is
not true anymore.
Change-Id: I8de386e5278a008c84ef2d3290d2c4351417a9f1
This compiler defines shared_ptr in std::tr1 namespace, but
for this <tr1/memory> is to be included. Further, this compiler
also does have <memory> header which confused previous shared
pointer check.
Simplified logic around defines now, so currently we've got:
- CERES_TR1_MEMORY_HEADER defined if <tr1/memory> is to be
used for shared_ptr, otherwise <memory> is to be used.
- CERES_TR1_SHARED_PTR defined if shared_ptr is defined in
std::tr1 namespace, otherwise it's defined in std namespace.
All the shared_ptr checks are now moved to own file FindSharedPtr
which simplifies main CMakeLists.
Change-Id: I558a74793baaa0bd088801910a356be4ef17c31b
The standard sparse normal Cholesky solver assumes a fixed
sparsity pattern which is useful for a large number of problems
presented to Ceres. However, some problems are symbolically dense
but numerically sparse i.e. each residual is a function of a
large number of parameters but at any given state the residual
only depends on a sparse subset of them. For these class of
problems it is faster to re-analyse the sparsity pattern of the
jacobian at each iteration of the non-linear optimisation instead
of including all of the zero entries in the step computation.
The proposed solution adds the dynamic_sparsity option which can
be used with SPARSE_NORMAL_CHOLESKY. A
DynamicCompressedRowSparseMatrix type (which extends
CompressedRowSparseMatrix) has been introduced which allows
dynamic addition and removal of elements. A Finalize method is
provided which then consolidates the matrix so that it can be
used in place of a regular CompressedRowSparseMatrix. An
associated jacobian writer has also been provided.
Changes that were required to make this extension were adding the
SetMaxNumNonZeros method to CompressedRowSparseMatrix and adding
a JacobianFinalizer template parameter to the ProgramEvaluator.
Change-Id: Ia5a8a9523fdae8d5b027bc35e70b4611ec2a8d01
Fix variable names in port.h and fix fpclassify when
using gnustl. This was tested by switching to gnustl
in the JNI build.
Thanks to Carlos Hernandez for suggesting the gnustl fixes.
Change-Id: I690b73caf495ccc79061f45288e416da1604cc72
By default shared_ptr is now assumed to be
in the standard <memory> header and in the
std namespace.
Previously the way the ifdefs were structured if the appropriate
variable was not defined, it would default to <t1/memory>.
The new defaults are more future proof.
Change-Id: If457806191196be2b6425b8289ea7a3488a27445
Solver::Options::linear_solver_ordering and
Solver::Options::inner_iteration_ordering
were bare pointers even though Solver::Options took ownership of these
objects.
This lead to buggy user code and the inability to copy Solver::Options
objects around.
With this change, these naked pointers have been replaced by a
shared_ptr object which will managed the lifetime of these objects. This
also leads to simplification of the lifetime handling of these objects
inside the solver.
The Android.mk and Application.mk files have also been updated
to use a newer NDK revision which ships with LLVM's libc++.
Change-Id: I25161fb3ddf737be0b3e5dfd8e7a0039b22548cd
- Breaking change: Problem::Options::enable_fast_parameter_block_removal
is now Problem::Options::enable_fast_removal, as it now controls
the behaviour for both parameter and residual blocks.
- Previously we did not check that the specified residual block to
remove in RemoveResidualBlock actually represented a valid residual
for the problem.
- This meant that Ceres would die unexpectedly if the user passed an
uninitialised residual_block, or more likely attempted to remove a
residual block that had already been removed automatically after
the user removed a parameter block upon on which it was dependent.
- RemoveResidualBlock now verifies the validity of the given
residual_block to remove. Either by checking against a hash set of
all residuals maintained in ProblemImpl iff enable_fast_removal
is enabled. Or by a full scan of the residual blocks if not.
Change-Id: I9ab178e2f68a74135f0a8e20905b16405c77a62b
- Previously AutoDiffLocalParameterization would internally instantiate
a functor instance whenever one was required. This prohibits the
user passing arguments to the constructor of the functor.
- Now AutoDiffLocalParameterization can take over ownership of an
allocated functor which the user created. This mimics the behaviour
of AutoDiffCostFunction.
Change-Id: I264e1face44ca5d5e71cc20c77cc7654d3f74cc0
These two methods allow the user to associate upper and lower bounds
with individual parameters inside parameter blocks.
Change-Id: I68dc37f20b64408da510ba06b89a4f08df54ddad
CostFunction now uses int32 instead of int16
to store the size of its parameter blocks.
This is an API breaking change.
Change-Id: I032ea583bc7ea4b3009be25d23a3be143749c73e
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
There was a bug in the way RemoveFixedBlocksFromProgram was working.
It only removed the constant parameter blocks from the
linear_solver_ordering, it was not even aware of the
inner_iteration_ordering.
This change fixes this bug. The code for RemoveFixedBlocksFromProgram
is also cleaned up and made more readable and the test have been updated.
Thanks to Mikael Persson for reporting this.
Change-Id: I454fa89f9b6f4f6320b02d5235e6f322cc15ff51
1. Move LinearSolverTerminationType to ceres::internal.
2. Add FATAL_ERROR as a new enum to LinearSolverTerminationType.
3. Pipe SuiteSparse errors via a LinearSolverTerminationType so
to distinguish between fatal and non-fatal errors.
4. Update levenberg marquardt and dogleg strategies to deal
with FATAL_ERROR.
5. Update trust_region_minimizer to terminate when FATAL_ERROR
is encountered.
6. Remove SuiteSparse::SolveCholesky as it screws up the error
handling.
7. Fix all clients calling SuiteSparse to handle the result of
SuiteSparse::Cholesky correctly.
8. Remove fatal failures in SuiteSparse when symbolic factorization
fails.
9. Fix all clients of SuiteSparse to deal with null symbolic factors.
This is a temporary fix to deal with some production problems. A more
extensive cleanup and testing regime will be put in place in a
subsequent CL.
Change-Id: I1f60d539799dd95db7ecc340911e261fa4824f92
Since we added special handling for the case for rho[2] < 0,
the bulk of CorrectJacobian is pointless in the common case.
So add a simple one dimensional loop which rescales the Jacobian.
This speeds up this method immensely.
The robustification of a Jacobian gets speeded up by > 50%.
Change-Id: I97c4e897ccbb5521c053e1fb931c5d0d32f542c7
This triggers -Wtype-limits warnings on comparisons
which are always true, since the test being done is
n >= 0, where n is of type size_t, which is always
true.
This causes problems when compiling Ceres on linux
with miniglog.
Change-Id: Ia1d1d1483e03469c71fde029b62ca6d84e9b27e0
The original visibility based preconditioning paper and
implementation only used the canonical views algorithm.
This algorithm for large dense graphs can be particularly
expensive. As its worst case complexity is cubic in size
of the graph.
Further, for many uses the SCHUR_JACOBI preconditioner
was both effective enough while being cheap. It however
suffers from a fatal flaw. If the camera parameter blocks
are split between two or more parameter blocks, e.g,
extrinsics and intrinsics. The preconditioner because
it is block diagonal will not capture the interactions
between them.
Using CLUSTER_JACOBI or CLUSTER_TRIDIAGONAL will fix
this problem but as mentioned above this can be quite
expensive depending on the problem.
This change extends the visibility based preconditioner
to allow for multiple clustering algorithms. And adds
a simple thresholded single linkage clustering algorithm
which allows you to construct versions of CLUSTER_JACOBI
and CLUSTER_TRIDIAGONAL preconditioners that are cheap
to construct and are more effective than SCHUR_JACOBI.
Currently the constants controlling the threshold above
which edges are considered in the single linkage algorithm
are not exposed. This would be done in a future change.
Change-Id: I7ddc36790943f24b19c7f08b10694ae9a822f5c9
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
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
1. Update the documentation to be Sphinx friendly.
2. Remove dead fields in Solver::Summary.
a. Solver::Summary::num_eliminate_blocks_given.
b. Solver::Summary::num_eliminate_blocks_used.
Change-Id: I43e0070c88abe3bf285d91e6c7524f3d887deb33
Move the GradientCheckingCostFunction to DynamicNumericDiffCostFunction.
Also fix a const correctness issue with DynamicNumericDiffCostFunction.
Change-Id: Id446810f43374e7b7db7fe4dd01a891e3c54abb9
- Earlier versions of Clang (up to at least v3.0) throw an ambiguous
operator= error in this assignment. Variations on this error have
cropped up occassionally in some other projects (e.g. PCL).
Change-Id: I73a632c43528eb69840ce697c55d9afc5f3d8e59