Skip to content

Commit

Permalink
global bounds for representatives of different subproblems (#1075)
Browse files Browse the repository at this point in the history
  • Loading branch information
guimarqu authored Sep 22, 2023
1 parent 9a1cc4b commit cb8cf62
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 3 deletions.
15 changes: 13 additions & 2 deletions src/decomposition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,26 @@ function instantiate_orig_vars!(
end

if !haskey(masterform, varid)
lb, ub = if is_representative(annotations, varid)
(
getperenlb(origform, var) * sum(BD.getlowermultiplicity.(annotations.ann_per_repr_var[varid])),
getperenub(origform, var) * sum(BD.getuppermultiplicity.(annotations.ann_per_repr_var[varid]))
)
else
(
getperenlb(origform, var) * BD.getlowermultiplicity(sp_ann),
getperenub(origform, var) * BD.getuppermultiplicity(sp_ann)
)
end
clonevar!(
origform,
masterform,
spform,
var,
MasterRepPricingVar,
is_explicit = false,
lb = getperenlb(origform, var) * BD.getlowermultiplicity(sp_ann),
ub = getperenub(origform, var) * BD.getuppermultiplicity(sp_ann)
lb = lb,
ub = ub
)
end
end
Expand Down
95 changes: 94 additions & 1 deletion test/unit/MathProg/dw_decomposition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,97 @@ function dw_decomposition_with_identical_subproblems()
@test Coluna.MathProg.getcurlb(sp1, sp1_vars["x2"]) == 2.0
@test Coluna.MathProg.getcurub(sp1, sp1_vars["x2"]) == 3.0
end
register!(unit_tests, "dw_decomposition", dw_decomposition_with_identical_subproblems)
register!(unit_tests, "dw_decomposition", dw_decomposition_with_identical_subproblems)

function dw_decomposition_repr()
"""
min e1
s.t. e1 >= 4
sp1 : 1 <= e1 <= 2 with lm = 0, lm= 2
sp2 : 1 <= e2 <= 3 with lm = 1, lm= 3
"""

env = Coluna.Env{Coluna.MathProg.VarId}(
Coluna.Params(
global_art_var_cost = 1000.0,
local_art_var_cost = 100.0
)
)

origform = Coluna.MathProg.create_formulation!(
env, Coluna.MathProg.Original()
)

# Variables
vars = Dict{String, Coluna.MathProg.VarId}()
e1 = Coluna.MathProg.getid(
Coluna.MathProg.setvar!(
origform, "e1", Coluna.MathProg.OriginalVar;
cost = 1.0, lb = 1.0, ub = 2.0, kind = Integ
)
)

# Constraints
constrs = Dict{String, Coluna.MathProg.ConstrId}()
c1 = Coluna.MathProg.getid(
Coluna.MathProg.setconstr!(
origform, "c1", Coluna.MathProg.OriginalConstr; rhs = 4.0, sense = Coluna.MathProg.Greater, members = Dict(e1 => 1.0)
)
)

# Decomposition tree
m = JuMP.Model()
BlockDecomposition.@axis(axis, [1, 2])
tree = BlockDecomposition.Tree(m, BlockDecomposition.DantzigWolfe, axis)
mast_ann = tree.root.master
sp_ann1 = BlockDecomposition.Annotation(tree, BlockDecomposition.DwPricingSp, BlockDecomposition.DantzigWolfe, [])
BlockDecomposition.setlowermultiplicity!(sp_ann1, 0)
BlockDecomposition.setuppermultiplicity!(sp_ann1, 2)
BlockDecomposition.create_leaf!(BlockDecomposition.getroot(tree), axis[1], sp_ann1)
sp_ann2 = BlockDecomposition.Annotation(tree, BlockDecomposition.DwPricingSp, BlockDecomposition.DantzigWolfe, [])
BlockDecomposition.setlowermultiplicity!(sp_ann2, 1)
BlockDecomposition.setuppermultiplicity!(sp_ann2, 3)
BlockDecomposition.create_leaf!(BlockDecomposition.getroot(tree), axis[2], sp_ann2)

# Dantzig-Wolfe annotations
ann = Coluna.Annotations()
ann.tree = tree
Coluna.store!(ann, mast_ann, Coluna.MathProg.getconstr(origform, c1))
Coluna.store_repr!(ann, [sp_ann1, sp_ann2], Coluna.MathProg.getvar(origform, e1))

problem = Coluna.MathProg.Problem(env)
Coluna.MathProg.set_original_formulation!(problem, origform)

Coluna.reformulate!(problem, ann, env)
reform = Coluna.MathProg.get_reformulation(problem)

# Test master
master = Coluna.MathProg.getmaster(reform)
master_vars = Dict(getname(master, varid) => var for (varid, var) in Coluna.MathProg.getvars(master))
master_constrs = Dict(getname(master, constrid) => constr for (constrid, constr) in Coluna.MathProg.getconstrs(master))

@show length(master_vars)
@test Coluna.MathProg.getcurlb(master, master_vars["e1"]) == 1.0 * (0 + 1)
@test Coluna.MathProg.getcurub(master, master_vars["e1"]) == 2.0 * (2 + 3)
@test Coluna.MathProg.getcurrhs(master, master_constrs["c1"]) == 4.0

# Test subproblem 1
sp1 = first(values(Coluna.MathProg.get_dw_pricing_sps(reform)))
sp1_vars = Dict(getname(sp1, varid) => var for (varid, var) in Coluna.MathProg.getvars(sp1))
sp1_constrs = Dict(getname(sp1, constrid) => constr for (constrid, constr) in Coluna.MathProg.getconstrs(sp1))

@test length(sp1_vars) == 2
@test Coluna.MathProg.getcurlb(sp1, sp1_vars["e1"]) == 1.0
@test Coluna.MathProg.getcurub(sp1, sp1_vars["e1"]) == 2.0

# Test subproblem 2
sp2 = collect(values(Coluna.MathProg.get_dw_pricing_sps(reform)))[2]
sp2_vars = Dict(getname(sp2, varid) => var for (varid, var) in Coluna.MathProg.getvars(sp2))
sp2_constrs = Dict(getname(sp2, constrid) => constr for (constrid, constr) in Coluna.MathProg.getconstrs(sp2))

@test length(sp2_vars) == 2
@test Coluna.MathProg.getcurlb(sp1, sp2_vars["e1"]) == 1.0
@test Coluna.MathProg.getcurub(sp1, sp2_vars["e1"]) == 2.0
end
register!(unit_tests, "dw_decomposition", dw_decomposition_repr)

0 comments on commit cb8cf62

Please sign in to comment.