Skip to content

Commit

Permalink
Possibility to specify global bounds for DW subproblem variables in f…
Browse files Browse the repository at this point in the history
…ormulation Parser (#1121)
  • Loading branch information
rrsadykov authored Jan 19, 2024
1 parent bc20f1f commit 1268124
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 10 deletions.
88 changes: 80 additions & 8 deletions src/Tests/Parser/Parser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module Parser
const _KW_SUBPROBLEM = Val{:subproblem}()
const _KW_SEPARATION = Val{:separation}()
const _KW_BOUNDS = Val{:bounds}()
const _KW_GLOBAL_BOUNDS = Val{:global_bounds}()
const _KW_CONSTRAINTS = Val{:constraints}()
const _KW_ORIGIN = Val{:origin}()
const _KW_SP_SOLUTIONS = Val{:sp_solutions}()
Expand All @@ -36,6 +37,9 @@ module Parser
# _KW_BOUNDS
"bound" => _KW_BOUNDS,
"bounds" => _KW_BOUNDS,
# _KW_GLOBAL_BOUNDS
"global_bound" => _KW_GLOBAL_BOUNDS,
"global_bounds" => _KW_GLOBAL_BOUNDS,
)

const _KW_SUBSECTION = Dict(
Expand Down Expand Up @@ -105,6 +109,8 @@ module Parser
duty::ClMP.Duty
lb::Float64
ub::Float64
global_lb::Float64
global_ub::Float64
end

mutable struct ConstrCache
Expand Down Expand Up @@ -333,10 +339,32 @@ module Parser
end
end

function read_global_bounds!(cache::ReadCache, line::AbstractString)
vars = String[]
if occursin("<=", line)
less_r = Regex("(($coeff_re)<=)?([\\w,]+)(<=($coeff_re))?")
vars, lb, ub = _read_bounds(line, less_r)
end
if occursin(">=", line)
greater_r = Regex("(($coeff_re)>=)?([\\w,]+)(>=($coeff_re))?")
vars, ub, lb = _read_bounds(line, greater_r)
end
for v in vars
if haskey(cache.variables, v)
if lb != ""
cache.variables[v].global_lb = parse(Float64, lb)
end
if ub != ""
cache.variables[v].global_ub = parse(Float64, ub)
end
end
end
end

function read_variables!(kind::ClMP.VarKind, duty::ClMP.Duty, cache::ReadCache, line::AbstractString)
vars = _get_vars_list(line)
for v in vars
cache.variables[v] = VarCache(kind, duty, -Inf, Inf)
cache.variables[v] = VarCache(kind, duty, -Inf, Inf, -Inf, Inf)
end
end

Expand Down Expand Up @@ -476,14 +504,32 @@ module Parser
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.AbstractOriginMasterVar || var.duty <= ClMP.AbstractAddedMasterVar
if var.duty <= ClMP.MasterCol
var_cache = cache.variables[varid]
if var_cache.duty <= ClMP.AbstractOriginMasterVar ||
var_cache.duty <= ClMP.AbstractAddedMasterVar
if var_cache.duty <= ClMP.MasterCol
origin_sp = _get_orig_sp_of_col(cache, varid, master)
v = ClMP.setvar!(master, varid, var.duty; lb = var.lb, ub = var.ub, kind = ClMP.Integ, is_explicit = true, origin = origin_sp)
v = ClMP.setvar!(
master,
varid,
var_cache.duty;
lb = var_cache.lb,
ub = var_cache.ub,
kind = ClMP.Integ,
is_explicit = true,
origin = origin_sp
)
else
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)
is_explicit = !(var_cache.duty <= ClMP.AbstractImplicitMasterVar)
v = ClMP.setvar!(
master,
varid,
var_cache.duty;
lb = var_cache.lb,
ub = var_cache.ub,
kind = var_cache.kind,
is_explicit = is_explicit
)
end
else
if haskey(all_spvars, varid)
Expand All @@ -496,7 +542,29 @@ module Parser
duty = ClMP.MasterPureVar
explicit = true
end
v = ClMP.clonevar!(sp, master, sp, var, duty; cost = ClMP.getcurcost(sp, var), is_explicit = explicit)
lb, ub, kind = if duty == ClMP.MasterRepPricingVar
# the representative of a binary variable in the master is integer in general
mast_kind = ClMP.getperenkind(sp, var) ==
ClMP.Continuous ? ClMP.Continuous : ClMP.Integ
var_cache.global_lb, var_cache.global_ub, mast_kind
else
ClMP.getperenlb(sp, var),
ClMP.getperenub(sp, var),
ClMP.getperenkind(sp, var)
end

v = ClMP.clonevar!(
sp,
master,
sp,
var,
duty;
cost = ClMP.getcurcost(sp, var),
is_explicit = explicit,
lb = lb,
ub = ub,
kind = kind
)
else
throw(UndefVarParserError("Variable $varid not present in any subproblem"))
end
Expand Down Expand Up @@ -695,6 +763,10 @@ module Parser
read_bounds!(cache, line)
continue
end
if section == _KW_GLOBAL_BOUNDS
read_global_bounds!(cache, line)
continue
end
read_variables!(section, sub_section, cache, line)
end

Expand Down
7 changes: 5 additions & 2 deletions test/integration/parser/parser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,9 @@ function minimize_test1()
pricing
z_1, z_2, z_3
global_bounds
0 <= y1 <= 1
bounds
20 >= x >= 0
0 <= y1 <= 1
Expand All @@ -359,10 +362,10 @@ function minimize_test1()

names, kinds, duties, costs, bounds = get_vars_info(master)
@test names == ["w", "x", "y2", "y1"]
@test kinds == [ClMP.Integ, ClMP.Integ, ClMP.Binary, ClMP.Binary]
@test kinds == [ClMP.Integ, ClMP.Integ, ClMP.Integ, ClMP.Integ]
@test duties == [ClMP.MasterPureVar, ClMP.MasterPureVar, ClMP.MasterRepPricingVar, ClMP.MasterRepPricingVar]
@test costs == [-5.0, 2.0, 1.0, 1.0]
@test bounds == [(-Inf, Inf), (0.0, 20.0), (0.0, 1.0), (0.0, 1.0)]
@test bounds == [(-Inf, Inf), (0.0, 20.0), (-Inf, Inf), (0.0, 1.0)]

constrs = get_constrs_info(master)
c1 = constrs[1] # x + w <= 9
Expand Down
25 changes: 25 additions & 0 deletions test/unit/Presolve/build_formulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ function presolve_toy_gap_with_penalties()
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
global_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
bounds
0.0 <= x_11 <= 1.0
0.0 <= x_21 <= 1.0
Expand Down Expand Up @@ -717,6 +733,15 @@ function presolve_reformulation_with_var_not_in_coeff_matrix()
representatives
x_11, x_12, x_13, x_14, x_15, x_16, x_17
global_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
bounds
0.0 <= x_11 <= 1.0
0.0 <= x_12 <= 1.0
Expand Down
8 changes: 8 additions & 0 deletions test/unit/Presolve/presolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,14 @@ function test_presolve_full()
representatives
x_1, x_2, x_3, x_4, x_6
global_bounds
0.0 <= x_1 <= 1.0
0.0 <= x_2 <= 1.0
0.0 <= x_3 <= 3.0
0.0 <= x_4 <= 3.0
0.0 <= x_5 <= 1.0
-Inf <= x_6 <= Inf
bounds
0.0 <= x_1 <= 1.0
0.0 <= x_2 <= 1.0
Expand Down

0 comments on commit 1268124

Please sign in to comment.