What is the best way to separate out indices of a variable?

Hi guys,

What do you recommend to do in this situation?

I have a set M consisting of three separate sets of vectors of various size. In other words M = [m_1, m_2, m_3] where m_i are vectors of different sizes. For instance m_1 could be 1:10 while m_2 = 22:65 and m_3 = 100:123(these are separate, no intersection in their elements).

with that, there need to have a variable x[i,j,m] to have some constraints as the following:

# N is a set which contains all net nodes 
# x,z are variables

x[i,j,m] >= z[i,j]    for all i,j in N and m in M  

Now, we have another variables that are only defined on m_i like y[i,j,m_1]. So, at some points in some constraints, there’s only need to put condition over a subset of M (not all of its components). Similar to the following:

#I'm not writing like julia-- more like math version

sum(x[i,j,m] for i in N) <= y[i, m]   for all  j in N and m in m_1

I did try to do this by:

@constraint(model, [j in N, m in m_1], sum( x[i,j,m]  for i in N) <=  y[i, m] ) 

This is not working though. Do you know how to do this? having a variables that can act both over the whole set M and also act locally over just m_1 or just m_2
I’m not sure if the issue is variable either. What I need to find out is that how to have flexible variable x that can handle M and m_1 at the same time.

Thanks all!

I think you need something like this:

M = [1:2, 4:5, 7:8]
model = Model()
all_M = unique(reduce(vcat, M))
@variable(model, x[all_M])
@expression(model, sum(x[m] for m in all_M))
@expression(model, sum(x[m] for m in M[1]))

What probably happened is that it used m_1, m_2, an m_3 as the keys of the variable, not the values of the m_ vectors as the keys.

1 Like

Thanks @odow This works fine when you only have one index for x, but when having x[i,j,m] it has some issue unless I change the way I defined variable (redefine them over set vs. tuples).

One thing that I’d like to know is that once you need to impose condition over your indices what is the best practice? I usually define variable over tuples. But not sure whether there’s any better (or difference) to write a variable like this:

m = Model();
I = [1: n_i]  # n_  is just an integer number
J = [1: n_j]
M = [1: n_m]

@variable(m, x[I,J,M] >= 0 , Bin);

Versus

m = Model();
I = [1: n_i]  # n_  is just an integer number
J = [1: n_j]
M = [1: n_m]

x_indices = [(i,j,m) for i in I  for j in J for m in M]
@variable(model, x[x_indices] >= 0, Bin)

Perhaps there’s a good practice that I’m unaware of it. But as a beginner I’m hungry to learn. So please recommend me one if there exist. Thanks!

I would say that the former is better for a single @variable declaration, since you’re not allocating an intermediate array (x_indices) but allowing JuMP to generate variables directly from your separate index sets. The latter is virtually equivalent but necessary if reusing an index set like x_indices in multiple locations.

There is the concept of generating values on demand in general in Julia: Generator Expressions.

2 Likes

Thanks for your info and the link @jd-foster I’ll check it out!

1 Like