Home | History | Annotate | Download | only in ceres
      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 #include "ceres/program.h"
     32 
     33 #include <map>
     34 #include <vector>
     35 #include "ceres/array_utils.h"
     36 #include "ceres/casts.h"
     37 #include "ceres/compressed_row_sparse_matrix.h"
     38 #include "ceres/cost_function.h"
     39 #include "ceres/evaluator.h"
     40 #include "ceres/internal/port.h"
     41 #include "ceres/local_parameterization.h"
     42 #include "ceres/loss_function.h"
     43 #include "ceres/map_util.h"
     44 #include "ceres/parameter_block.h"
     45 #include "ceres/problem.h"
     46 #include "ceres/residual_block.h"
     47 #include "ceres/stl_util.h"
     48 #include "ceres/triplet_sparse_matrix.h"
     49 
     50 namespace ceres {
     51 namespace internal {
     52 
     53 Program::Program() {}
     54 
     55 Program::Program(const Program& program)
     56     : parameter_blocks_(program.parameter_blocks_),
     57       residual_blocks_(program.residual_blocks_) {
     58 }
     59 
     60 const vector<ParameterBlock*>& Program::parameter_blocks() const {
     61   return parameter_blocks_;
     62 }
     63 
     64 const vector<ResidualBlock*>& Program::residual_blocks() const {
     65   return residual_blocks_;
     66 }
     67 
     68 vector<ParameterBlock*>* Program::mutable_parameter_blocks() {
     69   return &parameter_blocks_;
     70 }
     71 
     72 vector<ResidualBlock*>* Program::mutable_residual_blocks() {
     73   return &residual_blocks_;
     74 }
     75 
     76 bool Program::StateVectorToParameterBlocks(const double *state) {
     77   for (int i = 0; i < parameter_blocks_.size(); ++i) {
     78     if (!parameter_blocks_[i]->IsConstant() &&
     79         !parameter_blocks_[i]->SetState(state)) {
     80       return false;
     81     }
     82     state += parameter_blocks_[i]->Size();
     83   }
     84   return true;
     85 }
     86 
     87 void Program::ParameterBlocksToStateVector(double *state) const {
     88   for (int i = 0; i < parameter_blocks_.size(); ++i) {
     89     parameter_blocks_[i]->GetState(state);
     90     state += parameter_blocks_[i]->Size();
     91   }
     92 }
     93 
     94 void Program::CopyParameterBlockStateToUserState() {
     95   for (int i = 0; i < parameter_blocks_.size(); ++i) {
     96     parameter_blocks_[i]->GetState(parameter_blocks_[i]->mutable_user_state());
     97   }
     98 }
     99 
    100 bool Program::SetParameterBlockStatePtrsToUserStatePtrs() {
    101   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    102     if (!parameter_blocks_[i]->IsConstant() &&
    103         !parameter_blocks_[i]->SetState(parameter_blocks_[i]->user_state())) {
    104       return false;
    105     }
    106   }
    107   return true;
    108 }
    109 
    110 bool Program::Plus(const double* state,
    111                    const double* delta,
    112                    double* state_plus_delta) const {
    113   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    114     if (!parameter_blocks_[i]->Plus(state, delta, state_plus_delta)) {
    115       return false;
    116     }
    117     state += parameter_blocks_[i]->Size();
    118     delta += parameter_blocks_[i]->LocalSize();
    119     state_plus_delta += parameter_blocks_[i]->Size();
    120   }
    121   return true;
    122 }
    123 
    124 void Program::SetParameterOffsetsAndIndex() {
    125   // Set positions for all parameters appearing as arguments to residuals to one
    126   // past the end of the parameter block array.
    127   for (int i = 0; i < residual_blocks_.size(); ++i) {
    128     ResidualBlock* residual_block = residual_blocks_[i];
    129     for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) {
    130       residual_block->parameter_blocks()[j]->set_index(-1);
    131     }
    132   }
    133   // For parameters that appear in the program, set their position and offset.
    134   int state_offset = 0;
    135   int delta_offset = 0;
    136   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    137     parameter_blocks_[i]->set_index(i);
    138     parameter_blocks_[i]->set_state_offset(state_offset);
    139     parameter_blocks_[i]->set_delta_offset(delta_offset);
    140     state_offset += parameter_blocks_[i]->Size();
    141     delta_offset += parameter_blocks_[i]->LocalSize();
    142   }
    143 }
    144 
    145 bool Program::IsValid() const {
    146   for (int i = 0; i < residual_blocks_.size(); ++i) {
    147     const ResidualBlock* residual_block = residual_blocks_[i];
    148     if (residual_block->index() != i) {
    149       LOG(WARNING) << "Residual block: " << i
    150                    << " has incorrect index: " << residual_block->index();
    151       return false;
    152     }
    153   }
    154 
    155   int state_offset = 0;
    156   int delta_offset = 0;
    157   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    158     const ParameterBlock* parameter_block = parameter_blocks_[i];
    159     if (parameter_block->index() != i ||
    160         parameter_block->state_offset() != state_offset ||
    161         parameter_block->delta_offset() != delta_offset) {
    162       LOG(WARNING) << "Parameter block: " << i
    163                    << "has incorrect indexing information: "
    164                    << parameter_block->ToString();
    165       return false;
    166     }
    167 
    168     state_offset += parameter_blocks_[i]->Size();
    169     delta_offset += parameter_blocks_[i]->LocalSize();
    170   }
    171 
    172   return true;
    173 }
    174 
    175 bool Program::ParameterBlocksAreFinite(string* message) const {
    176   CHECK_NOTNULL(message);
    177   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    178     const ParameterBlock* parameter_block = parameter_blocks_[i];
    179     const double* array = parameter_block->user_state();
    180     const int size = parameter_block->Size();
    181     const int invalid_index = FindInvalidValue(size, array);
    182     if (invalid_index != size) {
    183       *message = StringPrintf(
    184           "ParameterBlock: %p with size %d has at least one invalid value.\n"
    185           "First invalid value is at index: %d.\n"
    186           "Parameter block values: ",
    187           array, size, invalid_index);
    188       AppendArrayToString(size, array, message);
    189       return false;
    190     }
    191   }
    192   return true;
    193 }
    194 
    195 bool Program::IsBoundsConstrained() const {
    196   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    197     const ParameterBlock* parameter_block = parameter_blocks_[i];
    198     if (parameter_block->IsConstant()) {
    199       continue;
    200     }
    201     const int size = parameter_block->Size();
    202     for (int j = 0; j < size; ++j) {
    203       const double lower_bound = parameter_block->LowerBoundForParameter(j);
    204       const double upper_bound = parameter_block->UpperBoundForParameter(j);
    205       if (lower_bound > -std::numeric_limits<double>::max() ||
    206           upper_bound < std::numeric_limits<double>::max()) {
    207         return true;
    208       }
    209     }
    210   }
    211   return false;
    212 }
    213 
    214 bool Program::IsFeasible(string* message) const {
    215   CHECK_NOTNULL(message);
    216   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    217     const ParameterBlock* parameter_block = parameter_blocks_[i];
    218     const double* parameters = parameter_block->user_state();
    219     const int size = parameter_block->Size();
    220     if (parameter_block->IsConstant()) {
    221       // Constant parameter blocks must start in the feasible region
    222       // to ultimately produce a feasible solution, since Ceres cannot
    223       // change them.
    224       for (int j = 0; j < size; ++j) {
    225         const double lower_bound = parameter_block->LowerBoundForParameter(j);
    226         const double upper_bound = parameter_block->UpperBoundForParameter(j);
    227         if (parameters[j] < lower_bound || parameters[j] > upper_bound) {
    228           *message = StringPrintf(
    229               "ParameterBlock: %p with size %d has at least one infeasible "
    230               "value."
    231               "\nFirst infeasible value is at index: %d."
    232               "\nLower bound: %e, value: %e, upper bound: %e"
    233               "\nParameter block values: ",
    234               parameters, size, j, lower_bound, parameters[j], upper_bound);
    235           AppendArrayToString(size, parameters, message);
    236           return false;
    237         }
    238       }
    239     } else {
    240       // Variable parameter blocks must have non-empty feasible
    241       // regions, otherwise there is no way to produce a feasible
    242       // solution.
    243       for (int j = 0; j < size; ++j) {
    244         const double lower_bound = parameter_block->LowerBoundForParameter(j);
    245         const double upper_bound = parameter_block->UpperBoundForParameter(j);
    246         if (lower_bound >= upper_bound) {
    247           *message = StringPrintf(
    248               "ParameterBlock: %p with size %d has at least one infeasible "
    249               "bound."
    250               "\nFirst infeasible bound is at index: %d."
    251               "\nLower bound: %e, upper bound: %e"
    252               "\nParameter block values: ",
    253               parameters, size, j, lower_bound, upper_bound);
    254           AppendArrayToString(size, parameters, message);
    255           return false;
    256         }
    257       }
    258     }
    259   }
    260 
    261   return true;
    262 }
    263 
    264 Program* Program::CreateReducedProgram(vector<double*>* removed_parameter_blocks,
    265                                        double* fixed_cost,
    266                                        string* error) const {
    267   CHECK_NOTNULL(removed_parameter_blocks);
    268   CHECK_NOTNULL(fixed_cost);
    269   CHECK_NOTNULL(error);
    270 
    271   scoped_ptr<Program> reduced_program(new Program(*this));
    272   if (!reduced_program->RemoveFixedBlocks(removed_parameter_blocks,
    273                                           fixed_cost,
    274                                           error)) {
    275     return NULL;
    276   }
    277 
    278   reduced_program->SetParameterOffsetsAndIndex();
    279   return reduced_program.release();
    280 }
    281 
    282 bool Program::RemoveFixedBlocks(vector<double*>* removed_parameter_blocks,
    283                                 double* fixed_cost,
    284                                 string* error) {
    285   CHECK_NOTNULL(removed_parameter_blocks);
    286   CHECK_NOTNULL(fixed_cost);
    287   CHECK_NOTNULL(error);
    288 
    289   scoped_array<double> residual_block_evaluate_scratch;
    290   residual_block_evaluate_scratch.reset(
    291       new double[MaxScratchDoublesNeededForEvaluate()]);
    292   *fixed_cost = 0.0;
    293 
    294   // Mark all the parameters as unused. Abuse the index member of the
    295   // parameter blocks for the marking.
    296   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    297     parameter_blocks_[i]->set_index(-1);
    298   }
    299 
    300   // Filter out residual that have all-constant parameters, and mark
    301   // all the parameter blocks that appear in residuals.
    302   int num_active_residual_blocks = 0;
    303   for (int i = 0; i < residual_blocks_.size(); ++i) {
    304     ResidualBlock* residual_block = residual_blocks_[i];
    305     int num_parameter_blocks = residual_block->NumParameterBlocks();
    306 
    307     // Determine if the residual block is fixed, and also mark varying
    308     // parameters that appear in the residual block.
    309     bool all_constant = true;
    310     for (int k = 0; k < num_parameter_blocks; k++) {
    311       ParameterBlock* parameter_block = residual_block->parameter_blocks()[k];
    312       if (!parameter_block->IsConstant()) {
    313         all_constant = false;
    314         parameter_block->set_index(1);
    315       }
    316     }
    317 
    318     if (!all_constant) {
    319       residual_blocks_[num_active_residual_blocks++] = residual_block;
    320       continue;
    321     }
    322 
    323     // The residual is constant and will be removed, so its cost is
    324     // added to the variable fixed_cost.
    325     double cost = 0.0;
    326     if (!residual_block->Evaluate(true,
    327                                   &cost,
    328                                   NULL,
    329                                   NULL,
    330                                   residual_block_evaluate_scratch.get())) {
    331       *error = StringPrintf("Evaluation of the residual %d failed during "
    332                             "removal of fixed residual blocks.", i);
    333       return false;
    334     }
    335     *fixed_cost += cost;
    336   }
    337   residual_blocks_.resize(num_active_residual_blocks);
    338 
    339   // Filter out unused or fixed parameter blocks.
    340   int num_active_parameter_blocks = 0;
    341   removed_parameter_blocks->clear();
    342   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    343     ParameterBlock* parameter_block = parameter_blocks_[i];
    344     if (parameter_block->index() == -1) {
    345       removed_parameter_blocks->push_back(parameter_block->mutable_user_state());
    346     } else {
    347       parameter_blocks_[num_active_parameter_blocks++] = parameter_block;
    348     }
    349   }
    350   parameter_blocks_.resize(num_active_parameter_blocks);
    351 
    352   if (!(((NumResidualBlocks() == 0) &&
    353          (NumParameterBlocks() == 0)) ||
    354         ((NumResidualBlocks() != 0) &&
    355          (NumParameterBlocks() != 0)))) {
    356     *error =  "Congratulations, you found a bug in Ceres. Please report it.";
    357     return false;
    358   }
    359 
    360   return true;
    361 }
    362 
    363 bool Program::IsParameterBlockSetIndependent(const set<double*>& independent_set) const {
    364   // Loop over each residual block and ensure that no two parameter
    365   // blocks in the same residual block are part of
    366   // parameter_block_ptrs as that would violate the assumption that it
    367   // is an independent set in the Hessian matrix.
    368   for (vector<ResidualBlock*>::const_iterator it = residual_blocks_.begin();
    369        it != residual_blocks_.end();
    370        ++it) {
    371     ParameterBlock* const* parameter_blocks = (*it)->parameter_blocks();
    372     const int num_parameter_blocks = (*it)->NumParameterBlocks();
    373     int count = 0;
    374     for (int i = 0; i < num_parameter_blocks; ++i) {
    375       count += independent_set.count(
    376           parameter_blocks[i]->mutable_user_state());
    377     }
    378     if (count > 1) {
    379       return false;
    380     }
    381   }
    382   return true;
    383 }
    384 
    385 TripletSparseMatrix* Program::CreateJacobianBlockSparsityTranspose() const {
    386   // Matrix to store the block sparsity structure of the Jacobian.
    387   TripletSparseMatrix* tsm =
    388       new TripletSparseMatrix(NumParameterBlocks(),
    389                               NumResidualBlocks(),
    390                               10 * NumResidualBlocks());
    391   int num_nonzeros = 0;
    392   int* rows = tsm->mutable_rows();
    393   int* cols = tsm->mutable_cols();
    394   double* values = tsm->mutable_values();
    395 
    396   for (int c = 0; c < residual_blocks_.size(); ++c) {
    397     const ResidualBlock* residual_block = residual_blocks_[c];
    398     const int num_parameter_blocks = residual_block->NumParameterBlocks();
    399     ParameterBlock* const* parameter_blocks =
    400         residual_block->parameter_blocks();
    401 
    402     for (int j = 0; j < num_parameter_blocks; ++j) {
    403       if (parameter_blocks[j]->IsConstant()) {
    404         continue;
    405       }
    406 
    407       // Re-size the matrix if needed.
    408       if (num_nonzeros >= tsm->max_num_nonzeros()) {
    409         tsm->set_num_nonzeros(num_nonzeros);
    410         tsm->Reserve(2 * num_nonzeros);
    411         rows = tsm->mutable_rows();
    412         cols = tsm->mutable_cols();
    413         values = tsm->mutable_values();
    414       }
    415 
    416       const int r = parameter_blocks[j]->index();
    417       rows[num_nonzeros] = r;
    418       cols[num_nonzeros] = c;
    419       values[num_nonzeros] = 1.0;
    420       ++num_nonzeros;
    421     }
    422   }
    423 
    424   tsm->set_num_nonzeros(num_nonzeros);
    425   return tsm;
    426 }
    427 
    428 int Program::NumResidualBlocks() const {
    429   return residual_blocks_.size();
    430 }
    431 
    432 int Program::NumParameterBlocks() const {
    433   return parameter_blocks_.size();
    434 }
    435 
    436 int Program::NumResiduals() const {
    437   int num_residuals = 0;
    438   for (int i = 0; i < residual_blocks_.size(); ++i) {
    439     num_residuals += residual_blocks_[i]->NumResiduals();
    440   }
    441   return num_residuals;
    442 }
    443 
    444 int Program::NumParameters() const {
    445   int num_parameters = 0;
    446   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    447     num_parameters += parameter_blocks_[i]->Size();
    448   }
    449   return num_parameters;
    450 }
    451 
    452 int Program::NumEffectiveParameters() const {
    453   int num_parameters = 0;
    454   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    455     num_parameters += parameter_blocks_[i]->LocalSize();
    456   }
    457   return num_parameters;
    458 }
    459 
    460 int Program::MaxScratchDoublesNeededForEvaluate() const {
    461   // Compute the scratch space needed for evaluate.
    462   int max_scratch_bytes_for_evaluate = 0;
    463   for (int i = 0; i < residual_blocks_.size(); ++i) {
    464     max_scratch_bytes_for_evaluate =
    465         max(max_scratch_bytes_for_evaluate,
    466             residual_blocks_[i]->NumScratchDoublesForEvaluate());
    467   }
    468   return max_scratch_bytes_for_evaluate;
    469 }
    470 
    471 int Program::MaxDerivativesPerResidualBlock() const {
    472   int max_derivatives = 0;
    473   for (int i = 0; i < residual_blocks_.size(); ++i) {
    474     int derivatives = 0;
    475     ResidualBlock* residual_block = residual_blocks_[i];
    476     int num_parameters = residual_block->NumParameterBlocks();
    477     for (int j = 0; j < num_parameters; ++j) {
    478       derivatives += residual_block->NumResiduals() *
    479                      residual_block->parameter_blocks()[j]->LocalSize();
    480     }
    481     max_derivatives = max(max_derivatives, derivatives);
    482   }
    483   return max_derivatives;
    484 }
    485 
    486 int Program::MaxParametersPerResidualBlock() const {
    487   int max_parameters = 0;
    488   for (int i = 0; i < residual_blocks_.size(); ++i) {
    489     max_parameters = max(max_parameters,
    490                          residual_blocks_[i]->NumParameterBlocks());
    491   }
    492   return max_parameters;
    493 }
    494 
    495 int Program::MaxResidualsPerResidualBlock() const {
    496   int max_residuals = 0;
    497   for (int i = 0; i < residual_blocks_.size(); ++i) {
    498     max_residuals = max(max_residuals,
    499                         residual_blocks_[i]->NumResiduals());
    500   }
    501   return max_residuals;
    502 }
    503 
    504 string Program::ToString() const {
    505   string ret = "Program dump\n";
    506   ret += StringPrintf("Number of parameter blocks: %d\n", NumParameterBlocks());
    507   ret += StringPrintf("Number of parameters: %d\n", NumParameters());
    508   ret += "Parameters:\n";
    509   for (int i = 0; i < parameter_blocks_.size(); ++i) {
    510     ret += StringPrintf("%d: %s\n",
    511                         i, parameter_blocks_[i]->ToString().c_str());
    512   }
    513   return ret;
    514 }
    515 
    516 }  // namespace internal
    517 }  // namespace ceres
    518