AnyMath 文档

使用平等和不平等约束

该页面正在翻译中。

多个优化包可与MathOptInterface和Optim的 IPNewton 求解器可以处理非线性约束。 优化。jl提供了一个简单的接口来将约束定义为Julia函数,然后在 优化功能 指示它是平等还是不等式约束。

让我们将rosenbrock函数定义为我们的目标函数,并将以下不等式视为我们的约束。

using Optimization, OptimizationMOI, OptimizationOptimJL, Ipopt
using ForwardDiff, ModelingToolkit

rosenbrock(x, p) = (p[1] - x[1])^2 + p[2] * (x[2] - x[1]^2)^2
x0 = zeros(2)
_p = [1.0, 1.0]
2-element Vector{Float64}:
 1.0
 1.0

接下来,我们将平方和与优化变量的乘积定义为约束函数。

cons(res, x, p) = (res .= [x[1]^2 + x[2]^2, x[1] * x[2]])
cons (generic function with 1 method)

我们将使用 IPNewton 来自Optim的求解器来解决问题。

optprob = OptimizationFunction(rosenbrock, Optimization.AutoForwardDiff(), cons = cons)
prob = OptimizationProblem(optprob, x0, _p, lcons = [-Inf, -1.0], ucons = [0.8, 2.0])
sol = solve(prob, IPNewton())
retcode: Success
u: 2-element Vector{Float64}:
 0.7519644536194577
 0.484303066780286

让我们检查约束是否满足,目标是否低于初始值。

res = zeros(2)
cons(res, sol.u, _p)
res
2-element Vector{Float64}:
 0.7999999999999997
 0.36417869099766553
prob.f(sol.u, _p)
0.06810654459826093

我们也可以将Ipopt库与OptimizationMOI包一起使用。

sol = solve(prob, Ipopt.Optimizer())
retcode: Success
u: 2-element Vector{Float64}:
 0.7519644519971305
 0.4843030638909282
res = zeros(2)
cons(res, sol.u, _p)
res
2-element Vector{Float64}:
 0.7999999947614852
 0.3641786880392731
prob.f(sol.u, _p)
0.06810654547600103

我们也可以使用ModelingToolkit作为我们的广告后端,并为目标和约束生成符号导数和表达式图。

让我们修改边界以将函数用作相等约束。 约束现在变成 -

optprob = OptimizationFunction(rosenbrock, Optimization.AutoSymbolics(), cons = cons)
prob = OptimizationProblem(optprob, x0, _p, lcons = [1.0, 0.5], ucons = [1.0, 0.5])
OptimizationProblem. In-place: true
u0: 2-element Vector{Float64}:
 0.0
 0.0

下面,AmplNLWriter。jl包用于使用Ipopt库来解决问题。

using AmplNLWriter, Ipopt_jll
sol = solve(prob, AmplNLWriter.Optimizer(Ipopt_jll.amplexe))
retcode: Default
u: 2-element Vector{Float64}:
 NaN
 NaN

约束条件如预期的那样分别评估为1.0和0.5。

res = zeros(2)
cons(res, sol.u, _p)
println(res)
[NaN, NaN]