plot_sparsity (generic function with 1 method)
Spectrahedron
This example shows an optimization problem over the spectraplex:
\[S = \{X \in \mathbb{S}_+^n, Tr(X) = 1\}\]
with $\mathbb{S}_+^n$ the set of positive semidefinite matrices. Linear optimization with symmetric objective $D$ over the spetraplex consists in computing the leading eigenvector of $D$.
The package also exposes UnitSpectrahedronLMO
which corresponds to the feasible set:
\[S_u = \{X \in \mathbb{S}_+^n, Tr(X) \leq 1\}\]
using FrankWolfe
using LinearAlgebra
using Random
using SparseArrays
The objective function will be the symmetric squared distance to a set of known or observed entries $Y_{ij}$ of the matrix.
\[f(X) = \sum_{(i,j) \in L} 1/2 (X_{ij} - Y_{ij})^2\]
Setting up the input data, objective, and gradient
Dimension, number of iterations and number of known entries:
n = 1500
k = 5000
n_entries = 1000
Random.seed!(41)
const entry_indices = unique!([minmax(rand(1:n, 2)...) for _ in 1:n_entries])
const entry_values = randn(length(entry_indices))
function f(X)
r = zero(eltype(X))
for (idx, (i, j)) in enumerate(entry_indices)
r += 1 / 2 * (X[i, j] - entry_values[idx])^2
r += 1 / 2 * (X[j, i] - entry_values[idx])^2
end
return r / length(entry_values)
end
function grad!(storage, X)
storage .= 0
for (idx, (i, j)) in enumerate(entry_indices)
storage[i, j] += (X[i, j] - entry_values[idx])
storage[j, i] += (X[j, i] - entry_values[idx])
end
return storage ./= length(entry_values)
end
grad! (generic function with 1 method)
Note that the ensure_symmetry = false
argument to SpectraplexLMO
. It skips an additional step making the used direction symmetric. It is not necessary when the gradient is a LinearAlgebra.Symmetric
(or more rarely a LinearAlgebra.Diagonal
or LinearAlgebra.UniformScaling
).
const lmo = FrankWolfe.SpectraplexLMO(1.0, n, false)
const x0 = FrankWolfe.compute_extreme_point(lmo, spzeros(n, n))
target_tolerance = 1e-8;
Running standard and lazified Frank-Wolfe
Xfinal, Vfinal, primal, dual_gap, trajectory = FrankWolfe.frank_wolfe(
f,
grad!,
lmo,
x0,
max_iteration=k,
line_search=FrankWolfe.MonotonicStepSize(),
print_iter=k / 10,
memory_mode=FrankWolfe.InplaceEmphasis(),
verbose=true,
trajectory=true,
epsilon=target_tolerance,
)
Xfinal, Vfinal, primal, dual_gap, trajectory_lazy = FrankWolfe.lazified_conditional_gradient(
f,
grad!,
lmo,
x0,
max_iteration=k,
line_search=FrankWolfe.MonotonicStepSize(),
print_iter=k / 10,
memory_mode=FrankWolfe.InplaceEmphasis(),
verbose=true,
trajectory=true,
epsilon=target_tolerance,
);
Vanilla Frank-Wolfe Algorithm.
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: MonotonicStepSize EPSILON: 1.0e-8 MAXITERATION: 5000 TYPE: Float64
MOMENTUM: nothing GRADIENTTYPE: Nothing
LMO: FrankWolfe.SpectraplexLMO{Float64, Matrix{Float64}}
[ Info: In memory_mode memory iterates are written back into x0!
-------------------------------------------------------------------------------------------------
Type Iteration Primal Dual Dual Gap Time It/sec
-------------------------------------------------------------------------------------------------
I 1 1.018597e+00 1.014119e+00 4.477824e-03 0.000000e+00 Inf
Last 25 1.014314e+00 1.014314e+00 9.179324e-09 1.010046e+00 2.475135e+01
-------------------------------------------------------------------------------------------------
Lazified Conditional Gradient (Frank-Wolfe + Lazification).
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: MonotonicStepSize EPSILON: 1.0e-8 MAXITERATION: 5000 lazy_tolerance: 2.0 TYPE: Float64
GRADIENTTYPE: Matrix{Float64} CACHESIZE Inf GREEDYCACHE: false
LMO: FrankWolfe.VectorCacheLMO{FrankWolfe.SpectraplexLMO{Float64, Matrix{Float64}}, FrankWolfe.RankOneMatrix{Float64, Vector{Float64}, Vector{Float64}}}
[ Info: In memory_mode memory iterates are written back into x0!
----------------------------------------------------------------------------------------------------------------
Type Iteration Primal Dual Dual Gap Time It/sec Cache Size
----------------------------------------------------------------------------------------------------------------
I 1 1.018597e+00 1.014119e+00 4.477824e-03 0.000000e+00 Inf 1
LD 2 1.014317e+00 1.014314e+00 3.630596e-06 6.087018e-01 3.285681e+00 2
LD 3 1.014315e+00 1.014314e+00 1.025225e-06 6.468251e-01 4.638039e+00 3
LD 4 1.014315e+00 1.014314e+00 5.032060e-07 6.849080e-01 5.840200e+00 4
LD 6 1.014314e+00 1.014314e+00 1.996252e-07 7.354154e-01 8.158654e+00 5
LD 9 1.014314e+00 1.014314e+00 8.299030e-08 8.009959e-01 1.123601e+01 6
LD 13 1.014314e+00 1.014314e+00 3.827847e-08 8.804884e-01 1.476453e+01 7
LD 19 1.014314e+00 1.014314e+00 1.745621e-08 9.895160e-01 1.920131e+01 8
LD 27 1.014314e+00 1.014314e+00 8.503621e-09 1.129999e+00 2.389383e+01 9
Last 27 1.014314e+00 1.014314e+00 7.896182e-09 1.205219e+00 2.240258e+01 10
----------------------------------------------------------------------------------------------------------------
Plotting the resulting trajectories
data = [trajectory, trajectory_lazy]
label = ["FW", "LCG"]
plot_trajectories(data, label, xscalelog=true)
This page was generated using Literate.jl.