From 0330a48abc587727eb9982e65ff72ed4999885d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Thu, 24 Oct 2024 23:28:36 +0200 Subject: [PATCH] format --- examples/blended_pairwise_with_direct.jl | 32 +++- ...wise_with_direct_non-standard-quadratic.jl | 8 +- examples/blended_pairwise_with_sparsify.jl | 5 +- src/active_set_quadratic_direct_solve.jl | 179 +++++++++++++++--- src/active_set_sparsifier.jl | 148 +++++++-------- src/blended_pairwise.jl | 1 - src/callback.jl | 3 +- src/defs.jl | 2 - test/quadratic_lp_active_set.jl | 9 +- 9 files changed, 271 insertions(+), 116 deletions(-) diff --git a/examples/blended_pairwise_with_direct.jl b/examples/blended_pairwise_with_direct.jl index 1304749d2..9a30bde76 100644 --- a/examples/blended_pairwise_with_direct.jl +++ b/examples/blended_pairwise_with_direct.jl @@ -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 = [] @@ -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)), ) @@ -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)), ) @@ -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)), ) @@ -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) diff --git a/examples/blended_pairwise_with_direct_non-standard-quadratic.jl b/examples/blended_pairwise_with_direct_non-standard-quadratic.jl index 017f1c866..d2a587a0b 100644 --- a/examples/blended_pairwise_with_direct_non-standard-quadratic.jl +++ b/examples/blended_pairwise_with_direct_non-standard-quadratic.jl @@ -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) diff --git a/examples/blended_pairwise_with_sparsify.jl b/examples/blended_pairwise_with_sparsify.jl index d3b31ebe7..6d42b7de4 100644 --- a/examples/blended_pairwise_with_sparsify.jl +++ b/examples/blended_pairwise_with_sparsify.jl @@ -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, diff --git a/src/active_set_quadratic_direct_solve.jl b/src/active_set_quadratic_direct_solve.jl index 0d71db82f..fef53a077 100644 --- a/src/active_set_quadratic_direct_solve.jl +++ b/src/active_set_quadratic_direct_solve.jl @@ -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 @@ -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 @@ -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 @@ -94,7 +212,10 @@ 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, @@ -102,7 +223,16 @@ function active_set_update!( 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 @@ -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) @@ -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 @@ -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[] diff --git a/src/active_set_sparsifier.jl b/src/active_set_sparsifier.jl index 3759adf88..6bb523217 100644 --- a/src/active_set_sparsifier.jl +++ b/src/active_set_sparsifier.jl @@ -1,35 +1,35 @@ struct ActiveSetSparsifier{AT,R,IT,AS<:AbstractActiveSet{AT,R,IT},OT<:MOI.AbstractOptimizer} <: - AbstractActiveSet{AT,R,IT} - active_set::AS - weights::Vector{R} - atoms::Vector{AT} - x::IT - optimizer::OT - minimum_vertices::Int - solve_frequency::Int - counter::Base.RefValue{Int} + AbstractActiveSet{AT,R,IT} + active_set::AS + weights::Vector{R} + atoms::Vector{AT} + x::IT + optimizer::OT + minimum_vertices::Int + solve_frequency::Int + counter::Base.RefValue{Int} end function ActiveSetSparsifier( - active_set::AbstractActiveSet, - optimizer::MOI.AbstractOptimizer; - minimum_vertices=50, - solve_frequency=50, + active_set::AbstractActiveSet, + optimizer::MOI.AbstractOptimizer; + minimum_vertices=50, + solve_frequency=50, ) - return ActiveSetSparsifier( - active_set, - active_set.weights, - active_set.atoms, - active_set.x, - optimizer, - minimum_vertices, - solve_frequency, - Ref(0), - ) + return ActiveSetSparsifier( + active_set, + active_set.weights, + active_set.atoms, + active_set.x, + optimizer, + minimum_vertices, + solve_frequency, + Ref(0), + ) end function Base.push!(as::ActiveSetSparsifier, (λ, a)) - return push!(as.active_set, (λ, a)) + return push!(as.active_set, (λ, a)) end Base.deleteat!(as::ActiveSetSparsifier, idx::Int) = deleteat!(as.active_set, idx) @@ -37,60 +37,60 @@ Base.deleteat!(as::ActiveSetSparsifier, idx::Int) = deleteat!(as.active_set, idx Base.empty!(as::ActiveSetSparsifier) = empty!(as.active_set) function active_set_update!( - as::ActiveSetSparsifier{AS,OT,AT,R,IT}, - lambda, - atom, - renorm=true, - idx=nothing; - kwargs..., + as::ActiveSetSparsifier{AS,OT,AT,R,IT}, + lambda, + atom, + renorm=true, + idx=nothing; + kwargs..., ) where {AS,OT,AT,R,IT} - active_set_update!(as.active_set, lambda, atom, renorm, idx; kwargs...) - n = length(as) - as.counter[] += 1 - if n > as.minimum_vertices && mod(as.counter[], as.solve_frequency) == 0 - # sparsifying active set - MOI.empty!(as.optimizer) - x0 = as.active_set.x - λ = MOI.add_variables(as.optimizer, n) - # λ ∈ Δ_n ⇔ λ ≥ 0, ∑ λ == 1 - MOI.add_constraint.(as.optimizer, λ, MOI.GreaterThan(0.0)) - MOI.add_constraint(as.optimizer, sum(λ; init=0.0), MOI.EqualTo(1.0)) - x_sum = 0 * as.active_set.atoms[1] - for (idx, atom) in enumerate(as.active_set.atoms) - x_sum += λ[idx] * atom - end - for idx in eachindex(x_sum) - MOI.add_constraint(as.optimizer, x_sum[idx], MOI.EqualTo(x0[idx])) - end - # Set a dummy objective (minimize ∑λ) - dummy_objective = sum(λ; init=0.0) - MOI.set(as.optimizer, MOI.ObjectiveFunction{typeof(dummy_objective)}(), dummy_objective) - MOI.set(as.optimizer, MOI.ObjectiveSense(), MOI.MIN_SENSE) - MOI.optimize!(as.optimizer) - if MOI.get(as.optimizer, MOI.TerminationStatus()) in - (MOI.OPTIMAL, MOI.FEASIBLE_POINT, MOI.ALMOST_OPTIMAL) - indices_to_remove = Int[] - new_weights = R[] - for idx in eachindex(λ) - weight_value = MOI.get(as.optimizer, MOI.VariablePrimal(), λ[idx]) - if weight_value <= sqrt(weight_purge_threshold_default(typeof(weight_value))) - push!(indices_to_remove, idx) - else - push!(new_weights, weight_value) - end - end - deleteat!(as.active_set.atoms, indices_to_remove) - deleteat!(as.active_set.weights, indices_to_remove) - @assert length(as) == length(new_weights) - as.active_set.weights .= new_weights - active_set_renormalize!(as) - end - end - return as + active_set_update!(as.active_set, lambda, atom, renorm, idx; kwargs...) + n = length(as) + as.counter[] += 1 + if n > as.minimum_vertices && mod(as.counter[], as.solve_frequency) == 0 + # sparsifying active set + MOI.empty!(as.optimizer) + x0 = as.active_set.x + λ = MOI.add_variables(as.optimizer, n) + # λ ∈ Δ_n ⇔ λ ≥ 0, ∑ λ == 1 + MOI.add_constraint.(as.optimizer, λ, MOI.GreaterThan(0.0)) + MOI.add_constraint(as.optimizer, sum(λ; init=0.0), MOI.EqualTo(1.0)) + x_sum = 0 * as.active_set.atoms[1] + for (idx, atom) in enumerate(as.active_set.atoms) + x_sum += λ[idx] * atom + end + for idx in eachindex(x_sum) + MOI.add_constraint(as.optimizer, x_sum[idx], MOI.EqualTo(x0[idx])) + end + # Set a dummy objective (minimize ∑λ) + dummy_objective = sum(λ; init=0.0) + MOI.set(as.optimizer, MOI.ObjectiveFunction{typeof(dummy_objective)}(), dummy_objective) + MOI.set(as.optimizer, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.optimize!(as.optimizer) + if MOI.get(as.optimizer, MOI.TerminationStatus()) in + (MOI.OPTIMAL, MOI.FEASIBLE_POINT, MOI.ALMOST_OPTIMAL) + indices_to_remove = Int[] + new_weights = R[] + for idx in eachindex(λ) + weight_value = MOI.get(as.optimizer, MOI.VariablePrimal(), λ[idx]) + if weight_value <= sqrt(weight_purge_threshold_default(typeof(weight_value))) + push!(indices_to_remove, idx) + else + push!(new_weights, weight_value) + end + end + deleteat!(as.active_set.atoms, indices_to_remove) + deleteat!(as.active_set.weights, indices_to_remove) + @assert length(as) == length(new_weights) + as.active_set.weights .= new_weights + active_set_renormalize!(as) + end + end + return as end active_set_renormalize!(as::ActiveSetSparsifier) = active_set_renormalize!(as.active_set) active_set_argmin(as::ActiveSetSparsifier, direction) = active_set_argmin(as.active_set, direction) active_set_argminmax(as::ActiveSetSparsifier, direction; Φ=0.5) = - active_set_argminmax(as.active_set, direction; Φ=Φ) \ No newline at end of file + active_set_argminmax(as.active_set, direction; Φ=Φ) diff --git a/src/blended_pairwise.jl b/src/blended_pairwise.jl index 40435d946..a42862063 100644 --- a/src/blended_pairwise.jl +++ b/src/blended_pairwise.jl @@ -290,7 +290,6 @@ function blended_pairwise_conditional_gradient( step_type = ST_REGULAR end vertex_taken = v - # short circuit for quadratic case dual_gap = fast_dot(gradient, x) - fast_dot(gradient, v) # if we are about to exit, compute dual_gap with the cleaned-up x if dual_gap ≤ epsilon diff --git a/src/callback.jl b/src/callback.jl index d796401db..71842a548 100644 --- a/src/callback.jl +++ b/src/callback.jl @@ -95,8 +95,7 @@ function make_print_callback_extension(callback, print_iter, headers, format_str elseif state.t == 1 || mod(state.t, print_iter) == 0 || state.step_type == ST_DUALSTEP || - state.step_type == ST_LAST || - state.step_type == ST_DIRECT + state.step_type == ST_LAST if state.t == 1 print("\e[u\e[3A") # Move to end of upper horizontal line line = "-"^compute_line_length(format_string) diff --git a/src/defs.jl b/src/defs.jl index f1205f031..85052b35e 100644 --- a/src/defs.jl +++ b/src/defs.jl @@ -19,7 +19,6 @@ struct OutplaceEmphasis <: MemoryEmphasis end ST_AWAY = 6 ST_PAIRWISE = 7 ST_DROP = 8 - ST_DIRECT = 9 ST_SIMPLEXDESCENT = 101 ST_LAST = 1000 ST_POSTPROCESS = 1001 @@ -34,7 +33,6 @@ const steptype_string = ( ST_AWAY="A", ST_PAIRWISE="P", ST_DROP="D", - ST_DIRECT="DS", ST_SIMPLEXDESCENT="SD", ST_LAST="Last", ST_POSTPROCESS="PP", diff --git a/test/quadratic_lp_active_set.jl b/test/quadratic_lp_active_set.jl index a86c0b713..a87b37cea 100644 --- a/test/quadratic_lp_active_set.jl +++ b/test/quadratic_lp_active_set.jl @@ -46,7 +46,8 @@ x, v, primal, dual_gap, _ = FrankWolfe.blended_pairwise_conditional_gradient( 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)), ) @@ -64,7 +65,8 @@ x, v, primal, dual_gap, _ = FrankWolfe.blended_pairwise_conditional_gradient( 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)), ) @@ -82,7 +84,8 @@ x, v, primal, dual_gap, _ = FrankWolfe.blended_pairwise_conditional_gradient( 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)), )