# fseminf
求解半无限约束多变量非线性函数的最小值
函数库: TyOptimization
# 语法
x,fval,exitflag,output,lambda = fseminf(fun,x0,ntheta,seminfcon)
_ = fseminf(fun,x0,ntheta,seminfcon,A,b)
_ = fseminf(fun,x0,ntheta,seminfcon,A,b,Aeq,beq)
_ = fseminf(fun,x0,ntheta,seminfcon,A,b,Aeq,beq,lb,ub)
_ = fseminf(fun,x0,ntheta,seminfcon,A,b,Aeq,beq,lb,ub,options)
_ = fseminf(problem)
# 说明
fseminf 是非线性规划求解器,用于求由下式指定的问题的最小值
b 和 beq 是向量;
A 和 Aeq 是矩阵;
c(x)、ceq(x) 和 Ki(x,wi) 是返回向量的函数;
f(x) 是返回标量的函数。
f(x)、c(x) 和 ceq(x) 可以是非线性函数。向量(或矩阵)Ki(x,wi) ≤ 0 是 x 和一组附加变量 w1,w2,...,wn 的连续函数。变量 w1,w2,...,wn 是长度最大为 2 的向量。
x,fval,exitflag,output,lambda = fseminf(fun,x0,ntheta,seminfcon) 从 x0 开始,求解满足 seminfcon 中定义的 ntheta 半无限约束条件的函数 fun 的最小值。fseminf 会返回以下值:示例
- x - 函数的最小值。
- fval - 目标函数 fun 在解 x 处的值。
- exitflag - 描述退出条件的值。
- output - 提供优化过程信息的结构体。
- lambda - 解 x 处的拉格朗日乘数结构体。
注意
如果为问题指定的输入边界不一致,则输出 x 为 x0,输出 fval 为 NaN。
_ = fseminf(fun,x0,ntheta,seminfcon,A,b) 还尝试满足线性不等式 A*x ≤ b。
_ = fseminf(fun,x0,ntheta,seminfcon,A,b,Aeq,beq) 还会在满足线性等式 Aeq*x = beq 的情况下进行最小化。如果不存在不等式,请设置 A = [] 和 b = []。
_ = fseminf(fun,x0,ntheta,seminfcon,A,b,Aeq,beq,lb,ub) 对 x 中的设计变量定义一组下界和上界,使解始终在 lb ≤ x ≤ ub 范围内。
_ = fseminf(fun,x0,ntheta,seminfcon,A,b,Aeq,beq,lb,ub,options) 使用 options 所指定的优化选项执行最小化。使用 optimoptions 可设置这些选项。
_ = fseminf(problem) 求 problem 的最小值,它是 problem 中所述的一个结构体。
# 示例
最小化具有半无限约束的函数
最小化函数
需满足以下约束:
无约束目标函数在 x=1 处具有最小值。然而,约束
意味着 x≤1/2。请注意,
因此:
当 x≤1/2 时,
要使用 fseminf 求解此问题,请将目标函数写为匿名函数。
using TyOptimization
objfun = x->(x[1]-1)^2
编写半无限约束函数 seminfcon,其中包括非线性约束 [ ]、t 的初始采样间隔(步长为 0.01,采样间隔为 0 到 1),以及半无限约束函数 g(x,t)
seminfcon = (x,s)-> begin
# 没有有限的非线性不等式和等式约束
c = Float64[]
ceq = Float64[]
# 样本集
if s === NaN
# 初始取样区间
s = [0.01 0];
end
t = 0:s[1]:1
# 计算半无限约束
K1 = (x[1] - 0.5) .- (t .- 0.5).^2
return c, ceq, K1, s
end
设置初始点 x0 = [0.2]。
x0 = [0.2]
指定一个半无限约束。
ntheta = 1
通过调用 fseminf 求解问题并查看结果。
x, = fseminf(objfun,x0,ntheta,seminfcon)
x = 1-element Vector{Float64}:
0.5000000000059635
检查 fseminf 输出
最小化函数
需满足以下约束:
示例最小化具有半无限约束的函数中表示了此问题并进行了求解,其中提供有关解和求解过程的详细信息。
要使用 fseminf 求解此问题,请将目标函数写为匿名函数。
using TyOptimization
objfun = x->(x[1]-1)^2
编写非线性和半无限约束函数 seminfcon。
seminfcon = (x,s)-> begin
# 没有有限的非线性不等式和等式约束
c = Float64[]
ceq = Float64[]
# 样本集
if s === NaN
# 初始取样区间
s = [0.01 0];
end
t = 0:s[1]:1
# 计算半无限约束
K1 = (x[1] - 0.5) .- (t .- 0.5).^2
return c, ceq, K1, s
end
设置初始点 x0 = [0.2]。
x0 = [0.2]
指定一个半无限约束。
ntheta = 1
通过调用 fseminf 求解问题并查看结果。
A = []
b = []
Aeq = []
beq = []
lb = [0]
ub = [2]
x,fval,exitflag,output,lambda = fseminf(objfun,x0,ntheta,seminfcon,A,b,Aeq,beq,lb,ub)
x = 1-element Vector{Float64}:
0.5000000000059635
fval = 0.24999999999403655
exitflag = 1
output = (iterations = 2, funcCount = 4, lssteplength = 1.0, stepsize = 4.490889330197164e-9, algorithm = "active-set", firstorderopt = 8.981778654160166e-9, constrviolation = -4.490889330197164e-9, message = "\nLocal minimum found that satisfies the constraints.\n\nOptimization 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.\n\n\nOptimization completed: The first-order optimality measure, 8.981778654160166e-9, is less than options.OptimalityTolerance = 0.0001, and the maximum constraint violation, -4.490889330197164e-9,is less than options.ConstraintTolerance = 1.0e-6.\n\n")
lambda = (lower = [0.0], upper = [0.0], eqlin = Float64[], eqnonlin = Float64[], ineqlin = Float64[], ineqnonlin = Float64[])
返回的值显示:
问题在 x=1/2 处求得解。
目标函数
求解器需要两次迭代和四次函数计算才能得到该解。
除了半无限约束之外,其他约束只有边界,因此 lambda 结构体没有线性或非线性值。对应于边界的 lambda.lower 和 lambda.upper 字段不为空,而是具有零值,因为解不在任一边界上。
# 输入参数
fun — 要计算最小值的函数函数句柄
要最小化的函数,指定为函数句柄或函数名称。fun 接受向量 x,并返回实数标量 f,即在 x 处计算的目标函数值。
将 fun 指定为文件的函数句柄。
x = fseminf(myfun,...)
此处,myfun 是一个 Syslab 函数,如下所示。
myfun = x->begin
f = ... # 计算在 x 处的值
return f
end
您还可以为匿名函数指定 fun 作为函数句柄。
x = fseminf(x->norm(x)^2,...)
如果您可以计算 fun 的梯度且 SpecifyObjectiveGradient 选项设置为 true,设置如下:
options = optimoptions(:fseminf,SpecifyObjectiveGradient=true)
则 fun 必须在第二个输出参数中返回梯度向量 g(x)。
示例: fun = x->sin(x[1])*cos(x[2])
x0 — 初始点实数向量
初始点,指定为实数向量。求解器使用 x0 中的元素数量来确定 fun 接受的变量数量。
示例: x0 = [1,2,3,4]
ntheta — 半无限约束的数量正整数
半无限约束的数量,指定为正整数。
示例: 4
seminfcon — 计算非线性约束和半无限约束的函数函数句柄
函数计算点 x 处的非线性不等式约束向量 c,非线性等式约束向量 ceq,以及在区间 S 上求值的 ntheta 半无限约束(向量或矩阵)K1、K2、...、Kntheta。您可以将 seminfcon 指定为函数句柄。
x = fseminf(myfun,x0,ntheta,myinfcon)
其中 myinfcon 是一个 Syslab 函数,例如
myinfcon = (x,S)->begin
% 初始采样区间
if S === NaN
S = ... # S 有 ntheta 行,两列
end
w1 = ...# 计算样本集
w2 = ...# 计算样本集
...
wntheta = ... # 计算样本集
K1 = ... # 在 x 和 w 的第一个半无限约束
K2 = ... # 在 x 和 w 的第二个半无限约束
...
Kntheta = ...# 在 x 和 w 的最后一个半无限约束
c = ... # 计算 x 处的非线性不等式约束
ceq = ... # 计算 x 处的非线性等式约束
return c,ceq,K1,K2,...,Kntheta,S
end
S 是建议的采样间隔,该函数可能不会使用它。如果不存在此类约束,则对 c 和 ceq 返回 Float64[]。
向量或矩阵 K1、K2、...、Kntheta 分别包含针对自变量 w1、w2、...、wntheta 的一组采样值计算的半无限约束。两列矩阵 S 包含 w1、w2、...、wntheta 的值的建议采样间隔,采样值将用于计算 K1、K2、... 和 Kntheta。S 的第 i 行包含用于计算 Ki 的建议采样间隔。当 Ki 是向量时,函数仅使用 S[i,1](第二列可以全为零)。当 Ki 是矩阵时,该函数使用 S[i,2] 对 Ki 中的行进行采样,并使用 S[i,1] 作为 Ki 的列的采样间隔(请参见Two-Dimensional Semi-Infinite Constraint)。由于 S 在第一次迭代中是 NaN,seminfcon 必须确定一个初始采样间隔。
A — 线性不等式约束实矩阵
线性不等式约束,指定为实矩阵。A 是 M×N 矩阵,其中 M 是不等式的数目,而 N 是变量的数目(x0 中的元素数)。对于大型问题,将 A 作为稀疏矩阵传递。
A 以如下形式编写 M 个线性不等式:
A*x <= b,
其中,x 是由 N 个变量组成的列向量,b 是具有 M 个元素的列向量。
例如,假设有以下不等式:
x1 +2x2 ≤10
3x1 +4x2 ≤20
5x1 +6x2 ≤30
通过输入以下约束来指定不等式。
A = [1 2;3 4;5 6]
b = [10,20,30]
示例: 要指定 x 分量总和等于或小于 1,请使用 A = ones(1,N) 和 b = [1]。
b — 线性不等式约束实数向量
线性不等式约束,指定为实数向量。b 是与 A 矩阵相关的包含 M 个元素的向量。对于大型问题,将 b 作为稀疏向量传递。
b 以如下形式编写 M 个线性不等式:
A*x <= b,
其中,x 是由 N 个变量组成的列向量,A 是大小为 M×N 的矩阵。
例如,假设有以下不等式:
x1 + 2x2 ≤ 10
3x1 + 4x2 ≤ 20
5x1 + 6x2 ≤ 30
通过输入以下约束来指定不等式。
A = [1 2;3 4;5 6]
b = [10,20,30]
示例: 要指定 x 分量总和等于或小于 1,请使用 A = ones(1,N) 和 b = [1]。
Aeq — 线性等式约束实矩阵
线性等式约束,指定为实矩阵。Aeq 是 Me×N 矩阵,其中 Me 是等式的数目,而 N 是变量的数目(x0 中的元素数)。对于大型问题,将 Aeq 作为稀疏矩阵传递。
Aeq 以如下形式编写 Me 个线性等式:
Aeq*x = beq
其中,x 是由 N 个变量组成的列向量,beq 是具有 Me 个元素的列向量。
例如,假设有以下不等式:
x1 +2x2 +3x3 =10
2x1 +4x2 + x3 =20
通过输入以下约束来指定不等式。
Aeq = [1 2 3;2 4 1]
beq = [10,20]
示例: 要指定 x 分量总和为 1,请使用 Aeq = ones(1,N) 和 beq = [1]。
beq — 线性等式约束实数向量
线性等式约束,指定为实数向量。beq 是与 Aeq 矩阵相关的包含 Me 个元素的向量。对于大型问题,将 beq 作为稀疏向量传递。
beq 以如下形式编写 Me 个线性等式:
Aeq*x = beq
其中,x 是由 N 个变量组成的列向量,Aeq 是大小为 Me×N 的矩阵。
例如,请参考以下等式:
x1 + 2x2 + 3x3 = 10
2x1 + 4x2 + x3 = 20
通过输入以下约束来指定等式。
Aeq = [1 2 3;2 4 1]
beq = [10,20]
示例: 要指定 x 分量总和为 1,请使用 Aeq = ones(1,N) 和 beq = [1]。
lb — 下界实数向量
下界,指定为实数向量。如果 x0 中的元素数等于 lb 中的元素数,则 lb 指定
x[i] >= lb[i](对于全部 i)。
如果 length(lb) < length(x0),则 lb 指定
x[i] >= lb[i] (1 <= i <= length(lb))。
如果 lb 的元素数少于 x0,求解器将发出警告。
示例: 要指定所有 x 分量为正,请使用 lb = zeros(size(x0))。
ub — 上界实数向量
上界,指定为实数向量。如果 x0 中的元素数等于 ub 中的元素数,则 ub 指定
x[i] <= ub[i](对于全部 i)。
如果 length(ub) < length(x0),则 ub 指定
x[i] <= ub[i] (1 <= i <= length(ub))。
如果 ub 的元素数少于 x0,求解器将发出警告。
示例: 要指定 x 的所有分量小于 1,请使用 ub = ones(size(x0))。
options — 优化选项optimoptions 的输出
优化选项,指定为 optimoptions 的输出或 optimset 等返回的结构体。有关详细信息,请参见优化选项参考。
optimoptions 显示中缺少某些选项。这些选项在下表中以斜体显示。有关详细信息,请参见查看优化选项。
| 选项 | 说明 |
|---|---|
| CheckGradients | 将用户提供的导数(目标或约束的梯度)与有限差分导数进行比较。选择项是 true 或默认值 false。 |
| ConstraintTolerance | 约束违反度的终止容差(正标量)。默认值为 1e-6。 |
| Diagnostics | 显示关于要最小化或求解的函数的诊断信息。选择项是 true 或默认值 false。 |
| DiffMaxChange | 有限差分梯度变量的最大变化(正标量)。默认值为 Inf。 |
| DiffMinChange | 有限差分梯度变量的最小变化(正标量)。默认值为 0。 |
| Display | 显示级别:
|
| FiniteDifferenceStepSize | 有限差分的标量或向量步长因子。当您将 FiniteDifferenceStepSize 设置为向量 v 时,前向有限差分 delta 是 delta = v.*sign′(x).*max.(abs.(x),TypicalX) 其中 sign′(x) = sign(x)(例外是 sign′(0) = 1)。中心有限差分是 delta = v.*max(abs(x),TypicalX) 标量 FiniteDifferenceStepSize 扩展为向量。默认值 Float64[] 为占位符。fseminf 在内部将使用 fill(sqrt(eps()),numberOfVariables) 或 fill(eps()^(1/3),numberOfVariables) 覆盖此默认值。正向有限差分使用 fill(sqrt(eps()),numberOfVariables);中心有限差分使用 fill(eps()^(1/3),numberOfVariables)。 |
| FiniteDifferenceType | 用于估计梯度的有限差分是 "forward"(默认值)或 "central"(中心化)。"central" 需要两倍的函数计算次数,但可以更准确。当同时估计这两种类型的有限差分时,该算法小心地遵守边界。例如,为了避免在边界之外的某个点处进行计算,算法可能需要后向差分,而不是前向差分。 |
| FunctionTolerance | 函数值的终止容差(正标量)。默认值为 1e-4。 |
| FunValCheck | 检查目标函数和约束值是否有效。当目标函数或约束返回的值是 complex、Inf 或 NaN 时,设置 true 显示错误。默认值 false 不显示错误。 |
| MaxFunctionEvaluations | 允许的函数计算的最大次数,为正整数。默认值 -1 为占位符,fseminf 在内部将使用 100*numberOfVariables 覆盖该默认值。如果指定 MaxFunctionEvaluations 为 -10,则允许的函数计算的最大次数为 Inf。 |
| MaxIterations | 允许的迭代最大次数,为正整数。默认值为 400。当指定 MaxIterations 为 -10 时,允许的迭代最大次数为 Inf。 |
| MaxSQPIter | 允许的 SQP 迭代最大次数(正整数)。默认值 -1 为占位符,fseminf 在内部将使用 10*max(numberOfVariables, numberOfInequalities + numberOfBounds) 覆盖该默认值。。 |
| OptimalityTolerance | 一阶最优性的终止容差(正标量)。默认值为 1e-6。 |
| RelLineSrchBnd | 线搜索步长的相对边界(非负实数标量值),使得 x 中的总位移满足 |Δx(i)| ≤ relLineSrchBnd· max(|x(i)|,|typicalx(i)|)。 当 fseminf 认为求解器采用的步长过大时,此选项可控制 x 中位移的模。默认值为无边界 (NaN)。 |
| RelLineSrchBndDuration | RelLineSrchBnd 所指定的边界应处于活动状态的迭代次数(默认值为 1)。 |
| SpecifyObjectiveGradient | 用户定义的目标函数梯度。请参见前面对 fun 的说明,了解如何在 fun 中定义梯度。将此选项设置为 true,以使 fseminf 采用用户定义的目标函数梯度。默认值 false 会导致 fseminf 使用有限差分来估计梯度。 |
| StepTolerance | 关于正标量 x 的终止容差。默认值为 1e-4。 |
| TolConSQP | 内部迭代 SQP 约束违反度的终止容差(正标量)。默认值为 1e-6。 |
| TypicalX | 典型的 x 值。TypicalX 中的元素数等于变量数。默认值 Float64[] 为占位符,fseminf 在内部将使用 ones(numberofvariables) 覆盖此默认值。fseminf 使用 TypicalX 缩放有限差分来进行梯度估计。 |
示例: options = optimoptions(:fseminf,SpecifyObjetiveGradient=true)
problem — 问题结构体结构体
问题结构体,指定为含有以下字段的结构体。
| 字段名称 | 条目 |
|---|---|
| objective | 目标函数 |
| x0 | x 的初始点 |
| ntheta | 半无限约束的数量 |
| seminfcon | 半无限约束函数 |
| Aineq | 线性不等式约束的矩阵 |
| bineq | 线性不等式约束的向量 |
| Aeq | 线性等式约束的矩阵 |
| beq | 线性等式约束的向量 |
| lb | 由下界组成的向量 |
| ub | 由上界组成的向量 |
| solver | "fmseminf" |
| options | 用 optimoptions 创建的选项 |
您必须在 problem 结构体中至少提供 objective、x0、seminfcon、ntheta、solver 和 options 字段。
# 输出参数
x — 解实数向量
解,以实数向量形式返回。x 的大小与 x0 的大小相同。通常情况下,当 exitflag 为正时,x 是该问题的局部解。有关解质量的信息,请参见求解成功后。
fval — 解处的目标函数值实数
解处的目标函数值,以实数形式返回。通常,fval = fun(x)。
exitflag — fseminf 停止的原因整数
fseminf 停止的原因,以整数形式返回。
| 标志 | 说明 |
|---|---|
| 1 | 函数收敛于解 x。 |
| 4 | 搜索方向的模小于指定的容差,约束违反度小于 options.ConstraintTolerance。 |
| 5 | 方向导数的模小于指定容差,约束违反度小于 options.ConstraintTolerance。 |
| 0 | 迭代次数超过 options.MaxIterations 或函数计算次数超过 options.MaxFunctionEvaluations。 |
| -1 | 由输出函数或绘图函数停止。 |
| -2 | 找不到可行点。 |
output — 有关优化过程的信息结构体
有关优化过程的信息,以包含下列字段的结构体形式返回。
| 字段名称 | 说明 |
|---|---|
| iterations | 执行的迭代次数 |
| funcCount | 函数计算次数 |
| lssteplength | 相对于搜索方向的线搜索步长 |
| stepsize | x 中的最终位移 |
| algorithm | 使用的优化算法 |
| constrviolation | 约束函数的最大值 |
| firstorderopt | 一阶最优性的度量 |
| message | 退出消息 |
| iterations | 执行的迭代次数 |
| funcCount | 函数计算次数 |
lambda — 解处的拉格朗日乘数结构体
解处的拉格朗日乘数,以包含下列字段的结构体形式返回。
| 字段名称 | 说明 |
|---|---|
| lower | 对应于 lb 的下界 |
| upper | 对应于 ub 的上界 |
| ineqlin | 对应于 A 和 b 的线性不等式 |
| eqlin | 对应于 Aeq 和 beq 的线性等式 |
| ineqnonlin | 对应于 seminfcon 中 c 的非线性不等式 |
| eqnonlin | 对应于 seminfcon 中 ceq 的非线性等式 |
# 局限性
要最小化的函数、约束和半无限约束必须为 x 和 w 的连续函数。
fseminf 可能只提供局部解。
# 算法
fseminf 使用三次和二次插值方法来估计半无限约束中的峰值。该算法使用峰值来构成一组约束,这些约束将提供给 SQP 方法,就像在 fmincon 函数中那样。当约束数量发生变化时,算法将重新为新的约束组分配拉格朗日乘数。
建议的采样间隔计算使用峰值插值和在数据集中的峰值之间的差值来估计函数需要增加还是减少数据点。该函数还通过外插曲线并将其与曲线中的其他点进行比较来计算内插的有效性。当峰值接近约束边界(即零)时,建议的采样间隔减小。
当问题不可行时,fseminf 会尝试最小化最大约束值。
有关所用算法的详细信息,请参见SQP 实现。有关 fseminf 算法的详细信息,请参见fseminf 问题的表示和算法。