Generate Variables JuMP

Hi,
I’m not sure if I had to make a new post or continue the old one, but as I have a new question I created a new topic.
I am solving an optimization problem with jump using the following table:

Row │ time  room_1   room_2   room_3   w_day     
     │ Float64  Float64  Float64  Float64  String  
─────┼─────────────────────────────────────────────
   1 │    10.0      2.0      1.0      5.0  Monday
   2 │    11.0      3.0      1.0      6.0  Monday

I need to create a binary variable x[time,room,w_day], my problem is that for time 10 I can only have courses 2, 1 and 5. that would get me x[10,2,Monday], x[10,1,Monday] and x[10,5,Monday].
I am to make the variable like this:

@variable(model, x[10,[1,2,5],["Monday"]], Bin)

From the 2 lines table above I would have to iterate through time [10 , 11]
getting:
x[10,2,Monday], x[10,1,Monday] and x[10,5,Monday]
x[11,3,Monday], x[11,1,Monday] and x[11,6,Monday]
But as I loop I get the error of “same name variable” (I understand that it is to prevent errors ), is there a way to make all the variables under the same variable array?
I found the topic of Anonymous Variables, but I’m not sure how I can use it to make my variables.
Thank you!

1 Like

There are a couple of options. The simplest would be to pre-compute the set of indices that you are interested in:

using JuMP, DataFrames
S = Tuple{Int,Int,String}[]
for row in eachrows(df)
    push!(S, (row.time, row.room_1, row.w_day))
    push!(S, (row.time, row.room_2, row.w_day))
    push!(S, (row.time, row.room_3, row.w_day))
end

model = Model()
@variable(model, x[S])

x[(10, 2, "Monday")]

Or you could do something like:

using JuMP, DataFrames
model = Model()
x = Dict(
    (Int(r.time), r.w_day) =>  @variable(model, [Int[r.room_1, r.room_2, r.room_3]])
    for r in eachrows(df)
)
x[(10, "Monday")][2]

It depends on what is in the rest of the data frame, and how you intend to use the variables.

A good part of JuMP is that it is flexible in how it lets you build data structures, but it’s also a bad part because there isn’t a single way to achieve things.

1 Like

Thanks for the answer, the first option works really well.
I ended up creating all the variables and a matrix of coeficients where 1 is “present” and 0 is “not”. So I ended up with this structure:

x[10.0,1.0,Segunda]  x[10.0,2.0,Segunda]  0                    0                    x[10.0,5.0,Segunda]  0

Worked all rigth, but it gives me extra variables so I believe your solution would be better.
Thanks again, as I’m new to Julia these insigths really help.
Cheers!

1 Like

Along that note, you could also use

times = [10, 11]
rooms = [1, 2, 3, 4, 5, 6]
days = ["Monday", "Tuesday"]
model = Model()
@variable(model, x[times, rooms, days], Bin)
# Disable rooms that we can't use by fixing their values to 0
for row in eachrow(df)
    for room in setdiff(rooms, Int[row.room_1, row.room_2, row.room_3])
        fix(x[Int(row.time), room, row.w_day], 0)
    end
end
1 Like