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/collections_port.h" 49 #include "ceres/problem.h" 50 #include "ceres/types.h" 51 52 namespace ceres { 53 54 class CostFunction; 55 class LossFunction; 56 class LocalParameterization; 57 struct CRSMatrix; 58 59 namespace internal { 60 61 class Program; 62 class ResidualBlock; 63 64 class ProblemImpl { 65 public: 66 typedef map<double*, ParameterBlock*> ParameterMap; 67 typedef HashSet<ResidualBlock*> ResidualBlockSet; 68 69 ProblemImpl(); 70 explicit ProblemImpl(const Problem::Options& options); 71 72 ~ProblemImpl(); 73 74 // See the public problem.h file for description of these methods. 75 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 76 LossFunction* loss_function, 77 const vector<double*>& parameter_blocks); 78 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 79 LossFunction* loss_function, 80 double* x0); 81 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 82 LossFunction* loss_function, 83 double* x0, double* x1); 84 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 85 LossFunction* loss_function, 86 double* x0, double* x1, double* x2); 87 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 88 LossFunction* loss_function, 89 double* x0, double* x1, double* x2, 90 double* x3); 91 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 92 LossFunction* loss_function, 93 double* x0, double* x1, double* x2, 94 double* x3, double* x4); 95 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 96 LossFunction* loss_function, 97 double* x0, double* x1, double* x2, 98 double* x3, double* x4, double* x5); 99 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 100 LossFunction* loss_function, 101 double* x0, double* x1, double* x2, 102 double* x3, double* x4, double* x5, 103 double* x6); 104 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 105 LossFunction* loss_function, 106 double* x0, double* x1, double* x2, 107 double* x3, double* x4, double* x5, 108 double* x6, double* x7); 109 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 110 LossFunction* loss_function, 111 double* x0, double* x1, double* x2, 112 double* x3, double* x4, double* x5, 113 double* x6, double* x7, double* x8); 114 ResidualBlockId AddResidualBlock(CostFunction* cost_function, 115 LossFunction* loss_function, 116 double* x0, double* x1, double* x2, 117 double* x3, double* x4, double* x5, 118 double* x6, double* x7, double* x8, 119 double* x9); 120 void AddParameterBlock(double* values, int size); 121 void AddParameterBlock(double* values, 122 int size, 123 LocalParameterization* local_parameterization); 124 125 void RemoveResidualBlock(ResidualBlock* residual_block); 126 void RemoveParameterBlock(double* values); 127 128 void SetParameterBlockConstant(double* values); 129 void SetParameterBlockVariable(double* values); 130 void SetParameterization(double* values, 131 LocalParameterization* local_parameterization); 132 const LocalParameterization* GetParameterization(double* values) const; 133 134 void SetParameterLowerBound(double* values, int index, double lower_bound); 135 void SetParameterUpperBound(double* values, int index, double upper_bound); 136 137 bool Evaluate(const Problem::EvaluateOptions& options, 138 double* cost, 139 vector<double>* residuals, 140 vector<double>* gradient, 141 CRSMatrix* jacobian); 142 143 int NumParameterBlocks() const; 144 int NumParameters() const; 145 int NumResidualBlocks() const; 146 int NumResiduals() const; 147 148 int ParameterBlockSize(const double* parameter_block) const; 149 int ParameterBlockLocalSize(const double* parameter_block) const; 150 151 bool HasParameterBlock(const double* parameter_block) const; 152 153 void GetParameterBlocks(vector<double*>* parameter_blocks) const; 154 void GetResidualBlocks(vector<ResidualBlockId>* residual_blocks) const; 155 156 void GetParameterBlocksForResidualBlock( 157 const ResidualBlockId residual_block, 158 vector<double*>* parameter_blocks) const; 159 160 void GetResidualBlocksForParameterBlock( 161 const double* values, 162 vector<ResidualBlockId>* residual_blocks) const; 163 164 const Program& program() const { return *program_; } 165 Program* mutable_program() { return program_.get(); } 166 167 const ParameterMap& parameter_map() const { return parameter_block_map_; } 168 const ResidualBlockSet& residual_block_set() const { 169 CHECK(options_.enable_fast_removal) 170 << "Fast removal not enabled, residual_block_set is not maintained."; 171 return residual_block_set_; 172 } 173 174 private: 175 ParameterBlock* InternalAddParameterBlock(double* values, int size); 176 void InternalRemoveResidualBlock(ResidualBlock* residual_block); 177 178 bool InternalEvaluate(Program* program, 179 double* cost, 180 vector<double>* residuals, 181 vector<double>* gradient, 182 CRSMatrix* jacobian); 183 184 // Delete the arguments in question. These differ from the Remove* functions 185 // in that they do not clean up references to the block to delete; they 186 // merely delete them. 187 template<typename Block> 188 void DeleteBlockInVector(vector<Block*>* mutable_blocks, 189 Block* block_to_remove); 190 void DeleteBlock(ResidualBlock* residual_block); 191 void DeleteBlock(ParameterBlock* parameter_block); 192 193 const Problem::Options options_; 194 195 // The mapping from user pointers to parameter blocks. 196 map<double*, ParameterBlock*> parameter_block_map_; 197 198 // Iff enable_fast_removal is enabled, contains the current residual blocks. 199 ResidualBlockSet residual_block_set_; 200 201 // The actual parameter and residual blocks. 202 internal::scoped_ptr<internal::Program> program_; 203 204 // When removing residual and parameter blocks, cost/loss functions and 205 // parameterizations have ambiguous ownership. Instead of scanning the entire 206 // problem to see if the cost/loss/parameterization is shared with other 207 // residual or parameter blocks, buffer them until destruction. 208 // 209 // TODO(keir): See if it makes sense to use sets instead. 210 vector<CostFunction*> cost_functions_to_delete_; 211 vector<LossFunction*> loss_functions_to_delete_; 212 vector<LocalParameterization*> local_parameterizations_to_delete_; 213 214 CERES_DISALLOW_COPY_AND_ASSIGN(ProblemImpl); 215 }; 216 217 } // namespace internal 218 } // namespace ceres 219 220 #endif // CERES_PUBLIC_PROBLEM_IMPL_H_ 221