Skip to content

Commit

Permalink
• Restored strong branching output (#1123)
Browse files Browse the repository at this point in the history
• Correction for global bounds output when strong branching is used
• Output information every time an improving primal solution is found
  • Loading branch information
rrsadykov authored Jan 19, 2024
1 parent 3db73e6 commit d1064d8
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 17 deletions.
4 changes: 4 additions & 0 deletions src/Algorithm/branching/branchingalgo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,10 @@ function Branching.eval_child_of_candidate!(child, phase::Branching.AbstractStro
restore_from_records!(units_to_restore, child.records)
conquer_input = ConquerInputFromSb(global_primal_handler, child, units_to_restore)
child.conquer_output = run!(Branching.get_conquer(phase), env, reform, conquer_input)
child.ip_dual_bound = get_lp_dual_bound(child.conquer_output)
for sol in get_ip_primal_sols(child.conquer_output)
store_ip_primal_sol!(global_primal_handler, sol)
end
TreeSearch.set_records!(child, create_records(reform))
end

Expand Down
4 changes: 2 additions & 2 deletions src/Algorithm/branching/printer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ function new_phase_context(
return PhasePrinter(inner_ctx, phase_index)
end

function Branching.perform_branching_phase!(candidates, cand_children, phase::PhasePrinter, sb_state, env, reform, input)
function Branching.perform_branching_phase!(candidates, cand_children, phase::PhasePrinter, env, reform, input)
println("**** Strong branching phase ", phase.phase_index, " is started *****");
scores = Branching.perform_branching_phase_inner!(cand_children, phase, sb_state, env, reform, input)
scores = Branching.perform_branching_phase_inner!(cand_children, phase, env, reform, input)
for (candidate, children, score) in Iterators.zip(candidates, cand_children, scores)
@printf "SB phase %i branch on %+10s" phase.phase_index Branching.getdescription(candidate)
@printf " (lhs=%.4f) : [" Branching.get_lhs(candidate)
Expand Down
5 changes: 4 additions & 1 deletion src/Algorithm/colgen/printer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ function ColGen.update_master_constrs_dual_vals!(ctx::ColGenPrinterContext, mast
end

ColGen.check_primal_ip_feasibility!(mast_primal_sol, ctx::ColGenPrinterContext, phase, env) = ColGen.check_primal_ip_feasibility!(mast_primal_sol, ctx.inner, phase, env)
ColGen.update_inc_primal_sol!(ctx::ColGenPrinterContext, ip_primal_sol, new_ip_primal_sol) = ColGen.update_inc_primal_sol!(ctx.inner, ip_primal_sol, new_ip_primal_sol)
function ColGen.update_inc_primal_sol!(ctx::ColGenPrinterContext, ip_primal_sol, new_ip_primal_sol)
@info "Improving primal solution with value $(ColunaBase.getvalue(new_ip_primal_sol)) is found during column generation"
ColGen.update_inc_primal_sol!(ctx.inner, ip_primal_sol, new_ip_primal_sol)
end

ColGen.get_subprob_var_orig_costs(ctx::ColGenPrinterContext) = ColGen.get_subprob_var_orig_costs(ctx.inner)
ColGen.get_subprob_var_coef_matrix(ctx::ColGenPrinterContext) = ColGen.get_subprob_var_coef_matrix(ctx.inner)
Expand Down
22 changes: 16 additions & 6 deletions src/Algorithm/conquer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct ColCutGenConquer <: AbstractConquerAlgorithm
max_nb_cut_rounds::Int # TODO : tailing-off ?
opt_atol::Float64# TODO : force this value in an init() method
opt_rtol::Float64 # TODO : force this value in an init() method
verbose::Bool
end

ColCutGenConquer(;
Expand All @@ -103,7 +104,8 @@ ColCutGenConquer(;
cutgen = CutCallbacks(),
max_nb_cut_rounds = 3,
opt_atol = AlgoAPI.default_opt_atol(),
opt_rtol = AlgoAPI.default_opt_rtol()
opt_rtol = AlgoAPI.default_opt_rtol(),
verbose = true
) = ColCutGenConquer(
colgen,
primal_heuristics,
Expand All @@ -113,7 +115,8 @@ ColCutGenConquer(;
cutgen,
max_nb_cut_rounds,
opt_atol,
opt_rtol
opt_rtol,
verbose
)

# ColCutGenConquer does not use any storage unit for the moment, therefore
Expand Down Expand Up @@ -261,11 +264,18 @@ function run_heuristics!(ctx::ColCutGenContext, heuristics, env, reform, input,
records = create_records(reform)
end

prev_primal_bound = get_ip_primal_bound(conquer_output)

heuristic_output = run!(heuristic.algorithm, env, reform, conquer_output)
update!(conquer_output, heuristic_output)
# for sol in Heuristic.get_primal_sols(output)
# store_ip_primal_sol!(get_global_primal_handler(input), sol)
# end
add_ip_primal_sols!(conquer_output, get_ip_primal_sols(heuristic_output)...)
update_ip_dual_bound!(conquer_output, get_ip_dual_bound(heuristic_output))

if ctx.params.verbose
curr_primal_bound = get_ip_primal_bound(conquer_output)
if curr_primal_bound != prev_primal_bound
@info "Heuristic $(heuristic.name) found improving primal solution with value $(curr_primal_bound.value)"
end
end

if ismanager(heuristic.algorithm)
restore_from_records!(input.units_to_restore, records)
Expand Down
6 changes: 0 additions & 6 deletions src/Algorithm/heuristic/restricted_master.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ function get_child_algorithms(algo::RestrictedMasterHeuristic, reform::Reformula
return child_algs
end

# struct RestrictedMasterHeuristicOutput <: Heuristic.AbstractHeuristicOutput
# ip_primal_sols::Vector{PrimalSolution}
# end

# Heuristic.get_primal_sols(o::RestrictedMasterHeuristicOutput) = o.ip_primal_sols

function run!(algo::RestrictedMasterHeuristic, env, reform, input::OptimizationState)
master = getmaster(reform)
ip_form_output = run!(algo.solve_ip_form_alg, env, master, input)
Expand Down
3 changes: 1 addition & 2 deletions src/ColGen/ColGen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,7 @@ function run_colgen_iteration!(context, phase, stage, env, ip_primal_sol, stab)

mast_dual_sol = get_dual_sol(mast_result)
if isnothing(mast_dual_sol)
error("Cannot continue")
# TODO: user friendly error message.
error("Column generation interrupted: LP solver did not return an optimal dual solution")
end

# Stores dual solution in the constraint. This is used when the pricing solver supports
Expand Down

0 comments on commit d1064d8

Please sign in to comment.