mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-29 16:40:38 +08:00
Respect bounds when using Solver::Options::check_gradients
When Solver::Options::check_gradients is true, Ceres internally creates a new ProblemImpl object which wraps each CostFunction in the user's problem with a GradientCheckingCostFunction. Doing this also requires creating new ParameterBlock objects, and when support for upper and lower bounds was added to Ceres, CreateGradientCheckingProblemImpl should also have been updated to create a problem with the same parameter bounds. As a result, if check_gradients is enabled for a bounded problem, it constructs an unconstrained problem and solves it. This CL fixes this, by introducing Problem::GetParameterLowerBound, and Problem::GetParameterUpperBound and using them to create a bounded problem when checking gradients. Thanks to @pbeeson for not only reporting this problem, but also providing a small standalone reproduction which made debugging this possible. https://github.com/ceres-solver/ceres-solver/issues/379 Change-Id: Id18eb858a7009bf4fa452a21b925922d13f3249f
This commit is contained in:
@@ -411,5 +411,38 @@ TEST(GradientCheckingProblemImpl, ProblemDimensionsMatch) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(GradientCheckingProblemImpl, ConstrainedProblemBoundsArePropagated) {
|
||||
// Parameter blocks with arbitrarily chosen initial values.
|
||||
double x[] = {1.0, 2.0, 3.0};
|
||||
ProblemImpl problem_impl;
|
||||
problem_impl.AddParameterBlock(x, 3);
|
||||
problem_impl.AddResidualBlock(new UnaryCostFunction(2, 3), NULL, x);
|
||||
problem_impl.SetParameterLowerBound(x,0,0.9);
|
||||
problem_impl.SetParameterUpperBound(x,1,2.5);
|
||||
|
||||
GradientCheckingIterationCallback callback;
|
||||
std::unique_ptr<ProblemImpl> gradient_checking_problem_impl(
|
||||
CreateGradientCheckingProblemImpl(&problem_impl, 1.0, 1.0, &callback));
|
||||
|
||||
// The dimensions of the two problems match.
|
||||
EXPECT_EQ(problem_impl.NumParameterBlocks(),
|
||||
gradient_checking_problem_impl->NumParameterBlocks());
|
||||
EXPECT_EQ(problem_impl.NumResidualBlocks(),
|
||||
gradient_checking_problem_impl->NumResidualBlocks());
|
||||
|
||||
EXPECT_EQ(problem_impl.NumParameters(),
|
||||
gradient_checking_problem_impl->NumParameters());
|
||||
EXPECT_EQ(problem_impl.NumResiduals(),
|
||||
gradient_checking_problem_impl->NumResiduals());
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
EXPECT_EQ(problem_impl.GetParameterLowerBound(x, i),
|
||||
gradient_checking_problem_impl->GetParameterLowerBound(x, i));
|
||||
EXPECT_EQ(problem_impl.GetParameterUpperBound(x, i),
|
||||
gradient_checking_problem_impl->GetParameterUpperBound(x, i));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
Reference in New Issue
Block a user