jump-dev / JuMP.jl

Modeling language for Mathematical Optimization (linear, mixed-integer, conic, semidefinite, nonlinear)
http://jump.dev/JuMP.jl/
Other
2.22k stars 393 forks source link

Diagnostics request: using variable in variable container bounds #3652

Closed LebedevRI closed 8 months ago

LebedevRI commented 8 months ago
using JuMP, SCIP

model = Model(SCIP.Optimizer)

max_a = 10

@variable(model, a, Int)

@variable(model, b[1:a], Int) 
# Should have been: @variable(model, b[1:max_a], Int) 
MethodError: no method matching (::Colon)(::Int64, ::VariableRef)

Closest candidates are:
  (::Colon)(::T, ::Any, ::T) where T<:Real
   @ Base range.jl:50
  (::Colon)(::A, ::Any, ::C) where {A<:Real, C<:Real}
   @ Base range.jl:10
  (::Colon)(::T, ::Any, ::T) where T
   @ Base range.jl:49
  ...

Stacktrace:
 [1] macro expansion
   @ ~/.julia/packages/JuMP/027Gt/src/macros.jl:375 [inlined]
 [2] top-level scope
   @ In[2]:6

I understand that this does not work, i meant to use max_a instead, but the diagnostic was not as helpful. Might it be possible to improve it perhaps?

LebedevRI commented 8 months ago

Same with

using JuMP, SCIP

model = Model(SCIP.Optimizer)

max_a = 10

@variable(model, a, Int)

@variable(model, b[1:max_a], Int) 
@constraint(model, [i=1:a], b[i] > 0)
# Should have been @constraint(model, [i=1:max_a], b[i] > 0)
odow commented 8 months ago

I don't know about this specific case. We'd have to intercept the method (::Colon)(::Int64, ::VariableRef). The issue is 1:a, regardless of the fact it appears in an @variable macro. But if we intercepted the method, we wouldn't be able give a good error message for the macro. We also can't tell, syntactically looking at @variable(model, b[1:a], Int) that a is a variable.

What we should do is improve the general case in which an error is thrown during parsing of the macro, because it is currently:

julia> @variable(model, b[1:a])
ERROR: MethodError: no method matching (::Colon)(::Int64, ::VariableRef)

Closest candidates are:
  (::Colon)(::T, ::Any, ::T) where T<:Real
   @ Base range.jl:50
  (::Colon)(::A, ::Any, ::C) where {A<:Real, C<:Real}
   @ Base range.jl:10
  (::Colon)(::T, ::Any, ::T) where T
   @ Base range.jl:49
  ...

Stacktrace:
 [1] macro expansion
   @ ~/.julia/dev/JuMP/src/macros.jl:375 [inlined]
 [2] top-level scope
   @ REPL[4]:1
LebedevRI commented 8 months ago

What we should do is improve the general case in which an error is thrown during parsing of the macro, because it is currently:

Here's another example, not sure if should go into another issue:

using JuMP, SCIP

model = Model(SCIP.Optimizer)

max_a = 10

@variable(model, a, Int)

@variable(model, b[1:max_a,1:max_a,], Int) 
@variable(model, c[1:max_a,1:max_a,], Bin) 

@constraint(model, [i=1:max_a, k=1:max_a], b[i,k] == 0

@constraint(model, [i=1:max_a, j=1:max_a], b[i,j] == c[i,j] * b[i,k])
# Should be  @constraint(model, [i=1:max_a, j=1:max_a], b[i,j] == c[i,j] * b[i,j])
ParseError:
# Error @ ]8;;file:///home/lebedevri/In[17]#14:1\In[17]:14:1]8;;\

@constraint(model, [i=1:max_a, j=1:max_a], b[i,j] == c[i,j] * b[i,k])
└──────────────────────────────────────┘ ── Expected `)`

Stacktrace:
 [1] top-level scope
   @ In[17]:14
odow commented 8 months ago

The parse error is because of @constraint(model, [i=1:max_a, k=1:max_a], b[i,k] == 0. You're missing a ).

As a comment, none of these are JuMP related. They're all just plain bugs in your code.