• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Ceres Solver - A fast non-linear least squares minimizer
2 // Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
3 // http://code.google.com/p/ceres-solver/
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 <map>
43 #include <vector>
44 
45 #include "ceres/internal/macros.h"
46 #include "ceres/internal/port.h"
47 #include "ceres/internal/scoped_ptr.h"
48 #include "ceres/problem.h"
49 #include "ceres/types.h"
50 
51 namespace ceres {
52 
53 class CostFunction;
54 class LossFunction;
55 class LocalParameterization;
56 struct CRSMatrix;
57 
58 namespace internal {
59 
60 class Program;
61 class ResidualBlock;
62 
63 class ProblemImpl {
64  public:
65   typedef map<double*, ParameterBlock*> ParameterMap;
66 
67   ProblemImpl();
68   explicit ProblemImpl(const Problem::Options& options);
69 
70   ~ProblemImpl();
71 
72   // See the public problem.h file for description of these methods.
73   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
74                                    LossFunction* loss_function,
75                                    const vector<double*>& parameter_blocks);
76   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
77                                    LossFunction* loss_function,
78                                    double* x0);
79   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
80                                    LossFunction* loss_function,
81                                    double* x0, double* x1);
82   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
83                                    LossFunction* loss_function,
84                                    double* x0, double* x1, double* x2);
85   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
86                                    LossFunction* loss_function,
87                                    double* x0, double* x1, double* x2,
88                                    double* x3);
89   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
90                                    LossFunction* loss_function,
91                                    double* x0, double* x1, double* x2,
92                                    double* x3, double* x4);
93   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
94                                    LossFunction* loss_function,
95                                    double* x0, double* x1, double* x2,
96                                    double* x3, double* x4, double* x5);
97   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
98                                    LossFunction* loss_function,
99                                    double* x0, double* x1, double* x2,
100                                    double* x3, double* x4, double* x5,
101                                    double* x6);
102   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
103                                    LossFunction* loss_function,
104                                    double* x0, double* x1, double* x2,
105                                    double* x3, double* x4, double* x5,
106                                    double* x6, double* x7);
107   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
108                                    LossFunction* loss_function,
109                                    double* x0, double* x1, double* x2,
110                                    double* x3, double* x4, double* x5,
111                                    double* x6, double* x7, double* x8);
112   ResidualBlockId AddResidualBlock(CostFunction* cost_function,
113                                    LossFunction* loss_function,
114                                    double* x0, double* x1, double* x2,
115                                    double* x3, double* x4, double* x5,
116                                    double* x6, double* x7, double* x8,
117                                    double* x9);
118   void AddParameterBlock(double* values, int size);
119   void AddParameterBlock(double* values,
120                          int size,
121                          LocalParameterization* local_parameterization);
122 
123   void RemoveResidualBlock(ResidualBlock* residual_block);
124   void RemoveParameterBlock(double* values);
125 
126   void SetParameterBlockConstant(double* values);
127   void SetParameterBlockVariable(double* values);
128   void SetParameterization(double* values,
129                            LocalParameterization* local_parameterization);
130 
131   bool Evaluate(const Problem::EvaluateOptions& options,
132                 double* cost,
133                 vector<double>* residuals,
134                 vector<double>* gradient,
135                 CRSMatrix* jacobian);
136 
137   int NumParameterBlocks() const;
138   int NumParameters() const;
139   int NumResidualBlocks() const;
140   int NumResiduals() const;
141 
142   int ParameterBlockSize(const double* parameter_block) const;
143   int ParameterBlockLocalSize(const double* parameter_block) const;
144   void GetParameterBlocks(vector<double*>* parameter_blocks) const;
145 
program()146   const Program& program() const { return *program_; }
mutable_program()147   Program* mutable_program() { return program_.get(); }
148 
parameter_map()149   const ParameterMap& parameter_map() const { return parameter_block_map_; }
150 
151  private:
152   ParameterBlock* InternalAddParameterBlock(double* values, int size);
153 
154   bool InternalEvaluate(Program* program,
155                         double* cost,
156                         vector<double>* residuals,
157                         vector<double>* gradient,
158                         CRSMatrix* jacobian);
159 
160   // Delete the arguments in question. These differ from the Remove* functions
161   // in that they do not clean up references to the block to delete; they
162   // merely delete them.
163   template<typename Block>
164   void DeleteBlockInVector(vector<Block*>* mutable_blocks,
165                            Block* block_to_remove);
166   void DeleteBlock(ResidualBlock* residual_block);
167   void DeleteBlock(ParameterBlock* parameter_block);
168 
169   const Problem::Options options_;
170 
171   // The mapping from user pointers to parameter blocks.
172   map<double*, ParameterBlock*> parameter_block_map_;
173 
174   // The actual parameter and residual blocks.
175   internal::scoped_ptr<internal::Program> program_;
176 
177   // When removing residual and parameter blocks, cost/loss functions and
178   // parameterizations have ambiguous ownership. Instead of scanning the entire
179   // problem to see if the cost/loss/parameterization is shared with other
180   // residual or parameter blocks, buffer them until destruction.
181   //
182   // TODO(keir): See if it makes sense to use sets instead.
183   vector<CostFunction*> cost_functions_to_delete_;
184   vector<LossFunction*> loss_functions_to_delete_;
185   vector<LocalParameterization*> local_parameterizations_to_delete_;
186 
187   CERES_DISALLOW_COPY_AND_ASSIGN(ProblemImpl);
188 };
189 
190 }  // namespace internal
191 }  // namespace ceres
192 
193 #endif  // CERES_PUBLIC_PROBLEM_IMPL_H_
194