Использование ограничений в виде равенств и неравенств
|
Страница в процессе перевода. |
Многие пакеты оптимизации, доступные с MathOptInterface и решателем IPNewton из Optim, могут работать с нелинейными ограничениями. Optimization.jl предоставляет простой интерфейс для определения ограничения в виде функции Julia с последующим указанием границ для результата в OptimizationFunction. Таким образом указывается, задано ли ограничение в виде равенства или неравенства.
Давайте определим функцию Розенброка в качестве целевой функции и примем приведенные ниже неравенства как ограничения.
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]