求解Powell’s Function
比第一个例子复杂一些,学习一下多维参数块的ceres求解写法
将每个残差方程单独构造
#include <iostream>
#include "ceres/ceres.h"
#include "glog/logging.h"
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::NumericDiffCostFunction;
using ceres::Problem;
using ceres::SizedCostFunction;
using ceres::Solve;
using ceres::Solver;
struct F1
{
template <typename T>
bool operator()(const T *const x1, const T *const x2, T *residual) const
{
residual[0] = x1[0] + T(10) * x2[0];
return true;
}
};
struct F2
{
template <typename T>
bool operator()(const T *const x3, const T *const x4, T *residual) const
{
residual[0] = T(sqrt(5.0)) * (x3[0] - x4[0]);
return true;
}
};
struct F3
{
template <typename T>
bool operator()(const T *const x2, const T *const x3, T *residual) const
{
residual[0] = (x2[0] - T(2) * x3[0]) * (x2[0] - T(2) * x3[0]);
return true;
}
};
struct F4
{
template <typename T>
bool operator()(const T *const x1, const T *const x4, T *residual) const
{
residual[0] = T(sqrt(10.0)) * (x1[0] - x4[0]) * (x1[0] - x4[0]);
return true;
}
};
int main(int argc, char **argv)
{
double x1 = 3.0;
double x2 = -1.0;
double x3 = 0.0;
double x4 = 1.0;
Problem problem;
problem.AddResidualBlock(
new AutoDiffCostFunction<F1, 1, 1, 1>(new F1), nullptr, &x1, &x2);
problem.AddResidualBlock(
new AutoDiffCostFunction<F2, 1, 1, 1>(new F2), nullptr, &x3, &x4);
problem.AddResidualBlock(
new AutoDiffCostFunction<F3, 1, 1, 1>(new F3), nullptr, &x2, &x3);
problem.AddResidualBlock(
new AutoDiffCostFunction<F4, 1, 1, 1>(new F4), nullptr, &x1, &x4);
Solver::Options options;
options.max_num_iterations = 100;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
std::cout << "Initial x1 = " << x1
<< ", x2 = " << x2
<< ", x3 = " << x3
<< ", x4 = " << x4
<< "\n";
Solver::Summary summary;
Solve(options, &problem, &summary);
std::cout << summary.FullReport() << "\n";
std::cout << "Final x1 = " << x1
<< ", x2 = " << x2
<< ", x3 = " << x3
<< ", x4 = " << x4
<< "\n";
return 0;
}
紧凑形式
#include <iostream>
#include "ceres/ceres.h"
#include "glog/logging.h"
using ceres::AutoDiffCostFunction;
using ceres::CostFunction;
using ceres::NumericDiffCostFunction;
using ceres::Problem;
using ceres::SizedCostFunction;
using ceres::Solve;
using ceres::Solver;
struct CostFunctor
{
template <typename T>
bool operator()(const T *const x, T *residule) const
{
residule[0] = x[0] + T(10) * x[1];
residule[1] = T(sqrt(5.0)) * (x[2] - x[3]);
residule[2] = pow(x[1] - T(2) * x[2], 2);
residule[3] = T(sqrt(10.0)) * (x[0] - x[3]) * (x[0] - x[3]);
return true;
}
};
int main(int argc, char **argv)
{
double x[4] = {3.0, -1.0, 0.0, 1.0};
Problem problem;
problem.AddResidualBlock(
new AutoDiffCostFunction<CostFunctor, 4, 4>(new CostFunctor), nullptr, x);
Solver::Options options;
options.max_num_iterations = 100;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
std::cout << "Initial x1 = " << x[0]
<< ", x2 = " << x[1]
<< ", x3 = " << x[2]
<< ", x4 = " << x[3]
<< "\n";
Solver::Summary summary;
Solve(options, &problem, &summary);
std::cout << summary.FullReport() << "\n";
std::cout << "Final x1 = " << x[0]
<< ", x2 = " << x[1]
<< ", x3 = " << x[2]
<< ", x4 = " << x[3]
<< "\n";
return 0;
}