Interior point meta-algorithm for handling nonlinear semidefinite constraints
Description
If you need to keep your any matrix-valued function of the decision variables positive semidefinite, Nonconvex supports an interface for the barrier method for semidefinite programming, which is a meta-algorithm transforming the optimization problem to a series of nonlinear programming problems and solving them using the pre-specified sub_alg and sub_options.
Quick start
Optimizing over a multivariate gaussian distribution with artificial samples using Ipopt:
using Nonconvex, Distributions
Nonconvex.@load Semidefinite Ipopt
# Draw random multivariate gaussian samples
# Random groundtruth
mat_dim = 3
μ = randn(mat_dim)
Σ = rand(mat_dim, mat_dim)
Σ = Σ + Σ' + 2I
# Generate
n_sample = 1000
samples = rand(MvNormal(μ, Σ), n_sample)
# Define objective function
function f((x_L, x_D))
return -loglikelihood(MvNormal(μ, decompress_symmetric(x_L, x_D)), samples)
end
# Define the matrix-valued function
function sd_constraint((x_L, x_D))
return decompress_symmetric(x_L, x_D)
end
# Define settings
model = Model(f)
mat_x0 = rand(mat_dim, mat_dim)
mat_x0 = mat_x0 + mat_x0' + I
x0 = [mat_x0[NonconvexSemidefinite.lowertriangind(mat_x0)], diag(mat_x0)]
lbs = [fill(-Inf, length(x0[1])), zeros(length(x0[2]))]
ubs = [fill(Inf, length(x0[1])), fill(Inf, length(x0[2]))]
addvar!(model, lbs, ubs)
add_sd_constraint!(model, sd_constraint)
alg = SDPBarrierAlg(sub_alg=IpoptAlg())
options = SDPBarrierOptions(sub_options=IpoptOptions(max_iter=200), n_iter = 20)
# Optimize
result = optimize(model, alg, x0, options = options)
# Relative error norm
norm(sd_constraint(result.minimizer) - Σ) / norm(Σ)Options
NonconvexSemidefinite.SDPBarrierOptions — TypeSDPBarrierOptions(; kwargs...)The keyword arguments which can be specified are:
c_init: (default 1.0) initial value for the coefficientcthat is multiplied by the barrier term, could be a real number or vector in the case of multiple semidefinite constraints.c_decr: (default 0.1) decreasing rate (< 1) that multiplies the barrier term in every iteration, could be either a real number or a vector in the case of multiple semidefinite constraints.n_iter: (default 20) number of sub-problems to solve in the barrier method.sub_options: options for the sub-problem's solverkeep_all: (defaultfalue) if set totrue,SDPBarrierResultstores the results from all the iterations
Optimizer
NonconvexSemidefinite.SDPBarrierAlg — TypeSDPBarrierAlg(sub_alg)A meta-algorithm that handles semidefinite constraints on nonlinear functions using a barrier approach. The coefficient of the barrier term is exponentially decayed and the sub-problems are solved using sub_alg. sub_alg can be any other compatible solver from Nonconvex.jl. The solver must be able to solve the sub-problem after removing the semidefinite constraints. The options to the solver should be pased to the SDPBarrierOptions struct and passed in as the options to the optimize function. Call ? SDPBarrierOptions to check all the different options that can be set.
Matrix interfaces
For every n*n real positive semidefinite matrix that optimization objective contains, please have two inputs x_L and x_D representing the lower-triangular and the diagonal part of it. In the function, call decompress_symmetric(x_L, x_d) to represent that matrix, which will be handled by Nonocnvex automatically
NonconvexSemidefinite.decompress_symmetric — Functiondecompress_symmetricFor example: a 3*3 positive semidefinite matrix: [ a b d; b c e; d e f ] represents by: [ x_D[1] x_L[3] x_L[2]; x_L[1] x_D[2] x_L[1]; x_L[2] x_L[3] x_D[3] ]
x_L::AbstractArray: representing lower triangular part of an*nmatrix, length should be(n^2-n)÷2x_D::AbstractArray: representing diagonal part of an*nmatrix, length should ben