虽然Ceres Solver的大部分致力于解决非线性最小二乘问题,但它内部包含一个求解器,可以解决一般的无约束优化问题,只使用其目标函数值和梯度。GradientProblem和GradientProblemSolver对象让用户可以访问这个求解器。

所以没有太多的麻烦,让我们看看如何使用它们。

Rosenbrock’s Function

我们考虑著名的Rosenbrock函数的最小化问题。我们首先定义一个FirstOrderFunction接口的实例。这是在Ceres定义非线性最小二乘问题时的成本函数的模拟。

class Rosenbrock : public ceres::FirstOrderFunction {
 public:
  virtual bool Evaluate(const double* parameters,
                        double* cost,
                        double* gradient) const {
    const double x = parameters[0];
    const double y = parameters[1];

    cost[0] = (1.0 - x) * (1.0 - x) + 100.0 * (y - x * x) * (y - x * x);
    if (gradient != nullptr) {
      // 对x求导数
      gradient[0] = -2.0 * (1.0 - x) - 200.0 * (y - x * x) * 2.0 * x;
      // 对y求导数
      gradient[1] = 200.0 * (y - x * x);
    }
    return true;
  }

  virtual int NumParameters() const { return 2; }
};

然后,通过构造GradientProblem对象并在其上调用Solve(),就可以简单地将其最小化。

double parameters[2] = {-1.2, 1.0};

ceres::GradientProblem problem(new Rosenbrock());

ceres::GradientProblemSolver::Options options;
options.minimizer_progress_to_stdout = true;
ceres::GradientProblemSolver::Summary summary;
ceres::Solve(options, problem, parameters, &summary);

std::cout << summary.FullReport() << "\n";

执行此代码结果,使用有限内存的BFGS算法解决问题。
代码示例在examples/rosenbrock.cc