Документация Engee

Использование SymbolicAnalysis.jl для подтверждения выпуклости

Страница в процессе перевода.

В этом руководстве мы покажем, как с помощью пакета SymbolicAnalysis.jl автоматически подтверждать выпуклость задачи оптимизации.

Для этого потребуется именованный аргумент structural_analysis для OptimizationProblem. Он предписывает пакету попытаться выполнить трассировку целевой функции и ограничений с использованием символьных переменных (дополнительные сведения об этом см. в документации по Symbolics). Такой подход основан на принципах дисциплинированного программирования, поэтому требует использования «единиц» из пакета SymbolicAnalysis.jl.

Продемонстрируем процесс подтверждения структуры выпуклости на простом примере.

using SymbolicAnalysis, Zygote, LinearAlgebra, Optimization, OptimizationLBFGSB

function f(x, p = nothing)
    return exp(x[1]) + x[1]^2
end

optf = OptimizationFunction(f, Optimization.AutoForwardDiff())
prob = OptimizationProblem(optf, [0.4], structural_analysis = true)

sol = solve(prob, OptimizationLBFGSB.LBFGSB(), maxiters = 1000)
retcode: Success
u: 1-element Vector{Float64}:
 -0.3517365907643902

Результат доступен в поле analysis_results решения.

sol.cache.analysis_results.objective
SymbolicAnalysis.AnalysisResult(SymbolicAnalysis.Convex, SymbolicAnalysis.Positive, nothing)

Аналогичным образом можно включить структурный анализ в задачах римановой оптимизации (поддерживается только на многообразии SPD).

Мы рассмотрим риманов центр масс матриц SPD, что, как известно, является геодезически выпуклой задачей на многообразии SPD.

using Optimization, OptimizationManopt, Symbolics, Manifolds, Random, LinearAlgebra,
      SymbolicAnalysis

M = SymmetricPositiveDefinite(5)
m = 100
σ = 0.005
q = Matrix{Float64}(LinearAlgebra.I(5)) .+ 2.0

data2 = [exp(M, q, σ * rand(M; vector_at = q)) for i in 1:m];

f(x, p = nothing) = sum(SymbolicAnalysis.distance(M, data2[i], x)^2 for i in 1:5)
optf = OptimizationFunction(f, Optimization.AutoZygote())
prob = OptimizationProblem(optf, data2[1]; manifold = M, structural_analysis = true)

opt = OptimizationManopt.GradientDescentOptimizer()
sol = solve(prob, opt, maxiters = 100)
retcode: Failure
u: 5×5 Matrix{Float64}:
 2.99973  1.99832  1.99887  1.99868  1.99957
 1.99832  2.99681  1.99758  1.99728  1.99829
 1.99887  1.99758  2.99771  1.99752  1.99855
 1.99868  1.99728  1.99752  2.99774  1.99845
 1.99957  1.99829  1.99855  1.99845  2.99924