Use Program::RemoveFixedBlocks.
And get rid of the code and tests related to
SolverImpl::RemovedFixedBlocksFromProgram.
Change-Id: Iccf6501dfe93db737f5a2265bbab0021712be92f
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc
index 30d5c16..9b39156 100644
--- a/internal/ceres/solver_impl.cc
+++ b/internal/ceres/solver_impl.cc
@@ -741,107 +741,6 @@
return true;
}
-
-// Strips varying parameters and residuals, maintaining order, and updating
-// orderings.
-bool SolverImpl::RemoveFixedBlocksFromProgram(
- Program* program,
- ParameterBlockOrdering* linear_solver_ordering,
- ParameterBlockOrdering* inner_iteration_ordering,
- double* fixed_cost,
- string* error) {
- scoped_array<double> residual_block_evaluate_scratch;
- if (fixed_cost != NULL) {
- residual_block_evaluate_scratch.reset(
- new double[program->MaxScratchDoublesNeededForEvaluate()]);
- *fixed_cost = 0.0;
- }
-
- vector<ParameterBlock*>* parameter_blocks =
- program->mutable_parameter_blocks();
- vector<ResidualBlock*>* residual_blocks =
- program->mutable_residual_blocks();
-
- // Mark all the parameters as unused. Abuse the index member of the
- // parameter blocks for the marking.
- for (int i = 0; i < parameter_blocks->size(); ++i) {
- (*parameter_blocks)[i]->set_index(-1);
- }
-
- // Filter out residual that have all-constant parameters, and mark all the
- // parameter blocks that appear in residuals.
- int num_active_residual_blocks = 0;
- for (int i = 0; i < residual_blocks->size(); ++i) {
- ResidualBlock* residual_block = (*residual_blocks)[i];
- int num_parameter_blocks = residual_block->NumParameterBlocks();
-
- // Determine if the residual block is fixed, and also mark varying
- // parameters that appear in the residual block.
- bool all_constant = true;
- for (int k = 0; k < num_parameter_blocks; k++) {
- ParameterBlock* parameter_block = residual_block->parameter_blocks()[k];
- if (!parameter_block->IsConstant()) {
- all_constant = false;
- parameter_block->set_index(1);
- }
- }
-
- if (!all_constant) {
- (*residual_blocks)[num_active_residual_blocks++] = residual_block;
- } else if (fixed_cost != NULL) {
- // The residual is constant and will be removed, so its cost is
- // added to the variable fixed_cost.
- double cost = 0.0;
- if (!residual_block->Evaluate(true,
- &cost,
- NULL,
- NULL,
- residual_block_evaluate_scratch.get())) {
- *error = StringPrintf("Evaluation of the residual %d failed during "
- "removal of fixed residual blocks.", i);
- return false;
- }
- *fixed_cost += cost;
- }
- }
- residual_blocks->resize(num_active_residual_blocks);
-
- // Filter out unused or fixed parameter blocks, and update the
- // linear_solver_ordering and the inner_iteration_ordering (if
- // present).
- int num_active_parameter_blocks = 0;
- for (int i = 0; i < parameter_blocks->size(); ++i) {
- ParameterBlock* parameter_block = (*parameter_blocks)[i];
- if (parameter_block->index() == -1) {
- // Parameter block is constant.
- if (linear_solver_ordering != NULL) {
- linear_solver_ordering->Remove(parameter_block->mutable_user_state());
- }
-
- // It is not necessary that the inner iteration ordering contain
- // this parameter block. But calling Remove is safe, as it will
- // just return false.
- if (inner_iteration_ordering != NULL) {
- inner_iteration_ordering->Remove(parameter_block->mutable_user_state());
- }
- continue;
- }
-
- (*parameter_blocks)[num_active_parameter_blocks++] = parameter_block;
- }
- parameter_blocks->resize(num_active_parameter_blocks);
-
- if (!(((program->NumResidualBlocks() == 0) &&
- (program->NumParameterBlocks() == 0)) ||
- ((program->NumResidualBlocks() != 0) &&
- (program->NumParameterBlocks() != 0)))) {
- *error = "Congratulations, you found a bug in Ceres. Please report it.";
- return false;
- }
-
- return true;
-}
-
Program* SolverImpl::CreateReducedProgram(Solver::Options* options,
ProblemImpl* problem_impl,
double* fixed_cost,
@@ -854,14 +753,18 @@
options->linear_solver_ordering.get();
const int min_group_id =
linear_solver_ordering->group_to_elements().begin()->first;
+ vector<double*> removed_parameter_blocks;
+ if (!transformed_program->RemoveFixedBlocks(&removed_parameter_blocks,
+ fixed_cost,
+ error)) {
+ return NULL;
+ }
+
+ linear_solver_ordering->Remove(removed_parameter_blocks);
ParameterBlockOrdering* inner_iteration_ordering =
options->inner_iteration_ordering.get();
- if (!RemoveFixedBlocksFromProgram(transformed_program.get(),
- linear_solver_ordering,
- inner_iteration_ordering,
- fixed_cost,
- error)) {
- return NULL;
+ if (inner_iteration_ordering != NULL) {
+ inner_iteration_ordering->Remove(removed_parameter_blocks);
}
VLOG(2) << "Reduced problem: "
diff --git a/internal/ceres/solver_impl_test.cc b/internal/ceres/solver_impl_test.cc
index 9e14d7e..c22ac49 100644
--- a/internal/ceres/solver_impl_test.cc
+++ b/internal/ceres/solver_impl_test.cc
@@ -64,7 +64,9 @@
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
- // Do nothing. This is never called.
+ for (int i = 0; i < kNumResiduals; ++i) {
+ residuals[i] = 0.0;
+ }
return true;
}
};
@@ -73,235 +75,6 @@
class BinaryCostFunction : public MockCostFunctionBase<2, 1, 1, 0> {};
class TernaryCostFunction : public MockCostFunctionBase<2, 1, 1, 1> {};
-TEST(SolverImpl, RemoveFixedBlocksNothingConstant) {
- ProblemImpl problem;
- double x;
- double y;
- double z;
-
- problem.AddParameterBlock(&x, 1);
- problem.AddParameterBlock(&y, 1);
- problem.AddParameterBlock(&z, 1);
- problem.AddResidualBlock(new UnaryCostFunction(), NULL, &x);
- problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y);
- problem.AddResidualBlock(new TernaryCostFunction(), NULL, &x, &y, &z);
-
- string message;
- {
- ParameterBlockOrdering linear_solver_ordering;
- linear_solver_ordering.AddElementToGroup(&x, 0);
- linear_solver_ordering.AddElementToGroup(&y, 0);
- linear_solver_ordering.AddElementToGroup(&z, 0);
-
- ParameterBlockOrdering inner_iteration_ordering;
- inner_iteration_ordering.AddElementToGroup(&x, 0);
- inner_iteration_ordering.AddElementToGroup(&y, 0);
- inner_iteration_ordering.AddElementToGroup(&z, 0);
-
- Program program(*problem.mutable_program());
- EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram(
- &program,
- &linear_solver_ordering,
- &inner_iteration_ordering,
- NULL,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 3);
- EXPECT_EQ(program.NumResidualBlocks(), 3);
- EXPECT_EQ(linear_solver_ordering.NumElements(), 3);
- EXPECT_EQ(inner_iteration_ordering.NumElements(), 3);
- }
-}
-
-TEST(SolverImpl, RemoveFixedBlocksAllParameterBlocksConstant) {
- ProblemImpl problem;
- double x;
-
- problem.AddParameterBlock(&x, 1);
- problem.AddResidualBlock(new UnaryCostFunction(), NULL, &x);
- problem.SetParameterBlockConstant(&x);
-
- ParameterBlockOrdering linear_solver_ordering;
- linear_solver_ordering.AddElementToGroup(&x, 0);
-
- ParameterBlockOrdering inner_iteration_ordering;
- inner_iteration_ordering.AddElementToGroup(&x, 0);
-
- Program program(problem.program());
- string message;
- EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram(
- &program,
- &linear_solver_ordering,
- &inner_iteration_ordering,
- NULL,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 0);
- EXPECT_EQ(program.NumResidualBlocks(), 0);
- EXPECT_EQ(linear_solver_ordering.NumElements(), 0);
- EXPECT_EQ(inner_iteration_ordering.NumElements(), 0);
-}
-
-TEST(SolverImpl, RemoveFixedBlocksNoResidualBlocks) {
- ProblemImpl problem;
- double x;
- double y;
- double z;
-
- problem.AddParameterBlock(&x, 1);
- problem.AddParameterBlock(&y, 1);
- problem.AddParameterBlock(&z, 1);
-
- ParameterBlockOrdering linear_solver_ordering;
- linear_solver_ordering.AddElementToGroup(&x, 0);
- linear_solver_ordering.AddElementToGroup(&y, 0);
- linear_solver_ordering.AddElementToGroup(&z, 0);
-
- ParameterBlockOrdering inner_iteration_ordering;
- inner_iteration_ordering.AddElementToGroup(&x, 0);
- inner_iteration_ordering.AddElementToGroup(&y, 0);
- inner_iteration_ordering.AddElementToGroup(&z, 0);
-
- Program program(problem.program());
- string message;
- EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram(
- &program,
- &linear_solver_ordering,
- &inner_iteration_ordering,
- NULL,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 0);
- EXPECT_EQ(program.NumResidualBlocks(), 0);
- EXPECT_EQ(linear_solver_ordering.NumElements(), 0);
- EXPECT_EQ(inner_iteration_ordering.NumElements(), 0);
-}
-
-TEST(SolverImpl, RemoveFixedBlocksOneParameterBlockConstant) {
- ProblemImpl problem;
- double x;
- double y;
- double z;
-
- problem.AddParameterBlock(&x, 1);
- problem.AddParameterBlock(&y, 1);
- problem.AddParameterBlock(&z, 1);
-
- ParameterBlockOrdering linear_solver_ordering;
- linear_solver_ordering.AddElementToGroup(&x, 0);
- linear_solver_ordering.AddElementToGroup(&y, 0);
- linear_solver_ordering.AddElementToGroup(&z, 0);
-
- ParameterBlockOrdering inner_iteration_ordering;
- inner_iteration_ordering.AddElementToGroup(&x, 0);
- inner_iteration_ordering.AddElementToGroup(&y, 0);
- inner_iteration_ordering.AddElementToGroup(&z, 0);
-
- problem.AddResidualBlock(new UnaryCostFunction(), NULL, &x);
- problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y);
- problem.SetParameterBlockConstant(&x);
-
-
- Program program(problem.program());
- string message;
- EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram(
- &program,
- &linear_solver_ordering,
- &inner_iteration_ordering,
- NULL,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 1);
- EXPECT_EQ(program.NumResidualBlocks(), 1);
- EXPECT_EQ(linear_solver_ordering.NumElements(), 1);
- EXPECT_EQ(inner_iteration_ordering.NumElements(), 1);
-}
-
-TEST(SolverImpl, RemoveFixedBlocksNumEliminateBlocks) {
- ProblemImpl problem;
- double x;
- double y;
- double z;
-
- problem.AddParameterBlock(&x, 1);
- problem.AddParameterBlock(&y, 1);
- problem.AddParameterBlock(&z, 1);
- problem.AddResidualBlock(new UnaryCostFunction(), NULL, &x);
- problem.AddResidualBlock(new TernaryCostFunction(), NULL, &x, &y, &z);
- problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y);
- problem.SetParameterBlockConstant(&x);
-
- ParameterBlockOrdering linear_solver_ordering;
- linear_solver_ordering.AddElementToGroup(&x, 0);
- linear_solver_ordering.AddElementToGroup(&y, 0);
- linear_solver_ordering.AddElementToGroup(&z, 1);
-
- ParameterBlockOrdering inner_iteration_ordering;
- inner_iteration_ordering.AddElementToGroup(&x, 0);
- inner_iteration_ordering.AddElementToGroup(&y, 0);
- inner_iteration_ordering.AddElementToGroup(&z, 1);
-
- Program program(problem.program());
- string message;
- EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram(
- &program,
- &linear_solver_ordering,
- &inner_iteration_ordering,
- NULL,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 2);
- EXPECT_EQ(program.NumResidualBlocks(), 2);
- EXPECT_EQ(linear_solver_ordering.NumElements(), 2);
- EXPECT_EQ(linear_solver_ordering.GroupId(&y), 0);
- EXPECT_EQ(linear_solver_ordering.GroupId(&z), 1);
- EXPECT_EQ(inner_iteration_ordering.NumElements(), 2);
- EXPECT_EQ(inner_iteration_ordering.GroupId(&y), 0);
- EXPECT_EQ(inner_iteration_ordering.GroupId(&z), 1);
-}
-
-TEST(SolverImpl, RemoveFixedBlocksFixedCost) {
- ProblemImpl problem;
- double x = 1.23;
- double y = 4.56;
- double z = 7.89;
-
- problem.AddParameterBlock(&x, 1);
- problem.AddParameterBlock(&y, 1);
- problem.AddParameterBlock(&z, 1);
- problem.AddResidualBlock(new UnaryIdentityCostFunction(), NULL, &x);
- problem.AddResidualBlock(new TernaryCostFunction(), NULL, &x, &y, &z);
- problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y);
- problem.SetParameterBlockConstant(&x);
-
- ParameterBlockOrdering linear_solver_ordering;
- linear_solver_ordering.AddElementToGroup(&x, 0);
- linear_solver_ordering.AddElementToGroup(&y, 0);
- linear_solver_ordering.AddElementToGroup(&z, 1);
-
- double fixed_cost = 0.0;
- Program program(problem.program());
-
- double expected_fixed_cost;
- ResidualBlock *expected_removed_block = program.residual_blocks()[0];
- scoped_array<double> scratch(
- new double[expected_removed_block->NumScratchDoublesForEvaluate()]);
- expected_removed_block->Evaluate(true,
- &expected_fixed_cost,
- NULL,
- NULL,
- scratch.get());
-
- string message;
- EXPECT_TRUE(SolverImpl::RemoveFixedBlocksFromProgram(
- &program,
- &linear_solver_ordering,
- NULL,
- &fixed_cost,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 2);
- EXPECT_EQ(program.NumResidualBlocks(), 2);
- EXPECT_EQ(linear_solver_ordering.NumElements(), 2);
- EXPECT_EQ(linear_solver_ordering.GroupId(&y), 0);
- EXPECT_EQ(linear_solver_ordering.GroupId(&z), 1);
- EXPECT_DOUBLE_EQ(fixed_cost, expected_fixed_cost);
-}
-
TEST(SolverImpl, ReorderResidualBlockNormalFunction) {
ProblemImpl problem;
double x;
@@ -393,8 +166,12 @@
// Create the reduced program. This should remove the fixed block "z",
// marking the index to -1 at the same time. x and y also get indices.
string message;
+ double fixed_cost;
scoped_ptr<Program> reduced_program(
- SolverImpl::CreateReducedProgram(&options, &problem, NULL, &message));
+ SolverImpl::CreateReducedProgram(&options,
+ &problem,
+ &fixed_cost,
+ &message));
const vector<ResidualBlock*>& residual_blocks =
problem.program().residual_blocks();
@@ -460,8 +237,12 @@
options.linear_solver_ordering.reset(linear_solver_ordering);
string message;
+ double fixed_cost;
scoped_ptr<Program> reduced_program(
- SolverImpl::CreateReducedProgram(&options, &problem, NULL, &message));
+ SolverImpl::CreateReducedProgram(&options,
+ &problem,
+ &fixed_cost,
+ &message));
const vector<ResidualBlock*>& residual_blocks =
reduced_program->residual_blocks();