diff --git a/test/parser.jl b/test/parser.jl index b394bee9f..a95132ae7 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -290,7 +290,7 @@ function create_subproblems!(env::Env{ClMP.VarId}, reform::ClMP.Reformulation, c if isnothing(spform) spform = ClMP.create_formulation!( env, - ClMP.DwSp(nothing, nothing, nothing, var.kind); + ClMP.DwSp(nothing, nothing, nothing, ClMP.Integ); obj_sense = sp.sense ) end diff --git a/test/unit/ColGen/colgen_default.jl b/test/unit/ColGen/colgen_default.jl index 651ec7d64..8fbdf6202 100644 --- a/test/unit/ColGen/colgen_default.jl +++ b/test/unit/ColGen/colgen_default.jl @@ -495,6 +495,146 @@ function toy_gap_with_obj_const() return env, master, sps, reform end +function check_identical_subproblems() + # Used to check the output of identical_subproblem. The two formulations should be equivalent. + # Subproblem 5 is introduced twice. + form = """ + master + min + 100.0 local_art_of_cov_5 + 100.0 local_art_of_cov_4 + 100.0 local_art_of_cov_6 + 100.0 local_art_of_cov_7 + 100.0 local_art_of_cov_2 + 100.0 local_art_of_cov_3 + 100.0 local_art_of_cov_1 + 100.0 local_art_of_sp_lb_5 + 100.0 local_art_of_sp_ub_5 + 100.0 local_art_of_sp_lb_4 + 100.0 local_art_of_sp_ub_4 + 1000.0 global_pos_art_var + 1000.0 global_neg_art_var + 8.0 x_11 + 5.0 x_12 + 11.0 x_13 + 21.0 x_14 + 6.0 x_15 + 5.0 x_16 + 19.0 x_17 + 8.0 x_21 + 5.0 x_22 + 11.0 x_23 + 21.0 x_24 + 6.0 x_25 + 5.0 x_26 + 19.0 x_27 + PricingSetupVar_sp_5 + 0.0 PricingSetupVar_sp_4 + s.t. + 1.0 x_11 + 1.0 x_21 + 1.0 local_art_of_cov_1 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_12 + 1.0 x_22 + 1.0 local_art_of_cov_2 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_13 + 1.0 x_23 + 1.0 local_art_of_cov_3 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_14 + 1.0 x_24 + 1.0 local_art_of_cov_4 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_15 + 1.0 x_25 + 1.0 local_art_of_cov_5 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_16 + 1.0 x_26 + 1.0 local_art_of_cov_6 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_17 + 1.0 x_27 + 1.0 local_art_of_cov_7 + 1.0 global_pos_art_var >= 1.0 + 1.0 PricingSetupVar_sp_5 + 1.0 local_art_of_sp_lb_5 >= 0.0 {MasterConvexityConstr} + 1.0 PricingSetupVar_sp_5 - 1.0 local_art_of_sp_ub_5 <= 1.0 {MasterConvexityConstr} + 1.0 PricingSetupVar_sp_4 + 1.0 local_art_of_sp_lb_4 >= 0.0 {MasterConvexityConstr} + 1.0 PricingSetupVar_sp_4 - 1.0 local_art_of_sp_ub_4 <= 1.0 {MasterConvexityConstr} + + dw_sp + min + x_11 + x_12 + x_13 + x_14 + x_15 + x_16 + x_17 + 0.0 PricingSetupVar_sp_5 + s.t. + 2.0 x_11 + 3.0 x_12 + 3.0 x_13 + 1.0 x_14 + 2.0 x_15 + 1.0 x_16 + 1.0 x_17 <= 5.0 + + dw_sp + min + x_21 + x_22 + x_23 + x_24 + x_25 + x_26 + x_27 + 0.0 PricingSetupVar_sp_4 + s.t. + 2.0 x_21 + 3.0 x_22 + 3.0 x_23 + 1.0 x_24 + 2.0 x_25 + 1.0 x_26 + 1.0 x_27 <= 5.0 + + continuous + artificial + local_art_of_cov_5, local_art_of_cov_4, local_art_of_cov_6, local_art_of_cov_7, local_art_of_cov_2, local_art_of_cov_3, local_art_of_cov_1, local_art_of_sp_lb_5, local_art_of_sp_ub_5, local_art_of_sp_lb_4, local_art_of_sp_ub_4, global_pos_art_var, global_neg_art_var + + integer + pricing_setup + PricingSetupVar_sp_4, PricingSetupVar_sp_5 + + binary + representatives + x_11, x_21, x_12, x_22, x_13, x_23, x_14, x_24, x_15, x_25, x_16, x_26, x_17, x_27 + + bounds + 0.0 <= x_11 <= 1.0 + 0.0 <= x_21 <= 1.0 + 0.0 <= x_12 <= 1.0 + 0.0 <= x_22 <= 1.0 + 0.0 <= x_13 <= 1.0 + 0.0 <= x_23 <= 1.0 + 0.0 <= x_14 <= 1.0 + 0.0 <= x_24 <= 1.0 + 0.0 <= x_15 <= 1.0 + 0.0 <= x_25 <= 1.0 + 0.0 <= x_16 <= 1.0 + 0.0 <= x_26 <= 1.0 + 0.0 <= x_17 <= 1.0 + 0.0 <= x_27 <= 1.0 + 1.0 <= PricingSetupVar_sp_4 <= 1.0 + 1.0 <= PricingSetupVar_sp_5 <= 1.0 + local_art_of_cov_5 >= 0.0 + local_art_of_cov_4 >= 0.0 + local_art_of_cov_6 >= 0.0 + local_art_of_cov_7 >= 0.0 + local_art_of_cov_2 >= 0.0 + local_art_of_cov_3 >= 0.0 + local_art_of_cov_1 >= 0.0 + local_art_of_sp_lb_5 >= 0.0 + local_art_of_sp_ub_5 >= 0.0 + local_art_of_sp_lb_4 >= 0.0 + local_art_of_sp_ub_4 >= 0.0 + global_pos_art_var >= 0.0 + global_neg_art_var >= 0.0 + """ + + env, master, sps, _, reform = reformfromstring(form) + return env, master, sps, reform + +end + +function identical_subproblems() + form = """ + master + min + 100.0 local_art_of_cov_5 + 100.0 local_art_of_cov_4 + 100.0 local_art_of_cov_6 + 100.0 local_art_of_cov_7 + 100.0 local_art_of_cov_2 + 100.0 local_art_of_cov_3 + 100.0 local_art_of_cov_1 + 100.0 local_art_of_sp_lb_5 + 100.0 local_art_of_sp_ub_5 + 1000.0 global_pos_art_var + 1000.0 global_neg_art_var + 8.0 x_11 + 5.0 x_12 + 11.0 x_13 + 21.0 x_14 + 6.0 x_15 + 5.0 x_16 + 19.0 x_17 + 0.0 PricingSetupVar_sp_5 + s.t. + 1.0 x_11 + 1.0 local_art_of_cov_1 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_12 + 1.0 local_art_of_cov_2 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_13 + 1.0 local_art_of_cov_3 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_14 + 1.0 local_art_of_cov_4 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_15 + 1.0 local_art_of_cov_5 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_16 + 1.0 local_art_of_cov_6 + 1.0 global_pos_art_var >= 1.0 + 1.0 x_17 + 1.0 local_art_of_cov_7 + 1.0 global_pos_art_var >= 1.0 + 1.0 PricingSetupVar_sp_5 + 1.0 local_art_of_sp_lb_5 >= 0.0 {MasterConvexityConstr} + 1.0 PricingSetupVar_sp_5 - 1.0 local_art_of_sp_ub_5 <= 2.0 {MasterConvexityConstr} + + dw_sp + min + x_11 + x_12 + x_13 + x_14 + x_15 + x_16 + x_17 + 0.0 PricingSetupVar_sp_5 + s.t. + 2.0 x_11 + 3.0 x_12 + 3.0 x_13 + 1.0 x_14 + 2.0 x_15 + 1.0 x_16 + 1.0 x_17 <= 5.0 + + continuous + artificial + local_art_of_cov_5, local_art_of_cov_4, local_art_of_cov_6, local_art_of_cov_7, local_art_of_cov_2, local_art_of_cov_3, local_art_of_cov_1, local_art_of_sp_lb_5, local_art_of_sp_ub_5, global_pos_art_var, global_neg_art_var + + integer + pricing_setup + PricingSetupVar_sp_5 + + binary + representatives + x_11, x_12, x_13, x_14, x_15, x_16, x_17 + + bounds + 0.0 <= x_11 <= 1.0 + 0.0 <= x_12 <= 1.0 + 0.0 <= x_13 <= 1.0 + 0.0 <= x_14 <= 1.0 + 0.0 <= x_15 <= 1.0 + 0.0 <= x_16 <= 1.0 + 0.0 <= x_17 <= 1.0 + 1.0 <= PricingSetupVar_sp_5 <= 1.0 + local_art_of_cov_5 >= 0.0 + local_art_of_cov_4 >= 0.0 + local_art_of_cov_6 >= 0.0 + local_art_of_cov_7 >= 0.0 + local_art_of_cov_2 >= 0.0 + local_art_of_cov_3 >= 0.0 + local_art_of_cov_1 >= 0.0 + local_art_of_sp_lb_5 >= 0.0 + local_art_of_sp_ub_5 >= 0.0 + global_pos_art_var >= 0.0 + global_neg_art_var >= 0.0 + """ + env, master, sps, _, reform = reformfromstring(form) + return env, master, sps, reform +end + ### Implementation of ColGen API to test and call the default implementation struct TestColGenIterationContext <: ColGen.AbstractColGenContext context::ClA.ColGenContext @@ -765,7 +905,7 @@ function test_colgen_iteration_pure_master_vars() @test output.infeasible_subproblem == false @test output.unbounded_subproblem == false end -#register!(unit_tests, "colgen_default", test_colgen_iteration_pure_master_vars) +register!(unit_tests, "colgen_default", test_colgen_iteration_pure_master_vars) function test_colgen_iteration_obj_const() env, master, sps, reform = toy_gap_with_obj_const() @@ -1189,6 +1329,40 @@ function min_toy_gap_for_colgen() return env, master, sps, reform end + + +function test_identical_subproblems() + env, master, sps, reform = identical_subproblems() + ClMP.push_optimizer!(master, () -> ClA.MoiOptimizer(GLPK.Optimizer())) # we need warm start + ClMP.relax_integrality!(master) + for sp in sps + ClMP.push_optimizer!(sp, () -> ClA.MoiOptimizer(GLPK.Optimizer())) + end + println("\e[35m results: :\e[0m") + ctx = ClA.ColGenPrinterContext(reform, ClA.ColumnGeneration()) + output = ColGen.run!(ctx, env) + @show output.mlp + @show output.db + println("\e[35m ************************************ :\e[0m") +end +register!(unit_tests, "colgen_default", test_identical_subproblems) + +function expected_output_identical_subproblems() + env, master, sps, reform = check_identical_subproblems() + ClMP.push_optimizer!(master, () -> ClA.MoiOptimizer(GLPK.Optimizer())) # we need warm start + ClMP.relax_integrality!(master) + for sp in sps + ClMP.push_optimizer!(sp, () -> ClA.MoiOptimizer(GLPK.Optimizer())) + end + println("\e[35m expected value: :\e[0m") + ctx = ClA.ColGenPrinterContext(reform, ClA.ColumnGeneration()) + output = ColGen.run!(ctx, env) + @show output.mlp + @show output.db + println("\e[35m *********************************** \e[0") +end +register!(unit_tests, "colgen_default", expected_output_identical_subproblems) + function test_colgen() env, master, sps, reform = min_toy_gap_for_colgen() # We need subsolvers to optimize the master and subproblems.