Move inner iteration ordering related methods. Inner iterations require specific constraints on parameter block orderings. The creation and validation routines for these orderings are not static methods in CoordinateDescentMinimizer. Change-Id: Ifc89491c9a8672e08523191b74b53058cbfa1db3
diff --git a/internal/ceres/coordinate_descent_minimizer.cc b/internal/ceres/coordinate_descent_minimizer.cc index bfe93c4..3b0553e 100644 --- a/internal/ceres/coordinate_descent_minimizer.cc +++ b/internal/ceres/coordinate_descent_minimizer.cc
@@ -40,15 +40,15 @@ #include "ceres/evaluator.h" #include "ceres/linear_solver.h" #include "ceres/minimizer.h" -#include "ceres/ordered_groups.h" #include "ceres/parameter_block.h" +#include "ceres/parameter_block_ordering.h" #include "ceres/problem_impl.h" #include "ceres/program.h" #include "ceres/residual_block.h" #include "ceres/solver.h" -#include "ceres/solver_impl.h" #include "ceres/trust_region_minimizer.h" #include "ceres/trust_region_strategy.h" +#include "ceres/parameter_block_ordering.h" namespace ceres { namespace internal { @@ -233,5 +233,38 @@ minimizer.Minimize(minimizer_options, parameter, summary); } +bool CoordinateDescentMinimizer::IsOrderingValid( + const Program& program, + const ParameterBlockOrdering& ordering, + string* message) { + const map<int, set<double*> >& group_to_elements = + ordering.group_to_elements(); + + // Verify that each group is an independent set + map<int, set<double*> >::const_iterator it = group_to_elements.begin(); + for ( ; it != group_to_elements.end(); ++it) { + if (!program.IsParameterBlockSetIndependent(it->second)) { + *message = + StringPrintf("The user-provided " + "parameter_blocks_for_inner_iterations does not " + "form an independent set. Group Id: %d", it->first); + return false; + } + } + return true; +} + +// Find a recursive decomposition of the Hessian matrix as a set +// of independent sets of decreasing size and invert it. This +// seems to work better in practice, i.e., Cameras before +// points. +ParameterBlockOrdering* CoordinateDescentMinimizer::CreateOrdering( + const Program& program) { + scoped_ptr<ParameterBlockOrdering> ordering(new ParameterBlockOrdering); + ComputeRecursiveIndependentSetOrdering(program, ordering.get()); + ordering->Reverse(); + return ordering.release(); +} + } // namespace internal } // namespace ceres
diff --git a/internal/ceres/coordinate_descent_minimizer.h b/internal/ceres/coordinate_descent_minimizer.h index 424acda..e324b38 100644 --- a/internal/ceres/coordinate_descent_minimizer.h +++ b/internal/ceres/coordinate_descent_minimizer.h
@@ -37,12 +37,13 @@ #include "ceres/evaluator.h" #include "ceres/minimizer.h" #include "ceres/problem_impl.h" -#include "ceres/program.h" #include "ceres/solver.h" namespace ceres { namespace internal { +class Program; + // Given a Program, and a ParameterBlockOrdering which partitions // (non-exhaustively) the Hessian matrix into independent sets, // perform coordinate descent on the parameter blocks in the @@ -66,6 +67,17 @@ double* parameters, Solver::Summary* summary); + // Verify that each group in the ordering forms an independent set. + static bool IsOrderingValid(const Program& program, + const ParameterBlockOrdering& ordering, + string* message); + + // Find a recursive decomposition of the Hessian matrix as a set + // of independent sets of decreasing size and invert it. This + // seems to work better in practice, i.e., Cameras before + // points. + static ParameterBlockOrdering* CreateOrdering(const Program& program); + private: void Solve(Program* program, LinearSolver* linear_solver,
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index 24034be..11398b1 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -1025,33 +1025,16 @@ ParameterBlockOrdering* ordering_ptr = NULL; if (options.inner_iteration_ordering.get() == NULL) { - // Find a recursive decomposition of the Hessian matrix as a set - // of independent sets of decreasing size and invert it. This - // seems to work better in practice, i.e., Cameras before - // points. - inner_iteration_ordering.reset(new ParameterBlockOrdering); - ComputeRecursiveIndependentSetOrdering(program, - inner_iteration_ordering.get()); - inner_iteration_ordering->Reverse(); + inner_iteration_ordering.reset( + CoordinateDescentMinimizer::CreateOrdering(program)); ordering_ptr = inner_iteration_ordering.get(); } else { - const map<int, set<double*> >& group_to_elements = - options.inner_iteration_ordering->group_to_elements(); - - // Iterate over each group and verify that it is an independent - // set. - map<int, set<double*> >::const_iterator it = group_to_elements.begin(); - for ( ; it != group_to_elements.end(); ++it) { - if (!IsParameterBlockSetIndependent(it->second, - program.residual_blocks())) { - summary->message = - StringPrintf("The user-provided " - "parameter_blocks_for_inner_iterations does not " - "form an independent set. Group Id: %d", it->first); - return NULL; - } - } ordering_ptr = options.inner_iteration_ordering.get(); + if (!CoordinateDescentMinimizer::IsOrderingValid(program, + *ordering_ptr, + &summary->message)) { + return NULL; + } } if (!inner_iteration_minimizer->Init(program,