Skip to content

Commit

Permalink
reduced costs ok for min gap (#775)
Browse files Browse the repository at this point in the history
  • Loading branch information
guimarqu authored Mar 23, 2023
1 parent 2e12575 commit 6d4ac3d
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 27 deletions.
15 changes: 8 additions & 7 deletions test/parser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ function create_subproblems!(env::Env{ClMP.VarId}, reform::ClMP.Reformulation, c
i = 1
constraints = ClMP.Constraint[]
subproblems = []
all_spvars = Dict{String, ClMP.Variable}()
all_spvars = Dict{String, Tuple{ClMP.Variable, ClMP.Formulation{ClMP.DwSp}}}()
for (_, sp) in cache.subproblems
spform = nothing
for (varid, cost) in sp.objective.vars
Expand All @@ -294,14 +294,14 @@ function create_subproblems!(env::Env{ClMP.VarId}, reform::ClMP.Reformulation, c
end
v = ClMP.setvar!(spform, varid, ClMP.DwSpPricingVar; lb = var.lb, ub = var.ub, kind = var.kind)
ClMP.setperencost!(spform, v, cost)
all_spvars[varid] = v
all_spvars[varid] = (v, spform)
end
else
throw(UndefVarParserError("Variable $varid duty and/or kind not defined"))
end
end
for constr in sp.constraints
members = Dict(ClMP.getid(all_spvars[varid]) => coeff for (varid, coeff) in constr.lhs.vars)
members = Dict(ClMP.getid(all_spvars[varid][1]) => coeff for (varid, coeff) in constr.lhs.vars)
c = ClMP.setconstr!(spform, "sp_c$i", ClMP.DwSpPureConstr; rhs = constr.rhs, sense = constr.sense, members = members)
push!(constraints, c)
i += 1
Expand All @@ -312,21 +312,22 @@ function create_subproblems!(env::Env{ClMP.VarId}, reform::ClMP.Reformulation, c
return subproblems, all_spvars, constraints
end

function add_master_vars!(master::ClMP.Formulation, all_spvars::Dict{String, ClMP.Variable}, cache::ReadCache)
function add_master_vars!(master::ClMP.Formulation, all_spvars::Dict, cache::ReadCache)
mastervars = Dict{String, ClMP.Variable}()
for (varid, cost) in cache.master.objective.vars
if haskey(cache.variables, varid)
var = cache.variables[varid]
if var.duty <= ClMP.AbstractMasterVar
if var.duty <= ClMP.AbstractOriginMasterVar || var.duty <= ClMP.AbstractAddedMasterVar
is_explicit = !(var.duty <= ClMP.AbstractImplicitMasterVar)
v = ClMP.setvar!(master, varid, var.duty; lb = var.lb, ub = var.ub, kind = var.kind, is_explicit = is_explicit)
else
if haskey(all_spvars, varid)
v = ClMP.setvar!(master, varid, ClMP.MasterRepPricingVar; lb = var.lb, ub = var.ub, kind = var.kind, id = ClMP.getid(all_spvars[varid]), is_explicit = false)
var, sp = all_spvars[varid]
v = ClMP.clonevar!(sp, master, sp, var, ClMP.MasterRepPricingVar; is_explicit = false)
else
throw(UndefVarParserError("Variable $varid not present in any subproblem"))
end
end
end
ClMP.setperencost!(master, v, cost)
mastervars[varid] = v
else
Expand Down
57 changes: 37 additions & 20 deletions test/unit/ColGen/colgen_default.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ master
x1 + x2 + x3 + y1 + y2 + y3 >= 10
x1 + 2x2 + y1 + 2y2 <= 100
x1 + 3x3 + y1 + + 3y3 == 100
dw_sp
min
x1 + x2 + x3 + y1 + y2 + y3
s.t.
x1 + x2 + x3 + y1 + y2 + y3 >= 10
integer
representatives
Expand Down Expand Up @@ -42,8 +48,6 @@ function test_reduced_costs_calculation_helper()
_, master, _, _, _ = reformfromstring(form1())
vids = get_name_to_varids(master)
cids = get_name_to_constrids(master)

@show master

helper = ClA.ReducedCostsCalculationHelper(master)
@test helper.c[vids["x1"]] == 3
Expand Down Expand Up @@ -76,19 +80,20 @@ register!(unit_tests, "colgen_default", test_reduced_costs_calculation_helper)
# All the tests are based on the Generalized Assignment problem.
# x_mj = 1 if job j is assigned to machine m

function min_toy_gap()
function min_toy_gap()
# We introduce variables z1 & z2 to force dual value of constraint c7 to equal to 28.
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 + 51.0 MC_30 + 38.0 MC_31 + 31.0 MC_32 + 35.0 MC_33 + 48.0 MC_34 + 13.0 MC_35 + 53.0 MC_36 + 28.0 MC_37 + 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 + 1.0 x_21 + 12.0 x_22 + 11.0 x_23 + 12.0 x_24 + 14.0 x_25 + 8.0 x_26 + 5.0 x_27 + 0.0 PricingSetupVar_sp_5 + 0.0 PricingSetupVar_sp_4
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 + 51.0 MC_30 + 38.0 MC_31 + 31.0 MC_32 + 35.0 MC_33 + 48.0 MC_34 + 13.0 MC_35 + 53.0 MC_36 + 28.0 MC_37 + 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 + 1.0 x_21 + 12.0 x_22 + 11.0 x_23 + 12.0 x_24 + 14.0 x_25 + 8.0 x_26 + 5.0 x_27 + 0.0 PricingSetupVar_sp_5 + 0.0 PricingSetupVar_sp_4 + 28 z1 - 28 z2
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 MC_31 + 1.0 MC_34 + 1.0 MC_35 + 1.0 MC_36 >= 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 MC_31 + 1.0 MC_32 + 1.0 MC_33 >= 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 MC_31 + 1.0 MC_32 + 1.0 MC_33 >= 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 MC_31 + 1.0 MC_33 + 1.0 MC_37 >= 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 MC_30 + 1.0 MC_32 + 1.0 MC_33 + 1.0 MC_34 + 1.0 MC_35 + 1.0 MC_36 + 1.0 MC_37 >= 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 MC_30 + 1.0 MC_31 >= 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 MC_30 + 1.0 MC_32 + 1.0 MC_36 >= 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 MC_30 + 1.0 MC_34 + 1.0 MC_36 + 1.0 MC_37 >= 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 MC_30 + 1.0 MC_34 + 1.0 MC_36 + 1.0 MC_37 + z1 - z2 >= 1.0
1.0 PricingSetupVar_sp_5 + 1.0 local_art_of_sp_lb_5 + 1.0 MC_30 + 1.0 MC_32 + 1.0 MC_34 + 1.0 MC_36 >= 0.0 {MasterConvexityConstr}
1.0 PricingSetupVar_sp_5 - 1.0 local_art_of_sp_ub_5 + 1.0 MC_30 + 1.0 MC_32 + 1.0 MC_34 + 1.0 MC_36 <= 1.0 {MasterConvexityConstr}
1.0 PricingSetupVar_sp_4 + 1.0 local_art_of_sp_lb_4 + 1.0 MC_31 + 1.0 MC_33 + 1.0 MC_35 + 1.0 MC_37 >= 0.0 {MasterConvexityConstr}
Expand All @@ -113,6 +118,9 @@ 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
pure
z1, z2
integer
pricing_setup
PricingSetupVar_sp_4, PricingSetupVar_sp_5
Expand Down Expand Up @@ -159,12 +167,13 @@ bounds
MC_35 >= 0.0
MC_36 >= 0.0
MC_37 >= 0.0
"""
z1 >= 0.0
z2 >= 0.0
"""
env, master, sps, _, reform = reformfromstring(form)
return env, master, sps, reform
end


function max_toy_gap()
form = """
master
Expand Down Expand Up @@ -458,7 +467,6 @@ ColGen.get_pricing_subprobs(ctx::TestColGenIterationContext) = ColGen.get_pricin
function ColGen.optimize_master_lp_problem!(master, ctx::TestColGenIterationContext, env)
output = ColGen.optimize_master_lp_problem!(master, ctx.context, env)
primal_sol = ColGen.get_primal_sol(output)
@show primal_sol
for (var_id, var) in ClMP.getvars(master)
name = ClMP.getname(master, var)
if !haskey(ctx.master_lp_primal_sol, name)
Expand All @@ -467,6 +475,16 @@ function ColGen.optimize_master_lp_problem!(master, ctx::TestColGenIterationCont
@test primal_sol[var_id] ctx.master_lp_primal_sol[name]
end
end

dual_sol = ColGen.get_dual_sol(output)
for (constr_id, constr) in ClMP.getconstrs(master)
name = ClMP.getname(master, constr)
if !haskey(ctx.master_lp_dual_sol, name)
@test dual_sol[constr_id] 0.0
else
@test dual_sol[constr_id] ctx.master_lp_dual_sol[name]
end
end
return output
end

Expand All @@ -477,10 +495,13 @@ ColGen.get_orig_costs(ctx::TestColGenIterationContext) = ColGen.get_orig_costs(c
ColGen.get_coef_matrix(ctx::TestColGenIterationContext) = ColGen.get_coef_matrix(ctx.context)

function ColGen.update_sp_vars_red_costs!(ctx::TestColGenIterationContext, sp::Formulation{DwSp}, red_costs)
@show red_costs
for i in 1:5
println("\e[34m ***************** \e[00m")
end
ColGen.update_sp_vars_red_costs!(ctx.context, sp, red_costs)
for (_, var) in ClMP.getvars(sp)
name = ClMP.getname(sp, var)
println(" ---- name = $(name) ---- expected : $(ctx.pricing_var_reduced_costs[name]) ---- actual : $(ClMP.getcurcost(sp, var)) --- cur_cost = $(ClMP.getcurcost(sp, var)))")
@test ctx.pricing_var_reduced_costs[name] ClMP.getcurcost(sp, var)
end
return
Expand All @@ -505,9 +526,6 @@ end
function test_colgen_iteration_min_gap()
env, master, sps, reform = min_toy_gap()

@show master
@show sps

# vids = get_name_to_varids(master)
# cids = get_name_to_constrids(master)

Expand All @@ -519,11 +537,11 @@ function test_colgen_iteration_min_gap()
"MC_37" => 1/3,
)
master_lp_dual_sol = Dict(
"c1" => 1/3,
"c2" => 2/3,
"c5" => 1/3,
"c6" => 1/3,
"c7" => 1/3,
"c1" => 11.33333333,
"c2" => 17.33333333,
"c5" => 9.33333333,
"c6" => 13.66666667,
"c7" => 28.0,
)
master_obj_val = 79.67

Expand Down Expand Up @@ -553,7 +571,7 @@ function test_colgen_iteration_min_gap()
master_obj_val,
pricing_var_reduced_costs,
)
ClMP.push_optimizer!(master, () -> ClA.MoiOptimizer(GLPK.Optimizer()))
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()))
Expand Down Expand Up @@ -589,7 +607,6 @@ register!(unit_tests, "colgen_default", test_colgen_iteration_obj_const)




# master
# min
# 7x_12 + 2x_13 + x_14 + 5x_15 + 3x_23 + 6x_24 + 8x_25 + 4x_34 + 2x_35 + 9x_45 + 28λ1 + 25λ2 + 21λ3 + 19λ4 + 22λ5 + 18λ6 + 28λ7
Expand Down

0 comments on commit 6d4ac3d

Please sign in to comment.