Program::RemoveFixedBlocks -> Program::CreateReducedProgram.
CreateReducedProgram is a safer API, reduces the possibility of
memory leaks and produces valid programs.
Change-Id: I094d53d207fced970a4d9ea0b66cdb09ce5f0657
diff --git a/internal/ceres/program.cc b/internal/ceres/program.cc
index 3a88b13..1d0a157 100644
--- a/internal/ceres/program.cc
+++ b/internal/ceres/program.cc
@@ -261,6 +261,24 @@
return true;
}
+Program* Program::CreateReducedProgram(vector<double*>* removed_parameter_blocks,
+ double* fixed_cost,
+ string* error) const {
+ CHECK_NOTNULL(removed_parameter_blocks);
+ CHECK_NOTNULL(fixed_cost);
+ CHECK_NOTNULL(error);
+
+ scoped_ptr<Program> reduced_program(new Program(*this));
+ if (!reduced_program->RemoveFixedBlocks(removed_parameter_blocks,
+ fixed_cost,
+ error)) {
+ return NULL;
+ }
+
+ reduced_program->SetParameterOffsetsAndIndex();
+ return reduced_program.release();
+}
+
bool Program::RemoveFixedBlocks(vector<double*>* removed_parameter_blocks,
double* fixed_cost,
string* error) {
diff --git a/internal/ceres/program.h b/internal/ceres/program.h
index 6b9190d..c7b22c4 100644
--- a/internal/ceres/program.h
+++ b/internal/ceres/program.h
@@ -129,16 +129,22 @@
// Caller owns the result.
TripletSparseMatrix* CreateJacobianBlockSparsityTranspose() const;
- // Removes constant parameter blocks and residual blocks with no
- // varying parameter blocks while preserving order.
+ // Create a copy of this program and removes constant parameter
+ // blocks and residual blocks with no varying parameter blocks while
+ // preserving their relative order.
//
- // WARNING: It is the caller's responsibility to track ownership of
- // the parameter and residual blocks removed from the
- // program. Generally speaking this method should only be called on
- // a copy of an existing program.
- bool RemoveFixedBlocks(vector<double*>* removed_parameter_blocks,
- double* fixed_cost,
- string* message);
+ // removed_parameter_blocks on exit will contain the list of
+ // parameter blocks that were removed.
+ //
+ // fixed_cost will be equal to the sum of the costs of the residual
+ // blocks that were removed.
+ //
+ // If there was a problem, then the function will return a NULL
+ // pointer and error will contain a human readable description of
+ // the problem.
+ Program* CreateReducedProgram(vector<double*>* removed_parameter_blocks,
+ double* fixed_cost,
+ string* error) const;
// See problem.h for what these do.
int NumParameterBlocks() const;
@@ -157,6 +163,21 @@
string ToString() const;
private:
+ // Remove constant parameter blocks and residual blocks with no
+ // varying parameter blocks while preserving their relative order.
+ //
+ // removed_parameter_blocks on exit will contain the list of
+ // parameter blocks that were removed.
+ //
+ // fixed_cost will be equal to the sum of the costs of the residual
+ // blocks that were removed.
+ //
+ // If there was a problem, then the function will return false and
+ // error will contain a human readable description of the problem.
+ bool RemoveFixedBlocks(vector<double*>* removed_parameter_blocks,
+ double* fixed_cost,
+ string* message);
+
// The Program does not own the ParameterBlock or ResidualBlock objects.
vector<ParameterBlock*> parameter_blocks_;
vector<ResidualBlock*> residual_blocks_;
diff --git a/internal/ceres/program_test.cc b/internal/ceres/program_test.cc
index f273872..10bfa12 100644
--- a/internal/ceres/program_test.cc
+++ b/internal/ceres/program_test.cc
@@ -88,15 +88,18 @@
problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y);
problem.AddResidualBlock(new TernaryCostFunction(), NULL, &x, &y, &z);
- Program program(problem.program());
vector<double*> removed_parameter_blocks;
double fixed_cost = 0.0;
string message;
- EXPECT_TRUE(program.RemoveFixedBlocks(&removed_parameter_blocks,
- &fixed_cost,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 3);
- EXPECT_EQ(program.NumResidualBlocks(), 3);
+ scoped_ptr<Program> reduced_program(
+ CHECK_NOTNULL(problem
+ .program()
+ .CreateReducedProgram(&removed_parameter_blocks,
+ &fixed_cost,
+ &message)));
+
+ EXPECT_EQ(reduced_program->NumParameterBlocks(), 3);
+ EXPECT_EQ(reduced_program->NumResidualBlocks(), 3);
EXPECT_EQ(removed_parameter_blocks.size(), 0);
EXPECT_EQ(fixed_cost, 0.0);
}
@@ -109,15 +112,17 @@
problem.AddResidualBlock(new UnaryCostFunction(), NULL, &x);
problem.SetParameterBlockConstant(&x);
- Program program(problem.program());
vector<double*> removed_parameter_blocks;
double fixed_cost = 0.0;
string message;
- EXPECT_TRUE(program.RemoveFixedBlocks(&removed_parameter_blocks,
- &fixed_cost,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 0);
- EXPECT_EQ(program.NumResidualBlocks(), 0);
+ scoped_ptr<Program> reduced_program(
+ CHECK_NOTNULL(problem
+ .program()
+ .CreateReducedProgram(&removed_parameter_blocks,
+ &fixed_cost,
+ &message)));
+ EXPECT_EQ(reduced_program->NumParameterBlocks(), 0);
+ EXPECT_EQ(reduced_program->NumResidualBlocks(), 0);
EXPECT_EQ(removed_parameter_blocks.size(), 1);
EXPECT_EQ(removed_parameter_blocks[0], &x);
EXPECT_EQ(fixed_cost, 9.0);
@@ -134,15 +139,17 @@
problem.AddParameterBlock(&y, 1);
problem.AddParameterBlock(&z, 1);
- Program program(problem.program());
vector<double*> removed_parameter_blocks;
double fixed_cost = 0.0;
string message;
- EXPECT_TRUE(program.RemoveFixedBlocks(&removed_parameter_blocks,
- &fixed_cost,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 0);
- EXPECT_EQ(program.NumResidualBlocks(), 0);
+ scoped_ptr<Program> reduced_program(
+ CHECK_NOTNULL(problem
+ .program()
+ .CreateReducedProgram(&removed_parameter_blocks,
+ &fixed_cost,
+ &message)));
+ EXPECT_EQ(reduced_program->NumParameterBlocks(), 0);
+ EXPECT_EQ(reduced_program->NumResidualBlocks(), 0);
EXPECT_EQ(removed_parameter_blocks.size(), 3);
EXPECT_EQ(fixed_cost, 0.0);
}
@@ -161,15 +168,17 @@
problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y);
problem.SetParameterBlockConstant(&x);
- Program program(problem.program());
vector<double*> removed_parameter_blocks;
double fixed_cost = 0.0;
string message;
- EXPECT_TRUE(program.RemoveFixedBlocks(&removed_parameter_blocks,
- &fixed_cost,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 1);
- EXPECT_EQ(program.NumResidualBlocks(), 1);
+ scoped_ptr<Program> reduced_program(
+ CHECK_NOTNULL(problem
+ .program()
+ .CreateReducedProgram(&removed_parameter_blocks,
+ &fixed_cost,
+ &message)));
+ EXPECT_EQ(reduced_program->NumParameterBlocks(), 1);
+ EXPECT_EQ(reduced_program->NumResidualBlocks(), 1);
}
TEST(Program, RemoveFixedBlocksNumEliminateBlocks) {
@@ -186,15 +195,17 @@
problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y);
problem.SetParameterBlockConstant(&x);
- Program program(problem.program());
vector<double*> removed_parameter_blocks;
double fixed_cost = 0.0;
string message;
- EXPECT_TRUE(program.RemoveFixedBlocks(&removed_parameter_blocks,
- &fixed_cost,
- &message));
- EXPECT_EQ(program.NumParameterBlocks(), 2);
- EXPECT_EQ(program.NumResidualBlocks(), 2);
+ scoped_ptr<Program> reduced_program(
+ CHECK_NOTNULL(problem
+ .program()
+ .CreateReducedProgram(&removed_parameter_blocks,
+ &fixed_cost,
+ &message)));
+ EXPECT_EQ(reduced_program->NumParameterBlocks(), 2);
+ EXPECT_EQ(reduced_program->NumResidualBlocks(), 2);
}
TEST(Program, RemoveFixedBlocksFixedCost) {
@@ -211,27 +222,29 @@
problem.AddResidualBlock(new BinaryCostFunction(), NULL, &x, &y);
problem.SetParameterBlockConstant(&x);
- Program program(problem.program());
-
- double expected_fixed_cost;
- ResidualBlock *expected_removed_block = program.residual_blocks()[0];
+ ResidualBlock *expected_removed_block = problem.program().residual_blocks()[0];
scoped_array<double> scratch(
new double[expected_removed_block->NumScratchDoublesForEvaluate()]);
+ double expected_fixed_cost;
expected_removed_block->Evaluate(true,
&expected_fixed_cost,
NULL,
NULL,
scratch.get());
+
vector<double*> removed_parameter_blocks;
double fixed_cost = 0.0;
string message;
- EXPECT_TRUE(program.RemoveFixedBlocks(&removed_parameter_blocks,
- &fixed_cost,
- &message));
+ scoped_ptr<Program> reduced_program(
+ CHECK_NOTNULL(problem
+ .program()
+ .CreateReducedProgram(&removed_parameter_blocks,
+ &fixed_cost,
+ &message)));
- EXPECT_EQ(program.NumParameterBlocks(), 2);
- EXPECT_EQ(program.NumResidualBlocks(), 2);
+ EXPECT_EQ(reduced_program->NumParameterBlocks(), 2);
+ EXPECT_EQ(reduced_program->NumResidualBlocks(), 2);
EXPECT_DOUBLE_EQ(fixed_cost, expected_fixed_cost);
}
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc
index 11398b1..dfdfecb 100644
--- a/internal/ceres/solver_impl.cc
+++ b/internal/ceres/solver_impl.cc
@@ -664,42 +664,44 @@
string* error) {
CHECK_NOTNULL(options->linear_solver_ordering.get());
Program* original_program = problem_impl->mutable_program();
- scoped_ptr<Program> transformed_program(new Program(*original_program));
+
+ vector<double*> removed_parameter_blocks;
+ scoped_ptr<Program> reduced_program(
+ original_program->CreateReducedProgram(&removed_parameter_blocks,
+ fixed_cost,
+ error));
+ if (reduced_program.get() == NULL) {
+ return NULL;
+ }
+
+ VLOG(2) << "Reduced problem: "
+ << reduced_program->NumParameterBlocks()
+ << " parameter blocks, "
+ << reduced_program->NumParameters()
+ << " parameters, "
+ << reduced_program->NumResidualBlocks()
+ << " residual blocks, "
+ << reduced_program->NumResiduals()
+ << " residuals.";
+
+ if (reduced_program->NumParameterBlocks() == 0) {
+ LOG(WARNING) << "No varying parameter blocks to optimize; "
+ << "bailing early.";
+ return reduced_program.release();
+ }
ParameterBlockOrdering* linear_solver_ordering =
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 (inner_iteration_ordering != NULL) {
inner_iteration_ordering->Remove(removed_parameter_blocks);
}
- VLOG(2) << "Reduced problem: "
- << transformed_program->NumParameterBlocks()
- << " parameter blocks, "
- << transformed_program->NumParameters()
- << " parameters, "
- << transformed_program->NumResidualBlocks()
- << " residual blocks, "
- << transformed_program->NumResiduals()
- << " residuals.";
-
- if (transformed_program->NumParameterBlocks() == 0) {
- LOG(WARNING) << "No varying parameter blocks to optimize; "
- << "bailing early.";
- return transformed_program.release();
- }
-
if (IsSchurType(options->linear_solver_type) &&
linear_solver_ordering->GroupSize(min_group_id) == 0) {
// If the user requested the use of a Schur type solver, and
@@ -730,11 +732,11 @@
options->sparse_linear_algebra_library_type,
problem_impl->parameter_map(),
linear_solver_ordering,
- transformed_program.get(),
+ reduced_program.get(),
error)) {
return NULL;
}
- return transformed_program.release();
+ return reduced_program.release();
}
if (options->linear_solver_type == SPARSE_NORMAL_CHOLESKY &&
@@ -742,16 +744,16 @@
if (!ReorderProgramForSparseNormalCholesky(
options->sparse_linear_algebra_library_type,
linear_solver_ordering,
- transformed_program.get(),
+ reduced_program.get(),
error)) {
return NULL;
}
- return transformed_program.release();
+ return reduced_program.release();
}
- transformed_program->SetParameterOffsetsAndIndex();
- return transformed_program.release();
+ reduced_program->SetParameterOffsetsAndIndex();
+ return reduced_program.release();
}
LinearSolver* SolverImpl::CreateLinearSolver(Solver::Options* options,