blob: eabeaed9a48e4a04839ca3491887688b6704d29b [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2015 Google Inc. All rights reserved.
3// 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;
56class LossFunction;
57class LocalParameterization;
58struct CRSMatrix;
59
60namespace internal {
61
62class Program;
63class ResidualBlock;
64
65class ProblemImpl {
66 public:
67 typedef std::map<double*, ParameterBlock*> ParameterMap;
68 typedef std::unordered_set<ResidualBlock*> ResidualBlockSet;
69 typedef std::map<CostFunction*, int> CostFunctionRefCount;
70 typedef std::map<LossFunction*, int> LossFunctionRefCount;
71
72 ProblemImpl();
73 explicit ProblemImpl(const Problem::Options& options);
74 ProblemImpl(const ProblemImpl&) = delete;
75 void operator=(const ProblemImpl&) = delete;
76
77 ~ProblemImpl();
78
79 // See the public problem.h file for description of these methods.
80 ResidualBlockId AddResidualBlock(
81 CostFunction* cost_function,
82 LossFunction* loss_function,
83 double* const* const parameter_blocks,
84 int num_parameter_blocks);
85
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);
104 void RemoveParameterBlock(double* values);
105
106 void SetParameterBlockConstant(double* values);
107 void SetParameterBlockVariable(double* values);
108 bool IsParameterBlockConstant(double* values) const;
109
110 void SetParameterization(double* values,
111 LocalParameterization* local_parameterization);
112 const LocalParameterization* GetParameterization(double* values) const;
113
114 void SetParameterLowerBound(double* values, int index, double lower_bound);
115 void SetParameterUpperBound(double* values, int index, double upper_bound);
116 double GetParameterLowerBound(double* values, int index) const;
117 double GetParameterUpperBound(double* values, int index) const;
118
119 bool Evaluate(const Problem::EvaluateOptions& options,
120 double* cost,
121 std::vector<double>* residuals,
122 std::vector<double>* gradient,
123 CRSMatrix* jacobian);
124
125 int NumParameterBlocks() const;
126 int NumParameters() const;
127 int NumResidualBlocks() const;
128 int NumResiduals() const;
129
130 int ParameterBlockSize(const double* parameter_block) const;
131 int ParameterBlockLocalSize(const double* parameter_block) const;
132
133 bool HasParameterBlock(const double* parameter_block) const;
134
135 void GetParameterBlocks(std::vector<double*>* parameter_blocks) const;
136 void GetResidualBlocks(std::vector<ResidualBlockId>* residual_blocks) const;
137
138 void GetParameterBlocksForResidualBlock(
139 const ResidualBlockId residual_block,
140 std::vector<double*>* parameter_blocks) const;
141
142 const CostFunction* GetCostFunctionForResidualBlock(
143 const ResidualBlockId residual_block) const;
144 const LossFunction* GetLossFunctionForResidualBlock(
145 const ResidualBlockId residual_block) const;
146
147 void GetResidualBlocksForParameterBlock(
148 const double* values,
149 std::vector<ResidualBlockId>* residual_blocks) const;
150
151 const Program& program() const { return *program_; }
152 Program* mutable_program() { return program_.get(); }
153
154 const ParameterMap& parameter_map() const { return parameter_block_map_; }
155 const ResidualBlockSet& residual_block_set() const {
156 CHECK(options_.enable_fast_removal)
157 << "Fast removal not enabled, residual_block_set is not maintained.";
158 return residual_block_set_;
159 }
160
161 ContextImpl* context() { return context_impl_; }
162
163 private:
164 ParameterBlock* InternalAddParameterBlock(double* values, int size);
165 void InternalRemoveResidualBlock(ResidualBlock* residual_block);
166
167 // Delete the arguments in question. These differ from the Remove* functions
168 // in that they do not clean up references to the block to delete; they
169 // merely delete them.
170 template <typename Block>
171 void DeleteBlockInVector(std::vector<Block*>* mutable_blocks,
172 Block* block_to_remove);
173 void DeleteBlock(ResidualBlock* residual_block);
174 void DeleteBlock(ParameterBlock* parameter_block);
175
176 const Problem::Options options_;
177
178 bool context_impl_owned_;
179 ContextImpl* context_impl_;
180
181 // The mapping from user pointers to parameter blocks.
182 ParameterMap parameter_block_map_;
183
184 // Iff enable_fast_removal is enabled, contains the current residual blocks.
185 ResidualBlockSet residual_block_set_;
186
187 // The actual parameter and residual blocks.
188 std::unique_ptr<internal::Program> program_;
189
190 // When removing parameter blocks, parameterizations have ambiguous
191 // ownership. Instead of scanning the entire problem to see if the
192 // parameterization is shared with other parameter blocks, buffer
193 // them until destruction.
194 //
195 // TODO(keir): See if it makes sense to use sets instead.
196 std::vector<LocalParameterization*> local_parameterizations_to_delete_;
197
198 // For each cost function and loss function in the problem, a count
199 // of the number of residual blocks that refer to them. When the
200 // count goes to zero and the problem owns these objects, they are
201 // destroyed.
202 CostFunctionRefCount cost_function_ref_count_;
203 LossFunctionRefCount loss_function_ref_count_;
204};
205
206} // namespace internal
207} // namespace ceres
208
209#endif // CERES_PUBLIC_PROBLEM_IMPL_H_