JuMP/GLPK with equal upper and lower bounds

Hello,

I’m solving a linear optimization problem with JuMP (0.19.2) using GLPK.jl (0.10.0) as the solver. I’m struggling with the situation where the lower and upper bounds of a variable are equal (and because it’s in a vector of inequalities, I can’t just simply remove the variable). Here is a MWE:

using JuMP #Call the modeling language
using GLPK # Call the solver 
probm = Model(with_optimizer(GLPK.Optimizer,))
 
@variable(probm, x[1:2])
xmax = [10., 0.]
@constraint(probm, 0. .<= x .<= xmax)
 
@objective(probm, Min, 0)

optimize!(probm)

The output is:

glp_simplex: row 2: lb = 0, ub = 0; incorrect bounds

I found related discussion on GLPK mailing list, and a slightly similar thread here but with Ipopt. However, I wonder if it’s possible to use GLPK here (with Clp it works). Maybe it’s possible to switch to using GLPK’s interior point solver, but I don’t know how. And maybe someone would have a better trick! Thanks for your help!

So the issue is an ScalarAffineFunction-in-Interval constraint with identical bounds. There are multiple work-arounds:

# Works
model = Model(with_optimizer(GLPK.Optimizer))
@variable(model, x == 1)  
optimize!(model)

# Works
model = Model(with_optimizer(GLPK.Optimizer))
@variable(model, 1 <= x <= 1) 
optimize!(model)

# Works
model = Model(with_optimizer(GLPK.Optimizer))
@variable(model, x)
@constraint(model, x == 1)
optimize!(model)

# Works
model = Model(with_optimizer(GLPK.Optimizer))
@variable(model, x)
@constraint(model, x >= 1)
@constraint(model, x <= 1)
optimize!(model)

# Doesn't work
model = Model(with_optimizer(GLPK.Optimizer))
@variable(model, x)
@constraint(model, 1 <= x <= 1)
optimize!(model)

Going forward, one option is to remove ScalarAffineFunction-in-Interval support from GLPK.jl and use a bridge to convert it into two constraints.

2 Likes

Thanks for the feedback. Among your propositions, I cannot take the ones with the == operator since I have vector bounds with some elements equal and some other unequals. However, splitting the constraint into two works (workaround 4), and using setting the variable bounds works as well (workaround 2).

I have one side question about the latter case, since I’m working with vectors. It seems I cannot set variable bounds using broadcasting notation:

xmax = [10., 0.]
@variable(model, 0 <= x[1:2] .<= xmax)

yields the error

In `@variable(model, 0 <= x[1:2] .<= xmax)`: Use the form lb <= ... <= ub.

Stacktrace:
 [1] error(::String, ::String) at ./error.jl:42
 [2] _macro_error(::Symbol, ::Tuple{Symbol,Expr}, ::String) at /home/pierre/.julia/packages/JuMP/ibcEh/src/macros.jl:1105
 [3] (::getfield(JuMP, Symbol("#_error#68")){Tuple{Symbol,Expr}})(::String) at /home/pierre/.julia/packages/JuMP/ibcEh/src/macros.jl:1341
 [4] parse_ternary_variable(::getfield(JuMP, Symbol("#_error#68")){Tuple{Symbol,Expr}}, ::JuMP._VariableInfoExpr, ::Val{:<=}, ::Int64, ::Val{:.<=}, ::Expr) at /home/pierre/.julia/packages/JuMP/ibcEh/src/macros.jl:1194
 [5] parse_variable(::Function, ::JuMP._VariableInfoExpr, ::Int64, ::Symbol, ::Expr, ::Symbol, ::Symbol) at /home/pierre/.julia/packages/JuMP/ibcEh/src/macros.jl:1199
 [6] @variable(::LineNumberNode, ::Module, ::Vararg{Any,N} where N) at /home/pierre/.julia/packages/JuMP/ibcEh/src/macros.jl:1376

Maybe this relates to issue #1455 broadcasting a JuMParray?

A working syntax is with using an explicit indexing variable:

@variable(model, 0 <= x[i=1:2] <= xmax[i])

Is it indeed the recommended way to define bounds on vector variables?

Explicit indexing is the way to go. The error message could be improved in the previous case. Want to open a GitHub issue at JuMP.jl?

You could also open an issue at GLPK.jl to remove direct support for interval constraints.

Ok, here is the issue for JuMP error message:

1 Like

And here is the GLPK.jl issue:

1 Like