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

colgen returns dual solution #843

Merged
merged 2 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Algorithm/colgen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,14 @@ function run!(algo::ColumnGeneration, env::Env, reform::Reformulation, input::Op
update_ip_primal_sol!(optstate, result.master_ip_primal_sol)
end

if !isnothing(result.master_lp_dual_sol)
update_lp_dual_sol!(optstate, result.master_lp_dual_sol)
end

if !isnothing(result.db)
set_lp_dual_bound!(optstate, DualBound(master, result.db))
set_ip_dual_bound!(optstate, DualBound(master, result.db))
end
end
return optstate
end

Expand Down
13 changes: 10 additions & 3 deletions src/Algorithm/colgen/default.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ ColGen.get_pricing_subprobs(ctx::ColGenContext) = get_dw_pricing_sps(ctx.reform)
struct ColGenPhaseOutput <: ColGen.AbstractColGenPhaseOutput
master_lp_primal_sol::Union{Nothing,PrimalSolution}
master_ip_primal_sol::Union{Nothing,PrimalSolution}
master_lp_dual_sol::Union{Nothing,DualSolution}
mlp::Union{Nothing, Float64}
db::Union{Nothing, Float64}
new_cut_in_master::Bool
Expand All @@ -61,14 +62,16 @@ end
struct ColGenOutput <: ColGen.AbstractColGenOutput
master_lp_primal_sol::Union{Nothing,PrimalSolution}
master_ip_primal_sol::Union{Nothing,PrimalSolution}
master_lp_dual_sol::Union{Nothing,DualSolution}
mlp::Union{Nothing, Float64}
db::Union{Nothing, Float64}
end

function ColGen.new_output(::Type{<:ColGenOutput}, output::ColGenPhaseOutput)
return ColGenOutput(
output.master_lp_primal_sol,
output.master_ip_primal_sol,
output.master_ip_primal_sol,
output.master_lp_dual_sol,
output.mlp,
output.db
)
Expand Down Expand Up @@ -486,6 +489,7 @@ struct ColGenIterationOutput <: ColGen.AbstractColGenIterationOutput
time_limit_reached::Bool
master_lp_primal_sol::Union{Nothing, PrimalSolution}
master_ip_primal_sol::Union{Nothing, PrimalSolution}
master_lp_dual_sol::Union{Nothing, DualSolution}
end

ColGen.colgen_iteration_output_type(::ColGenContext) = ColGenIterationOutput
Expand All @@ -502,7 +506,8 @@ function ColGen.new_iteration_output(::Type{<:ColGenIterationOutput},
unbounded_subproblem,
time_limit_reached,
master_lp_primal_sol,
master_ip_primal_sol
master_ip_primal_sol,
master_lp_dual_sol
)
return ColGenIterationOutput(
min_sense,
Expand All @@ -516,7 +521,8 @@ function ColGen.new_iteration_output(::Type{<:ColGenIterationOutput},
unbounded_subproblem,
time_limit_reached,
master_lp_primal_sol,
master_ip_primal_sol
master_ip_primal_sol,
master_lp_dual_sol
)
end

Expand Down Expand Up @@ -556,6 +562,7 @@ function ColGen.new_phase_output(::Type{<:ColGenPhaseOutput}, colgen_iter_output
return ColGenPhaseOutput(
colgen_iter_output.master_lp_primal_sol,
colgen_iter_output.master_ip_primal_sol,
colgen_iter_output.master_lp_dual_sol,
colgen_iter_output.mlp,
colgen_iter_output.db,
colgen_iter_output.new_cut_in_master
Expand Down
11 changes: 6 additions & 5 deletions src/ColGen/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ abstract type AbstractColGenIterationOutput end
unbounded_subproblem,
time_limit_reached,
master_primal_sol,
ip_primal_sol
ip_primal_sol,
dual_sol
) = nothing

@mustimplement "ColGenIterationOutput" get_nb_new_cols(::AbstractColGenIterationOutput) = nothing
Expand All @@ -249,7 +250,7 @@ function run_colgen_iteration!(context, phase, env, ip_primal_sol)
# Iteration continues only if master is not infeasible nor unbounded and has dual
# solution.
if is_infeasible(mast_result)
return new_iteration_output(O, is_min_sense, nothing, _inf(is_min_sense), 0, false, true, false, false, false, false, nothing, nothing)
return new_iteration_output(O, is_min_sense, nothing, _inf(is_min_sense), 0, false, true, false, false, false, false, nothing, nothing, nothing)
elseif is_unbounded(mast_result)
throw(UnboundedProblemError("Unbounded master problem."))
end
Expand All @@ -269,7 +270,7 @@ function run_colgen_iteration!(context, phase, env, ip_primal_sol)
# memoization to calculate reduced costs and stabilization.
new_ip_primal_sol, new_cut_in_master = check_primal_ip_feasibility!(mast_primal_sol, context, phase, get_reform(context), env)
if new_cut_in_master
return new_iteration_output(O, is_min_sense, nothing, nothing, 0, true, false, false, false, false, false, nothing, ip_primal_sol)
return new_iteration_output(O, is_min_sense, nothing, nothing, 0, true, false, false, false, false, false, nothing, ip_primal_sol, nothing)
end
if !isnothing(new_ip_primal_sol) && isbetter(new_ip_primal_sol, ip_primal_sol)
ip_primal_sol = new_ip_primal_sol
Expand Down Expand Up @@ -332,7 +333,7 @@ function run_colgen_iteration!(context, phase, env, ip_primal_sol)
# Iteration continues only if the pricing solution is not infeasible nor unbounded.
if is_infeasible(pricing_result)
# TODO: if the lower multiplicity of the subproblem is zero, we can continue.
return new_iteration_output(O, is_min_sense, nothing, _inf(is_min_sense), 0, false, false, false, true, false, false, mast_primal_sol, ip_primal_sol)
return new_iteration_output(O, is_min_sense, nothing, _inf(is_min_sense), 0, false, false, false, true, false, false, mast_primal_sol, ip_primal_sol, mast_dual_sol)
elseif is_unbounded(pricing_result)
# We do not support unbounded pricing (even if it's theorically possible).
# We must stop Coluna here by throwing an exception because we can't claim
Expand Down Expand Up @@ -376,6 +377,6 @@ function run_colgen_iteration!(context, phase, env, ip_primal_sol)

# update_stab_after_gencols!

return new_iteration_output(O, is_min_sense, master_lp_obj_val, valid_db, nb_cols_inserted, false, false, false, false, false, false, mast_primal_sol, ip_primal_sol)
return new_iteration_output(O, is_min_sense, master_lp_obj_val, valid_db, nb_cols_inserted, false, false, false, false, false, false, mast_primal_sol, ip_primal_sol, mast_dual_sol)
end

1 change: 1 addition & 0 deletions test/.222-revise-exit-code
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
222
7 changes: 5 additions & 2 deletions test/unit/ColGen/colgen_iteration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ struct TestColGenIterationOutput <: ColGen.AbstractColGenIterationOutput
time_limit_reached::Bool
master_lp_primal_sol::Union{Nothing, Vector{Float64}}
master_ip_primal_sol::Union{Nothing, Vector{Float64}}
master_lp_dual_sol::Union{Nothing, Vector{Float64}}
end

ColGen.colgen_iteration_output_type(::ColGenIterationTestContext) = TestColGenIterationOutput
Expand All @@ -236,7 +237,8 @@ function ColGen.new_iteration_output(::Type{<:TestColGenIterationOutput},
unbounded_subproblem,
time_limit_reached,
master_lp_primal_sol,
master_ip_primal_sol
master_ip_primal_sol,
master_lp_dual_sol
)
return TestColGenIterationOutput(
min_sense,
Expand All @@ -250,7 +252,8 @@ function ColGen.new_iteration_output(::Type{<:TestColGenIterationOutput},
unbounded_subproblem,
time_limit_reached,
master_lp_primal_sol,
master_ip_primal_sol
master_ip_primal_sol,
master_lp_dual_sol
)
end

Expand Down
11 changes: 11 additions & 0 deletions test/unit/ColGen/colgen_phase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ function stop_colgen_phase_if_colgen_converged_eq()
false,
false,
nothing,
nothing,
nothing
)

Expand All @@ -155,6 +156,7 @@ function stop_colgen_phase_if_colgen_converged_min()
false,
false,
nothing,
nothing,
nothing
)

Expand All @@ -181,6 +183,7 @@ function stop_colgen_phase_if_colgen_converged_max()
false,
false,
nothing,
nothing,
nothing
)

Expand All @@ -207,6 +210,7 @@ function stop_colgen_phase_if_iterations_limit()
false,
false,
nothing,
nothing,
nothing
)

Expand All @@ -233,6 +237,7 @@ function stop_colgen_phase_if_time_limit()
false,
true,
nothing,
nothing,
nothing
)

Expand All @@ -259,6 +264,7 @@ function stop_colgen_phase_if_subproblem_infeasible()
false,
false,
nothing,
nothing,
nothing
)

Expand All @@ -285,6 +291,7 @@ function stop_colgen_phase_if_subproblem_unbounded()
true,
false,
nothing,
nothing,
nothing
)

Expand All @@ -311,6 +318,7 @@ function stop_colgen_phase_if_master_unbounded()
false,
false,
nothing,
nothing,
nothing
)

Expand All @@ -337,6 +345,7 @@ function stop_colgen_phase_if_no_new_column()
false,
false,
nothing,
nothing,
nothing
)
@test ColGen.stop_colgen_phase(ctx, ClA.ColGenPhase1(), env, colgen_iter_output, colgen_iteration, cutsep_iteration)
Expand All @@ -362,6 +371,7 @@ function stop_colgen_phase_if_new_cut_in_master()
false,
false,
nothing,
nothing,
nothing
)
@test ColGen.stop_colgen_phase(ctx, ClA.ColGenPhase3(), env, colgen_iter_output, colgen_iteration, cutsep_iteration)
Expand All @@ -387,6 +397,7 @@ function continue_colgen_phase_otherwise()
false,
false,
nothing,
nothing,
nothing
)
@test !ColGen.stop_colgen_phase(ctx, ClA.ColGenPhase1(), env, colgen_iter_output, colgen_iteration, cutsep_iteration)
Expand Down
6 changes: 6 additions & 0 deletions test/unit/ColGen/colgen_printer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function printer_colgen_iteration_master_ok_pricing_ok()
false,
false,
nothing,
nothing,
nothing
)
expected_str = " <it= 1> <et= 2.34> <mst= 1.23> <sp= 0.12> <cols= 1> <al= 0.00> <DB= 16.7500> <mlp= 22.5000> <PB=Inf>"
Expand All @@ -33,6 +34,7 @@ function printer_colgen_iteration_master_infeasible()
false,
false,
nothing,
nothing,
nothing
)
expected_str = " <it= 1> <et= 2.34> - infeasible master"
Expand All @@ -54,6 +56,7 @@ function printer_colgen_iteration_pricing_infeasible()
false,
false,
nothing,
nothing,
nothing
)
expected_str = " <it= 1> <et= 2.34> - infeasible subproblem"
Expand All @@ -75,6 +78,7 @@ function printer_colgen_iteration_master_unbounded()
false,
false,
nothing,
nothing,
nothing
)
expected_str = ""
Expand All @@ -96,6 +100,7 @@ function printer_colgen_iteration_pricing_unbounded()
true,
false,
nothing,
nothing,
nothing
)
expected_str = " <it= 1> <et= 2.34> - unbounded subproblem"
Expand Down Expand Up @@ -139,6 +144,7 @@ function printer_colgen_new_cuts_in_master()
false,
false,
nothing,
nothing,
nothing
)
expected_str = " <it= 1> <et= 2.34> <mst= 1.23> <sp= 0.12> <cols= 1> <al= 0.00> <DB= 16.7500> <mlp= 22.5000> <PB=Inf>"
Expand Down