Schur ordering was operating on the original program. Thanks to Ricardo Martin for reporting this. Change-Id: Iacf44f672287e4d76633878c7051694a39b3056f
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index 062577e..03fe921 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -627,7 +627,7 @@ // maximal independent set. if (original_num_groups == 1 && IsSchurType(options->linear_solver_type)) { vector<ParameterBlock*> schur_ordering; - const int num_eliminate_blocks = ComputeSchurOrdering(*original_program, + const int num_eliminate_blocks = ComputeSchurOrdering(*transformed_program, &schur_ordering); CHECK_EQ(schur_ordering.size(), transformed_program->NumParameterBlocks()) << "Congratulations, you found a Ceres bug! Please report this error "
diff --git a/internal/ceres/solver_impl_test.cc b/internal/ceres/solver_impl_test.cc index 5f4a82c..9b01766 100644 --- a/internal/ceres/solver_impl_test.cc +++ b/internal/ceres/solver_impl_test.cc
@@ -386,6 +386,63 @@ } } +TEST(SolverImpl, AutomaticSchurReorderingRespectsConstantBlocks) { + ProblemImpl problem; + double x; + double y; + double z; + + problem.AddParameterBlock(&x, 1); + problem.AddParameterBlock(&y, 1); + problem.AddParameterBlock(&z, 1); + + // Set one parameter block constant. + problem.SetParameterBlockConstant(&z); + + problem.AddResidualBlock(new UnaryCostFunction(), NULL, &x); + problem.AddResidualBlock(new BinaryCostFunction(), NULL, &z, &x); + problem.AddResidualBlock(new BinaryCostFunction(), NULL, &z, &y); + problem.AddResidualBlock(new BinaryCostFunction(), NULL, &z, &y); + problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &z); + problem.AddResidualBlock(new BinaryCostFunction(), NULL, &z, &y); + problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &z); + problem.AddResidualBlock(new UnaryCostFunction(), NULL, &y); + problem.AddResidualBlock(new UnaryCostFunction(), NULL, &z); + + ParameterBlockOrdering* ordering = new ParameterBlockOrdering; + ordering->AddElementToGroup(&x, 0); + ordering->AddElementToGroup(&z, 0); + ordering->AddElementToGroup(&y, 0); + + Solver::Options options; + options.linear_solver_type = DENSE_SCHUR; + options.ordering = ordering; + + string error; + scoped_ptr<Program> reduced_program( + SolverImpl::CreateReducedProgram(&options, &problem, NULL, &error)); + + const vector<ResidualBlock*>& residual_blocks = + reduced_program->residual_blocks(); + const vector<ParameterBlock*>& parameter_blocks = + reduced_program->parameter_blocks(); + + const vector<ResidualBlock*>& original_residual_blocks = + problem.program().residual_blocks(); + + EXPECT_EQ(residual_blocks.size(), 8); + EXPECT_EQ(reduced_program->parameter_blocks().size(), 2); + + // Verify that right parmeter block and the residual blocks have + // been removed. + for (int i = 0; i < 8; ++i) { + EXPECT_NE(residual_blocks[i], original_residual_blocks.back()); + } + for (int i = 0; i < 2; ++i) { + EXPECT_NE(parameter_blocks[i]->mutable_user_state(), &z); + } +} + TEST(SolverImpl, ApplyUserOrderingOrderingTooSmall) { ProblemImpl problem; double x;