# Hello World

我们尝试找到如下函数的最小值

$$
\frac{1}{2}(10-x)^2
$$

貌似这个问题太简单了哈，最小值点在 $$x=10$$ 处取得，但是计算机不是人，我们只能通过程序的方式来让他求解，这就是 Ceres 要做的事。接下来我们就来通过 Ceres 来求解该问题。

第一步是编写一个 functor 来评估函数 $$f(x)=10-x$$

```cpp
struct CostFunctor {
   template <typename T>
   bool operator()(const T* const x, T* residual) const {
     residual[0] = 10.0 - x[0];
     return true;
   }
};
```

上述最重要的部分是 `operator()` 这个重载函数，它是一个模板函数，它所有的输入和输出类型都是某种类型 `T`。在这里使用模板则允许 Ceres 调用 `CostFunctor::operator<T>()` ，当只需要残差值时使用 `T=double`，当同时需要雅可比时使用特殊类型 `T=Jet` （这个类型是 Ceres 为什么能够进行自动求导的关键）。在 [Derivatives](/ceres/optimization-tutorial/non-linear-least-squares/derivation.md) 中，也就是后文的导数章节，我们将更详细地讨论向 Ceres 提供导数的各种方法。

一旦我们有了计算残差的方法，就可以利用它去构建一个非线性最小二乘法问题，并使用 Ceres 解决它。

```cpp
int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);

  // The variable to solve for with its initial value.
  double initial_x = 5.0;
  double x = initial_x;

  // Build the problem.
  Problem problem;

  // Set up the only cost function (also known as residual). This uses
  // auto-differentiation to obtain the derivative (jacobian).
  CostFunction* cost_function =
      new AutoDiffCostFunction<CostFunctor, 1, 1>();
  problem.AddResidualBlock(cost_function, nullptr, &x);

  // Run the solver!
  Solver::Options options;
  options.linear_solver_type = ceres::DENSE_QR;
  options.minimizer_progress_to_stdout = true;
  Solver::Summary summary;
  Solve(options, &problem, &summary);

  std::cout << summary.BriefReport() << "\n";
  std::cout << "x : " << initial_x
            << " -> " << x << "\n";
  return 0;
}
```

`AutoDiffCostFunction` 将一个`CostFunctor`作为输入，自动对其进行微分，并给出一个 `CostFunction` 接口。

编译并运行 [examples/helloworld.cc](https://ceres-solver.googlesource.com/ceres-solver/+/master/examples/helloworld.cc) 将会得到如下结果

```sh
iter      cost      cost_change  |gradient|   |step|    tr_ratio  tr_radius  ls_iter  iter_time  total_time
   0  4.512500e+01    0.00e+00    9.50e+00   0.00e+00   0.00e+00  1.00e+04       0    5.33e-04    3.46e-03
   1  4.511598e-07    4.51e+01    9.50e-04   9.50e+00   1.00e+00  3.00e+04       1    5.00e-04    4.05e-03
   2  5.012552e-16    4.51e-07    3.17e-08   9.50e-04   1.00e+00  9.00e+04       1    1.60e-05    4.09e-03
Ceres Solver Report: Iterations: 2, Initial cost: 4.512500e+01, Final cost: 5.012552e-16, Termination: CONVERGENCE
x : 0.5 -> 10
```

$$x$$ 的初始值设置为 $$0.5$$（[Ceres 的英文文档这里写的 $$5$$，貌似是个笔误](http://ceres-solver.org/nnls_tutorial.html#hello-world)），经过两轮迭代后为 $$10$$，细心的读者会发现，这是一个线性问题，一次线性求解就足以得到最优值，然而 Ceres 求解器的默认配置是针对非线性问题的，为了简单起见，我们在本例中没有更改，不过，使用 Ceres 只进行一次迭代也确实可以得到这个问题的解。我们将在讨论 Ceres 的收敛性和参数设置时更详细地讨论这些问题。

## Footnotes

> 1. 实际上，求解器运行了三次迭代，通过观察第三次迭代中线性求解器返回的值，它发现参数块的更新太小，于是宣布收敛。Ceres 只在迭代结束时打印显示，一旦检测到收敛就会终止，这就是为什么你在这里只看到两次迭代而不是三次。
> 2. [examples/helloworld.cc](https://ceres-solver.googlesource.com/ceres-solver/+/master/examples/helloworld.cc)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ceres-solver-tutorial-cn.gitbook.io/ceres/optimization-tutorial/non-linear-least-squares/hello-world.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
