Skip to content

Commit 670d2fa

Browse files
authored
Fix VariableBasisStatus and add test (#214)
1 parent 254aa6d commit 670d2fa

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

src/MOI_wrapper/MOI_wrapper.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,16 +2199,16 @@ function MOI.get(
21992199
_throw_if_optimize_in_progress(model, attr)
22002200
col = column(model, x)
22012201
vbasis = glp_get_col_stat(model, col)
2202-
if vbasis == GLP_BS
2202+
if vbasis == GLP_BS # basic variable
22032203
return MOI.BASIC
2204-
elseif vbasis == GLP_NL
2204+
elseif vbasis == GLP_NL # non-basic variable having active lower bound
22052205
return MOI.NONBASIC_AT_LOWER
2206-
elseif vbasis == GLP_NU
2206+
elseif vbasis == GLP_NU # non-basic variable having active upper bound
22072207
return MOI.NONBASIC_AT_UPPER
2208-
elseif vbasis == GLP_NF
2209-
return MOI.NONBASIC
2210-
else
2211-
@assert vbasis == GLP_NS
2208+
elseif vbasis == GLP_NF # non-basic free variable
22122209
return MOI.SUPER_BASIC
2210+
else
2211+
@assert vbasis == GLP_NS # nonbasic fixed variable
2212+
return MOI.NONBASIC
22132213
end
22142214
end

test/MOI_wrapper.jl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,58 @@ function test_unbounded_ray()
492492
return
493493
end
494494

495+
"""
496+
test_variable_basis_status()
497+
498+
This is a specially crafted linear program to expose the different variable
499+
basis behavior of GLPK. Because the problem is degenerate, this test might break
500+
in a future update of GLPK, but it works with GLPK_jll@5.0.0.
501+
502+
Example constructed from a model provided by @guimarqu in
503+
https://github.com/jump-dev/GLPK.jl/pull/213.
504+
"""
505+
function test_variable_basis_status()
506+
str = """
507+
variables: x1, x2, x3, x4, x5, x6, x7, x8, x9
508+
minobjective: 1.0 * x9
509+
c1: x1 + x2 + x4 <= 1.0
510+
c4: x8 + x3 + x5 <= 1.0
511+
c7: x1 + x2 + x4 >= 1.0
512+
c8: x3 + x5 >= 1.0
513+
c9: -1.0*x1 >= 0.0
514+
c10: x5 + x3 >= 0.0
515+
c11: x6 + -1.0*x2 >= 0.0
516+
c17: x9 + -72.0*x1 + -108.0*x2 + -26.0*x3 + -144.0*x4 + -130.0*x5 + -18.0*x6 >= -202.0
517+
x1 in Interval(0.0, 1.0)
518+
x2 in Interval(0.0, 1.0)
519+
x3 in Interval(0.0, 1.0)
520+
x4 in Interval(0.0, 1.0)
521+
x5 in Interval(0.0, 1.0)
522+
x6 in Interval(0.0, 1.0)
523+
x7 in Interval(0.0, 0.0)
524+
x9 >= 0.0
525+
"""
526+
model = GLPK.Optimizer()
527+
MOI.Utilities.loadfromstring!(model, str)
528+
MOI.optimize!(model)
529+
x = MOI.get(model, MOI.ListOfVariableIndices())
530+
status = MOI.get.(model, MOI.VariableBasisStatus(), x)
531+
x_val = MOI.get.(model, MOI.VariablePrimal(), x)
532+
@test x_val == [0, 0, 1, 1, 0, 0, 0, 0, 0]
533+
@test status == [
534+
MOI.BASIC, # x1 is [0, 1] at 0 but in basis => degenerate
535+
MOI.BASIC, # x2 is [0, 1] at 0 but in basis => degenerate
536+
MOI.NONBASIC_AT_UPPER, # x3 is [0, 1] at 1
537+
MOI.NONBASIC_AT_UPPER, # x4 is [0, 1] at 1
538+
MOI.NONBASIC_AT_LOWER, # x5 is [0, 1] at 0
539+
MOI.NONBASIC_AT_LOWER, # x6 is [0, 1] at 0
540+
MOI.NONBASIC, # x7 is fixed variable
541+
MOI.SUPER_BASIC, # x8 is a free variable at 0
542+
MOI.NONBASIC_AT_LOWER, # x9 is >= 0 at 0
543+
]
544+
return
545+
end
546+
495547
end # module
496548

497549
TestMOIWrapper.runtests()

0 commit comments

Comments
 (0)