Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bpcg with direct solve #515

Merged
merged 46 commits into from
Nov 6, 2024
Merged

Bpcg with direct solve #515

merged 46 commits into from
Nov 6, 2024

Conversation

pokutta
Copy link
Member

@pokutta pokutta commented Oct 25, 2024

No description provided.

pokutta and others added 23 commits October 3, 2024 18:24
* sparsifier active set

* fix typo

* added sparsifying tests

* generic tolerane

* remove sparsification

* format

* HiGHS dep
* sparsifier active set

* start working on LP AS

* first working quadratic

* remove quadratic LP from current

* cleanup

* HiGHS in test deps

* working reworked LP quadratic

* working version generic quadratic

* slow version generic quadratic

* faster term manipulation

* copy sufficient

* remove comment

* added test for quadratic

* minor

* simplify example

* clean up code, verify error with ASQuad

* Add update_weights! to fix direct solve with active_set_quadratic

* remove direct solve from BPCG

* rng changed

---------

Co-authored-by: Sébastien Designolle <[email protected]>
@pokutta
Copy link
Member Author

pokutta commented Oct 25, 2024

reopened the branch from before

MOI.empty!(o)
λ = MOI.add_variables(o, nv)
# λ ≥ 0, ∑ λ == 1
# MOI.add_constraint.(o, λ, MOI.GreaterThan(0.0))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commented out the nonnegativity constraint

Comment on lines 292 to 324
# Wolfe's pull back
## Extract lambda values into a vector
lambda_values = Vector{Float64}(undef, length(λ))
for idx in eachindex(λ)
lambda_values[idx] = MOI.get(o, MOI.VariablePrimal(), λ[idx])
end

## Load old weights into vector and do ratio test
old_weights = as.weights
tau_min = 1.0
for i in 1:length(lambda_values)
if lambda_values[i] < old_weights[i]
tau_min = min(tau_min, old_weights[i] / (old_weights[i] - lambda_values[i]))
end
end
tau = tau_min

# println("lambda_values: ", lambda_values)
# println("tau: ", tau)

## Compute new lambdas
new_lambdas = Vector{R}(undef, length(lambda_values))
for i in 1:length(lambda_values)
new_lambdas[i] = (1 - tau) * old_weights[i] + tau * lambda_values[i]
end

@assert all(0 .<= new_lambdas .<= 1) "All new_lambdas must be between 0 and 1"
@assert isapprox(sum(new_lambdas), 1.0, atol=1e-5) "The sum of new_lambdas must be approximately 1"

indices_to_remove = Int[]
new_weights = R[]
for idx in eachindex(λ)
weight_value = new_lambdas[idx] # using new lambdas
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should implement wolfe's pullback. get the unconstrained solution. form the line segment between current solution and unconstrained solution. compute tau on the line so that you stay feasible. update lambda and use

Comment on lines 95 to 127
active_set_quadratic_automatic_standard = FrankWolfe.ActiveSetQuadraticLinearSolve(
FrankWolfe.ActiveSet([(1.0, copy(x00))]),
grad!,
MOI.instantiate(MOI.OptimizerWithAttributes(HiGHS.Optimizer, MOI.Silent() => true)),
scheduler=FrankWolfe.LogScheduler(start_time=10, scaling_factor=1),
)
trajectoryBPCG_quadratic_automatic_standard = []
x, v, primal, dual_gap, _ = FrankWolfe.blended_pairwise_conditional_gradient(
f,
grad!,
lmo,
active_set_quadratic_automatic_standard,
max_iteration=k,
verbose=true,
callback=build_callback(trajectoryBPCG_quadratic_automatic_standard),
);


active_set_quadratic_wolfe = FrankWolfe.ActiveSetQuadraticLinearSolveWolfe(
FrankWolfe.ActiveSet([(1.0, copy(x00))]),
grad!,
MOI.instantiate(MOI.OptimizerWithAttributes(HiGHS.Optimizer, MOI.Silent() => true)),
scheduler=FrankWolfe.LogScheduler(start_time=10, scaling_factor=1),
)
trajectoryBPCG_quadratic_wolfe = []
x, v, primal, dual_gap, _ = FrankWolfe.blended_pairwise_conditional_gradient(
f,
grad!,
lmo,
active_set_quadratic_wolfe,
max_iteration=k,
verbose=true,
callback=build_callback(trajectoryBPCG_quadratic_wolfe),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these two runs cycle (irrespective of using the Wolfe one or the non-Wolfe one)

@pokutta
Copy link
Member Author

pokutta commented Oct 29, 2024

still some minor issue - run the direct_solve example with seed 10 @matbesancon

maybe it is just numerics or some edge case. we need to check

Blended Pairwise Conditional Gradient Algorithm.
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: Adaptive{Float64, Int64} EPSILON: 1.0e-7 MAXITERATION: 10000 TYPE: Float64
GRADIENTTYPE: Vector{Float64} LAZY: false lazy_tolerance: 2.0
LMO: FrankWolfe.KSparseLMO{Float64}

----------------------------------------------------------------------------------------------------------------
  Type     Iteration         Primal           Dual       Dual Gap           Time         It/sec     #ActiveSet
----------------------------------------------------------------------------------------------------------------
     I             1   5.000051e+06  -1.500005e+07   2.000010e+07   0.000000e+00            Inf              1
ERROR: LoadError: AssertionError: All new_lambdas must be between nonnegative
Stacktrace:
 [1] _compute_new_weights_wolfe_step(λ::Vector{MathOptInterface.VariableIndex}, ::Type{Float64}, old_weights::Vector{Float64}, o::HiGHS.Optimizer)

also for the Lp-norm LMO:

Blended Pairwise Conditional Gradient Algorithm.
MEMORY_MODE: FrankWolfe.InplaceEmphasis() STEPSIZE: Adaptive{Float64, Int64} EPSILON: 1.0e-7 MAXITERATION: 10000 TYPE: Float64
GRADIENTTYPE: Vector{Float64} LAZY: false lazy_tolerance: 2.0
LMO: FrankWolfe.LpNormLMO{Float64, 5}

----------------------------------------------------------------------------------------------------------------
  Type     Iteration         Primal           Dual       Dual Gap           Time         It/sec     #ActiveSet
----------------------------------------------------------------------------------------------------------------
     I             1   1.443502e+05  -4.411142e+05   5.854644e+05   0.000000e+00            Inf              1
ERROR: LoadError: AssertionError: Infeasible Wolfe subproblem: INFEASIBLE
Stacktrace:
 [1] solve_quadratic_activeset_lp!(as::FrankWolfe.ActiveSetQuadraticLinearSolve{…})

@matbesancon matbesancon merged commit 013dc15 into master Nov 6, 2024
12 checks passed
@matbesancon matbesancon deleted the BPCG-with-direct-solve branch November 6, 2024 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants