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/collections_port.h" 49#include "ceres/problem.h" 50#include "ceres/types.h" 51 52namespace ceres { 53 54class CostFunction; 55class LossFunction; 56class LocalParameterization; 57struct CRSMatrix; 58 59namespace internal { 60 61class Program; 62class ResidualBlock; 63 64class 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