List comprehension of JuMP variables

Beginner to Julia and want to quickly recapitulate an ILP model I wrote in Python to evaluate speed in JuMP.

I’m wondering how list comprehensions work for JuMP objects?

In Python, I use list comprehension to make the following constraints:

# PYTHON
for k in range(0,math.ceil(K_window/34)):
    model.addConstr(y_i_k.sum('*',[l for l in range(k*34,min(k*34+34,K_window))]) <=1,name='Seen_'+str(k))

After reading about Julia syntax on list comprehension, I tried the following but it does not work:

# JULIA
for k in 1:floor(Int, K_window/34)
    @constraint(model, sum(y_i_k[:, l] for l in (k*34):min(k*34, min(k*34+34, K_window)), dims=1) <=1)
end

I realize this is question may alternatively be categorized as “First Steps”, I have a hunch it’s just me not understanding Julia syntax? Thank you for your help.

So y_i_k[:, l] is the lth column of y_i_k. So the sum is a vector. Then you constraint this sum to be smaller than 1. What does it means for a vector to be smaller than a number ?
If you want each entry to be smaller than 1, do .<= instead of <=.

2 Likes

I see, I’d like to get the column sum. I was expecting a scalar output, rather than a vector.

More explicitly, I want the sum of all entry in that column to be less than or equal to 1

Here, you are constraining, for each row, the sum of all entries of that row that are in the column range (k*34):min(k*34, min(k*34+34, K_window)) to be smaller than or equal to 1.

1 Like

Oops, yes you are right, I am trying to constrain each row sum of given indeces to be less than or equal to 1.

I find the following expression works. Maybe there is a more elegant way of writing this?

for k in 1:floor(Int, K_window/34)
    @constraint(model, [i in 1:I_round], sum(y_i_k[i, l] for l in [k*34:min(k*34, min(k*34+34, K_window))]) <=1)
end

I doesn’t work for me because [k*34:min(k*34, min(k*34+34, K_window))] is a vector containing one range so the for loop has one iteration with l = k*34:min(k*34, min(k*34+34, K_window)) and the sum is therefore the some of one term which is the term itself and you are left with a vector that cannot be compared to 1.
So either do
sum(y_i_k[i, l] for l in k*34:min(k*34, min(k*34+34, K_window)))
or
sum(y_i_k[i, k*34:min(k*34, min(k*34+34, K_window))])

1 Like

Thank you for your patience and guidance @blegat!

May I ask why sometimes the list comprehensions look like they are “evaluated”, rather than expressed?

What I mean is, in Python I have written this line:

for i in range(I_round):
    for k in range(K_window):
        model.addConstr(gp.quicksum(r_i_j[i,j]*y_i_k[i,k]*s_j_k[j,k] for j in range(J))>= T1*y_i_k[i,k])

In Julia, the following are not expressed as terms of r_i_j*y_i_k*s_j_k, but directly evaluated (0). I wonder why this is the case?

for i in 1:I_round
    for k in 1:K_window
        @constraint(model, sum(r_i_j[i,1:J]*y_i_k[i,k]*s_j_k[1:J,k]) >= T1*y_i_k[i,k] )
    end
end

Hi there! Since you’re new to Julia, please read this post.

In particular, it’s easier to help if you provide a minimal working example that we can copy-paste and see the same result.

but directly evaluated (0)

Presumably, there is a typo somewhere. I can’t say more because I can’t run your code. The direct equivalent of your Python constraint is:

@constraint(
    model, 
    [i=1:I_round, k=1:K_window],
    sum(r_i_j[i, j] * y_i_k[i, k] * s_j_k[j, k] for j in 1:J) >= T1 * y_i_k[i, k],
)
1 Like

I see, the indeces can be provided outside the summation, and the list comprehension can still be employed inside.

I will read over the introductory post, thank you for pointing me to this reference!