| // Ceres Solver - A fast non-linear least squares minimizer |
| // Copyright 2012 Google Inc. All rights reserved. |
| // http://code.google.com/p/ceres-solver/ |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are met: |
| // |
| // * Redistributions of source code must retain the above copyright notice, |
| // this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above copyright notice, |
| // this list of conditions and the following disclaimer in the documentation |
| // and/or other materials provided with the distribution. |
| // * Neither the name of Google Inc. nor the names of its contributors may be |
| // used to endorse or promote products derived from this software without |
| // specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
| // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| // POSSIBILITY OF SUCH DAMAGE. |
| // |
| // Author: sameeragarwal@google.com (Sameer Agarwal) |
| |
| #include <map> |
| #include <set> |
| #include "ceres/internal/port.h" |
| #include "glog/logging.h" |
| |
| namespace ceres { |
| |
| // The order in which variables are eliminated in a linear solver can |
| // have a significant of impact on the efficiency and accuracy of the |
| // method. e.g., when doing sparse Cholesky factorization, there are |
| // matrices for which a good ordering will give a Cholesky factor with |
| // O(n) storage, where as a bad ordering will result in an completely |
| // dense factor. |
| // |
| // Ceres allows the user to provide varying amounts of hints to the |
| // solver about the variable elimination ordering to use. This can |
| // range from no hints, where the solver is free to decide the best |
| // possible ordering based on the user's choices like the linear |
| // solver being used, to an exact order in which the variables should |
| // be eliminated, and a variety of possibilities in between. Instances |
| // of the Ordering class are used to communicate this infornation to |
| // Ceres. |
| // |
| // Formally an ordering is an ordered partitioning of the parameter |
| // blocks, i.e, each parameter block belongs to exactly one group, and |
| // each group has a unique integer associated with it, that determines |
| // its order in the set of groups. |
| // |
| // Given such an ordering, Ceres ensures that the parameter blocks in |
| // the lowest numbered group are eliminated first, and then the |
| // parmeter blocks in the next lowest numbered group and so on. Within |
| // each group, Ceres is free to order the parameter blocks as it |
| // chooses. |
| // e.g. Consider the linear system |
| // |
| // x + y = 3 |
| // 2x + 3y = 7 |
| // |
| // There are two ways in which it can be solved. First eliminating x |
| // from the two equations, solving for y and then back substituting |
| // for x, or first eliminating y, solving for x and back substituting |
| // for y. The user can construct three orderings here. |
| // |
| // {0: x}, {1: y} - eliminate x first. |
| // {0: y}, {1: x} - eliminate y first. |
| // {0: x, y} - Solver gets to decide the elimination order. |
| // |
| // Thus, to have Ceres determine the ordering automatically using |
| // heuristics, put all the variables in group 0 and to control the |
| // ordering for every variable, create groups 0..N-1, one per |
| // variable, in the desired order. |
| // |
| // Bundle Adjustment |
| // ----------------- |
| // |
| // A particular case of interest is bundle adjustment, where the user |
| // has two options. The default is to not specify an ordering at all, |
| // the solver will see that the user wants to use a Schur type solver |
| // and figure out the right elimination ordering. |
| // |
| // But if the user already knows what parameter blocks are points and |
| // what are cameras, they can save preprocessing time by partitioning |
| // the parameter blocks into two groups, one for the points and one |
| // for the cameras, where the group containing the points has an id |
| // smaller than the group containing cameras. |
| class Ordering { |
| public: |
| // Add a parameter block to a group with id group_id. If a group |
| // with this id does not exist, one is created. This method can be |
| // called any number of times for a parameter block. |
| void AddParameterBlockToGroup(double* parameter_block, int group_id); |
| |
| // Remove the parameter block from the ordering, no matter what |
| // group it is in. If the parameter block is not known to the |
| // ordering, calling this method will result in a crash. |
| void RemoveParameterBlock(double* parameter_block); |
| |
| // Return the group id for the parameter block. If the parameter |
| // block is not known to the Ordering, calling this method results |
| // in a crash. |
| int GroupIdForParameterBlock(double* parameter_block) const; |
| |
| // This function always succeeds. For a group_id unknown to the |
| // ordering is treated as empty groups and the function returns |
| // zero. |
| int GroupSize(int group_id) const; |
| |
| bool ContainsParameterBlock(double* parameter_block) const; |
| int NumParameterBlocks() const; |
| int NumGroups() const; |
| const map<int, set<double*> >& group_id_to_parameter_blocks() const; |
| |
| private: |
| map<int, set<double*> > group_id_to_parameter_blocks_; |
| map<double*, int> parameter_block_to_group_id_; |
| }; |
| |
| } // namespace ceres |