Initial Ceres integration into Blender

Currently only put sources of Ceres library into extern/libmv/third_party and
setup CMake and SCons building systems.

Integration details:

- Even CMake build files are not re-used from Ceres's trunk: they're using some
  automatic stuff detection like glog, pthreads, protobuf and so and it's not
  so clear how to re-use that files without modifications.
  And IMO it's easier if build files are getting re-generated automatically to
  match Blender-specific setup rather than keeping changes made locally in
  Blender in sync when re-bundling Ceres library. Especially in case when it's
  alerady needed to support SCons build system.
- Integrated only actual sources, all tests were stripped. Probably it'll be nice
  to have them, but they'll need clear integration with current module test stuff
  in Blender.
  Hopefully integration went smooth.
- Suitesparse was disabled. It'll help a lot having it, but there are some difficulties
  making cholmod working fine on windows. Would be added in future
- collections_port.cc was also stripped. It's not used by Ceres's upstream and
  it gives compilation error (undefined uint32 -- looks like namespace issue).
- Currently all schur eliminators are included. Not sure if it makes sense,
  also not sure if it makes sense having them switchable on and off -- IMO better
  to have single configuration which works and does not require special tweaks
  after everything was set up.
- Personally i'd say if some of Ceres modules are not used better to drop it
  away -- all symbols would be stripped anyway, but it'll be waste of compilation
  time which is annoying in cases when one doing, say, binary search of revision
  at which some regression was introduced. Especially when it's easy to add modules
  which should be used by Blender.
  But as long as it stays in Tomato i'm not worrying much about this.

To bundle updated version of Ceres:

- You'll need to use GIT-SVN checkout,
  Re-bundling Ceres using SVN is still NOT supported!
- Go to extern/libmv/third_party/ceres folder
- Run ./bundle.sh

This will checkout fresh Ceres snapshot of Windows branch (which is currently
most interesting from integration into Blender POV), apply all patches listed
in patches/series and copy needed files into Blender's working copy. This will
also re-generate CMake/SCons build rules.

If you'll need extra files from Ceres repository which are not present in
Blender, you'll need to copy them manually and then run ./mkfiles.sh from
extern/libmv/third_party/ceres folder which will update list of files used
by Blender.

Thanks all Ceres developers for this library and thanks to Keir Mierle with
help integrating Ceres into Blender!
This commit is contained in:
Sergey Sharybin 2012-05-09 15:39:54 +00:00
parent dfad263219
commit 5b7cad343e
170 changed files with 25035 additions and 37 deletions

@ -32,6 +32,7 @@ set(INC
third_party/ssba
third_party/ldl/Include
../colamd/Include
third_party/ceres/include
)
set(INC_SYS
@ -250,3 +251,5 @@ add_definitions(
)
blender_add_lib(extern_libmv "${SRC}" "${INC}" "${INC_SYS}")
add_subdirectory(third_party)

@ -1,3 +1,54 @@
commit b813dbe3f46bbbc7e73ac791d4665622e4fc7ba5
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 9 19:01:10 2012 +0600
Modal solver: Detect rigid transformation between initial frame and current
instead of detecting it between two neighbour frames.
This prevents accumulation of error and seems to be working better in footages i've tested.
commit 9254621c76daaf239ec1f535e197ca792eea97b6
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Wed May 9 18:57:00 2012 +0600
Backport changes made by Keir in Blender:
- Enhance logging in libmv's trackers.
- Cleanups in brute_region_tracker.cc.
commit d9c56b9d3c63f886d83129ca0ebed1e76d9c93d7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Apr 27 16:20:41 2012 +0600
Fixes for MinGW64 support by Caleb Joseph with slight modifications by Antony Riakiotakis
- Functions snprintf and sincos shouldn't be redefined for MinGW64
- Type pid_t shouldn't be re-defined for MinGW64
commit e1902b6938676011607ac99986b8b140bdbf090e
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Apr 27 16:04:19 2012 +0600
Fixes for Qt calibration tool
- Passing directory with images via command line argument now isn't
required -- it there's no such directory specified standard open
dialog might be used for this (before application used to abort
due to accessing to non-existing list element).
- Conversion of source images to grayscale now happens correct.
It was needed to build grayscale palette for 8bit indexed buffer.
commit 05f1a0a78ad8ff6646d1e8da97e6f7575b891536
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Sat Apr 14 17:21:29 2012 +0600
Make QtTracker compilable again porting it to recent API change and code cleanup:
- It was using SAD tracker with own API, now it's using standard RegionTracker API
which should make it easier to switch between different trackers.
- Restored LaplaceFilter from old SAD module which convolves images with the
discrete laplacian operator.
commit a44312a7beb2963b8e3bf8015c516d2eff40cc3d
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Thu Apr 12 13:56:02 2012 +0600
@ -503,33 +554,3 @@ Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Fri Aug 19 18:37:48 2011 +0200
Fix CMake build.
commit 2ac7281ff6b9545b425dd84fb03bf9c5c98b4de2
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Fri Aug 19 17:34:45 2011 +0200
Avoid symbol shadowing.
commit 2a7c3de4acc60e0433b4952f69e30528dbafe0d2
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Fri Aug 19 17:22:47 2011 +0200
Better dragging behavior when hitting borders.
commit a14eb3953c9521b2e08ff9ddd45b33ff1f8aeafb
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Fri Aug 19 17:12:12 2011 +0200
Update marker preview to new affine tracking.
commit 5299ea67043459eda147950e589c2d327a8fbced
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Fri Aug 19 16:05:54 2011 +0200
sqrt takes double precision.
commit 9f9221ce151d788c49b48f6f293ab2e2f8813978
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Fri Aug 19 16:04:37 2011 +0200
MSVC compatibility: heap allocate pattern, explicit float cast.

@ -30,7 +30,7 @@ src += env.Glob('third_party/ldl/Source/*.c')
src += env.Glob('third_party/ssba/Geometry/*.cpp')
src += env.Glob('third_party/ssba/Math/*.cpp')
incs = '. ../Eigen3'
incs = '. ../Eigen3 third_party/ceres/include'
incs += ' ' + env['BF_PNG_INC']
incs += ' ' + env['BF_ZLIB_INC']
@ -65,3 +65,5 @@ else:
incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include'
env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv )
SConscript(['third_party/SConscript'])

@ -23,7 +23,7 @@ for p in `cat ./patches/series`; do
done
rm -rf libmv
rm -rf third_party
rm -rf `find third_party/ -mindepth 1 -maxdepth 1 | grep -v ceres | grep -v CMake | grep -c SCons`
cat "files.txt" | while read f; do
mkdir -p `dirname $f`
@ -37,14 +37,14 @@ chmod 664 ./third_party/glog/src/windows/*.cc ./third_party/glog/src/windows/*.h
sources=`find ./libmv -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | sort -d`
headers=`find ./libmv -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d`
third_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep -v glog | sed -r 's/^\.\//\t/' | sort -d`
third_headers=`find ./third_party -type f -iname '*.h' | grep -v glog | sed -r 's/^\.\//\t/' | sort -d`
third_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep -v glog | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d`
third_headers=`find ./third_party -type f -iname '*.h' | grep -v glog | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d`
third_glog_sources=`find ./third_party -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort -d`
third_glog_headers=`find ./third_party -type f -iname '*.h' | grep glog | grep -v windows | sed -r 's/^\.\//\t\t/' | sort -d`
src_dir=`find ./libmv -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq`
src_third_dir=`find ./third_party -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq`
src_third_dir=`find ./third_party -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | grep -v ceres | sed -r 's/^\.\//\t/' | sort -d | uniq`
src=""
win_src=""
for x in $src_dir $src_third_dir; do
@ -124,6 +124,7 @@ set(INC
third_party/ssba
third_party/ldl/Include
../colamd/Include
third_party/ceres/include
)
set(INC_SYS
@ -218,6 +219,8 @@ add_definitions(
)
blender_add_lib(extern_libmv "\${SRC}" "\${INC}" "\${INC_SYS}")
add_subdirectory(third_party)
EOF
cat > SConscript << EOF
@ -244,7 +247,7 @@ defs.append('GOOGLE_GLOG_DLL_DECL=')
src = env.Glob("*.cpp")
$src
incs = '. ../Eigen3'
incs = '. ../Eigen3 third_party/ceres/include'
incs += ' ' + env['BF_PNG_INC']
incs += ' ' + env['BF_ZLIB_INC']
@ -279,4 +282,6 @@ else:
incs += ' ./third_party/ssba ./third_party/ldl/Include ../colamd/Include'
env.BlenderLib ( libname = 'extern_libmv', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137], compileflags=cflags_libmv, cc_compileflags=ccflags_libmv, cxx_compileflags=cxxflags_libmv )
SConscript(['third_party/SConscript'])
EOF

@ -302,4 +302,18 @@ void BoxFilter(const Array3Df &in,
BoxFilterVertical(tmp, box_width, out);
}
void LaplaceFilter(unsigned char* src, unsigned char* dst, int width, int height, int strength) {
for(int y=1; y<height-1; y++) for(int x=1; x<width-1; x++) {
const unsigned char* s = &src[y*width+x];
int l = 128 +
s[-width-1] + s[-width] + s[-width+1] +
s[1] - 8*s[0] + s[1] +
s[ width-1] + s[ width] + s[ width+1] ;
int d = ((256-strength)*s[0] + strength*l) / 256;
if(d < 0) d=0;
if(d > 255) d=255;
dst[y*width+x] = d;
}
}
} // namespace libmv

@ -87,6 +87,16 @@ void BoxFilter(const FloatImage &in,
int box_width,
FloatImage *out);
/*!
Convolve \a src into \a dst with the discrete laplacian operator.
\a src and \a dst should be \a width x \a height images.
\a strength is an interpolation coefficient (0-256) between original image and the laplacian.
\note Make sure the search region is filtered with the same strength as the pattern.
*/
void LaplaceFilter(unsigned char* src, unsigned char* dst, int width, int height, int strength);
} // namespace libmv
#endif // LIBMV_IMAGE_CONVOLVE_H_

@ -1,4 +1,4 @@
#!/bin/sh
find ./libmv/ -type f | sed -r 's/^\.\///' | sort > files.txt
find ./third_party/ -type f | sed -r 's/^\.\///' | sort >> files.txt
find ./third_party/ -mindepth 2 -type f | grep -v third_party/ceres | sed -r 's/^\.\///' | sort >> files.txt

@ -0,0 +1,2 @@
add_subdirectory(ceres)

3
extern/libmv/third_party/SConscript vendored Normal file

@ -0,0 +1,3 @@
#!/usr/bin/python
SConscript(['ceres/SConscript'])

@ -0,0 +1,218 @@
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2012, Blender Foundation
# All rights reserved.
#
# Contributor(s): Blender Foundation,
# Sergey Sharybin
#
# ***** END GPL LICENSE BLOCK *****
# NOTE: This file is automatically generated by bundle.sh script
# If you're doing changes in this file, please update template
# in that script too
set(INC
.
../../../Eigen3
include
internal
../gflags
)
set(INC_SYS
)
set(SRC
internal/ceres/block_evaluate_preparer.cc
internal/ceres/block_jacobian_writer.cc
internal/ceres/block_jacobi_preconditioner.cc
internal/ceres/block_random_access_dense_matrix.cc
internal/ceres/block_random_access_matrix.cc
internal/ceres/block_random_access_sparse_matrix.cc
internal/ceres/block_sparse_matrix.cc
internal/ceres/block_structure.cc
internal/ceres/canonical_views_clustering.cc
internal/ceres/cgnr_solver.cc
internal/ceres/compressed_row_jacobian_writer.cc
internal/ceres/compressed_row_sparse_matrix.cc
internal/ceres/conditioned_cost_function.cc
internal/ceres/conjugate_gradients_solver.cc
internal/ceres/corrector.cc
internal/ceres/dense_qr_solver.cc
internal/ceres/dense_sparse_matrix.cc
internal/ceres/detect_structure.cc
internal/ceres/evaluator.cc
internal/ceres/file.cc
internal/ceres/generated/schur_eliminator_2_2_2.cc
internal/ceres/generated/schur_eliminator_2_2_3.cc
internal/ceres/generated/schur_eliminator_2_2_4.cc
internal/ceres/generated/schur_eliminator_2_2_d.cc
internal/ceres/generated/schur_eliminator_2_3_3.cc
internal/ceres/generated/schur_eliminator_2_3_4.cc
internal/ceres/generated/schur_eliminator_2_3_9.cc
internal/ceres/generated/schur_eliminator_2_3_d.cc
internal/ceres/generated/schur_eliminator_2_4_3.cc
internal/ceres/generated/schur_eliminator_2_4_4.cc
internal/ceres/generated/schur_eliminator_2_4_d.cc
internal/ceres/generated/schur_eliminator_4_4_2.cc
internal/ceres/generated/schur_eliminator_4_4_3.cc
internal/ceres/generated/schur_eliminator_4_4_4.cc
internal/ceres/generated/schur_eliminator_4_4_d.cc
internal/ceres/generated/schur_eliminator_d_d_d.cc
internal/ceres/gradient_checking_cost_function.cc
internal/ceres/implicit_schur_complement.cc
internal/ceres/iterative_schur_complement_solver.cc
internal/ceres/levenberg_marquardt.cc
internal/ceres/linear_least_squares_problems.cc
internal/ceres/linear_operator.cc
internal/ceres/linear_solver.cc
internal/ceres/local_parameterization.cc
internal/ceres/loss_function.cc
internal/ceres/normal_prior.cc
internal/ceres/partitioned_matrix_view.cc
internal/ceres/problem.cc
internal/ceres/problem_impl.cc
internal/ceres/program.cc
internal/ceres/residual_block.cc
internal/ceres/residual_block_utils.cc
internal/ceres/runtime_numeric_diff_cost_function.cc
internal/ceres/schur_complement_solver.cc
internal/ceres/schur_eliminator.cc
internal/ceres/schur_ordering.cc
internal/ceres/scratch_evaluate_preparer.cc
internal/ceres/solver.cc
internal/ceres/solver_impl.cc
internal/ceres/sparse_matrix.cc
internal/ceres/sparse_normal_cholesky_solver.cc
internal/ceres/split.cc
internal/ceres/stringprintf.cc
internal/ceres/suitesparse.cc
internal/ceres/triplet_sparse_matrix.cc
internal/ceres/types.cc
internal/ceres/visibility_based_preconditioner.cc
internal/ceres/visibility.cc
include/ceres/autodiff_cost_function.h
include/ceres/ceres.h
include/ceres/conditioned_cost_function.h
include/ceres/cost_function.h
include/ceres/internal/autodiff.h
include/ceres/internal/eigen.h
include/ceres/internal/fixed_array.h
include/ceres/internal/macros.h
include/ceres/internal/manual_constructor.h
include/ceres/internal/port.h
include/ceres/internal/scoped_ptr.h
include/ceres/iteration_callback.h
include/ceres/jet.h
include/ceres/local_parameterization.h
include/ceres/loss_function.h
include/ceres/normal_prior.h
include/ceres/numeric_diff_cost_function.h
include/ceres/problem.h
include/ceres/rotation.h
include/ceres/sized_cost_function.h
include/ceres/solver.h
include/ceres/types.h
internal/ceres/block_evaluate_preparer.h
internal/ceres/block_jacobian_writer.h
internal/ceres/block_jacobi_preconditioner.h
internal/ceres/block_random_access_dense_matrix.h
internal/ceres/block_random_access_matrix.h
internal/ceres/block_random_access_sparse_matrix.h
internal/ceres/block_sparse_matrix.h
internal/ceres/block_structure.h
internal/ceres/canonical_views_clustering.h
internal/ceres/casts.h
internal/ceres/cgnr_linear_operator.h
internal/ceres/cgnr_solver.h
internal/ceres/collections_port.h
internal/ceres/compressed_row_jacobian_writer.h
internal/ceres/compressed_row_sparse_matrix.h
internal/ceres/conjugate_gradients_solver.h
internal/ceres/corrector.h
internal/ceres/dense_jacobian_writer.h
internal/ceres/dense_qr_solver.h
internal/ceres/dense_sparse_matrix.h
internal/ceres/detect_structure.h
internal/ceres/evaluator.h
internal/ceres/file.h
internal/ceres/gradient_checking_cost_function.h
internal/ceres/graph_algorithms.h
internal/ceres/graph.h
internal/ceres/implicit_schur_complement.h
internal/ceres/integral_types.h
internal/ceres/iterative_schur_complement_solver.h
internal/ceres/levenberg_marquardt.h
internal/ceres/linear_least_squares_problems.h
internal/ceres/linear_operator.h
internal/ceres/linear_solver.h
internal/ceres/map_util.h
internal/ceres/matrix_proto.h
internal/ceres/minimizer.h
internal/ceres/mutex.h
internal/ceres/parameter_block.h
internal/ceres/partitioned_matrix_view.h
internal/ceres/problem_impl.h
internal/ceres/program_evaluator.h
internal/ceres/program.h
internal/ceres/random.h
internal/ceres/residual_block.h
internal/ceres/residual_block_utils.h
internal/ceres/runtime_numeric_diff_cost_function.h
internal/ceres/schur_complement_solver.h
internal/ceres/schur_eliminator.h
internal/ceres/schur_eliminator_impl.h
internal/ceres/schur_ordering.h
internal/ceres/scratch_evaluate_preparer.h
internal/ceres/solver_impl.h
internal/ceres/sparse_matrix.h
internal/ceres/sparse_normal_cholesky_solver.h
internal/ceres/stl_util.h
internal/ceres/stringprintf.h
internal/ceres/suitesparse.h
internal/ceres/triplet_sparse_matrix.h
internal/ceres/visibility_based_preconditioner.h
internal/ceres/visibility.h
)
if(WIN32)
list(APPEND INC
../glog/src/windows
)
if(NOT MINGW)
list(APPEND INC
third_party/msinttypes
)
endif()
else()
list(APPEND INC
../glog/src
)
endif()
add_definitions(
-DCERES_HAVE_PTHREAD
-D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {"
-D"CERES_HASH_NAMESPACE_END=}}"
-DCERES_NO_SUITESPARSE
-DCERES_DONT_HAVE_PROTOCOL_BUFFERS
)
blender_add_lib(extern_ceres "${SRC}" "${INC}" "${INC_SYS}")

227
extern/libmv/third_party/ceres/ChangeLog vendored Normal file

@ -0,0 +1,227 @@
commit d297f8d3d3f5025c24752f0f4c1ec2469a769f99
Merge: 7e74d81 f8bd7fa
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 8 05:39:56 2012 -0700
Merge branch 'master' into windows
commit f8bd7fa9aa9dbf64b6165606630287cf8cf21194
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 8 05:39:32 2012 -0700
Small tweaks to the block jacobi preconditioner.
commit 7e74d81ad57a159f14110eb5348b3bc7990b8bd4
Merge: ecd7c8d e2a6cdc
Author: Keir Mierle <mierle@gmail.com>
Date: Mon May 7 07:02:49 2012 -0700
Merge branch 'master' into windows
commit e2a6cdc0816af9d0c77933f5017f137da3d52a35
Author: Keir Mierle <mierle@gmail.com>
Date: Mon May 7 06:39:56 2012 -0700
Address some of the comments on CGNR patch
- Rename BlockDiagonalPreconditioner to BlockJacobiPreconditioner
- Include the diagonal in the block jacobi preconditioner.
- Better flag help for eta.
- Enable test for CGNR
- Rename CONJUGATE_GRADIENTS to CGNR.
- etc.
commit 1b95dc580aa5d89be021c0915e26df83f18013bb
Merge: 211812a 7646039
Author: Keir Mierle <mierle@gmail.com>
Date: Mon May 7 04:34:10 2012 -0700
Merge branch 'master' of https://code.google.com/p/ceres-solver
commit 211812a57360d2011cbcfd115cd55e0eb73600db
Author: Keir Mierle <mierle@gmail.com>
Date: Mon May 7 04:33:50 2012 -0700
Better error handling in bundle_adjuster.cc
commit 7646039ad9672b267495f5b31925473ad3022ac8
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Sun May 6 22:02:19 2012 -0700
Kashif's corrections to the docs
commit 0d2d34148d10c5c7e924b3ca82ad2b237573ef64
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Sun May 6 21:16:03 2012 -0700
glog minimum version requirements
Building Ceres requires version 0.3.1 or better of glog.
Fedora 16 ships with a busted version 0.3.
issue 15 contains the gory details.
Added a note to the build documentation to this effect.
commit 39efc5ec4b64b8f5a2c5a3dbacdbc45421221547
Author: Keir Mierle <mierle@gmail.com>
Date: Sun May 6 16:09:52 2012 -0700
Fix tests broken by the CGNR change.
commit 3faa08b7f7c4ac73661c6a15a6824c12080dfcb1
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Sun May 6 16:08:22 2012 -0700
Formatting fixed based on Keir's comments and extended the tests
commit 4f21c68409bc478c431a9b6aedf9e5cfdf11d2f3
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Sun May 6 15:33:47 2012 -0700
Fix the struct weak ordering used by independent set ordering, tests for it
commit 887b156b917ccd4c172484452b059d33ea45f4f0
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Sun May 6 15:14:47 2012 -0700
fix he degree ordering routine
commit ecd7c8df2af19404dc394b36bbe96e9db3bce840
Author: Keir Mierle <mierle@gmail.com>
Date: Sun May 6 00:09:41 2012 -0700
First step towards windows compatibilty
This adds some small changes to Ceres to make it mostly
compile on Windows. There are still issues with the
hash map use in schur_ordering.cc but I will fix those
shortly.
commit f7898fba1b92f0e996571b5bfa22a37f5e3644de
Author: Keir Mierle <mierle@gmail.com>
Date: Sat May 5 20:55:08 2012 -0700
Add a general sparse iterative solver: CGNR
This adds a new LinearOperator which implements symmetric
products of a matrix, and a new CGNR solver to leverage
CG to directly solve the normal equations. This also
includes a block diagonal preconditioner. In experiments
on problem-16, the non-preconditioned version is about
1/5 the speed of SPARSE_SCHUR, and the preconditioned
version using block cholesky is about 20% slower than
SPARSE_SCHUR.
commit 0a359d6198d257776a8831c3eb98f64ee91cf836
Author: Keir Mierle <mierle@gmail.com>
Date: Sat May 5 20:33:46 2012 -0700
Comment formatting.
commit db4ec9312bb2f1ca7b2337812f6bad6cdd75b227
Author: Keir Mierle <mierle@gmail.com>
Date: Sat May 5 20:33:16 2012 -0700
Comment formatting
commit f10163aaf3e57f52551bcd60bbdae873890a49dd
Author: Keir Mierle <mierle@gmail.com>
Date: Fri May 4 21:33:53 2012 -0700
Warn about disabled schur specializations.
This commit brought to you from 30,000ft.
commit ad7b2b4aaf3ccc51f2b854febd53a9df54686cfe
Author: Keir Mierle <mierle@gmail.com>
Date: Fri May 4 20:15:28 2012 -0700
Add vim swapfiles to .gitignore
commit 6447219826bf6e47b0c99d9ff0eaf5e2ba573d79
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Thu May 3 21:53:07 2012 -0700
1. Changes the tutorial to refer to BriefReport.
2. Some of the enums have commas at the end.
3. Fix a bug in the default value of circle_fit.cc in the examples.
commit 30c5f93c7f88dec49f76168663372772e06f17f5
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Thu May 3 10:44:43 2012 -0700
Rework the glog and gtest path checking to be consistent with the rest of the file and disable the dashboard support enabled by the earlier ctesting related patch.
commit f10b033eb4aca77919987bc551d16d8a88b10110
Merge: cc38774 e0a52a9
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Thu May 3 08:45:20 2012 -0700
Merge branch 'ctest'
commit e0a52a993394e73bc7f7db8d520728926feab83e
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Thu May 3 08:43:34 2012 -0700
Arnaus Gelas' patch to add better path searching for gflags and glog
commit a9b8e815e1c026599734510399b10f4cf014c9cd
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Thu May 3 08:41:52 2012 -0700
Arnaus Gelas' patch to add .gitignore
commit a0cefc3347c32b2065053bbaff4f34d11529d931
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Thu May 3 08:38:33 2012 -0700
Arnaus Gelas' patch to move to Ctest
commit cc38774d74e287704915282425fbd16818a72ec3
Author: Keir Mierle <mierle@gmail.com>
Date: Thu May 3 01:27:50 2012 -0700
Clarify ProgramEvaluator comments.
commit 017c9530df557863f78212fb5ccd02814baa9fa8
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Wed May 2 08:21:59 2012 -0700
Mac OS X build instructions are much simpler, as homebrew takes care of gflags when glog is brought in. Also CMAKE does not need any flags to do the default thing
commit 92d5ab5f8ae6fe355c30b606a5f230415ee0494b
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 1 18:33:08 2012 -0700
Link BLAS explicitly on non-Mac platforms
Fixes issue #3.
commit df3e54eb4a6b001b7f0560a2da73a5bd7f18615e
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 1 18:22:51 2012 -0700
Fix link order of CHOLMOD
This was working by accident due to dynamic linking. Fixes issue #2.
commit f477a3835329e2b48eb20c34c631a480b0f0d5bf
Author: Keir Mierle <mierle@gmail.com>
Date: Tue May 1 18:10:48 2012 -0700
Fix Eigen search paths
Fixes issue #1 on http://code.google.com/p/ceres-solver.
commit 17fbc8ebb894c1d22bb3b0b02ea1394b580120f8
Author: Sameer Agarwal <sameeragarwal@google.com>
Date: Tue May 1 00:21:19 2012 -0700
Minor changes to the documentation. Formatting, and typos.
commit 8ebb0730388045570f22b89fe8672c860cd2ad1b
Author: Keir Mierle <mierle@gmail.com>
Date: Mon Apr 30 23:09:08 2012 -0700
Initial commit of Ceres Solver.

27
extern/libmv/third_party/ceres/LICENSE vendored Normal file

@ -0,0 +1,27 @@
Ceres Solver - A fast non-linear least squares minimizer
Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
http://code.google.com/p/ceres-solver/
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Google Inc. nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

3
extern/libmv/third_party/ceres/README vendored Normal file

@ -0,0 +1,3 @@
Ceres Solver - A non-linear least squares minimizer
==================================================
Please see ceres.pdf in docs/ for a tutorial and reference.

@ -0,0 +1,34 @@
#!/usr/bin/python
# NOTE: This file is automatically generated by bundle.sh script
# If you're doing changes in this file, please update template
# in that script too
import sys
import os
Import('env')
src = []
defs = []
src += env.Glob('internal/ceres/*.cc')
src += env.Glob('internal/ceres/generated/*.cc')
defs.append('CERES_HAVE_PTHREAD')
defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {')
defs.append('CERES_HASH_NAMESPACE_END=}}')
defs.append('CERES_NO_SUITESPARSE')
defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS')
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags'
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ../msinttypes'
incs += ' ../glog/src/windows'
else:
incs += ' ../glog/src'
env.BlenderLib ( libname = 'extern_ceres', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])

183
extern/libmv/third_party/ceres/bundle.sh vendored Executable file

@ -0,0 +1,183 @@
#!/bin/sh
if [ -d ./.svn ]; then
echo "This script is supposed to work only when using git-svn"
exit 1
fi
repo="https://code.google.com/p/ceres-solver/"
branch="windows"
tmp=`mktemp -d`
GIT="git --git-dir $tmp/ceres/.git --work-tree $tmp/ceres"
git clone $repo $tmp/ceres
if [ $branch != "master" ]; then
$GIT checkout -t remotes/origin/$branch
fi
$GIT log -n 50 > ChangeLog
for p in `cat ./patches/series`; do
echo "Applying patch $p..."
cat ./patches/$p | patch -d $tmp/ceres -p1
done
rm -rf include
rm -rf internal
cat "files.txt" | while read f; do
mkdir -p `dirname $f`
cp $tmp/ceres/$f $f
done
rm -rf $tmp
sources=`find ./include ./internal -type f -iname '*.cc' -or -iname '*.cpp' -or -iname '*.c' | sed -r 's/^\.\//\t/' | sort -d`
headers=`find ./include ./internal -type f -iname '*.h' | sed -r 's/^\.\//\t/' | sort -d`
src_dir=`find ./internal -type f -iname '*.cc' -exec dirname {} \; -or -iname '*.cpp' -exec dirname {} \; -or -iname '*.c' -exec dirname {} \; | sed -r 's/^\.\//\t/' | sort -d | uniq`
src=""
for x in $src_dir $src_third_dir; do
t=""
if test `echo "$x" | grep -c glog ` -eq 1; then
continue;
fi
if stat $x/*.cpp > /dev/null 2>&1; then
t="src += env.Glob('`echo $x'/*.cpp'`')"
fi
if stat $x/*.c > /dev/null 2>&1; then
if [ -z "$t" ]; then
t="src += env.Glob('`echo $x'/*.c'`')"
else
t="$t + env.Glob('`echo $x'/*.c'`')"
fi
fi
if stat $x/*.cc > /dev/null 2>&1; then
if [ -z "$t" ]; then
t="src += env.Glob('`echo $x'/*.cc'`')"
else
t="$t + env.Glob('`echo $x'/*.cc'`')"
fi
fi
if [ -z "$src" ]; then
src=$t
else
src=`echo "$src\n$t"`
fi
done
cat > CMakeLists.txt << EOF
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2012, Blender Foundation
# All rights reserved.
#
# Contributor(s): Blender Foundation,
# Sergey Sharybin
#
# ***** END GPL LICENSE BLOCK *****
# NOTE: This file is automatically generated by bundle.sh script
# If you're doing changes in this file, please update template
# in that script too
set(INC
.
../../../Eigen3
include
internal
../gflags
)
set(INC_SYS
)
set(SRC
${sources}
${headers}
)
if(WIN32)
list(APPEND INC
../glog/src/windows
)
if(NOT MINGW)
list(APPEND INC
third_party/msinttypes
)
endif()
else()
list(APPEND INC
../glog/src
)
endif()
add_definitions(
-DCERES_HAVE_PTHREAD
-D"CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {"
-D"CERES_HASH_NAMESPACE_END=}}"
-DCERES_NO_SUITESPARSE
-DCERES_DONT_HAVE_PROTOCOL_BUFFERS
)
blender_add_lib(extern_ceres "\${SRC}" "\${INC}" "\${INC_SYS}")
EOF
cat > SConscript << EOF
#!/usr/bin/python
# NOTE: This file is automatically generated by bundle.sh script
# If you're doing changes in this file, please update template
# in that script too
import sys
import os
Import('env')
src = []
defs = []
$src
defs.append('CERES_HAVE_PTHREAD')
defs.append('CERES_HASH_NAMESPACE_START=namespace std { namespace tr1 {')
defs.append('CERES_HASH_NAMESPACE_END=}}')
defs.append('CERES_NO_SUITESPARSE')
defs.append('CERES_DONT_HAVE_PROTOCOL_BUFFERS')
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags'
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
incs += ' ../msinttypes'
incs += ' ../glog/src/windows'
else:
incs += ' ../glog/src'
env.BlenderLib ( libname = 'extern_ceres', sources=src, includes=Split(incs), defines=defs, libtype=['extern', 'player'], priority=[20,137])
EOF

150
extern/libmv/third_party/ceres/files.txt vendored Normal file

@ -0,0 +1,150 @@
include/ceres/autodiff_cost_function.h
include/ceres/ceres.h
include/ceres/conditioned_cost_function.h
include/ceres/cost_function.h
include/ceres/internal/autodiff.h
include/ceres/internal/eigen.h
include/ceres/internal/fixed_array.h
include/ceres/internal/macros.h
include/ceres/internal/manual_constructor.h
include/ceres/internal/port.h
include/ceres/internal/scoped_ptr.h
include/ceres/iteration_callback.h
include/ceres/jet.h
include/ceres/local_parameterization.h
include/ceres/loss_function.h
include/ceres/normal_prior.h
include/ceres/numeric_diff_cost_function.h
include/ceres/problem.h
include/ceres/rotation.h
include/ceres/sized_cost_function.h
include/ceres/solver.h
include/ceres/types.h
internal/ceres/block_evaluate_preparer.cc
internal/ceres/block_evaluate_preparer.h
internal/ceres/block_jacobian_writer.cc
internal/ceres/block_jacobian_writer.h
internal/ceres/block_jacobi_preconditioner.cc
internal/ceres/block_jacobi_preconditioner.h
internal/ceres/block_random_access_dense_matrix.cc
internal/ceres/block_random_access_dense_matrix.h
internal/ceres/block_random_access_matrix.cc
internal/ceres/block_random_access_matrix.h
internal/ceres/block_random_access_sparse_matrix.cc
internal/ceres/block_random_access_sparse_matrix.h
internal/ceres/block_sparse_matrix.cc
internal/ceres/block_sparse_matrix.h
internal/ceres/block_structure.cc
internal/ceres/block_structure.h
internal/ceres/canonical_views_clustering.cc
internal/ceres/canonical_views_clustering.h
internal/ceres/casts.h
internal/ceres/cgnr_linear_operator.h
internal/ceres/cgnr_solver.cc
internal/ceres/cgnr_solver.h
internal/ceres/collections_port.h
internal/ceres/compressed_row_jacobian_writer.cc
internal/ceres/compressed_row_jacobian_writer.h
internal/ceres/compressed_row_sparse_matrix.cc
internal/ceres/compressed_row_sparse_matrix.h
internal/ceres/conditioned_cost_function.cc
internal/ceres/conjugate_gradients_solver.cc
internal/ceres/conjugate_gradients_solver.h
internal/ceres/corrector.cc
internal/ceres/corrector.h
internal/ceres/dense_jacobian_writer.h
internal/ceres/dense_qr_solver.cc
internal/ceres/dense_qr_solver.h
internal/ceres/dense_sparse_matrix.cc
internal/ceres/dense_sparse_matrix.h
internal/ceres/detect_structure.cc
internal/ceres/detect_structure.h
internal/ceres/evaluator.cc
internal/ceres/evaluator.h
internal/ceres/file.cc
internal/ceres/file.h
internal/ceres/generated/schur_eliminator_2_2_2.cc
internal/ceres/generated/schur_eliminator_2_2_3.cc
internal/ceres/generated/schur_eliminator_2_2_4.cc
internal/ceres/generated/schur_eliminator_2_2_d.cc
internal/ceres/generated/schur_eliminator_2_3_3.cc
internal/ceres/generated/schur_eliminator_2_3_4.cc
internal/ceres/generated/schur_eliminator_2_3_9.cc
internal/ceres/generated/schur_eliminator_2_3_d.cc
internal/ceres/generated/schur_eliminator_2_4_3.cc
internal/ceres/generated/schur_eliminator_2_4_4.cc
internal/ceres/generated/schur_eliminator_2_4_d.cc
internal/ceres/generated/schur_eliminator_4_4_2.cc
internal/ceres/generated/schur_eliminator_4_4_3.cc
internal/ceres/generated/schur_eliminator_4_4_4.cc
internal/ceres/generated/schur_eliminator_4_4_d.cc
internal/ceres/generated/schur_eliminator_d_d_d.cc
internal/ceres/gradient_checking_cost_function.cc
internal/ceres/gradient_checking_cost_function.h
internal/ceres/graph_algorithms.h
internal/ceres/graph.h
internal/ceres/implicit_schur_complement.cc
internal/ceres/implicit_schur_complement.h
internal/ceres/integral_types.h
internal/ceres/iterative_schur_complement_solver.cc
internal/ceres/iterative_schur_complement_solver.h
internal/ceres/levenberg_marquardt.cc
internal/ceres/levenberg_marquardt.h
internal/ceres/linear_least_squares_problems.cc
internal/ceres/linear_least_squares_problems.h
internal/ceres/linear_operator.cc
internal/ceres/linear_operator.h
internal/ceres/linear_solver.cc
internal/ceres/linear_solver.h
internal/ceres/local_parameterization.cc
internal/ceres/loss_function.cc
internal/ceres/map_util.h
internal/ceres/matrix_proto.h
internal/ceres/minimizer.h
internal/ceres/mutex.h
internal/ceres/normal_prior.cc
internal/ceres/parameter_block.h
internal/ceres/partitioned_matrix_view.cc
internal/ceres/partitioned_matrix_view.h
internal/ceres/problem.cc
internal/ceres/problem_impl.cc
internal/ceres/problem_impl.h
internal/ceres/program.cc
internal/ceres/program_evaluator.h
internal/ceres/program.h
internal/ceres/random.h
internal/ceres/residual_block.cc
internal/ceres/residual_block.h
internal/ceres/residual_block_utils.cc
internal/ceres/residual_block_utils.h
internal/ceres/runtime_numeric_diff_cost_function.cc
internal/ceres/runtime_numeric_diff_cost_function.h
internal/ceres/schur_complement_solver.cc
internal/ceres/schur_complement_solver.h
internal/ceres/schur_eliminator.cc
internal/ceres/schur_eliminator.h
internal/ceres/schur_eliminator_impl.h
internal/ceres/schur_ordering.cc
internal/ceres/schur_ordering.h
internal/ceres/scratch_evaluate_preparer.cc
internal/ceres/scratch_evaluate_preparer.h
internal/ceres/solver.cc
internal/ceres/solver_impl.cc
internal/ceres/solver_impl.h
internal/ceres/sparse_matrix.cc
internal/ceres/sparse_matrix.h
internal/ceres/sparse_normal_cholesky_solver.cc
internal/ceres/sparse_normal_cholesky_solver.h
internal/ceres/split.cc
internal/ceres/stl_util.h
internal/ceres/stringprintf.cc
internal/ceres/stringprintf.h
internal/ceres/suitesparse.cc
internal/ceres/suitesparse.h
internal/ceres/triplet_sparse_matrix.cc
internal/ceres/triplet_sparse_matrix.h
internal/ceres/types.cc
internal/ceres/visibility_based_preconditioner.cc
internal/ceres/visibility_based_preconditioner.h
internal/ceres/visibility.cc
internal/ceres/visibility.h

@ -0,0 +1,170 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Helpers for making CostFunctions as needed by the least squares framework,
// with Jacobians computed via automatic differentiation. For more information
// on automatic differentation, see the wikipedia article at
// http://en.wikipedia.org/wiki/Automatic_differentiation
//
// To get an auto differentiated cost function, you must define a class with a
// templated operator() (a functor) that computes the cost function in terms of
// the template parameter T. The autodiff framework substitutes appropriate
// "jet" objects for T in order to compute the derivative when necessary, but
// this is hidden, and you should write the function as if T were a scalar type
// (e.g. a double-precision floating point number).
//
// The function must write the computed value in the last argument (the only
// non-const one) and return true to indicate success.
//
// For example, consider a scalar error e = k - x'y, where both x and y are
// two-dimensional column vector parameters, the prime sign indicates
// transposition, and k is a constant. The form of this error, which is the
// difference between a constant and an expression, is a common pattern in least
// squares problems. For example, the value x'y might be the model expectation
// for a series of measurements, where there is an instance of the cost function
// for each measurement k.
//
// The actual cost added to the total problem is e^2, or (k - x'k)^2; however,
// the squaring is implicitly done by the optimization framework.
//
// To write an auto-differentiable cost function for the above model, first
// define the object
//
// class MyScalarCostFunction {
// MyScalarCostFunction(double k): k_(k) {}
//
// template <typename T>
// bool operator()(const T* const x , const T* const y, T* e) const {
// e[0] = T(k_) - x[0] * y[0] + x[1] * y[1];
// return true;
// }
//
// private:
// double k_;
// };
//
// Note that in the declaration of operator() the input parameters x and y come
// first, and are passed as const pointers to arrays of T. If there were three
// input parameters, then the third input parameter would come after y. The
// output is always the last parameter, and is also a pointer to an array. In
// the example above, e is a scalar, so only e[0] is set.
//
// Then given this class definition, the auto differentiated cost function for
// it can be constructed as follows.
//
// CostFunction* cost_function
// = new AutoDiffCostFunction<MyScalarCostFunction, 1, 2, 2>(
// new MyScalarCostFunction(1.0)); ^ ^ ^
// | | |
// Dimension of residual ------+ | |
// Dimension of x ----------------+ |
// Dimension of y -------------------+
//
// In this example, there is usually an instance for each measumerent of k.
//
// In the instantiation above, the template parameters following
// "MyScalarCostFunction", "1, 2, 2", describe the functor as computing a
// 1-dimensional output from two arguments, both 2-dimensional.
//
// The framework can currently accommodate cost functions of up to 6 independent
// variables, and there is no limit on the dimensionality of each of them.
//
// WARNING #1: Since the functor will get instantiated with different types for
// T, you must to convert from other numeric types to T before mixing
// computations with other variables of type T. In the example above, this is
// seen where instead of using k_ directly, k_ is wrapped with T(k_).
//
// WARNING #2: A common beginner's error when first using autodiff cost
// functions is to get the sizing wrong. In particular, there is a tendency to
// set the template parameters to (dimension of residual, number of parameters)
// instead of passing a dimension parameter for *every parameter*. In the
// example above, that would be <MyScalarCostFunction, 1, 2>, which is missing
// the last '2' argument. Please be careful when setting the size parameters.
#ifndef CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
#define CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_
#include <glog/logging.h>
#include "ceres/internal/autodiff.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/sized_cost_function.h"
namespace ceres {
// A cost function which computes the derivative of the cost with respect to the
// parameters (a.k.a. the jacobian) using an autodifferentiation framework. The
// first template argument is the functor object, described in the header
// comment. The second argument is the dimension of the residual, and subsequent
// arguments describe the size of the Nth parameter, one per parameter.
//
// The constructor, which takes a cost functor, takes ownership of the functor.
template <typename CostFunctor,
int M, // Number of residuals.
int N0, // Number of parameters in block 0.
int N1 = 0, // Number of parameters in block 1.
int N2 = 0, // Number of parameters in block 2.
int N3 = 0, // Number of parameters in block 3.
int N4 = 0, // Number of parameters in block 4.
int N5 = 0> // Number of parameters in block 5.
class AutoDiffCostFunction :
public SizedCostFunction<M, N0, N1, N2, N3, N4, N5> {
public:
// Takes ownership of functor.
explicit AutoDiffCostFunction(CostFunctor* functor) : functor_(functor) {}
virtual ~AutoDiffCostFunction() {}
// Implementation details follow; clients of the autodiff cost function should
// not have to examine below here.
//
// To handle varardic cost functions, some template magic is needed. It's
// mostly hidden inside autodiff.h.
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
if (!jacobians) {
return internal::VariadicEvaluate<
CostFunctor, double, M, N0, N1, N2, N3, N4, N5>
::Call(*functor_, parameters, residuals);
}
return internal::AutoDiff<CostFunctor, double,
M, N0, N1, N2, N3, N4, N5>::Differentiate(*functor_,
parameters,
residuals,
jacobians);
}
private:
internal::scoped_ptr<CostFunctor> functor_;
};
} // namespace ceres
#endif // CERES_PUBLIC_AUTODIFF_COST_FUNCTION_H_

@ -0,0 +1,48 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// This is a forwarding header containing the public symbols exported from
// Ceres. Anything in the "ceres" namespace is available for use.
#ifndef CERES_PUBLIC_CERES_H_
#define CERES_PUBLIC_CERES_H_
#include "ceres/autodiff_cost_function.h"
#include "ceres/cost_function.h"
#include "ceres/iteration_callback.h"
#include "ceres/local_parameterization.h"
#include "ceres/loss_function.h"
#include "ceres/numeric_diff_cost_function.h"
#include "ceres/problem.h"
#include "ceres/sized_cost_function.h"
#include "ceres/solver.h"
#include "ceres/types.h"
#endif // CERES_PUBLIC_CERES_H_

@ -0,0 +1,97 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: wjr@google.com (William Rucklidge)
//
// This file contains a cost function that can apply a transformation to
// each residual value before they are square-summed.
#ifndef CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
#define CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_
#include <vector>
#include "ceres/cost_function.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
namespace ceres {
// This class allows you to apply different conditioning to the residual
// values of a wrapped cost function. An example where this is useful is
// where you have an existing cost function that produces N values, but you
// want the total cost to be something other than just the sum of these
// squared values - maybe you want to apply a different scaling to some
// values, to change their contribution to the cost.
//
// Usage:
//
// // my_cost_function produces N residuals
// CostFunction* my_cost_function = ...
// CHECK_EQ(N, my_cost_function->num_residuals());
// vector<CostFunction*> conditioners;
//
// // Make N 1x1 cost functions (1 parameter, 1 residual)
// CostFunction* f_1 = ...
// conditioners.push_back(f_1);
// ...
// CostFunction* f_N = ...
// conditioners.push_back(f_N);
// ConditionedCostFunction* ccf =
// new ConditionedCostFunction(my_cost_function, conditioners);
//
// Now ccf's residual i (i=0..N-1) will be passed though the i'th conditioner.
//
// ccf_residual[i] = f_i(my_cost_function_residual[i])
//
// and the Jacobian will be affected appropriately.
class ConditionedCostFunction : public CostFunction {
public:
// Builds a cost function based on a wrapped cost function, and a
// per-residual conditioner. Takes ownership of all of the wrapped cost
// functions, or not, depending on the ownership parameter. Conditioners
// may be NULL, in which case the corresponding residual is not modified.
ConditionedCostFunction(CostFunction* wrapped_cost_function,
const vector<CostFunction*>& conditioners,
Ownership ownership);
virtual ~ConditionedCostFunction();
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const;
private:
internal::scoped_ptr<CostFunction> wrapped_cost_function_;
vector<CostFunction*> conditioners_;
Ownership ownership_;
};
} // namespace ceres
#endif // CERES_PUBLIC_CONDITIONED_COST_FUNCTION_H_

@ -0,0 +1,127 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
// keir@google.m (Keir Mierle)
//
// This is the interface through which the least squares solver accesses the
// residual and Jacobian of the least squares problem. Users are expected to
// subclass CostFunction to define their own terms in the least squares problem.
//
// It is recommended that users define templated residual functors for use as
// arguments for AutoDiffCostFunction (see autodiff_cost_function.h), instead of
// directly implementing the CostFunction interface. This often results in both
// shorter code and faster execution than hand-coded derivatives. However,
// specialized cases may demand direct implementation of the lower-level
// CostFunction interface; for example, this is true when calling legacy code
// which is not templated on numeric types.
#ifndef CERES_PUBLIC_COST_FUNCTION_H_
#define CERES_PUBLIC_COST_FUNCTION_H_
#include <vector>
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
#include "ceres/types.h"
namespace ceres {
// This class implements the computation of the cost (a.k.a. residual) terms as
// a function of the input (control) variables, and is the interface for users
// to describe their least squares problem to Ceres. In other words, this is the
// modelling layer between users and the Ceres optimizer. The signature of the
// function (number and sizes of input parameter blocks and number of outputs)
// is stored in parameter_block_sizes_ and num_residuals_ respectively. User
// code inheriting from this class is expected to set these two members with the
// corresponding accessors. This information will be verified by the Problem
// when added with AddResidualBlock().
class CostFunction {
public:
CostFunction() : num_residuals_(0) {}
virtual ~CostFunction() {}
// Inputs:
//
// parameters is an array of pointers to arrays containing the
// various parameter blocks. parameters has the same number of
// elements as parameter_block_sizes_. Parameter blocks are in the
// same order as parameter_block_sizes_.i.e.,
//
// parameters_[i] = double[parameter_block_sizes_[i]]
//
// Outputs:
//
// residuals is an array of size num_residuals_.
//
// jacobians is an array of size parameter_block_sizes_ containing
// pointers to storage for jacobian blocks corresponding to each
// parameter block. Jacobian blocks are in the same order as
// parameter_block_sizes, i.e. jacobians[i], is an
// array that contains num_residuals_* parameter_block_sizes_[i]
// elements. Each jacobian block is stored in row-major order, i.e.,
//
// jacobians[i][r*parameter_block_size_[i] + c] =
// d residual[r] / d parameters[i][c]
//
// If jacobians is NULL, then no derivatives are returned; this is
// the case when computing cost only. If jacobians[i] is NULL, then
// the jacobian block corresponding to the i'th parameter block must
// not to be returned.
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const = 0;
const vector<int16>& parameter_block_sizes() const {
return parameter_block_sizes_;
}
int num_residuals() const {
return num_residuals_;
}
protected:
vector<int16>* mutable_parameter_block_sizes() {
return &parameter_block_sizes_;
}
void set_num_residuals(int num_residuals) {
num_residuals_ = num_residuals;
}
private:
// Cost function signature metadata: number of inputs & their sizes,
// number of outputs (residuals).
vector<int16> parameter_block_sizes_;
int num_residuals_;
DISALLOW_COPY_AND_ASSIGN(CostFunction);
};
} // namespace ceres
#endif // CERES_PUBLIC_COST_FUNCTION_H_

@ -0,0 +1,374 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// Computation of the Jacobian matrix for vector-valued functions of multiple
// variables, using automatic differentiation based on the implementation of
// dual numbers in jet.h. Before reading the rest of this file, it is adivsable
// to read jet.h's header comment in detail.
//
// The helper wrapper AutoDiff::Differentiate() computes the jacobian of
// functors with templated operator() taking this form:
//
// struct F {
// template<typename T>
// bool operator(const T *x, const T *y, ..., T *z) {
// // Compute z[] based on x[], y[], ...
// // return true if computation succeeded, false otherwise.
// }
// };
//
// All inputs and outputs may be vector-valued.
//
// To understand how jets are used to compute the jacobian, a
// picture may help. Consider a vector-valued function, F, returning 3
// dimensions and taking a vector-valued parameter of 4 dimensions:
//
// y x
// [ * ] F [ * ]
// [ * ] <--- [ * ]
// [ * ] [ * ]
// [ * ]
//
// Similar to the 2-parameter example for f described in jet.h, computing the
// jacobian dy/dx is done by substutiting a suitable jet object for x and all
// intermediate steps of the computation of F. Since x is has 4 dimensions, use
// a Jet<double, 4>.
//
// Before substituting a jet object for x, the dual components are set
// appropriately for each dimension of x:
//
// y x
// [ * | * * * * ] f [ * | 1 0 0 0 ] x0
// [ * | * * * * ] <--- [ * | 0 1 0 0 ] x1
// [ * | * * * * ] [ * | 0 0 1 0 ] x2
// ---+--- [ * | 0 0 0 1 ] x3
// | ^ ^ ^ ^
// dy/dx | | | +----- infinitesimal for x3
// | | +------- infinitesimal for x2
// | +--------- infinitesimal for x1
// +----------- infinitesimal for x0
//
// The reason to set the internal 4x4 submatrix to the identity is that we wish
// to take the derivative of y separately with respect to each dimension of x.
// Each column of the 4x4 identity is therefore for a single component of the
// independent variable x.
//
// Then the jacobian of the mapping, dy/dx, is the 3x4 sub-matrix of the
// extended y vector, indicated in the above diagram.
//
// Functors with multiple parameters
// ---------------------------------
// In practice, it is often convenient to use a function f of two or more
// vector-valued parameters, for example, x[3] and z[6]. Unfortunately, the jet
// framework is designed for a single-parameter vector-valued input. The wrapper
// in this file addresses this issue adding support for functions with one or
// more parameter vectors.
//
// To support multiple parameters, all the parameter vectors are concatenated
// into one and treated as a single parameter vector, except that since the
// functor expects different inputs, we need to construct the jets as if they
// were part of a single parameter vector. The extended jets are passed
// separately for each parameter.
//
// For example, consider a functor F taking two vector parameters, p[2] and
// q[3], and producing an output y[4]:
//
// struct F {
// template<typename T>
// bool operator(const T *p, const T *q, T *z) {
// // ...
// }
// };
//
// In this case, the necessary jet type is Jet<double, 5>. Here is a
// visualization of the jet objects in this case:
//
// Dual components for p ----+
// |
// -+-
// y [ * | 1 0 | 0 0 0 ] --- p[0]
// [ * | 0 1 | 0 0 0 ] --- p[1]
// [ * | . . | + + + ] |
// [ * | . . | + + + ] v
// [ * | . . | + + + ] <--- F(p, q)
// [ * | . . | + + + ] ^
// ^^^ ^^^^^ |
// dy/dp dy/dq [ * | 0 0 | 1 0 0 ] --- q[0]
// [ * | 0 0 | 0 1 0 ] --- q[1]
// [ * | 0 0 | 0 0 1 ] --- q[2]
// --+--
// |
// Dual components for q --------------+
//
// where the 4x2 submatrix (marked with ".") and 4x3 submatrix (marked with "+"
// of y in the above diagram are the derivatives of y with respect to p and q
// respectively. This is how autodiff works for functors taking multiple vector
// valued arguments (up to 6).
//
// Jacobian NULL pointers
// ----------------------
// In general, the functions below will accept NULL pointers for all or some of
// the Jacobian parameters, meaning that those Jacobians will not be computed.
#ifndef CERES_PUBLIC_INTERNAL_AUTODIFF_H_
#define CERES_PUBLIC_INTERNAL_AUTODIFF_H_
#include <stddef.h>
#include <glog/logging.h>
#include "ceres/jet.h"
#include "ceres/internal/fixed_array.h"
namespace ceres {
namespace internal {
// Extends src by a 1st order pertubation for every dimension and puts it in
// dst. The size of src is N. Since this is also used for perturbations in
// blocked arrays, offset is used to shift which part of the jet the
// perturbation occurs. This is used to set up the extended x augmented by an
// identity matrix. The JetT type should be a Jet type, and T should be a
// numeric type (e.g. double). For example,
//
// 0 1 2 3 4 5 6 7 8
// dst[0] [ * | . . | 1 0 0 | . . . ]
// dst[1] [ * | . . | 0 1 0 | . . . ]
// dst[2] [ * | . . | 0 0 1 | . . . ]
//
// is what would get put in dst if N was 3, offset was 3, and the jet type JetT
// was 8-dimensional.
template <typename JetT, typename T>
inline void Make1stOrderPerturbation(int offset, int N, const T *src,
JetT *dst) {
DCHECK(src);
DCHECK(dst);
for (int j = 0; j < N; ++j) {
dst[j] = JetT(src[j], offset + j);
}
}
// Takes the 0th order part of src, assumed to be a Jet type, and puts it in
// dst. This is used to pick out the "vector" part of the extended y.
template <typename JetT, typename T>
inline void Take0thOrderPart(int M, const JetT *src, T dst) {
DCHECK(src);
for (int i = 0; i < M; ++i) {
dst[i] = src[i].a;
}
}
// Takes N 1st order parts, starting at index N0, and puts them in the M x N
// matrix 'dst'. This is used to pick out the "matrix" parts of the extended y.
template <typename JetT, typename T, int M, int N0, int N>
inline void Take1stOrderPart(const JetT *src, T *dst) {
DCHECK(src);
DCHECK(dst);
// TODO(keir): Change Jet to use a single array, where v[0] is the
// non-infinitesimal part rather than "a". That way it's possible to use a
// single memcpy or eigen operation, rather than the explicit loop. The loop
// doesn't exploit any SSE or other intrinsics.
for (int i = 0; i < M; ++i) {
for (int j = 0; j < N; ++j) {
dst[N * i + j] = src[i].v[N0 + j];
}
}
}
// This block of quasi-repeated code calls the user-supplied functor, which may
// take a variable number of arguments. This is accomplished by specializing the
// struct based on the size of the trailing parameters; parameters with 0 size
// are assumed missing.
//
// Supporting variadic functions is the primary source of complexity in the
// autodiff implementation.
template<typename Functor, typename T, int kNumOutputs,
int N0, int N1, int N2, int N3, int N4, int N5>
struct VariadicEvaluate {
static bool Call(const Functor& functor, T const *const *input, T* output) {
return functor(input[0],
input[1],
input[2],
input[3],
input[4],
input[5],
output);
}
};
template<typename Functor, typename T, int kNumOutputs,
int N0, int N1, int N2, int N3, int N4>
struct VariadicEvaluate<Functor, T, kNumOutputs, N0, N1, N2, N3, N4, 0> {
static bool Call(const Functor& functor, T const *const *input, T* output) {
return functor(input[0],
input[1],
input[2],
input[3],
input[4],
output);
}
};
template<typename Functor, typename T, int kNumOutputs,
int N0, int N1, int N2, int N3>
struct VariadicEvaluate<Functor, T, kNumOutputs, N0, N1, N2, N3, 0, 0> {
static bool Call(const Functor& functor, T const *const *input, T* output) {
return functor(input[0],
input[1],
input[2],
input[3],
output);
}
};
template<typename Functor, typename T, int kNumOutputs,
int N0, int N1, int N2>
struct VariadicEvaluate<Functor, T, kNumOutputs, N0, N1, N2, 0, 0, 0> {
static bool Call(const Functor& functor, T const *const *input, T* output) {
return functor(input[0],
input[1],
input[2],
output);
}
};
template<typename Functor, typename T, int kNumOutputs,
int N0, int N1>
struct VariadicEvaluate<Functor, T, kNumOutputs, N0, N1, 0, 0, 0, 0> {
static bool Call(const Functor& functor, T const *const *input, T* output) {
return functor(input[0],
input[1],
output);
}
};
template<typename Functor, typename T, int kNumOutputs, int N0>
struct VariadicEvaluate<Functor, T, kNumOutputs, N0, 0, 0, 0, 0, 0> {
static bool Call(const Functor& functor, T const *const *input, T* output) {
return functor(input[0],
output);
}
};
// This is in a struct because default template parameters on a function are not
// supported in C++03 (though it is available in C++0x). N0 through N5 are the
// dimension of the input arguments to the user supplied functor.
template <typename Functor, typename T, int kNumOutputs,
int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0, int N5=0>
struct AutoDiff {
static bool Differentiate(const Functor& functor,
T const *const *parameters,
T *function_value,
T **jacobians) {
typedef Jet<T, N0 + N1 + N2 + N3 + N4 + N5> JetT;
DCHECK_GT(N0, 0)
<< "Cost functions must have at least one parameter block.";
DCHECK((!N1 && !N2 && !N3 && !N4 && !N5) ||
((N1 > 0) && !N2 && !N3 && !N4 && !N5) ||
((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) ||
((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) ||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5) ||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0)))
<< "Zero block cannot precede a non-zero block. Block sizes are "
<< "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
<< N3 << ", " << N4 << ", " << N5;
DCHECK_GT(kNumOutputs, 0);
FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(
N0 + N1 + N2 + N3 + N4 + N5 + kNumOutputs);
// It's ugly, but it works.
const int jet0 = 0;
const int jet1 = N0;
const int jet2 = N0 + N1;
const int jet3 = N0 + N1 + N2;
const int jet4 = N0 + N1 + N2 + N3;
const int jet5 = N0 + N1 + N2 + N3 + N4;
const int jet6 = N0 + N1 + N2 + N3 + N4 + N5;
const JetT *unpacked_parameters[6] = {
x.get() + jet0,
x.get() + jet1,
x.get() + jet2,
x.get() + jet3,
x.get() + jet4,
x.get() + jet5,
};
JetT *output = x.get() + jet6;
#define CERES_MAKE_1ST_ORDER_PERTURBATION(i) \
if (N ## i) { \
internal::Make1stOrderPerturbation(jet ## i, \
N ## i, \
parameters[i], \
x.get() + jet ## i); \
}
CERES_MAKE_1ST_ORDER_PERTURBATION(0);
CERES_MAKE_1ST_ORDER_PERTURBATION(1);
CERES_MAKE_1ST_ORDER_PERTURBATION(2);
CERES_MAKE_1ST_ORDER_PERTURBATION(3);
CERES_MAKE_1ST_ORDER_PERTURBATION(4);
CERES_MAKE_1ST_ORDER_PERTURBATION(5);
#undef CERES_MAKE_1ST_ORDER_PERTURBATION
if (!VariadicEvaluate<Functor, JetT, kNumOutputs,
N0, N1, N2, N3, N4, N5>::Call(
functor, unpacked_parameters, output)) {
return false;
}
internal::Take0thOrderPart(kNumOutputs, output, function_value);
#define CERES_TAKE_1ST_ORDER_PERTURBATION(i) \
if (N ## i) { \
if (jacobians[i]) { \
internal::Take1stOrderPart<JetT, T, \
kNumOutputs, \
jet ## i, \
N ## i>(output, \
jacobians[i]); \
} \
}
CERES_TAKE_1ST_ORDER_PERTURBATION(0);
CERES_TAKE_1ST_ORDER_PERTURBATION(1);
CERES_TAKE_1ST_ORDER_PERTURBATION(2);
CERES_TAKE_1ST_ORDER_PERTURBATION(3);
CERES_TAKE_1ST_ORDER_PERTURBATION(4);
CERES_TAKE_1ST_ORDER_PERTURBATION(5);
#undef CERES_TAKE_1ST_ORDER_PERTURBATION
return true;
}
};
} // namespace internal
} // namespace ceres
#endif // CERES_PUBLIC_INTERNAL_AUTODIFF_H_

@ -0,0 +1,80 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_INTERNAL_EIGEN_H_
#define CERES_INTERNAL_EIGEN_H_
#include "Eigen/Core"
namespace ceres {
using Eigen::Dynamic;
using Eigen::RowMajor;
typedef Eigen::Matrix<double, Dynamic, 1> Vector;
typedef Eigen::Matrix<double, Dynamic, Dynamic, RowMajor> Matrix;
typedef Eigen::Map<Vector> VectorRef;
typedef Eigen::Map<Matrix> MatrixRef;
typedef Eigen::Map<Matrix, Eigen::Aligned> AlignedMatrixRef;
typedef Eigen::Map<const Vector> ConstVectorRef;
typedef Eigen::Map<const Matrix, Eigen::Aligned> ConstAlignedMatrixRef;
typedef Eigen::Map<const Matrix> ConstMatrixRef;
// C++ does not support templated typdefs, thus the need for this
// struct so that we can support statically sized Matrix and Maps.
template <int num_rows = Eigen::Dynamic, int num_cols = Eigen::Dynamic>
struct EigenTypes {
typedef Eigen::Matrix <double, num_rows, num_cols, RowMajor>
Matrix;
typedef Eigen::Map<
Eigen::Matrix<double, num_rows, num_cols, RowMajor> >
MatrixRef;
typedef Eigen::Matrix <double, num_rows, 1>
Vector;
typedef Eigen::Map <
Eigen::Matrix<double, num_rows, 1> >
VectorRef;
typedef Eigen::Map<
const Eigen::Matrix<double, num_rows, num_cols, RowMajor> >
ConstMatrixRef;
typedef Eigen::Map <
const Eigen::Matrix<double, num_rows, 1> >
ConstVectorRef;
};
} // namespace ceres
#endif // CERES_INTERNAL_EIGEN_H_

@ -0,0 +1,193 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: rennie@google.com (Jeffrey Rennie)
// Author: sanjay@google.com (Sanjay Ghemawat) -- renamed to FixedArray
#ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
#define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
#include <cstddef>
#include <glog/logging.h>
#include "ceres/internal/manual_constructor.h"
namespace ceres {
namespace internal {
// A FixedArray<T> represents a non-resizable array of T where the
// length of the array does not need to be a compile time constant.
//
// FixedArray allocates small arrays inline, and large arrays on
// the heap. It is a good replacement for non-standard and deprecated
// uses of alloca() and variable length arrays (a GCC extension).
//
// FixedArray keeps performance fast for small arrays, because it
// avoids heap operations. It also helps reduce the chances of
// accidentally overflowing your stack if large input is passed to
// your function.
//
// Also, FixedArray is useful for writing portable code. Not all
// compilers support arrays of dynamic size.
// Most users should not specify an inline_elements argument and let
// FixedArray<> automatically determine the number of elements
// to store inline based on sizeof(T).
//
// If inline_elements is specified, the FixedArray<> implementation
// will store arrays of length <= inline_elements inline.
//
// Finally note that unlike vector<T> FixedArray<T> will not zero-initialize
// simple types like int, double, bool, etc.
//
// Non-POD types will be default-initialized just like regular vectors or
// arrays.
#if defined(_WIN64)
typedef __int64 ssize_t;
#elif defined(_WIN32)
typedef __int32 ssize_t;
#endif
template <typename T, ssize_t inline_elements = -1>
class FixedArray {
public:
// For playing nicely with stl:
typedef T value_type;
typedef T* iterator;
typedef T const* const_iterator;
typedef T& reference;
typedef T const& const_reference;
typedef T* pointer;
typedef std::ptrdiff_t difference_type;
typedef size_t size_type;
// REQUIRES: n >= 0
// Creates an array object that can store "n" elements.
//
// FixedArray<T> will not zero-initialiaze POD (simple) types like int,
// double, bool, etc.
// Non-POD types will be default-initialized just like regular vectors or
// arrays.
explicit FixedArray(size_type n);
// Releases any resources.
~FixedArray();
// Returns the length of the array.
inline size_type size() const { return size_; }
// Returns the memory size of the array in bytes.
inline size_t memsize() const { return size_ * sizeof(T); }
// Returns a pointer to the underlying element array.
inline const T* get() const { return &array_[0].element; }
inline T* get() { return &array_[0].element; }
// REQUIRES: 0 <= i < size()
// Returns a reference to the "i"th element.
inline T& operator[](size_type i) {
DCHECK_GE(i, 0);
DCHECK_LT(i, size_);
return array_[i].element;
}
// REQUIRES: 0 <= i < size()
// Returns a reference to the "i"th element.
inline const T& operator[](size_type i) const {
DCHECK_GE(i, 0);
DCHECK_LT(i, size_);
return array_[i].element;
}
inline iterator begin() { return &array_[0].element; }
inline iterator end() { return &array_[size_].element; }
inline const_iterator begin() const { return &array_[0].element; }
inline const_iterator end() const { return &array_[size_].element; }
private:
// Container to hold elements of type T. This is necessary to handle
// the case where T is a a (C-style) array. The size of InnerContainer
// and T must be the same, otherwise callers' assumptions about use
// of this code will be broken.
struct InnerContainer {
T element;
};
// How many elements should we store inline?
// a. If not specified, use a default of 256 bytes (256 bytes
// seems small enough to not cause stack overflow or unnecessary
// stack pollution, while still allowing stack allocation for
// reasonably long character arrays.
// b. Never use 0 length arrays (not ISO C++)
static const size_type S1 = ((inline_elements < 0)
? (256/sizeof(T)) : inline_elements);
static const size_type S2 = (S1 <= 0) ? 1 : S1;
static const size_type kInlineElements = S2;
size_type const size_;
InnerContainer* const array_;
// Allocate some space, not an array of elements of type T, so that we can
// skip calling the T constructors and destructors for space we never use.
ManualConstructor<InnerContainer> inline_space_[kInlineElements];
};
// Implementation details follow
template <class T, ssize_t S>
inline FixedArray<T, S>::FixedArray(typename FixedArray<T, S>::size_type n)
: size_(n),
array_((n <= kInlineElements
? reinterpret_cast<InnerContainer*>(inline_space_)
: new InnerContainer[n])) {
DCHECK_GE(n, 0);
// Construct only the elements actually used.
if (array_ == reinterpret_cast<InnerContainer*>(inline_space_)) {
for (int i = 0; i != size_; ++i) {
inline_space_[i].Init();
}
}
}
template <class T, ssize_t S>
inline FixedArray<T, S>::~FixedArray() {
if (array_ != reinterpret_cast<InnerContainer*>(inline_space_)) {
delete[] array_;
} else {
for (int i = 0; i != size_; ++i) {
inline_space_[i].Destroy();
}
}
}
} // namespace internal
} // namespace ceres
#endif // CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_

@ -0,0 +1,154 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//
// Various Google-specific macros.
//
// This code is compiled directly on many platforms, including client
// platforms like Windows, Mac, and embedded systems. Before making
// any changes here, make sure that you're not breaking any platforms.
#ifndef CERES_PUBLIC_INTERNAL_MACROS_H_
#define CERES_PUBLIC_INTERNAL_MACROS_H_
#include <cstddef> // For size_t.
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
//
// For disallowing only assign or copy, write the code directly, but declare
// the intend in a comment, for example:
// void operator=(const TypeName&); // DISALLOW_ASSIGN
// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
// semantically, one should either use disallow both or neither. Try to
// avoid these in new code.
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
DISALLOW_COPY_AND_ASSIGN(TypeName)
// The arraysize(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
// used in defining new arrays, for example. If you use arraysize on
// a pointer by mistake, you will get a compile-time error.
//
// One caveat is that arraysize() doesn't accept any array of an
// anonymous type or a type defined inside a function. In these rare
// cases, you have to use the unsafe ARRAYSIZE() macro below. This is
// due to a limitation in C++'s template system. The limitation might
// eventually be removed, but it hasn't happened yet.
// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
// That gcc wants both of these prototypes seems mysterious. VC, for
// its part, can't decide which to use (another mystery). Matching of
// template overloads: the final frontier.
#ifndef _WIN32
template <typename T, size_t N>
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
// ARRAYSIZE performs essentially the same calculation as arraysize,
// but can be used on anonymous types or types defined inside
// functions. It's less safe than arraysize as it accepts some
// (although not all) pointers. Therefore, you should use arraysize
// whenever possible.
//
// The expression ARRAYSIZE(a) is a compile-time constant of type
// size_t.
//
// ARRAYSIZE catches a few type errors. If you see a compiler error
//
// "warning: division by zero in ..."
//
// when using ARRAYSIZE, you are (wrongfully) giving it a pointer.
// You should only use ARRAYSIZE on statically allocated arrays.
//
// The following comments are on the implementation details, and can
// be ignored by the users.
//
// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
// the array) and sizeof(*(arr)) (the # of bytes in one array
// element). If the former is divisible by the latter, perhaps arr is
// indeed an array, in which case the division result is the # of
// elements in the array. Otherwise, arr cannot possibly be an array,
// and we generate a compiler error to prevent the code from
// compiling.
//
// Since the size of bool is implementation-defined, we need to cast
// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
// result has type size_t.
//
// This macro is not perfect as it wrongfully accepts certain
// pointers, namely where the pointer size is divisible by the pointee
// size. Since all our code has to go through a 32-bit compiler,
// where a pointer is 4 bytes, this means all pointers to a type whose
// size is 3 or greater than 4 will be (righteously) rejected.
//
// Kudos to Jorg Brown for this simple and elegant implementation.
//
// - wan 2005-11-16
//
// Starting with Visual C++ 2005, WinNT.h includes ARRAYSIZE. However,
// the definition comes from the over-broad windows.h header that
// introduces a macro, ERROR, that conflicts with the logging framework
// that Ceres uses. Instead, rename ARRAYSIZE to CERES_ARRAYSIZE.
#define CERES_ARRAYSIZE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
// Tell the compiler to warn about unused return values for functions declared
// with this macro. The macro should be used on function declarations
// following the argument list:
//
// Sprocket* AllocateSprocket() MUST_USE_RESULT;
//
#undef MUST_USE_RESULT
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) \
&& !defined(COMPILER_ICC)
#define MUST_USE_RESULT __attribute__ ((warn_unused_result))
#else
#define MUST_USE_RESULT
#endif
#endif // CERES_PUBLIC_INTERNAL_MACROS_H_

@ -0,0 +1,214 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: kenton@google.com (Kenton Varda)
//
// ManualConstructor statically-allocates space in which to store some
// object, but does not initialize it. You can then call the constructor
// and destructor for the object yourself as you see fit. This is useful
// for memory management optimizations, where you want to initialize and
// destroy an object multiple times but only allocate it once.
//
// (When I say ManualConstructor statically allocates space, I mean that
// the ManualConstructor object itself is forced to be the right size.)
#ifndef CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
#define CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
#include <new>
namespace ceres {
namespace internal {
// ------- Define ALIGNED_CHAR_ARRAY --------------------------------
#ifndef ALIGNED_CHAR_ARRAY
// Because MSVC and older GCCs require that the argument to their alignment
// construct to be a literal constant integer, we use a template instantiated
// at all the possible powers of two.
template<int alignment, int size> struct AlignType { };
template<int size> struct AlignType<0, size> { typedef char result[size]; };
#if defined(_MSC_VER)
#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __declspec(align(X))
#define BASE_PORT_H_ALIGN_OF(T) __alignof(T)
#elif defined(__GNUC__)
#define BASE_PORT_H_ALIGN_ATTRIBUTE(X) __attribute__((aligned(X)))
#define BASE_PORT_H_ALIGN_OF(T) __alignof__(T)
#endif
#if defined(BASE_PORT_H_ALIGN_ATTRIBUTE)
#define BASE_PORT_H_ALIGNTYPE_TEMPLATE(X) \
template<int size> struct AlignType<X, size> { \
typedef BASE_PORT_H_ALIGN_ATTRIBUTE(X) char result[size]; \
}
BASE_PORT_H_ALIGNTYPE_TEMPLATE(1);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(2);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(4);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(8);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(16);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(32);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(64);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(128);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(256);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(512);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(1024);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(2048);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(4096);
BASE_PORT_H_ALIGNTYPE_TEMPLATE(8192);
// Any larger and MSVC++ will complain.
#define ALIGNED_CHAR_ARRAY(T, Size) \
typename AlignType<BASE_PORT_H_ALIGN_OF(T), sizeof(T) * Size>::result
#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE
#undef BASE_PORT_H_ALIGN_ATTRIBUTE
#else // defined(BASE_PORT_H_ALIGN_ATTRIBUTE)
#define ALIGNED_CHAR_ARRAY you_must_define_ALIGNED_CHAR_ARRAY_for_your_compiler
#endif // defined(BASE_PORT_H_ALIGN_ATTRIBUTE)
#undef BASE_PORT_H_ALIGNTYPE_TEMPLATE
#undef BASE_PORT_H_ALIGN_ATTRIBUTE
#endif // ALIGNED_CHAR_ARRAY
template <typename Type>
class ManualConstructor {
public:
// No constructor or destructor because one of the most useful uses of
// this class is as part of a union, and members of a union cannot have
// constructors or destructors. And, anyway, the whole point of this
// class is to bypass these.
inline Type* get() {
return reinterpret_cast<Type*>(space_);
}
inline const Type* get() const {
return reinterpret_cast<const Type*>(space_);
}
inline Type* operator->() { return get(); }
inline const Type* operator->() const { return get(); }
inline Type& operator*() { return *get(); }
inline const Type& operator*() const { return *get(); }
// You can pass up to four constructor arguments as arguments of Init().
inline void Init() {
new(space_) Type;
}
template <typename T1>
inline void Init(const T1& p1) {
new(space_) Type(p1);
}
template <typename T1, typename T2>
inline void Init(const T1& p1, const T2& p2) {
new(space_) Type(p1, p2);
}
template <typename T1, typename T2, typename T3>
inline void Init(const T1& p1, const T2& p2, const T3& p3) {
new(space_) Type(p1, p2, p3);
}
template <typename T1, typename T2, typename T3, typename T4>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
new(space_) Type(p1, p2, p3, p4);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5) {
new(space_) Type(p1, p2, p3, p4, p5);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6) {
new(space_) Type(p1, p2, p3, p4, p5, p6);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9, const T10& p10) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
}
template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10,
typename T11>
inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
const T5& p5, const T6& p6, const T7& p7, const T8& p8,
const T9& p9, const T10& p10, const T11& p11) {
new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
}
inline void Destroy() {
get()->~Type();
}
private:
ALIGNED_CHAR_ARRAY(Type, 1) space_;
};
#undef ALIGNED_CHAR_ARRAY
} // namespace internal
} // namespace ceres
#endif // CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_

@ -0,0 +1,44 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#ifndef CERES_PUBLIC_INTERNAL_PORT_H_
#define CERES_PUBLIC_INTERNAL_PORT_H_
namespace ceres {
// It is unfortunate that this import of the entire standard namespace is
// necessary. The reasons are historical and won't be explained here, but
// suffice to say it is not a mistake and can't be removed without breaking
// things outside of the Ceres optimization package.
using namespace std;
} // namespace ceres
#endif // CERES_PUBLIC_INTERNAL_PORT_H_

@ -0,0 +1,311 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: jorg@google.com (Jorg Brown)
//
// This is an implementation designed to match the anticipated future TR2
// implementation of the scoped_ptr class, and its closely-related brethren,
// scoped_array, scoped_ptr_malloc, and make_scoped_ptr.
#ifndef CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_
#define CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_
#include <assert.h>
#include <stdlib.h>
#include <cstddef>
namespace ceres {
namespace internal {
template <class C> class scoped_ptr;
template <class C, class Free> class scoped_ptr_malloc;
template <class C> class scoped_array;
template <class C>
scoped_ptr<C> make_scoped_ptr(C *);
// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
// automatically deletes the pointer it holds (if any). That is, scoped_ptr<T>
// owns the T object that it points to. Like a T*, a scoped_ptr<T> may hold
// either NULL or a pointer to a T object. Also like T*, scoped_ptr<T> is
// thread-compatible, and once you dereference it, you get the threadsafety
// guarantees of T.
//
// The size of a scoped_ptr is small: sizeof(scoped_ptr<C>) == sizeof(C*)
template <class C>
class scoped_ptr {
public:
// The element type
typedef C element_type;
// Constructor. Defaults to intializing with NULL.
// There is no way to create an uninitialized scoped_ptr.
// The input parameter must be allocated with new.
explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
// Destructor. If there is a C object, delete it.
// We don't need to test ptr_ == NULL because C++ does that for us.
~scoped_ptr() {
enum { type_must_be_complete = sizeof(C) };
delete ptr_;
}
// Reset. Deletes the current owned object, if any.
// Then takes ownership of a new object, if given.
// this->reset(this->get()) works.
void reset(C* p = NULL) {
if (p != ptr_) {
enum { type_must_be_complete = sizeof(C) };
delete ptr_;
ptr_ = p;
}
}
// Accessors to get the owned object.
// operator* and operator-> will assert() if there is no current object.
C& operator*() const {
assert(ptr_ != NULL);
return *ptr_;
}
C* operator->() const {
assert(ptr_ != NULL);
return ptr_;
}
C* get() const { return ptr_; }
// Comparison operators.
// These return whether a scoped_ptr and a raw pointer refer to
// the same object, not just to two different but equal objects.
bool operator==(const C* p) const { return ptr_ == p; }
bool operator!=(const C* p) const { return ptr_ != p; }
// Swap two scoped pointers.
void swap(scoped_ptr& p2) {
C* tmp = ptr_;
ptr_ = p2.ptr_;
p2.ptr_ = tmp;
}
// Release a pointer.
// The return value is the current pointer held by this object.
// If this object holds a NULL pointer, the return value is NULL.
// After this operation, this object will hold a NULL pointer,
// and will not own the object any more.
C* release() {
C* retVal = ptr_;
ptr_ = NULL;
return retVal;
}
private:
C* ptr_;
// google3 friend class that can access copy ctor (although if it actually
// calls a copy ctor, there will be a problem) see below
friend scoped_ptr<C> make_scoped_ptr<C>(C *p);
// Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
// make sense, and if C2 == C, it still doesn't make sense because you should
// never have the same object owned by two different scoped_ptrs.
template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
// Disallow evil constructors
scoped_ptr(const scoped_ptr&);
void operator=(const scoped_ptr&);
};
// Free functions
template <class C>
inline void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) {
p1.swap(p2);
}
template <class C>
inline bool operator==(const C* p1, const scoped_ptr<C>& p2) {
return p1 == p2.get();
}
template <class C>
inline bool operator==(const C* p1, const scoped_ptr<const C>& p2) {
return p1 == p2.get();
}
template <class C>
inline bool operator!=(const C* p1, const scoped_ptr<C>& p2) {
return p1 != p2.get();
}
template <class C>
inline bool operator!=(const C* p1, const scoped_ptr<const C>& p2) {
return p1 != p2.get();
}
template <class C>
scoped_ptr<C> make_scoped_ptr(C *p) {
// This does nothing but to return a scoped_ptr of the type that the passed
// pointer is of. (This eliminates the need to specify the name of T when
// making a scoped_ptr that is used anonymously/temporarily.) From an
// access control point of view, we construct an unnamed scoped_ptr here
// which we return and thus copy-construct. Hence, we need to have access
// to scoped_ptr::scoped_ptr(scoped_ptr const &). However, it is guaranteed
// that we never actually call the copy constructor, which is a good thing
// as we would call the temporary's object destructor (and thus delete p)
// if we actually did copy some object, here.
return scoped_ptr<C>(p);
}
// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
// with new [] and the destructor deletes objects with delete [].
//
// As with scoped_ptr<C>, a scoped_array<C> either points to an object
// or is NULL. A scoped_array<C> owns the object that it points to.
// scoped_array<T> is thread-compatible, and once you index into it,
// the returned objects have only the threadsafety guarantees of T.
//
// Size: sizeof(scoped_array<C>) == sizeof(C*)
template <class C>
class scoped_array {
public:
// The element type
typedef C element_type;
// Constructor. Defaults to intializing with NULL.
// There is no way to create an uninitialized scoped_array.
// The input parameter must be allocated with new [].
explicit scoped_array(C* p = NULL) : array_(p) { }
// Destructor. If there is a C object, delete it.
// We don't need to test ptr_ == NULL because C++ does that for us.
~scoped_array() {
enum { type_must_be_complete = sizeof(C) };
delete[] array_;
}
// Reset. Deletes the current owned object, if any.
// Then takes ownership of a new object, if given.
// this->reset(this->get()) works.
void reset(C* p = NULL) {
if (p != array_) {
enum { type_must_be_complete = sizeof(C) };
delete[] array_;
array_ = p;
}
}
// Get one element of the current object.
// Will assert() if there is no current object, or index i is negative.
C& operator[](std::ptrdiff_t i) const {
assert(i >= 0);
assert(array_ != NULL);
return array_[i];
}
// Get a pointer to the zeroth element of the current object.
// If there is no current object, return NULL.
C* get() const {
return array_;
}
// Comparison operators.
// These return whether a scoped_array and a raw pointer refer to
// the same array, not just to two different but equal arrays.
bool operator==(const C* p) const { return array_ == p; }
bool operator!=(const C* p) const { return array_ != p; }
// Swap two scoped arrays.
void swap(scoped_array& p2) {
C* tmp = array_;
array_ = p2.array_;
p2.array_ = tmp;
}
// Release an array.
// The return value is the current pointer held by this object.
// If this object holds a NULL pointer, the return value is NULL.
// After this operation, this object will hold a NULL pointer,
// and will not own the object any more.
C* release() {
C* retVal = array_;
array_ = NULL;
return retVal;
}
private:
C* array_;
// Forbid comparison of different scoped_array types.
template <class C2> bool operator==(scoped_array<C2> const& p2) const;
template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
// Disallow evil constructors
scoped_array(const scoped_array&);
void operator=(const scoped_array&);
};
// Free functions
template <class C>
inline void swap(scoped_array<C>& p1, scoped_array<C>& p2) {
p1.swap(p2);
}
template <class C>
inline bool operator==(const C* p1, const scoped_array<C>& p2) {
return p1 == p2.get();
}
template <class C>
inline bool operator==(const C* p1, const scoped_array<const C>& p2) {
return p1 == p2.get();
}
template <class C>
inline bool operator!=(const C* p1, const scoped_array<C>& p2) {
return p1 != p2.get();
}
template <class C>
inline bool operator!=(const C* p1, const scoped_array<const C>& p2) {
return p1 != p2.get();
}
// This class wraps the c library function free() in a class that can be
// passed as a template argument to scoped_ptr_malloc below.
class ScopedPtrMallocFree {
public:
inline void operator()(void* x) const {
free(x);
}
};
} // namespace internal
} // namespace ceres
#endif // CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_

@ -0,0 +1,159 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// When an iteration callback is specified, Ceres calls the callback after each
// optimizer step and pass it an IterationSummary object, defined below.
#ifndef CERES_PUBLIC_ITERATION_CALLBACK_H_
#define CERES_PUBLIC_ITERATION_CALLBACK_H_
#include "ceres/types.h"
namespace ceres {
// This struct describes the state of the optimizer after each
// iteration of the minimization.
struct IterationSummary {
// Current iteration number.
int32 iteration;
// Whether or not the algorithm made progress in this iteration.
bool step_is_successful;
// Value of the objective function.
double cost;
// Change in the value of the objective function in this
// iteration. This can be positive or negative. Negative change
// means that the step was not successful.
double cost_change;
// Infinity norm of the gradient vector.
double gradient_max_norm;
// 2-norm of the size of the step computed by the optimization
// algorithm.
double step_norm;
// For trust region algorithms, the ratio of the actual change in
// cost and the change in the cost of the linearized approximation.
double relative_decrease;
// Value of the regularization parameter for Levenberg-Marquardt
// algorithm at the end of the current iteration.
double mu;
// For the inexact step Levenberg-Marquardt algorithm, this is the
// relative accuracy with which the Newton(LM) step is solved. This
// number affects only the iterative solvers capable of solving
// linear systems inexactly. Factorization-based exact solvers
// ignore it.
double eta;
// Number of iterations taken by the linear solver to solve for the
// Newton step.
int linear_solver_iterations;
// TODO(sameeragarwal): Change to use a higher precision timer using
// clock_gettime.
// Time (in seconds) spent inside the linear least squares solver.
int iteration_time_sec;
// Time (in seconds) spent inside the linear least squares solver.
int linear_solver_time_sec;
};
// Interface for specifying callbacks that are executed at the end of
// each iteration of the Minimizer. The solver uses the return value
// of operator() to decide whether to continue solving or to
// terminate. The user can return three values.
//
// SOLVER_ABORT indicates that the callback detected an abnormal
// situation. The solver returns without updating the parameter blocks
// (unless Solver::Options::update_state_every_iteration is set
// true). Solver returns with Solver::Summary::termination_type set to
// USER_ABORT.
//
// SOLVER_TERMINATE_SUCCESSFULLY indicates that there is no need to
// optimize anymore (some user specified termination criterion has
// been met). Solver returns with Solver::Summary::termination_type
// set to USER_SUCCESS.
//
// SOLVER_CONTINUE indicates that the solver should continue
// optimizing.
//
// For example, the following Callback is used internally by Ceres to
// log the progress of the optimization.
//
// Callback for logging the state of the minimizer to STDERR or STDOUT
// depending on the user's preferences and logging level.
//
// class LoggingCallback : public IterationCallback {
// public:
// explicit LoggingCallback(bool log_to_stdout)
// : log_to_stdout_(log_to_stdout) {}
//
// ~LoggingCallback() {}
//
// CallbackReturnType operator()(const IterationSummary& summary) {
// const char* kReportRowFormat =
// "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e "
// "rho:% 3.2e mu:% 3.2e eta:% 3.2e li:% 3d";
// string output = StringPrintf(kReportRowFormat,
// summary.iteration,
// summary.cost,
// summary.cost_change,
// summary.gradient_max_norm,
// summary.step_norm,
// summary.relative_decrease,
// summary.mu,
// summary.eta,
// summary.linear_solver_iterations);
// if (log_to_stdout_) {
// cout << output << endl;
// } else {
// VLOG(1) << output;
// }
// return SOLVER_CONTINUE;
// }
//
// private:
// const bool log_to_stdout_;
// };
//
class IterationCallback {
public:
virtual ~IterationCallback() {}
virtual CallbackReturnType operator()(const IterationSummary& summary) = 0;
};
} // namespace ceres
#endif // CERES_PUBLIC_ITERATION_CALLBACK_H_

@ -0,0 +1,671 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// A simple implementation of N-dimensional dual numbers, for automatically
// computing exact derivatives of functions.
//
// While a complete treatment of the mechanics of automatic differentation is
// beyond the scope of this header (see
// http://en.wikipedia.org/wiki/Automatic_differentiation for details), the
// basic idea is to extend normal arithmetic with an extra element, "e," often
// denoted with the greek symbol epsilon, such that e != 0 but e^2 = 0. Dual
// numbers are extensions of the real numbers analogous to complex numbers:
// whereas complex numbers augment the reals by introducing an imaginary unit i
// such that i^2 = -1, dual numbers introduce an "infinitesimal" unit e such
// that e^2 = 0. Dual numbers have two components: the "real" component and the
// "infinitesimal" component, generally written as x + y*e. Surprisingly, this
// leads to a convenient method for computing exact derivatives without needing
// to manipulate complicated symbolic expressions.
//
// For example, consider the function
//
// f(x) = x^2 ,
//
// evaluated at 10. Using normal arithmetic, f(10) = 100, and df/dx(10) = 20.
// Next, augument 10 with an infinitesimal to get:
//
// f(10 + e) = (10 + e)^2
// = 100 + 2 * 10 * e + e^2
// = 100 + 20 * e -+-
// -- |
// | +--- This is zero, since e^2 = 0
// |
// +----------------- This is df/dx!
//
// Note that the derivative of f with respect to x is simply the infinitesimal
// component of the value of f(x + e). So, in order to take the derivative of
// any function, it is only necessary to replace the numeric "object" used in
// the function with one extended with infinitesimals. The class Jet, defined in
// this header, is one such example of this, where substitution is done with
// templates.
//
// To handle derivatives of functions taking multiple arguments, different
// infinitesimals are used, one for each variable to take the derivative of. For
// example, consider a scalar function of two scalar parameters x and y:
//
// f(x, y) = x^2 + x * y
//
// Following the technique above, to compute the derivatives df/dx and df/dy for
// f(1, 3) involves doing two evaluations of f, the first time replacing x with
// x + e, the second time replacing y with y + e.
//
// For df/dx:
//
// f(1 + e, y) = (1 + e)^2 + (1 + e) * 3
// = 1 + 2 * e + 3 + 3 * e
// = 4 + 5 * e
//
// --> df/dx = 5
//
// For df/dy:
//
// f(1, 3 + e) = 1^2 + 1 * (3 + e)
// = 1 + 3 + e
// = 4 + e
//
// --> df/dy = 1
//
// To take the gradient of f with the implementation of dual numbers ("jets") in
// this file, it is necessary to create a single jet type which has components
// for the derivative in x and y, and passing them to a templated version of f:
//
// template<typename T>
// T f(const T &x, const T &y) {
// return x * x + x * y;
// }
//
// // The "2" means there should be 2 dual number components.
// Jet<double, 2> x(0); // Pick the 0th dual number for x.
// Jet<double, 2> y(1); // Pick the 1st dual number for y.
// Jet<double, 2> z = f(x, y);
//
// LG << "df/dx = " << z.a[0]
// << "df/dy = " << z.a[1];
//
// Most users should not use Jet objects directly; a wrapper around Jet objects,
// which makes computing the derivative, gradient, or jacobian of templated
// functors simple, is in autodiff.h. Even autodiff.h should not be used
// directly; instead autodiff_cost_function.h is typically the file of interest.
//
// For the more mathematically inclined, this file implements first-order
// "jets". A 1st order jet is an element of the ring
//
// T[N] = T[t_1, ..., t_N] / (t_1, ..., t_N)^2
//
// which essentially means that each jet consists of a "scalar" value 'a' from T
// and a 1st order perturbation vector 'v' of length N:
//
// x = a + \sum_i v[i] t_i
//
// A shorthand is to write an element as x = a + u, where u is the pertubation.
// Then, the main point about the arithmetic of jets is that the product of
// perturbations is zero:
//
// (a + u) * (b + v) = ab + av + bu + uv
// = ab + (av + bu) + 0
//
// which is what operator* implements below. Addition is simpler:
//
// (a + u) + (b + v) = (a + b) + (u + v).
//
// The only remaining question is how to evaluate the function of a jet, for
// which we use the chain rule:
//
// f(a + u) = f(a) + f'(a) u
//
// where f'(a) is the (scalar) derivative of f at a.
//
// By pushing these things through sufficiently and suitably templated
// functions, we can do automatic differentiation. Just be sure to turn on
// function inlining and common-subexpression elimination, or it will be very
// slow!
//
// WARNING: Most Ceres users should not directly include this file or know the
// details of how jets work. Instead the suggested method for automatic
// derivatives is to use autodiff_cost_function.h, which is a wrapper around
// both jets.h and autodiff.h to make taking derivatives of cost functions for
// use in Ceres easier.
#ifndef CERES_PUBLIC_JET_H_
#define CERES_PUBLIC_JET_H_
#include <cmath>
#include <iosfwd>
#include <iostream> // NOLINT
#include <string>
#include "Eigen/Core"
// Visual Studio 2010 or older version
#if defined(_MSC_VER) && _MSC_VER <= 1600
namespace std {
inline bool isfinite(double x) { return _finite(x); }
inline bool isinf (double x) { return !_finite(x) && !_isnan(x); }
inline bool isnan (double x) { return _isnan(x); }
inline bool isnormal(double x) { return _finite(x) && x != 0.0; }
} // namespace std
#endif
namespace ceres {
template <typename T, int N>
struct Jet {
enum { DIMENSION = N };
// Default-construct "a" because otherwise this can lead to false errors about
// uninitialized uses when other classes relying on default constructed T
// (where T is a Jet<T, N>). This usually only happens in opt mode. Note that
// the C++ standard mandates that e.g. default constructed doubles are
// initialized to 0.0; see sections 8.5 of the C++03 standard.
Jet() : a() {}
// Constructor from scalar: a + 0.
explicit Jet(const T& value) {
a = value;
v.setZero();
}
// Constructor from scalar plus variable: a + t_i.
Jet(const T& value, int k) {
a = value;
v.setZero();
v[k] = T(1.0);
}
// Compound operators
Jet<T, N>& operator+=(const Jet<T, N> &y) {
*this = *this + y;
return *this;
}
Jet<T, N>& operator-=(const Jet<T, N> &y) {
*this = *this - y;
return *this;
}
Jet<T, N>& operator*=(const Jet<T, N> &y) {
*this = *this * y;
return *this;
}
Jet<T, N>& operator/=(const Jet<T, N> &y) {
*this = *this / y;
return *this;
}
T a; // The scalar part.
Eigen::Matrix<T, N, 1> v; // The infinitesimal part.
};
// Unary +
template<typename T, int N> inline
Jet<T, N> const& operator+(const Jet<T, N>& f) {
return f;
}
// TODO(keir): Try adding __attribute__((always_inline)) to these functions to
// see if it causes a performance increase.
// Unary -
template<typename T, int N> inline
Jet<T, N> operator-(const Jet<T, N>&f) {
Jet<T, N> g;
g.a = -f.a;
g.v = -f.v;
return g;
}
// Binary +
template<typename T, int N> inline
Jet<T, N> operator+(const Jet<T, N>& f,
const Jet<T, N>& g) {
Jet<T, N> h;
h.a = f.a + g.a;
h.v = f.v + g.v;
return h;
}
// Binary + with a scalar: x + s
template<typename T, int N> inline
Jet<T, N> operator+(const Jet<T, N>& f, T s) {
Jet<T, N> h;
h.a = f.a + s;
h.v = f.v;
return h;
}
// Binary + with a scalar: s + x
template<typename T, int N> inline
Jet<T, N> operator+(T s, const Jet<T, N>& f) {
Jet<T, N> h;
h.a = f.a + s;
h.v = f.v;
return h;
}
// Binary -
template<typename T, int N> inline
Jet<T, N> operator-(const Jet<T, N>& f,
const Jet<T, N>& g) {
Jet<T, N> h;
h.a = f.a - g.a;
h.v = f.v - g.v;
return h;
}
// Binary - with a scalar: x - s
template<typename T, int N> inline
Jet<T, N> operator-(const Jet<T, N>& f, T s) {
Jet<T, N> h;
h.a = f.a - s;
h.v = f.v;
return h;
}
// Binary - with a scalar: s - x
template<typename T, int N> inline
Jet<T, N> operator-(T s, const Jet<T, N>& f) {
Jet<T, N> h;
h.a = s - f.a;
h.v = -f.v;
return h;
}
// Binary *
template<typename T, int N> inline
Jet<T, N> operator*(const Jet<T, N>& f,
const Jet<T, N>& g) {
Jet<T, N> h;
h.a = f.a * g.a;
h.v = f.a * g.v + f.v * g.a;
return h;
}
// Binary * with a scalar: x * s
template<typename T, int N> inline
Jet<T, N> operator*(const Jet<T, N>& f, T s) {
Jet<T, N> h;
h.a = f.a * s;
h.v = f.v * s;
return h;
}
// Binary * with a scalar: s * x
template<typename T, int N> inline
Jet<T, N> operator*(T s, const Jet<T, N>& f) {
Jet<T, N> h;
h.a = f.a * s;
h.v = f.v * s;
return h;
}
// Binary /
template<typename T, int N> inline
Jet<T, N> operator/(const Jet<T, N>& f,
const Jet<T, N>& g) {
Jet<T, N> h;
// This uses:
//
// a + u (a + u)(b - v) (a + u)(b - v)
// ----- = -------------- = --------------
// b + v (b + v)(b - v) b^2
//
// which holds because v*v = 0.
h.a = f.a / g.a;
h.v = (f.v - f.a / g.a * g.v) / g.a;
return h;
}
// Binary / with a scalar: s / x
template<typename T, int N> inline
Jet<T, N> operator/(T s, const Jet<T, N>& g) {
Jet<T, N> h;
h.a = s / g.a;
h.v = - s * g.v / (g.a * g.a);
return h;
}
// Binary / with a scalar: x / s
template<typename T, int N> inline
Jet<T, N> operator/(const Jet<T, N>& f, T s) {
Jet<T, N> h;
h.a = f.a / s;
h.v = f.v / s;
return h;
}
// Binary comparison operators for both scalars and jets.
#define CERES_DEFINE_JET_COMPARISON_OPERATOR(op) \
template<typename T, int N> inline \
bool operator op(const Jet<T, N>& f, const Jet<T, N>& g) { \
return f.a op g.a; \
} \
template<typename T, int N> inline \
bool operator op(const T& s, const Jet<T, N>& g) { \
return s op g.a; \
} \
template<typename T, int N> inline \
bool operator op(const Jet<T, N>& f, const T& s) { \
return f.a op s; \
}
CERES_DEFINE_JET_COMPARISON_OPERATOR( < ) // NOLINT
CERES_DEFINE_JET_COMPARISON_OPERATOR( <= ) // NOLINT
CERES_DEFINE_JET_COMPARISON_OPERATOR( > ) // NOLINT
CERES_DEFINE_JET_COMPARISON_OPERATOR( >= ) // NOLINT
CERES_DEFINE_JET_COMPARISON_OPERATOR( == ) // NOLINT
CERES_DEFINE_JET_COMPARISON_OPERATOR( != ) // NOLINT
#undef CERES_DEFINE_JET_COMPARISON_OPERATOR
// Pull some functions from namespace std.
//
// This is necessary because we want to use the same name (e.g. 'sqrt') for
// double-valued and Jet-valued functions, but we are not allowed to put
// Jet-valued functions inside namespace std.
//
// Missing: cosh, sinh, tanh, tan
// TODO(keir): Switch to "using".
inline double abs (double x) { return std::abs(x); }
inline double log (double x) { return std::log(x); }
inline double exp (double x) { return std::exp(x); }
inline double sqrt (double x) { return std::sqrt(x); }
inline double cos (double x) { return std::cos(x); }
inline double acos (double x) { return std::acos(x); }
inline double sin (double x) { return std::sin(x); }
inline double asin (double x) { return std::asin(x); }
inline bool isfinite(double x) { return std::isfinite(x); }
inline bool isinf (double x) { return std::isinf(x); }
inline bool isnan (double x) { return std::isnan(x); }
inline bool isnormal(double x) { return std::isnormal(x); }
inline double pow (double x, double y) { return std::pow(x, y); }
inline double atan2(double y, double x) { return std::atan2(y, x); }
// In general, f(a + h) ~= f(a) + f'(a) h, via the chain rule.
// abs(x + h) ~= x + h or -(x + h)
template <typename T, int N> inline
Jet<T, N> abs(const Jet<T, N>& f) {
return f.a < T(0.0) ? -f : f;
}
// log(a + h) ~= log(a) + h / a
template <typename T, int N> inline
Jet<T, N> log(const Jet<T, N>& f) {
Jet<T, N> g;
g.a = log(f.a);
g.v = f.v / f.a;
return g;
}
// exp(a + h) ~= exp(a) + exp(a) h
template <typename T, int N> inline
Jet<T, N> exp(const Jet<T, N>& f) {
Jet<T, N> g;
g.a = exp(f.a);
g.v = g.a * f.v;
return g;
}
// sqrt(a + h) ~= sqrt(a) + h / (2 sqrt(a))
template <typename T, int N> inline
Jet<T, N> sqrt(const Jet<T, N>& f) {
Jet<T, N> g;
g.a = sqrt(f.a);
g.v = f.v / (T(2.0) * g.a);
return g;
}
// cos(a + h) ~= cos(a) - sin(a) h
template <typename T, int N> inline
Jet<T, N> cos(const Jet<T, N>& f) {
Jet<T, N> g;
g.a = cos(f.a);
T sin_a = sin(f.a);
g.v = - sin_a * f.v;
return g;
}
// acos(a + h) ~= acos(a) - 1 / sqrt(1 - a^2) h
template <typename T, int N> inline
Jet<T, N> acos(const Jet<T, N>& f) {
Jet<T, N> g;
g.a = acos(f.a);
g.v = - T(1.0) / sqrt(T(1.0) - f.a * f.a) * f.v;
return g;
}
// sin(a + h) ~= sin(a) + cos(a) h
template <typename T, int N> inline
Jet<T, N> sin(const Jet<T, N>& f) {
Jet<T, N> g;
g.a = sin(f.a);
T cos_a = cos(f.a);
g.v = cos_a * f.v;
return g;
}
// asin(a + h) ~= asin(a) + 1 / sqrt(1 - a^2) h
template <typename T, int N> inline
Jet<T, N> asin(const Jet<T, N>& f) {
Jet<T, N> g;
g.a = asin(f.a);
g.v = T(1.0) / sqrt(T(1.0) - f.a * f.a) * f.v;
return g;
}
// Jet Classification. It is not clear what the appropriate semantics are for
// these classifications. This picks that isfinite and isnormal are "all"
// operations, i.e. all elements of the jet must be finite for the jet itself to
// be finite (or normal). For isnan and isinf, the answer is less clear. This
// takes a "any" approach for isnan and isinf such that if any part of a jet is
// nan or inf, then the entire jet is nan or inf. This leads to strange
// situations like a jet can be both isinf and isnan, but in practice the "any"
// semantics are the most useful for e.g. checking that derivatives are sane.
// The jet is finite if all parts of the jet are finite.
template <typename T, int N> inline
bool isfinite(const Jet<T, N>& f) {
if (!isfinite(f.a)) {
return false;
}
for (int i = 0; i < N; ++i) {
if (!isfinite(f.v[i])) {
return false;
}
}
return true;
}
// The jet is infinite if any part of the jet is infinite.
template <typename T, int N> inline
bool isinf(const Jet<T, N>& f) {
if (isinf(f.a)) {
return true;
}
for (int i = 0; i < N; i++) {
if (isinf(f.v[i])) {
return true;
}
}
return false;
}
// The jet is NaN if any part of the jet is NaN.
template <typename T, int N> inline
bool isnan(const Jet<T, N>& f) {
if (isnan(f.a)) {
return true;
}
for (int i = 0; i < N; ++i) {
if (isnan(f.v[i])) {
return true;
}
}
return false;
}
// The jet is normal if all parts of the jet are normal.
template <typename T, int N> inline
bool isnormal(const Jet<T, N>& f) {
if (!isnormal(f.a)) {
return false;
}
for (int i = 0; i < N; ++i) {
if (!isnormal(f.v[i])) {
return false;
}
}
return true;
}
// atan2(b + db, a + da) ~= atan2(b, a) + (- b da + a db) / (a^2 + b^2)
//
// In words: the rate of change of theta is 1/r times the rate of
// change of (x, y) in the positive angular direction.
template <typename T, int N> inline
Jet<T, N> atan2(const Jet<T, N>& g, const Jet<T, N>& f) {
// Note order of arguments:
//
// f = a + da
// g = b + db
Jet<T, N> out;
out.a = atan2(g.a, f.a);
T const temp = T(1.0) / (f.a * f.a + g.a * g.a);
out.v = temp * (- g.a * f.v + f.a * g.v);
return out;
}
// pow -- base is a differentiatble function, exponent is a constant.
// (a+da)^p ~= a^p + p*a^(p-1) da
template <typename T, int N> inline
Jet<T, N> pow(const Jet<T, N>& f, double g) {
Jet<T, N> out;
out.a = pow(f.a, g);
T const temp = g * pow(f.a, g - T(1.0));
out.v = temp * f.v;
return out;
}
// pow -- base is a constant, exponent is a differentiable function.
// (a)^(p+dp) ~= a^p + a^p log(a) dp
template <typename T, int N> inline
Jet<T, N> pow(double f, const Jet<T, N>& g) {
Jet<T, N> out;
out.a = pow(f, g.a);
T const temp = log(f) * out.a;
out.v = temp * g.v;
return out;
}
// pow -- both base and exponent are differentiable functions.
// (a+da)^(b+db) ~= a^b + b * a^(b-1) da + a^b log(a) * db
template <typename T, int N> inline
Jet<T, N> pow(const Jet<T, N>& f, const Jet<T, N>& g) {
Jet<T, N> out;
T const temp1 = pow(f.a, g.a);
T const temp2 = g.a * pow(f.a, g.a - T(1.0));
T const temp3 = temp1 * log(f.a);
out.a = temp1;
out.v = temp2 * f.v + temp3 * g.v;
return out;
}
// Define the helper functions Eigen needs to embed Jet types.
//
// NOTE(keir): machine_epsilon() and precision() are missing, because they don't
// work with nested template types (e.g. where the scalar is itself templated).
// Among other things, this means that decompositions of Jet's does not work,
// for example
//
// Matrix<Jet<T, N> ... > A, x, b;
// ...
// A.solve(b, &x)
//
// does not work and will fail with a strange compiler error.
//
// TODO(keir): This is an Eigen 2.0 limitation that is lifted in 3.0. When we
// switch to 3.0, also add the rest of the specialization functionality.
template<typename T, int N> inline const Jet<T, N>& ei_conj(const Jet<T, N>& x) { return x; } // NOLINT
template<typename T, int N> inline const Jet<T, N>& ei_real(const Jet<T, N>& x) { return x; } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_imag(const Jet<T, N>& ) { return Jet<T, N>(0.0); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_abs (const Jet<T, N>& x) { return fabs(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_abs2(const Jet<T, N>& x) { return x * x; } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_sqrt(const Jet<T, N>& x) { return sqrt(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_exp (const Jet<T, N>& x) { return exp(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_log (const Jet<T, N>& x) { return log(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_sin (const Jet<T, N>& x) { return sin(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_cos (const Jet<T, N>& x) { return cos(x); } // NOLINT
template<typename T, int N> inline Jet<T, N> ei_pow (const Jet<T, N>& x, Jet<T, N> y) { return pow(x, y); } // NOLINT
// Note: This has to be in the ceres namespace for argument dependent lookup to
// function correctly. Otherwise statements like CHECK_LE(x, 2.0) fail with
// strange compile errors.
template <typename T, int N>
inline std::ostream &operator<<(std::ostream &s, const Jet<T, N>& z) {
return s << "[" << z.a << " ; " << z.v.transpose() << "]";
}
} // namespace ceres
namespace Eigen {
// Creating a specialization of NumTraits enables placing Jet objects inside
// Eigen arrays, getting all the goodness of Eigen combined with autodiff.
template<typename T, int N>
struct NumTraits<ceres::Jet<T, N> > {
typedef ceres::Jet<T, N> Real;
typedef ceres::Jet<T, N> NonInteger;
typedef ceres::Jet<T, N> Nested;
static typename ceres::Jet<T, N> dummy_precision() {
return ceres::Jet<T, N>(1e-12);
}
enum {
IsComplex = 0,
IsInteger = 0,
IsSigned,
ReadCost = 1,
AddCost = 1,
// For Jet types, multiplication is more expensive than addition.
MulCost = 3,
HasFloatingPoint = 1
};
};
} // namespace Eigen
#endif // CERES_PUBLIC_JET_H_

@ -0,0 +1,189 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
// sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
#define CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_
#include <vector>
#include "ceres/internal/port.h"
namespace ceres {
// Purpose: Sometimes parameter blocks x can overparameterize a problem
//
// min f(x)
// x
//
// In that case it is desirable to choose a parameterization for the
// block itself to remove the null directions of the cost. More
// generally, if x lies on a manifold of a smaller dimension than the
// ambient space that it is embedded in, then it is numerically and
// computationally more effective to optimize it using a
// parameterization that lives in the tangent space of that manifold
// at each point.
//
// For example, a sphere in three dimensions is a 2 dimensional
// manifold, embedded in a three dimensional space. At each point on
// the sphere, the plane tangent to it defines a two dimensional
// tangent space. For a cost function defined on this sphere, given a
// point x, moving in the direction normal to the sphere at that point
// is not useful. Thus a better way to do a local optimization is to
// optimize over two dimensional vector delta in the tangent space at
// that point and then "move" to the point x + delta, where the move
// operation involves projecting back onto the sphere. Doing so
// removes a redundent dimension from the optimization, making it
// numerically more robust and efficient.
//
// More generally we can define a function
//
// x_plus_delta = Plus(x, delta),
//
// where x_plus_delta has the same size as x, and delta is of size
// less than or equal to x. The function Plus, generalizes the
// definition of vector addition. Thus it satisfies the identify
//
// Plus(x, 0) = x, for all x.
//
// A trivial version of Plus is when delta is of the same size as x
// and
//
// Plus(x, delta) = x + delta
//
// A more interesting case if x is two dimensional vector, and the
// user wishes to hold the first coordinate constant. Then, delta is a
// scalar and Plus is defined as
//
// Plus(x, delta) = x + [0] * delta
// [1]
//
// An example that occurs commonly in Structure from Motion problems
// is when camera rotations are parameterized using Quaternion. There,
// it is useful only make updates orthogonal to that 4-vector defining
// the quaternion. One way to do this is to let delta be a 3
// dimensional vector and define Plus to be
//
// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x
//
// The multiplication between the two 4-vectors on the RHS is the
// standard quaternion product.
//
// Given g and a point x, optimizing f can now be restated as
//
// min f(Plus(x, delta))
// delta
//
// Given a solution delta to this problem, the optimal value is then
// given by
//
// x* = Plus(x, delta)
//
// The class LocalParameterization defines the function Plus and its
// Jacobian which is needed to compute the Jacobian of f w.r.t delta.
class LocalParameterization {
public:
virtual ~LocalParameterization() {}
// Generalization of the addition operation,
//
// x_plus_delta = Plus(x, delta)
//
// with the condition that Plus(x, 0) = x.
virtual bool Plus(const double* x,
const double* delta,
double* x_plus_delta) const = 0;
// The jacobian of Plus(x, delta) w.r.t delta at delta = 0.
virtual bool ComputeJacobian(const double* x, double* jacobian) const = 0;
// Size of x.
virtual int GlobalSize() const = 0;
// Size of delta.
virtual int LocalSize() const = 0;
};
// Some basic parameterizations
// Identity Parameterization: Plus(x, delta) = x + delta
class IdentityParameterization : public LocalParameterization {
public:
explicit IdentityParameterization(int size);
virtual ~IdentityParameterization() {}
virtual bool Plus(const double* x,
const double* delta,
double* x_plus_delta) const;
virtual bool ComputeJacobian(const double* x,
double* jacobian) const;
virtual int GlobalSize() const { return size_; }
virtual int LocalSize() const { return size_; }
private:
const int size_;
};
// Hold a subset of the parameters inside a parameter block constant.
class SubsetParameterization : public LocalParameterization {
public:
explicit SubsetParameterization(int size,
const vector<int>& constant_parameters);
virtual ~SubsetParameterization() {}
virtual bool Plus(const double* x,
const double* delta,
double* x_plus_delta) const;
virtual bool ComputeJacobian(const double* x,
double* jacobian) const;
virtual int GlobalSize() const { return constancy_mask_.size(); }
virtual int LocalSize() const { return local_size_; }
private:
const int local_size_;
vector<int> constancy_mask_;
};
// Plus(x, delta) = [cos(|delta|), sin(|delta|) delta / |delta|] * x
// with * being the quaternion multiplication operator. Here we assume
// that the first element of the quaternion vector is the real (cos
// theta) part.
class QuaternionParameterization : public LocalParameterization {
public:
virtual ~QuaternionParameterization() {}
virtual bool Plus(const double* x,
const double* delta,
double* x_plus_delta) const;
virtual bool ComputeJacobian(const double* x,
double* jacobian) const;
virtual int GlobalSize() const { return 4; }
virtual int LocalSize() const { return 3; }
};
} // namespace ceres
#endif // CERES_PUBLIC_LOCAL_PARAMETERIZATION_H_

@ -0,0 +1,322 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// The LossFunction interface is the way users describe how residuals
// are converted to cost terms for the overall problem cost function.
// For the exact manner in which loss functions are converted to the
// overall cost for a problem, see problem.h.
//
// For least squares problem where there are no outliers and standard
// squared loss is expected, it is not necessary to create a loss
// function; instead passing a NULL to the problem when adding
// residuals implies a standard squared loss.
//
// For least squares problems where the minimization may encounter
// input terms that contain outliers, that is, completely bogus
// measurements, it is important to use a loss function that reduces
// their associated penalty.
//
// Consider a structure from motion problem. The unknowns are 3D
// points and camera parameters, and the measurements are image
// coordinates describing the expected reprojected position for a
// point in a camera. For example, we want to model the geometry of a
// street scene with fire hydrants and cars, observed by a moving
// camera with unknown parameters, and the only 3D points we care
// about are the pointy tippy-tops of the fire hydrants. Our magic
// image processing algorithm, which is responsible for producing the
// measurements that are input to Ceres, has found and matched all
// such tippy-tops in all image frames, except that in one of the
// frame it mistook a car's headlight for a hydrant. If we didn't do
// anything special (i.e. if we used a basic quadratic loss), the
// residual for the erroneous measurement will result in extreme error
// due to the quadratic nature of squared loss. This results in the
// entire solution getting pulled away from the optimimum to reduce
// the large error that would otherwise be attributed to the wrong
// measurement.
//
// Using a robust loss function, the cost for large residuals is
// reduced. In the example above, this leads to outlier terms getting
// downweighted so they do not overly influence the final solution.
//
// What cost function is best?
//
// In general, there isn't a principled way to select a robust loss
// function. The authors suggest starting with a non-robust cost, then
// only experimenting with robust loss functions if standard squared
// loss doesn't work.
#ifndef CERES_PUBLIC_LOSS_FUNCTION_H_
#define CERES_PUBLIC_LOSS_FUNCTION_H_
#include <glog/logging.h>
#include "ceres/internal/macros.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
namespace ceres {
class LossFunction {
public:
virtual ~LossFunction() {}
// For a residual vector with squared 2-norm 'sq_norm', this method
// is required to fill in the value and derivatives of the loss
// function (rho in this example):
//
// out[0] = rho(sq_norm),
// out[1] = rho'(sq_norm),
// out[2] = rho''(sq_norm),
//
// Here the convention is that the contribution of a term to the
// cost function is given by 1/2 rho(s), where
//
// s = ||residuals||^2.
//
// Calling the method with a negative value of 's' is an error and
// the implementations are not required to handle that case.
//
// Most sane choices of rho() satisfy:
//
// rho(0) = 0,
// rho'(0) = 1,
// rho'(s) < 1 in outlier region,
// rho''(s) < 0 in outlier region,
//
// so that they mimic the least squares cost for small residuals.
virtual void Evaluate(double sq_norm, double out[3]) const = 0;
};
// Some common implementations follow below.
//
// Note: in the region of interest (i.e. s < 3) we have:
// TrivialLoss >= HuberLoss >= SoftLOneLoss >= CauchyLoss
// This corresponds to no robustification.
//
// rho(s) = s
//
// At s = 0: rho = [0, 1, 0].
//
// It is not normally necessary to use this, as passing NULL for the
// loss function when building the problem accomplishes the same
// thing.
class TrivialLoss : public LossFunction {
public:
virtual void Evaluate(double, double*) const;
};
// Scaling
// -------
// Given one robustifier
// s -> rho(s)
// one can change the length scale at which robustification takes
// place, by adding a scale factor 'a' as follows:
//
// s -> a^2 rho(s / a^2).
//
// The first and second derivatives are:
//
// s -> rho'(s / a^2),
// s -> (1 / a^2) rho''(s / a^2),
//
// but the behaviour near s = 0 is the same as the original function,
// i.e.
//
// rho(s) = s + higher order terms,
// a^2 rho(s / a^2) = s + higher order terms.
//
// The scalar 'a' should be positive.
//
// The reason for the appearance of squaring is that 'a' is in the
// units of the residual vector norm whereas 's' is a squared
// norm. For applications it is more convenient to specify 'a' than
// its square. The commonly used robustifiers below are described in
// un-scaled format (a = 1) but their implementations work for any
// non-zero value of 'a'.
// Huber.
//
// rho(s) = s for s <= 1,
// rho(s) = 2 sqrt(s) - 1 for s >= 1.
//
// At s = 0: rho = [0, 1, 0].
//
// The scaling parameter 'a' corresponds to 'delta' on this page:
// http://en.wikipedia.org/wiki/Huber_Loss_Function
class HuberLoss : public LossFunction {
public:
explicit HuberLoss(double a) : a_(a), b_(a * a) { }
virtual void Evaluate(double, double*) const;
private:
const double a_;
// b = a^2.
const double b_;
};
// Soft L1, similar to Huber but smooth.
//
// rho(s) = 2 (sqrt(1 + s) - 1).
//
// At s = 0: rho = [0, 1, -1/2].
class SoftLOneLoss : public LossFunction {
public:
explicit SoftLOneLoss(double a) : b_(a * a), c_(1 / b_) { }
virtual void Evaluate(double, double*) const;
private:
// b = a^2.
const double b_;
// c = 1 / a^2.
const double c_;
};
// Inspired by the Cauchy distribution
//
// rho(s) = log(1 + s).
//
// At s = 0: rho = [0, 1, -1].
class CauchyLoss : public LossFunction {
public:
explicit CauchyLoss(double a) : b_(a * a), c_(1 / b_) { }
virtual void Evaluate(double, double*) const;
private:
// b = a^2.
const double b_;
// c = 1 / a^2.
const double c_;
};
// The discussion above has to do with length scaling: it affects the space
// in which s is measured. Sometimes you want to simply scale the output
// value of the robustifier. For example, you might want to weight
// different error terms differently (e.g., weight pixel reprojection
// errors differently from terrain errors).
//
// If rho is the wrapped robustifier, then this simply outputs
// s -> a * rho(s)
//
// The first and second derivatives are, not surprisingly
// s -> a * rho'(s)
// s -> a * rho''(s)
//
// Since we treat the a NULL Loss function as the Identity loss
// function, rho = NULL is a valid input and will result in the input
// being scaled by a. This provides a simple way of implementing a
// scaled ResidualBlock.
class ScaledLoss : public LossFunction {
public:
// Constructs a ScaledLoss wrapping another loss function. Takes
// ownership of the wrapped loss function or not depending on the
// ownership parameter.
ScaledLoss(const LossFunction* rho, double a, Ownership ownership) :
rho_(rho), a_(a), ownership_(ownership) { }
virtual ~ScaledLoss() {
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
rho_.release();
}
}
virtual void Evaluate(double, double*) const;
private:
internal::scoped_ptr<const LossFunction> rho_;
const double a_;
const Ownership ownership_;
DISALLOW_COPY_AND_ASSIGN(ScaledLoss);
};
// Sometimes after the optimization problem has been constructed, we
// wish to mutate the scale of the loss function. For example, when
// performing estimation from data which has substantial outliers,
// convergence can be improved by starting out with a large scale,
// optimizing the problem and then reducing the scale. This can have
// better convergence behaviour than just using a loss function with a
// small scale.
//
// This templated class allows the user to implement a loss function
// whose scale can be mutated after an optimization problem has been
// constructed.
//
// Example usage
//
// Problem problem;
//
// // Add parameter blocks
//
// CostFunction* cost_function =
// new AutoDiffCostFunction < UW_Camera_Mapper, 2, 9, 3>(
// new UW_Camera_Mapper(data->observations[2*i + 0],
// data->observations[2*i + 1]));
//
// LossFunctionWrapper* loss_function(new HuberLoss(1.0), TAKE_OWNERSHIP);
//
// problem.AddResidualBlock(cost_function, loss_function, parameters);
//
// Solver::Options options;
// scoped_ptr<Solver::Summary> summary1(Solve(problem, options));
//
// loss_function->Reset(new HuberLoss(1.0), TAKE_OWNERSHIP);
//
// scoped_ptr<Solver::Summary> summary2(Solve(problem, options));
//
class LossFunctionWrapper : public LossFunction {
public:
LossFunctionWrapper(LossFunction* rho, Ownership ownership)
: rho_(rho), ownership_(ownership) {
}
virtual ~LossFunctionWrapper() {
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
rho_.release();
}
}
virtual void Evaluate(double sq_norm, double out[3]) const {
CHECK_NOTNULL(rho_.get());
rho_->Evaluate(sq_norm, out);
}
void Reset(LossFunction* rho, Ownership ownership) {
if (ownership_ == DO_NOT_TAKE_OWNERSHIP) {
rho_.release();
}
rho_.reset(rho);
ownership_ = ownership;
}
private:
internal::scoped_ptr<const LossFunction> rho_;
Ownership ownership_;
DISALLOW_COPY_AND_ASSIGN(LossFunctionWrapper);
};
} // namespace ceres
#endif // CERES_PUBLIC_LOSS_FUNCTION_H_

@ -0,0 +1,75 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Cost term that implements a prior on a parameter block using a
// normal distribution.
#ifndef CERES_PUBLIC_NORMAL_PRIOR_H_
#define CERES_PUBLIC_NORMAL_PRIOR_H_
#include "ceres/cost_function.h"
#include "ceres/internal/eigen.h"
namespace ceres {
// Implements a cost function of the form
//
// cost(x) = ||A(x - b)||^2
//
// where, the matrix A and the vector b are fixed and x is the
// variable. In case the user is interested in implementing a cost
// function of the form
//
// cost(x) = (x - mu)^T S^{-1} (x - mu)
//
// where, mu is a vector and S is a covariance matrix, then, A =
// S^{-1/2}, i.e the matrix A is the square root of the inverse of the
// covariance, also known as the stiffness matrix. There are however
// no restrictions on the shape of A. It is free to be rectangular,
// which would be the case if the covariance matrix S is rank
// deficient.
class NormalPrior: public CostFunction {
public:
// Check that the number of rows in the vector b are the same as the
// number of columns in the matrix A, crash otherwise.
NormalPrior(const Matrix& A, const Vector& b);
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const;
private:
Matrix A_;
Vector b_;
};
} // namespace ceres
#endif // CERES_PUBLIC_NORMAL_PRIOR_H_

@ -0,0 +1,283 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// Create CostFunctions as needed by the least squares framework with jacobians
// computed via numeric (a.k.a. finite) differentiation. For more details see
// http://en.wikipedia.org/wiki/Numerical_differentiation.
//
// To get a numerically differentiated cost function, define a subclass of
// CostFunction such that the Evaluate() function ignores the jacobian
// parameter. The numeric differentiation wrapper will fill in the jacobian
// parameter if nececssary by repeatedly calling the Evaluate() function with
// small changes to the appropriate parameters, and computing the slope. For
// performance, the numeric differentiation wrapper class is templated on the
// concrete cost function, even though it could be implemented only in terms of
// the virtual CostFunction interface.
//
// The numerically differentiated version of a cost function for a cost function
// can be constructed as follows:
//
// CostFunction* cost_function
// = new NumericDiffCostFunction<MyCostFunction, CENTRAL, 1, 4, 8>(
// new MyCostFunction(...), TAKE_OWNERSHIP);
//
// where MyCostFunction has 1 residual and 2 parameter blocks with sizes 4 and 8
// respectively. Look at the tests for a more detailed example.
//
// The central difference method is considerably more accurate at the cost of
// twice as many function evaluations than forward difference. Consider using
// central differences begin with, and only after that works, trying forward
// difference to improve performance.
//
// TODO(keir): Characterize accuracy; mention pitfalls; provide alternatives.
#ifndef CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_
#define CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_
#include <cstring>
#include <glog/logging.h>
#include "Eigen/Dense"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/sized_cost_function.h"
#include "ceres/types.h"
namespace ceres {
enum NumericDiffMethod {
CENTRAL,
FORWARD
};
// This is split from the main class because C++ doesn't allow partial template
// specializations for member functions. The alternative is to repeat the main
// class for differing numbers of parameters, which is also unfortunate.
template <typename CostFunctionNoJacobian,
int num_residuals,
int parameter_block_size,
int parameter_block,
NumericDiffMethod method>
struct Differencer {
// Mutates parameters but must restore them before return.
static bool EvaluateJacobianForParameterBlock(
const CostFunctionNoJacobian *function,
double const* residuals_at_eval_point,
double **parameters,
double **jacobians) {
using Eigen::Map;
using Eigen::Matrix;
using Eigen::RowMajor;
typedef Matrix<double, num_residuals, 1> ResidualVector;
typedef Matrix<double, parameter_block_size, 1> ParameterVector;
typedef Matrix<double, num_residuals, parameter_block_size, RowMajor>
JacobianMatrix;
Map<JacobianMatrix> parameter_jacobian(jacobians[parameter_block],
num_residuals,
parameter_block_size);
// Mutate 1 element at a time and then restore.
Map<ParameterVector> x_plus_delta(parameters[parameter_block],
parameter_block_size);
ParameterVector x(x_plus_delta);
// TODO(keir): Pick a smarter number! In theory a good choice is sqrt(eps) *
// x, which for doubles means about 1e-8 * x. However, I have found this
// number too optimistic. This number should be exposed for users to change.
const double kRelativeStepSize = 1e-6;
ParameterVector step_size = x.array().abs() * kRelativeStepSize;
// To handle cases where a parameter is exactly zero, instead use the mean
// step_size for the other dimensions.
double fallback_step_size = step_size.sum() / step_size.rows();
if (fallback_step_size == 0.0) {
// If all the parameters are zero, there's no good answer. Take
// kRelativeStepSize as a guess and hope for the best.
fallback_step_size = kRelativeStepSize;
}
// For each parameter in the parameter block, use finite differences to
// compute the derivative for that parameter.
for (int j = 0; j < parameter_block_size; ++j) {
if (step_size(j) == 0.0) {
// The parameter is exactly zero, so compromise and use the mean
// step_size from the other parameters. This can break in many cases,
// but it's hard to pick a good number without problem specific
// knowledge.
step_size(j) = fallback_step_size;
}
x_plus_delta(j) = x(j) + step_size(j);
double residuals[num_residuals]; // NOLINT
if (!function->Evaluate(parameters, residuals, NULL)) {
// Something went wrong; bail.
return false;
}
// Compute this column of the jacobian in 3 steps:
// 1. Store residuals for the forward part.
// 2. Subtract residuals for the backward (or 0) part.
// 3. Divide out the run.
parameter_jacobian.col(j) =
Map<const ResidualVector>(residuals, num_residuals);
double one_over_h = 1 / step_size(j);
if (method == CENTRAL) {
// Compute the function on the other side of x(j).
x_plus_delta(j) = x(j) - step_size(j);
if (!function->Evaluate(parameters, residuals, NULL)) {
// Something went wrong; bail.
return false;
}
parameter_jacobian.col(j) -=
Map<ResidualVector>(residuals, num_residuals, 1);
one_over_h /= 2;
} else {
// Forward difference only; reuse existing residuals evaluation.
parameter_jacobian.col(j) -=
Map<const ResidualVector>(residuals_at_eval_point, num_residuals);
}
x_plus_delta(j) = x(j); // Restore x_plus_delta.
// Divide out the run to get slope.
parameter_jacobian.col(j) *= one_over_h;
}
return true;
}
};
// Prevent invalid instantiations.
template <typename CostFunctionNoJacobian,
int num_residuals,
int parameter_block,
NumericDiffMethod method>
struct Differencer<CostFunctionNoJacobian,
num_residuals,
0 /* parameter_block_size */,
parameter_block,
method> {
static bool EvaluateJacobianForParameterBlock(
const CostFunctionNoJacobian *function,
double const* residuals_at_eval_point,
double **parameters,
double **jacobians) {
LOG(FATAL) << "Shouldn't get here.";
return true;
}
};
template <typename CostFunctionNoJacobian,
NumericDiffMethod method = CENTRAL, int M = 0,
int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0, int N5 = 0>
class NumericDiffCostFunction
: public SizedCostFunction<M, N0, N1, N2, N3, N4, N5> {
public:
NumericDiffCostFunction(CostFunctionNoJacobian* function,
Ownership ownership)
: function_(function), ownership_(ownership) {}
virtual ~NumericDiffCostFunction() {
if (ownership_ != TAKE_OWNERSHIP) {
function_.release();
}
}
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
// Get the function value (residuals) at the the point to evaluate.
bool success = function_->Evaluate(parameters, residuals, NULL);
if (!success) {
// Something went wrong; ignore the jacobian.
return false;
}
if (!jacobians) {
// Nothing to do; just forward.
return true;
}
// Create a copy of the parameters which will get mutated.
const int kParametersSize = N0 + N1 + N2 + N3 + N4 + N5;
double parameters_copy[kParametersSize];
double *parameters_references_copy[6];
parameters_references_copy[0] = &parameters_copy[0];
parameters_references_copy[1] = &parameters_copy[0] + N0;
parameters_references_copy[2] = &parameters_copy[0] + N0 + N1;
parameters_references_copy[3] = &parameters_copy[0] + N0 + N1 + N2;
parameters_references_copy[4] = &parameters_copy[0] + N0 + N1 + N2 + N3;
parameters_references_copy[5] =
&parameters_copy[0] + N0 + N1 + N2 + N3 + N4;
#define COPY_PARAMETER_BLOCK(block) \
if (N ## block) memcpy(parameters_references_copy[block], \
parameters[block], \
sizeof(double) * N ## block); // NOLINT
COPY_PARAMETER_BLOCK(0);
COPY_PARAMETER_BLOCK(1);
COPY_PARAMETER_BLOCK(2);
COPY_PARAMETER_BLOCK(3);
COPY_PARAMETER_BLOCK(4);
COPY_PARAMETER_BLOCK(5);
#undef COPY_PARAMETER_BLOCK
#define EVALUATE_JACOBIAN_FOR_BLOCK(block) \
if (N ## block && jacobians[block]) { \
if (!Differencer<CostFunctionNoJacobian, /* NOLINT */ \
M, \
N ## block, \
block, \
method>::EvaluateJacobianForParameterBlock( \
function_.get(), \
residuals, \
parameters_references_copy, \
jacobians)) { \
return false; \
} \
}
EVALUATE_JACOBIAN_FOR_BLOCK(0);
EVALUATE_JACOBIAN_FOR_BLOCK(1);
EVALUATE_JACOBIAN_FOR_BLOCK(2);
EVALUATE_JACOBIAN_FOR_BLOCK(3);
EVALUATE_JACOBIAN_FOR_BLOCK(4);
EVALUATE_JACOBIAN_FOR_BLOCK(5);
#undef EVALUATE_JACOBIAN_FOR_BLOCK
return true;
}
private:
internal::scoped_ptr<CostFunctionNoJacobian> function_;
Ownership ownership_;
};
} // namespace ceres
#endif // CERES_PUBLIC_NUMERIC_DIFF_COST_FUNCTION_H_

@ -0,0 +1,265 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
// keir@google.com (Keir Mierle)
//
// The Problem object is used to build and hold least squares problems.
#ifndef CERES_PUBLIC_PROBLEM_H_
#define CERES_PUBLIC_PROBLEM_H_
#include <cstddef>
#include <map>
#include <set>
#include <vector>
#include <glog/logging.h>
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
namespace ceres {
class CostFunction;
class LossFunction;
class LocalParameterization;
namespace internal {
class Preprocessor;
class ProblemImpl;
class ParameterBlock;
class ResidualBlock;
class SolverImpl;
} // namespace internal
// A ResidualBlockId is a handle clients can use to delete residual
// blocks after creating them. They are opaque for any purposes other
// than that.
typedef const internal::ResidualBlock* ResidualBlockId;
// A class to represent non-linear least squares problems. Such
// problems have a cost function that is a sum of error terms (known
// as "residuals"), where each residual is a function of some subset
// of the parameters. The cost function takes the form
//
// N 1
// SUM --- loss( || r_i1, r_i2,..., r_ik ||^2 ),
// i=1 2
//
// where
//
// r_ij is residual number i, component j; the residual is a
// function of some subset of the parameters x1...xk. For
// example, in a structure from motion problem a residual
// might be the difference between a measured point in an
// image and the reprojected position for the matching
// camera, point pair. The residual would have two
// components, error in x and error in y.
//
// loss(y) is the loss function; for example, squared error or
// Huber L1 loss. If loss(y) = y, then the cost function is
// non-robustified least squares.
//
// This class is specifically designed to address the important subset
// of "sparse" least squares problems, where each component of the
// residual depends only on a small number number of parameters, even
// though the total number of residuals and parameters may be very
// large. This property affords tremendous gains in scale, allowing
// efficient solving of large problems that are otherwise
// inaccessible.
//
// The canonical example of a sparse least squares problem is
// "structure-from-motion" (SFM), where the parameters are points and
// cameras, and residuals are reprojection errors. Typically a single
// residual will depend only on 9 parameters (3 for the point, 6 for
// the camera).
//
// To create a least squares problem, use the AddResidualBlock() and
// AddParameterBlock() methods, documented below. Here is an example least
// squares problem containing 3 parameter blocks of sizes 3, 4 and 5
// respectively and two residual terms of size 2 and 6:
//
// double x1[] = { 1.0, 2.0, 3.0 };
// double x2[] = { 1.0, 2.0, 3.0, 5.0 };
// double x3[] = { 1.0, 2.0, 3.0, 6.0, 7.0 };
//
// Problem problem;
//
// problem.AddResidualBlock(new MyUnaryCostFunction(...), x1);
// problem.AddResidualBlock(new MyBinaryCostFunction(...), x2, x3);
//
// Please see cost_function.h for details of the CostFunction object.
class Problem {
public:
struct Options {
Options()
: cost_function_ownership(TAKE_OWNERSHIP),
loss_function_ownership(TAKE_OWNERSHIP),
local_parameterization_ownership(TAKE_OWNERSHIP) {}
// These flags control whether the Problem object owns the cost
// functions, loss functions, and parameterizations passed into
// the Problem. If set to TAKE_OWNERSHIP, then the problem object
// will delete the corresponding cost or loss functions on
// destruction. The destructor is careful to delete the pointers
// only once, since sharing cost/loss/parameterizations is
// allowed.
Ownership cost_function_ownership;
Ownership loss_function_ownership;
Ownership local_parameterization_ownership;
};
// The default constructor is equivalent to the
// invocation Problem(Problem::Options()).
Problem();
explicit Problem(const Options& options);
~Problem();
// Add a residual block to the overall cost function. The cost
// function carries with it information about the sizes of the
// parameter blocks it expects. The function checks that these match
// the sizes of the parameter blocks listed in parameter_blocks. The
// program aborts if a mismatch is detected. loss_function can be
// NULL, in which case the cost of the term is just the squared norm
// of the residuals.
//
// The user has the option of explicitly adding the parameter blocks
// using AddParameterBlock. This causes additional correctness
// checking; however, AddResidualBlock implicitly adds the parameter
// blocks if they are not present, so calling AddParameterBlock
// explicitly is not required.
//
// The Problem object by default takes ownership of the
// cost_function and loss_function pointers. These objects remain
// live for the life of the Problem object. If the user wishes to
// keep control over the destruction of these objects, then they can
// do this by setting the corresponding enums in the Options struct.
//
// Note: Even though the Problem takes ownership of cost_function
// and loss_function, it does not preclude the user from re-using
// them in another residual block. The destructor takes care to call
// delete on each cost_function or loss_function pointer only once,
// regardless of how many residual blocks refer to them.
//
// Example usage:
//
// double x1[] = {1.0, 2.0, 3.0};
// double x2[] = {1.0, 2.0, 5.0, 6.0};
// double x3[] = {3.0, 6.0, 2.0, 5.0, 1.0};
//
// Problem problem;
//
// problem.AddResidualBlock(new MyUnaryCostFunction(...), NULL, x1);
// problem.AddResidualBlock(new MyBinaryCostFunction(...), NULL, x2, x1);
//
ResidualBlockId AddResidualBlock(CostFunction* cost_function,
LossFunction* loss_function,
const vector<double*>& parameter_blocks);
// Convenience methods for adding residuals with a small number of
// parameters. This is the common case. Instead of specifying the
// parameter block arguments as a vector, list them as pointers.
ResidualBlockId AddResidualBlock(CostFunction* cost_function,
LossFunction* loss_function,
double* x0);
ResidualBlockId AddResidualBlock(CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1);
ResidualBlockId AddResidualBlock(CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1, double* x2);
ResidualBlockId AddResidualBlock(CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1, double* x2,
double* x3);
ResidualBlockId AddResidualBlock(CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1, double* x2,
double* x3, double* x4);
ResidualBlockId AddResidualBlock(CostFunction* cost_function,
LossFunction* loss_function,
double* x0, double* x1, double* x2,
double* x3, double* x4, double* x5);
// Add a parameter block with appropriate size to the problem.
// Repeated calls with the same arguments are ignored. Repeated
// calls with the same double pointer but a different size results
// in undefined behaviour.
void AddParameterBlock(double* values, int size);
// Add a parameter block with appropriate size and parameterization
// to the problem. Repeated calls with the same arguments are
// ignored. Repeated calls with the same double pointer but a
// different size results in undefined behaviour.
void AddParameterBlock(double* values,
int size,
LocalParameterization* local_parameterization);
// Hold the indicated parameter block constant during optimization.
void SetParameterBlockConstant(double* values);
// Allow the indicated parameter to vary during optimization.
void SetParameterBlockVariable(double* values);
// Set the local parameterization for one of the parameter blocks.
// The local_parameterization is owned by the Problem by default. It
// is acceptable to set the same parameterization for multiple
// parameters; the destructor is careful to delete local
// parameterizations only once. The local parameterization can only
// be set once per parameter, and cannot be changed once set.
void SetParameterization(double* values,
LocalParameterization* local_parameterization);
// Number of parameter blocks in the problem. Always equals
// parameter_blocks().size() and parameter_block_sizes().size().
int NumParameterBlocks() const;
// The size of the parameter vector obtained by summing over the
// sizes of all the parameter blocks.
int NumParameters() const;
// Number of residual blocks in the problem. Always equals
// residual_blocks().size().
int NumResidualBlocks() const;
// The size of the residual vector obtained by summing over the
// sizes of all of the residual blocks.
int NumResiduals() const;
private:
friend class internal::SolverImpl;
internal::scoped_ptr<internal::ProblemImpl> problem_impl_;
DISALLOW_COPY_AND_ASSIGN(Problem);
};
} // namespace ceres
#endif // CERES_PUBLIC_PROBLEM_H_

@ -0,0 +1,526 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
// sameeragarwal@google.com (Sameer Agarwal)
//
// Templated functions for manipulating rotations. The templated
// functions are useful when implementing functors for automatic
// differentiation.
//
// In the following, the Quaternions are laid out as 4-vectors, thus:
//
// q[0] scalar part.
// q[1] coefficient of i.
// q[2] coefficient of j.
// q[3] coefficient of k.
//
// where: i*i = j*j = k*k = -1 and i*j = k, j*k = i, k*i = j.
#ifndef CERES_PUBLIC_ROTATION_H_
#define CERES_PUBLIC_ROTATION_H_
#include <algorithm>
#include <cmath>
namespace ceres {
// Convert a value in combined axis-angle representation to a quaternion.
// The value angle_axis is a triple whose norm is an angle in radians,
// and whose direction is aligned with the axis of rotation,
// and quaternion is a 4-tuple that will contain the resulting quaternion.
// The implementation may be used with auto-differentiation up to the first
// derivative, higher derivatives may have unexpected results near the origin.
template<typename T>
void AngleAxisToQuaternion(T const* angle_axis, T* quaternion);
// Convert a quaternion to the equivalent combined axis-angle representation.
// The value quaternion must be a unit quaternion - it is not normalized first,
// and angle_axis will be filled with a value whose norm is the angle of
// rotation in radians, and whose direction is the axis of rotation.
// The implemention may be used with auto-differentiation up to the first
// derivative, higher derivatives may have unexpected results near the origin.
template<typename T>
void QuaternionToAngleAxis(T const* quaternion, T* angle_axis);
// Conversions between 3x3 rotation matrix (in column major order) and
// axis-angle rotation representations. Templated for use with
// autodifferentiation.
template <typename T>
void RotationMatrixToAngleAxis(T const * R, T * angle_axis);
template <typename T>
void AngleAxisToRotationMatrix(T const * angle_axis, T * R);
// Conversions between 3x3 rotation matrix (in row major order) and
// Euler angle (in degrees) rotation representations.
//
// The {pitch,roll,yaw} Euler angles are rotations around the {x,y,z}
// axes, respectively. They are applied in that same order, so the
// total rotation R is Rz * Ry * Rx.
template <typename T>
void EulerAnglesToRotationMatrix(const T* euler, int row_stride, T* R);
// Convert a 4-vector to a 3x3 scaled rotation matrix.
//
// The choice of rotation is such that the quaternion [1 0 0 0] goes to an
// identity matrix and for small a, b, c the quaternion [1 a b c] goes to
// the matrix
//
// [ 0 -c b ]
// I + 2 [ c 0 -a ] + higher order terms
// [ -b a 0 ]
//
// which corresponds to a Rodrigues approximation, the last matrix being
// the cross-product matrix of [a b c]. Together with the property that
// R(q1 * q2) = R(q1) * R(q2) this uniquely defines the mapping from q to R.
//
// The rotation matrix is row-major.
//
// No normalization of the quaternion is performed, i.e.
// R = ||q||^2 * Q, where Q is an orthonormal matrix
// such that det(Q) = 1 and Q*Q' = I
template <typename T> inline
void QuaternionToScaledRotation(const T q[4], T R[3 * 3]);
// Same as above except that the rotation matrix is normalized by the
// Frobenius norm, so that R * R' = I (and det(R) = 1).
template <typename T> inline
void QuaternionToRotation(const T q[4], T R[3 * 3]);
// Rotates a point pt by a quaternion q:
//
// result = R(q) * pt
//
// Assumes the quaternion is unit norm. This assumption allows us to
// write the transform as (something)*pt + pt, as is clear from the
// formula below. If you pass in a quaternion with |q|^2 = 2 then you
// WILL NOT get back 2 times the result you get for a unit quaternion.
template <typename T> inline
void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]);
// With this function you do not need to assume that q has unit norm.
// It does assume that the norm is non-zero.
template <typename T> inline
void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]);
// zw = z * w, where * is the Quaternion product between 4 vectors.
template<typename T> inline
void QuaternionProduct(const T z[4], const T w[4], T zw[4]);
// xy = x cross y;
template<typename T> inline
void CrossProduct(const T x[3], const T y[3], T x_cross_y[3]);
template<typename T> inline
T DotProduct(const T x[3], const T y[3]);
// y = R(angle_axis) * x;
template<typename T> inline
void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]);
// --- IMPLEMENTATION
// Duplicate rather than decorate every use of cmath with _USE_MATH_CONSTANTS.
// Necessitated by Windows.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#define CERES_NEED_M_PI_UNDEF
#endif
template<typename T>
inline void AngleAxisToQuaternion(const T* angle_axis, T* quaternion) {
const T &a0 = angle_axis[0];
const T &a1 = angle_axis[1];
const T &a2 = angle_axis[2];
const T theta_squared = a0 * a0 + a1 * a1 + a2 * a2;
// For points not at the origin, the full conversion is numerically stable.
if (theta_squared > T(0.0)) {
const T theta = sqrt(theta_squared);
const T half_theta = theta * T(0.5);
const T k = sin(half_theta) / theta;
quaternion[0] = cos(half_theta);
quaternion[1] = a0 * k;
quaternion[2] = a1 * k;
quaternion[3] = a2 * k;
} else {
// At the origin, sqrt() will produce NaN in the derivative since
// the argument is zero. By approximating with a Taylor series,
// and truncating at one term, the value and first derivatives will be
// computed correctly when Jets are used.
const T k(0.5);
quaternion[0] = T(1.0);
quaternion[1] = a0 * k;
quaternion[2] = a1 * k;
quaternion[3] = a2 * k;
}
}
template<typename T>
inline void QuaternionToAngleAxis(const T* quaternion, T* angle_axis) {
const T &q1 = quaternion[1];
const T &q2 = quaternion[2];
const T &q3 = quaternion[3];
const T sin_squared = q1 * q1 + q2 * q2 + q3 * q3;
// For quaternions representing non-zero rotation, the conversion
// is numerically stable.
if (sin_squared > T(0.0)) {
const T sin_theta = sqrt(sin_squared);
const T k = T(2.0) * atan2(sin_theta, quaternion[0]) / sin_theta;
angle_axis[0] = q1 * k;
angle_axis[1] = q2 * k;
angle_axis[2] = q3 * k;
} else {
// For zero rotation, sqrt() will produce NaN in the derivative since
// the argument is zero. By approximating with a Taylor series,
// and truncating at one term, the value and first derivatives will be
// computed correctly when Jets are used.
const T k(2.0);
angle_axis[0] = q1 * k;
angle_axis[1] = q2 * k;
angle_axis[2] = q3 * k;
}
}
// The conversion of a rotation matrix to the angle-axis form is
// numerically problematic when then rotation angle is close to zero
// or to Pi. The following implementation detects when these two cases
// occurs and deals with them by taking code paths that are guaranteed
// to not perform division by a small number.
template <typename T>
inline void RotationMatrixToAngleAxis(const T * R, T * angle_axis) {
// x = k * 2 * sin(theta), where k is the axis of rotation.
angle_axis[0] = R[5] - R[7];
angle_axis[1] = R[6] - R[2];
angle_axis[2] = R[1] - R[3];
static const T kOne = T(1.0);
static const T kTwo = T(2.0);
// Since the right hand side may give numbers just above 1.0 or
// below -1.0 leading to atan misbehaving, we threshold.
T costheta = std::min(std::max((R[0] + R[4] + R[8] - kOne) / kTwo,
T(-1.0)),
kOne);
// sqrt is guaranteed to give non-negative results, so we only
// threshold above.
T sintheta = std::min(sqrt(angle_axis[0] * angle_axis[0] +
angle_axis[1] * angle_axis[1] +
angle_axis[2] * angle_axis[2]) / kTwo,
kOne);
// Use the arctan2 to get the right sign on theta
const T theta = atan2(sintheta, costheta);
// Case 1: sin(theta) is large enough, so dividing by it is not a
// problem. We do not use abs here, because while jets.h imports
// std::abs into the namespace, here in this file, abs resolves to
// the int version of the function, which returns zero always.
//
// We use a threshold much larger then the machine epsilon, because
// if sin(theta) is small, not only do we risk overflow but even if
// that does not occur, just dividing by a small number will result
// in numerical garbage. So we play it safe.
static const double kThreshold = 1e-12;
if ((sintheta > kThreshold) || (sintheta < -kThreshold)) {
const T r = theta / (kTwo * sintheta);
for (int i = 0; i < 3; ++i) {
angle_axis[i] *= r;
}
return;
}
// Case 2: theta ~ 0, means sin(theta) ~ theta to a good
// approximation.
if (costheta > 0) {
const T kHalf = T(0.5);
for (int i = 0; i < 3; ++i) {
angle_axis[i] *= kHalf;
}
return;
}
// Case 3: theta ~ pi, this is the hard case. Since theta is large,
// and sin(theta) is small. Dividing by theta by sin(theta) will
// either give an overflow or worse still numerically meaningless
// results. Thus we use an alternate more complicated formula
// here.
// Since cos(theta) is negative, division by (1-cos(theta)) cannot
// overflow.
const T inv_one_minus_costheta = kOne / (kOne - costheta);
// We now compute the absolute value of coordinates of the axis
// vector using the diagonal entries of R. To resolve the sign of
// these entries, we compare the sign of angle_axis[i]*sin(theta)
// with the sign of sin(theta). If they are the same, then
// angle_axis[i] should be positive, otherwise negative.
for (int i = 0; i < 3; ++i) {
angle_axis[i] = theta * sqrt((R[i*4] - costheta) * inv_one_minus_costheta);
if (((sintheta < 0) && (angle_axis[i] > 0)) ||
((sintheta > 0) && (angle_axis[i] < 0))) {
angle_axis[i] = -angle_axis[i];
}
}
}
template <typename T>
inline void AngleAxisToRotationMatrix(const T * angle_axis, T * R) {
static const T kOne = T(1.0);
const T theta2 = DotProduct(angle_axis, angle_axis);
if (theta2 > 0.0) {
// We want to be careful to only evaluate the square root if the
// norm of the angle_axis vector is greater than zero. Otherwise
// we get a division by zero.
const T theta = sqrt(theta2);
const T wx = angle_axis[0] / theta;
const T wy = angle_axis[1] / theta;
const T wz = angle_axis[2] / theta;
const T costheta = cos(theta);
const T sintheta = sin(theta);
R[0] = costheta + wx*wx*(kOne - costheta);
R[1] = wz*sintheta + wx*wy*(kOne - costheta);
R[2] = -wy*sintheta + wx*wz*(kOne - costheta);
R[3] = wx*wy*(kOne - costheta) - wz*sintheta;
R[4] = costheta + wy*wy*(kOne - costheta);
R[5] = wx*sintheta + wy*wz*(kOne - costheta);
R[6] = wy*sintheta + wx*wz*(kOne - costheta);
R[7] = -wx*sintheta + wy*wz*(kOne - costheta);
R[8] = costheta + wz*wz*(kOne - costheta);
} else {
// At zero, we switch to using the first order Taylor expansion.
R[0] = kOne;
R[1] = -angle_axis[2];
R[2] = angle_axis[1];
R[3] = angle_axis[2];
R[4] = kOne;
R[5] = -angle_axis[0];
R[6] = -angle_axis[1];
R[7] = angle_axis[0];
R[8] = kOne;
}
}
template <typename T>
inline void EulerAnglesToRotationMatrix(const T* euler,
const int row_stride,
T* R) {
const T degrees_to_radians(M_PI / 180.0);
const T pitch(euler[0] * degrees_to_radians);
const T roll(euler[1] * degrees_to_radians);
const T yaw(euler[2] * degrees_to_radians);
const T c1 = cos(yaw);
const T s1 = sin(yaw);
const T c2 = cos(roll);
const T s2 = sin(roll);
const T c3 = cos(pitch);
const T s3 = sin(pitch);
// Rows of the rotation matrix.
T* R1 = R;
T* R2 = R1 + row_stride;
T* R3 = R2 + row_stride;
R1[0] = c1*c2;
R1[1] = -s1*c3 + c1*s2*s3;
R1[2] = s1*s3 + c1*s2*c3;
R2[0] = s1*c2;
R2[1] = c1*c3 + s1*s2*s3;
R2[2] = -c1*s3 + s1*s2*c3;
R3[0] = -s2;
R3[1] = c2*s3;
R3[2] = c2*c3;
}
template <typename T> inline
void QuaternionToScaledRotation(const T q[4], T R[3 * 3]) {
// Make convenient names for elements of q.
T a = q[0];
T b = q[1];
T c = q[2];
T d = q[3];
// This is not to eliminate common sub-expression, but to
// make the lines shorter so that they fit in 80 columns!
T aa = a * a;
T ab = a * b;
T ac = a * c;
T ad = a * d;
T bb = b * b;
T bc = b * c;
T bd = b * d;
T cc = c * c;
T cd = c * d;
T dd = d * d;
R[0] = aa + bb - cc - dd; R[1] = T(2) * (bc - ad); R[2] = T(2) * (ac + bd); // NOLINT
R[3] = T(2) * (ad + bc); R[4] = aa - bb + cc - dd; R[5] = T(2) * (cd - ab); // NOLINT
R[6] = T(2) * (bd - ac); R[7] = T(2) * (ab + cd); R[8] = aa - bb - cc + dd; // NOLINT
}
template <typename T> inline
void QuaternionToRotation(const T q[4], T R[3 * 3]) {
QuaternionToScaledRotation(q, R);
T normalizer = q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
CHECK_NE(normalizer, T(0));
normalizer = T(1) / normalizer;
for (int i = 0; i < 9; ++i) {
R[i] *= normalizer;
}
}
template <typename T> inline
void UnitQuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) {
const T t2 = q[0] * q[1];
const T t3 = q[0] * q[2];
const T t4 = q[0] * q[3];
const T t5 = -q[1] * q[1];
const T t6 = q[1] * q[2];
const T t7 = q[1] * q[3];
const T t8 = -q[2] * q[2];
const T t9 = q[2] * q[3];
const T t1 = -q[3] * q[3];
result[0] = T(2) * ((t8 + t1) * pt[0] + (t6 - t4) * pt[1] + (t3 + t7) * pt[2]) + pt[0]; // NOLINT
result[1] = T(2) * ((t4 + t6) * pt[0] + (t5 + t1) * pt[1] + (t9 - t2) * pt[2]) + pt[1]; // NOLINT
result[2] = T(2) * ((t7 - t3) * pt[0] + (t2 + t9) * pt[1] + (t5 + t8) * pt[2]) + pt[2]; // NOLINT
}
template <typename T> inline
void QuaternionRotatePoint(const T q[4], const T pt[3], T result[3]) {
// 'scale' is 1 / norm(q).
const T scale = T(1) / sqrt(q[0] * q[0] +
q[1] * q[1] +
q[2] * q[2] +
q[3] * q[3]);
// Make unit-norm version of q.
const T unit[4] = {
scale * q[0],
scale * q[1],
scale * q[2],
scale * q[3],
};
UnitQuaternionRotatePoint(unit, pt, result);
}
template<typename T> inline
void QuaternionProduct(const T z[4], const T w[4], T zw[4]) {
zw[0] = z[0] * w[0] - z[1] * w[1] - z[2] * w[2] - z[3] * w[3];
zw[1] = z[0] * w[1] + z[1] * w[0] + z[2] * w[3] - z[3] * w[2];
zw[2] = z[0] * w[2] - z[1] * w[3] + z[2] * w[0] + z[3] * w[1];
zw[3] = z[0] * w[3] + z[1] * w[2] - z[2] * w[1] + z[3] * w[0];
}
// xy = x cross y;
template<typename T> inline
void CrossProduct(const T x[3], const T y[3], T x_cross_y[3]) {
x_cross_y[0] = x[1] * y[2] - x[2] * y[1];
x_cross_y[1] = x[2] * y[0] - x[0] * y[2];
x_cross_y[2] = x[0] * y[1] - x[1] * y[0];
}
template<typename T> inline
T DotProduct(const T x[3], const T y[3]) {
return (x[0] * y[0] + x[1] * y[1] + x[2] * y[2]);
}
template<typename T> inline
void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) {
T w[3];
T sintheta;
T costheta;
const T theta2 = DotProduct(angle_axis, angle_axis);
if (theta2 > 0.0) {
// Away from zero, use the rodriguez formula
//
// result = pt costheta +
// (w x pt) * sintheta +
// w (w . pt) (1 - costheta)
//
// We want to be careful to only evaluate the square root if the
// norm of the angle_axis vector is greater than zero. Otherwise
// we get a division by zero.
//
const T theta = sqrt(theta2);
w[0] = angle_axis[0] / theta;
w[1] = angle_axis[1] / theta;
w[2] = angle_axis[2] / theta;
costheta = cos(theta);
sintheta = sin(theta);
T w_cross_pt[3];
CrossProduct(w, pt, w_cross_pt);
T w_dot_pt = DotProduct(w, pt);
for (int i = 0; i < 3; ++i) {
result[i] = pt[i] * costheta +
w_cross_pt[i] * sintheta +
w[i] * (T(1.0) - costheta) * w_dot_pt;
}
} else {
// Near zero, the first order Taylor approximation of the rotation
// matrix R corresponding to a vector w and angle w is
//
// R = I + hat(w) * sin(theta)
//
// But sintheta ~ theta and theta * w = angle_axis, which gives us
//
// R = I + hat(w)
//
// and actually performing multiplication with the point pt, gives us
// R * pt = pt + w x pt.
//
// Switching to the Taylor expansion at zero helps avoid all sorts
// of numerical nastiness.
T w_cross_pt[3];
CrossProduct(angle_axis, pt, w_cross_pt);
for (int i = 0; i < 3; ++i) {
result[i] = pt[i] + w_cross_pt[i];
}
}
}
} // namespace ceres
// Clean define pollution.
#ifdef CERES_NEED_M_PI_UNDEF
#undef CERES_NEED_M_PI_UNDEF
#undef M_PI
#endif
#endif // CERES_PUBLIC_ROTATION_H_

@ -0,0 +1,82 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// A convenience class for cost functions which are statically sized.
// Compared to the dynamically-sized base class, this reduces boilerplate.
#ifndef CERES_PUBLIC_SIZED_COST_FUNCTION_H_
#define CERES_PUBLIC_SIZED_COST_FUNCTION_H_
#include <glog/logging.h>
#include "ceres/cost_function.h"
namespace ceres {
template<int kNumResiduals,
int N0 = 0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0, int N5 = 0>
class SizedCostFunction : public CostFunction {
public:
SizedCostFunction() {
// Sanity checking.
DCHECK_GT(kNumResiduals, 0) << "Cost functions must have at least "
<< "one residual block.";
DCHECK_GT(N0, 0)
<< "Cost functions must have at least one parameter block.";
DCHECK((!N1 && !N2 && !N3 && !N4 && !N5) ||
((N1 > 0) && !N2 && !N3 && !N4 && !N5) ||
((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5) ||
((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5) ||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5) ||
((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0)))
<< "Zero block cannot precede a non-zero block. Block sizes are "
<< "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
<< N3 << ", " << N4 << ", " << N5;
set_num_residuals(kNumResiduals);
#define ADD_PARAMETER_BLOCK(N) \
if (N) mutable_parameter_block_sizes()->push_back(N);
ADD_PARAMETER_BLOCK(N0);
ADD_PARAMETER_BLOCK(N1);
ADD_PARAMETER_BLOCK(N2);
ADD_PARAMETER_BLOCK(N3);
ADD_PARAMETER_BLOCK(N4);
ADD_PARAMETER_BLOCK(N5);
#undef ADD_PARAMETER_BLOCK
}
virtual ~SizedCostFunction() { }
// Subclasses must implement Evaluate().
};
} // namespace ceres
#endif // CERES_PUBLIC_SIZED_COST_FUNCTION_H_

@ -0,0 +1,379 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_PUBLIC_SOLVER_H_
#define CERES_PUBLIC_SOLVER_H_
#include <cmath>
#include <string>
#include <vector>
#include "ceres/iteration_callback.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
#include "ceres/types.h"
namespace ceres {
class Problem;
// Interface for non-linear least squares solvers.
class Solver {
public:
virtual ~Solver();
// The options structure contains, not surprisingly, options that control how
// the solver operates. The defaults should be suitable for a wide range of
// problems; however, better performance is often obtainable with tweaking.
//
// The constants are defined inside types.h
struct Options {
// Default constructor that sets up a generic sparse problem.
Options() {
minimizer_type = LEVENBERG_MARQUARDT;
max_num_iterations = 50;
max_solver_time_sec = 1.0e9;
num_threads = 1;
tau = 1e-4;
min_relative_decrease = 1e-3;
function_tolerance = 1e-6;
gradient_tolerance = 1e-10;
parameter_tolerance = 1e-8;
#ifndef CERES_NO_SUITESPARSE
linear_solver_type = SPARSE_NORMAL_CHOLESKY;
#else
linear_solver_type = DENSE_QR;
#endif // CERES_NO_SUITESPARSE
preconditioner_type = JACOBI;
num_linear_solver_threads = 1;
num_eliminate_blocks = 0;
ordering_type = NATURAL;
linear_solver_min_num_iterations = 1;
linear_solver_max_num_iterations = 500;
eta = 1e-1;
jacobi_scaling = true;
logging_type = PER_MINIMIZER_ITERATION;
minimizer_progress_to_stdout = false;
return_initial_residuals = false;
return_final_residuals = false;
lsqp_dump_format = "lm_iteration_%03d.lsqp";
crash_and_dump_lsqp_on_failure = false;
check_gradients = false;
gradient_check_relative_precision = 1e-8;
numeric_derivative_relative_step_size = 1e-6;
update_state_every_iteration = false;
}
// Minimizer options ----------------------------------------
MinimizerType minimizer_type;
// Maximum number of iterations for the minimizer to run for.
int max_num_iterations;
// Maximum time for which the minimizer should run for.
double max_solver_time_sec;
// Number of threads used by Ceres for evaluating the cost and
// jacobians.
int num_threads;
// For Levenberg-Marquardt, the initial value for the
// regularizer. This is the inversely related to the size of the
// initial trust region.
double tau;
// For trust region methods, this is lower threshold for the
// relative decrease before a step is accepted.
double min_relative_decrease;
// Minimizer terminates when
//
// (new_cost - old_cost) < function_tolerance * old_cost;
//
double function_tolerance;
// Minimizer terminates when
//
// max_i |gradient_i| < gradient_tolerance * max_i|initial_gradient_i|
//
// This value should typically be 1e-4 * function_tolerance.
double gradient_tolerance;
// Minimizer terminates when
//
// |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance)
//
double parameter_tolerance;
// Linear least squares solver options -------------------------------------
LinearSolverType linear_solver_type;
// Type of preconditioner to use with the iterative linear solvers.
PreconditionerType preconditioner_type;
// Number of threads used by Ceres to solve the Newton
// step. Currently only the SPARSE_SCHUR solver is capable of
// using this setting.
int num_linear_solver_threads;
// For Schur reduction based methods, the first 0 to num blocks are
// eliminated using the Schur reduction. For example, when solving
// traditional structure from motion problems where the parameters are in
// two classes (cameras and points) then num_eliminate_blocks would be the
// number of points.
//
// This parameter is used in conjunction with the ordering.
// Applies to: Preprocessor and linear least squares solver.
int num_eliminate_blocks;
// Internally Ceres reorders the parameter blocks to help the
// various linear solvers. This parameter allows the user to
// influence the re-ordering strategy used. For structure from
// motion problems use SCHUR, for other problems NATURAL (default)
// is a good choice. In case you wish to specify your own ordering
// scheme, for example in conjunction with num_eliminate_blocks,
// use USER.
OrderingType ordering_type;
// The ordering of the parameter blocks. The solver pays attention
// to it if the ordering_type is set to USER and the vector is
// non-empty.
vector<double*> ordering;
// Minimum number of iterations for which the linear solver should
// run, even if the convergence criterion is satisfied.
int linear_solver_min_num_iterations;
// Maximum number of iterations for which the linear solver should
// run. If the solver does not converge in less than
// linear_solver_max_num_iterations, then it returns
// MAX_ITERATIONS, as its termination type.
int linear_solver_max_num_iterations;
// Forcing sequence parameter. The truncated Newton solver uses
// this number to control the relative accuracy with which the
// Newton step is computed.
//
// This constant is passed to ConjugateGradientsSolver which uses
// it to terminate the iterations when
//
// (Q_i - Q_{i-1})/Q_i < eta/i
double eta;
// Normalize the jacobian using Jacobi scaling before calling
// the linear least squares solver.
bool jacobi_scaling;
// Logging options ---------------------------------------------------------
LoggingType logging_type;
// By default the Minimizer progress is logged to VLOG(1), which
// is sent to STDERR depending on the vlog level. If this flag is
// set to true, and logging_type is not SILENT, the logging output
// is sent to STDOUT.
bool minimizer_progress_to_stdout;
bool return_initial_residuals;
bool return_final_residuals;
// List of iterations at which the optimizer should dump the
// linear least squares problem to disk. Useful for testing and
// benchmarking. If empty (default), no problems are dumped.
//
// This is ignored if protocol buffers are disabled.
vector<int> lsqp_iterations_to_dump;
// Format string for the file name used for dumping the least
// squares problem to disk. If the format is 'ascii', then the
// problem is logged to the screen; don't try this with large
// problems or expect a frozen terminal.
string lsqp_dump_format;
// Dump the linear least squares problem to disk if the minimizer
// fails due to NUMERICAL_FAILURE and crash the process. This flag
// is useful for generating debugging information. The problem is
// dumped in a file whose name is determined by
// Solver::Options::lsqp_dump_format.
//
// Note: This requires a version of Ceres built with protocol buffers.
bool crash_and_dump_lsqp_on_failure;
// Finite differences options ----------------------------------------------
// Check all jacobians computed by each residual block with finite
// differences. This is expensive since it involves computing the
// derivative by normal means (e.g. user specified, autodiff,
// etc), then also computing it using finite differences. The
// results are compared, and if they differ substantially, details
// are printed to the log.
bool check_gradients;
// Relative precision to check for in the gradient checker. If the
// relative difference between an element in a jacobian exceeds
// this number, then the jacobian for that cost term is dumped.
double gradient_check_relative_precision;
// Relative shift used for taking numeric derivatives. For finite
// differencing, each dimension is evaluated at slightly shifted
// values; for the case of central difference, this is what gets
// evaluated:
//
// delta = numeric_derivative_relative_step_size;
// f_initial = f(x)
// f_forward = f((1 + delta) * x)
// f_backward = f((1 - delta) * x)
//
// The finite differencing is done along each dimension. The
// reason to use a relative (rather than absolute) step size is
// that this way, numeric differentation works for functions where
// the arguments are typically large (e.g. 1e9) and when the
// values are small (e.g. 1e-5). It is possible to construct
// "torture cases" which break this finite difference heuristic,
// but they do not come up often in practice.
//
// TODO(keir): Pick a smarter number than the default above! In
// theory a good choice is sqrt(eps) * x, which for doubles means
// about 1e-8 * x. However, I have found this number too
// optimistic. This number should be exposed for users to change.
double numeric_derivative_relative_step_size;
// If true, the user's parameter blocks are updated at the end of
// every Minimizer iteration, otherwise they are updated when the
// Minimizer terminates. This is useful if, for example, the user
// wishes to visualize the state of the optimization every
// iteration.
bool update_state_every_iteration;
// Callbacks that are executed at the end of each iteration of the
// Minimizer. They are executed in the order that they are
// specified in this vector. By default, parameter blocks are
// updated only at the end of the optimization, i.e when the
// Minimizer terminates. This behaviour is controlled by
// update_state_every_variable. If the user wishes to have access
// to the update parameter blocks when his/her callbacks are
// executed, then set update_state_every_iteration to true.
//
// The solver does NOT take ownership of these pointers.
vector<IterationCallback*> callbacks;
};
struct Summary {
Summary();
// A brief one line description of the state of the solver after
// termination.
string BriefReport() const;
// A full multiline description of the state of the solver after
// termination.
string FullReport() const;
// Minimizer summary -------------------------------------------------
SolverTerminationType termination_type;
// If the solver did not run, or there was a failure, a
// description of the error.
string error;
// Cost of the problem before and after the optimization. See
// problem.h for definition of the cost of a problem.
double initial_cost;
double final_cost;
// The part of the total cost that comes from residual blocks that
// were held fixed by the preprocessor because all the parameter
// blocks that they depend on were fixed.
double fixed_cost;
// Residuals before and after the optimization. Each vector
// contains problem.NumResiduals() elements. Residuals are in the
// same order in which they were added to the problem object when
// constructing this problem.
vector<double> initial_residuals;
vector<double> final_residuals;
vector<IterationSummary> iterations;
int num_successful_steps;
int num_unsuccessful_steps;
double preprocessor_time_in_seconds;
double minimizer_time_in_seconds;
double total_time_in_seconds;
// Preprocessor summary.
int num_parameter_blocks;
int num_parameters;
int num_residual_blocks;
int num_residuals;
int num_parameter_blocks_reduced;
int num_parameters_reduced;
int num_residual_blocks_reduced;
int num_residuals_reduced;
int num_eliminate_blocks_given;
int num_eliminate_blocks_used;
int num_threads_given;
int num_threads_used;
int num_linear_solver_threads_given;
int num_linear_solver_threads_used;
LinearSolverType linear_solver_type_given;
LinearSolverType linear_solver_type_used;
PreconditionerType preconditioner_type;
OrderingType ordering_type;
};
// Once a least squares problem has been built, this function takes
// the problem and optimizes it based on the values of the options
// parameters. Upon return, a detailed summary of the work performed
// by the preprocessor, the non-linear minmizer and the linear
// solver are reported in the summary object.
virtual void Solve(const Options& options,
Problem* problem,
Solver::Summary* summary);
};
// Helper function which avoids going through the interface.
void Solve(const Solver::Options& options,
Problem* problem,
Solver::Summary* summary);
} // namespace ceres
#endif // CERES_PUBLIC_SOLVER_H_

@ -0,0 +1,224 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Enums and other top level class definitions.
//
// Note: internal/types.cc defines stringification routines for some
// of these enums. Please update those routines if you extend or
// remove enums from here.
#ifndef CERES_PUBLIC_TYPES_H_
#define CERES_PUBLIC_TYPES_H_
namespace ceres {
// Basic integer types. These typedefs are in the Ceres namespace to avoid
// conflicts with other packages having similar typedefs.
typedef short int16;
typedef int int32;
// Argument type used in interfaces that can optionally take ownership
// of a passed in argument. If TAKE_OWNERSHIP is passed, the called
// object takes ownership of the pointer argument, and will call
// delete on it upon completion.
enum Ownership {
DO_NOT_TAKE_OWNERSHIP,
TAKE_OWNERSHIP
};
// TODO(keir): Considerably expand the explanations of each solver type.
enum LinearSolverType {
// These solvers are for general rectangular systems formed from the
// normal equations A'A x = A'b. They are direct solvers and do not
// assume any special problem structure.
// Solve the normal equations using a sparse cholesky solver; based
// on CHOLMOD.
SPARSE_NORMAL_CHOLESKY,
// Solve the normal equations using a dense QR solver; based on
// Eigen.
DENSE_QR,
// Specialized solvers, specific to problems with a generalized
// bi-partitite structure.
// Solves the reduced linear system using a dense Cholesky solver;
// based on Eigen.
DENSE_SCHUR,
// Solves the reduced linear system using a sparse Cholesky solver;
// based on CHOLMOD.
SPARSE_SCHUR,
// Solves the reduced linear system using Conjugate Gradients, based
// on a new Ceres implementation. Suitable for large scale
// problems.
ITERATIVE_SCHUR,
// Conjugate gradients on the normal equations.
CGNR
};
enum PreconditionerType {
// Trivial preconditioner - the identity matrix.
IDENTITY,
// Block diagonal of the Gauss-Newton Hessian.
JACOBI,
// Block diagonal of the Schur complement. This preconditioner may
// only be used with the ITERATIVE_SCHUR solver. Requires
// SuiteSparse/CHOLMOD.
SCHUR_JACOBI,
// Visibility clustering based preconditioners.
//
// These preconditioners are well suited for Structure from Motion
// problems, particularly problems arising from community photo
// collections. These preconditioners use the visibility structure
// of the scene to determine the sparsity structure of the
// preconditioner. Requires SuiteSparse/CHOLMOD.
CLUSTER_JACOBI,
CLUSTER_TRIDIAGONAL
};
enum LinearSolverTerminationType {
// Termination criterion was met. For factorization based solvers
// the tolerance is assumed to be zero. Any user provided values are
// ignored.
TOLERANCE,
// Solver ran for max_num_iterations and terminated before the
// termination tolerance could be satified.
MAX_ITERATIONS,
// Solver is stuck and further iterations will not result in any
// measurable progress.
STAGNATION,
// Solver failed. Solver was terminated due to numerical errors. The
// exact cause of failure depends on the particular solver being
// used.
FAILURE
};
enum OrderingType {
// The order in which the parameter blocks were defined.
NATURAL,
// Use the ordering specificed in the vector ordering.
USER,
// Automatically figure out the best ordering to use the schur
// complement based solver.
SCHUR
};
// Logging options
// The options get progressively noisier.
enum LoggingType {
SILENT,
PER_MINIMIZER_ITERATION
};
enum MinimizerType {
LEVENBERG_MARQUARDT
};
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,
// Minimized terminated because
// |step|_2 <= parameter_tolerance * ( |x|_2 + parameter_tolerance)
PARAMETER_TOLERANCE,
// The minimizer terminated because it encountered a numerical error
// that it could not recover from.
NUMERICAL_FAILURE,
// Using an IterationCallback object, user code can control the
// minimizer. The following enums indicate that the user code was
// responsible for termination.
// User's IterationCallback returned SOLVER_ABORT.
USER_ABORT,
// User's IterationCallback returned SOLVER_TERMINATE_SUCCESSFULLY
USER_SUCCESS
};
// Enums used by the IterationCallback instances to indicate to the
// solver whether it should continue solving, the user detected an
// error or the solution is good enough and the solver should
// terminate.
enum CallbackReturnType {
// Continue solving to next iteration.
SOLVER_CONTINUE,
// Terminate solver, and do not update the parameter blocks upon
// return. Unless the user has set
// Solver:Options:::update_state_every_iteration, in which case the
// state would have been updated every iteration
// anyways. Solver::Summary::termination_type is set to USER_ABORT.
SOLVER_ABORT,
// Terminate solver, update state and
// return. Solver::Summary::termination_type is set to USER_SUCCESS.
SOLVER_TERMINATE_SUCCESSFULLY
};
const char* LinearSolverTypeToString(LinearSolverType type);
const char* PreconditionerTypeToString(PreconditionerType type);
const char* LinearSolverTerminationTypeToString(
LinearSolverTerminationType type);
const char* OrderingTypeToString(OrderingType type);
const char* SolverTerminationTypeToString(SolverTerminationType type);
bool IsSchurType(LinearSolverType type);
} // namespace ceres
#endif // CERES_PUBLIC_TYPES_H_

@ -0,0 +1,73 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#include "ceres/block_evaluate_preparer.h"
#include <vector>
#include "ceres/block_sparse_matrix.h"
#include "ceres/casts.h"
#include "ceres/parameter_block.h"
#include "ceres/residual_block.h"
#include "ceres/sparse_matrix.h"
namespace ceres {
namespace internal {
void BlockEvaluatePreparer::Init(int** jacobian_layout) {
jacobian_layout_ = jacobian_layout;
}
// Point the jacobian blocks directly into the block sparse matrix.
void BlockEvaluatePreparer::Prepare(const ResidualBlock* residual_block,
int residual_block_index,
SparseMatrix* jacobian,
double** jacobians) const {
CHECK(jacobian != NULL);
double* jacobian_values =
down_cast<BlockSparseMatrix*>(jacobian)->mutable_values();
const int* jacobian_block_offset = jacobian_layout_[residual_block_index];
const int num_parameter_blocks = residual_block->NumParameterBlocks();
for (int j = 0; j < num_parameter_blocks; ++j) {
if (!residual_block->parameter_blocks()[j]->IsConstant()) {
jacobians[j] = jacobian_values + *jacobian_block_offset;
// The jacobian_block_offset can't be indexed with 'j' since the code
// that creates the layout strips out any blocks for inactive
// parameters. Instead, bump the pointer for active parameters only.
jacobian_block_offset++;
} else {
jacobians[j] = NULL;
}
}
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,67 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// A evaluate preparer which puts jacobian the evaluated jacobian blocks
// directly into their final resting place in an overall block sparse matrix.
// The evaluator takes care to avoid evaluating the jacobian for fixed
// parameters.
#ifndef CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_
#define CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_
namespace ceres {
namespace internal {
class ResidualBlock;
class SparseMatrix;
class BlockEvaluatePreparer {
public:
// Using Init() instead of a constructor allows for allocating this structure
// with new[]. This is because C++ doesn't allow passing arguments to objects
// constructed with new[] (as opposed to plain 'new').
void Init(int** jacobian_layout);
// EvaluatePreparer interface
// Point the jacobian blocks directly into the block sparse matrix.
void Prepare(const ResidualBlock* residual_block,
int residual_block_index,
SparseMatrix* jacobian,
double** jacobians) const;
private:
int const* const* jacobian_layout_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_

@ -0,0 +1,136 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#include "ceres/block_jacobi_preconditioner.h"
#include "Eigen/Cholesky"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
#include "ceres/casts.h"
#include "ceres/integral_types.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
BlockJacobiPreconditioner::BlockJacobiPreconditioner(
const LinearOperator& A)
: block_structure_(
*(down_cast<const BlockSparseMatrix*>(&A)->block_structure())),
num_rows_(A.num_rows()) {
// Calculate the amount of storage needed.
int storage_needed = 0;
for (int c = 0; c < block_structure_.cols.size(); ++c) {
int size = block_structure_.cols[c].size;
storage_needed += size * size;
}
// Size the offsets and storage.
blocks_.resize(block_structure_.cols.size());
block_storage_.resize(storage_needed);
// Put pointers to the storage in the offsets.
double* block_cursor = &block_storage_[0];
for (int c = 0; c < block_structure_.cols.size(); ++c) {
int size = block_structure_.cols[c].size;
blocks_[c] = block_cursor;
block_cursor += size * size;
}
}
BlockJacobiPreconditioner::~BlockJacobiPreconditioner() {
}
void BlockJacobiPreconditioner::Update(const LinearOperator& matrix, const double* D) {
const BlockSparseMatrix& A = *(down_cast<const BlockSparseMatrix*>(&matrix));
const CompressedRowBlockStructure* bs = A.block_structure();
// Compute the diagonal blocks by block inner products.
std::fill(block_storage_.begin(), block_storage_.end(), 0.0);
for (int r = 0; r < bs->rows.size(); ++r) {
const int row_block_size = bs->rows[r].block.size;
const vector<Cell>& cells = bs->rows[r].cells;
const double* row_values = A.RowBlockValues(r);
for (int c = 0; c < cells.size(); ++c) {
const int col_block_size = bs->cols[cells[c].block_id].size;
ConstMatrixRef m(row_values + cells[c].position,
row_block_size,
col_block_size);
MatrixRef(blocks_[cells[c].block_id],
col_block_size,
col_block_size).noalias() += m.transpose() * m;
// TODO(keir): Figure out when the below expression is actually faster
// than doing the full rank update. The issue is that for smaller sizes,
// the rankUpdate() function is slower than the full product done above.
//
// On the typical bundling problems, the above product is ~5% faster.
//
// MatrixRef(blocks_[cells[c].block_id],
// col_block_size,
// col_block_size).selfadjointView<Eigen::Upper>().rankUpdate(m);
//
}
}
// Add the diagonal and invert each block.
for (int c = 0; c < bs->cols.size(); ++c) {
const int size = block_structure_.cols[c].size;
const int position = block_structure_.cols[c].position;
MatrixRef block(blocks_[c], size, size);
if (D != NULL) {
block.diagonal() += ConstVectorRef(D + position, size).array().square().matrix();
}
block = block.selfadjointView<Eigen::Upper>()
.ldlt()
.solve(Matrix::Identity(size, size));
}
}
void BlockJacobiPreconditioner::RightMultiply(const double* x, double* y) const {
for (int c = 0; c < block_structure_.cols.size(); ++c) {
const int size = block_structure_.cols[c].size;
const int position = block_structure_.cols[c].position;
ConstMatrixRef D(blocks_[c], size, size);
ConstVectorRef x_block(x + position, size);
VectorRef y_block(y + position, size);
y_block += D * x_block;
}
}
void BlockJacobiPreconditioner::LeftMultiply(const double* x, double* y) const {
RightMultiply(x, y);
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,84 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#ifndef CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_
#define CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_
#include <vector>
#include "ceres/linear_operator.h"
namespace ceres {
namespace internal {
class CompressedRowBlockStructure;
class LinearOperator;
class SparseMatrix;
// A block Jacobi preconditioner. This is intended for use with conjugate
// gradients, or other iterative symmetric solvers. To use the preconditioner,
// create one by passing a BlockSparseMatrix as the linear operator "A" to the
// constructor. This fixes the sparsity pattern to the pattern of the matrix
// A^TA.
//
// Before each use of the preconditioner in a solve with conjugate gradients,
// update the matrix by running Update(A, D). The values of the matrix A are
// inspected to construct the preconditioner. The vector D is applied as the
// D^TD diagonal term.
class BlockJacobiPreconditioner : public LinearOperator {
public:
// A must remain valid while the BlockJacobiPreconditioner is.
BlockJacobiPreconditioner(const LinearOperator& A);
virtual ~BlockJacobiPreconditioner();
// Update the preconditioner with the values found in A. The sparsity pattern
// must match that of the A passed to the constructor. D is a vector that
// must have the same number of rows as A, and is applied as a diagonal in
// addition to the block diagonals of A.
void Update(const LinearOperator& A, const double* D);
// LinearOperator interface.
virtual void RightMultiply(const double* x, double* y) const;
virtual void LeftMultiply(const double* x, double* y) const;
virtual int num_rows() const { return num_rows_; }
virtual int num_cols() const { return num_rows_; }
private:
std::vector<double*> blocks_;
std::vector<double> block_storage_;
int num_rows_;
// The block structure of the matrix this preconditioner is for (e.g. J).
const CompressedRowBlockStructure& block_structure_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_

@ -0,0 +1,209 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#include "ceres/block_jacobian_writer.h"
#include "ceres/block_evaluate_preparer.h"
#include "ceres/block_sparse_matrix.h"
#include "ceres/parameter_block.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
namespace ceres {
namespace internal {
namespace {
// Given the residual block ordering, build a lookup table to determine which
// per-parameter jacobian goes where in the overall program jacobian.
//
// Since we expect to use a Schur type linear solver to solve the LM step, take
// extra care to place the E blocks and the F blocks contiguously. E blocks are
// the first num_eliminate_blocks parameter blocks as indicated by the parameter
// block ordering. The remaining parameter blocks are the F blocks.
//
// TODO(keir): Consider if we should use a boolean for each parameter block
// instead of num_eliminate_blocks.
void BuildJacobianLayout(const Program& program,
int num_eliminate_blocks,
vector<int*>* jacobian_layout,
vector<int>* jacobian_layout_storage) {
const vector<ResidualBlock*>& residual_blocks = program.residual_blocks();
// Iterate over all the active residual blocks and determine how many E blocks
// are there. This will determine where the F blocks start in the jacobian
// matrix. Also compute the number of jacobian blocks.
int f_block_pos = 0;
int num_jacobian_blocks = 0;
for (int i = 0; i < residual_blocks.size(); ++i) {
ResidualBlock* residual_block = residual_blocks[i];
const int num_residuals = residual_block->NumResiduals();
const int num_parameter_blocks = residual_block->NumParameterBlocks();
// Advance f_block_pos over each E block for this residual.
for (int j = 0; j < num_parameter_blocks; ++j) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
if (!parameter_block->IsConstant()) {
// Only count blocks for active parameters.
num_jacobian_blocks++;
if (parameter_block->index() < num_eliminate_blocks) {
f_block_pos += num_residuals * parameter_block->LocalSize();
}
}
}
}
// We now know that the E blocks are laid out starting at zero, and the F
// blocks are laid out starting at f_block_pos. Iterate over the residual
// blocks again, and this time fill the jacobian_layout array with the
// position information.
jacobian_layout->resize(program.NumResidualBlocks());
jacobian_layout_storage->resize(num_jacobian_blocks);
int e_block_pos = 0;
int* jacobian_pos = &(*jacobian_layout_storage)[0];
for (int i = 0; i < residual_blocks.size(); ++i) {
const ResidualBlock* residual_block = residual_blocks[i];
const int num_residuals = residual_block->NumResiduals();
const int num_parameter_blocks = residual_block->NumParameterBlocks();
(*jacobian_layout)[i] = jacobian_pos;
for (int j = 0; j < num_parameter_blocks; ++j) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
const int parameter_block_index = parameter_block->index();
if (parameter_block->IsConstant()) {
continue;
}
const int jacobian_block_size =
num_residuals * parameter_block->LocalSize();
if (parameter_block_index < num_eliminate_blocks) {
*jacobian_pos = e_block_pos;
e_block_pos += jacobian_block_size;
} else {
*jacobian_pos = f_block_pos;
f_block_pos += jacobian_block_size;
}
jacobian_pos++;
}
}
}
} // namespace
BlockJacobianWriter::BlockJacobianWriter(const Evaluator::Options& options,
Program* program)
: program_(program) {
CHECK_GE(options.num_eliminate_blocks, 0)
<< "num_eliminate_blocks must be greater than 0.";
BuildJacobianLayout(*program,
options.num_eliminate_blocks,
&jacobian_layout_,
&jacobian_layout_storage_);
}
// Create evaluate prepareres that point directly into the final jacobian. This
// makes the final Write() a nop.
BlockEvaluatePreparer* BlockJacobianWriter::CreateEvaluatePreparers(
int num_threads) {
BlockEvaluatePreparer* preparers = new BlockEvaluatePreparer[num_threads];
for (int i = 0; i < num_threads; i++) {
preparers[i].Init(&jacobian_layout_[0]);
}
return preparers;
}
SparseMatrix* BlockJacobianWriter::CreateJacobian() const {
CompressedRowBlockStructure* bs = new CompressedRowBlockStructure;
const vector<ParameterBlock*>& parameter_blocks =
program_->parameter_blocks();
// Construct the column blocks.
bs->cols.resize(parameter_blocks.size());
for (int i = 0, cursor = 0; i < parameter_blocks.size(); ++i) {
CHECK_NE(parameter_blocks[i]->index(), -1);
CHECK(!parameter_blocks[i]->IsConstant());
bs->cols[i].size = parameter_blocks[i]->LocalSize();
bs->cols[i].position = cursor;
cursor += bs->cols[i].size;
}
// Construct the cells in each row.
const vector<ResidualBlock*>& residual_blocks =
program_->residual_blocks();
int row_block_position = 0;
bs->rows.resize(residual_blocks.size());
for (int i = 0; i < residual_blocks.size(); ++i) {
const ResidualBlock* residual_block = residual_blocks[i];
CompressedRow* row = &bs->rows[i];
row->block.size = residual_block->NumResiduals();
row->block.position = row_block_position;
row_block_position += row->block.size;
// Size the row by the number of active parameters in this residual.
const int num_parameter_blocks = residual_block->NumParameterBlocks();
int num_active_parameter_blocks = 0;
for (int j = 0; j < num_parameter_blocks; ++j) {
if (residual_block->parameter_blocks()[j]->index() != -1) {
num_active_parameter_blocks++;
}
}
row->cells.resize(num_active_parameter_blocks);
// Add layout information for the active parameters in this row.
for (int j = 0, k = 0; j < num_parameter_blocks; ++j) {
const ParameterBlock* parameter_block =
residual_block->parameter_blocks()[j];
if (!parameter_block->IsConstant()) {
Cell& cell = row->cells[k];
cell.block_id = parameter_block->index();
cell.position = jacobian_layout_[i][k];
// Only increment k for active parameters, since there is only layout
// information for active parameters.
k++;
}
}
sort(row->cells.begin(), row->cells.end(), CellLessThan);
}
BlockSparseMatrix* jacobian = new BlockSparseMatrix(bs);
CHECK_NOTNULL(jacobian);
return jacobian;
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,127 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// A jacobian writer that writes to block sparse matrices. The "writer" name is
// misleading, since the Write() operation on the block jacobian writer does not
// write anything. Instead, the Prepare() method on the BlockEvaluatePreparers
// makes a jacobians array which has direct pointers into the block sparse
// jacobian. When the cost function is evaluated, the jacobian blocks get placed
// directly in their final location.
#ifndef CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_
#define CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_
#include <vector>
#include "ceres/evaluator.h"
#include "ceres/internal/port.h"
namespace ceres {
namespace internal {
class BlockEvaluatePreparer;
class Program;
class SparseMatrix;
class BlockJacobianWriter {
public:
BlockJacobianWriter(const Evaluator::Options& options,
Program* program);
// JacobianWriter interface.
// Create evaluate prepareres that point directly into the final jacobian.
// This makes the final Write() a nop.
BlockEvaluatePreparer* CreateEvaluatePreparers(int num_threads);
SparseMatrix* CreateJacobian() const;
void Write(int /* residual_id */,
int /* residual_offset */,
double** /* jacobians */,
SparseMatrix* /* jacobian */) {
// This is a noop since the blocks were written directly into their final
// position by the outside evaluate call, thanks to the jacobians array
// prepared by the BlockEvaluatePreparers.
}
private:
Program* program_;
// Stores the position of each residual / parameter jacobian.
//
// The block sparse matrix that this writer writes to is stored as a set of
// contiguos dense blocks, one after each other; see BlockSparseMatrix. The
// "double* values_" member of the block sparse matrix contains all of these
// blocks. Given a pointer to the first element of a block and the size of
// that block, it's possible to write to it.
//
// In the case of a block sparse jacobian, the jacobian writer needs a way to
// find the offset in the values_ array of each residual/parameter jacobian
// block.
//
// That is the purpose of jacobian_layout_.
//
// In particular, jacobian_layout_[i][j] is the offset in the values_ array of
// the derivative of residual block i with respect to the parameter block at
// active argument position j.
//
// The active qualifier means that non-active parameters do not count. Care
// must be taken when indexing into jacobian_layout_ to account for this.
// Consider a single residual example:
//
// r(x, y, z)
//
// with r in R^3, x in R^4, y in R^2, and z in R^5.
// Take y as a constant (non-active) parameter.
// Take r as residual number 0.
//
// In this case, the active arguments are only (x, z), so the active argument
// position for x is 0, and the active argument position for z is 1. This is
// similar to thinking of r as taking only 2 parameters:
//
// r(x, z)
//
// There are only 2 jacobian blocks: dr/dx and dr/dz. jacobian_layout_ would
// have the following contents:
//
// jacobian_layout_[0] = { 0, 12 }
//
// which indicates that dr/dx is located at values_[0], and dr/dz is at
// values_[12]. See BlockEvaluatePreparer::Prepare()'s comments about 'j'.
vector<int*> jacobian_layout_;
// The pointers in jacobian_layout_ point directly into this vector.
vector<int> jacobian_layout_storage_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_

@ -0,0 +1,83 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/block_random_access_dense_matrix.h"
#include <vector>
#include <glog/logging.h>
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
namespace ceres {
namespace internal {
BlockRandomAccessDenseMatrix::BlockRandomAccessDenseMatrix(
const vector<int>& blocks) {
block_layout_.resize(blocks.size(), 0);
num_rows_ = 0;
for (int i = 0; i < blocks.size(); ++i) {
block_layout_[i] = num_rows_;
num_rows_ += blocks[i];
}
values_.reset(new double[num_rows_ * num_rows_]);
CHECK_NOTNULL(values_.get());
cell_info_.values = values_.get();
SetZero();
}
// Assume that the user does not hold any locks on any cell blocks
// when they are calling SetZero.
BlockRandomAccessDenseMatrix::~BlockRandomAccessDenseMatrix() {
}
CellInfo* BlockRandomAccessDenseMatrix::GetCell(const int row_block_id,
const int col_block_id,
int* row,
int* col,
int* row_stride,
int* col_stride) {
*row = block_layout_[row_block_id];
*col = block_layout_[col_block_id];
*row_stride = num_rows_;
*col_stride = num_rows_;
return &cell_info_;
}
// Assume that the user does not hold any locks on any cell blocks
// when they are calling SetZero.
void BlockRandomAccessDenseMatrix::SetZero() {
if (num_rows_) {
VectorRef(values_.get(), num_rows_ * num_rows_).setZero();
}
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,98 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_
#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_
#include "ceres/block_random_access_matrix.h"
#include <vector>
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
namespace ceres {
namespace internal {
// A square block random accessible matrix with the same row and
// column block structure. All cells are stored in the same single
// array, so that its also accessible as a dense matrix of size
// num_rows x num_cols.
//
// This class is NOT thread safe. Since all n^2 cells are stored,
// GetCell never returns NULL for any (row_block_id, col_block_id)
// pair.
//
// ReturnCell is a nop.
class BlockRandomAccessDenseMatrix : public BlockRandomAccessMatrix {
public:
// blocks is a vector of block sizes. The resulting matrix has
// blocks.size() * blocks.size() cells.
explicit BlockRandomAccessDenseMatrix(const vector<int>& blocks);
// The destructor is not thread safe. It assumes that no one is
// modifying any cells when the matrix is being destroyed.
virtual ~BlockRandomAccessDenseMatrix();
// BlockRandomAccessMatrix interface.
virtual CellInfo* GetCell(int row_block_id,
int col_block_id,
int* row,
int* col,
int* row_stride,
int* col_stride);
// This is not a thread safe method, it assumes that no cell is
// locked.
virtual void SetZero();
// Since the matrix is square with the same row and column block
// structure, num_rows() = num_cols().
virtual int num_rows() const { return num_rows_; }
virtual int num_cols() const { return num_rows_; }
// The underlying matrix storing the cells.
const double* values() const { return values_.get(); }
double* mutable_values() { return values_.get(); }
private:
CellInfo cell_info_;
int num_rows_;
vector<int> block_layout_;
scoped_array<double> values_;
DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessDenseMatrix);
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_

@ -0,0 +1,40 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/block_random_access_matrix.h"
namespace ceres {
namespace internal {
BlockRandomAccessMatrix::~BlockRandomAccessMatrix() {
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,132 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Interface for matrices that allow block based random access.
#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_
#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_
#include "ceres/mutex.h"
namespace ceres {
namespace internal {
// A matrix implementing the BlockRandomAccessMatrix interface is a
// matrix whose rows and columns are divided into blocks. For example
// the matrix A:
//
// 3 4 5
// A = 5 [c_11 c_12 c_13]
// 4 [c_21 c_22 c_23]
//
// has row blocks of size 5 and 4, and column blocks of size 3, 4 and
// 5. It has six cells corresponding to the six row-column block
// combinations.
//
// BlockRandomAccessMatrix objects provide access to cells c_ij using
// the GetCell method. when a cell is present, GetCell will return a
// CellInfo object containing a pointer to an array which contains the
// cell as a submatrix and a mutex that guards this submatrix. If the
// user is accessing the matrix concurrently, it is his responsibility
// to use the mutex to exclude other writers from writing to the cell
// concurrently.
//
// There is no requirement that all cells be present, i.e. the matrix
// itself can be block sparse. When a cell is not present, the GetCell
// method will return a NULL pointer.
//
// There is no requirement about how the cells are stored beyond that
// form a dense submatrix of a larger dense matrix. Like everywhere
// else in Ceres, RowMajor storage assumed.
//
// Example usage:
//
// BlockRandomAccessMatrix* A = new BlockRandomAccessMatrixSubClass(...)
//
// int row, col, row_stride, col_stride;
// CellInfo* cell = A->GetCell(row_block_id, col_block_id,
// &row, &col,
// &row_stride, &col_stride);
//
// if (cell != NULL) {
// MatrixRef m(cell->values, row_stride, col_stride);
// MutexLock l(&cell->m);
// m.block(row, col, row_block_size, col_block_size) = ...
// }
// Structure to carry a pointer to the array containing a cell and the
// Mutex guarding it.
struct CellInfo {
CellInfo()
: values(NULL) {
}
explicit CellInfo(double* ptr)
: values(ptr) {
}
double* values;
Mutex m;
};
class BlockRandomAccessMatrix {
public:
virtual ~BlockRandomAccessMatrix();
// If the cell (row_block_id, col_block_id) is present, then return
// a CellInfo with a pointer to the dense matrix containing it,
// otherwise return NULL. The dense matrix containing this cell has
// size row_stride, col_stride and the cell is located at position
// (row, col) within this matrix.
//
// The size of the cell is row_block_size x col_block_size is
// assumed known to the caller. row_block_size less than or equal to
// row_stride and col_block_size is upper bounded by col_stride.
virtual CellInfo* GetCell(int row_block_id,
int col_block_id,
int* row,
int* col,
int* row_stride,
int* col_stride) = 0;
// Zero out the values of the array. The structure of the matrix
// (size and sparsity) is preserved.
virtual void SetZero() = 0;
// Number of scalar rows and columns in the matrix, i.e the sum of
// all row blocks and column block sizes respectively.
virtual int num_rows() const = 0;
virtual int num_cols() const = 0;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_MATRIX_H_

@ -0,0 +1,158 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/block_random_access_sparse_matrix.h"
#include <algorithm>
#include <set>
#include <utility>
#include <vector>
#include <glog/logging.h>
#include "ceres/mutex.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix(
const vector<int>& blocks,
const set<pair<int, int> >& block_pairs)
: kMaxRowBlocks(10 * 1000 * 1000),
blocks_(blocks) {
CHECK_LT(blocks.size(), kMaxRowBlocks);
// Build the row/column layout vector and count the number of scalar
// rows/columns.
int num_cols = 0;
vector<int> col_layout;
for (int i = 0; i < blocks_.size(); ++i) {
col_layout.push_back(num_cols);
num_cols += blocks_[i];
}
// Count the number of scalar non-zero entries and build the layout
// object for looking into the values array of the
// TripletSparseMatrix.
int num_nonzeros = 0;
for (set<pair<int, int> >::const_iterator it = block_pairs.begin();
it != block_pairs.end();
++it) {
const int row_block_size = blocks_[it->first];
const int col_block_size = blocks_[it->second];
num_nonzeros += row_block_size * col_block_size;
}
VLOG(1) << "Matrix Size [" << num_cols
<< "," << num_cols
<< "] " << num_nonzeros;
tsm_.reset(new TripletSparseMatrix(num_cols, num_cols, num_nonzeros));
tsm_->set_num_nonzeros(num_nonzeros);
int* rows = tsm_->mutable_rows();
int* cols = tsm_->mutable_cols();
double* values = tsm_->mutable_values();
int pos = 0;
for (set<pair<int, int> >::const_iterator it = block_pairs.begin();
it != block_pairs.end();
++it) {
const int row_block_size = blocks_[it->first];
const int col_block_size = blocks_[it->second];
layout_[IntPairToLong(it->first, it->second)] =
new CellInfo(values + pos);
pos += row_block_size * col_block_size;
}
// Fill the sparsity pattern of the underlying matrix.
for (set<pair<int, int> >::const_iterator it = block_pairs.begin();
it != block_pairs.end();
++it) {
const int row_block_id = it->first;
const int col_block_id = it->second;
const int row_block_size = blocks_[row_block_id];
const int col_block_size = blocks_[col_block_id];
int pos =
layout_[IntPairToLong(row_block_id, col_block_id)]->values - values;
for (int r = 0; r < row_block_size; ++r) {
for (int c = 0; c < col_block_size; ++c, ++pos) {
rows[pos] = col_layout[row_block_id] + r;
cols[pos] = col_layout[col_block_id] + c;
values[pos] = 1.0;
DCHECK_LT(rows[pos], tsm_->num_rows());
DCHECK_LT(cols[pos], tsm_->num_rows());
}
}
}
}
// Assume that the user does not hold any locks on any cell blocks
// when they are calling SetZero.
BlockRandomAccessSparseMatrix::~BlockRandomAccessSparseMatrix() {
for (LayoutType::iterator it = layout_.begin();
it != layout_.end();
++it) {
delete it->second;
}
}
CellInfo* BlockRandomAccessSparseMatrix::GetCell(int row_block_id,
int col_block_id,
int* row,
int* col,
int* row_stride,
int* col_stride) {
const LayoutType::iterator it =
layout_.find(IntPairToLong(row_block_id, col_block_id));
if (it == layout_.end()) {
return NULL;
}
// Each cell is stored contiguously as its own little dense matrix.
*row = 0;
*col = 0;
*row_stride = blocks_[row_block_id];
*col_stride = blocks_[col_block_id];
return it->second;
}
// Assume that the user does not hold any locks on any cell blocks
// when they are calling SetZero.
void BlockRandomAccessSparseMatrix::SetZero() {
if (tsm_->num_nonzeros()) {
VectorRef(tsm_->mutable_values(),
tsm_->num_nonzeros()).setZero();
}
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,109 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_
#define CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_
#include <set>
#include <vector>
#include <utility>
#include "ceres/mutex.h"
#include "ceres/block_random_access_matrix.h"
#include "ceres/collections_port.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/port.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
// A threaf safe square block sparse implementation of
// BlockRandomAccessMatrix. Internally a TripletSparseMatrix is used
// for doing the actual storage. This class augments this matrix with
// an unordered_map that allows random read/write access.
class BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix {
public:
// blocks is an array of block sizes. block_pairs is a set of
// <row_block_id, col_block_id> pairs to identify the non-zero cells
// of this matrix.
BlockRandomAccessSparseMatrix(const vector<int>& blocks,
const set<pair<int, int> >& block_pairs);
// The destructor is not thread safe. It assumes that no one is
// modifying any cells when the matrix is being destroyed.
virtual ~BlockRandomAccessSparseMatrix();
// BlockRandomAccessMatrix Interface.
virtual CellInfo* GetCell(int row_block_id,
int col_block_id,
int* row,
int* col,
int* row_stride,
int* col_stride);
// This is not a thread safe method, it assumes that no cell is
// locked.
virtual void SetZero();
virtual bool IsThreadSafe() const { return true; }
// Since the matrix is square, num_rows() == num_cols().
virtual int num_rows() const { return tsm_->num_rows(); }
virtual int num_cols() const { return tsm_->num_cols(); }
// Access to the underlying matrix object.
const TripletSparseMatrix* matrix() const { return tsm_.get(); }
TripletSparseMatrix* mutable_matrix() { return tsm_.get(); }
private:
long int IntPairToLong(int a, int b) {
return a * kMaxRowBlocks + b;
}
const int kMaxRowBlocks;
// row/column block sizes.
const vector<int> blocks_;
// A mapping from <row_block_id, col_block_id> to the position in
// the values array of tsm_ where the block is stored.
typedef HashMap<long int, CellInfo* > LayoutType;
LayoutType layout_;
// The underlying matrix object which actually stores the cells.
scoped_ptr<TripletSparseMatrix> tsm_;
DISALLOW_COPY_AND_ASSIGN(BlockRandomAccessSparseMatrix);
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_

@ -0,0 +1,263 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/block_sparse_matrix.h"
#include <cstddef>
#include <algorithm>
#include <vector>
#include <glog/logging.h>
#include "ceres/block_structure.h"
#include "ceres/matrix_proto.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
BlockSparseMatrix::~BlockSparseMatrix() {}
BlockSparseMatrix::BlockSparseMatrix(
CompressedRowBlockStructure* block_structure)
: num_rows_(0),
num_cols_(0),
num_nonzeros_(0),
values_(NULL),
block_structure_(block_structure) {
CHECK_NOTNULL(block_structure_.get());
// Count the number of columns in the matrix.
for (int i = 0; i < block_structure_->cols.size(); ++i) {
num_cols_ += block_structure_->cols[i].size;
}
// Count the number of non-zero entries and the number of rows in
// the matrix.
for (int i = 0; i < block_structure_->rows.size(); ++i) {
int row_block_size = block_structure_->rows[i].block.size;
num_rows_ += row_block_size;
const vector<Cell>& cells = block_structure_->rows[i].cells;
for (int j = 0; j < cells.size(); ++j) {
int col_block_id = cells[j].block_id;
int col_block_size = block_structure_->cols[col_block_id].size;
num_nonzeros_ += col_block_size * row_block_size;
}
}
CHECK_GE(num_rows_, 0);
CHECK_GE(num_cols_, 0);
CHECK_GE(num_nonzeros_, 0);
VLOG(2) << "Allocating values array with "
<< num_nonzeros_ * sizeof(double) << " bytes."; // NOLINT
values_.reset(new double[num_nonzeros_]);
CHECK_NOTNULL(values_.get());
}
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
BlockSparseMatrix::BlockSparseMatrix(const SparseMatrixProto& outer_proto) {
CHECK(outer_proto.has_block_matrix());
const BlockSparseMatrixProto& proto = outer_proto.block_matrix();
CHECK(proto.has_num_rows());
CHECK(proto.has_num_cols());
CHECK_EQ(proto.num_nonzeros(), proto.values_size());
num_rows_ = proto.num_rows();
num_cols_ = proto.num_cols();
num_nonzeros_ = proto.num_nonzeros();
// Copy out the values into *this.
values_.reset(new double[num_nonzeros_]);
for (int i = 0; i < proto.num_nonzeros(); ++i) {
values_[i] = proto.values(i);
}
// Create the block structure according to the proto.
block_structure_.reset(new CompressedRowBlockStructure);
ProtoToBlockStructure(proto.block_structure(), block_structure_.get());
}
#endif
void BlockSparseMatrix::SetZero() {
fill(values_.get(), values_.get() + num_nonzeros_, 0.0);
}
void BlockSparseMatrix::RightMultiply(const double* x, double* y) const {
CHECK_NOTNULL(x);
CHECK_NOTNULL(y);
for (int i = 0; i < block_structure_->rows.size(); ++i) {
int row_block_pos = block_structure_->rows[i].block.position;
int row_block_size = block_structure_->rows[i].block.size;
VectorRef yref(y + row_block_pos, row_block_size);
const vector<Cell>& cells = block_structure_->rows[i].cells;
for (int j = 0; j < cells.size(); ++j) {
int col_block_id = cells[j].block_id;
int col_block_size = block_structure_->cols[col_block_id].size;
int col_block_pos = block_structure_->cols[col_block_id].position;
ConstVectorRef xref(x + col_block_pos, col_block_size);
MatrixRef m(values_.get() + cells[j].position,
row_block_size, col_block_size);
yref += m.lazyProduct(xref);
}
}
}
void BlockSparseMatrix::LeftMultiply(const double* x, double* y) const {
CHECK_NOTNULL(x);
CHECK_NOTNULL(y);
for (int i = 0; i < block_structure_->rows.size(); ++i) {
int row_block_pos = block_structure_->rows[i].block.position;
int row_block_size = block_structure_->rows[i].block.size;
const ConstVectorRef xref(x + row_block_pos, row_block_size);
const vector<Cell>& cells = block_structure_->rows[i].cells;
for (int j = 0; j < cells.size(); ++j) {
int col_block_id = cells[j].block_id;
int col_block_size = block_structure_->cols[col_block_id].size;
int col_block_pos = block_structure_->cols[col_block_id].position;
VectorRef yref(y + col_block_pos, col_block_size);
MatrixRef m(values_.get() + cells[j].position,
row_block_size, col_block_size);
yref += m.transpose().lazyProduct(xref);
}
}
}
void BlockSparseMatrix::SquaredColumnNorm(double* x) const {
CHECK_NOTNULL(x);
VectorRef(x, num_cols_).setZero();
for (int i = 0; i < block_structure_->rows.size(); ++i) {
int row_block_size = block_structure_->rows[i].block.size;
const vector<Cell>& cells = block_structure_->rows[i].cells;
for (int j = 0; j < cells.size(); ++j) {
int col_block_id = cells[j].block_id;
int col_block_size = block_structure_->cols[col_block_id].size;
int col_block_pos = block_structure_->cols[col_block_id].position;
const MatrixRef m(values_.get() + cells[j].position,
row_block_size, col_block_size);
VectorRef(x + col_block_pos, col_block_size) += m.colwise().squaredNorm();
}
}
}
void BlockSparseMatrix::ScaleColumns(const double* scale) {
CHECK_NOTNULL(scale);
for (int i = 0; i < block_structure_->rows.size(); ++i) {
int row_block_size = block_structure_->rows[i].block.size;
const vector<Cell>& cells = block_structure_->rows[i].cells;
for (int j = 0; j < cells.size(); ++j) {
int col_block_id = cells[j].block_id;
int col_block_size = block_structure_->cols[col_block_id].size;
int col_block_pos = block_structure_->cols[col_block_id].position;
MatrixRef m(values_.get() + cells[j].position,
row_block_size, col_block_size);
m *= ConstVectorRef(scale + col_block_pos, col_block_size).asDiagonal();
}
}
}
void BlockSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
CHECK_NOTNULL(dense_matrix);
dense_matrix->resize(num_rows_, num_cols_);
dense_matrix->setZero();
Matrix& m = *dense_matrix;
for (int i = 0; i < block_structure_->rows.size(); ++i) {
int row_block_pos = block_structure_->rows[i].block.position;
int row_block_size = block_structure_->rows[i].block.size;
const vector<Cell>& cells = block_structure_->rows[i].cells;
for (int j = 0; j < cells.size(); ++j) {
int col_block_id = cells[j].block_id;
int col_block_size = block_structure_->cols[col_block_id].size;
int col_block_pos = block_structure_->cols[col_block_id].position;
int jac_pos = cells[j].position;
m.block(row_block_pos, col_block_pos, row_block_size, col_block_size)
+= MatrixRef(values_.get() + jac_pos, row_block_size, col_block_size);
}
}
}
void BlockSparseMatrix::ToTripletSparseMatrix(
TripletSparseMatrix* matrix) const {
CHECK_NOTNULL(matrix);
matrix->Reserve(num_nonzeros_);
matrix->Resize(num_rows_, num_cols_);
matrix->SetZero();
for (int i = 0; i < block_structure_->rows.size(); ++i) {
int row_block_pos = block_structure_->rows[i].block.position;
int row_block_size = block_structure_->rows[i].block.size;
const vector<Cell>& cells = block_structure_->rows[i].cells;
for (int j = 0; j < cells.size(); ++j) {
int col_block_id = cells[j].block_id;
int col_block_size = block_structure_->cols[col_block_id].size;
int col_block_pos = block_structure_->cols[col_block_id].position;
int jac_pos = cells[j].position;
for (int r = 0; r < row_block_size; ++r) {
for (int c = 0; c < col_block_size; ++c, ++jac_pos) {
matrix->mutable_rows()[jac_pos] = row_block_pos + r;
matrix->mutable_cols()[jac_pos] = col_block_pos + c;
matrix->mutable_values()[jac_pos] = values_[jac_pos];
}
}
}
}
matrix->set_num_nonzeros(num_nonzeros_);
}
// Return a pointer to the block structure. We continue to hold
// ownership of the object though.
const CompressedRowBlockStructure* BlockSparseMatrix::block_structure()
const {
return block_structure_.get();
}
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
void BlockSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
outer_proto->Clear();
BlockSparseMatrixProto* proto = outer_proto->mutable_block_matrix();
proto->set_num_rows(num_rows_);
proto->set_num_cols(num_cols_);
proto->set_num_nonzeros(num_nonzeros_);
for (int i = 0; i < num_nonzeros_; ++i) {
proto->add_values(values_[i]);
}
BlockStructureToProto(*block_structure_, proto->mutable_block_structure());
}
#endif
} // namespace internal
} // namespace ceres

@ -0,0 +1,142 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Implementation of the SparseMatrix interface for block sparse
// matrices.
#ifndef CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_
#define CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_
#include "ceres/block_structure.h"
#include "ceres/sparse_matrix.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/scoped_ptr.h"
namespace ceres {
namespace internal {
class SparseMatrixProto;
class TripletSparseMatrix;
// A further extension of the SparseMatrix interface to support block-oriented
// matrices. The key addition is the RowBlockValues() accessor, which enables
// the lazy block sparse matrix implementation.
class BlockSparseMatrixBase : public SparseMatrix {
public:
BlockSparseMatrixBase() {}
virtual ~BlockSparseMatrixBase() {}
// Convert this matrix into a triplet sparse matrix.
virtual void ToTripletSparseMatrix(TripletSparseMatrix* matrix) const = 0;
// Returns a pointer to the block structure. Does not transfer
// ownership.
virtual const CompressedRowBlockStructure* block_structure() const = 0;
// Returns a pointer to a row of the matrix. The returned array is only valid
// until the next call to RowBlockValues. The caller does not own the result.
//
// The returned array is laid out such that cells on the specified row are
// contiguous in the returned array, though neighbouring cells in row order
// may not be contiguous in the row values. The cell values for cell
// (row_block, cell_block) are found at offset
//
// block_structure()->rows[row_block].cells[cell_block].position
//
virtual const double* RowBlockValues(int row_block_index) const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrixBase);
};
// This class implements the SparseMatrix interface for storing and
// manipulating block sparse matrices. The block structure is stored
// in the CompressedRowBlockStructure object and one is needed to
// initialize the matrix. For details on how the blocks structure of
// the matrix is stored please see the documentation
//
// internal/ceres/block_structure.h
//
class BlockSparseMatrix : public BlockSparseMatrixBase {
public:
// Construct a block sparse matrix with a fully initialized
// CompressedRowBlockStructure objected. The matrix takes over
// ownership of this object and destroys it upon destruction.
//
// TODO(sameeragarwal): Add a function which will validate legal
// CompressedRowBlockStructure objects.
explicit BlockSparseMatrix(CompressedRowBlockStructure* block_structure);
// Construct a block sparse matrix from a protocol buffer.
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
explicit BlockSparseMatrix(const SparseMatrixProto& proto);
#endif
BlockSparseMatrix();
virtual ~BlockSparseMatrix();
// Implementation of SparseMatrix interface.
virtual void SetZero();
virtual void RightMultiply(const double* x, double* y) const;
virtual void LeftMultiply(const double* x, double* y) const;
virtual void SquaredColumnNorm(double* x) const;
virtual void ScaleColumns(const double* scale);
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
virtual void ToProto(SparseMatrixProto* proto) const;
#endif
virtual int num_rows() const { return num_rows_; }
virtual int num_cols() const { return num_cols_; }
virtual int num_nonzeros() const { return num_nonzeros_; }
virtual const double* values() const { return values_.get(); }
virtual double* mutable_values() { return values_.get(); }
// Implementation of BlockSparseMatrixBase interface.
virtual void ToTripletSparseMatrix(TripletSparseMatrix* matrix) const;
virtual const CompressedRowBlockStructure* block_structure() const;
virtual const double* RowBlockValues(int row_block_index) const {
return values_.get();
}
private:
int num_rows_;
int num_cols_;
int max_num_nonzeros_;
int num_nonzeros_;
scoped_array<double> values_;
scoped_ptr<CompressedRowBlockStructure> block_structure_;
DISALLOW_COPY_AND_ASSIGN(BlockSparseMatrix);
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_

@ -0,0 +1,92 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/block_structure.h"
#include "ceres/matrix_proto.h"
namespace ceres {
namespace internal {
bool CellLessThan(const Cell& lhs, const Cell& rhs) {
return (lhs.block_id < rhs.block_id);
}
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
void ProtoToBlockStructure(const BlockStructureProto &proto,
CompressedRowBlockStructure *block_structure) {
// Decode the column blocks.
block_structure->cols.resize(proto.cols_size());
for (int i = 0; i < proto.cols_size(); ++i) {
block_structure->cols[i].size = proto.cols(i).size();
block_structure->cols[i].position =
proto.cols(i).position();
}
// Decode the row structure.
block_structure->rows.resize(proto.rows_size());
for (int i = 0; i < proto.rows_size(); ++i) {
const CompressedRowProto &row = proto.rows(i);
block_structure->rows[i].block.size = row.block().size();
block_structure->rows[i].block.position = row.block().position();
// Copy the cells within the row.
block_structure->rows[i].cells.resize(row.cells_size());
for (int j = 0; j < row.cells_size(); ++j) {
const CellProto &cell = row.cells(j);
block_structure->rows[i].cells[j].block_id = cell.block_id();
block_structure->rows[i].cells[j].position = cell.position();
}
}
}
void BlockStructureToProto(const CompressedRowBlockStructure &block_structure,
BlockStructureProto *proto) {
// Encode the column blocks.
for (int i = 0; i < block_structure.cols.size(); ++i) {
BlockProto *block = proto->add_cols();
block->set_size(block_structure.cols[i].size);
block->set_position(block_structure.cols[i].position);
}
// Encode the row structure.
for (int i = 0; i < block_structure.rows.size(); ++i) {
CompressedRowProto *row = proto->add_rows();
BlockProto *block = row->mutable_block();
block->set_size(block_structure.rows[i].block.size);
block->set_position(block_structure.rows[i].block.position);
for (int j = 0; j < block_structure.rows[i].cells.size(); ++j) {
CellProto *cell = row->add_cells();
cell->set_block_id(block_structure.rows[i].cells[j].block_id);
cell->set_position(block_structure.rows[i].cells[j].position);
}
}
}
#endif
} // namespace internal
} // namespace ceres

@ -0,0 +1,105 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Block structure objects are used to carry information about the
// dense block structure of sparse matrices. The BlockSparseMatrix
// object uses the BlockStructure objects to keep track of the matrix
// structure and operate upon it. This allows us to use more cache
// friendly block oriented linear algebra operations on the matrix
// instead of accessing it one scalar entry at a time.
#ifndef CERES_INTERNAL_BLOCK_STRUCTURE_H_
#define CERES_INTERNAL_BLOCK_STRUCTURE_H_
#include <vector>
#include "ceres/internal/port.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
class BlockStructureProto;
typedef int16 BlockSize;
struct Block {
Block() : size(-1), position(-1) {}
Block(int size_, int position_) : size(size_), position(position_) {}
BlockSize size;
int position; // Position along the row/column.
};
struct Cell {
Cell() : block_id(-1), position(-1) {}
Cell(int block_id_, int position_)
: block_id(block_id_), position(position_) {}
// Column or row block id as the case maybe.
int block_id;
// Where in the values array of the jacobian is this cell located.
int position;
};
// Order cell by their block_id;
bool CellLessThan(const Cell& lhs, const Cell& rhs);
struct CompressedList {
Block block;
vector<Cell> cells;
};
typedef CompressedList CompressedRow;
typedef CompressedList CompressedColumn;
struct CompressedRowBlockStructure {
vector<Block> cols;
vector<CompressedRow> rows;
};
struct CompressedColumnBlockStructure {
vector<Block> rows;
vector<CompressedColumn> cols;
};
// Deserialize the given block structure proto to the given block structure.
// Destroys previous contents of block_structure.
void ProtoToBlockStructure(const BlockStructureProto &proto,
CompressedRowBlockStructure *block_structure);
// Serialize the given block structure to the given proto. Destroys previous
// contents of proto.
void BlockStructureToProto(const CompressedRowBlockStructure &block_structure,
BlockStructureProto *proto);
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_BLOCK_STRUCTURE_H_

@ -0,0 +1,238 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: David Gallup (dgallup@google.com)
// Sameer Agarwal (sameeragarwal@google.com)
#include "ceres/canonical_views_clustering.h"
#include <glog/logging.h>
#include "ceres/graph.h"
#include "ceres/collections_port.h"
#include "ceres/map_util.h"
#include "ceres/internal/macros.h"
namespace ceres {
namespace internal {
typedef HashMap<int, int> IntMap;
typedef HashSet<int> IntSet;
class CanonicalViewsClustering {
public:
CanonicalViewsClustering() {}
// Compute the canonical views clustering of the vertices of the
// graph. centers will contain the vertices that are the identified
// as the canonical views/cluster centers, and membership is a map
// from vertices to cluster_ids. The i^th cluster center corresponds
// to the i^th cluster. It is possible depending on the
// configuration of the clustering algorithm that some of the
// vertices may not be assigned to any cluster. In this case they
// are assigned to a cluster with id = kInvalidClusterId.
void ComputeClustering(const Graph<int>& graph,
const CanonicalViewsClusteringOptions& options,
vector<int>* centers,
IntMap* membership);
private:
void FindValidViews(IntSet* valid_views) const;
double ComputeClusteringQualityDifference(const int candidate,
const vector<int>& centers) const;
void UpdateCanonicalViewAssignments(const int canonical_view);
void ComputeClusterMembership(const vector<int>& centers,
IntMap* membership) const;
CanonicalViewsClusteringOptions options_;
const Graph<int>* graph_;
// Maps a view to its representative canonical view (its cluster
// center).
IntMap view_to_canonical_view_;
// Maps a view to its similarity to its current cluster center.
HashMap<int, double> view_to_canonical_view_similarity_;
DISALLOW_COPY_AND_ASSIGN(CanonicalViewsClustering);
};
void ComputeCanonicalViewsClustering(
const Graph<int>& graph,
const CanonicalViewsClusteringOptions& options,
vector<int>* centers,
IntMap* membership) {
time_t start_time = time(NULL);
CanonicalViewsClustering cv;
cv.ComputeClustering(graph, options, centers, membership);
VLOG(2) << "Canonical views clustering time (secs): "
<< time(NULL) - start_time;
}
// Implementation of CanonicalViewsClustering
void CanonicalViewsClustering::ComputeClustering(
const Graph<int>& graph,
const CanonicalViewsClusteringOptions& options,
vector<int>* centers,
IntMap* membership) {
options_ = options;
CHECK_NOTNULL(centers)->clear();
CHECK_NOTNULL(membership)->clear();
graph_ = &graph;
IntSet valid_views;
FindValidViews(&valid_views);
while (valid_views.size() > 0) {
// Find the next best canonical view.
double best_difference = -std::numeric_limits<double>::max();
int best_view = 0;
// TODO(sameeragarwal): Make this loop multi-threaded.
for (IntSet::const_iterator view = valid_views.begin();
view != valid_views.end();
++view) {
const double difference =
ComputeClusteringQualityDifference(*view, *centers);
if (difference > best_difference) {
best_difference = difference;
best_view = *view;
}
}
CHECK_GT(best_difference, -std::numeric_limits<double>::max());
// Add canonical view if quality improves, or if minimum is not
// yet met, otherwise break.
if ((best_difference <= 0) &&
(centers->size() >= options_.min_views)) {
break;
}
centers->push_back(best_view);
valid_views.erase(best_view);
UpdateCanonicalViewAssignments(best_view);
}
ComputeClusterMembership(*centers, membership);
}
// Return the set of vertices of the graph which have valid vertex
// weights.
void CanonicalViewsClustering::FindValidViews(
IntSet* valid_views) const {
const IntSet& views = graph_->vertices();
for (IntSet::const_iterator view = views.begin();
view != views.end();
++view) {
if (graph_->VertexWeight(*view) != Graph<int>::InvalidWeight()) {
valid_views->insert(*view);
}
}
}
// Computes the difference in the quality score if 'candidate' were
// added to the set of canonical views.
double CanonicalViewsClustering::ComputeClusteringQualityDifference(
const int candidate,
const vector<int>& centers) const {
// View score.
double difference =
options_.view_score_weight * graph_->VertexWeight(candidate);
// Compute how much the quality score changes if the candidate view
// was added to the list of canonical views and its nearest
// neighbors became members of its cluster.
const IntSet& neighbors = graph_->Neighbors(candidate);
for (IntSet::const_iterator neighbor = neighbors.begin();
neighbor != neighbors.end();
++neighbor) {
const double old_similarity =
FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0);
const double new_similarity = graph_->EdgeWeight(*neighbor, candidate);
if (new_similarity > old_similarity) {
difference += new_similarity - old_similarity;
}
}
// Number of views penalty.
difference -= options_.size_penalty_weight;
// Orthogonality.
for (int i = 0; i < centers.size(); ++i) {
difference -= options_.similarity_penalty_weight *
graph_->EdgeWeight(centers[i], candidate);
}
return difference;
}
// Reassign views if they're more similar to the new canonical view.
void CanonicalViewsClustering::UpdateCanonicalViewAssignments(
const int canonical_view) {
const IntSet& neighbors = graph_->Neighbors(canonical_view);
for (IntSet::const_iterator neighbor = neighbors.begin();
neighbor != neighbors.end();
++neighbor) {
const double old_similarity =
FindWithDefault(view_to_canonical_view_similarity_, *neighbor, 0.0);
const double new_similarity =
graph_->EdgeWeight(*neighbor, canonical_view);
if (new_similarity > old_similarity) {
view_to_canonical_view_[*neighbor] = canonical_view;
view_to_canonical_view_similarity_[*neighbor] = new_similarity;
}
}
}
// Assign a cluster id to each view.
void CanonicalViewsClustering::ComputeClusterMembership(
const vector<int>& centers,
IntMap* membership) const {
CHECK_NOTNULL(membership)->clear();
// The i^th cluster has cluster id i.
IntMap center_to_cluster_id;
for (int i = 0; i < centers.size(); ++i) {
center_to_cluster_id[centers[i]] = i;
}
static const int kInvalidClusterId = -1;
const IntSet& views = graph_->vertices();
for (IntSet::const_iterator view = views.begin();
view != views.end();
++view) {
IntMap::const_iterator it =
view_to_canonical_view_.find(*view);
int cluster_id = kInvalidClusterId;
if (it != view_to_canonical_view_.end()) {
cluster_id = FindOrDie(center_to_cluster_id, it->second);
}
InsertOrDie(membership, *view, cluster_id);
}
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,133 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// An implementation of the Canonical Views clustering algorithm from
// "Scene Summarization for Online Image Collections", Ian Simon, Noah
// Snavely, Steven M. Seitz, ICCV 2007.
//
// More details can be found at
// http://grail.cs.washington.edu/projects/canonview/
//
// Ceres uses this algorithm to perform view clustering for
// constructing visibility based preconditioners.
#ifndef CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_
#define CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_
#include <vector>
#include <glog/logging.h>
#include "ceres/collections_port.h"
#include "ceres/graph.h"
#include "ceres/map_util.h"
#include "ceres/internal/macros.h"
namespace ceres {
namespace internal {
class CanonicalViewsClusteringOptions;
// Compute a partitioning of the vertices of the graph using the
// canonical views clustering algorithm.
//
// In the following we will use the terms vertices and views
// interchangably. Given a weighted Graph G(V,E), the canonical views
// of G are the the set of vertices that best "summarize" the content
// of the graph. If w_ij i s the weight connecting the vertex i to
// vertex j, and C is the set of canonical views. Then the objective
// of the canonical views algorithm is
//
// E[C] = sum_[i in V] max_[j in C] w_ij
// - size_penalty_weight * |C|
// - similarity_penalty_weight * sum_[i in C, j in C, j > i] w_ij
//
// alpha is the size penalty that penalizes large number of canonical
// views.
//
// beta is the similarity penalty that penalizes canonical views that
// are too similar to other canonical views.
//
// Thus the canonical views algorithm tries to find a canonical view
// for each vertex in the graph which best explains it, while trying
// to minimize the number of canonical views and the overlap between
// them.
//
// We further augment the above objective function by allowing for per
// vertex weights, higher weights indicating a higher preference for
// being chosen as a canonical view. Thus if w_i is the vertex weight
// for vertex i, the objective function is then
//
// E[C] = sum_[i in V] max_[j in C] w_ij
// - size_penalty_weight * |C|
// - similarity_penalty_weight * sum_[i in C, j in C, j > i] w_ij
// + view_score_weight * sum_[i in C] w_i
//
// centers will contain the vertices that are the identified
// as the canonical views/cluster centers, and membership is a map
// from vertices to cluster_ids. The i^th cluster center corresponds
// to the i^th cluster.
//
// It is possible depending on the configuration of the clustering
// algorithm that some of the vertices may not be assigned to any
// cluster. In this case they are assigned to a cluster with id = -1;
void ComputeCanonicalViewsClustering(
const Graph<int>& graph,
const CanonicalViewsClusteringOptions& options,
vector<int>* centers,
HashMap<int, int>* membership);
struct CanonicalViewsClusteringOptions {
CanonicalViewsClusteringOptions()
: min_views(3),
size_penalty_weight(5.75),
similarity_penalty_weight(100.0),
view_score_weight(0.0) {
}
// The minimum number of canonical views to compute.
int min_views;
// Penalty weight for the number of canonical views. A higher
// number will result in fewer canonical views.
double size_penalty_weight;
// Penalty weight for the diversity (orthogonality) of the
// canonical views. A higher number will encourage less similar
// canonical views.
double similarity_penalty_weight;
// Weight for per-view scores. Lower weight places less
// confidence in the view scores.
double view_score_weight;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_

@ -0,0 +1,108 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#ifndef CERES_INTERNAL_CASTS_H_
#define CERES_INTERNAL_CASTS_H_
#include <cassert>
#include <cstddef> // For NULL.
namespace ceres {
// Identity metafunction.
template <class T>
struct identity_ {
typedef T type;
};
// Use implicit_cast as a safe version of static_cast or const_cast
// for implicit conversions. For example:
// - Upcasting in a type hierarchy.
// - Performing arithmetic conversions (int32 to int64, int to double, etc.).
// - Adding const or volatile qualifiers.
//
// In general, implicit_cast can be used to convert this code
// To to = from;
// DoSomething(to);
// to this
// DoSomething(implicit_cast<To>(from));
//
// base::identity_ is used to make a non-deduced context, which
// forces all callers to explicitly specify the template argument.
template<typename To>
inline To implicit_cast(typename identity_<To>::type to) {
return to;
}
// This version of implicit_cast is used when two template arguments
// are specified. It's obsolete and should not be used.
template<typename To, typename From>
inline To implicit_cast(typename identity_<From>::type const &f) {
return f;
}
// When you upcast (that is, cast a pointer from type Foo to type
// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
// always succeed. When you downcast (that is, cast a pointer from
// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
// how do you know the pointer is really of type SubclassOfFoo? It
// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
// when you downcast, you should use this macro. In debug mode, we
// use dynamic_cast<> to double-check the downcast is legal (we die
// if it's not). In normal mode, we do the efficient static_cast<>
// instead. Thus, it's important to test in debug mode to make sure
// the cast is legal!
// This is the only place in the code we should use dynamic_cast<>.
// In particular, you SHOULDN'T be using dynamic_cast<> in order to
// do RTTI (eg code like this:
// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
// You should design the code some other way not to need this.
template<typename To, typename From> // use like this: down_cast<T*>(foo);
inline To down_cast(From* f) { // so we only accept pointers
// Ensures that To is a sub-type of From *. This test is here only
// for compile-time type checking, and has no overhead in an
// optimized build at run-time, as it will be optimized away
// completely.
// TODO(csilvers): This should use COMPILE_ASSERT.
if (false) {
implicit_cast<From*, To>(NULL);
}
// uses RTTI in dbg and fastbuild. asserts are disabled in opt builds.
assert(f == NULL || dynamic_cast<To>(f) != NULL); // NOLINT
return static_cast<To>(f);
}
} // namespace ceres
#endif // CERES_INTERNAL_CASTS_H_

@ -0,0 +1,120 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#ifndef CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_
#define CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_
#include <algorithm>
#include "ceres/linear_operator.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
class SparseMatrix;
// A linear operator which takes a matrix A and a diagonal vector D and
// performs products of the form
//
// (A^T A + D^T D)x
//
// This is used to implement iterative general sparse linear solving with
// conjugate gradients, where A is the Jacobian and D is a regularizing
// parameter. A brief proof that D^T D is the correct regularizer:
//
// Given a regularized least squares problem:
//
// min ||Ax - b||^2 + ||Dx||^2
// x
//
// First expand into matrix notation:
//
// (Ax - b)^T (Ax - b) + xD^TDx
//
// Then multiply out to get:
//
// = xA^TAx - 2b^T Ax + b^Tb + xD^TDx
//
// Take the derivative:
//
// 0 = 2A^TAx - 2A^T b + 2 D^TDx
// 0 = A^TAx - A^T b + D^TDx
// 0 = (A^TA + D^TD)x - A^T b
//
// Thus, the symmetric system we need to solve for CGNR is
//
// Sx = z
//
// with S = A^TA + D^TD
// and z = A^T b
//
// Note: This class is not thread safe, since it uses some temporary storage.
class CgnrLinearOperator : public LinearOperator {
public:
CgnrLinearOperator(const LinearOperator& A, const double *D)
: A_(A), D_(D), z_(new double[A.num_rows()]) {
}
virtual ~CgnrLinearOperator() {}
virtual void RightMultiply(const double* x, double* y) const {
std::fill(z_.get(), z_.get() + A_.num_rows(), 0.0);
// z = Ax
A_.RightMultiply(x, z_.get());
// y = y + Atz
A_.LeftMultiply(z_.get(), y);
// y = y + DtDx
if (D_ != NULL) {
int n = A_.num_cols();
VectorRef(y, n).array() += ConstVectorRef(D_, n).array().square() *
ConstVectorRef(x, n).array();
}
}
virtual void LeftMultiply(const double* x, double* y) const {
RightMultiply(x, y);
}
virtual int num_rows() const { return A_.num_cols(); }
virtual int num_cols() const { return A_.num_cols(); }
private:
const LinearOperator& A_;
const double* D_;
scoped_array<double> z_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_

@ -0,0 +1,80 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#include "ceres/cgnr_solver.h"
#include "glog/logging.h"
#include "ceres/linear_solver.h"
#include "ceres/cgnr_linear_operator.h"
#include "ceres/conjugate_gradients_solver.h"
#include "ceres/block_jacobi_preconditioner.h"
namespace ceres {
namespace internal {
CgnrSolver::CgnrSolver(const LinearSolver::Options& options)
: options_(options),
jacobi_preconditioner_(NULL) {
}
LinearSolver::Summary CgnrSolver::Solve(
LinearOperator* A,
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
// Form z = Atb.
scoped_array<double> z(new double[A->num_cols()]);
std::fill(z.get(), z.get() + A->num_cols(), 0.0);
A->LeftMultiply(b, z.get());
// Precondition if necessary.
LinearSolver::PerSolveOptions cg_per_solve_options = per_solve_options;
if (options_.preconditioner_type == JACOBI) {
if (jacobi_preconditioner_.get() == NULL) {
jacobi_preconditioner_.reset(new BlockJacobiPreconditioner(*A));
}
jacobi_preconditioner_->Update(*A, per_solve_options.D);
cg_per_solve_options.preconditioner = jacobi_preconditioner_.get();
} else if (options_.preconditioner_type != IDENTITY) {
LOG(FATAL) << "CGNR only supports IDENTITY and JACOBI preconditioners.";
}
// Solve (AtA + DtD)x = z (= Atb).
std::fill(x, x + A->num_cols(), 0.0);
CgnrLinearOperator lhs(*A, per_solve_options.D);
ConjugateGradientsSolver conjugate_gradient_solver(options_);
return conjugate_gradient_solver.Solve(&lhs,
z.get(),
cg_per_solve_options,
x);
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,66 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#ifndef CERES_INTERNAL_CGNR_SOLVER_H_
#define CERES_INTERNAL_CGNR_SOLVER_H_
#include "ceres/internal/scoped_ptr.h"
#include "ceres/linear_solver.h"
namespace ceres {
namespace internal {
class BlockJacobiPreconditioner;
// A conjugate gradients on the normal equations solver. This directly solves
// for the solution to
//
// (A^T A + D^T D)x = A^T b
//
// as required for solving for x in the least squares sense. Currently only
// block diagonal preconditioning is supported.
class CgnrSolver : public LinearSolver {
public:
explicit CgnrSolver(const LinearSolver::Options& options);
virtual Summary Solve(LinearOperator* A,
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x);
private:
const LinearSolver::Options options_;
scoped_ptr<BlockJacobiPreconditioner> jacobi_preconditioner_;
DISALLOW_COPY_AND_ASSIGN(CgnrSolver);
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_CGNR_SOLVER_H_

@ -0,0 +1,141 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// Portable HashMap and HashSet, and a specialized overload for hashing pairs.
#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_
#define CERES_INTERNAL_COLLECTIONS_PORT_H_
#if defined(_MSC_VER) && _MSC_VER <= 1600
#include <unordered_map>
#include <unordered_set>
#else
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#endif
#include <utility>
#include "ceres/integral_types.h"
#include "ceres/internal/port.h"
namespace ceres {
namespace internal {
template<typename K, typename V>
struct HashMap : tr1::unordered_map<K, V> {};
template<typename K>
struct HashSet : tr1::unordered_set<K> {};
#ifdef _WIN32
#define GG_LONGLONG(x) x##I64
#define GG_ULONGLONG(x) x##UI64
#else
#define GG_LONGLONG(x) x##LL
#define GG_ULONGLONG(x) x##ULL
#endif
// The hash function is due to Bob Jenkins (see
// http://burtleburtle.net/bob/hash/index.html). Each mix takes 36 instructions,
// in 18 cycles if you're lucky. On x86 architectures, this requires 45
// instructions in 27 cycles, if you're lucky.
//
// 32bit version
inline void hash_mix(uint32& a, uint32& b, uint32& c) {
a -= b; a -= c; a ^= (c>>13);
b -= c; b -= a; b ^= (a<<8);
c -= a; c -= b; c ^= (b>>13);
a -= b; a -= c; a ^= (c>>12);
b -= c; b -= a; b ^= (a<<16);
c -= a; c -= b; c ^= (b>>5);
a -= b; a -= c; a ^= (c>>3);
b -= c; b -= a; b ^= (a<<10);
c -= a; c -= b; c ^= (b>>15);
}
// 64bit version
inline void hash_mix(uint64& a, uint64& b, uint64& c) {
a -= b; a -= c; a ^= (c>>43);
b -= c; b -= a; b ^= (a<<9);
c -= a; c -= b; c ^= (b>>8);
a -= b; a -= c; a ^= (c>>38);
b -= c; b -= a; b ^= (a<<23);
c -= a; c -= b; c ^= (b>>5);
a -= b; a -= c; a ^= (c>>35);
b -= c; b -= a; b ^= (a<<49);
c -= a; c -= b; c ^= (b>>11);
}
inline uint32 Hash32NumWithSeed(uint32 num, uint32 c) {
// The golden ratio; an arbitrary value.
uint32 b = 0x9e3779b9UL;
hash_mix(num, b, c);
return c;
}
inline uint64 Hash64NumWithSeed(uint64 num, uint64 c) {
// More of the golden ratio.
uint64 b = GG_ULONGLONG(0xe08c1d668b756f82);
hash_mix(num, b, c);
return c;
}
} // namespace internal
} // namespace ceres
// Since on some platforms this is a doubly-nested namespace (std::tr1) and
// others it is not, the entire namespace line must be in a macro.
CERES_HASH_NAMESPACE_START
// The outrageously annoying specializations below are for portability reasons.
// In short, it's not possible to have two overloads of hash<pair<T1, T2>
// Hasher for STL pairs. Requires hashers for both members to be defined.
template<typename T>
struct hash<pair<T, T> > {
size_t operator()(const pair<T, T>& p) const {
size_t h1 = hash<T>()(p.first);
size_t h2 = hash<T>()(p.second);
// The decision below is at compile time
return (sizeof(h1) <= sizeof(ceres::internal::uint32)) ?
ceres::internal::Hash32NumWithSeed(h1, h2) :
ceres::internal::Hash64NumWithSeed(h1, h2);
}
// Less than operator for MSVC.
bool operator()(const pair<T, T>& a,
const pair<T, T>& b) const {
return a < b;
}
static const size_t bucket_size = 4; // These are required by MSVC
static const size_t min_buckets = 8; // 4 and 8 are defaults.
};
CERES_HASH_NAMESPACE_END
#endif // CERES_INTERNAL_COLLECTIONS_PORT_H_

@ -0,0 +1,201 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#include "ceres/compressed_row_jacobian_writer.h"
#include "ceres/casts.h"
#include "ceres/compressed_row_sparse_matrix.h"
#include "ceres/parameter_block.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
#include "ceres/scratch_evaluate_preparer.h"
namespace ceres {
namespace internal {
SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const {
const vector<ResidualBlock*>& residual_blocks =
program_->residual_blocks();
int total_num_residuals = program_->NumResiduals();
int total_num_effective_parameters = program_->NumEffectiveParameters();
// Count the number of jacobian nonzeros.
int num_jacobian_nonzeros = 0;
for (int i = 0; i < residual_blocks.size(); ++i) {
ResidualBlock* residual_block = residual_blocks[i];
const int num_residuals = residual_block->NumResiduals();
const int num_parameter_blocks = residual_block->NumParameterBlocks();
for (int j = 0; j < num_parameter_blocks; ++j) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
if (!parameter_block->IsConstant()) {
num_jacobian_nonzeros += num_residuals * parameter_block->LocalSize();
}
}
}
// Allocate storage for the jacobian with some extra space at the end.
// Allocate more space than needed to store the jacobian so that when the LM
// algorithm adds the diagonal, no reallocation is necessary. This reduces
// peak memory usage significantly.
CompressedRowSparseMatrix* jacobian =
new CompressedRowSparseMatrix(
total_num_residuals,
total_num_effective_parameters,
num_jacobian_nonzeros + total_num_effective_parameters);
// At this stage, the CompressedSparseMatrix is an invalid state. But this
// seems to be the only way to construct it without doing a memory copy.
int* rows = jacobian->mutable_rows();
int* cols = jacobian->mutable_cols();
int row_pos = 0;
rows[0] = 0;
for (int i = 0; i < residual_blocks.size(); ++i) {
const ResidualBlock* residual_block = residual_blocks[i];
const int num_parameter_blocks = residual_block->NumParameterBlocks();
// Count the number of derivatives for a row of this residual block and
// build a list of active parameter block indices.
int num_derivatives = 0;
vector<int> parameter_indices;
for (int j = 0; j < num_parameter_blocks; ++j) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
if (!parameter_block->IsConstant()) {
parameter_indices.push_back(parameter_block->index());
num_derivatives += parameter_block->LocalSize();
}
}
// Sort the parameters by their position in the state vector.
sort(parameter_indices.begin(), parameter_indices.end());
CHECK(unique(parameter_indices.begin(), parameter_indices.end()) ==
parameter_indices.end())
<< "Ceres internal error: "
<< "Duplicate parameter blocks detected in a cost function. "
<< "This should never happen. Please report this to "
<< "the Ceres developers.";
// Update the row indices.
const int num_residuals = residual_block->NumResiduals();
for (int j = 0; j < num_residuals; ++j) {
rows[row_pos + j + 1] = rows[row_pos + j] + num_derivatives;
}
// Iterate over parameter blocks in the order which they occur in the
// parameter vector. This code mirrors that in Write(), where jacobian
// values are updated.
int col_pos = 0;
for (int j = 0; j < parameter_indices.size(); ++j) {
ParameterBlock* parameter_block =
program_->parameter_blocks()[parameter_indices[j]];
const int parameter_block_size = parameter_block->LocalSize();
for (int r = 0; r < num_residuals; ++r) {
// This is the position in the values array of the jacobian where this
// row of the jacobian block should go.
const int column_block_begin = rows[row_pos + r] + col_pos;
for (int c = 0; c < parameter_block_size; ++c) {
cols[column_block_begin + c] = parameter_block->delta_offset() + c;
}
}
col_pos += parameter_block_size;
}
row_pos += num_residuals;
}
CHECK_EQ(num_jacobian_nonzeros, rows[total_num_residuals]);
return jacobian;
}
void CompressedRowJacobianWriter::Write(int residual_id,
int residual_offset,
double **jacobians,
SparseMatrix* base_jacobian) {
CompressedRowSparseMatrix* jacobian =
down_cast<CompressedRowSparseMatrix*>(base_jacobian);
double* jacobian_values = jacobian->mutable_values();
const int* jacobian_rows = jacobian->rows();
const ResidualBlock* residual_block =
program_->residual_blocks()[residual_id];
const int num_parameter_blocks = residual_block->NumParameterBlocks();
const int num_residuals = residual_block->NumResiduals();
// It is necessary to determine the order of the jacobian blocks before
// copying them into the CompressedRowSparseMatrix. Just because a cost
// function uses parameter blocks 1 after 2 in its arguments does not mean
// that the block 1 occurs before block 2 in the column layout of the
// jacobian. Thus, determine the order by sorting the jacobian blocks by their
// position in the state vector.
vector<pair<int, int> > evaluated_jacobian_blocks;
for (int j = 0; j < num_parameter_blocks; ++j) {
const ParameterBlock* parameter_block =
residual_block->parameter_blocks()[j];
if (!parameter_block->IsConstant()) {
evaluated_jacobian_blocks.push_back(
make_pair(parameter_block->index(), j));
}
}
sort(evaluated_jacobian_blocks.begin(), evaluated_jacobian_blocks.end());
// Where in the current row does the jacobian for a parameter block begin.
int col_pos = 0;
// Iterate over the jacobian blocks in increasing order of their
// positions in the reduced parameter vector.
for (int i = 0; i < evaluated_jacobian_blocks.size(); ++i) {
const ParameterBlock* parameter_block =
program_->parameter_blocks()[evaluated_jacobian_blocks[i].first];
const int argument = evaluated_jacobian_blocks[i].second;
const int parameter_block_size = parameter_block->LocalSize();
// Copy one row of the jacobian block at a time.
for (int r = 0; r < num_residuals; ++r) {
// Position of the r^th row of the current jacobian block.
const double* block_row_begin =
jacobians[argument] + r * parameter_block_size;
// Position in the values array of the jacobian where this
// row of the jacobian block should go.
double* column_block_begin =
jacobian_values + jacobian_rows[residual_offset + r] + col_pos;
copy(block_row_begin,
block_row_begin + parameter_block_size,
column_block_begin);
}
col_pos += parameter_block_size;
}
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,75 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// A jacobian writer that directly writes to compressed row sparse matrices.
#ifndef CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_
#define CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_
#include "ceres/evaluator.h"
#include "ceres/scratch_evaluate_preparer.h"
namespace ceres {
namespace internal {
class Program;
class SparseMatrix;
class CompressedRowJacobianWriter {
public:
CompressedRowJacobianWriter(Evaluator::Options /* ignored */,
Program* program)
: program_(program) {
}
// JacobianWriter interface.
// Since the compressed row matrix has different layout than that assumed by
// the cost functions, use scratch space to store the jacobians temporarily
// then copy them over to the larger jacobian in the Write() function.
ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads) {
return ScratchEvaluatePreparer::Create(*program_, num_threads);
}
SparseMatrix* CreateJacobian() const;
void Write(int residual_id,
int residual_offset,
double **jacobians,
SparseMatrix* base_jacobian);
private:
Program* program_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_

@ -0,0 +1,325 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/compressed_row_sparse_matrix.h"
#include <algorithm>
#include <vector>
#include "ceres/matrix_proto.h"
#include "ceres/internal/port.h"
namespace ceres {
namespace internal {
namespace {
// Helper functor used by the constructor for reordering the contents
// of a TripletSparseMatrix.
struct RowColLessThan {
RowColLessThan(const int* rows, const int* cols)
: rows(rows), cols(cols) {
}
bool operator()(const int x, const int y) const {
if (rows[x] == rows[y]) {
return (cols[x] < cols[y]);
}
return (rows[x] < rows[y]);
}
const int* rows;
const int* cols;
};
} // namespace
// This constructor gives you a semi-initialized CompressedRowSparseMatrix.
CompressedRowSparseMatrix::CompressedRowSparseMatrix(int num_rows,
int num_cols,
int max_num_nonzeros) {
num_rows_ = num_rows;
num_cols_ = num_cols;
max_num_nonzeros_ = max_num_nonzeros;
VLOG(1) << "# of rows: " << num_rows_ << " # of columns: " << num_cols_
<< " max_num_nonzeros: " << max_num_nonzeros_
<< ". Allocating " << (num_rows_ + 1) * sizeof(int) + // NOLINT
max_num_nonzeros_ * sizeof(int) + // NOLINT
max_num_nonzeros_ * sizeof(double); // NOLINT
rows_.reset(new int[num_rows_ + 1]);
cols_.reset(new int[max_num_nonzeros_]);
values_.reset(new double[max_num_nonzeros_]);
fill(rows_.get(), rows_.get() + num_rows_ + 1, 0);
fill(cols_.get(), cols_.get() + max_num_nonzeros_, 0);
fill(values_.get(), values_.get() + max_num_nonzeros_, 0);
}
CompressedRowSparseMatrix::CompressedRowSparseMatrix(
const TripletSparseMatrix& m) {
num_rows_ = m.num_rows();
num_cols_ = m.num_cols();
max_num_nonzeros_ = m.max_num_nonzeros();
// index is the list of indices into the TripletSparseMatrix m.
vector<int> index(m.num_nonzeros(), 0);
for (int i = 0; i < m.num_nonzeros(); ++i) {
index[i] = i;
}
// Sort index such that the entries of m are ordered by row and ties
// are broken by column.
sort(index.begin(), index.end(), RowColLessThan(m.rows(), m.cols()));
VLOG(1) << "# of rows: " << num_rows_ << " # of columns: " << num_cols_
<< " max_num_nonzeros: " << max_num_nonzeros_
<< ". Allocating " << (num_rows_ + 1) * sizeof(int) + // NOLINT
max_num_nonzeros_ * sizeof(int) + // NOLINT
max_num_nonzeros_ * sizeof(double); // NOLINT
rows_.reset(new int[num_rows_ + 1]);
cols_.reset(new int[max_num_nonzeros_]);
values_.reset(new double[max_num_nonzeros_]);
// rows_ = 0
fill(rows_.get(), rows_.get() + num_rows_ + 1, 0);
// Copy the contents of the cols and values array in the order given
// by index and count the number of entries in each row.
for (int i = 0; i < m.num_nonzeros(); ++i) {
const int idx = index[i];
++rows_[m.rows()[idx] + 1];
cols_[i] = m.cols()[idx];
values_[i] = m.values()[idx];
}
// Find the cumulative sum of the row counts.
for (int i = 1; i < num_rows_ + 1; ++i) {
rows_[i] += rows_[i-1];
}
CHECK_EQ(num_nonzeros(), m.num_nonzeros());
}
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
CompressedRowSparseMatrix::CompressedRowSparseMatrix(
const SparseMatrixProto& outer_proto) {
CHECK(outer_proto.has_compressed_row_matrix());
const CompressedRowSparseMatrixProto& proto =
outer_proto.compressed_row_matrix();
num_rows_ = proto.num_rows();
num_cols_ = proto.num_cols();
rows_.reset(new int[proto.rows_size()]);
cols_.reset(new int[proto.cols_size()]);
values_.reset(new double[proto.values_size()]);
for (int i = 0; i < proto.rows_size(); ++i) {
rows_[i] = proto.rows(i);
}
CHECK_EQ(proto.rows_size(), num_rows_ + 1);
CHECK_EQ(proto.cols_size(), proto.values_size());
CHECK_EQ(proto.cols_size(), rows_[num_rows_]);
for (int i = 0; i < proto.cols_size(); ++i) {
cols_[i] = proto.cols(i);
values_[i] = proto.values(i);
}
max_num_nonzeros_ = proto.cols_size();
}
#endif
CompressedRowSparseMatrix::CompressedRowSparseMatrix(const double* diagonal,
int num_rows) {
CHECK_NOTNULL(diagonal);
num_rows_ = num_rows;
num_cols_ = num_rows;
max_num_nonzeros_ = num_rows;
rows_.reset(new int[num_rows_ + 1]);
cols_.reset(new int[num_rows_]);
values_.reset(new double[num_rows_]);
rows_[0] = 0;
for (int i = 0; i < num_rows_; ++i) {
cols_[i] = i;
values_[i] = diagonal[i];
rows_[i + 1] = i + 1;
}
CHECK_EQ(num_nonzeros(), num_rows);
}
CompressedRowSparseMatrix::~CompressedRowSparseMatrix() {
}
void CompressedRowSparseMatrix::SetZero() {
fill(values_.get(), values_.get() + num_nonzeros(), 0.0);
}
void CompressedRowSparseMatrix::RightMultiply(const double* x,
double* y) const {
CHECK_NOTNULL(x);
CHECK_NOTNULL(y);
for (int r = 0; r < num_rows_; ++r) {
for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) {
y[r] += values_[idx] * x[cols_[idx]];
}
}
}
void CompressedRowSparseMatrix::LeftMultiply(const double* x, double* y) const {
CHECK_NOTNULL(x);
CHECK_NOTNULL(y);
for (int r = 0; r < num_rows_; ++r) {
for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) {
y[cols_[idx]] += values_[idx] * x[r];
}
}
}
void CompressedRowSparseMatrix::SquaredColumnNorm(double* x) const {
CHECK_NOTNULL(x);
fill(x, x + num_cols_, 0.0);
for (int idx = 0; idx < rows_[num_rows_]; ++idx) {
x[cols_[idx]] += values_[idx] * values_[idx];
}
}
void CompressedRowSparseMatrix::ScaleColumns(const double* scale) {
CHECK_NOTNULL(scale);
for (int idx = 0; idx < rows_[num_rows_]; ++idx) {
values_[idx] *= scale[cols_[idx]];
}
}
void CompressedRowSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
CHECK_NOTNULL(dense_matrix);
dense_matrix->resize(num_rows_, num_cols_);
dense_matrix->setZero();
for (int r = 0; r < num_rows_; ++r) {
for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) {
(*dense_matrix)(r, cols_[idx]) = values_[idx];
}
}
}
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
void CompressedRowSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
CHECK_NOTNULL(outer_proto);
outer_proto->Clear();
CompressedRowSparseMatrixProto* proto
= outer_proto->mutable_compressed_row_matrix();
proto->set_num_rows(num_rows_);
proto->set_num_cols(num_cols_);
for (int r = 0; r < num_rows_ + 1; ++r) {
proto->add_rows(rows_[r]);
}
for (int idx = 0; idx < rows_[num_rows_]; ++idx) {
proto->add_cols(cols_[idx]);
proto->add_values(values_[idx]);
}
}
#endif
void CompressedRowSparseMatrix::DeleteRows(int delta_rows) {
CHECK_GE(delta_rows, 0);
CHECK_LE(delta_rows, num_rows_);
int new_num_rows = num_rows_ - delta_rows;
num_rows_ = new_num_rows;
int* new_rows = new int[num_rows_ + 1];
copy(rows_.get(), rows_.get() + num_rows_ + 1, new_rows);
rows_.reset(new_rows);
}
void CompressedRowSparseMatrix::AppendRows(const CompressedRowSparseMatrix& m) {
CHECK_EQ(m.num_cols(), num_cols_);
// Check if there is enough space. If not, then allocate new arrays
// to hold the combined matrix and copy the contents of this matrix
// into it.
if (max_num_nonzeros_ < num_nonzeros() + m.num_nonzeros()) {
int new_max_num_nonzeros = num_nonzeros() + m.num_nonzeros();
VLOG(1) << "Reallocating " << sizeof(int) * new_max_num_nonzeros; // NOLINT
int* new_cols = new int[new_max_num_nonzeros];
copy(cols_.get(), cols_.get() + max_num_nonzeros_, new_cols);
cols_.reset(new_cols);
double* new_values = new double[new_max_num_nonzeros];
copy(values_.get(), values_.get() + max_num_nonzeros_, new_values);
values_.reset(new_values);
max_num_nonzeros_ = new_max_num_nonzeros;
}
// Copy the contents of m into this matrix.
copy(m.cols(), m.cols() + m.num_nonzeros(), cols_.get() + num_nonzeros());
copy(m.values(),
m.values() + m.num_nonzeros(),
values_.get() + num_nonzeros());
// Create the new rows array to hold the enlarged matrix.
int* new_rows = new int[num_rows_ + m.num_rows() + 1];
// The first num_rows_ entries are the same
copy(rows_.get(), rows_.get() + num_rows_, new_rows);
// new_rows = [rows_, m.row() + rows_[num_rows_]]
fill(new_rows + num_rows_,
new_rows + num_rows_ + m.num_rows() + 1,
rows_[num_rows_]);
for (int r = 0; r < m.num_rows() + 1; ++r) {
new_rows[num_rows_ + r] += m.rows()[r];
}
rows_.reset(new_rows);
num_rows_ += m.num_rows();
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,129 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_
#define CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_
#include <glog/logging.h>
#include "ceres/sparse_matrix.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/macros.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
class SparseMatrixProto;
class CompressedRowSparseMatrix : public SparseMatrix {
public:
// Build a matrix with the same content as the TripletSparseMatrix
// m. TripletSparseMatrix objects are easier to construct
// incrementally, so we use them to initialize SparseMatrix
// objects.
//
// We assume that m does not have any repeated entries.
explicit CompressedRowSparseMatrix(const TripletSparseMatrix& m);
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
explicit CompressedRowSparseMatrix(const SparseMatrixProto& proto);
#endif
// Use this constructor only if you know what you are doing. This
// creates a "blank" matrix with the appropriate amount of memory
// allocated. However, the object itself is in an inconsistent state
// as the rows and cols matrices do not match the values of
// num_rows, num_cols and max_num_nonzeros.
//
// The use case for this constructor is that when the user knows the
// size of the matrix to begin with and wants to update the layout
// manually, instead of going via the indirect route of first
// constructing a TripletSparseMatrix, which leads to more than
// double the peak memory usage.
CompressedRowSparseMatrix(int num_rows,
int num_cols,
int max_num_nonzeros);
// Build a square sparse diagonal matrix with num_rows rows and
// columns. The diagonal m(i,i) = diagonal(i);
CompressedRowSparseMatrix(const double* diagonal, int num_rows);
virtual ~CompressedRowSparseMatrix();
// SparseMatrix interface.
virtual void SetZero();
virtual void RightMultiply(const double* x, double* y) const;
virtual void LeftMultiply(const double* x, double* y) const;
virtual void SquaredColumnNorm(double* x) const;
virtual void ScaleColumns(const double* scale);
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
virtual void ToProto(SparseMatrixProto* proto) const;
#endif
virtual int num_rows() const { return num_rows_; }
virtual int num_cols() const { return num_cols_; }
virtual int num_nonzeros() const { return rows_[num_rows_]; }
virtual const double* values() const { return values_.get(); }
virtual double* mutable_values() { return values_.get(); }
// Delete the bottom delta_rows.
// num_rows -= delta_rows
void DeleteRows(int delta_rows);
// Append the contents of m to the bottom of this matrix. m must
// have the same number of columns as this matrix.
void AppendRows(const CompressedRowSparseMatrix& m);
// Low level access methods that expose the structure of the matrix.
const int* cols() const { return cols_.get(); }
int* mutable_cols() { return cols_.get(); }
const int* rows() const { return rows_.get(); }
int* mutable_rows() { return rows_.get(); }
private:
scoped_array<int> cols_;
scoped_array<int> rows_;
scoped_array<double> values_;
int num_rows_;
int num_cols_;
int max_num_nonzeros_;
DISALLOW_COPY_AND_ASSIGN(CompressedRowSparseMatrix);
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_

@ -0,0 +1,130 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: wjr@google.com (William Rucklidge)
//
// This file contains the implementation of the conditioned cost function.
#include "ceres/conditioned_cost_function.h"
#include <cstddef>
#include <glog/logging.h>
#include "ceres/stl_util.h"
#include "ceres/internal/eigen.h"
#include "ceres/types.h"
namespace ceres {
// This cost function has the same dimensions (parameters, residuals) as
// the one it's wrapping.
ConditionedCostFunction::ConditionedCostFunction(
CostFunction* wrapped_cost_function,
const vector<CostFunction*>& conditioners,
Ownership ownership)
: wrapped_cost_function_(wrapped_cost_function),
conditioners_(conditioners),
ownership_(ownership) {
// Set up our dimensions.
set_num_residuals(wrapped_cost_function_->num_residuals());
*mutable_parameter_block_sizes() =
wrapped_cost_function_->parameter_block_sizes();
// Sanity-check the conditioners' dimensions.
CHECK_EQ(wrapped_cost_function_->num_residuals(), conditioners_.size());
for (int i = 0; i < wrapped_cost_function_->num_residuals(); i++) {
if (conditioners[i]) {
CHECK_EQ(1, conditioners[i]->num_residuals());
CHECK_EQ(1, conditioners[i]->parameter_block_sizes().size());
CHECK_EQ(1, conditioners[i]->parameter_block_sizes()[0]);
}
}
}
ConditionedCostFunction::~ConditionedCostFunction() {
if (ownership_ == TAKE_OWNERSHIP) {
STLDeleteElements(&conditioners_);
} else {
wrapped_cost_function_.release();
}
}
bool ConditionedCostFunction::Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
bool success = wrapped_cost_function_->Evaluate(parameters, residuals,
jacobians);
if (!success) {
return false;
}
for (int r = 0; r < wrapped_cost_function_->num_residuals(); r++) {
// On output, we want to have
// residuals[r] = conditioners[r](wrapped_residuals[r])
// For parameter block i, column c,
// jacobians[i][r*parameter_block_size_[i] + c] =
// = d residual[r] / d parameters[i][c]
// = conditioners[r]'(wrapped_residuals[r]) *
// d wrapped_residuals[r] / d parameters[i][c]
if (conditioners_[r]) {
double conditioner_derivative;
double* conditioner_derivative_pointer = &conditioner_derivative;
double** conditioner_derivative_pointer2 =
&conditioner_derivative_pointer;
if (!jacobians) {
conditioner_derivative_pointer2 = NULL;
}
double unconditioned_residual = residuals[r];
double* parameter_pointer = &unconditioned_residual;
success = conditioners_[r]->Evaluate(&parameter_pointer,
&residuals[r],
conditioner_derivative_pointer2);
if (!success) {
return false;
}
if (jacobians) {
for (int i = 0;
i < wrapped_cost_function_->parameter_block_sizes().size();
i++) {
if (jacobians[i]) {
int parameter_block_size =
wrapped_cost_function_->parameter_block_sizes()[i];
VectorRef jacobian_row(jacobians[i] + r * parameter_block_size,
parameter_block_size, 1);
jacobian_row *= conditioner_derivative;
}
}
}
}
}
return true;
}
} // namespace ceres

@ -0,0 +1,233 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// A preconditioned conjugate gradients solver
// (ConjugateGradientsSolver) for positive semidefinite linear
// systems.
//
// We have also augmented the termination criterion used by this
// solver to support not just residual based termination but also
// termination based on decrease in the value of the quadratic model
// that CG optimizes.
#include "ceres/conjugate_gradients_solver.h"
#include <cmath>
#include <cstddef>
#include <glog/logging.h>
#include "ceres/linear_operator.h"
#include "ceres/internal/eigen.h"
#include "ceres/types.h"
#include "ceres/jet.h"
namespace ceres {
namespace internal {
namespace {
bool IsZeroOrInfinity(double x) {
return ((x == 0.0) || (isinf(x)));
}
// Constant used in the MATLAB implementation ~ 2 * eps.
const double kEpsilon = 2.2204e-16;
} // namespace
ConjugateGradientsSolver::ConjugateGradientsSolver(
const LinearSolver::Options& options)
: options_(options) {
}
LinearSolver::Summary ConjugateGradientsSolver::Solve(
LinearOperator* A,
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
CHECK_NOTNULL(A);
CHECK_NOTNULL(x);
CHECK_NOTNULL(b);
CHECK_EQ(A->num_rows(), A->num_cols());
LinearSolver::Summary summary;
summary.termination_type = MAX_ITERATIONS;
summary.num_iterations = 0;
int num_cols = A->num_cols();
VectorRef xref(x, num_cols);
ConstVectorRef bref(b, num_cols);
double norm_b = bref.norm();
if (norm_b == 0.0) {
xref.setZero();
summary.termination_type = TOLERANCE;
return summary;
}
Vector r(num_cols);
Vector p(num_cols);
Vector z(num_cols);
Vector tmp(num_cols);
double tol_r = per_solve_options.r_tolerance * norm_b;
tmp.setZero();
A->RightMultiply(x, tmp.data());
r = bref - tmp;
double norm_r = r.norm();
if (norm_r <= tol_r) {
summary.termination_type = TOLERANCE;
return summary;
}
double rho = 1.0;
// Initial value of the quadratic model Q = x'Ax - 2 * b'x.
double Q0 = -1.0 * xref.dot(bref + r);
for (summary.num_iterations = 1;
summary.num_iterations < options_.max_num_iterations;
++summary.num_iterations) {
VLOG(2) << "cg iteration " << summary.num_iterations;
// Apply preconditioner
if (per_solve_options.preconditioner != NULL) {
z.setZero();
per_solve_options.preconditioner->RightMultiply(r.data(), z.data());
} else {
z = r;
}
double last_rho = rho;
rho = r.dot(z);
if (IsZeroOrInfinity(rho)) {
LOG(ERROR) << "Numerical failure. rho = " << rho;
summary.termination_type = FAILURE;
break;
};
if (summary.num_iterations == 1) {
p = z;
} else {
double beta = rho / last_rho;
if (IsZeroOrInfinity(beta)) {
LOG(ERROR) << "Numerical failure. beta = " << beta;
summary.termination_type = FAILURE;
break;
}
p = z + beta * p;
}
Vector& q = z;
q.setZero();
A->RightMultiply(p.data(), q.data());
double pq = p.dot(q);
if ((pq <= 0) || isinf(pq)) {
LOG(ERROR) << "Numerical failure. pq = " << pq;
summary.termination_type = FAILURE;
break;
}
double alpha = rho / pq;
if (isinf(alpha)) {
LOG(ERROR) << "Numerical failure. alpha " << alpha;
summary.termination_type = FAILURE;
break;
}
xref = xref + alpha * p;
// Ideally we would just use the update r = r - alpha*q to keep
// track of the residual vector. However this estimate tends to
// drift over time due to round off errors. Thus every
// residual_reset_period iterations, we calculate the residual as
// r = b - Ax. We do not do this every iteration because this
// requires an additional matrix vector multiply which would
// double the complexity of the CG algorithm.
if (summary.num_iterations % options_.residual_reset_period == 0) {
tmp.setZero();
A->RightMultiply(x, tmp.data());
r = bref - tmp;
} else {
r = r - alpha * q;
}
// Quadratic model based termination.
// Q1 = x'Ax - 2 * b' x.
double Q1 = -1.0 * xref.dot(bref + r);
// For PSD matrices A, let
//
// Q(x) = x'Ax - 2b'x
//
// be the cost of the quadratic function defined by A and b. Then,
// the solver terminates at iteration i if
//
// i * (Q(x_i) - Q(x_i-1)) / Q(x_i) < q_tolerance.
//
// This termination criterion is more useful when using CG to
// solve the Newton step. This particular convergence test comes
// from Stephen Nash's work on truncated Newton
// methods. References:
//
// 1. Stephen G. Nash & Ariela Sofer, Assessing A Search
// Direction Within A Truncated Newton Method, Operation
// Research Letters 9(1990) 219-221.
//
// 2. Stephen G. Nash, A Survey of Truncated Newton Methods,
// Journal of Computational and Applied Mathematics,
// 124(1-2), 45-59, 2000.
//
double zeta = summary.num_iterations * (Q1 - Q0) / Q1;
VLOG(2) << "Q termination: zeta " << zeta
<< " " << per_solve_options.q_tolerance;
if (zeta < per_solve_options.q_tolerance) {
summary.termination_type = TOLERANCE;
break;
}
Q0 = Q1;
// Residual based termination.
norm_r = r. norm();
VLOG(2) << "R termination: norm_r " << norm_r
<< " " << tol_r;
if (norm_r <= tol_r) {
summary.termination_type = TOLERANCE;
break;
}
}
return summary;
};
} // namespace internal
} // namespace ceres

@ -0,0 +1,74 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Preconditioned Conjugate Gradients based solver for positive
// semidefinite linear systems.
#ifndef CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_
#define CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_
#include "ceres/linear_solver.h"
#include "ceres/internal/macros.h"
namespace ceres {
namespace internal {
class LinearOperator;
// This class implements the now classical Conjugate Gradients
// algorithm of Hestenes & Stiefel for solving postive semidefinite
// linear sytems. Optionally it can use a preconditioner also to
// reduce the condition number of the linear system and improve the
// convergence rate. Modern references for Conjugate Gradients are the
// books by Yousef Saad and Trefethen & Bau. This implementation of CG
// has been augmented with additional termination tests that are
// needed for forcing early termination when used as part of an
// inexact Newton solver.
//
// For more details see the documentation for
// LinearSolver::PerSolveOptions::r_tolerance and
// LinearSolver::PerSolveOptions::q_tolerance in linear_solver.h.
class ConjugateGradientsSolver : public LinearSolver {
public:
explicit ConjugateGradientsSolver(const LinearSolver::Options& options);
virtual Summary Solve(LinearOperator* A,
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x);
private:
const LinearSolver::Options options_;
DISALLOW_COPY_AND_ASSIGN(ConjugateGradientsSolver);
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_

@ -0,0 +1,125 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/corrector.h"
#include <cstddef>
#include <cmath>
#include <glog/logging.h>
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
Corrector::Corrector(double sq_norm, const double rho[3]) {
CHECK_GE(sq_norm, 0.0);
CHECK_GT(rho[1], 0.0);
sqrt_rho1_ = sqrt(rho[1]);
// If sq_norm = 0.0, the correction becomes trivial, the residual
// and the jacobian are scaled by the squareroot of the derivative
// of rho. Handling this case explicitly avoids the divide by zero
// error that would occur below.
//
// The case where rho'' < 0 also gets special handling. Technically
// it shouldn't, and the computation of the scaling should proceed
// as below, however we found in experiments that applying the
// curvature correction when rho'' < 0, which is the case when we
// are in the outlier region slows down the convergence of the
// algorithm significantly.
//
// Thus, we have divided the action of the robustifier into two
// parts. In the inliner region, we do the full second order
// correction which re-wights the gradient of the function by the
// square root of the derivative of rho, and the Gauss-Newton
// Hessian gets both the scaling and the rank-1 curvature
// correction. Normaly, alpha is upper bounded by one, but with this
// change, alpha is bounded above by zero.
//
// Empirically we have observed that the full Triggs correction and
// the clamped correction both start out as very good approximations
// to the loss function when we are in the convex part of the
// function, but as the function starts transitioning from convex to
// concave, the Triggs approximation diverges more and more and
// ultimately becomes linear. The clamped Triggs model however
// remains quadratic.
//
// The reason why the Triggs approximation becomes so poor is
// because the curvature correction that it applies to the gauss
// newton hessian goes from being a full rank correction to a rank
// deficient correction making the inversion of the Hessian fraught
// with all sorts of misery and suffering.
//
// The clamped correction retains its quadratic nature and inverting it
// is always well formed.
if ((sq_norm == 0.0) || (rho[2] <= 0.0)) {
residual_scaling_ = sqrt_rho1_;
alpha_sq_norm_ = 0.0;
return;
}
// Calculate the smaller of the two solutions to the equation
//
// 0.5 * alpha^2 - alpha - rho'' / rho' * z'z = 0.
//
// Start by calculating the discriminant D.
const double D = 1.0 + 2.0 * sq_norm*rho[2] / rho[1];
// Since both rho[1] and rho[2] are guaranteed to be positive at
// this point, we know that D > 1.0.
const double alpha = 1.0 - sqrt(D);
// Calculate the constants needed by the correction routines.
residual_scaling_ = sqrt_rho1_ / (1 - alpha);
alpha_sq_norm_ = alpha / sq_norm;
}
void Corrector::CorrectResiduals(int nrow, double* residuals) {
DCHECK(residuals != NULL);
VectorRef r_ref(residuals, nrow);
// Equation 11 in BANS.
r_ref *= residual_scaling_;
}
void Corrector::CorrectJacobian(int nrow, int ncol,
double* residuals, double* jacobian) {
DCHECK(residuals != NULL);
DCHECK(jacobian != NULL);
ConstVectorRef r_ref(residuals, nrow);
MatrixRef j_ref(jacobian, nrow, ncol);
// Equation 11 in BANS.
j_ref = sqrt_rho1_ * (j_ref - alpha_sq_norm_ *
r_ref * (r_ref.transpose() * j_ref));
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,88 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Class definition for the object that is responsible for applying a
// second order correction to the Gauss-Newton based on the ideas in
// BANS by Triggs et al.
#ifndef CERES_INTERNAL_CORRECTOR_H_
#define CERES_INTERNAL_CORRECTOR_H_
namespace ceres {
namespace internal {
// Corrector is responsible for applying the second order correction
// to the residual and jacobian of a least squares problem based on a
// radial robust loss.
//
// The key idea here is to look at the expressions for the robustified
// gauss newton approximation and then take its squareroot to get the
// corresponding corrections to the residual and jacobian. For the
// full expressions see Eq. 10 and 11 in BANS by Triggs et al.
class Corrector {
public:
// The constructor takes the squared norm, the value, the first and
// second derivatives of the LossFunction. It precalculates some of
// the constants that are needed to apply the correction. The
// correction constant alpha is constrained to be smaller than 1, if
// it becomes larger than 1, then it will reverse the sign of the
// residual and the correction. If alpha is equal to 1 will result
// in a divide by zero error. Thus we constrain alpha to be upper
// bounded by 1 - epsilon_.
//
// rho[1] needs to be positive. The constructor will crash if this
// condition is not met.
//
// In practical use CorrectJacobian should always be called before
// CorrectResidual, because the jacobian correction depends on the
// value of the uncorrected residual values.
explicit Corrector(double sq_norm, const double rho[3]);
// residuals *= sqrt(rho[1]) / (1 - alpha)
void CorrectResiduals(int nrow, double* residuals);
// jacobian = sqrt(rho[1]) * jacobian -
// sqrt(rho[1]) * alpha / sq_norm * residuals residuals' * jacobian.
//
// The method assumes that the jacobian has row-major storage. It is
// the caller's responsibility to ensure that the pointer to
// jacobian is not null.
void CorrectJacobian(int nrow, int ncol,
double* residuals, double* jacobian);
private:
double sqrt_rho1_;
double residual_scaling_;
double alpha_sq_norm_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_CORRECTOR_H_

@ -0,0 +1,110 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// A jacobian writer that writes to dense Eigen matrices.
#ifndef CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_
#define CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_
#include "ceres/casts.h"
#include "ceres/dense_sparse_matrix.h"
#include "ceres/parameter_block.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
#include "ceres/scratch_evaluate_preparer.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
class DenseJacobianWriter {
public:
DenseJacobianWriter(Evaluator::Options /* ignored */,
Program* program)
: program_(program) {
}
// JacobianWriter interface.
// Since the dense matrix has different layout than that assumed by the cost
// functions, use scratch space to store the jacobians temporarily then copy
// them over to the larger jacobian later.
ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads) {
return ScratchEvaluatePreparer::Create(*program_, num_threads);
}
SparseMatrix* CreateJacobian() const {
return new DenseSparseMatrix(program_->NumResiduals(),
program_->NumEffectiveParameters());
}
void Write(int residual_id,
int residual_offset,
double **jacobians,
SparseMatrix* jacobian) {
DenseSparseMatrix* dense_jacobian;
if (jacobian != NULL) {
dense_jacobian = down_cast<DenseSparseMatrix*>(jacobian);
}
const ResidualBlock* residual_block =
program_->residual_blocks()[residual_id];
int num_parameter_blocks = residual_block->NumParameterBlocks();
int num_residuals = residual_block->NumResiduals();
// Now copy the jacobians for each parameter into the dense jacobian matrix.
for (int j = 0; j < num_parameter_blocks; ++j) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
// If the parameter block is fixed, then there is nothing to do.
if (parameter_block->IsConstant()) {
continue;
}
int parameter_block_size = parameter_block->LocalSize();
MatrixRef parameter_jacobian(jacobians[j],
num_residuals,
parameter_block_size);
dense_jacobian->mutable_matrix().block(
residual_offset,
parameter_block->delta_offset(),
num_residuals,
parameter_block_size) = parameter_jacobian;
}
}
private:
Program* program_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_

@ -0,0 +1,93 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include "ceres/dense_qr_solver.h"
#include <cstddef>
#include "Eigen/Dense"
#include "ceres/linear_solver.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
DenseQRSolver::DenseQRSolver(const LinearSolver::Options& options)
: options_(options) {}
LinearSolver::Summary DenseQRSolver::SolveImpl(
DenseSparseMatrix* A,
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x) {
const int num_rows = A->num_rows();
const int num_cols = A->num_cols();
VLOG(2) << "DenseQRSolver: "
<< num_rows << " x " << num_cols << " system.";
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.
A->AppendDiagonal(per_solve_options.D);
}
// rhs = [b;0] to account for the additional rows in the lhs.
Vector rhs(num_rows + ((per_solve_options.D !=NULL) ? num_cols : 0));
rhs.setZero();
rhs.head(num_rows) = ConstVectorRef(b, num_rows);
// Solve the system.
VectorRef(x, num_cols) = A->matrix().colPivHouseholderQr().solve(rhs);
VLOG(3) << "A:\n" << A->matrix();
VLOG(3) << "x:\n" << VectorRef(x, num_cols);
VLOG(3) << "b:\n" << rhs;
VLOG(3) << "error: " << (A->matrix() * VectorRef(x, num_cols) - rhs).norm();
if (per_solve_options.D != NULL) {
// Undo the modifications to the matrix A.
A->RemoveDiagonal();
}
// We always succeed, since the QR solver returns the best solution
// it can. It is the job of the caller to determine if the solution
// is good enough or not.
LinearSolver::Summary summary;
summary.num_iterations = 1;
summary.termination_type = TOLERANCE;
return summary;
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,99 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Solve dense rectangular systems Ax = b using the QR factoriztion.
#ifndef CERES_INTERNAL_DENSE_QR_SOLVER_H_
#define CERES_INTERNAL_DENSE_QR_SOLVER_H_
#include "ceres/linear_solver.h"
#include "ceres/internal/macros.h"
namespace ceres {
namespace internal {
class DenseSparseMatrix;
// This class implements the LinearSolver interface for solving
// rectangular/unsymmetric (well constrained) linear systems of the
// form
//
// Ax = b
//
// Since there does not usually exist a solution that satisfies these
// equations, the solver instead solves the linear least squares
// problem
//
// min_x |Ax - b|^2
//
// The solution strategy is based on computing the QR decomposition of
// A, i.e.
//
// A = QR
//
// Where Q is an orthonormal matrix and R is an upper triangular
// matrix. Then
//
// Ax = b
// QRx = b
// Q'QRx = Q'b
// Rx = Q'b
// x = R^{-1} Q'b
//
// If the PerSolveOptions struct has a non-null array D, then the
// augmented/regularized linear system
//
// [ A ]x = [b]
// [ diag(D) ] [0]
//
// is solved.
//
// This class uses the dense QR factorization routines from the Eigen
// library. This solver always returns a solution, it is the user's
// responsibility to judge if the solution is good enough for their
// purposes.
class DenseQRSolver: public DenseSparseMatrixSolver {
public:
explicit DenseQRSolver(const LinearSolver::Options& options);
private:
virtual LinearSolver::Summary SolveImpl(
DenseSparseMatrix* A,
const double* b,
const LinearSolver::PerSolveOptions& per_solve_options,
double* x);
const LinearSolver::Options options_;
DISALLOW_COPY_AND_ASSIGN(DenseQRSolver);
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_DENSE_QR_SOLVER_H_

@ -0,0 +1,184 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#include "ceres/dense_sparse_matrix.h"
#include <algorithm>
#include "ceres/matrix_proto.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/port.h"
namespace ceres {
namespace internal {
DenseSparseMatrix::DenseSparseMatrix(int num_rows, int num_cols)
: has_diagonal_appended_(false),
has_diagonal_reserved_(false) {
// Allocate enough space for the diagonal.
m_.resize(num_rows, num_cols);
m_.setZero();
}
DenseSparseMatrix::DenseSparseMatrix(const TripletSparseMatrix& m)
: m_(Eigen::MatrixXd::Zero(m.num_rows(), m.num_cols())),
has_diagonal_appended_(false),
has_diagonal_reserved_(false) {
const double *values = m.values();
const int *rows = m.rows();
const int *cols = m.cols();
int num_nonzeros = m.num_nonzeros();
for (int i = 0; i < num_nonzeros; ++i) {
m_(rows[i], cols[i]) += values[i];
}
}
DenseSparseMatrix::DenseSparseMatrix(const Matrix& m)
: m_(m),
has_diagonal_appended_(false),
has_diagonal_reserved_(false) {
}
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
DenseSparseMatrix::DenseSparseMatrix(const SparseMatrixProto& outer_proto)
: m_(Eigen::MatrixXd::Zero(
outer_proto.dense_matrix().num_rows(),
outer_proto.dense_matrix().num_cols())),
has_diagonal_appended_(false),
has_diagonal_reserved_(false) {
const DenseSparseMatrixProto& proto = outer_proto.dense_matrix();
for (int i = 0; i < m_.rows(); ++i) {
for (int j = 0; j < m_.cols(); ++j) {
m_(i, j) = proto.values(m_.cols() * i + j);
}
}
}
#endif
void DenseSparseMatrix::SetZero() {
m_.setZero();
}
void DenseSparseMatrix::RightMultiply(const double* x, double* y) const {
VectorRef(y, num_rows()) += matrix() * ConstVectorRef(x, num_cols());
}
void DenseSparseMatrix::LeftMultiply(const double* x, double* y) const {
VectorRef(y, num_cols()) +=
matrix().transpose() * ConstVectorRef(x, num_rows());
}
void DenseSparseMatrix::SquaredColumnNorm(double* x) const {
VectorRef(x, num_cols()) = m_.colwise().squaredNorm();
}
void DenseSparseMatrix::ScaleColumns(const double* scale) {
m_ *= ConstVectorRef(scale, num_cols()).asDiagonal();
}
void DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const {
*dense_matrix = m_;
}
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
void DenseSparseMatrix::ToProto(SparseMatrixProto* outer_proto) const {
CHECK(!has_diagonal_appended_) << "Not supported.";
outer_proto->Clear();
DenseSparseMatrixProto* proto = outer_proto->mutable_dense_matrix();
proto->set_num_rows(num_rows());
proto->set_num_cols(num_cols());
int num_nnz = num_nonzeros();
for (int i = 0; i < num_nnz; ++i) {
proto->add_values(m_.data()[i]);
}
}
#endif
void DenseSparseMatrix::AppendDiagonal(double *d) {
CHECK(!has_diagonal_appended_);
if (!has_diagonal_reserved_) {
Matrix tmp = m_;
m_.resize(m_.rows() + m_.cols(), m_.cols());
m_.setZero();
m_.block(0, 0, tmp.rows(), tmp.cols()) = tmp;
has_diagonal_reserved_ = true;
}
m_.bottomLeftCorner(m_.cols(), m_.cols()) =
ConstVectorRef(d, m_.cols()).asDiagonal();
has_diagonal_appended_ = true;
}
void DenseSparseMatrix::RemoveDiagonal() {
CHECK(has_diagonal_appended_);
has_diagonal_appended_ = false;
// Leave the diagonal reserved.
}
int DenseSparseMatrix::num_rows() const {
if (has_diagonal_reserved_ && !has_diagonal_appended_) {
return m_.rows() - m_.cols();
}
return m_.rows();
}
int DenseSparseMatrix::num_cols() const {
return m_.cols();
}
int DenseSparseMatrix::num_nonzeros() const {
if (has_diagonal_reserved_ && !has_diagonal_appended_) {
return (m_.rows() - m_.cols()) * m_.cols();
}
return m_.rows() * m_.cols();
}
ConstAlignedMatrixRef DenseSparseMatrix::matrix() const {
if (has_diagonal_reserved_ && !has_diagonal_appended_) {
return ConstAlignedMatrixRef(
m_.data(), m_.rows() - m_.cols(), m_.cols());
}
return ConstAlignedMatrixRef(m_.data(), m_.rows(), m_.cols());
}
AlignedMatrixRef DenseSparseMatrix::mutable_matrix() {
if (has_diagonal_reserved_ && !has_diagonal_appended_) {
return AlignedMatrixRef(
m_.data(), m_.rows() - m_.cols(), m_.cols());
}
return AlignedMatrixRef(m_.data(), m_.rows(), m_.cols());
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,115 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// A dense matrix implemented under the SparseMatrix interface.
#ifndef CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_
#define CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_
#include <glog/logging.h>
#include "ceres/sparse_matrix.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/macros.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
class SparseMatrixProto;
class TripletSparseMatrix;
class DenseSparseMatrix : public SparseMatrix {
public:
// Build a matrix with the same content as the TripletSparseMatrix
// m. This assumes that m does not have any repeated entries.
explicit DenseSparseMatrix(const TripletSparseMatrix& m);
explicit DenseSparseMatrix(const Matrix& m);
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
explicit DenseSparseMatrix(const SparseMatrixProto& proto);
#endif
DenseSparseMatrix(int num_rows, int num_cols);
virtual ~DenseSparseMatrix() {}
// SparseMatrix interface.
virtual void SetZero();
virtual void RightMultiply(const double* x, double* y) const;
virtual void LeftMultiply(const double* x, double* y) const;
virtual void SquaredColumnNorm(double* x) const;
virtual void ScaleColumns(const double* scale);
virtual void ToDenseMatrix(Matrix* dense_matrix) const;
#ifndef CERES_DONT_HAVE_PROTOCOL_BUFFERS
virtual void ToProto(SparseMatrixProto* proto) const;
#endif
virtual int num_rows() const;
virtual int num_cols() const;
virtual int num_nonzeros() const;
virtual const double* values() const { return m_.data(); }
virtual double* mutable_values() { return m_.data(); }
ConstAlignedMatrixRef matrix() const;
AlignedMatrixRef mutable_matrix();
// Only one diagonal can be appended at a time. The diagonal is appended to
// as a new set of rows, e.g.
//
// Original matrix:
//
// x x x
// x x x
// x x x
//
// After append diagonal (1, 2, 3):
//
// x x x
// x x x
// x x x
// 1 0 0
// 0 2 0
// 0 0 3
//
// Calling RemoveDiagonal removes the block. It is a fatal error to append a
// diagonal to a matrix that already has an appended diagonal, and it is also
// a fatal error to remove a diagonal from a matrix that has none.
void AppendDiagonal(double *d);
void RemoveDiagonal();
private:
Matrix m_;
bool has_diagonal_appended_;
bool has_diagonal_reserved_;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_

@ -0,0 +1,114 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#include <glog/logging.h>
#include "ceres/detect_structure.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
void DetectStructure(const CompressedRowBlockStructure& bs,
const int num_eliminate_blocks,
int* row_block_size,
int* e_block_size,
int* f_block_size) {
const int num_row_blocks = bs.rows.size();
*row_block_size = 0;
*e_block_size = 0;
*f_block_size = 0;
// Iterate over row blocks of the matrix, checking if row_block,
// e_block or f_block sizes remain constant.
for (int r = 0; r < num_row_blocks; ++r) {
const CompressedRow& row = bs.rows[r];
// We do not care about the sizes of the blocks in rows which do
// not contain e_blocks.
if (row.cells.front().block_id >= num_eliminate_blocks) {
break;
}
const int e_block_id = row.cells.front().block_id;
if (*row_block_size == 0) {
*row_block_size = row.block.size;
} else if (*row_block_size != Eigen::Dynamic &&
*row_block_size != row.block.size) {
*row_block_size = Eigen::Dynamic;
VLOG(2) << "Dynamic row block size because the block size changed from "
<< *row_block_size << " to "
<< row.block.size;
}
if (*e_block_size == 0) {
*e_block_size = bs.cols[e_block_id].size;
} else if (*e_block_size != Eigen::Dynamic &&
*e_block_size != bs.cols[e_block_id].size) {
*e_block_size = Eigen::Dynamic;
VLOG(2) << "Dynamic e block size because the block size changed from "
<< *e_block_size << " to "
<< bs.cols[e_block_id].size;
}
if (*f_block_size == 0) {
if (row.cells.size() > 1) {
const int f_block_id = row.cells[1].block_id;
*f_block_size = bs.cols[f_block_id].size;
}
} else if (*f_block_size != Eigen::Dynamic) {
for (int c = 1; c < row.cells.size(); ++c) {
if (*f_block_size != bs.cols[row.cells[c].block_id].size) {
*f_block_size = Eigen::Dynamic;
VLOG(2) << "Dynamic f block size because the block size "
<< "changed from " << *f_block_size << " to "
<< bs.cols[row.cells[c].block_id].size;
break;
}
}
}
const bool is_everything_dynamic = (*row_block_size == Eigen::Dynamic &&
*e_block_size == Eigen::Dynamic &&
*f_block_size == Eigen::Dynamic);
if (is_everything_dynamic) {
break;
}
}
CHECK_NE(*row_block_size, 0) << "No rows found";
CHECK_NE(*e_block_size, 0) << "No e type blocks found";
VLOG(1) << "Schur complement static structure <"
<< *row_block_size << ","
<< *e_block_size << ","
<< *f_block_size << ">.";
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,63 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_INTERNAL_DETECT_STRUCTURE_H_
#define CERES_INTERNAL_DETECT_STRUCTURE_H_
#include "ceres/block_structure.h"
namespace ceres {
namespace internal {
// Detect static blocks in the problem sparsity. For rows containing
// e_blocks, we are interested in detecting if the size of the row
// blocks, e_blocks and the f_blocks remain constant. If they do, then
// we can use template specialization to improve the performance of
// the block level linear algebra operations used by the
// SchurEliminator.
//
// If a block size is not constant, we return Eigen::Dynamic as the
// value. This just means that the eliminator uses dynamically sized
// linear algebra operations rather than static operations whose size
// is known as compile time.
//
// For more details about e_blocks and f_blocks, see
// schur_complement.h. This information is used to initialized an
// appropriate template specialization of SchurEliminator.
void DetectStructure(const CompressedRowBlockStructure& bs,
const int num_eliminate_blocks,
int* row_block_size,
int* e_block_size,
int* f_block_size);
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_DETECT_STRUCTURE_H_

@ -0,0 +1,71 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#include <glog/logging.h>
#include "ceres/evaluator.h"
#include "ceres/block_evaluate_preparer.h"
#include "ceres/block_jacobian_writer.h"
#include "ceres/compressed_row_jacobian_writer.h"
#include "ceres/scratch_evaluate_preparer.h"
#include "ceres/dense_jacobian_writer.h"
#include "ceres/program_evaluator.h"
namespace ceres {
namespace internal {
Evaluator::~Evaluator() {}
Evaluator* Evaluator::Create(const Evaluator::Options& options,
Program* program,
string* error) {
switch (options.linear_solver_type) {
case DENSE_QR:
return new ProgramEvaluator<ScratchEvaluatePreparer,
DenseJacobianWriter>(options,
program);
case DENSE_SCHUR:
case SPARSE_SCHUR:
case ITERATIVE_SCHUR:
case CGNR:
return new ProgramEvaluator<BlockEvaluatePreparer,
BlockJacobianWriter>(options,
program);
case SPARSE_NORMAL_CHOLESKY:
return new ProgramEvaluator<ScratchEvaluatePreparer,
CompressedRowJacobianWriter>(options,
program);
default:
*error = "Invalid Linear Solver Type. Unable to create evaluator.";
return NULL;
}
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,129 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
// keir@google.com (Keir Mierle)
#ifndef CERES_INTERNAL_EVALUATOR_H_
#define CERES_INTERNAL_EVALUATOR_H_
#include <string>
#include "ceres/internal/port.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
class Program;
class SparseMatrix;
// The Evaluator interface offers a way to interact with a least squares cost
// function that is useful for an optimizer that wants to minimize the least
// squares objective. This insulates the optimizer from issues like Jacobian
// storage, parameterization, etc.
class Evaluator {
public:
virtual ~Evaluator();
struct Options {
Options()
: num_threads(1),
num_eliminate_blocks(-1),
linear_solver_type(DENSE_QR) {}
int num_threads;
int num_eliminate_blocks;
LinearSolverType linear_solver_type;
};
static Evaluator* Create(const Options& options,
Program* program,
string* error);
// Build and return a sparse matrix for storing and working with the Jacobian
// of the objective function. The jacobian has dimensions
// NumEffectiveParameters() by NumParameters(), and is typically extremely
// sparse. Since the sparsity pattern of the Jacobian remains constant over
// the lifetime of the optimization problem, this method is used to
// instantiate a SparseMatrix object with the appropriate sparsity structure
// (which can be an expensive operation) and then reused by the optimization
// algorithm and the various linear solvers.
//
// It is expected that the classes implementing this interface will be aware
// of their client's requirements for the kind of sparse matrix storage and
// layout that is needed for an efficient implementation. For example
// CompressedRowOptimizationProblem creates a compressed row representation of
// the jacobian for use with CHOLMOD, where as BlockOptimizationProblem
// creates a BlockSparseMatrix representation of the jacobian for use in the
// Schur complement based methods.
virtual SparseMatrix* CreateJacobian() const = 0;
// Evaluate the cost function for the given state. Returns the cost,
// residuals, and jacobian in the corresponding arguments. Both residuals and
// jacobian are optional; to avoid computing them, pass NULL.
//
// If non-NULL, the Jacobian must have a suitable sparsity pattern; only the
// values array of the jacobian is modified.
//
// state is an array of size NumParameters(), cost is a pointer to a single
// double, and residuals is an array of doubles of size NumResiduals().
virtual bool Evaluate(const double* state,
double* cost,
double* residuals,
SparseMatrix* jacobian) = 0;
// Make a change delta (of size NumEffectiveParameters()) to state (of size
// NumParameters()) and store the result in state_plus_delta.
//
// In the case that there are no parameterizations used, this is equivalent to
//
// state_plus_delta[i] = state[i] + delta[i] ;
//
// however, the mapping is more complicated in the case of parameterizations
// like quaternions. This is the same as the "Plus()" operation in
// local_parameterization.h, but operating over the entire state vector for a
// problem.
virtual bool Plus(const double* state,
const double* delta,
double* state_plus_delta) const = 0;
// The number of parameters in the optimization problem.
virtual int NumParameters() const = 0;
// This is the effective number of parameters that the optimizer may adjust.
// This applies when there are parameterizations on some of the parameters.
virtual int NumEffectiveParameters() const = 0;
// The number of residuals in the optimization problem.
virtual int NumResiduals() const = 0;
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_EVALUATOR_H_

@ -0,0 +1,93 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// Really simple file IO.
#include <cstdio>
#include <glog/logging.h>
namespace ceres {
namespace internal {
using std::string;
void WriteStringToFileOrDie(const string &data, const string &filename) {
FILE* file_descriptor = fopen(filename.c_str(), "wb");
if (!file_descriptor) {
LOG(FATAL) << "Couldn't write to file: " << filename;
}
fwrite(data.c_str(), 1, data.size(), file_descriptor);
fclose(file_descriptor);
}
void ReadFileToStringOrDie(const string &filename, string *data) {
FILE* file_descriptor = file_descriptor = fopen(filename.c_str(), "r");
if (!file_descriptor) {
LOG(FATAL) << "Couldn't read file: " << filename;
}
// Resize the input buffer appropriately.
fseek(file_descriptor, 0L, SEEK_END);
int num_bytes = ftell(file_descriptor);
data->resize(num_bytes);
// Read the data.
fseek(file_descriptor, 0L, SEEK_SET);
int num_read = fread(&((*data)[0]),
sizeof((*data)[0]),
num_bytes,
file_descriptor);
if (num_read != num_bytes) {
LOG(FATAL) << "Couldn't read all of " << filename
<< "expected bytes: " << num_bytes * sizeof((*data)[0])
<< "actual bytes: " << num_read;
}
fclose(file_descriptor);
}
string JoinPath(const string& dirname, const string& basename) {
#ifdef _WIN32
static const char separator = '\\';
#else
static const char separator = '/';
#endif // _WIN32
if ((!basename.empty() && basename[0] == separator) || dirname.empty()) {
return basename;
} else if (dirname[dirname.size() - 1] == separator) {
return dirname + basename;
} else {
return dirname + string(&separator, 1) + basename;
}
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,52 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
//
// Simple file IO support. This is a portability shim.
#ifndef CERES_INTERNAL_FILE_H_
#define CERES_INTERNAL_FILE_H_
#include <string>
#include "ceres/internal/port.h"
namespace ceres {
namespace internal {
void WriteStringToFileOrDie(const string &data, const string &filename);
void ReadFileToStringOrDie(const string &filename, string *data);
// Join two path components, adding a slash if necessary. If basename is an
// absolute path then JoinPath ignores dirname and simply returns basename.
string JoinPath(const string& dirname, const string& basename);
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_FILE_H_

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 2, 2>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 2, 3>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 2, 4>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 2, Dynamic>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 3, 3>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 3, 4>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 3, 9>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 3, Dynamic>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 4, 3>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 4, 4>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<2, 4, Dynamic>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<4, 4, 2>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<4, 4, 3>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<4, 4, 4>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<4, 4, Dynamic>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,53 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
//
// Template specialization of SchurEliminator.
//
// ========================================
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
//=========================================
//
// This file is generated using generate_eliminator_specializations.py.
// Editing it manually is not recommended.
#include "ceres/schur_eliminator_impl.h"
#include "ceres/internal/eigen.h"
namespace ceres {
namespace internal {
template class SchurEliminator<Dynamic, Dynamic, Dynamic>;
} // namespace internal
} // namespace ceres

@ -0,0 +1,308 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#include "ceres/gradient_checking_cost_function.h"
#include <algorithm>
#include <cmath>
#include <numeric>
#include <string>
#include <vector>
#include <glog/logging.h>
#include "ceres/parameter_block.h"
#include "ceres/problem_impl.h"
#include "ceres/program.h"
#include "ceres/residual_block.h"
#include "ceres/runtime_numeric_diff_cost_function.h"
#include "ceres/stringprintf.h"
#include "ceres/cost_function.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/scoped_ptr.h"
#include "ceres/problem.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
namespace {
// True if x and y have an absolute relative difference less than
// relative_precision and false otherwise. Stores the relative and absolute
// difference in relative/absolute_error if non-NULL.
bool IsClose(double x, double y, double relative_precision,
double *relative_error,
double *absolute_error) {
double local_absolute_error;
double local_relative_error;
if (!absolute_error) {
absolute_error = &local_absolute_error;
}
if (!relative_error) {
relative_error = &local_relative_error;
}
*absolute_error = fabs(x - y);
*relative_error = *absolute_error / max(fabs(x), fabs(y));
if (x == 0 || y == 0) {
// If x or y is exactly zero, then relative difference doesn't have any
// meaning. Take the absolute difference instead.
*relative_error = *absolute_error;
}
return fabs(*relative_error) < fabs(relative_precision);
}
class GradientCheckingCostFunction : public CostFunction {
public:
GradientCheckingCostFunction(const CostFunction* function,
double relative_step_size,
double relative_precision,
const string& extra_info)
: function_(function),
finite_diff_cost_function_(
CreateRuntimeNumericDiffCostFunction(function,
CENTRAL,
relative_step_size)),
relative_precision_(relative_precision),
extra_info_(extra_info) {
*mutable_parameter_block_sizes() = function->parameter_block_sizes();
set_num_residuals(function->num_residuals());
}
virtual ~GradientCheckingCostFunction() { }
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
if (!jacobians) {
// Nothing to check in this case; just forward.
return function_->Evaluate(parameters, residuals, NULL);
}
int num_residuals = function_->num_residuals();
// Make space for the jacobians of the two methods.
const vector<int16>& block_sizes = function_->parameter_block_sizes();
vector<Matrix> term_jacobians(block_sizes.size());
vector<Matrix> finite_difference_jacobians(block_sizes.size());
vector<double*> term_jacobian_pointers(block_sizes.size());
vector<double*> finite_difference_jacobian_pointers(block_sizes.size());
for (int i = 0; i < block_sizes.size(); i++) {
term_jacobians[i].resize(num_residuals, block_sizes[i]);
term_jacobian_pointers[i] = term_jacobians[i].data();
finite_difference_jacobians[i].resize(num_residuals, block_sizes[i]);
finite_difference_jacobian_pointers[i] =
finite_difference_jacobians[i].data();
}
// Evaluate the derivative using the user supplied code.
if (!function_->Evaluate(parameters,
residuals,
&term_jacobian_pointers[0])) {
LOG(WARNING) << "Function evaluation failed.";
return false;
}
// Evaluate the derivative using numeric derivatives.
finite_diff_cost_function_->Evaluate(
parameters,
residuals,
&finite_difference_jacobian_pointers[0]);
// See if any elements have relative error larger than the threshold.
int num_bad_jacobian_components = 0;
double worst_relative_error = 0;
// Accumulate the error message for all the jacobians, since it won't get
// output if there are no bad jacobian components.
string m;
for (int k = 0; k < block_sizes.size(); k++) {
// Copy the original jacobian blocks into the jacobians array.
if (jacobians[k] != NULL) {
MatrixRef(jacobians[k],
term_jacobians[k].rows(),
term_jacobians[k].cols()) = term_jacobians[k];
}
StringAppendF(&m,
"========== "
"Jacobian for " "block %d: (%ld by %ld)) "
"==========\n",
k,
term_jacobians[k].rows(),
term_jacobians[k].cols());
// The funny spacing creates appropriately aligned column headers.
m += " block row col user dx/dy num diff dx/dy "
"abs error relative error parameter residual\n";
for (int i = 0; i < term_jacobians[k].rows(); i++) {
for (int j = 0; j < term_jacobians[k].cols(); j++) {
double term_jacobian = term_jacobians[k](i, j);
double finite_jacobian = finite_difference_jacobians[k](i, j);
double relative_error, absolute_error;
bool bad_jacobian_entry =
!IsClose(term_jacobian,
finite_jacobian,
relative_precision_,
&relative_error,
&absolute_error);
worst_relative_error = std::max(worst_relative_error,
relative_error);
StringAppendF(&m, "%6d %4d %4d %17g %17g %17g %17g %17g %17g",
k, i, j,
term_jacobian, finite_jacobian,
absolute_error, relative_error,
parameters[k][j],
residuals[i]);
if (bad_jacobian_entry) {
num_bad_jacobian_components++;
StringAppendF(
&m, " ------ (%d,%d,%d) Relative error worse than %g",
k, i, j, relative_precision_);
}
m += "\n";
}
}
}
// Since there were some bad errors, dump comprehensive debug info.
if (num_bad_jacobian_components) {
string header = StringPrintf("Detected %d bad jacobian component(s). "
"Worst relative error was %g.\n",
num_bad_jacobian_components,
worst_relative_error);
if (!extra_info_.empty()) {
header += "Extra info for this residual: " + extra_info_ + "\n";
}
LOG(WARNING) << "\n" << header << m;
}
return true;
}
private:
const CostFunction* function_;
internal::scoped_ptr<CostFunction> finite_diff_cost_function_;
double relative_precision_;
string extra_info_;
};
} // namespace
CostFunction *CreateGradientCheckingCostFunction(
const CostFunction *cost_function,
double relative_step_size,
double relative_precision,
const string& extra_info) {
return new GradientCheckingCostFunction(cost_function,
relative_step_size,
relative_precision,
extra_info);
}
ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl,
double relative_step_size,
double relative_precision) {
// We create new CostFunctions by wrapping the original CostFunction
// in a gradient checking CostFunction. So its okay for the
// ProblemImpl to take ownership of it and destroy it. The
// LossFunctions and LocalParameterizations are reused and since
// they are owned by problem_impl, gradient_checking_problem_impl
// should not take ownership of it.
Problem::Options gradient_checking_problem_options;
gradient_checking_problem_options.cost_function_ownership = TAKE_OWNERSHIP;
gradient_checking_problem_options.loss_function_ownership =
DO_NOT_TAKE_OWNERSHIP;
gradient_checking_problem_options.local_parameterization_ownership =
DO_NOT_TAKE_OWNERSHIP;
ProblemImpl* gradient_checking_problem_impl = new ProblemImpl(
gradient_checking_problem_options);
Program* program = problem_impl->mutable_program();
// For every ParameterBlock in problem_impl, create a new parameter
// block with the same local parameterization and constancy.
const vector<ParameterBlock*>& parameter_blocks = program->parameter_blocks();
for (int i = 0; i < parameter_blocks.size(); ++i) {
ParameterBlock* parameter_block = parameter_blocks[i];
gradient_checking_problem_impl->AddParameterBlock(
parameter_block->mutable_user_state(),
parameter_block->Size(),
parameter_block->mutable_local_parameterization());
if (parameter_block->IsConstant()) {
gradient_checking_problem_impl->SetParameterBlockConstant(
parameter_block->mutable_user_state());
}
}
// For every ResidualBlock in problem_impl, create a new
// ResidualBlock by wrapping its CostFunction inside a
// GradientCheckingCostFunction.
const vector<ResidualBlock*>& residual_blocks = program->residual_blocks();
for (int i = 0; i < residual_blocks.size(); ++i) {
ResidualBlock* residual_block = residual_blocks[i];
// Build a human readable string which identifies the
// ResidualBlock. This is used by the GradientCheckingCostFunction
// when logging debugging information.
string extra_info = StringPrintf(
"Residual block id %d; depends on parameters [", i);
vector<double*> parameter_blocks;
for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) {
ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
parameter_blocks.push_back(parameter_block->mutable_user_state());
StringAppendF(&extra_info, "%p", parameter_block->mutable_user_state());
extra_info += (j < residual_block->NumParameterBlocks() - 1) ? ", " : "]";
}
// Wrap the original CostFunction in a GradientCheckingCostFunction.
CostFunction* gradient_checking_cost_function =
CreateGradientCheckingCostFunction(residual_block->cost_function(),
relative_step_size,
relative_precision,
extra_info);
// The const_cast is necessary because
// ProblemImpl::AddResidualBlock can potentially take ownership of
// the LossFunction, but in this case we are guaranteed that this
// will not be the case, so this const_cast is harmless.
gradient_checking_problem_impl->AddResidualBlock(
gradient_checking_cost_function,
const_cast<LossFunction*>(residual_block->loss_function()),
parameter_blocks);
}
return gradient_checking_problem_impl;
}
} // namespace internal
} // namespace ceres

@ -0,0 +1,85 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: keir@google.com (Keir Mierle)
#ifndef CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_
#define CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_
#include <string>
#include "ceres/cost_function.h"
namespace ceres {
namespace internal {
class ProblemImpl;
// Creates a CostFunction that checks the jacobians that cost_function computes
// with finite differences. Bad results are logged; required precision is
// controlled by relative_precision and the numeric differentiation step size is
// controlled with relative_step_size. See solver.h for a better explanation of
// relative_step_size. Caller owns result.
//
// The condition enforced is that
//
// (J_actual(i, j) - J_numeric(i, j))
// ------------------------------------ < relative_precision
// max(J_actual(i, j), J_numeric(i, j))
//
// where J_actual(i, j) is the jacobian as computed by the supplied cost
// function (by the user) and J_numeric is the jacobian as computed by finite
// differences.
//
// Note: This is quite inefficient and is intended only for debugging.
CostFunction* CreateGradientCheckingCostFunction(
const CostFunction* cost_function,
double relative_step_size,
double relative_precision,
const string& extra_info);
// Create a new ProblemImpl object from the input problem_impl, where
// each CostFunctions in problem_impl are wrapped inside a
// GradientCheckingCostFunctions. This gives us a ProblemImpl object
// which checks its derivatives against estimates from numeric
// differentiation everytime a ResidualBlock is evaluated.
//
// relative_step_size and relative_precision are parameters to control
// the numeric differentiation and the relative tolerance between the
// jacobian computed by the CostFunctions in problem_impl and
// jacobians obtained by numerically differentiating them. For more
// details see the documentation for
// CreateGradientCheckingCostFunction above.
ProblemImpl* CreateGradientCheckingProblemImpl(ProblemImpl* problem_impl,
double relative_step_size,
double relative_precision);
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_

@ -0,0 +1,138 @@
// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
// http://code.google.com/p/ceres-solver/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)
#ifndef CERES_INTERNAL_GRAPH_H_
#define CERES_INTERNAL_GRAPH_H_
#include <limits>
#include <glog/logging.h>
#include "ceres/integral_types.h"
#include "ceres/map_util.h"
#include "ceres/collections_port.h"
#include "ceres/internal/macros.h"
#include "ceres/types.h"
namespace ceres {
namespace internal {
// A weighted undirected graph templated over the vertex ids. Vertex
// should be hashable and comparable.
template <typename Vertex>
class Graph {
public:
Graph() {}
// Add a weighted vertex. If the vertex already exists in the graph,
// its weight is set to the new weight.
void AddVertex(const Vertex& vertex, double weight) {
if (vertices_.find(vertex) == vertices_.end()) {
vertices_.insert(vertex);
edges_[vertex] = HashSet<Vertex>();
}
vertex_weights_[vertex] = weight;
}
// Uses weight = 1.0. If vertex already exists, its weight is set to
// 1.0.
void AddVertex(const Vertex& vertex) {
AddVertex(vertex, 1.0);
}
// Add a weighted edge between the vertex1 and vertex2. Calling
// AddEdge on a pair of vertices which do not exist in the graph yet
// will result in undefined behavior.
//
// It is legal to call this method repeatedly for the same set of
// vertices.
void AddEdge(const Vertex& vertex1, const Vertex& vertex2, double weight) {
DCHECK(vertices_.find(vertex1) != vertices_.end());
DCHECK(vertices_.find(vertex2) != vertices_.end());
if (edges_[vertex1].insert(vertex2).second) {
edges_[vertex2].insert(vertex1);
}
if (vertex1 < vertex2) {
edge_weights_[make_pair(vertex1, vertex2)] = weight;
} else {
edge_weights_[make_pair(vertex2, vertex1)] = weight;
}
}
// Uses weight = 1.0.
void AddEdge(const Vertex& vertex1, const Vertex& vertex2) {
AddEdge(vertex1, vertex2, 1.0);
}
// Calling VertexWeight on a vertex not in the graph will result in
// undefined behavior.
double VertexWeight(const Vertex& vertex) const {
return FindOrDie(vertex_weights_, vertex);
}
// Calling EdgeWeight on a pair of vertices where either one of the
// vertices is not present in the graph will result in undefined
// behaviour. If there is no edge connecting vertex1 and vertex2,
// the edge weight is zero.
double EdgeWeight(const Vertex& vertex1, const Vertex& vertex2) const {
if (vertex1 < vertex2) {
return FindWithDefault(edge_weights_, make_pair(vertex1, vertex2), 0.0);
} else {
return FindWithDefault(edge_weights_, make_pair(vertex2, vertex1), 0.0);
}
}
// Calling Neighbors on a vertex not in the graph will result in
// undefined behaviour.
const HashSet<Vertex>& Neighbors(const Vertex& vertex) const {
return FindOrDie(edges_, vertex);
}
const HashSet<Vertex>& vertices() const {
return vertices_;
}
static double InvalidWeight() {
return std::numeric_limits<double>::quiet_NaN();
};
private:
HashSet<Vertex> vertices_;
HashMap<Vertex, double> vertex_weights_;
HashMap<Vertex, HashSet<Vertex> > edges_;
HashMap<pair<Vertex, Vertex>, double> edge_weights_;
DISALLOW_COPY_AND_ASSIGN(Graph);
};
} // namespace internal
} // namespace ceres
#endif // CERES_INTERNAL_GRAPH_H_

Some files were not shown because too many files have changed in this diff Show More