plot_sparsity (generic function with 1 method)
Accelerations for quadratic functions and symmetric problems
This example illustrates how to exploit symmetry to reduce the dimension of the problem via SymmetricLMO
. Moreover, active set based algorithms can be accelerated by using the specialized structure ActiveSetQuadratic
.
The specific problem we consider here comes from quantum information and some context can be found here. Formally, we want to find the distance between a tensor of size m^N
and the N
-partite local polytope which is defined by its vertices
\[d^{\vec{a}^{(1)}\ldots \vec{a}^{(N)}}_{x_1\ldots x_N}\coloneqq\prod_{n=1}^Na^{(n)}_{x_n}\]
labeled by $\vec{a}^{(n)}=a^{(n)}_1\ldots a^{(n)}_m$ for $n\in[1,N]$, where $a^{(n)}_x=\pm1$. In the bipartite case (N=2
), this polytope is affinely equivalent to the cut polytope.
Import and setup
We first import the necessary packages.
import Combinatorics
import FrankWolfe
import LinearAlgebra
import Tullio
Then we can define our custom LMO, together with the method compute_extreme_point
, which simply enumerates the vertices $d^{\vec{a}^{(1)}}$ defined above. This structure is specialized for the case N=5
and contains pre-allocated fields used to accelerate the enumeration. Note that the output type (full tensor) is quite naive, but this is enough to illustrate the syntax in this toy example.
struct BellCorrelationsLMO{T} <: FrankWolfe.LinearMinimizationOracle
m::Int # size of the tensor
tmp1::Array{T, 1}
tmp2::Array{T, 2}
tmp3::Array{T, 3}
tmp4::Array{T, 4}
end
function FrankWolfe.compute_extreme_point(lmo::BellCorrelationsLMO{T}, A::Array{T, 5}; kwargs...) where {T <: Number}
ax = [ones(T, lmo.m) for n in 1:5]
sc1 = zero(T)
sc2 = one(T)
axm = [zeros(T, lmo.m) for n in 1:5]
scm = typemax(T)
L = 2^lmo.m
aux = zeros(Int, lmo.m)
for λa5 in 0:(L÷2)-1
digits!(aux, λa5, base=2)
ax[5] .= 2aux .- 1
Tullio.@tullio lmo.tmp4[x1, x2, x3, x4] = A[x1, x2, x3, x4, x5] * ax[5][x5]
for λa4 in 0:L-1
digits!(aux, λa4, base=2)
ax[4] .= 2aux .- 1
Tullio.@tullio lmo.tmp3[x1, x2, x3] = lmo.tmp4[x1, x2, x3, x4] * ax[4][x4]
for λa3 in 0:L-1
digits!(aux, λa3, base=2)
ax[3] .= 2aux .- 1
Tullio.@tullio lmo.tmp2[x1, x2] = lmo.tmp3[x1, x2, x3] * ax[3][x3]
for λa2 in 0:L-1
digits!(aux, λa2, base=2)
ax[2] .= 2aux .- 1
LinearAlgebra.mul!(lmo.tmp1, lmo.tmp2, ax[2])
for x1 in 1:lmo.m
ax[1][x1] = lmo.tmp1[x1] > zero(T) ? -one(T) : one(T)
end
sc = LinearAlgebra.dot(ax[1], lmo.tmp1)
if sc < scm
scm = sc
for n in 1:5
axm[n] .= ax[n]
end
end
end
end
end
end
return [axm[1][x1]*axm[2][x2]*axm[3][x3]*axm[4][x4]*axm[5][x5] for x1 in 1:lmo.m, x2 in 1:lmo.m, x3 in 1:lmo.m, x4 in 1:lmo.m, x5 in 1:lmo.m]
end
Then we define our specific instance, coming from a GHZ state measured with measurements forming a regular polygon on the equator of the Bloch sphere. See this article for definitions and references.
function correlation_tensor_GHZ_polygon(::Type{T}, N::Int, m::Int) where {T <: Number}
res = zeros(T, m*ones(Int, N)...)
tab_cos = [cos(x*T(pi)/m) for x in 0:N*m]
tab_cos[abs.(tab_cos) .< Base.rtoldefault(T)] .= zero(T)
for ci in CartesianIndices(res)
res[ci] = tab_cos[sum(ci.I)-N+1]
end
return res
end
T = Float64
verbose = true
max_iteration = 10^4
m = 5
p = 0.23correlation_tensor_GHZ_polygon(T, 5, m)
x0 = zeros(T, size(p))
The objective function is simply $\frac12\|x-p\|_2^2$, which we decompose in different terms for speed.
normp2 = LinearAlgebra.dot(p, p) / 2
f = let p = p, normp2 = normp2
x -> LinearAlgebra.dot(x, x) / 2 - LinearAlgebra.dot(p, x) + normp2
end
grad! = let p = p
(storage, x) -> begin
@inbounds for i in eachindex(x)
storage[i] = x[i] - p[i]
end
end
end
Naive run
If we run the blended pairwise conditional gradient algorithm without modifications, convergence is not reached in 10000 iterations.
lmo_naive = BellCorrelationsLMO{T}(m, zeros(T, m), zeros(T, m, m), zeros(T, m, m, m), zeros(T, m, m, m, m))
as_naive = FrankWolfe.ActiveSet([(one(T), x0)])
@time FrankWolfe.blended_pairwise_conditional_gradient(f, grad!, lmo_naive, as_naive; verbose, lazy=true, line_search=FrankWolfe.Shortstep(one(T)), max_iteration)
Blended Pairwise Conditional Gradient Algorithm.
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: Shortstep EPSILON: 1.0e-7 MAXITERATION: 10000 TYPE: Float64
GRADIENTTYPE: Array{Float64, 5} LAZY: true lazy_tolerance: 2.0
LMO: Main.BellCorrelationsLMO{Float64}
----------------------------------------------------------------------------------------------------------------
Type Iteration Primal Dual Dual Gap Time It/sec #ActiveSet
----------------------------------------------------------------------------------------------------------------
I 1 4.132813e+01 -4.029553e+01 8.162365e+01 0.000000e+00 Inf 1
LD 46 1.102218e+01 -2.888659e+01 3.990877e+01 1.078171e+01 4.266485e+00 46
LD 112 4.160807e+00 -1.560197e+01 1.976278e+01 2.124813e+01 5.271053e+00 88
LD 215 1.198957e+00 -4.345338e+00 5.544295e+00 3.092935e+01 6.951326e+00 126
LD 369 7.209992e-01 -2.020307e+00 2.741306e+00 3.967060e+01 9.301599e+00 160
P 1000 4.811978e-01 -2.260109e+00 2.741306e+00 7.233756e+01 1.382408e+01 289
P 2000 2.153509e-01 -2.525956e+00 2.741306e+00 1.164784e+02 1.717056e+01 451
LD 2126 1.869199e-01 -1.162610e+00 1.349530e+00 1.240793e+02 1.713420e+01 479
P 3000 1.233569e-01 -1.226173e+00 1.349530e+00 1.310373e+02 2.289425e+01 498
P 4000 5.988011e-02 -1.289650e+00 1.349530e+00 1.591784e+02 2.512903e+01 607
LD 4561 2.768136e-02 -3.409421e-01 3.686235e-01 1.728020e+02 2.639437e+01 653
P 5000 1.825337e-02 -3.503701e-01 3.686235e-01 1.733525e+02 2.884296e+01 625
LD 5916 1.173454e-02 -8.843410e-02 1.001686e-01 1.740029e+02 3.399943e+01 625
P 6000 1.147967e-02 -8.868896e-02 1.001686e-01 1.742948e+02 3.442443e+01 625
P 7000 9.885996e-03 -9.028264e-02 1.001686e-01 1.750002e+02 3.999995e+01 625
LD 7903 9.475200e-03 -1.638953e-02 2.586473e-02 1.756650e+02 4.498904e+01 625
P 8000 9.453302e-03 -1.641143e-02 2.586473e-02 1.759657e+02 4.546340e+01 625
P 9000 9.327751e-03 -1.653698e-02 2.586473e-02 1.766691e+02 5.094269e+01 625
P 10000 9.290467e-03 -1.657427e-02 2.586473e-02 1.773698e+02 5.637938e+01 625
Last 10001 9.290427e-03 1.176967e-03 8.113461e-03 1.776883e+02 5.628395e+01 625
----------------------------------------------------------------------------------------------------------------
PP 10001 9.290427e-03 1.176967e-03 8.113461e-03 1.779855e+02 5.618998e+01 625
----------------------------------------------------------------------------------------------------------------
178.220923 seconds (3.29 G allocations: 76.985 GiB, 4.89% gc time, 0.03% compilation time)
Faster active set for quadratic functions
A first acceleration can be obtained by using the active set specialized for the quadratic objective function, whose gradient is here $x-p$, explaining the hessian and linear part provided as arguments. The speedup is obtained by pre-computing some scalar products to quickly obtained, in each iteration, the best and worst atoms currently in the active set.
asq_naive = FrankWolfe.ActiveSetQuadratic([(one(T), x0)], LinearAlgebra.I, -p)
@time FrankWolfe.blended_pairwise_conditional_gradient(f, grad!, lmo_naive, asq_naive; verbose, lazy=true, line_search=FrankWolfe.Shortstep(one(T)), max_iteration)
Blended Pairwise Conditional Gradient Algorithm.
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: Shortstep EPSILON: 1.0e-7 MAXITERATION: 10000 TYPE: Float64
GRADIENTTYPE: Array{Float64, 5} LAZY: true lazy_tolerance: 2.0
LMO: Main.BellCorrelationsLMO{Float64}
----------------------------------------------------------------------------------------------------------------
Type Iteration Primal Dual Dual Gap Time It/sec #ActiveSet
----------------------------------------------------------------------------------------------------------------
I 1 4.132813e+01 -4.029553e+01 8.162365e+01 0.000000e+00 Inf 1
LD 46 1.102218e+01 -2.888659e+01 3.990877e+01 1.082342e+01 4.250043e+00 46
LD 106 4.630016e+00 -1.445646e+01 1.908648e+01 1.899251e+01 5.581146e+00 79
LD 225 1.132318e+00 -4.781394e+00 5.913712e+00 3.044171e+01 7.391174e+00 126
LD 363 7.274406e-01 -2.207406e+00 2.934847e+00 3.870982e+01 9.377465e+00 157
P 1000 4.624255e-01 -2.472421e+00 2.934847e+00 7.539692e+01 1.326314e+01 306
LD 1836 2.172535e-01 -1.224204e+00 1.441458e+00 1.205135e+02 1.523481e+01 486
P 2000 1.982804e-01 -1.243177e+00 1.441458e+00 1.207776e+02 1.655936e+01 484
P 3000 1.217963e-01 -1.319661e+00 1.441458e+00 1.333047e+02 2.250484e+01 520
P 4000 4.862297e-02 -1.392835e+00 1.441458e+00 1.612399e+02 2.480776e+01 625
LD 4311 2.750372e-02 -3.639247e-01 3.914285e-01 1.682647e+02 2.562034e+01 648
P 5000 1.488184e-02 -3.765466e-01 3.914285e-01 1.686278e+02 2.965111e+01 626
LD 5521 1.184656e-02 -8.883781e-02 1.006844e-01 1.687472e+02 3.271759e+01 625
P 6000 1.057020e-02 -9.011417e-02 1.006844e-01 1.690627e+02 3.548979e+01 625
P 7000 9.610191e-03 -9.107418e-02 1.006844e-01 1.692628e+02 4.135581e+01 625
LD 7455 9.459506e-03 -1.662258e-02 2.608208e-02 1.693719e+02 4.401557e+01 625
P 8000 9.366945e-03 -1.671514e-02 2.608208e-02 1.696977e+02 4.714266e+01 625
P 9000 9.300757e-03 -1.678132e-02 2.608208e-02 1.698969e+02 5.297331e+01 625
LD 9578 9.287270e-03 2.510164e-03 6.777106e-03 1.700244e+02 5.633310e+01 625
P 10000 9.282033e-03 2.504927e-03 6.777106e-03 1.703558e+02 5.870067e+01 625
Last 10001 9.282014e-03 3.724653e-03 5.557361e-03 1.706567e+02 5.860302e+01 625
----------------------------------------------------------------------------------------------------------------
PP 10001 9.282014e-03 3.724653e-03 5.557361e-03 1.709555e+02 5.850059e+01 625
----------------------------------------------------------------------------------------------------------------
171.202053 seconds (3.30 G allocations: 77.213 GiB, 5.04% gc time, 0.03% compilation time)
In this small example, the acceleration is quite minimal, but as soon as one of the following conditions is met, significant speedups (factor ten at least) can be expected:
- quite expensive scalar product between atoms, for instance, due to a high dimension (say, more than 10000),
- high number of atoms in the active set (say, more than 1000),
- high number of iterations (say, more than 100000), spending most of the time redistributing the weights in the active set.
Dimension reduction via symmetrization
Permutation of the tensor axes
It is easy to see that our specific instance remains invariant under permutation of the dimensions of the tensor. This means that all computations can be performed in the symmetric subspace, which leads to an important speedup, owing to the reduced dimension (hence reduced size of the final active set and reduced number of iterations).
The way to operate this in the FrankWolfe
package is to use a symmetrized LMO, which basically does the following:
- symmetrize the gradient, which is not necessary here as the gradient remains symmetric throughout the algorithm,
- call the standard LMO,
- symmetrize its output, which amounts to averaging over its orbit with respect to the group considered (here the symmetric group permuting the dimensions of the tensor).
function reynolds_permutedims(atom::Array{T, N}, lmo::BellCorrelationsLMO{T}) where {T <: Number, N}
res = zeros(T, size(atom))
for per in Combinatorics.permutations(1:N)
res .+= permutedims(atom, per)
end
res ./= factorial(N)
return res
end
Note that the second argument lmo
is not used here but could in principle be exploited to obtain a very small speedup by precomputing and storing Combinatorics.permutations(1:N)
in a dedicated field of our custom LMO.
lmo_permutedims = FrankWolfe.SymmetricLMO(lmo_naive, reynolds_permutedims)
asq_permutedims = FrankWolfe.ActiveSetQuadratic([(one(T), x0)], LinearAlgebra.I, -p)
@time FrankWolfe.blended_pairwise_conditional_gradient(f, grad!, lmo_permutedims, asq_permutedims; verbose, lazy=true, line_search=FrankWolfe.Shortstep(one(T)), max_iteration)
Blended Pairwise Conditional Gradient Algorithm.
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: Shortstep EPSILON: 1.0e-7 MAXITERATION: 10000 TYPE: Float64
GRADIENTTYPE: Array{Float64, 5} LAZY: true lazy_tolerance: 2.0
LMO: FrankWolfe.SymmetricLMO{Main.BellCorrelationsLMO{Float64}, typeof(Main.reynolds_permutedims), FrankWolfe.var"#10#11"}
----------------------------------------------------------------------------------------------------------------
Type Iteration Primal Dual Dual Gap Time It/sec #ActiveSet
----------------------------------------------------------------------------------------------------------------
I 1 4.132813e+01 -4.029553e+01 8.162365e+01 0.000000e+00 Inf 1
LD 11 1.153403e+01 -2.734161e+01 3.887563e+01 1.798675e+00 6.115614e+00 9
LD 31 3.285725e+00 -1.376230e+01 1.704803e+01 3.073525e+00 1.008614e+01 13
LD 50 1.646307e+00 -6.869795e+00 8.516102e+00 3.823962e+00 1.307544e+01 15
LD 93 7.245404e-01 -2.896319e+00 3.620859e+00 5.806974e+00 1.601523e+01 20
LD 172 2.996542e-01 -1.378052e+00 1.677706e+00 7.568174e+00 2.272675e+01 24
LD 329 7.534658e-02 -6.003412e-01 6.756878e-01 9.619555e+00 3.420116e+01 29
LD 654 2.017129e-02 -2.325514e-01 2.527227e-01 1.092043e+01 5.988776e+01 32
LD 918 1.120386e-02 -5.331182e-02 6.451568e-02 1.121052e+01 8.188734e+01 26
P 1000 1.035776e-02 -5.415791e-02 6.451568e-02 1.150581e+01 8.691258e+01 26
LD 1324 9.405322e-03 -6.061341e-03 1.546666e-02 1.156681e+01 1.144655e+02 26
LD 1763 9.281060e-03 6.068677e-03 3.212383e-03 1.185873e+01 1.486669e+02 26
P 2000 9.275508e-03 6.063125e-03 3.212383e-03 1.214353e+01 1.646968e+02 26
LD 2213 9.274505e-03 8.598448e-03 6.760579e-04 1.218141e+01 1.816703e+02 26
LD 2646 9.274227e-03 9.121418e-03 1.528092e-04 1.249676e+01 2.117348e+02 26
P 3000 9.274215e-03 9.121406e-03 1.528092e-04 1.281493e+01 2.341020e+02 26
LD 3077 9.274215e-03 9.237360e-03 3.685452e-05 1.282990e+01 2.398305e+02 26
LD 3514 9.274214e-03 9.265220e-03 8.994042e-06 1.314787e+01 2.672676e+02 26
LD 3915 9.274214e-03 9.272267e-03 1.947318e-06 1.345815e+01 2.909017e+02 26
P 4000 9.274214e-03 9.272267e-03 1.947318e-06 1.373295e+01 2.912703e+02 26
LD 4376 9.274214e-03 9.273758e-03 4.562791e-07 1.379790e+01 3.171498e+02 26
LD 4777 9.274214e-03 9.274102e-03 1.122895e-07 1.411101e+01 3.385301e+02 26
P 5000 9.274214e-03 9.274102e-03 1.122895e-07 1.439181e+01 3.474198e+02 26
LD 5151 9.274214e-03 9.274188e-03 2.584730e-08 1.441883e+01 3.572412e+02 26
Last 5151 9.274214e-03 9.274188e-03 2.584730e-08 1.492404e+01 3.451478e+02 26
----------------------------------------------------------------------------------------------------------------
PP 5151 9.274214e-03 9.274188e-03 2.584730e-08 1.516964e+01 3.395599e+02 26
----------------------------------------------------------------------------------------------------------------
15.418026 seconds (274.86 M allocations: 6.612 GiB, 4.65% gc time, 0.38% compilation time)
Now, convergence is reached within 10000 iterations, and the size of the final active set is considerably smaller than before, thanks to the reduced dimension.
Uniqueness pattern
In this specific case, there is a bigger symmetry group that we can exploit. Its action roughly allows us to work in the subspace respecting the structure of the objective point p
, that is, to average over tensor entries that have the same value in p
. Although quite general, this kind of symmetry is not always applicable, and great care has to be taken when using it, in particular, to ensure that there exists a suitable group action whose Reynolds operator corresponds to this averaging procedure. In our current case, the theoretical study enabling this further symmetrization can be found here.
function build_reynolds_unique(p::Array{T, N}) where {T <: Number, N}
ptol = round.(p; digits=8)
ptol[ptol .== zero(T)] .= zero(T) # transform -0.0 into 0.0 as isequal(0.0, -0.0) is false
uniquetol = unique(ptol[:])
indices = [ptol .== u for u in uniquetol]
return function(A::Array{T, N}, lmo)
res = zeros(T, size(A))
for ind in indices
@view(res[ind]) .= sum(A[ind]) / sum(ind) # average over ind
end
return res
end
end
lmo_unique = FrankWolfe.SymmetricLMO(lmo_naive, build_reynolds_unique(p))
asq_unique = FrankWolfe.ActiveSetQuadratic([(one(T), x0)], LinearAlgebra.I, -p)
@time FrankWolfe.blended_pairwise_conditional_gradient(f, grad!, lmo_unique, asq_unique; verbose, lazy=true, line_search=FrankWolfe.Shortstep(one(T)), max_iteration)
Blended Pairwise Conditional Gradient Algorithm.
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: Shortstep EPSILON: 1.0e-7 MAXITERATION: 10000 TYPE: Float64
GRADIENTTYPE: Array{Float64, 5} LAZY: true lazy_tolerance: 2.0
LMO: FrankWolfe.SymmetricLMO{Main.BellCorrelationsLMO{Float64}, Main.var"#43#45"{5, Float64, Vector{BitArray{5}}}, FrankWolfe.var"#10#11"}
----------------------------------------------------------------------------------------------------------------
Type Iteration Primal Dual Dual Gap Time It/sec #ActiveSet
----------------------------------------------------------------------------------------------------------------
I 1 4.132813e+01 -4.029553e+01 8.162365e+01 0.000000e+00 Inf 1
LD 4 2.991558e+00 -4.896575e+00 7.888134e+00 2.710608e-01 1.475684e+01 3
LD 7 4.010409e-01 -3.282121e+00 3.683161e+00 5.235709e-01 1.336973e+01 3
LD 15 1.802237e-01 -4.675134e-01 6.477370e-01 1.540416e+00 9.737627e+00 5
LD 32 2.002807e-02 -1.556256e-01 1.756537e-01 2.267057e+00 1.411522e+01 5
LD 72 1.368120e-02 -4.123301e-02 5.491421e-02 2.497637e+00 2.882725e+01 3
LD 130 9.506383e-03 -9.057423e-03 1.856381e-02 3.008074e+00 4.321702e+01 4
LD 145 9.308486e-03 1.142443e-03 8.166042e-03 3.226554e+00 4.493959e+01 4
LD 160 9.278954e-03 6.339760e-03 2.939194e-03 3.464956e+00 4.617663e+01 4
LD 178 9.275038e-03 8.020945e-03 1.254093e-03 3.743968e+00 4.754314e+01 4
LD 193 9.274328e-03 8.822599e-03 4.517287e-04 3.955830e+00 4.878875e+01 4
LD 211 9.274234e-03 9.080960e-03 1.932742e-04 4.197688e+00 5.026577e+01 4
LD 226 9.274217e-03 9.204592e-03 6.962503e-05 4.439777e+00 5.090346e+01 4
LD 244 9.274214e-03 9.244275e-03 2.993943e-05 4.691582e+00 5.200804e+01 4
LD 259 9.274214e-03 9.263418e-03 1.079580e-05 4.947783e+00 5.234667e+01 4
LD 277 9.274214e-03 9.269571e-03 4.642816e-06 5.186889e+00 5.340388e+01 4
LD 292 9.274214e-03 9.272535e-03 1.678918e-06 5.444781e+00 5.362934e+01 4
LD 307 9.274214e-03 9.273611e-03 6.027276e-07 5.679246e+00 5.405647e+01 4
LD 323 9.274214e-03 9.273974e-03 2.398615e-07 5.920923e+00 5.455230e+01 4
LD 338 9.274214e-03 9.274110e-03 1.036546e-07 6.186729e+00 5.463307e+01 4
LD 351 9.274214e-03 9.274168e-03 4.575080e-08 6.412647e+00 5.473558e+01 4
Last 351 9.274214e-03 9.274168e-03 4.575080e-08 6.923227e+00 5.069890e+01 4
----------------------------------------------------------------------------------------------------------------
PP 351 9.274214e-03 9.274168e-03 4.575080e-08 7.140386e+00 4.915700e+01 4
----------------------------------------------------------------------------------------------------------------
7.351973 seconds (142.16 M allocations: 3.339 GiB, 4.95% gc time, 0.72% compilation time)
Reduction of the memory footprint of the iterate
In the previous run, the dimension reduction is mathematically exploited to accelerate the algorithm, but it is not used to effectively work in a subspace of reduced dimension. Indeed, the iterate, although symmetric, was still a full tensor. As a last example of the speedup obtainable through symmetry reduction, we show how to map the computations into a space whose physical dimension is also reduced during the algorithm. This makes all in-place operations marginally faster, which can lead, in bigger instances, to significant accelerations, especially for active set based algorithms in the regime where many lazy iterations are performed. We refer to the example symmetric.jl
for a small benchmark with symmetric matrices.
function build_reduce_inflate(p::Array{T, N}) where {T <: Number, N}
ptol = round.(p; digits=8)
ptol[ptol .== zero(T)] .= zero(T) # transform -0.0 into 0.0 as isequal(0.0, -0.0) is false
uniquetol = unique(ptol[:])
dim = length(uniquetol) # reduced dimension
indices = [ptol .== u for u in uniquetol]
mul = [sum(ind) for ind in indices] # multiplicities, used to have matching scalar products
sqmul = sqrt.(mul) # precomputed for speed
return function(A::Array{T, N}, lmo)
vec = zeros(T, dim)
for (i, ind) in enumerate(indices)
vec[i] = sum(A[ind]) / sqmul[i]
end
return FrankWolfe.SymmetricArray(A, vec)
end, function(x::FrankWolfe.SymmetricArray, lmo)
for (i, ind) in enumerate(indices)
@view(x.data[ind]) .= x.vec[i] / sqmul[i]
end
return x.data
end
end
reduce, inflate = build_reduce_inflate(p)
p_reduce = reduce(p, nothing)
x0_reduce = reduce(x0, nothing)
f_reduce = let p_reduce = p_reduce, normp2 = normp2
x -> LinearAlgebra.dot(x, x) / 2 - LinearAlgebra.dot(p_reduce, x) + normp2
end
grad_reduce! = let p_reduce = p_reduce
(storage, x) -> begin
@inbounds for i in eachindex(x)
storage[i] = x[i] - p_reduce[i]
end
end
end
Note that the objective function and its gradient have to be explicitly rewritten. In this simple example, their shape remains unchanged, but in general this may need some reformulation, which falls to the user.
lmo_reduce = FrankWolfe.SymmetricLMO(lmo_naive, reduce, inflate)
asq_reduce = FrankWolfe.ActiveSetQuadratic([(one(T), x0_reduce)], LinearAlgebra.I, -p_reduce)
@time FrankWolfe.blended_pairwise_conditional_gradient(f_reduce, grad_reduce!, lmo_reduce, asq_reduce; verbose, lazy=true, line_search=FrankWolfe.Shortstep(one(T)), max_iteration)
Blended Pairwise Conditional Gradient Algorithm.
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: Shortstep EPSILON: 1.0e-7 MAXITERATION: 10000 TYPE: Float64
GRADIENTTYPE: FrankWolfe.SymmetricArray{false, Float64, Array{Float64, 5}, Vector{Float64}} LAZY: true lazy_tolerance: 2.0
LMO: FrankWolfe.SymmetricLMO{Main.BellCorrelationsLMO{Float64}, Main.var"#48#52"{5, Float64, Vector{Float64}, Vector{BitArray{5}}, Int64}, Main.var"#49#53"{Vector{Float64}, Vector{BitArray{5}}}}
----------------------------------------------------------------------------------------------------------------
Type Iteration Primal Dual Dual Gap Time It/sec #ActiveSet
----------------------------------------------------------------------------------------------------------------
I 1 4.132813e+01 -4.029553e+01 8.162365e+01 0.000000e+00 Inf 1
LD 4 2.991558e+00 -4.896575e+00 7.888134e+00 3.038019e-01 1.316648e+01 3
LD 7 4.010409e-01 -3.282121e+00 3.683161e+00 5.546945e-01 1.261956e+01 3
LD 16 1.663895e-01 -3.019507e-01 4.683402e-01 1.524055e+00 1.049831e+01 5
LD 30 1.909390e-02 -6.502115e-02 8.411505e-02 2.024959e+00 1.481511e+01 4
LD 131 9.738911e-03 -1.106636e-02 2.080527e-02 2.578751e+00 5.079980e+01 4
LD 155 9.318517e-03 5.789313e-03 3.529204e-03 2.830931e+00 5.475231e+01 4
LD 207 9.275282e-03 8.691635e-03 5.836471e-04 3.073480e+00 6.735036e+01 4
LD 263 9.274251e-03 9.174862e-03 9.938911e-05 3.309358e+00 7.947161e+01 4
LD 320 9.274215e-03 9.255732e-03 1.848329e-05 3.554988e+00 9.001438e+01 4
LD 376 9.274214e-03 9.271193e-03 3.021432e-06 3.796650e+00 9.903469e+01 4
LD 427 9.274214e-03 9.273665e-03 5.489460e-07 4.031752e+00 1.059093e+02 4
LD 483 9.274214e-03 9.274124e-03 9.004990e-08 4.284591e+00 1.127295e+02 4
Last 483 9.274214e-03 9.274124e-03 9.004990e-08 4.768426e+00 1.012913e+02 4
----------------------------------------------------------------------------------------------------------------
PP 483 9.274214e-03 9.274124e-03 9.004990e-08 5.028572e+00 9.605113e+01 4
----------------------------------------------------------------------------------------------------------------
5.270069 seconds (99.55 M allocations: 2.339 GiB, 5.57% gc time, 1.14% compilation time)
This page was generated using Literate.jl.