Commit Graph

216 Commits

Author SHA1 Message Date
Sameer Agarwal 3c4f012606 ClangTidy fixes #2
Change-Id: Ib3baa62248342276d63b900b45561323fd81402d
2024-07-21 20:31:32 -07:00
Sameer Agarwal 0ca2db57c7 Fix a number of typos
Change-Id: I0038f9c91dc70c422c01305dc10fca5a22a2f0d0
2024-07-21 15:15:36 -07:00
Sameer Agarwal 6b9a690009 ClangTidy cleanup part 1
Change-Id: Id592fc68b8f184cd002df9d94a68d05fbbf9c24d
2024-07-21 14:55:46 -07:00
Sameer Agarwal 7566ebae08 Various cleanups
Change-Id: Ie453e199a128a102bf3d5524a466f549aac0c7ce
2024-07-21 08:14:08 -07:00
Sameer Agarwal 0a53aa9054 Take abseil as a dependency
1. Add abseil-cpp as a submodule. We are tracking the latest LTS
release, which is lts_2024_01_16.
2. Replace glog/gflags with absl::log and absl::flags.
3. Remove miniglog
4. Also take a whack at making the bazel build work with
   abseil-cpp and gtest.

There are a number of TODOs in this CL that still need to be resolved.

Change-Id: I39355ed7d61375be4ebcbc8596d9cc70acc1c678
2024-07-18 00:24:49 -07:00
Mark Shachkov 6fb3dae4ee Add cuDSS as sparse Cholesky solver
cuDSS could be used as an alternative for SuiteSparse and EigenSparse
in case if CUDA capable GPU is available.

Change-Id: I7a567093ce91363478118153e181134ed5804573
2024-07-09 20:23:18 +02:00
Sameer Agarwal f71181a92d Remove remaining references to CXSparse
Also remove examples/Makefile.example as it is hopelessly
out of date.

Change-Id: I2ed2f0c4768eacbf65cf76299c7a8b3474eb750b
2024-05-21 12:20:49 -07:00
Sergiu Deitsch 91773746be Simplify instantiation of cost functions and their functors
If arguments are passed to a cost function that can be used to construct
the functor, the latter will be instantiated by the cost function using
std::make_unique to ensure exception safety. This not only avoids static
analysis warnings caused by calling new but also spelling the cost
functor type name multiple times.

Also expand deduction guides for instantiating
Dynamic(Auto|Numeric)DiffCostFunction from std::unique_ptr enabled
constructor overloads.

Finally, make CostFunction default move constructible and assignable but
only through derived classes. This in turn allows derived classes to be
movable without relying on custom implementations of corresponding
operators.

Change-Id: Idee8b9871d862bc9f9f8b5a8d0bedc52863e93c0
2024-01-23 01:34:27 +01:00
Sergiu Deitsch 4519b8d774 Drop use of POSIX M_PI
Change-Id: I37342a366161bb13d6456ecc67569fe12705e05c
2023-10-04 22:59:15 +02:00
Sameer Agarwal 94335e3b9e More ClangTidy fixes
Change-Id: If7e056b0d2eddca581d87503340fdaac87adba86
2023-10-03 13:24:33 -07:00
Sameer Agarwal 399395c4f1 Miscellaneous ClangTidy fixes
Change-Id: Iba2f8b1dccb77cefde750e5079e609b2b2a3ec95
2023-10-03 11:52:09 -07:00
Sergiu Deitsch 4893392195 Rework MSVC warning suppression
Previously, MSVC warning C4996 was suppressed unconditionally in the
entire code base which made it difficult identifying and fixing specific
problems, particularly those in the public interface.

Prefer now to disable warnings at the specific location they occur. This
approach, however, reveals an inconsistency in how Ceres handles POSIX
functions which are declared deprecated by MSVC. Specifically, Bessel
functions use the underscore form whereas the read function does not. To
simplify the logic, we revert to POSIX compatible functions.

C++23 also deprecates std::numeric_limits<T>::has_denorm which MSVC
warns about. Here, we disable the deprecation warning locally to avoid
the warning leaking into the user code.

Fixes #1013

Change-Id: Ida8457cc8dd8770b4384a7c49d16f213b02cdec4
2023-09-30 13:37:39 +02:00
Sameer Agarwal 4588b0fbbf Add an example for EvaluationCallback
Change-Id: Ia488f8b181118c8d07861149c4bd52f7217336ce
2023-09-28 21:49:32 +00:00
Sameer Agarwal 0fc3fd4fce Add documentation for examples
Also remove random.h which is not used anymore.

Change-Id: I389a0fc0fd771619e179dcf305bb0991ad1d82ff
2023-09-28 14:45:18 -07:00
Sameer Agarwal 83ee376d86 Add an example for IterationCallback
iteration_callback_example.cc uses the curve_fitting.cc example
and uses a custom IterationCallback to log the values of the
parameter blocks are they change over the course of the optimization.

Change-Id: I6a478a8418e237aff576ca627d9b5c0b751b8088
2023-09-27 22:39:01 +00:00
Sameer Agarwal 3712650941 Cleanup example code
Remove "using ceres:foo" directives from example code. The using
directives actually make the code harder to read unless you already
know the ceres API. By making the namespace explicit it is clear
to the reader that these are functions and objects from the Ceres
API.

Change-Id: I89b1281c754bf71c0f82e39e1607c5e40a148388
2023-09-27 14:46:54 -07:00
Sameer Agarwal 5a30cae583 Preparing for 2.2.0rc1
1. Add a version history
2. Update copyright years across the code base
3. Run format_all.sh
4. Update version strings from 2.1.0 to 2.2.0 in the docs and
   elsewhere.

Change-Id: I46d8d479d54bd6002d532785e67342106e73c9ac
2023-09-21 11:23:38 -07:00
Sameer Agarwal d340f81bd0 Clang Tidy fixes
Change-Id: I51429acbf2a7b81605a2fd03a6b7c10317984674
2023-04-10 16:43:30 -07:00
Alexander Ivanov f9bffbb6fb Removing -Wshorten-64-to-32 warnings from examples (part 1)
Change-Id: I3cdacc8306c1d1a07420d7171e18726a5bef0012
2023-01-19 23:40:20 +00:00
Sameer Agarwal 749a442d97 Clang-Tidy fixes
Change-Id: I58900a452591315a39754b329e94b315c34926cd
2023-01-16 07:38:05 -08:00
Sameer Agarwal 9602ed7b76 ClangFormat changes
Change-Id: I88c9e38b0450aed26c60e1dd54964ab6571e3eef
2023-01-14 05:54:24 -08:00
Alexander Ivanov 53df5ddcfd Removing using std::...
Change-Id: I584402e2a34869183c1d59071a15d97b216c52fb
2023-01-11 16:51:38 +00:00
Alexander Ivanov f982d3071d Fixing bazel build
Change-Id: I610c5a1f4f8c46d7ef75dd4861e31e98c2fa825d
2023-01-09 06:19:18 +00:00
Sameer Agarwal e15ec89f3b Speed up bundle_adjuster
1. Use hardware_concurrency to configure number of threads.
2. Use user ordering instead of automatic ordering.

Fixes https://github.com/ceres-solver/ceres-solver/issues/874

Change-Id: I4d7d69612e1ee40358943019a0c3a909e419c4e4
2022-08-17 12:47:02 -07:00
Joydeep Biswas 829089053e CUDA CGNR, Part 4: CudaCgnrSolver
* Added CudaCgnrSolver, a new CUDA-accelerated CGNR.
* To use CudaCgnrSolver, the user must select CGNR as the linear_solver
  and CUDA_SPARSE as the sparse_linear_algebra_library.
* Updated ConjugateGradientSolver to work with an array of pointers to
  scratch to support CudaVectors as scratch.
* Moved CUDA initialization to run in Solver::Solve as needed.

Some performance comparisons on an Ubuntu 20.04 desktop with an
Intel i9-9940X CPU @ 3.30GHz, and an nVidia Quadro RTX 6000,
all configurations run with 24 threads, and 10 iterations.

=================================================
CGNR + CUDA_SPARSE + IDENTITY Preconditioner
problem-1778-993923-pre.txt
=================================================
Cost:
Initial                          2.563973e+08
Final                            1.724755e+06
Change                           2.546725e+08

Minimizer iterations                       11
Successful steps                            7
Unsuccessful steps                          4

Time (in seconds):
Preprocessor                         4.020158

  Residual only evaluation           1.567092 (10)
  Jacobian & residual evaluation     7.847130 (7)
  Linear solver                     31.688898 (10)
Minimizer                           46.834987

Postprocessor                        0.353974
Total                               51.209120

=================================================
SPARSE_SCHUR (CPU) + SUITE_SPARSE + AMD
problem-1778-993923-pre.txt
=================================================
Cost:
Initial                          2.563973e+08
Final                            1.651617e+06
Change                           2.547457e+08

Minimizer iterations                       11
Successful steps                           11
Unsuccessful steps                          0

Time (in seconds):
Preprocessor                        35.812003

  Residual only evaluation           1.658980 (10)
  Jacobian & residual evaluation    12.218799 (11)
  Linear solver                     76.409992 (10)
Minimizer                           98.809773

Postprocessor                        0.372712
Total                              134.994489

=================================================
ITERATIVE_SCHUR (CPU) + JACOBI Preconditioner
problem-1778-993923-pre.txt
=================================================
Cost:
Initial                          2.563973e+08
Final                            1.684447e+06
Change                           2.547128e+08

Minimizer iterations                       11
Successful steps                            8
Unsuccessful steps                          3

Time (in seconds):
Preprocessor                        15.331614

  Residual only evaluation           1.606114 (10)
  Jacobian & residual evaluation     8.502166 (8)
  Linear solver                    351.910080 (10)
Minimizer                          368.797327

Postprocessor                        0.363536
Total                              384.492478

=================================================
CGNR + CUDA_SPARSE + IDENTITY Preconditioner
problem-13682-4456117-pre.txt
=================================================
Cost:
Initial                          1.126372e+09
Final                            2.269329e+07
Change                           1.103678e+09

Minimizer iterations                       11
Successful steps                            7
Unsuccessful steps                          4

Time (in seconds):
Preprocessor                        19.140087

  Residual only evaluation           8.721920 (10)
  Jacobian & residual evaluation    41.955923 (7)
  Linear solver                    214.121861 (10)
Minimizer                          296.636890

Postprocessor                        1.971827
Total                              317.748804

Change-Id: I3a09f31aa6903f661e91f595afd39d427583e856
2022-08-15 23:44:34 -05:00
Sameer Agarwal 2c78c5f339 Small naming fixups.
use_power_series_expansion_initialization -> use_spse_initialization
max_linear_solve_iterations -> max_linear_solver_iterations

Change-Id: I7775fa9b1ad12e28c8d01d44349b7eaef9b57edd
2022-08-13 11:59:16 -07:00
Mark Shachkov 2a25d86b01 Integrate schur power series expansion options to bundle adjuster
Change-Id: I64c0b135adeece273a7924d0a7200369eb166b0a
2022-08-13 21:34:02 +03:00
Sameer Agarwal 560ef46fbd A bunch of minor fixes.
1. Remove an unused variable from block_sparse_matrix.cc
2. Add explicit types to the distributions to get around
   -Wctad-maybe-unsupported

Change-Id: Ib7d606fbfe2b93ba4fce408f38ee4f7626b74ff0
2022-08-08 20:16:51 -07:00
Sameer Agarwal 5d0bca14dd Remove ceres/internal/random.h in favor of <random>
Fixes https://github.com/ceres-solver/ceres-solver/issues/854

Change-Id: Id30b8dc2221f9afe4eb83f3a9304b9b2bc7e05d4
2022-08-08 07:06:21 -07:00
Sergiu Deitsch 027e741a1a Eliminated MinGW warning
Change-Id: I35a852e742cc7d678c3af40e1bcd8a4f962303ee
2022-06-26 05:09:09 +00:00
Sameer Agarwal fbc2eea166 Nested dissection for ACCELERATE_SPARSE & EIGEN_SPARSE
Change-Id: Iec8ea6b0a537559b48b59bcfc91b94b58cb2070e
2022-05-27 06:50:12 -07:00
Sameer Agarwal 39ec5e8f99 Add Nested Dissection based fill reducing ordering
With this change, the user can now choose between Approximate Minimum
Degree and Nested Dissection as a fill reducing algorithm when using
a sparse direct factorization based linear solver like SPARSE_NORMAL_CHOLESKY
or SPARSE_SCHUR.

Currenly only SUITE_SPARSE is supported. It requires that
SuiteSparse be compiled with Metis support enabled.

On most problems AMD is still the better choice, but in some cases
like the grid3D dataset from https://lucacarlone.mit.edu/datasets/
the solution time with AMD is 57s and with NESDIS 38 on my M1 Mac.

On some other problems at Google we have observed speedups of 10x,
there is also a corresponding decrease in the total amount of memory
used.

This patch is based on the original work done by NeroBurner in
https://ceres-solver-review.googlesource.com/c/ceres-solver/+/20580

1. Add a new enum to the public api LinearSolverOrderingType and
   a setting Solver::Options::linear_solver_ordering_type.
2. TrustRegionPreprocessor had some complicated logic which determined
   when linear solvers should reorder their matrices on their own and not
   this has been refactored into a more readable function that lives
   inside reorder_program.h/cc.
3. Plumbing in reorder_program.cc and trust_region_processor.cc to use
   nested dissection.
4. Update bundle_adjuster.cc to use nested dissection.

Change-Id: I388b027934f86c58b4da2b65a4fa5204ea73bf40
2022-05-19 12:36:20 -07:00
Evan Levine f1414cb5bd Correct spelling in comments and docs.
Change-Id: Iad9a0599d644d3b3cd54244edaf64d408cb1308e
2022-04-24 21:40:13 -07:00
Sameer Agarwal caf614a6c1 Modernize code using c++17 constructs
Mostly done using

find . \( -name '*.cc' -o -name '*.h' \) -a -type f -exec clang-tidy -p \
cmake-build -checks='-*,google-*,modernize-*,-modernize-use-nodiscard,-modernize-use-trailing-return-type' {} -fix \;

Change-Id: Ifccbcabe7a1d9a32a09d28ac4f3f8466696c1a50
2022-04-22 06:11:18 -07:00
Sameer Agarwal ee35ef66f6 ClangFormat cleanup via scripts/all_format.sh
Change-Id: Ideafec543a9d090a767bae58123b7512c9e9ae4a
2022-03-12 16:25:45 -08:00
Sergiu Deitsch 94af09186f Force C++ linker
Forcing linker language to C causes linker errors when compiling using NDK.

Change-Id: Iea587d1ab00d10b2c331ccc3e178e16c6a78ce5f
2022-03-06 15:54:54 +01:00
Sergiu Deitsch 284be88ca1 Allow ProductManifold default construction
In many cases, manifolds stored in ProductManifold have a default
constructor which can simplify ProductManifold initialization even
further. Allow default construction of ProductManifold in this case.

Change-Id: I29b2612870c02232556688019a77049709684a55
2022-03-03 14:50:03 +01:00
Sergiu Deitsch 7743d2e73c Store ProductManifold instances in a tuple
Since the number of manifolds used to initialize ProductManifold and
their types are known at compile-time, it is possible to avoid storing
pointers to the base class as required by a homogeneous, currently
dynamically sized container. Instead, we can use std::tuple<> as a
heterogenous container with the number of elements fixed at compile-time
that allows us to store the concrete manifold realizations.

The advantage of this approach is that we can bypass the vtable when
iterating over each manifold within ProductManifold. The indirection is
invoked only once while accessing the ProductManifoldImpl members.
Additionally, potential dynamic memory allocations by a std::vector can
be completely avoided. This makes the ProductManifold implementation
more efficient both in memory and runtime.

Change-Id: Ic71b0c175ab726f8992e9703f7666bca477baf19
2022-03-02 23:57:10 +00:00
Sameer Agarwal 6a37fbf9b4 Add static/compile time sizing to EuclideanManifold
This brings it in line with other manifolds like SphereManifold
and LineManifold, where the user has the choice to specify the size
of the manifold at compile time or runtime.

Most of the time the size is known at compile time so this will
speed up the common case.

Change-Id: I0c7ff8b7a9a64a81203eb11afc074874e208815a
2022-03-01 09:34:23 -08:00
Sameer Agarwal ae4d95df6e Two small clang-tidy fixes
Change-Id: I1eb3b5aabc9586958d618c680ca1a2c6ed501fd4
2022-02-27 05:41:07 -08:00
Sergiu Deitsch c8658c8992 Modernize more
Apply clang-tidy Google and modernize fixes without trailing return type
using:

$ clang-tidy -p <build-dir> \
  -checks='-*,google-*,modernize-*,-modernize-use-trailing-return-type' {} -fix

Change-Id: I7450cc58ea9abf928f73a467e87876083217fa26
2022-02-26 22:16:56 +00:00
Sergiu Deitsch 09ec4997fa Cleanup examples
Remove logic invoked based on obsolete variable definitions. Use new
(explicit) target_link_libraries syntax to link binaries against
dependencies. Do not rely on prior knowledge about the compiler for
specifying flags and system libraries but instead directly test their
presence to be more robust.

Change-Id: I76e0d10fae6eba4b343048e4404f0a9b08c7cb6c
2022-02-18 00:53:44 +01:00
Joydeep Biswas 7d2e4152ec Add support for dense CUDA solvers #2
1. Add CUDADenseQR & tests.
   CUDADenseQR uses the cuSolverDN LAPACK implementation
   of QR factorization. A key limitation, however, is that
   this solver does not perform singularity checking --
   this is because cuSolverDN does not have a trtrs
   implementation; we instead use cuBLAS' trsv for
   backsubstitution.
2. All CPU -> GPU memory transfers are now async, and both
   CUDADenseQR and CUDADenseCholesky explicitly manage their
   own streams for async operations.
3. Simplified CUDADenseCholesky to only use the legacy 32-bit
   cuSolverDN API.

Change-Id: I2a9b7b65469658ddfe33b5b2a3892c8744d6e437
2022-02-14 15:22:39 -06:00
Sergiu Deitsch c6158e0ab5 Replace NULL by nullptr
Change-Id: I200a40678091b984a01635d8637a487b7ad5cc13
2022-02-14 19:22:21 +01:00
Sameer Agarwal ae65219e04 ClangTidy cleanups
1. NULL -> nullptr
2. foo.reset(new Bar) -> = foo = std::make_unique<Bar>()
3. Missing std library includes & prefixes

Change-Id: I260b261b484554be681ee5a7398126fdb3b3a789
2022-02-09 10:06:49 -08:00
Joydeep Biswas 36d6d86908 Add support for dense CUDA solvers #1
1. Add CUDADenseCholesky64Bit, CUDADenseCholesky32Bit, & tests.
   CUDADenseCholesky32Bit uses the legacy versions of potrf/potrs
   in cuSolverDN, while CUDADenseCholesky64Bit uses the new 64-bit
   versions available since Cuda 11.1. The legacy versions are
   provided since some platforms such as the Nvidia Jetsons only
   support Cuda 10.2.
2. Expose CUDA as a new option under DenseLinearAlgebraLibraryType.
   The relevant option to string and string to option helper functions
   are modified accordingly.
3. Add cuda as a dense_linear_algebra_library option in bundle_adjuster
   to demonstrate the use of the new CUDA option.

Change-Id: I23615e1d301df5185ed646b3e33ee802508dae86
2022-02-07 19:26:29 -06:00
Sameer Agarwal cab853fd5f Add DenseQR Interface
1. Add EigenDenseQR & tests.
   This implementation now uses an in place decomposition,
   which means that we are not allocating, deallocating
   memory every call.
2. Add LAPACKDenseQR and tests.
   The LAPACK implementation instead of using dgels which is a
   routine which does the factorization and solve in one
   call, now uses dgeqrf for factorization and then
   dormqr and dtrtrs for solving. This allows us to
   have a factorize and solve interface like DenseCholesky.
   And opens the door to iterative refinement and mixed
   precision solves.
3. The refactor also allows us to simplify the interface to
   DenseSparseMatrix considerably. The internals of this
   class were complicated because we had the AppendDiagonal
   and RemoveDiagonal methods and we did not want to allocate
   deallocate memory every call. But since we pay the cost
   of the copy anyways, we can just hold that buffer
   in DenseQRSolver.
4. Delete lapack.cc/h
5. The net result is that everything seems to be a bit faster.
   For LAPACK we are not doing some of the scaling work that
   dgels was doing. For Eigen I think it maybe the inplace
   decomposition.

Benchmark                                                                     Time             CPU      Time Old      Time New       CPU Old       CPU New
----------------------------------------------------------------------------------------------------------------------------------------------------------
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/1/1                          -0.1154         -0.1159           692           612           691           611
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/2/1                          -0.1601         -0.1553           717           603           712           601
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/3/1                          -0.1673         -0.1575           733           610           724           610
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/6/2                          -0.1008         -0.1003           886           797           884           796
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/10/3                         -0.1489         -0.1514          1283          1092          1281          1087
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/12/4                         -0.1040         -0.1104          1556          1394          1553          1381
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/20/5                         -0.0007         -0.0097          1911          1910          1908          1890
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/40/5                         -0.1033         -0.1022          2981          2673          2957          2655
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/100/10                       -0.0147         +0.0015          9275          9138          9026          9040
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/200/10                       -0.1408         -0.1284         15093         12968         14778         12880
BM_DenseSolver<ceres::EIGEN, ceres::DENSE_QR>/200/20                       -0.0310         -0.0355         38973         37765         38837         37460
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/1/1                         -0.1228         -0.1256           736           646           731           640
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/2/1                         -0.1401         -0.1396           740           636           735           633
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/3/1                         -0.1731         -0.1695           744           615           738           613
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/6/2                         -0.1399         -0.1408          1121           965          1113           956
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/10/3                        -0.1110         -0.1145          1571          1397          1560          1382
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/12/4                        -0.1411         -0.1417          2006          1722          1993          1710
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/20/5                        -0.1740         -0.1729          2741          2264          2724          2253
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/40/5                        -0.0966         -0.1123          3462          3128          3425          3040
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/100/10                      -0.0387         -0.0998         10365          9964         10339          9307
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/200/10                      -0.2044         -0.2049         16031         12754         15998         12720
BM_DenseSolver<ceres::LAPACK, ceres::DENSE_QR>/200/20                      -0.2391         -0.2386         35777         27223         35716         27193

Change-Id: I782f0d7664efe1435eebda92ddf47a0fe66c9c72
2022-02-07 11:54:01 -08:00
Sameer Agarwal 77c0c4d09c Migrate examples to use Manifolds
Also change NULL to nullptr.

Change-Id: I80a2328185d7891f61e07e64d5c1b59e74588ac7
2022-01-22 11:18:19 -08:00
Dmitriy Korchemkin 31008453fe Add example for BiCubicInterpolator
Add example of BiCubicInterpolator usage, for both analytic and
automatic differentiation

Change-Id: I2e52bec5e0721a21a789e714a126ea24b1c0ce8b
2021-10-06 20:26:18 +03:00
Sameer Agarwal 17dccef91b Add NumericDiffFirstOrderFunction
This has been a long requested feature so that users can minimize
functions using numeric differentiation.

As part of this, I have also redone rosenbrock.cc, which now has three
variants.

rosenbrock.cc now uses automatic differentiation.
rosenbrock_numeric_diff.cc uses numeric differentiation.
rosenbrock_analytic_diff.cc uses analytic derivatives.

This is analogus to how the helloworld example code is structured.

The tutorial for GradientProblemSolver has also been updated to reflect
this.

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

Change-Id: Ib0fb9e35127fe4c8299d4793bea3558722c70dd7
2021-09-15 06:21:02 -07:00