Main Content

## 编写标量目标函数

### 函数文件

f(x) = 3*(x – y)4 + 4*(x + z)2 / (1 + x2 + y2 + z2) + cosh(x – 1) + tanh(y + z)。

1. 将此函数编写为接受向量 `xin` = [x;y;z] 并返回 f 的文件：

```function f = myObjective(xin) f = 3*(xin(1)-xin(2))^4 + 4*(xin(1)+xin(3))^2/(1+norm(xin)^2) ... + cosh(xin(1)-1) + tanh(xin(2)+xin(3));```
2. 将其以名为 `myObjective.m` 的文件保存到 MATLAB® 路径上的文件夹中。

3. 检查函数是否能够正确进行计算：

```myObjective([1;2;3]) ans = 9.2666```

#### 局部函数和嵌套函数

```function [x fval] = callObjConstr(x0,options) % Using a local function for just one file if nargin < 2 options = optimoptions('fmincon','Algorithm','interior-point'); end [x fval] = fmincon(@myObjective,x0,[],[],[],[],[],[], ... @ellipseparabola,options); function f = myObjective(xin) f = 3*(xin(1)-xin(2))^4 + 4*(xin(1)+xin(3))^2/(1+sum(xin.^2)) ... + cosh(xin(1)-1) + tanh(xin(2)+xin(3)); function [c,ceq] = ellipseparabola(x) c(1) = (x(1)^2)/9 + (x(2)^2)/4 - 1; c(2) = x(1)^2 - x(2) - 1; ceq = [];```

```[x fval] = callObjConstr(ones(3,1)) Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the default value of the function tolerance, and constraints are satisfied to within the default value of the constraint tolerance. x = 1.1835 0.8345 -1.6439 fval = 0.5383```

### 匿名函数目标

`anonrosen = @(x)(100*(x(2) - x(1)^2)^2 + (1-x(1))^2);`

```anonrosen([-1 2]) ans = 104```

```options = optimoptions(@fminunc,'Algorithm','quasi-newton'); [x fval] = fminunc(anonrosen,[-1;2],options) Local minimum found. Optimization completed because the size of the gradient is less than the default value of the function tolerance. x = 1.0000 1.0000 fval = 1.2266e-10```

### 包括梯度和黑塞函数

#### 为求解器提供导数

`fmincon``active-set`可选
`interior-point`可选可选（请参阅适用于 fmincon 内点算法的黑塞函数
`sqp`可选
`trust-region-reflective`必需可选（请参阅适用于 fminunc 信赖域或 fmincon 信赖域反射算法的黑塞函数
`fminunc``quasi-newton`可选
`trust-region`必需可选（请参阅适用于 fminunc 信赖域或 fmincon 信赖域反射算法的黑塞函数

#### 如何包含梯度

1. 编写返回以下内容的代码：

• 目标函数（标量）作为第一个输出

• 梯度（向量）作为第二个输出

2. 使用 `optimoptions``SpecifyObjectiveGradient` 选项设置为 `true`。适用时，也将 `SpecifyConstraintGradient` 选项设置为 `true`

3. （可选）检查梯度函数是否与有限差分逼近匹配。请参阅检查梯度或雅可比矩阵的有效性

`$f\left(x\right)=100{\left({x}_{2}-{x}_{1}^{2}\right)}^{2}+{\left(1-{x}_{1}\right)}^{2},$`

`$\nabla f\left(x\right)=\left[\begin{array}{c}-400\left({x}_{2}-{x}_{1}^{2}\right){x}_{1}-2\left(1-{x}_{1}\right)\\ 200\left({x}_{2}-{x}_{1}^{2}\right)\end{array}\right],$`

`rosentwo` 是条件化函数，可返回求解器所需的任何内容：

```function [f,g] = rosentwo(x) % Calculate objective f f = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2; if nargout > 1 % gradient required g = [-400*(x(2)-x(1)^2)*x(1)-2*(1-x(1)); 200*(x(2)-x(1)^2)]; end```

`nargout` 检查调用函数指定的参量个数。请参阅查找函数参量的数量

```options = optimoptions(@fminunc,'Algorithm','trust-region',... 'SpecifyObjectiveGradient',true);```

`[-1;2]` 开始运行 `fminunc`

```[x fval] = fminunc(@rosentwo,[-1;2],options) Local minimum found. Optimization completed because the size of the gradient is less than the default value of the function tolerance. x = 1.0000 1.0000 fval = 1.9886e-17```

#### 包含黑塞函数

`$H\left(x\right)=\left[\begin{array}{cc}1200{x}_{1}^{2}-400{x}_{2}+2& -400{x}_{1}\\ -400{x}_{1}& 200\end{array}\right].$`

```function [f, g, H] = rosenboth(x) % Calculate objective f f = 100*(x(2) - x(1)^2)^2 + (1-x(1))^2; if nargout > 1 % gradient required g = [-400*(x(2)-x(1)^2)*x(1)-2*(1-x(1)); 200*(x(2)-x(1)^2)]; if nargout > 2 % Hessian required H = [1200*x(1)^2-400*x(2)+2, -400*x(1); -400*x(1), 200]; end end```

`HessianFcn` 设置为 `'objective'`。例如，

```options = optimoptions('fminunc','Algorithm','trust-region',... 'SpecifyObjectiveGradient',true,'HessianFcn','objective');```

`$L\left(x,\lambda \right)=f\left(x\right)+\sum {\lambda }_{g,i}{g}_{i}\left(x\right)+\sum {\lambda }_{h,i}{h}_{i}\left(x\right).$`

g 和 h 是向量函数，分别表示所有不等式和等式约束（指有界、线性和非线性约束），因此最小化问题的公式为

 ${\nabla }_{xx}^{2}L\left(x,\lambda \right)={\nabla }^{2}f\left(x\right)+\sum {\lambda }_{g,i}{\nabla }^{2}{g}_{i}\left(x\right)+\sum {\lambda }_{h,i}{\nabla }^{2}{h}_{i}\left(x\right).$ (1)

`hessian = hessianfcn(x,lambda)`

`hessian` 是 n×n 矩阵（稀疏或稠密），其中 n 是变量的数目。如果 `hessian` 很大并且非零项相对较少，请将 `hessian` 表示为稀疏矩阵，以节省运行时间和内存。`lambda` 是具有与非线性约束相关联的拉格朗日乘数向量的结构体：

```lambda.ineqnonlin lambda.eqnonlin```

`fmincon` 计算结构体 `lambda`，并将其传递给您的黑塞函数。`hessianfcn` 必须计算公式 1 中的总和。通过设置以下选项表明您提供了黑塞函数：

```options = optimoptions('fmincon','Algorithm','interior-point',... 'SpecifyObjectiveGradient',true,'SpecifyConstraintGradient',true,... 'HessianFcn',@hessianfcn);```

`$\begin{array}{c}\nabla g\left(x\right)=\left[\begin{array}{c}2{x}_{1}\\ 2{x}_{2}\end{array}\right]\\ {H}_{g}\left(x\right)=\left[\begin{array}{cc}2& 0\\ 0& 2\end{array}\right].\end{array}$`

```function Hout = hessianfcn(x,lambda) % Hessian of objective H = [1200*x(1)^2-400*x(2)+2, -400*x(1); -400*x(1), 200]; % Hessian of nonlinear inequality constraint Hg = 2*eye(2); Hout = H + lambda.ineqnonlin*Hg;```

`hessianfcn` 保存到 MATLAB 路径。为了完成此示例，包含梯度的约束函数为

```function [c,ceq,gc,gceq] = unitdisk2(x) c = x(1)^2 + x(2)^2 - 1; ceq = [ ]; if nargout > 2 gc = [2*x(1);2*x(2)]; gceq = []; end```

```fun = @rosenboth; nonlcon = @unitdisk2; x0 = [-1;2]; options = optimoptions('fmincon','Algorithm','interior-point',... 'SpecifyObjectiveGradient',true,'SpecifyConstraintGradient',true,... 'HessianFcn',@hessianfcn); [x,fval,exitflag,output] = fmincon(fun,x0,[],[],[],[],[],[],@unitdisk2,options);```

• 对于 `interior-point` 算法，语法如下

`W = HessMultFcn(x,lambda,v);`

结果 `W` 应为 `H*v` 的积，其中 `H` 是在 `x` 处拉格朗日方程的黑塞函数（请参阅公式 3），`lambda` 是拉格朗日乘数（由 `fmincon` 计算），`v` 是大小为 n×1 的向量。按如下所示设置选项：

```options = optimoptions('fmincon','Algorithm','interior-point','SpecifyObjectiveGradient',true,... 'SpecifyConstraintGradient',true,'SubproblemAlgorithm','cg','HessianMultiplyFcn',@HessMultFcn);```

提供函数 `HessMultFcn`，该函数返回 n×1 向量，其中 n 是 x 的维数。`HessianMultiplyFcn` 选项使您能够传递黑塞函数乘以向量的结果，而无需计算黑塞函数。

• `trust-region-reflective` 算法不涉及 `lambda`

`W = HessMultFcn(H,v);`

结果 `W = H*v``fmincon` 传递 `H` 作为在目标函数的第三个输出中返回的值（请参阅适用于 fminunc 信赖域或 fmincon 信赖域反射算法的黑塞函数）。`fmincon` 还传递 `v`，即包含 n 个行的向量或矩阵。`v` 中的列数可能会有所不同，因此请写入 `HessMultFcn` 以接受任意数量的列。`H` 不一定是黑塞函数；它可以是任何让您能够计算 `W = H*v` 的项。

按如下所示设置选项：

```options = optimoptions('fmincon','Algorithm','trust-region-reflective',... 'SpecifyObjectiveGradient',true,'HessianMultiplyFcn',@HessMultFcn);```

有关将黑塞函数乘法函数和 `trust-region-reflective` 算法结合使用的示例，请参阅使用密集结构 Hessian 和线性等式进行最小化

#### 为内点 `fmincon` 选择输入黑塞函数逼近方法

`fmincon` `interior-point` 算法提供了许多选项用来选择输入黑塞函数逼近方法。有关语法详细信息，请参阅作为输入的黑塞矩阵。以下是选项以及对其相对特征的估计。

`'bfgs'`（默认值）高（适用于大型问题）
`'lbfgs'`低到中等中等
`'fin-diff-grads'`中等
`'HessianMultiplyFcn'`低（取决于您的代码）中等
`'HessianFcn'`不确定（取决于您的代码）高（取决于您的代码）

`'lbfgs'` 只有中等效率的原因是需要进行双倍计算。它采用计算成本相对高昂的谢尔曼-莫里森更新。由于 `'lbfgs'` 有内存使用限制，得到的迭代步可能不够准确。

`'fin-diff-grads'``HessianMultiplyFcn` 只有中等效率的原因是它们使用共轭梯度法。它们能准确估计目标函数的黑塞函数，但它们不生成最准确的迭代步。有关详细信息，请参阅fmincon 内点算法，及其关于求解公式 38 的 LDL 方法和共轭梯度法的讨论。