Skip to content

Commit

Permalink
format
Browse files Browse the repository at this point in the history
  • Loading branch information
matbesancon committed Oct 24, 2024
1 parent 71291c7 commit 0330a48
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 116 deletions.
32 changes: 23 additions & 9 deletions examples/blended_pairwise_with_direct.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ as_quad = FrankWolfe.ActiveSetQuadratic([(1.0, copy(x00))], 2 * LinearAlgebra.I,
callback=build_callback(trajectoryBPCG_quadratic),
);

as_quad = FrankWolfe.ActiveSetQuadratic(
[(1.0, copy(x00))],
2 * LinearAlgebra.I, -2xp,
)
as_quad = FrankWolfe.ActiveSetQuadratic([(1.0, copy(x00))], 2 * LinearAlgebra.I, -2xp)

# with quadratic active set
trajectoryBPCG_quadratic_as = []
Expand All @@ -95,7 +92,8 @@ trajectoryBPCG_quadratic_as = []

as_quad_direct = FrankWolfe.ActiveSetQuadraticLinearSolve(
[(1.0, copy(x00))],
2 * LinearAlgebra.I, -2xp,
2 * LinearAlgebra.I,
-2xp,
MOI.instantiate(MOI.OptimizerWithAttributes(HiGHS.Optimizer, MOI.Silent() => true)),
)

Expand All @@ -114,7 +112,8 @@ trajectoryBPCG_quadratic_direct = []

as_quad_direct_generic = FrankWolfe.ActiveSetQuadraticLinearSolve(
[(1.0, copy(x00))],
2 * Diagonal(ones(length(xp))), -2xp,
2 * Diagonal(ones(length(xp))),
-2xp,
MOI.instantiate(MOI.OptimizerWithAttributes(HiGHS.Optimizer, MOI.Silent() => true)),
)

Expand All @@ -133,7 +132,8 @@ trajectoryBPCG_quadratic_direct_generic = []

as_quad_direct_basic_as = FrankWolfe.ActiveSetQuadraticLinearSolve(
FrankWolfe.ActiveSet([1.0], [copy(x00)], collect(x00)),
2 * LinearAlgebra.I, -2xp,
2 * LinearAlgebra.I,
-2xp,
MOI.instantiate(MOI.OptimizerWithAttributes(HiGHS.Optimizer, MOI.Silent() => true)),
)

Expand All @@ -153,8 +153,22 @@ trajectoryBPCG_quadratic_noqas = []


# Update the data and labels for plotting
data_trajectories = [trajectoryBPCG_standard, trajectoryBPCG_quadratic, trajectoryBPCG_quadratic_as, trajectoryBPCG_quadratic_direct, trajectoryBPCG_quadratic_direct_generic, trajectoryBPCG_quadratic_noqas]
labels_trajectories = ["BPCG (Standard)", "BPCG (Specific Direct)", "AS_Quad", "Reloaded", "Reloaded_generic", "Reloaded_noqas"]
data_trajectories = [
trajectoryBPCG_standard,
trajectoryBPCG_quadratic,
trajectoryBPCG_quadratic_as,
trajectoryBPCG_quadratic_direct,
trajectoryBPCG_quadratic_direct_generic,
trajectoryBPCG_quadratic_noqas,
]
labels_trajectories = [
"BPCG (Standard)",
"BPCG (Specific Direct)",
"AS_Quad",
"Reloaded",
"Reloaded_generic",
"Reloaded_noqas",
]

# Plot trajectories
plot_trajectories(data_trajectories, labels_trajectories, xscalelog=false)
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,13 @@ x, v, primal, dual_gap, _ = FrankWolfe.blended_pairwise_conditional_gradient(
);


dataSparsity = [trajectoryBPCG_standard, trajectoryBPCG_quadratic_automatic, trajectoryBPCG_quadratic_automatic_standard]
dataSparsity = [
trajectoryBPCG_standard,
trajectoryBPCG_quadratic_automatic,
trajectoryBPCG_quadratic_automatic_standard,
]
labelSparsity = ["BPCG (Standard)", "AS_Quad", "AS_Standard"]


# Plot trajectories
plot_trajectories(dataSparsity, labelSparsity,xscalelog=false)
plot_trajectories(dataSparsity, labelSparsity, xscalelog=false)
5 changes: 4 additions & 1 deletion examples/blended_pairwise_with_sparsify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ trajectoryBPCG_standard = []
);

trajectoryBPCG_as_sparse = []
active_set_sparse = FrankWolfe.ActiveSetSparsifier(FrankWolfe.ActiveSet([1.0], [x00], similar(x00)), HiGHS.Optimizer())
active_set_sparse = FrankWolfe.ActiveSetSparsifier(
FrankWolfe.ActiveSet([1.0], [x00], similar(x00)),
HiGHS.Optimizer(),
)

@time x, v, primal, dual_gap, _ = FrankWolfe.blended_pairwise_conditional_gradient(
f,
Expand Down
179 changes: 157 additions & 22 deletions src/active_set_quadratic_direct_solve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ The `weight`, `atoms`, and `x` fields should only be accessed to read and are ef
The structure also contains a scheduler struct which is called with the `should_solve_lp` function.
To define a new frequency at which the LP should be solved, one can define another scheduler struct and implement the corresponding method.
"""
struct ActiveSetQuadraticLinearSolve{AT, R <: Real, IT, H, BT, OT <: MOI.AbstractOptimizer, AS <: AbstractActiveSet, SF} <: AbstractActiveSet{AT,R,IT}
struct ActiveSetQuadraticLinearSolve{
AT,
R<:Real,
IT,
H,
BT,
OT<:MOI.AbstractOptimizer,
AS<:AbstractActiveSet,
SF,
} <: AbstractActiveSet{AT,R,IT}
weights::Vector{R}
atoms::Vector{AT}
x::IT
Expand All @@ -33,7 +42,12 @@ end
Creates an ActiveSetQuadraticLinearSolve by computing the Hessian and linear term from `grad!`.
"""
function ActiveSetQuadraticLinearSolve(tuple_values::Vector{Tuple{R,AT}}, grad!::Function, lp_optimizer; scheduler=LogScheduler()) where {AT,R}
function ActiveSetQuadraticLinearSolve(
tuple_values::Vector{Tuple{R,AT}},
grad!::Function,
lp_optimizer;
scheduler=LogScheduler(),
) where {AT,R}
A, b = detect_quadratic_function(grad!, tuple_values[1][2])
return ActiveSetQuadraticLinearSolve(tuple_values, A, b, lp_optimizer, scheduler=scheduler)
end
Expand All @@ -43,45 +57,149 @@ end
Creates an `ActiveSetQuadraticLinearSolve` from the given Hessian `A`, linear term `b` and `lp_optimizer` by creating an inner `ActiveSetQuadratic` active set.
"""
function ActiveSetQuadraticLinearSolve(tuple_values::Vector{Tuple{R,AT}}, A::H, b, lp_optimizer; scheduler=LogScheduler()) where {AT,R,H}
function ActiveSetQuadraticLinearSolve(
tuple_values::Vector{Tuple{R,AT}},
A::H,
b,
lp_optimizer;
scheduler=LogScheduler(),
) where {AT,R,H}
inner_as = ActiveSetQuadratic(tuple_values, A, b)
return ActiveSetQuadraticLinearSolve(inner_as.weights, inner_as.atoms, inner_as.x, inner_as.A, inner_as.b, inner_as, lp_optimizer, scheduler, Ref(0))
return ActiveSetQuadraticLinearSolve(
inner_as.weights,
inner_as.atoms,
inner_as.x,
inner_as.A,
inner_as.b,
inner_as,
lp_optimizer,
scheduler,
Ref(0),
)
end

function ActiveSetQuadraticLinearSolve(inner_as::AbstractActiveSet, A, b, lp_optimizer; scheduler=LogScheduler())
as = ActiveSetQuadraticLinearSolve(inner_as.weights, inner_as.atoms, inner_as.x, A, b, inner_as, lp_optimizer, scheduler, Ref(0))
function ActiveSetQuadraticLinearSolve(
inner_as::AbstractActiveSet,
A,
b,
lp_optimizer;
scheduler=LogScheduler(),
)
as = ActiveSetQuadraticLinearSolve(
inner_as.weights,
inner_as.atoms,
inner_as.x,
A,
b,
inner_as,
lp_optimizer,
scheduler,
Ref(0),
)
compute_active_set_iterate!(as)
return as
end

function ActiveSetQuadraticLinearSolve(inner_as::AbstractActiveSet, A::LinearAlgebra.UniformScaling, b, lp_optimizer; scheduler=LogScheduler())
as = ActiveSetQuadraticLinearSolve(inner_as.weights, inner_as.atoms, inner_as.x, A, b, inner_as, lp_optimizer, scheduler, Ref(0))
function ActiveSetQuadraticLinearSolve(
inner_as::AbstractActiveSet,
A::LinearAlgebra.UniformScaling,
b,
lp_optimizer;
scheduler=LogScheduler(),
)
as = ActiveSetQuadraticLinearSolve(
inner_as.weights,
inner_as.atoms,
inner_as.x,
A,
b,
inner_as,
lp_optimizer,
scheduler,
Ref(0),
)
compute_active_set_iterate!(as)
return as
end

function ActiveSetQuadraticLinearSolve(inner_as::AbstractActiveSet, grad!::Function, lp_optimizer; scheduler=LogScheduler())
function ActiveSetQuadraticLinearSolve(
inner_as::AbstractActiveSet,
grad!::Function,
lp_optimizer;
scheduler=LogScheduler(),
)
A, b = detect_quadratic_function(grad!, inner_as.atoms[1])
return ActiveSetQuadraticLinearSolve(inner_as, A, b, lp_optimizer; scheduler=scheduler)
end

function ActiveSetQuadraticLinearSolve{AT,R}(tuple_values::Vector{<:Tuple{<:Number,<:Any}}, grad!::Function, lp_optimizer; scheduler=LogScheduler()) where {AT,R}
function ActiveSetQuadraticLinearSolve{AT,R}(
tuple_values::Vector{<:Tuple{<:Number,<:Any}},
grad!::Function,
lp_optimizer;
scheduler=LogScheduler(),
) where {AT,R}
A, b = detect_quadratic_function(grad!, tuple_values[1][2])
return ActiveSetQuadraticLinearSolve{AT,R}(tuple_values, A, b, lp_optimizer; scheduler=scheduler)
return ActiveSetQuadraticLinearSolve{AT,R}(
tuple_values,
A,
b,
lp_optimizer;
scheduler=scheduler,
)
end

function ActiveSetQuadraticLinearSolve{AT,R}(tuple_values::Vector{<:Tuple{<:Number,<:Any}}, A::H, b, lp_optimizer; scheduler=LogScheduler()) where {AT,R,H}
function ActiveSetQuadraticLinearSolve{AT,R}(
tuple_values::Vector{<:Tuple{<:Number,<:Any}},
A::H,
b,
lp_optimizer;
scheduler=LogScheduler(),
) where {AT,R,H}
inner_as = ActiveSetQuadratic{AT,R}(tuple_values, A, b)
as = ActiveSetQuadraticLinearSolve{AT,R,typeof(x),H}(inner_as.weights, inner_as.atoms, inner_as.x, A, b, inner_as, lp_optimizer, scheduler, Ref(0))
as = ActiveSetQuadraticLinearSolve{AT,R,typeof(x),H}(
inner_as.weights,
inner_as.atoms,
inner_as.x,
A,
b,
inner_as,
lp_optimizer,
scheduler,
Ref(0),
)
compute_active_set_iterate!(as)
return as
end

function ActiveSetQuadraticLinearSolve(tuple_values::Vector{Tuple{R,AT}}, A::UniformScaling, b, lp_optimizer; scheduler=LogScheduler()) where {AT,R}
return ActiveSetQuadraticLinearSolve(tuple_values, Identity(A.λ), b, lp_optimizer; scheduler=scheduler)
function ActiveSetQuadraticLinearSolve(
tuple_values::Vector{Tuple{R,AT}},
A::UniformScaling,
b,
lp_optimizer;
scheduler=LogScheduler(),
) where {AT,R}
return ActiveSetQuadraticLinearSolve(
tuple_values,
Identity(A.λ),
b,
lp_optimizer;
scheduler=scheduler,
)
end
function ActiveSetQuadraticLinearSolve{AT,R}(tuple_values::Vector{<:Tuple{<:Number,<:Any}}, A::UniformScaling, b, lp_optimizer; scheduler=LogScheduler()) where {AT,R}
return ActiveSetQuadraticLinearSolve{AT,R}(tuple_values, Identity(A.λ), b, lp_optimizer; scheduler=scheduler)
function ActiveSetQuadraticLinearSolve{AT,R}(
tuple_values::Vector{<:Tuple{<:Number,<:Any}},
A::UniformScaling,
b,
lp_optimizer;
scheduler=LogScheduler(),
) where {AT,R}
return ActiveSetQuadraticLinearSolve{AT,R}(
tuple_values,
Identity(A.λ),
b,
lp_optimizer;
scheduler=scheduler,
)
end

# all mutating functions are delegated to the inner active set
Expand All @@ -94,15 +212,27 @@ Base.empty!(as::ActiveSetQuadraticLinearSolve) = empty!(as.active_set)

function active_set_update!(
as::ActiveSetQuadraticLinearSolve{AT,R},
lambda, atom, renorm=true, idx=nothing;
lambda,
atom,
renorm=true,
idx=nothing;
weight_purge_threshold=weight_purge_threshold_default(R),
add_dropped_vertices=false,
vertex_storage=nothing,
) where {AT,R}
if idx === nothing
idx = find_atom(as, atom)
end
active_set_update!(as.active_set, lambda, atom, renorm, idx; weight_purge_threshold=weight_purge_threshold, add_dropped_vertices=add_dropped_vertices, vertex_storage=vertex_storage)
active_set_update!(
as.active_set,
lambda,
atom,
renorm,
idx;
weight_purge_threshold=weight_purge_threshold,
add_dropped_vertices=add_dropped_vertices,
vertex_storage=vertex_storage,
)
# new atom introduced, we can solve the auxiliary LP
if idx < 0
as.counter[] += 1
Expand Down Expand Up @@ -131,7 +261,9 @@ end
Solves the auxiliary LP over the current active set.
The method is specialized by type `H` of the Hessian matrix `A`.
"""
function solve_quadratic_activeset_lp!(as::ActiveSetQuadraticLinearSolve{AT, R, IT, <: AbstractMatrix}) where {AT, R, IT}
function solve_quadratic_activeset_lp!(
as::ActiveSetQuadraticLinearSolve{AT,R,IT,<:AbstractMatrix},
) where {AT,R,IT}
nv = length(as)
o = as.lp_optimizer
MOI.empty!(o)
Expand Down Expand Up @@ -178,7 +310,9 @@ end

# special case of scaled identity Hessian

function solve_quadratic_activeset_lp!(as::ActiveSetQuadraticLinearSolve{AT, R, IT, <: Union{Identity, LinearAlgebra.UniformScaling}}) where {AT, R, IT}
function solve_quadratic_activeset_lp!(
as::ActiveSetQuadraticLinearSolve{AT,R,IT,<:Union{Identity,LinearAlgebra.UniformScaling}},
) where {AT,R,IT}
hessian_scaling = as.A.λ
nv = length(as)
o = as.lp_optimizer
Expand Down Expand Up @@ -233,7 +367,8 @@ struct LogScheduler{T}
last_solve_counter::Base.RefValue{Int}
end

LogScheduler(; start_time=20, scaling_factor=1.5, max_interval=1000) = LogScheduler(start_time, scaling_factor, max_interval, Ref(start_time), Ref(0))
LogScheduler(; start_time=20, scaling_factor=1.5, max_interval=1000) =
LogScheduler(start_time, scaling_factor, max_interval, Ref(start_time), Ref(0))

function should_solve_lp(as::ActiveSetQuadraticLinearSolve, scheduler::LogScheduler)
if as.counter[] - scheduler.last_solve_counter[] >= scheduler.current_interval[]
Expand Down
Loading

0 comments on commit 0330a48

Please sign in to comment.