# fcn2optimexpr

## 语法

``[out1,out2,...,outN] = fcn2optimexpr(fcn,in1,in2,...,inK)``
``[out1,out2,...,outN] = fcn2optimexpr(fcn,in1,in2,...,inK,Name,Value)``

## 说明

``[out1,out2,...,outN] = fcn2optimexpr(fcn,in1,in2,...,inK)` 将函数 `fcn(in1,in2,...,inK)` 转换为具有 `N` 个输出的优化表达式。`

``[out1,out2,...,outN] = fcn2optimexpr(fcn,in1,in2,...,inK,Name,Value)` 使用一个或多个名称-值对组参数指定其他选项。例如，您可以通过传递 `OutputSize` 来保存函数计算。`

## 示例

```x = optimvar('x'); obj = fcn2optimexpr(@gamma,x); prob = optimproblem('Objective',obj); show(prob)```
``` OptimizationProblem : Solve for: x minimize : gamma(x) ```

```x0.x = 1/2; sol = solve(prob,x0)```
```Solving problem using fminunc. Local minimum found. Optimization completed because the size of the gradient is less than the value of the optimality tolerance. ```
```sol = struct with fields: x: 1.4616 ```

`type gammabrock`
```function f = gammabrock(x,y) f = (10*(y - gamma(x)))^2 + (1 - x)^2; ```

```x = optimvar('x','LowerBound',0); y = optimvar('y'); obj = fcn2optimexpr(@gammabrock,x,y); prob = optimproblem('Objective',obj); show(prob)```
``` OptimizationProblem : Solve for: x, y minimize : gammabrock(x, y) variable bounds: 0 <= x ```

`gammabrock` 函数是平方和。通过将函数表示为优化表达式的显式平方和，可以得到更高效的问题表示。

```f = fcn2optimexpr(@(x,y)y - gamma(x),x,y); obj2 = (10*f)^2 + (1-x)^2; prob2 = optimproblem('Objective',obj2);```

```x0.x = 1/2; x0.y = 1/2; [sol,fval,~,output] = solve(prob,x0);```
```Solving problem using fmincon. Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance. ```
`[sol2,fval2,~,output2] = solve(prob2,x0);`
```Solving problem using lsqnonlin. Local minimum found. Optimization completed because the size of the gradient is less than the value of the optimality tolerance. ```
`fprintf('prob took %d iterations, but prob2 took %d iterations\n',output.iterations,output2.iterations)`
```prob took 21 iterations, but prob2 took 2 iterations ```

`type expfn3`
```function [f,g,mineval] = expfn3(u,v) mineval = min(eig(u)); f = v'*u*v; f = -exp(-f); t = u*v; g = t'*t + sum(t) - 3; ```

```u = optimvar('u',2,2); v = optimvar('v',2); [f,g,mineval] = fcn2optimexpr(@expfn3,u,v); prob = optimproblem; prob.Objective = f*g/(1 + f^2); show(prob)```
``` OptimizationProblem : Solve for: u, v minimize : ((arg2 .* arg3) ./ (1 + arg1.^2)) where: [arg1,~,~] = expfn3(u, v); [arg2,~,~] = expfn3(u, v); [~,arg3,~] = expfn3(u, v); ```

`type gammafn2`
```function f = gammafn2(x,y) f = -gamma(x)*(y/(1+y^2)); ```

```x = optimvar('x','LowerBound',0); y = optimvar('y','LowerBound',0); expr1 = fcn2optimexpr(@gammafn2,x,y); confn = expr1 <= -1/2; show(confn)```
``` gammafn2(x, y) <= -0.5 ```

`confn2 = expr1 >= x + y;`

```prob = optimproblem; prob.Constraints.confn = confn; prob.Constraints.confn2 = confn2; show(prob)```
``` OptimizationProblem : Solve for: x, y minimize : subject to confn: gammafn2(x, y) <= -0.5 subject to confn2: gammafn2(x, y) >= (x + y) variable bounds: 0 <= x 0 <= y ```

`type rosenbrocknorm`
```function [f,c] = rosenbrocknorm(x) pause(1) % Simulates time-consuming function c = dot(x,x); f = 100*(x(2) - x(1)^2)^2 + (1 - x(1))^2; ```

```x = optimvar('x',2); [f,c] = fcn2optimexpr(@rosenbrocknorm,x,... 'ReuseEvaluation',true,'Analysis','off');```

```prob = optimproblem('Objective',f); prob.Constraints.cineq = c <= 4; show(prob)```
``` OptimizationProblem : Solve for: x minimize : [argout,~] = rosenbrocknorm(x) subject to cineq: arg_LHS <= 4 where: [~,arg_LHS] = rosenbrocknorm(x); ```

```x0.x = [-1;1]; tic [sol,fval,exitflag,output] = solve(prob,x0)```
```Solving problem using fmincon. Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance. <stopping criteria details> ```
```sol = struct with fields: x: [2×1 double] ```
```fval = 4.5793e-11 ```
```exitflag = OptimalSolution ```
```output = struct with fields: iterations: 44 funcCount: 164 constrviolation: 0 stepsize: 4.3124e-08 algorithm: 'interior-point' firstorderopt: 5.1691e-07 cgiterations: 10 message: 'Local minimum found that satisfies the constraints.↵↵Optimization completed because the objective function is non-decreasing in ↵feasible directions, to within the value of the optimality tolerance,↵and constraints are satisfied to within the value of the constraint tolerance.↵↵<stopping criteria details>↵↵Optimization completed: The relative first-order optimality measure, 5.169074e-07,↵is less than options.OptimalityTolerance = 1.000000e-06, and the relative maximum constraint↵violation, 0.000000e+00, is less than options.ConstraintTolerance = 1.000000e-06.' bestfeasible: [1×1 struct] objectivederivative: "finite-differences" constraintderivative: "finite-differences" solver: 'fmincon' ```
`toc`
```Elapsed time is 165.623157 seconds. ```

## 输入参数

### 名称-值参数

• 如果您希望使用 `fcn2optimexpr` 来分析 `fcn` 并尽可能使用支持的运算来实现 `fcn`，请指定 `"on"`。此设定使 `fcn` 能够使用自动微分并选择合适的求解器，如 `Solver` 中所述。

• 如果您不希望使用 `fcn2optimexpr` 来分析 `fcn`，并因此将 `fcn` 视为不使用自动微分的黑盒，请指定 `"off"`。在这种情况下，`solve` 仅使用 `fmincon``fminunc``lsqnonlin` 作为求解器。

• 整数向量 - 如果函数有一个输出 `out`1，`OutputSize` 指定 `out`1 的大小。如果函数有多个输出 `out`1、…、`out`N，`OutputSize` 指定所有输出都具有相同大小。

• 整数向量元胞数组 - 输出 `out`j 的大小是 `OutputSize` 的第 j 个元素。

`Analysis` = `"on"` 时，`ReuseEvaluation` 可能不起作用。

`ReuseEvaluation` 可以使您的问题求解运行得更快，例如，当目标和一些非线性约束依赖于共同的计算时。在这种情况下，求解器会存储值以便在需要时重用，避免重新计算该值。

## 局限性

`Analysis` 可能忽略非计算函数

• `Analysis` 算法可能不包含非计算函数。算法的这一特点可能导致以下结果：

• `pause` 语句被忽略。

• 不影响结果的全局变量可能被忽略。例如，如果您使用全局变量来计算函数运行的次数，则可能会得到误导性的计数。

• 如果该函数包含对 `rand``rng` 的调用，则该函数可能只执行第一次调用，以后的调用不会设置随机数流。

• `plot` 调用可能不会在所有迭代中都更新图窗。

• 可能不会在每次迭代时都将数据保存到 `mat` 文件或文本文件中。

• 为了确保非计算函数按预期运行，请将 `Analysis` 名称-值参数设置为 `"off"`

## 算法

### 分析

`Analysis` 参数采用默认设置 `"on"` 时，`fcn2optimexpr` 会执行几个步骤来尝试创建最高效的优化表达式。请参阅 fcn2optimexpr Algorithm Description 中的算法描述。

• 使用重载。如果一个函数中的所有运算均为Supported Operations for Optimization Variables and Expressions，您可以直接对优化变量调用该函数。例如，

`prob.Objective = sin(3*x)*exp(-x-y);`
• 对未修改的函数使用 `fcn2optimexpr`。如果一个函数中有至少一项运算不受支持，则必须调用 `fcn2optimexpr`。例如，`besselh` 函数不受支持，因此要将其包含在目标函数中，必须使用 `fcn2optimexpr`

`prob.Objective = fcn2optimexpr(@(z)besselh(3,z),x);`
• 修改函数，使其内部 `for` 循环出现在单独的函数中。这样做可以通过静态分析加快循环执行速度。请参阅Create for Loop for Static AnalysisStatic Analysis of Optimization Expressions

• `fcn2optimexpr` 中的 `Analysis` 参数设置为 `"off"`。这样做会使得 `fcn2optimexpr` 将函数封装为黑盒，这是一项速度很快的操作。得到的表达式无法利用自动微分（请参阅Automatic Differentiation Background），因此会导致求解器使用更多函数计算来进行有限差分梯度估计。