JuMP mutually exclusive indices iterated over the same set

Hello,

I am new here and a relatively new Julia user. I have a constraint in a model I am writing where I have variables twice indexed over the same set, but I need the indices to iterate mutually exclusively. The code is:

(ThreeZH2 is the model name, variables start with ‘v’, constraints start with ‘c’, say ‘vTNUM’ is a variable, ‘cTCAP’ is a constraint)

@constraints(ThreeZH2, begin 
    cTCap[t in T, l in L, n in N, m in N],
        transport.max_flow[l,n,m] * (vTNUM[n,m] + vTNUM[m,n]) >= vFLOW[t,l,n,m] + vFLOW[t,l,m,n] 

    cTSym[l in L, n in N, m in M]
        vTNUM[n,m] == vTNUM[m,n]
end)

for context, variables start with ‘v’ such as vTNUM is a variable. The indices n and m are both indexed over the set ‘N’ which is say 1:3, or in general 1:p where p is some number (For my model N = 1:3).

The problem is if I run this constraint n and m can both equal the same number at the same time, say n = 2 and m = 2. I need the indices n and m to be mutually exclusive where m does not equal n. I’m sorry if I am not explaining this well, I hope the problem statement is clear. I feel like the solution should be simple but I cannot figure it out. Any suggestions would be very helpful! Sorry if there is another post with this solution but I could not find one.

Thank you!

1 Like

Hi there!

Use ; m != n]:

model = Model()
@variable(model, x[1:4])
@constraint(model, c[a=1:4, b=1:4; a != b], x[a] + x[b] == 1)

Docs: https://jump.dev/JuMP.jl/stable/constraints/#SparseAxisArrays

2 Likes

Thank you for such a quick reply! Goodness, I knew it would be something simple, I tried
m != n in N but of course didn’t work so wasn’t sure that was the right way. I’ll use cTCap[t in T, l in L, n in N, m != n].

Just to check for concept purposes… this means m is also indexed by the same set as n but not equal to the n? Straightforward, thank you again!

You want cTCap[t in T, l in L, n in N, m in N; m != n]. (The semicolon ; is important.) You can read this as “for t in T, l in L, n in N, and m in N, where m is not equal to n”.

2 Likes

Perfect, I am glad I checked. Still learning, and I appreciate all the help. That makes a lot of sense.

2 Likes

To anyone curious, I found another iteration of this problem.

In a new iteration of this problem, I have the variable vFLOW[t,l,n,m] where n and m are indices both defined over the set N. I have a constraint that is defined over n in N but not over the index m. Instead, I sum over m for the variable vFLOW[t,l,n,m] within the constraint. However, since I have defined the variable vFLOW[t,l,n,m] as vFLOW[t in T, l in L, n in N, m in N; m != n] >= 0, I must sum over m in N; m != n.

When I run this constraint I get the error:

ERROR: syntax: invalid keyword argument syntax “(m != n)” around /Users/parispijuan/.julia/packages/MutableArithmetics/bPWR4/src/rewrite.jl:276
Stacktrace:
[1] top-level scope at REPL[93]:1

However, if I remove the the m != n I get an error telling me there is now vFLOW[1,1,1,1], because, of course, I have defined the variable so that m != n.

I guess one work around is to define the variable vFLOW[t,l,n,m] to be zero for n = m and just sum normally but I was wondering if there was another way.

The full constraint is:

STARTS and INTERIORS are subsets of the full time of the model, set T. hpp is "hours_per_period". These are wrapping constraints for time reduction. But the problem is actually in the sum. 


    # -- G) State of Charge constraint + Wrap
    @constraints(ThreeZH2, begin
        cSOC[t in INTERIORS, s in S, n in N],
            vSOC[t,s,n] == vSOC[t-1,s,n] + in_eff * sum(vGENG[t,g,n] for g in G) - out_eff * vGENS[t,s,n] + sum(vFLOW[t-1,l,n,m] - vFLOW[t,l,m,n] for l in L, m in N; m != n)

        cSOC[t in STARTS, s in S, n in N],
            vSOC[t,s,n] == vSOC[t+hpp-1,s,n] + in_eff  * sum(vGENG[t,g,n] for g in G) - out_eff * vGENS[t,s,n] + sum(vFLOW[t+hpp-1,l,n,m] - vFLOW[t,l,m,n] for l in L, m in N; m != n)
    end)