mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-29 16:40:38 +08:00
Fix an exact equality test causing breakage in gradient_checker_test.
Also clang-format the file to fix some accumulated cruft. Change-Id: Icf41e3f864a4fe925426477893602b50ff2131f4
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2015 Google Inc. All rights reserved.
|
||||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
// http://ceres-solver.org/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@@ -58,7 +58,7 @@ using std::vector;
|
||||
// version, they are both block vectors, of course.
|
||||
class GoodTestTerm : public CostFunction {
|
||||
public:
|
||||
GoodTestTerm(int arity, int const *dim) : arity_(arity), return_value_(true) {
|
||||
GoodTestTerm(int arity, int const* dim) : arity_(arity), return_value_(true) {
|
||||
// Make 'arity' random vectors.
|
||||
a_.resize(arity_);
|
||||
for (int j = 0; j < arity_; ++j) {
|
||||
@@ -98,7 +98,7 @@ class GoodTestTerm : public CostFunction {
|
||||
if (jacobians[j]) {
|
||||
for (int u = 0; u < parameter_block_sizes()[j]; ++u) {
|
||||
// See comments before class.
|
||||
jacobians[j][u] = - f * a_[j][u];
|
||||
jacobians[j][u] = -f * a_[j][u];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,9 +107,7 @@ class GoodTestTerm : public CostFunction {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetReturnValue(bool return_value) {
|
||||
return_value_ = return_value;
|
||||
}
|
||||
void SetReturnValue(bool return_value) { return_value_ = return_value; }
|
||||
|
||||
private:
|
||||
int arity_;
|
||||
@@ -119,7 +117,7 @@ class GoodTestTerm : public CostFunction {
|
||||
|
||||
class BadTestTerm : public CostFunction {
|
||||
public:
|
||||
BadTestTerm(int arity, int const *dim) : arity_(arity) {
|
||||
BadTestTerm(int arity, int const* dim) : arity_(arity) {
|
||||
// Make 'arity' random vectors.
|
||||
a_.resize(arity_);
|
||||
for (int j = 0; j < arity_; ++j) {
|
||||
@@ -156,7 +154,7 @@ class BadTestTerm : public CostFunction {
|
||||
if (jacobians[j]) {
|
||||
for (int u = 0; u < parameter_block_sizes()[j]; ++u) {
|
||||
// See comments before class.
|
||||
jacobians[j][u] = - f * a_[j][u] + 0.001;
|
||||
jacobians[j][u] = -f * a_[j][u] + 0.001;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,10 +170,10 @@ class BadTestTerm : public CostFunction {
|
||||
|
||||
const double kTolerance = 1e-6;
|
||||
|
||||
void CheckDimensions(
|
||||
const GradientChecker::ProbeResults& results,
|
||||
const std::vector<int>& parameter_sizes,
|
||||
const std::vector<int>& local_parameter_sizes, int residual_size) {
|
||||
void CheckDimensions(const GradientChecker::ProbeResults& results,
|
||||
const std::vector<int>& parameter_sizes,
|
||||
const std::vector<int>& local_parameter_sizes,
|
||||
int residual_size) {
|
||||
CHECK_EQ(parameter_sizes.size(), local_parameter_sizes.size());
|
||||
int num_parameters = parameter_sizes.size();
|
||||
ASSERT_EQ(residual_size, results.residuals.size());
|
||||
@@ -187,7 +185,8 @@ void CheckDimensions(
|
||||
EXPECT_EQ(residual_size, results.local_jacobians.at(i).rows());
|
||||
EXPECT_EQ(local_parameter_sizes[i], results.local_jacobians.at(i).cols());
|
||||
EXPECT_EQ(residual_size, results.local_numeric_jacobians.at(i).rows());
|
||||
EXPECT_EQ(local_parameter_sizes[i], results.local_numeric_jacobians.at(i).cols());
|
||||
EXPECT_EQ(local_parameter_sizes[i],
|
||||
results.local_numeric_jacobians.at(i).cols());
|
||||
EXPECT_EQ(residual_size, results.jacobians.at(i).rows());
|
||||
EXPECT_EQ(parameter_sizes[i], results.jacobians.at(i).cols());
|
||||
EXPECT_EQ(residual_size, results.numeric_jacobians.at(i).rows());
|
||||
@@ -221,9 +220,9 @@ TEST(GradientChecker, SmokeTest) {
|
||||
GoodTestTerm good_term(num_parameters, parameter_sizes.data());
|
||||
GradientChecker good_gradient_checker(&good_term, NULL, numeric_diff_options);
|
||||
EXPECT_TRUE(good_gradient_checker.Probe(parameters.get(), kTolerance, NULL));
|
||||
EXPECT_TRUE(good_gradient_checker.Probe(parameters.get(), kTolerance,
|
||||
&results))
|
||||
<< results.error_log;
|
||||
EXPECT_TRUE(
|
||||
good_gradient_checker.Probe(parameters.get(), kTolerance, &results))
|
||||
<< results.error_log;
|
||||
|
||||
// Check that results contain sensible data.
|
||||
ASSERT_EQ(results.return_value, true);
|
||||
@@ -235,9 +234,9 @@ TEST(GradientChecker, SmokeTest) {
|
||||
// Test that if the cost function return false, Probe should return false.
|
||||
good_term.SetReturnValue(false);
|
||||
EXPECT_FALSE(good_gradient_checker.Probe(parameters.get(), kTolerance, NULL));
|
||||
EXPECT_FALSE(good_gradient_checker.Probe(parameters.get(), kTolerance,
|
||||
&results))
|
||||
<< results.error_log;
|
||||
EXPECT_FALSE(
|
||||
good_gradient_checker.Probe(parameters.get(), kTolerance, &results))
|
||||
<< results.error_log;
|
||||
|
||||
// Check that results contain sensible data.
|
||||
ASSERT_EQ(results.return_value, false);
|
||||
@@ -254,8 +253,8 @@ TEST(GradientChecker, SmokeTest) {
|
||||
BadTestTerm bad_term(num_parameters, parameter_sizes.data());
|
||||
GradientChecker bad_gradient_checker(&bad_term, NULL, numeric_diff_options);
|
||||
EXPECT_FALSE(bad_gradient_checker.Probe(parameters.get(), kTolerance, NULL));
|
||||
EXPECT_FALSE(bad_gradient_checker.Probe(parameters.get(), kTolerance,
|
||||
&results));
|
||||
EXPECT_FALSE(
|
||||
bad_gradient_checker.Probe(parameters.get(), kTolerance, &results));
|
||||
|
||||
// Check that results contain sensible data.
|
||||
ASSERT_EQ(results.return_value, true);
|
||||
@@ -279,7 +278,6 @@ TEST(GradientChecker, SmokeTest) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper cost function that multiplies the parameters by the given jacobians
|
||||
* and adds a constant offset.
|
||||
@@ -291,7 +289,8 @@ class LinearCostFunction : public CostFunction {
|
||||
set_num_residuals(residuals_offset_.size());
|
||||
}
|
||||
|
||||
virtual bool Evaluate(double const* const* parameter_ptrs, double* residuals_ptr,
|
||||
virtual bool Evaluate(double const* const* parameter_ptrs,
|
||||
double* residuals_ptr,
|
||||
double** residual_J_params) const {
|
||||
CHECK_GE(residual_J_params_.size(), 0.0);
|
||||
VectorRef residuals(residuals_ptr, residual_J_params_[0].rows());
|
||||
@@ -308,8 +307,8 @@ class LinearCostFunction : public CostFunction {
|
||||
// Return Jacobian.
|
||||
if (residual_J_params != NULL && residual_J_params[i] != NULL) {
|
||||
Eigen::Map<Matrix> residual_J_param_out(residual_J_params[i],
|
||||
residual_J_param.rows(),
|
||||
residual_J_param.cols());
|
||||
residual_J_param.rows(),
|
||||
residual_J_param.cols());
|
||||
if (jacobian_offsets_.count(i) != 0) {
|
||||
residual_J_param_out = residual_J_param + jacobian_offsets_.at(i);
|
||||
} else {
|
||||
@@ -414,8 +413,8 @@ TEST(GradientChecker, TestCorrectnessWithLocalParameterizations) {
|
||||
|
||||
Matrix residual_expected = residual_offset + j0 * param0 + j1 * param1;
|
||||
|
||||
EXPECT_TRUE(j1_out == j0);
|
||||
EXPECT_TRUE(j2_out == j1);
|
||||
ExpectMatricesClose(j1_out, j0, std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(j2_out, j1, std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(residual, residual_expected, kTolerance);
|
||||
|
||||
// Create local parameterization.
|
||||
@@ -433,7 +432,9 @@ TEST(GradientChecker, TestCorrectnessWithLocalParameterizations) {
|
||||
|
||||
Eigen::Matrix<double, 3, 2, Eigen::RowMajor> global_J_local_out;
|
||||
parameterization.ComputeJacobian(x.data(), global_J_local_out.data());
|
||||
EXPECT_TRUE(global_J_local_out == global_J_local);
|
||||
ExpectMatricesClose(global_J_local_out,
|
||||
global_J_local,
|
||||
std::numeric_limits<double>::epsilon());
|
||||
|
||||
Eigen::Vector3d x_plus_delta;
|
||||
parameterization.Plus(x.data(), delta.data(), x_plus_delta.data());
|
||||
@@ -446,8 +447,8 @@ TEST(GradientChecker, TestCorrectnessWithLocalParameterizations) {
|
||||
parameterizations[1] = NULL;
|
||||
NumericDiffOptions numeric_diff_options;
|
||||
GradientChecker::ProbeResults results;
|
||||
GradientChecker gradient_checker(&cost_function, ¶meterizations,
|
||||
numeric_diff_options);
|
||||
GradientChecker gradient_checker(
|
||||
&cost_function, ¶meterizations, numeric_diff_options);
|
||||
|
||||
Problem::Options problem_options;
|
||||
problem_options.cost_function_ownership = DO_NOT_TAKE_OWNERSHIP;
|
||||
@@ -457,8 +458,8 @@ TEST(GradientChecker, TestCorrectnessWithLocalParameterizations) {
|
||||
Eigen::Vector2d param1_solver;
|
||||
problem.AddParameterBlock(param0_solver.data(), 3, ¶meterization);
|
||||
problem.AddParameterBlock(param1_solver.data(), 2);
|
||||
problem.AddResidualBlock(&cost_function, NULL, param0_solver.data(),
|
||||
param1_solver.data());
|
||||
problem.AddResidualBlock(
|
||||
&cost_function, NULL, param0_solver.data(), param1_solver.data());
|
||||
Solver::Options solver_options;
|
||||
solver_options.check_gradients = true;
|
||||
solver_options.initial_trust_region_radius = 1e10;
|
||||
@@ -468,20 +469,25 @@ TEST(GradientChecker, TestCorrectnessWithLocalParameterizations) {
|
||||
// First test case: everything is correct.
|
||||
EXPECT_TRUE(gradient_checker.Probe(parameters.data(), kTolerance, NULL));
|
||||
EXPECT_TRUE(gradient_checker.Probe(parameters.data(), kTolerance, &results))
|
||||
<< results.error_log;
|
||||
<< results.error_log;
|
||||
|
||||
// Check that results contain correct data.
|
||||
ASSERT_EQ(results.return_value, true);
|
||||
ASSERT_TRUE(results.residuals == residual);
|
||||
ExpectMatricesClose(
|
||||
results.residuals, residual, std::numeric_limits<double>::epsilon());
|
||||
CheckDimensions(results, parameter_sizes, local_parameter_sizes, 3);
|
||||
ExpectMatricesClose(results.local_jacobians.at(0), j0 * global_J_local,
|
||||
kTolerance);
|
||||
EXPECT_TRUE(results.local_jacobians.at(1) == j1);
|
||||
ExpectMatricesClose(results.local_numeric_jacobians.at(0),
|
||||
j0 * global_J_local, kTolerance);
|
||||
ExpectMatricesClose(
|
||||
results.local_jacobians.at(0), j0 * global_J_local, kTolerance);
|
||||
ExpectMatricesClose(results.local_jacobians.at(1),
|
||||
j1,
|
||||
std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(
|
||||
results.local_numeric_jacobians.at(0), j0 * global_J_local, kTolerance);
|
||||
ExpectMatricesClose(results.local_numeric_jacobians.at(1), j1, kTolerance);
|
||||
EXPECT_TRUE(results.jacobians.at(0) == j0);
|
||||
EXPECT_TRUE(results.jacobians.at(1) == j1);
|
||||
ExpectMatricesClose(
|
||||
results.jacobians.at(0), j0, std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(
|
||||
results.jacobians.at(1), j1, std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(results.numeric_jacobians.at(0), j0, kTolerance);
|
||||
ExpectMatricesClose(results.numeric_jacobians.at(1), j1, kTolerance);
|
||||
EXPECT_GE(results.maximum_relative_error, 0.0);
|
||||
@@ -502,22 +508,27 @@ TEST(GradientChecker, TestCorrectnessWithLocalParameterizations) {
|
||||
cost_function.SetJacobianOffset(0, j0_offset);
|
||||
EXPECT_FALSE(gradient_checker.Probe(parameters.data(), kTolerance, NULL));
|
||||
EXPECT_FALSE(gradient_checker.Probe(parameters.data(), kTolerance, &results))
|
||||
<< results.error_log;
|
||||
<< results.error_log;
|
||||
|
||||
// Check that results contain correct data.
|
||||
ASSERT_EQ(results.return_value, true);
|
||||
ASSERT_TRUE(results.residuals == residual);
|
||||
ExpectMatricesClose(
|
||||
results.residuals, residual, std::numeric_limits<double>::epsilon());
|
||||
CheckDimensions(results, parameter_sizes, local_parameter_sizes, 3);
|
||||
ASSERT_EQ(results.local_jacobians.size(), 2);
|
||||
ASSERT_EQ(results.local_numeric_jacobians.size(), 2);
|
||||
ExpectMatricesClose(results.local_jacobians.at(0),
|
||||
(j0 + j0_offset) * global_J_local, kTolerance);
|
||||
EXPECT_TRUE(results.local_jacobians.at(1) == j1);
|
||||
ExpectMatricesClose(results.local_numeric_jacobians.at(0),
|
||||
j0 * global_J_local, kTolerance);
|
||||
(j0 + j0_offset) * global_J_local,
|
||||
kTolerance);
|
||||
ExpectMatricesClose(results.local_jacobians.at(1),
|
||||
j1,
|
||||
std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(
|
||||
results.local_numeric_jacobians.at(0), j0 * global_J_local, kTolerance);
|
||||
ExpectMatricesClose(results.local_numeric_jacobians.at(1), j1, kTolerance);
|
||||
ExpectMatricesClose(results.jacobians.at(0), j0 + j0_offset, kTolerance);
|
||||
EXPECT_TRUE(results.jacobians.at(1) == j1);
|
||||
ExpectMatricesClose(
|
||||
results.jacobians.at(1), j1, std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(results.numeric_jacobians.at(0), j0, kTolerance);
|
||||
ExpectMatricesClose(results.numeric_jacobians.at(1), j1, kTolerance);
|
||||
EXPECT_GT(results.maximum_relative_error, 0.0);
|
||||
@@ -536,23 +547,28 @@ TEST(GradientChecker, TestCorrectnessWithLocalParameterizations) {
|
||||
|
||||
// Verify that the gradient checker does not treat this as an error.
|
||||
EXPECT_TRUE(gradient_checker.Probe(parameters.data(), kTolerance, &results))
|
||||
<< results.error_log;
|
||||
<< results.error_log;
|
||||
|
||||
// Check that results contain correct data.
|
||||
ASSERT_EQ(results.return_value, true);
|
||||
ASSERT_TRUE(results.residuals == residual);
|
||||
ExpectMatricesClose(
|
||||
results.residuals, residual, std::numeric_limits<double>::epsilon());
|
||||
CheckDimensions(results, parameter_sizes, local_parameter_sizes, 3);
|
||||
ASSERT_EQ(results.local_jacobians.size(), 2);
|
||||
ASSERT_EQ(results.local_numeric_jacobians.size(), 2);
|
||||
ExpectMatricesClose(results.local_jacobians.at(0),
|
||||
(j0 + j0_offset) * parameterization.global_J_local,
|
||||
kTolerance);
|
||||
EXPECT_TRUE(results.local_jacobians.at(1) == j1);
|
||||
ExpectMatricesClose(results.local_jacobians.at(1),
|
||||
j1,
|
||||
std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(results.local_numeric_jacobians.at(0),
|
||||
j0 * parameterization.global_J_local, kTolerance);
|
||||
j0 * parameterization.global_J_local,
|
||||
kTolerance);
|
||||
ExpectMatricesClose(results.local_numeric_jacobians.at(1), j1, kTolerance);
|
||||
ExpectMatricesClose(results.jacobians.at(0), j0 + j0_offset, kTolerance);
|
||||
EXPECT_TRUE(results.jacobians.at(1) == j1);
|
||||
ExpectMatricesClose(
|
||||
results.jacobians.at(1), j1, std::numeric_limits<double>::epsilon());
|
||||
ExpectMatricesClose(results.numeric_jacobians.at(0), j0, kTolerance);
|
||||
ExpectMatricesClose(results.numeric_jacobians.at(1), j1, kTolerance);
|
||||
EXPECT_GE(results.maximum_relative_error, 0.0);
|
||||
|
||||
Reference in New Issue
Block a user