gmi_dual: stop early; fix gap improvement with zero cuts issue

feature/replay^2
Alinson S. Xavier 1 year ago
parent 24532614e5
commit 77c7e94927
Signed by: isoron
GPG Key ID: 0DA8E4B9E1109DCA

@ -48,6 +48,7 @@ function collect_gmi_dual(
all_cuts = nothing all_cuts = nothing
all_cuts_bases = nothing all_cuts_bases = nothing
all_cuts_rows = nothing all_cuts_rows = nothing
last_round_obj = nothing
end end
@timeit "Read problem" begin @timeit "Read problem" begin
@ -86,15 +87,21 @@ function collect_gmi_dual(
@timeit "Optimize standard model" begin @timeit "Optimize standard model" begin
@info "Optimizing standard model..." @info "Optimizing standard model..."
optimize!(model_s) optimize!(model_s)
if round == 1
obj = objective_value(model_s) obj = objective_value(model_s)
if round == 1
push!(stats_obj, obj) push!(stats_obj, obj)
push!(stats_gap, gap(obj)) push!(stats_gap, gap(obj))
push!(stats_ncuts, 0) push!(stats_ncuts, 0)
else
if obj last_round_obj
@info ("No improvement in obj value. Aborting.")
break
end
end end
if termination_status(model_s) != MOI.OPTIMAL if termination_status(model_s) != MOI.OPTIMAL
error("Non-optimal termination status") error("Non-optimal termination status")
end end
last_round_obj = obj
end end
@timeit "Select tableau rows" begin @timeit "Select tableau rows" begin
@ -165,31 +172,35 @@ function collect_gmi_dual(
undo_relax = relax_integrality(model) undo_relax = relax_integrality(model)
@info "Optimizing original model (constr)..." @info "Optimizing original model (constr)..."
optimize!(model) optimize!(model)
obj1 = objective_value(model) obj = objective_value(model)
push!(stats_obj, obj1) push!(stats_obj, obj)
push!(stats_gap, gap(obj1)) push!(stats_gap, gap(obj))
sp = [shadow_price(c) for c in constrs] sp = [shadow_price(c) for c in constrs]
undo_relax() undo_relax()
end useful = [abs(sp[i]) > 1e-6 for (i, _) in enumerate(constrs)]
keep = findall(useful .== true)
@timeit "Update obj function of original model" begin
delete.(model, constrs)
set_objective_function(
model,
obj_original - sum(sp[i] * gmi_exps[i] for (i, c) in enumerate(constrs)),
)
end end
@timeit "Filter out useless cuts" begin @timeit "Filter out useless cuts" begin
useful = [abs(sp[i]) > 0.001 for (i, _) in enumerate(constrs)] @info "Keeping $(length(keep)) useful cuts"
keep = findall(useful .== true)
@info "Keeping only $(length(keep)) useful cuts"
all_cuts.lhs = all_cuts.lhs[keep, :] all_cuts.lhs = all_cuts.lhs[keep, :]
all_cuts.lb = all_cuts.lb[keep] all_cuts.lb = all_cuts.lb[keep]
all_cuts.ub = all_cuts.ub[keep] all_cuts.ub = all_cuts.ub[keep]
all_cuts_bases = all_cuts_bases[keep, :] all_cuts_bases = all_cuts_bases[keep, :]
all_cuts_rows = all_cuts_rows[keep, :] all_cuts_rows = all_cuts_rows[keep, :]
push!(stats_ncuts, length(all_cuts_rows)) push!(stats_ncuts, length(all_cuts_rows))
if isempty(keep)
break
end
end
@timeit "Update obj function of original model" begin
delete.(model, constrs)
set_objective_function(
model,
obj_original -
sum(sp[i] * gmi_exps[i] for (i, c) in enumerate(constrs) if useful[i]),
)
end end
end end

@ -7,7 +7,7 @@ using SparseArrays
Base.@kwdef mutable struct ProblemData Base.@kwdef mutable struct ProblemData
obj::Vector{Float64} obj::Vector{Float64}
obj_offset::Float64 obj_offset::Float64
obj_sense obj_sense::Any
constr_lb::Vector{Float64} constr_lb::Vector{Float64}
constr_ub::Vector{Float64} constr_ub::Vector{Float64}
constr_lhs::SparseMatrixCSC constr_lhs::SparseMatrixCSC

Loading…
Cancel
Save