Quadratic Programs
A quadratic program (QP) has a positive semidefinite Hessian Q:
minimize ½ yᵀQy - cᵀy
subject to Ay ≥ b
Gy = dExample: Projection onto the Simplex
Project the point p = [1, 2, 3, 4, 5] onto the probability simplex {y : y ≥ 0, ∑yᵢ = 1}. This is equivalent to solving minimize ½ ‖y - p‖² subject to y ≥ 0, 1ᵀy = 1, which in ConicIP form becomes minimize ½ yᵀIy - pᵀy with appropriate constraints.
using ConicIP, SparseArrays, LinearAlgebra
n = 5
Q = sparse(1.0I, n, n)
p = collect(1.0:n)
# Nonnegativity constraints: y ≥ 0
A = sparse(1.0I, n, n)
b = zeros(n)
cone_dims = [("R", n)]
# Simplex constraint: sum(y) = 1
G = ones(1, n)
d = [1.0]
# Note: we pass Q*p as the linear term c = Qp = Ip = p
sol = conicIP(Q, Q * p, A, b, cone_dims, G, d;
verbose=false, optTol=1e-7)
sol.status:Optimalround.(sol.y, digits=4)5-element Vector{Float64}:
0.0
0.0
0.0
0.0005
0.9995The solution concentrates weight on the largest components of p, as expected for the nearest point on the simplex.
Convergence Diagnostics
The Solution struct reports convergence diagnostics:
prFeas– primal feasibility residualduFeas– dual feasibility (KKT stationarity) residualmuFeas– complementarity residualpobj,dobj– primal and dual objective values
(prFeas=sol.prFeas, duFeas=sol.duFeas, muFeas=sol.muFeas,
pobj=round(sol.pobj, digits=6), dobj=round(sol.dobj, digits=6))(prFeas = 0.0, duFeas = 1.49244812711217e-16, muFeas = 9.532282634397393e-8, pobj = -4.5, dobj = -4.5)At optimality, pobj ≈ dobj and all residuals are below optTol.
Example: Portfolio Optimization
A classic application of QP is mean-variance portfolio optimization. Given expected returns μ and a covariance matrix Σ, find the minimum-variance portfolio with expected return at least r_min:
minimize ½ yᵀΣy
subject to μᵀy ≥ r_min
1ᵀy = 1
y ≥ 0using Random
Random.seed!(42)
nassets = 8
returns = rand(nassets) * 0.1 # expected returns: 0% to 10%
# Build a realistic covariance matrix from factor model
F = randn(nassets, 3) * 0.05
Sigma = F * F' + Diagonal(rand(nassets) * 0.01 .+ 0.001)
Sigma = sparse(Symmetric(Sigma))
r_min = 0.05 # target minimum return
# Q = Sigma, c = 0 (pure quadratic objective)
Q_port = Sigma
c_port = zeros(nassets)
# Inequality constraints: [μᵀ; I] y ≥ [r_min; 0]
A_port = sparse([returns'; I(nassets)])
b_port = [r_min; zeros(nassets)]
cone_dims_port = [("R", 1 + nassets)]
# Equality constraint: sum(y) = 1
G_port = ones(1, nassets)
d_port = [1.0]
sol_port = conicIP(Q_port, c_port, A_port, b_port, cone_dims_port,
G_port, d_port; verbose=false, optTol=1e-7)
sol_port.status:Optimalweights = round.(sol_port.y, digits=4)8-element Vector{Float64}:
0.0
0.0472
0.0
0.2381
0.1796
0.0279
0.1701
0.3371Portfolio expected return and variance:
port_return = round(dot(returns, sol_port.y), digits=6)
port_variance = round((sol_port.y' * Sigma * sol_port.y)[1], digits=6)
(expected_return=port_return, variance=port_variance)(expected_return = 0.05, variance = 0.00146)