blob: 9abff3f19aec3d87c3f2ff431358f992bf7cf20c [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
Austin Schuh1d1e6ea2020-12-23 21:56:30 -08002// Copyright 2019 Google Inc. All rights reserved.
Austin Schuh70cc9552019-01-21 19:46:48 -08003// http://ceres-solver.org/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28//
29// Author: keir@google.com (Keir Mierle)
30//
31// This is the implementation of the public Problem API. The pointer to
32// implementation (PIMPL) idiom makes it possible for Ceres internal code to
33// refer to the private data members without needing to exposing it to the
34// world. An alternative to PIMPL is to have a factory which returns instances
35// of a virtual base class; while that approach would work, it requires clients
36// to always put a Problem object into a scoped pointer; this needlessly muddies
37// client code for little benefit. Therefore, the PIMPL comprise was chosen.
38
39#ifndef CERES_PUBLIC_PROBLEM_IMPL_H_
40#define CERES_PUBLIC_PROBLEM_IMPL_H_
41
42#include <array>
43#include <map>
44#include <memory>
45#include <unordered_set>
46#include <vector>
47
48#include "ceres/context_impl.h"
49#include "ceres/internal/port.h"
50#include "ceres/problem.h"
51#include "ceres/types.h"
52
53namespace ceres {
54
55class CostFunction;
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080056class EvaluationCallback;
Austin Schuh70cc9552019-01-21 19:46:48 -080057class LossFunction;
58class LocalParameterization;
59struct CRSMatrix;
60
61namespace internal {
62
63class Program;
64class ResidualBlock;
65
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080066class CERES_EXPORT_INTERNAL ProblemImpl {
Austin Schuh70cc9552019-01-21 19:46:48 -080067 public:
68 typedef std::map<double*, ParameterBlock*> ParameterMap;
69 typedef std::unordered_set<ResidualBlock*> ResidualBlockSet;
70 typedef std::map<CostFunction*, int> CostFunctionRefCount;
71 typedef std::map<LossFunction*, int> LossFunctionRefCount;
72
73 ProblemImpl();
74 explicit ProblemImpl(const Problem::Options& options);
75 ProblemImpl(const ProblemImpl&) = delete;
76 void operator=(const ProblemImpl&) = delete;
77
78 ~ProblemImpl();
79
80 // See the public problem.h file for description of these methods.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080081 ResidualBlockId AddResidualBlock(CostFunction* cost_function,
82 LossFunction* loss_function,
83 double* const* const parameter_blocks,
84 int num_parameter_blocks);
Austin Schuh70cc9552019-01-21 19:46:48 -080085
86 template <typename... Ts>
87 ResidualBlockId AddResidualBlock(CostFunction* cost_function,
88 LossFunction* loss_function,
89 double* x0,
90 Ts*... xs) {
91 const std::array<double*, sizeof...(Ts) + 1> parameter_blocks{{x0, xs...}};
92 return AddResidualBlock(cost_function,
93 loss_function,
94 parameter_blocks.data(),
95 static_cast<int>(parameter_blocks.size()));
96 }
97
98 void AddParameterBlock(double* values, int size);
99 void AddParameterBlock(double* values,
100 int size,
101 LocalParameterization* local_parameterization);
102
103 void RemoveResidualBlock(ResidualBlock* residual_block);
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800104 void RemoveParameterBlock(const double* values);
Austin Schuh70cc9552019-01-21 19:46:48 -0800105
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800106 void SetParameterBlockConstant(const double* values);
Austin Schuh70cc9552019-01-21 19:46:48 -0800107 void SetParameterBlockVariable(double* values);
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800108 bool IsParameterBlockConstant(const double* values) const;
Austin Schuh70cc9552019-01-21 19:46:48 -0800109
110 void SetParameterization(double* values,
111 LocalParameterization* local_parameterization);
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800112 const LocalParameterization* GetParameterization(const double* values) const;
Austin Schuh70cc9552019-01-21 19:46:48 -0800113
114 void SetParameterLowerBound(double* values, int index, double lower_bound);
115 void SetParameterUpperBound(double* values, int index, double upper_bound);
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800116 double GetParameterLowerBound(const double* values, int index) const;
117 double GetParameterUpperBound(const double* values, int index) const;
Austin Schuh70cc9552019-01-21 19:46:48 -0800118
119 bool Evaluate(const Problem::EvaluateOptions& options,
120 double* cost,
121 std::vector<double>* residuals,
122 std::vector<double>* gradient,
123 CRSMatrix* jacobian);
124
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800125 bool EvaluateResidualBlock(ResidualBlock* residual_block,
126 bool apply_loss_function,
127 bool new_point,
128 double* cost,
129 double* residuals,
130 double** jacobians) const;
131
Austin Schuh70cc9552019-01-21 19:46:48 -0800132 int NumParameterBlocks() const;
133 int NumParameters() const;
134 int NumResidualBlocks() const;
135 int NumResiduals() const;
136
137 int ParameterBlockSize(const double* parameter_block) const;
138 int ParameterBlockLocalSize(const double* parameter_block) const;
139
140 bool HasParameterBlock(const double* parameter_block) const;
141
142 void GetParameterBlocks(std::vector<double*>* parameter_blocks) const;
143 void GetResidualBlocks(std::vector<ResidualBlockId>* residual_blocks) const;
144
145 void GetParameterBlocksForResidualBlock(
146 const ResidualBlockId residual_block,
147 std::vector<double*>* parameter_blocks) const;
148
149 const CostFunction* GetCostFunctionForResidualBlock(
150 const ResidualBlockId residual_block) const;
151 const LossFunction* GetLossFunctionForResidualBlock(
152 const ResidualBlockId residual_block) const;
153
154 void GetResidualBlocksForParameterBlock(
155 const double* values,
156 std::vector<ResidualBlockId>* residual_blocks) const;
157
158 const Program& program() const { return *program_; }
159 Program* mutable_program() { return program_.get(); }
160
161 const ParameterMap& parameter_map() const { return parameter_block_map_; }
162 const ResidualBlockSet& residual_block_set() const {
163 CHECK(options_.enable_fast_removal)
164 << "Fast removal not enabled, residual_block_set is not maintained.";
165 return residual_block_set_;
166 }
167
168 ContextImpl* context() { return context_impl_; }
169
170 private:
171 ParameterBlock* InternalAddParameterBlock(double* values, int size);
172 void InternalRemoveResidualBlock(ResidualBlock* residual_block);
173
174 // Delete the arguments in question. These differ from the Remove* functions
175 // in that they do not clean up references to the block to delete; they
176 // merely delete them.
177 template <typename Block>
178 void DeleteBlockInVector(std::vector<Block*>* mutable_blocks,
179 Block* block_to_remove);
180 void DeleteBlock(ResidualBlock* residual_block);
181 void DeleteBlock(ParameterBlock* parameter_block);
182
183 const Problem::Options options_;
184
185 bool context_impl_owned_;
186 ContextImpl* context_impl_;
187
188 // The mapping from user pointers to parameter blocks.
189 ParameterMap parameter_block_map_;
190
191 // Iff enable_fast_removal is enabled, contains the current residual blocks.
192 ResidualBlockSet residual_block_set_;
193
194 // The actual parameter and residual blocks.
195 std::unique_ptr<internal::Program> program_;
196
197 // When removing parameter blocks, parameterizations have ambiguous
198 // ownership. Instead of scanning the entire problem to see if the
199 // parameterization is shared with other parameter blocks, buffer
200 // them until destruction.
201 //
202 // TODO(keir): See if it makes sense to use sets instead.
203 std::vector<LocalParameterization*> local_parameterizations_to_delete_;
204
205 // For each cost function and loss function in the problem, a count
206 // of the number of residual blocks that refer to them. When the
207 // count goes to zero and the problem owns these objects, they are
208 // destroyed.
209 CostFunctionRefCount cost_function_ref_count_;
210 LossFunctionRefCount loss_function_ref_count_;
211};
212
213} // namespace internal
214} // namespace ceres
215
216#endif // CERES_PUBLIC_PROBLEM_IMPL_H_