Commit Graph

54 Commits

Author SHA1 Message Date
Sameer Agarwal 8bfdb02fb1 Rewrite uses of VLOG_IF and LOG_IF.
VLOG_IF's evaluation order is ambiguous - does it mean
`if (cond) VLOG(lvl)` or `if (VLOG_IS_ON(lvl) && cond) LOG(INFO)`?
In particular, the way it works now is inconsistent with the way the
rest of the LOG macros evaluate their arguments.
Fixing this would be hard, and the macro's behavior would still surprise
some people. Replacing it with an if statement is simple, clear, and unambiguous.

Change-Id: I97a92d17a932c0a5344a1bf98d676308793ba877
2020-10-12 18:34:24 +00:00
Sameer Agarwal db2af1be87 Add Problem::EvaluateResidualBlockAssumingParametersUnchanged
Simplify the semantics for Problem::EvaluateResidualBlock to
not ignore the presence of EvaluationCallback and add another method
EvaluateResidualBlockAssumingParametersUnchanged to handle the case
where the user has an EvaluationCallback but knows that the parameter
blocks do not change between calls.

Updated the documentation for the methods and EvaluationCallback to
reflect these semantics.

Also added tests for Evaluation related methods calling i
EvaluationCallback when its present.

https://github.com/ceres-solver/ceres-solver/issues/483

Change-Id: If0a0c95c2f1f92e9183a90df240104a69a71c46d
2020-08-04 13:59:42 -07:00
Sameer Agarwal 27183d661e Allow LocalParameterizations to have zero local size.
Local parameterizations with zero tangent/local size will cause the
corresponding parameter block to be treated as constant.

https://github.com/ceres-solver/ceres-solver/issues/347

Change-Id: I554a2acc420f5dd9d0cc7f97b691877eb057b2c0
2020-04-02 06:49:42 -07:00
Sameer Agarwal f212c92954 Let Problem::SetParameterization be called more than once.
https://github.com/ceres-solver/ceres-solver/issues/501

Change-Id: Ia94e6e62553e97fa2052db2cbebc5c472e26a406
2019-12-17 19:00:06 +00:00
Sameer Agarwal bf709ecac2 Move EvaluationCallback from Solver::Options to Problem::Options.
Adding it to Solver::Options was a mistake, as it prevents it from
being used in covariance estimation. Also updated associated docs.

https://github.com/ceres-solver/ceres-solver/issues/380
https://github.com/ceres-solver/ceres-solver/issues/401
https://github.com/ceres-solver/ceres-solver/issues/484

Change-Id: I63809a47a58e84c04a58bf8e59ace92f45fc2873
2019-07-08 21:24:08 +02:00
Sameer Agarwal db1f5b57a0 Allow some methods in Problem to use const double*.
Some methods in Problem do not modify the parameter block
and those methods now allow the user to call them with const double*.

The methods are

RemoveParameterBlock
SetParameterBlockConstant
IsParameterBlockConstant
GetParameterization
GetParameterLowerBound
GetParameterUpperBound

https://github.com/ceres-solver/ceres-solver/issues/479

Change-Id: I59dcb77134f59576dd498bd732e29aae9abd28b1
2019-06-05 15:45:02 -07:00
Sameer Agarwal 1b852c57e0 Add Problem::EvaluateResidualBlock.
This method gives the user the ability to evaluate a given residual
block.

A couple of minor cleanups.

Problem::problem_impl_ -> Problem::impl_
NULL -> nullptr

https://github.com/ceres-solver/ceres-solver/issues/417

Change-Id: I6dd94762c475fa264c387b8c93d516f6e06fe832
2019-04-29 09:46:33 -07:00
Johannes Beck e51e9b46f6 Implement AddResidualBlock using variadic templates
This CL changes the implementation of AddResidualBlock() in
ceres::Problem using variadic templates. Also one new overload for
AddResidualBlock() is added using a double** and the number of
parameter blocks.

Change-Id: I007a82a06897335a117213a0d12fedb4a77076a0
2018-11-07 21:02:11 +01:00
Sameer Agarwal 0040434507 Add ParameterBlock::IsSetConstantByUser()
Introduce IsSetConstantByUser method which indicates whether
the user set the parameter block constant or not.

Changed the definition of IsConstant() to indicate if the
parameter block is effectively constant or not, which is
now the uniion of two conditions - the user set it to be constant
or the local tangent space is of size zero. Currently
this change has no effect as we do not allow local parameterizations
with zero tangent space size, but thats an inconsistency we are
working on fixing.

A variety of code cleans up to parameter_block.h

1. Remove an old TODO comment which is not really actionable.
2. Remove Init() method.
3. NULL -> nullptr
4. memcpy -> std::copy

Change-Id: I12973ee0f053fa22f09908cf36e9aa57d9d8dd74
2018-10-10 10:56:13 -07:00
Sameer Agarwal 94712db5c7 Convert calls to CHECK_NOTNULL to CHECK.
CHECK_NOTNULL is being deprecated and removed from the
glog library.

Change-Id: I4a6d1eec6e82a768c7861c8f776bf1f9c0b50c74
2018-08-28 08:14:19 -07:00
Sameer Agarwal e82e128344 Deprecate integral_types.h
This header defined integral types in the pre-C++11 days, and can
be replaced with <cstdint> and the types defined therein.

Also remove a shallow (and incorrect) typedef in include/ceres/types.h

https://github.com/ceres-solver/ceres-solver/issues/409

Change-Id: I398c652f74d24bbeea459672508bf28f591b100f
2018-08-09 12:17:05 -07:00
Sameer Agarwal 32cb9e4a12 Respect bounds when using Solver::Options::check_gradients
When Solver::Options::check_gradients is true, Ceres internally
creates a new ProblemImpl object which wraps each CostFunction
in the user's problem with a GradientCheckingCostFunction.

Doing this also requires creating new ParameterBlock objects,
and when support for upper and lower bounds was added to Ceres,
CreateGradientCheckingProblemImpl should also have been updated
to create a problem with the same parameter bounds. As a result,
if check_gradients is enabled for a bounded problem, it constructs
an unconstrained problem and solves it.

This CL fixes this, by introducing Problem::GetParameterLowerBound,
and Problem::GetParameterUpperBound and using them to create a bounded
problem when checking gradients.

Thanks to @pbeeson for not only reporting this problem, but also
providing a small standalone reproduction which made debugging this
possible.

https://github.com/ceres-solver/ceres-solver/issues/379

Change-Id: Id18eb858a7009bf4fa452a21b925922d13f3249f
2018-07-09 23:48:45 -07:00
Alex Stewart 16f9b34c3b Remove Intel TBB threading support.
- In light of the C++11 threads threading option this is no longer
  necessary for cross-platform threading support and did not offer a
  noticeable performance gain over either the C++11 threads
  implementation or OpenMP.

Change-Id: Icb588d520888c19a1775171795b55bcaffb3d256
2018-07-03 18:05:36 +00:00
Keir Mierle 7c4e8a454e Replace scoped_ptr with C++11's unique_ptr
Change-Id: Ib5a504c491e3a79af52a95accf009df473470c6b
2018-04-02 14:47:47 -07:00
Sameer Agarwal a1458f3348 More C++11ification.
1. Replace HashMap and HashSet with std::unordered_map and
   std::unordered_set respectively.
2. Extract the pair hasher into a struct pair_hash.
3. Delete collections_port.h
4. Convert explicit iterator based loops to auto based
   loops where sensible.

Change-Id: Ib88bcd13a7463d18435639d3b771abaa52080efb
2018-03-30 12:03:28 -07:00
Mike Vitus f408f89e8b Adds a Ceres Context structure.
A Ceres Context holds common global state that can be re-used within
Ceres.  The Context current contains a thread pool if compiling with
C++11 threading support.  Threads are expensive to create and destroy so
it is good to maintain across multiple Ceres solves.

Tested by compiling with and without TBB support and ran unit tests. Ran
bazel as well.

Change-Id: I82f598dfae642aa0e81a6039dc174608a5e8dbfb
2018-02-26 10:37:53 -08:00
Keir Mierle 4bea6d7a2d Add a comment about default constructed reference counts=
Change-Id: Ia6b8a75144755d9bcf05c893bb97a1e207da6b0f
2017-09-25 13:09:41 -07:00
Sameer Agarwal 600262e8f8 Delete cost and loss functions when not in use.
Delete CostFunctions and LossFunctions when there are no more
ResidualBlocks referring to them. This is done by maintaining
a map with reference counts for CostFunctions and
LossFunctions.

The same maps are also used at the time of the destruction
of the ProblemImpl object itself. Previously vectors of these
objects were constructed, uniqed and the objects destroyed.

The update to the maps increases the cost of calling AddResidualBlock,
this has been mitigated, actually making AddResidualBlock faster, by
reusing a temporary vector rather than allocating one on the stack
every time.

Change-Id: I28b5287511713d28069ae428e2ff69224c0d03b4
2017-09-25 17:44:15 +00:00
Yury Prokazov 4ffec20a44 Add TBB threading support.
There are platforms where OpenMP is not available. This
patch adds support for Intel Threading Building Blocks (TBB)
as an alternative threading backend.

Change-Id: I94497d7cba0c3cfaccfc992169236f17fe948ae9
2017-09-25 12:43:14 +02:00
Sameer Agarwal 08e60379ba Integrate InnerProductComputer
Despite its relative size, this is very significant change
to Ceres.

Why
===

Up till now, when the user chose SPARSE_NORMAL_CHOLESKY,
the Jacobian was evaluated in a CompressedRowSparseMatrix,
which was then use to compute the normal equations which were
passed to a sparse linear algebra library for factorization.

The reason to do this was because in the case of SuiteSparse,
we were able to pass the Jacobian matrix directly without
computing the normal equations and SuiteSparse/CHOLMOD did the
normal equation computation.

This turned out to be slow, so Cheng Wang implemented a high
performance version of the matrix-matrix multiply to compute
the normal equations, and all the sparse linear algebra libraries
now are passed the normal equations.

So that raises the question, as to what the best representation
of the Jacobian which is suitable for the normal equation computation.

Turns out BlockSparseMatrix is ideal. It brings two advantages.

1. Jacobian evaluation into a BlockSparseMatrix is considerably
   faster when using a BlockSparseMatrix than
   CompressedRowSparseMatrix. This is because we save on a bunch
   of memory copies.

2. To make the matrix multiplication fast and use the block structure
   Cheng Wang had to essentially make the CompressedRowSparseMatrix
   carry a bunch of sidecar information about the block sparsity,
   essentially making it behave like a BlockSparseMatrix. The resulting
   code had fairly complicated indexing and complicated the semantics
   of CompressedRowSparseMatrix. The new InnerProductComputer class
   does away with all that and once this CL goes in, I will be able to
   remove all that code and simplify the semantics of
   CompressedRowSparseMatrix.

Changes
=======

1. Use InnerProductComputer in SparseNormalCholeskySolver.
2. Change the evaluator instantiated for SPARSE_NORMAL_CHOLESKY with
   static sparsity inside evaluator.cc
3. The former change necessitates that we change ProblemImpl::Evaluate
   to create the evaluate it needs on its own, because it was
   depending on passing "SPARSE_NORMAL_CHOLESKY" as linear solver type
   to the evaluator factor to get an Evaluator which can use
   CompressedRowSparseMatrix objects for storing the Jacobian.
4. Update the tests for SparseNormalCholeskySolver.
5. Separate out the tests for DynamicSparseNormalCholeskySolver into its
   own file.

Change-Id: I2ef7ef8fbfbb4967d0c1ec2068c1c778248fdf5b
2017-06-21 23:41:36 -07:00
Thomas Schneider d61e94da52 Add IsParameterBlockConstant to the ceres::Problem class.
Change-Id: I7d0e828e81324443209c17fa54dd1d37605e5bfe
2016-04-06 23:52:18 +02:00
Sameer Agarwal 8ecfb2d705 Fix the build.
Change-Id: I95a62a180a1a21fc379fe27b1309d72f19d9ef29
2015-12-17 13:55:02 -08:00
Sameer Agarwal a1019f6610 Use std::adjacent_find instead of std::unique
When detecting duplicates, it is more efficient to use std::adjacent_find
than it is to use std::unique.

Change-Id: Ib6b4671c10848bb7dd10aa7a1baeffc8c9c825b5
2015-12-17 20:21:42 +00:00
Keir Mierle 7492b0d8de Update copyright headers with new year and URL
Since Ceres is moving to using GitHub for issues, and the Google
Code URL in the current copyright header will soon become invalid,
update all the headers.

Change-Id: I1fce70375d1bcf098591f07b4d8f01a5c1e0789c
2015-03-18 05:43:23 +00:00
Alex Stewart ffa324765e Force use of single-thread in Problem::Evaluate() without OpenMP.
- Ensure that, as in the preprocessor, we force num_threads to be 1
  if Ceres was compiled without OpenMP to prevent a CHECK() failure
  in internal code.

Change-Id: I49d7bdeff81e5bb24aaaa3945018d9d012cd9df9
2015-03-15 22:30:50 +00:00
Sameer Agarwal db1a76d866 Better crash error messages.
When a user requests an operation on a parameter block which has
not been added to the problem, we now display a more helpful
error message with more context.

Change-Id: Ia7e54815111eb6375b31ed0d1cddca5917138ae1
2015-01-16 11:54:28 -08:00
Sameer Agarwal 05a07ecc77 Remove using std::string from port.h
Change-Id: I7376f5e7eace22ec1fc05a61eaa858594f08682d
2015-01-07 15:10:46 -08:00
Sameer Agarwal bcc865f81c Remove using namespace std;
For historical reasons we had a "using namespace std;" in port.h. This
is generally a bad idea. So removing it and along the way doing a bunch
of cpplint cleanup.

Change-Id: Ia125601a55ae62695e247fb0250df4c6f86c46c6
2015-01-07 14:26:53 -08:00
Sameer Agarwal 6c45d6b891 Add more inspection methods to Problem.
Problem::GetCostFunctionForResidualBlock
Problem::GetLossFunctionForResidualBlock

are added, so that users do not have to maintain this mapping
outside the Problem.

Change-Id: I38356dfa094b2c7eec90651dafeaf3a33c5f5f56
2014-09-11 12:17:54 -07:00
Sameer Agarwal 5ecb1c3f1d Add Problem::IsParameterBlockPresent.
This allows the user to query the Problem to see if a
parameter block is already present or not.

Change-Id: If786f6c008cc644f3398597901d718d12a6d865d
2014-04-01 10:04:12 -07:00
Alex Stewart 195e49351b Check validity of residual block before removal in RemoveResidualBlock.
- 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
2014-03-26 17:49:36 +00:00
Sameer Agarwal a482ab8ad5 Add Problem::SetParameterLowerBound and Problem::SetParameterUpperBound.
These two methods allow the user to associate upper and lower bounds
with individual parameters inside parameter blocks.

Change-Id: I68dc37f20b64408da510ba06b89a4f08df54ddad
2014-02-19 00:06:41 -08:00
Sameer Agarwal f949bab440 Add Problem::GetParameterization.
This allows the user to query the local parameterization associated
with a parameter block.

Change-Id: I3ab274aa88221c8e2def7c463825bf3927b1fdc9
2014-02-18 10:11:02 -08:00
Sameer Agarwal 85561eee95 Use int32 for parameter block sizes.
CostFunction now uses int32 instead of int16
to store the size of its parameter blocks.

This is an API breaking change.

Change-Id: I032ea583bc7ea4b3009be25d23a3be143749c73e
2014-01-07 22:22:14 -08:00
Sameer Agarwal 324eccb5f6 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
2013-12-03 10:58:24 -08:00
Sameer Agarwal 89a592f410 LinearSolver::Summary::status -> LinearSolver::Summary::message.
And a bunch of minor lint cleanups as they showed up.

Change-Id: I430a6b05710923c72daf6a5df4dfcd16fbf44b3a
2013-11-26 11:35:49 -08:00
Keir Mierle fda69b5213 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
2013-10-29 02:30:57 +00:00
Sameer Agarwal 8af1322662 Fix Problem::RemoveParameterBlock after calling solve.
The indexing parameter in the parameter block is expected
to be the same as its position in the program. However,
when Solve is called, the parameter blocks are made
members of a new program and the same indexing parameter
is used to store the position of the parameter block
in this new reordered program.

So when the user calls RemoveParameterBlock after calling
Solve, and ProblemImpl checks the invariant on the
indexing parameter it does not match and causes a crash.

The fix is to make sure that before returning from Solve,
the state of the indexing parameter's values are restored
to their original values corresponding to their positions
in the Program object contained in the ProblemImpl object.

Thanks to Simon Lynen for reporting this.

Change-Id: I060745026cd23a688c1fb5e2c9e6053e9ba1c78f
2013-09-24 23:24:42 -07:00
Sameer Agarwal a427c877f9 Lint cleanup.
Change-Id: Ie489f1ff182d99251ed8c0728cc6ea8e1c262ce0
2013-06-24 18:04:28 -07:00
Sameer Agarwal 02706c1906 Sparse covariance estimation.
Add a Covariance object to the API.

Given a Problem object and a set of parameter block pairs the
Covariance object computes a sparse covariance matrix corresponding
to those block pairs and provides random access to them.

Constant parameter blocks and parameter blocks with local parameterizations
are correctly handled.

Sparse and dense implementations are provided. With the dense implementation
rank deficient Jacobians can also be handled.

Parts of the code are threaded using OpenMP if available.

Change-Id: I5b49583b3d79579df3e0f334c22567acb23ed4ad
2013-05-18 23:33:02 -07:00
Sameer Agarwal 3d9546963d Add the ability to query the Problem about parameter blocks.
Change-Id: Ieda1aefa28e7a1d18fe6c8d1665882e4d9c274f2
2013-04-18 22:43:56 +00:00
Sameer Agarwal c290df85a4 Typo fix.
(Thanks to Pieree Moulon for reporting this)

Change-Id: I536724ab4b7e9c97768d5197aa86b41f37a04d38
2013-04-07 19:41:40 +00:00
Sergey Sharybin f46de9e697 Silent no previous declaration warning for FindParameterBlockOrDie
Use anonymous namespace for this. Also move some surrounding static
function to this anonymous namespace.

Change-Id: Ie235eb7936976563a9db115ec13c59e6e6869b96
2013-03-21 23:03:58 +06:00
Sergey Sharybin 16636efeff Compilation fix for msvc2010
Usage of back_inserter requires <iterator> header when using msvc2010

Change-Id: I92ee1649795ce0468ce337fc414eb0ca6e90c51e
2013-03-21 15:12:01 +06:00
Sameer Agarwal 020d8e1e48 Better error reporting in the modeling API.
More informative error when user passes an
unknown parameter block to Problem methods.

Change-Id: I517360e4b0b55814904ca3e664877d76ad3f59e8
2013-03-06 16:19:26 -08:00
Sameer Agarwal 039ff07dd1 Evaluate ResidualBlocks without LossFunction if needed.
1. Add the ability to evaluate the problem without loss function.
2. Remove static Evaluator::Evaluate
3. Refactor the common code from problem_test.cc and
   evaluator_test.cc into evaluator_test_utils.cc

Change-Id: I1aa841580afe91d288fbb65288b0ffdd1e43e827
2013-02-27 05:38:28 +00:00
Sameer Agarwal 931c309b27 Cleanup based on comments by William Rucklidge
Change-Id: If269ba8e388965a8ea32260fd6f17a133a19ab9b
2013-02-25 10:13:29 -08:00
Sameer Agarwal 509f68cfe3 Problem::Evaluate implementation.
1. Add Problem::Evaluate and tests.
2. Remove Solver::Summary::initial/final_*
3. Remove Solver::Options::return_* members.
4. Various cpplint cleanups.

Change-Id: I4266de53489896f72d9c6798c5efde6748d68a47
2013-02-24 19:04:21 +00:00
Sameer Agarwal beb4505311 Minor fixes
Based on William Rucklidge's review, including
a nasty bug in parameter block removal.

Change-Id: I3a692e589f600ff560ecae9fa85bb0b76063d403
2013-02-22 13:37:05 -08:00
Keir Mierle 04938efe4b Add support for removing parameter and residual blocks.
This adds support for removing parameter and residual blocks.
There are two modes of operation: in the first, removals of
paremeter blocks are expensive, since each remove requires
scanning all residual blocks to find ones that depend on the
removed parameter. In the other, extra memory is sacrificed to
maintain a list of the residuals a parameter block depends on,
removing the need to scan. In both cases, removing residual blocks
is fast.

As a caveat, any removals destroys the ordering of the parameters,
so the residuals or jacobian returned from Solver::Solve() is
meaningless. There is some debate on the best way to handle this;
the details remain for a future change.

This also adds some overhead, even in the case that fast removals
are not requested:

- 1 int32 to each residual, to track its position in the program.
- 1 pointer to each parameter, to store the dependent residuals.

Change-Id: I71dcac8656679329a15ee7fc12c0df07030c12af
2013-02-18 15:00:30 -08:00