Skip to content

Commit

Permalink
colgen returns dual solution (#843)
Browse files Browse the repository at this point in the history
* colgen returns dual solution

* Update test/revise.jl
  • Loading branch information
guimarqu authored Apr 26, 2023
1 parent d6ed80f commit 835f0d9
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 11 deletions.
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

0 comments on commit 835f0d9

Please sign in to comment.