Using SymbolicAnalysis.jl for convexity certificates
In this tutorial, we will show how to use automatic convexity certification of the optimization problem using SymbolicAnalysis.jl.
This works with the structural_analysis
keyword argument to OptimizationProblem
. This tells the package to try to trace through the objective and constraints with symbolic variables (for more details on this look at the Symbolics documentation). This relies on the Disciplined Programming approach hence neccessitates the use of "atoms" from the SymbolicAnalysis.jl package.
We'll use a simple example to illustrate the convexity structure certification process.
using SymbolicAnalysis, Zygote, LinearAlgebra, Optimization
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, Optimization.LBFGS(), maxiters = 1000)
retcode: Success
u: 1-element Vector{Float64}:
-0.3517365907643902
The result can be accessed as the analysis_results
field of the solution.
sol.cache.analysis_results.objective
SymbolicAnalysis.AnalysisResult(SymbolicAnalysis.Convex, SymbolicAnalysis.Positive, nothing)
Relatedly you can enable structural analysis in Riemannian optimization problems (supported only on the SPD manifold).
We'll look at the Riemannian center of mass of SPD matrices which is known to be a Geodesically Convex problem on the SPD manifold.
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.99572 1.99688 1.99689 1.99583 1.99731
1.99688 2.99767 1.99756 1.9971 1.99827
1.99689 1.99756 2.99724 1.99676 1.99835
1.99583 1.9971 1.99676 2.99603 1.99761
1.99731 1.99827 1.99835 1.99761 2.9986