Skip to content

Commit

Permalink
• Corrections in the presolve algorithm
Browse files Browse the repository at this point in the history
• A better `Base.show` function for `PrimalSolution` which can show expanded view of columns
  • Loading branch information
rrsadykov committed Jan 18, 2024
1 parent fad7b99 commit 0d9c693
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/Algorithm/presolve/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ function update_multiplicities!(presolve_repr_master, presolve_sp, feasible::Boo
varid = getid(var)
master_col = presolve_repr_master.var_to_col[varid]
global_lb = presolve_repr_master.form.lbs[master_col]
global_ub = presolve_repr_master.form.lbs[master_col]
global_ub = presolve_repr_master.form.ubs[master_col]

# update of lower multiplicity
if global_lb > 0 && local_ub > 0
Expand Down
6 changes: 3 additions & 3 deletions src/Algorithm/presolve/propagation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function propagate_local_bounds!(
local_lb = presolve_sp.form.lbs[i]
local_ub = presolve_sp.form.ubs[i]

if !isinf(global_lb) && !isinf(local_ub)
if !isinf(global_lb) && !isinf(local_ub) && !isinf(um)
new_local_lb = global_lb - (um - 1) * local_ub
presolve_sp.form.lbs[i] = max(new_local_lb, local_lb)
end
Expand Down Expand Up @@ -129,8 +129,8 @@ function compute_repr_master_var_domains(
ub = getcurub(sp_form, var)

(global_lb, global_ub) = get(sp_domains, varid, (0.0, 0.0))
global_lb += (lb > 0 ? lm : um) * lb
global_ub += (ub > 0 ? um : lm) * ub
global_lb += isinf(lb) ? lb : (lb > 0 ? lm : um) * lb
global_ub += isinf(ub) ? ub : (ub > 0 ? um : lm) * ub

sp_domains[varid] = (global_lb, global_ub)
end
Expand Down
20 changes: 18 additions & 2 deletions src/MathProg/solutions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,25 @@ function Base.show(io::IO, solution::DualSolution{M}) where {M}
end

function Base.show(io::IO, solution::PrimalSolution{M}) where {M}
model = getmodel(solution)
user_only = get(io, :user_only, false) && model isa Formulation
println(io, "Primal solution")
for (varid, value) in solution
println(io, "| ", getname(getmodel(solution), varid), " = ", value)
for (varid, value) in solution
if user_only && isaNonUserDefinedDuty(getduty(varid))
if getduty(varid) <= MasterCol
print(io, "| ", getname(model, varid), " = [")
origin_form_uid = getoriginformuid(varid)
spform = get_dw_pricing_sps(getparent(model))[origin_form_uid]
spsol = @view get_primal_sol_pool(spform).solutions[varid, :]
for (sp_var_id, sp_value) in spsol
isaNonUserDefinedDuty(getduty(sp_var_id)) && continue
print(io, getname(spform, sp_var_id), " = ", sp_value, " ")
end
println(io, "] = ", value)
end
else
println(io, "| ", getname(model, varid), " = ", value)
end
end
Printf.@printf(io, "└ value = %.2f \n", getvalue(solution))
end
Expand Down
Empty file.
83 changes: 51 additions & 32 deletions test/unit/Presolve/presolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -461,20 +461,22 @@ function test_presolve_full()
formstring = """
master
min
1.0 x_1 + 1.0 x_2 + 1.0 x_3 + 1.0 x_4 + 1.0 x_5 + 0.0 PricingSetupVar_sp_5 + 0.0 PricingSetupVar_sp_4
1.0 x_1 + 1.0 x_2 + 1.0 x_3 + 1.0 x_4 + 1.0 x_5 + 0.0 x_6 + 0.0 PricingSetupVar_sp_6 + 0.0 PricingSetupVar_sp_5 + 0.0 PricingSetupVar_sp_4
s.t.
2.0 x_1 + 3.0 x_2 + 1.0 x_3 + 0.0 x_4 + 1.0 x_5 == 5.0
0.0 x_1 + 0.0 x_2 + 0.0 x_3 + 1.0 x_4 + 0.0 x_5 >= 2.0
2.0 x_1 + 3.0 x_2 + 1.0 x_3 + 0.0 x_4 + 1.0 x_5 + 0.0 x_6 == 5.0
0.0 x_1 + 0.0 x_2 + 0.0 x_3 + 1.0 x_4 + 0.0 x_5 + 0.0 x_6 >= 2.0
1.0 PricingSetupVar_sp_4 >= 0.0 {MasterConvexityConstr}
1.0 PricingSetupVar_sp_4 <= 2.0 {MasterConvexityConstr}
1.0 PricingSetupVar_sp_5 >= 0.0 {MasterConvexityConstr}
1.0 PricingSetupVar_sp_5 <= 2.0 {MasterConvexityConstr}
1.0 PricingSetupVar_sp_6 >= 0.0 {MasterConvexityConstr}
1.0 PricingSetupVar_sp_6 <= 0.0 {MasterConvexityConstr}
dw_sp
min
x_3 + x_4 + 0.0 PricingSetupVar_sp_5
x_6 + 0.0 PricingSetupVar_sp_6
s.t.
1.0 x_3 + 1.0 x_4 >= 4.0
1.0 x_6 <= 1.0
dw_sp
min
Expand All @@ -484,24 +486,32 @@ function test_presolve_full()
solutions
1.0 x_1 {MC_1}
dw_sp
min
x_3 + x_4 + 0.0 PricingSetupVar_sp_5
s.t.
1.0 x_3 + 1.0 x_4 >= 4.0
continuous
pure
x_5
integer
pricing_setup
PricingSetupVar_sp_4, PricingSetupVar_sp_5
PricingSetupVar_sp_4, PricingSetupVar_sp_5, PricingSetupVar_sp_6
representatives
x_1, x_2, x_3, x_4
x_1, x_2, x_3, x_4, x_6
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
1.0 <= PricingSetupVar_sp_4 <= 1.0
1.0 <= PricingSetupVar_sp_5 <= 1.0
1.0 <= PricingSetupVar_sp_6 <= 1.0
"""
env, master, sps, _, reform = reformfromstring(formstring)

Expand Down Expand Up @@ -545,35 +555,44 @@ function test_presolve_full()
@test Coluna.MathProg.getcurrhs(master, master_constrs["c5"]) == 1.0 # l_mult of sp5
@test Coluna.MathProg.getcurrhs(master, master_constrs["c6"]) == 1.0 # u_mult of sp5

for sp in sps
sp_vars = Dict{String, Coluna.MathProg.VarId}(
Coluna.MathProg.getname(sp, var) => varid
for (varid, var) in Coluna.MathProg.getvars(sp)
)
if findfirst(name->name == "x_3",collect(keys(sp_vars))) !== nothing
@test Coluna.MathProg.getcurlb(sp, sp_vars["x_3"]) == 2.0
@test Coluna.MathProg.getcurub(sp, sp_vars["x_3"]) == 2.0
@test Coluna.MathProg.getcurlb(sp, sp_vars["x_4"]) == 2.0
@test Coluna.MathProg.getcurub(sp, sp_vars["x_4"]) == 3.0
elseif findfirst(name->name == "x_1",collect(keys(sp_vars))) !== nothing
@test Coluna.MathProg.getcurub(sp, sp_vars["x_1"]) == 0.0
@test Coluna.MathProg.getcurlb(sp, sp_vars["x_2"]) == 1.0
end

end

master_partal_sol = Coluna.MathProg.getpartialsol(master)
@test master_partal_sol[master_vars["x_5"]] == 1.0
@test master_partal_sol[master_vars["MC_1"]] == 1.0

sp5_index = findfirst(sp->Coluna.MathProg.getuid(sp) == 5, sps)
@test sp5_index !== nothing
sp5 = sps[sp5_index]
sp5_vars = Dict{String, Coluna.MathProg.VarId}(
Coluna.MathProg.getname(sp5, var) => varid
for (varid, var) in Coluna.MathProg.getvars(sp5)
)

@test Coluna.MathProg.getcurlb(sp5, sp5_vars["x_3"]) == 2.0
@test Coluna.MathProg.getcurub(sp5, sp5_vars["x_3"]) == 2.0
@test Coluna.MathProg.getcurlb(sp5, sp5_vars["x_4"]) == 2.0
@test Coluna.MathProg.getcurub(sp5, sp5_vars["x_4"]) == 3.0

sp4_index = findfirst(sp->Coluna.MathProg.getuid(sp) == 4, sps)
@test sp4_index !== nothing
sp4 = sps[sp4_index]
sp4_vars = Dict{String, Coluna.MathProg.VarId}(
Coluna.MathProg.getname(sp4, var) => varid
for (varid, var) in Coluna.MathProg.getvars(sp4)
)

@test Coluna.MathProg.getcurub(sp4, sp4_vars["x_1"]) == 0.0
@test Coluna.MathProg.getcurlb(sp4, sp4_vars["x_2"]) == 1.0


# testing "expanded" printing of a primal solution with columns
primal_solution = Coluna.MathProg.PrimalSolution(
master,
[master_vars["MC_1"], master_vars["x_5"]],
[1.0, 1.0],
1.0,
Coluna.ColunaBase.FEASIBLE_SOL
)
_io = IOBuffer()
print(IOContext(_io, :user_only => true), primal_solution)
@test String(take!(_io)) ==
"""
Primal solution
| x_5 = 1.0
| MC_1 = [x_1 = 1.0 ] = 1.0
└ value = 1.00
"""
return nothing
end

Expand Down

0 comments on commit 0d9c693

Please sign in to comment.