diff --git a/src/Algorithm/colgen/default.jl b/src/Algorithm/colgen/default.jl index a03238d3c..ebe416f73 100644 --- a/src/Algorithm/colgen/default.jl +++ b/src/Algorithm/colgen/default.jl @@ -949,23 +949,19 @@ end ColGen.get_master_ip_primal_sol(output::ColGenPhaseOutput) = output.master_ip_primal_sol -ColGen.update_stabilization_after_pricing_optim!(::NoColGenStab, ctx::ColGenContext, generated_columns, master, valid_db, pseudo_db, mast_dual_sol) = nothing -function ColGen.update_stabilization_after_pricing_optim!(stab::ColGenStab, ctx::ColGenContext, generated_columns, master, valid_db, pseudo_db, mast_dual_sol) +ColGen.update_stabilization_after_pricing_optim!(::NoColGenStab, ctx::ColGenContext, generated_columns, master, pseudo_db, smooth_dual_sol) = nothing +function ColGen.update_stabilization_after_pricing_optim!(stab::ColGenStab, ctx::ColGenContext, generated_columns, master, pseudo_db, smooth_dual_sol) # At each iteration, we always update α after the first pricing optimization. # We don't update α if we are in a misprice sequence. if stab.automatic && stab.nb_misprices == 0 is_min = ColGen.is_minimization(ctx) primal_sol = _primal_solution(master, generated_columns, is_min) - α = _dynamic_alpha_schedule(stab.base_α, mast_dual_sol, stab.cur_stab_center, subgradient_helper(ctx), primal_sol, is_min) + α = _dynamic_alpha_schedule(stab.base_α, smooth_dual_sol, stab.cur_stab_center, subgradient_helper(ctx), primal_sol, is_min) stab.base_α = α end - if isbetter(DualBound(master, valid_db), stab.valid_dual_bound) - stab.cur_stab_center = mast_dual_sol - stab.valid_dual_bound = DualBound(master, valid_db) - end if isbetter(DualBound(master, pseudo_db), stab.pseudo_dual_bound) - stab.stab_center_for_next_iteration = mast_dual_sol + stab.stab_center_for_next_iteration = smooth_dual_sol stab.pseudo_dual_bound = DualBound(master, pseudo_db) end return diff --git a/src/Algorithm/colgen/printer.jl b/src/Algorithm/colgen/printer.jl index cb4dc9a95..c2cbf5f4f 100644 --- a/src/Algorithm/colgen/printer.jl +++ b/src/Algorithm/colgen/printer.jl @@ -28,8 +28,8 @@ ColGen.is_minimization(ctx::ColGenPrinterContext) = ColGen.is_minimization(ctx.i ColGen.get_pricing_subprobs(ctx::ColGenPrinterContext) = ColGen.get_pricing_subprobs(ctx.inner) ColGen.setup_stabilization!(ctx::ColGenPrinterContext, master) = ColGen.setup_stabilization!(ctx.inner, master) -function ColGen.update_stabilization_after_pricing_optim!(stab, ctx::ColGenPrinterContext, generated_columns, master, valid_db, pseudo_db, mast_dual_sol) - return ColGen.update_stabilization_after_pricing_optim!(stab, ctx.inner, generated_columns, master, valid_db, pseudo_db, mast_dual_sol) +function ColGen.update_stabilization_after_pricing_optim!(stab, ctx::ColGenPrinterContext, generated_columns, master, pseudo_db, smooth_dual_sol) + return ColGen.update_stabilization_after_pricing_optim!(stab, ctx.inner, generated_columns, master, pseudo_db, smooth_dual_sol) end ColGen.new_phase_iterator(ctx::ColGenPrinterContext) = ColGen.new_phase_iterator(ctx.inner) diff --git a/src/ColGen/ColGen.jl b/src/ColGen/ColGen.jl index ff365affd..6c1f7fe6b 100644 --- a/src/ColGen/ColGen.jl +++ b/src/ColGen/ColGen.jl @@ -254,12 +254,13 @@ function run_colgen_iteration!(context, phase, stage, env, ip_primal_sol, stab) # pseudo dual bound is used for stabilization only. pseudo_db = compute_dual_bound(context, phase, sps_pb, generated_columns, sep_mast_dual_sol) - update_stabilization_after_pricing_optim!(stab, context, generated_columns, master, valid_db, pseudo_db, mast_dual_sol) + update_stabilization_after_pricing_optim!(stab, context, generated_columns, master, pseudo_db, sep_mast_dual_sol) # We have finished to solve all pricing subproblems. - # If we have stabilization, we need to check if we have misprice. - # If we have misprice, we need to update the stabilization center and solve again - # the pricing subproblems. + # If we have stabilization, we need to check if we have misprice, i.e. if smoothing is active + # and no negative reduced cost columns are generated + # If we have misprice, we need to update the stabilization center and the smoothed dual solution + # and solve again the pricing subproblems. # If we don't have misprice, we can stop the pricing loop. misprice = check_misprice(stab, generated_columns, mast_dual_sol) if misprice diff --git a/src/ColGen/stabilization.jl b/src/ColGen/stabilization.jl index abace6a55..91a182948 100644 --- a/src/ColGen/stabilization.jl +++ b/src/ColGen/stabilization.jl @@ -26,11 +26,10 @@ Returns the dual solution used for the pricing in the current column generation """ Updates stabilization after pricing optimization where: - `mast_dual_sol` is the dual solution to the master problem -- `valid_db` is the valid dual bound of the problem after optimization of the pricing problems - `pseudo_db` is the pseudo dual bound of the problem after optimization of the pricing problems -- `mast_dual_sol` is the dual solution to the master problem +- `smooth_dual_sol` is the current smoothed dual solution """ -@mustimplement "ColGenStab" update_stabilization_after_pricing_optim!(stab, ctx, generated_columns, master, valid_db, pseudo_db, mast_dual_sol) = nothing +@mustimplement "ColGenStab" update_stabilization_after_pricing_optim!(stab, ctx, generated_columns, master, pseudo_db, smooth_dual_sol) = nothing """ Updates stabilization after a misprice. diff --git a/test/unit/ColGen/colgen_iteration.jl b/test/unit/ColGen/colgen_iteration.jl index b06c4ce05..50bca9606 100644 --- a/test/unit/ColGen/colgen_iteration.jl +++ b/test/unit/ColGen/colgen_iteration.jl @@ -221,7 +221,7 @@ function ColGen.compute_dual_bound(::ColGenIterationTestContext, ::ColGenIterati return 22.5 - 23/4 end -ColGen.update_stabilization_after_pricing_optim!(::Coluna.Algorithm.NoColGenStab, ::ColGenIterationTestContext, _, _, _, _, _) = nothing +ColGen.update_stabilization_after_pricing_optim!(::Coluna.Algorithm.NoColGenStab, ::ColGenIterationTestContext, _, _, _, _) = nothing struct TestColGenIterationOutput <: ColGen.AbstractColGenIterationOutput min_sense::Bool @@ -274,7 +274,7 @@ function ColGen.new_iteration_output(::Type{<:TestColGenIterationOutput}, ) end -ColGen.update_stabilization_after_pricing_optim!(::Coluna.Algorithm.NoColGenStab, ::TestColGenIterationContext, _, _, _, _, _) = nothing +ColGen.update_stabilization_after_pricing_optim!(::Coluna.Algorithm.NoColGenStab, ::TestColGenIterationContext, _, _, _, _) = nothing function colgen_iteration_master_ok_pricing_ok() ctx = ColGenIterationTestContext() diff --git a/test/unit/ColGen/colgen_stabilization.jl b/test/unit/ColGen/colgen_stabilization.jl index 0fb007ea8..8d1106f70 100644 --- a/test/unit/ColGen/colgen_stabilization.jl +++ b/test/unit/ColGen/colgen_stabilization.jl @@ -379,8 +379,8 @@ ColGen.get_pricing_strategy(::ColGenStabFlowCtx, phase) = ColGenStabFlowPricingS ColGen.pricing_strategy_iterate(::ColGenStabFlowPricingStrategy) = nothing ColGen.compute_dual_bound(ctx::ColGenStabFlowCtx, phase, bounds, generated_columns, mast_dual_sol) = ctx.nb_compute_dual_bound += 1 -function ColGen.update_stabilization_after_pricing_optim!(stab::ColGenStabFlowStab, ctx, generated_columns, master, valid_db, pseudo_db, mast_dual_sol) - @test mast_dual_sol == [1.0, 1.0, 1.0] # we need the out point in this method. +function ColGen.update_stabilization_after_pricing_optim!(stab::ColGenStabFlowStab, ctx, generated_columns, master, pseudo_db, smooth_dual_sol) + @test smooth_dual_sol == [0.5, 0.5, 0.5] # we need the out point in this method. stab.nb_update_stab_after_pricing_done += 1 return true end