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 (at) 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 146 const Program& program() const { return *program_; } 147 Program* mutable_program() { return program_.get(); } 148 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