MethodError: no method matching isless(::Int64, ::Array{UnitRange{Int64},1})

Hi I am a newbie to JuMP(Julia) and coding too,

I am currently computing the following constraints in code below however, it is returning the following error and I am not exactly sure how to solve and I do not understand the error at all. Some of the other constraints have been computed using similar syntax and are returning no errors. Is there something I am missing?

MethodError: no method matching isless(::Int64, ::Array{UnitRange{Int64},1})
Closest candidates are:
isless(!Matched::Missing, ::Any) at missing.jl:87
isless(!Matched::FlexTable{1}, ::AbstractArray{T,1} where T) at C:\Users\glmab.julia\packages\TypedTables\ZF2b3\src\FlexTable.jl:308
isless(::Real, !Matched::AbstractFloat) at operators.jl:166
…

Stacktrace:
[1] <(::Int64, ::Array{UnitRange{Int64},1}) at .\operators.jl:277
[2] <=(::Int64, ::Array{UnitRange{Int64},1}) at .\operators.jl:326
[3] macro expansion at C:\Users\glmab.julia\packages\MutableArithmetics\bPWR4\src\rewrite.jl:276 [inlined]
[4] macro expansion at C:\Users\glmab.julia\packages\JuMP\qhoVb\src\macros.jl:440 [inlined]
[5] (::var"#430#435")(::String) at C:\Users\glmab.julia\packages\JuMP\qhoVb\src\Containers\macro.jl:183
[6] #28 at C:\Users\glmab.julia\packages\JuMP\qhoVb\src\Containers\container.jl:85 [inlined]
[7] iterate at .\generator.jl:47 [inlined]
[8] collect(::Base.Generator{JuMP.Containers.VectorizedProductIterator{Tuple{Array{String,1}}},JuMP.Containers.var"#28#29"{var"#430#435"}}) at .\array.jl:686
[9] map(::Function, ::JuMP.Containers.VectorizedProductIterator{Tuple{Array{String,1}}}) at .\abstractarray.jl:2188
[10] container(::Function, ::JuMP.Containers.VectorizedProductIterator{Tuple{Array{String,1}}}, ::Type{JuMP.Containers.DenseAxisArray}) at C:\Users\glmab.julia\packages\JuMP\qhoVb\src\Containers\container.jl:85
[11] container(::Function, ::JuMP.Containers.VectorizedProductIterator{Tuple{Array{String,1}}}) at C:\Users\glmab.julia\packages\JuMP\qhoVb\src\Containers\container.jl:65
[12] top-level scope at C:\Users\glmab.julia\packages\JuMP\qhoVb\src\macros.jl:91
[13] top-level scope at In[54]:9
[14] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091

@constraints example2_netprofit begin
    tight1[j in j],
      sum(sum( (alpha[i]*w[i,n,np] + beta[i]*bs[i,n,np] ) for n in 1:length(n) if n <= np <= n+d) for i in Ij1) <= H

    tight2[j in j],
      sum(sum( (alpha[i]*w[i,n,np] + beta[i]*bs[i,n,np] ) for n in 1:length(n) if n <= np <= n+d) for i in Ij2) <= H

    tight3[j in j],
      sum(sum( (alpha[i]*w[i,n,np] + beta[i]*bs[i,n,np] ) for n in 1:length(n) if n <= np <= n+d) for i in Ij3) <= H

    tight4[j in j],
      sum(sum( (alpha[i]*w[i,n,np] + beta[i]*bs[i,n,np] ) for n in 1:length(n) if n <= np <= n+d) for i in Ij4) <= H

    tight5[j in j],
      sum(sum( (alpha[i]*w[i,n,np] + beta[i]*bs[i,n,np] ) for n in 1:length(n) if n <= np <= n+d) for i in Ij5) <= H

end

Hi, I would advise next time you post a MWE (Minimal Working Example) that reproduces your error as it is suggested in the item 3 of this list of good practices when asking in this forum.

Only with the error message and this excerpt of code I would deduce that:

  1. None of alpha, w, beta, and bs are JuMP variable containers. They all are Number Vectors because the message complains about the left-hand side of the <= being an Int.
  2. H seems to be a Vector of UnitRange{Int64}, in other words something like this: [1:10, 7:30, -10:10] (a list of ranges).

Without a MWE we cannot know why your Vectors that seems as they should be JuMP variable containers are just Number containers, nor why H seem to be a Vector of ranges. Other confusing things are, for example: from where np comes from? should np be varying too or it is fixed?

Sorry I had forgotten to input the Set and Parameter information required, please see below

#Sets
#  i 'tasks' /t1*t5/
#  j 'units' /j1*j5/
#  n 'events' /n0*n3/
#  s 'states' /s1*s4/

i = ["t1","t2","t3","t4","t5"];
j = ["j1","j2","j3","j4","j5"];
n = [1:N]
s = ["s1","s2","s3","s4"]

#SubSets

#Ij1(i) 'tasks which can be performed in unit 1' /task1/
#Ij2(i) 'tasks which can be performed in unit 2' /task2/
#Ij3(i) 'tasks which can be performed in unit 3' /task3/
#Ij4(i) 'tasks which can be performed in unit 4' /task4/
#Ij5(i) 'tasks which can be performed in unit 5' /task5/

Ij1 = i[1];
Ij2 = i[2];
Ij3 = i[3];
Ij4 = i[4];
Ij5 = i[5];

#Is1(i)'tasks which process state 1 and either produce or consume' /task1,task2/
#Is2(i)'tasks which process state 2 and either produce or consume' /task1,task2,task3/
#Is3(i)'tasks which process state 3 and either produce or consume' /task3,task4,task5/
#Is4(i)'tasks which process state 4 and either produce or consume' /task4,task5/

Is1 = i[1:2];
Is2 = i[1:3];
Is3 = i[3:5];
Is4 = i[4:5];

#Ips1(i) 'tasks which produce state 2' //
#Ips2(i) 'tasks which produce state 2' /task1,task2/
#Ips3(i) 'tasks which produce state 3' /task3/
#Ips4(i) 'tasks which produce state 4' /task4,task5/

Ips1 = [];
Ips2 = i[1:2];
Ips3 = i[3];
Ips4 = i[4:5];

#Ics1(i) 'tasks which consume state 1' /task1,task2/
#Ics2(i) 'tasks which consume state 2' /task3/
#Ics3(i) 'tasks which consume state 3' /task4,task5/
#Ics4(i) 'tasks which consume state 4' //

Ics1 = i[1:2];
Ics2 = i[3];
Ics3 = i[4:5];
Ics4 = [];

Sr =s[1]
Sfis = s[2:3]
Sp = s[4]

#alias(i,ip)
#alias(j,jp)
#alias(n,np,npp)

ip = i;
jp = j;
np = n;
npp = n;

println(1:length(s))




AND

#PARAMETERS
#bmin = [0,0,0,0,0]

bmin = OrderedDict(
   "t1" => 0,
   "t2" => 0,
   "t3" => 0,
   "t4" => 0,
   "t5" => 0   
)

#bmax = [100,150,200,150,150]
bmax = OrderedDict(
   "t1" => 100,
   "t2" => 150,
   "t3" => 200,
   "t4" => 150,
   "t5" => 150 
)

#STin = [10000, 0, 0, 0]
STin = OrderedDict(
     "s1" => 10000,
     "s2" => 0,
     "s3" => 0,
     "s4" => 0)

#STmax = [+inf, 200, 250, +inf ]
STmax = OrderedDict(
     "s1" => Inf,
     "s2" => 200,
     "s3" => 250,
     "s4" => 0
)

#alpha = [1.333, 1.333, 1.000, 0.667, 0.667]
alpha = OrderedDict(
"t1" => 1.333,
"t2" => 1.333,
"t3" => 1.000,
"t4" => 0.667,
"t5" => 0.667
)

#beta = [0.01333, 0.01333, 0.00500, 0.00445, 0.00445]
beta = OrderedDict(
"t1" => 0.01333,
"t2" => 0.01333,
"t3" => 0.00500,
"t4" => 0.00445,
"t5" => 0.00445       
)

price = OrderedDict(
"s1" => 0,
"s2" => 0,
"s3" => 0,
"s4" => 5
)

demand = OrderedDict(
"s1" => 0,
"s2" => 0,
"s3" => 0,
"s4" => 0
)

#rho_table = wsv"""
#i        s1       s2     s3    s4
#t1       -1       +1      0     0
#t2       -1       +1      0     0
#t3        0       -1     +1     0
#t4        0        0     -1    +1
#t5        0        0     -1    +1
#"""

rho_table = DataFrame([(i = "t1", s1 = -1, s2 = +1, s3 = 0, s4 = 0 ),
                   (i = "t2", s1 = -1, s2 = +1, s3 = 0, s4 = 0 ),
                   (i = "t3", s1 = 0, s2 = -1, s3 = +1, s4 = 0 ),
                   (i = "t4", s1 = 0, s2 = 0, s3 = -1, s4 = +1 ),
                   (i = "t5", s1 = 0, s2 = 0, s3 = -1, s4 = +1 )]);

rho = OrderedDict( (r[:i],states) => r[Symbol(states)] for r in eachrow(rho_table), states in s);


Comments are just GAMS syntax as I am converting from GAMS to JuMP.

Hope the above helps in clarifying

I did not found the definition of H, or w, or bs.

Now I am certain everything is in. My apologies. I will definitely do better next time

H = 8;
d = 0;
N = 4;

@variables example2_netprofit begin
    w[i in i, n in n, np in np], Bin
    bs[i in i, n in n, np in np] >= 0
    ST0[s in s, n in n] >= 0
    ST[s in s, n in n] >= 0
    Ts[i in i, n in n] >= 0
    Tf[i in i,n in n] >= 0
    NetP
    MS
end

The next time I suggest you either put all of your code in https://pastebin.com/, or try to make it minimal (the M of MWE). The code was yet impossible to run because it did not include the packages (no using keywords), and it did not define example2_netprofit. I have added the necessary packages and created a simple model called example2_netprofit, so I was finally able to reproduce your problem.

The problem seem to be the n <= np <= n+d bit. n is an Int64 and np is 1:4 (a UnitRange{Int64}). What are you trying to achieve here? n <= 1:4 should give what results for which values of n?

The reassembled code is here, for anyone that is interested in helping too.

This is the original constraint from the paper that I am trying to reproduce in Julia (did in GAMS).

np is an alias of n that is used in the model. elements in n are is a time/event point (model is a scheduling problem) and it is needed that when indexing from both sets that np and n not be the same i.e when n = 1, np != 1 and so forth. Hope I am making sense.

I think you are wrong about this point. Both n and n' are from set N, and the restriction imposed by n <= n' <= n + Ξ”n means that n' will go from equal to n to equal to n + Ξ”n so, in fact, you will have n == n' in the first term of the sum. Your Ξ”n (that is d in the code) is zero, so n is not sometimes equal to n' but always equal to n' in fact (the inner sum has only one term).

However, I do not understand how you ended up with np as a range. In your code np is a global variable, when it is clear by this constraint that np should be an iterator (i.e., you should use a for clause to introduce it), as n and i are. There also other problems in your code, like how you are trying to use j (you are not subscribing anything with j and you probably should not have variables Ij1, Ij2, etc), and that your global n is not a range like you think it is (that 1:length(n) will always be 1:1), but one problem at a time. I think what you want is something more like:

sum(alpha[i] * w[i, n, np] + beta[i] * bs[i, n, np] for i in Ij1 for n in 1:length(n) for np in n:(n+d)) <= H

Thank you for your assistance. It worked. The only issue is Ij1 only has one element and I have noticed that when the set has only 1 element (t1) the for loop does not work i.e. it splits it into t and 1 and then returns the error key β€˜t’ not found. What can I do to overcome this has it is another error I am experiencing in the other constraints that I am computing.

Regarding n not being a range, how do I make it a range from 1:N? As that is a vital part of the model. When I used the function range I obtained a similar error. I would like to have it as n1, n2 n3, n4 etc but I will be changing N moving forward.

In GAMS, I can create a set such as n0 * n10 (11 time points) or n0 * n5 (6 time points, n0, n1, n2, n3, n4, n5) how can I do the same thing in JuMP.

Ij1 is not a set. It is a single String and therefore when you iterate it, you get each character. If you wanted it to be a collection (in special, a Vector like you defined i, j, n and s in the start) you should put it inside brackets (Ij1 = [i[1]]). Now, this makes absolutely no sense to me. Why have a variable Ij1 when you can just do i[1] instead? Why are you creating such variables with numbers at the end instead just accessing them from the Vectors when necessary? You will not be able to create loops using these variables (because the index is in the name), but you are able to create loops using Vectors.

I am not sure if I understand your question. Julia ranges are created with : If you write 1:10 you have the range of numbers between 1 and 10 including both extremities. I do not understand why you are putting letters in front of the numbers, or trying to have them as variables.

I am not sure if you want n to be a range, do you not want it to be a number? An iterator that varies within 1:N? About increasing a range, if you declare r = 1:N and N is 10, when you change N to be 15, for example, you should recompute r = 1:N.

No it is a mis understanding but I have managed to fix the error as you directed prior. Thank you

Hi Henrique,

Thank so much for your previous assistance I have managed to compute all the constraints for this model. I am currently having problems with the objective function that is returning a key error.

@objective example2_netprofit Max begin
    NetP == sum(price[s] * sum(ST[s,n] + sum(rho[i,s]*bs[i,np,n] for i in 1:length(Ips4) for np in (n-d):n ) for n in 1:length(n) if n != 1:length(n)-1) for s in Sp)   
end

Here is the error returned

KeyError: key (1, β€œs4”) not found

Stacktrace:
[1] getindex at C:\Users\glmab.julia\packages\OrderedCollections\DqfZ7\src\ordered_dict.jl:346 [inlined]
[2] getindex(::OrderedDict{Tuple{String,String},Int64}, ::Int64, ::String) at .\abstractdict.jl:499
[3] (::var"#435#441"{Int64,Int64,String})(::Int64) at .\none:0
[4] MappingRF at .\reduce.jl:93 [inlined]
[5] _foldl_impl(::Base.MappingRF{var"#435#441"{Int64,Int64,String},Base.BottomRF{typeof(Base.add_sum)}}, ::Base._InitialValue, ::UnitRange{Int64}) at .\reduce.jl:58
[6] FlatteningRF at .\reduce.jl:119 [inlined]
[7] MappingRF at .\reduce.jl:93 [inlined]
[8] _foldl_impl(::Base.MappingRF{var"#436#440"{Int64,String},Base.FlatteningRF{Base.BottomRF{typeof(Base.add_sum)}}}, ::Base._InitialValue, ::UnitRange{Int64}) at .\reduce.jl:58
[9] foldl_impl at .\reduce.jl:48 [inlined]
[10] mapfoldl_impl at .\reduce.jl:44 [inlined]
[11] #mapfoldl#204 at .\reduce.jl:160 [inlined]
[12] mapfoldl at .\reduce.jl:160 [inlined]
[13] #mapreduce#208 at .\reduce.jl:287 [inlined]
[14] mapreduce at .\reduce.jl:287 [inlined]
[15] sum at .\reduce.jl:494 [inlined]
[16] sum(::Base.Iterators.Flatten{Base.Generator{UnitRange{Int64},var"#436#440"{Int64,String}}}) at .\reduce.jl:511
[17] (::var"#434#439"{String})(::Int64) at .\none:0
[18] MappingRF at .\reduce.jl:93 [inlined]
[19] FilteringRF at .\reduce.jl:105 [inlined]
[20] _foldl_impl(::Base.FilteringRF{var"#437#442",Base.MappingRF{var"#434#439"{String},Base.BottomRF{typeof(Base.add_sum)}}}, ::Base._InitialValue, ::UnitRange{Int64}) at .\reduce.jl:58
[21] foldl_impl at .\reduce.jl:48 [inlined]
[22] mapfoldl_impl at .\reduce.jl:44 [inlined]
[23] #mapfoldl#204 at .\reduce.jl:160 [inlined]
[24] mapfoldl at .\reduce.jl:160 [inlined]
[25] #mapreduce#208 at .\reduce.jl:287 [inlined]
[26] mapreduce at .\reduce.jl:287 [inlined]
[27] sum at .\reduce.jl:494 [inlined]
[28] sum(::Base.Generator{Base.Iterators.Filter{var"#437#442",UnitRange{Int64}},var"#434#439"{String}}) at .\reduce.jl:511
[29] (::var"#433#438")(::String) at .\none:0
[30] MappingRF at .\reduce.jl:93 [inlined]
[31] _foldl_impl(::Base.MappingRF{var"#433#438",Base.BottomRF{typeof(Base.add_sum)}}, ::Base._InitialValue, ::Array{String,1}) at .\reduce.jl:58
[32] foldl_impl at .\reduce.jl:48 [inlined]
[33] mapfoldl_impl(::typeof(identity), ::typeof(Base.add_sum), ::NamedTuple{(),Tuple{}}, ::Base.Generator{Array{String,1},var"#433#438"}) at .\reduce.jl:44
[34] mapfoldl(::Function, ::Function, ::Base.Generator{Array{String,1},var"#433#438"}; kw::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at .\reduce.jl:160
[35] mapfoldl at .\reduce.jl:160 [inlined]
[36] mapreduce(::Function, ::Function, ::Base.Generator{Array{String,1},var"#433#438"}; kw::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at .\reduce.jl:287
[37] mapreduce at .\reduce.jl:287 [inlined]
[38] sum at .\reduce.jl:494 [inlined]
[39] sum(::Base.Generator{Array{String,1},var"#433#438"}) at .\reduce.jl:511
[40] top-level scope at In[33]:4
[41] top-level scope at C:\Users\glmab.julia\packages\MutableArithmetics\bPWR4\src\rewrite.jl:276
[42] top-level scope at C:\Users\glmab.julia\packages\JuMP\y5vgk\src\macros.jl:928
[43] top-level scope at In[33]:3
[44] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091

When I change the one component giving therror to for i in Ips4 see code below

@objective example2_netprofit Max begin
    NetP == sum(price[s] * sum(ST[s,n] + sum(rho[i,s]*bs[i,np,n] for i in Ips4 for np in (n-d):n ) for n in 1:length(n) if n != 1:length(n)-1) for s in Sp)   
end

It returns the following error

KeyError: key ([β€œt4”, β€œt5”], β€œs4”) not found

Stacktrace:
[1] getindex at C:\Users\glmab.julia\packages\OrderedCollections\DqfZ7\src\ordered_dict.jl:346 [inlined]
[2] getindex(::OrderedDict{Tuple{String,String},Int64}, ::Array{String,1}, ::String) at .\abstractdict.jl:499
[3] (::var"#445#451"{Array{String,1},Int64,String})(::Int64) at .\none:0
[4] MappingRF at .\reduce.jl:93 [inlined]
[5] _foldl_impl(::Base.MappingRF{var"#445#451"{Array{String,1},Int64,String},Base.BottomRF{typeof(Base.add_sum)}}, ::Base._InitialValue, ::UnitRange{Int64}) at .\reduce.jl:58
[6] FlatteningRF at .\reduce.jl:119 [inlined]
[7] MappingRF at .\reduce.jl:93 [inlined]
[8] _foldl_impl(::Base.MappingRF{var"#446#450"{Int64,String},Base.FlatteningRF{Base.BottomRF{typeof(Base.add_sum)}}}, ::Base._InitialValue, ::Array{Array{String,1},1}) at .\reduce.jl:58
[9] foldl_impl at .\reduce.jl:48 [inlined]
[10] mapfoldl_impl at .\reduce.jl:44 [inlined]
[11] #mapfoldl#204 at .\reduce.jl:160 [inlined]
[12] mapfoldl at .\reduce.jl:160 [inlined]
[13] #mapreduce#208 at .\reduce.jl:287 [inlined]
[14] mapreduce at .\reduce.jl:287 [inlined]
[15] sum at .\reduce.jl:494 [inlined]
[16] sum(::Base.Iterators.Flatten{Base.Generator{Array{Array{String,1},1},var"#446#450"{Int64,String}}}) at .\reduce.jl:511
[17] (::var"#444#449"{String})(::Int64) at .\none:0
[18] MappingRF at .\reduce.jl:93 [inlined]
[19] FilteringRF at .\reduce.jl:105 [inlined]
[20] _foldl_impl(::Base.FilteringRF{var"#447#452",Base.MappingRF{var"#444#449"{String},Base.BottomRF{typeof(Base.add_sum)}}}, ::Base._InitialValue, ::UnitRange{Int64}) at .\reduce.jl:58
[21] foldl_impl at .\reduce.jl:48 [inlined]
[22] mapfoldl_impl at .\reduce.jl:44 [inlined]
[23] #mapfoldl#204 at .\reduce.jl:160 [inlined]
[24] mapfoldl at .\reduce.jl:160 [inlined]
[25] #mapreduce#208 at .\reduce.jl:287 [inlined]
[26] mapreduce at .\reduce.jl:287 [inlined]
[27] sum at .\reduce.jl:494 [inlined]
[28] sum(::Base.Generator{Base.Iterators.Filter{var"#447#452",UnitRange{Int64}},var"#444#449"{String}}) at .\reduce.jl:511
[29] (::var"#443#448")(::String) at .\none:0
[30] MappingRF at .\reduce.jl:93 [inlined]
[31] _foldl_impl(::Base.MappingRF{var"#443#448",Base.BottomRF{typeof(Base.add_sum)}}, ::Base._InitialValue, ::Array{String,1}) at .\reduce.jl:58
[32] foldl_impl at .\reduce.jl:48 [inlined]
[33] mapfoldl_impl(::typeof(identity), ::typeof(Base.add_sum), ::NamedTuple{(),Tuple{}}, ::Base.Generator{Array{String,1},var"#443#448"}) at .\reduce.jl:44
[34] mapfoldl(::Function, ::Function, ::Base.Generator{Array{String,1},var"#443#448"}; kw::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at .\reduce.jl:160
[35] mapfoldl at .\reduce.jl:160 [inlined]
[36] mapreduce(::Function, ::Function, ::Base.Generator{Array{String,1},var"#443#448"}; kw::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at .\reduce.jl:287
[37] mapreduce at .\reduce.jl:287 [inlined]
[38] sum at .\reduce.jl:494 [inlined]
[39] sum(::Base.Generator{Array{String,1},var"#443#448"}) at .\reduce.jl:511
[40] top-level scope at In[34]:4
[41] top-level scope at C:\Users\glmab.julia\packages\MutableArithmetics\bPWR4\src\rewrite.jl:276
[42] top-level scope at C:\Users\glmab.julia\packages\JuMP\y5vgk\src\macros.jl:928
[43] top-level scope at In[34]:3
[44] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091

I am looking for it to be indexed as (β€œt4”, β€œs4”) and (β€œt5”, β€œs4”)

Hope you can assist in this. The above information can be utilised.
Thank you in advance

Can you post the formulation objective as you did with the previous constraint? (i.e., the mathematical formula)

Also,

  1. You have NetP == ... in the objective, this makes little sense. The objective function is not a constraint, it should be just an expression (i.e., probably just the value you have in the right side of the ==) not an equality.
  2. for n in 1:length(n) if n != 1:length(n)-1 this also makes little sense. First there is the terrible style of having an outer/global n that is used as limit for an inner/iterator/local n, you should give different names to your variables. But also if n != 1:length(n)-1 is nonsense, n here is a value between 1 and length(n) (for the global n), it will always be different from a range.
  3. In the code up until now you do not define a variable called ST (only STmin and STmax) and the you had in your old code Sp is probably not the Sp used here. So it is hard to know what is triggering the error, probably you have incorrect values in Sp.

Here is the mathematical formula


Point 1 noted
Regarding point 2 n should be equal to the last element in n and that’s how I saw it best to compute it.
Point 3, ST is a variable please see list of variables above (where bs[i,n,np] is etc)

In turn,

  1. If n (the inner one) should only be the last element of n (the outer one) then just drop the for n in 1:length(n) if n != 1:length(n)-1 (consequently, disappear with the inner n) and use last(n) in each place you would use n in the objective.
  2. Sorry, I forgot to check the JuMP variable definitions, but this does not tell me what is Sp.

About the mathematical formulation, I have to say that, for me, the βˆ‘ with n = N is irregular notation. If you say to me it means the last value in N I will believe you, but it seems kinda a sloppy way to do it. Ideally they should have graphed n ∈ {max(N)} (or something like that).

Sp is a set, Sp = [s[4]]

Defined amongst the sets
Point 2 noted

What is your Ips4? Because the problem appears when indexing rho, that is:

OrderedDict{Tuple{String, String}, Int64} with 20 entries:
  ("t1", "s1") => -1
  ("t2", "s1") => -1
  ("t3", "s1") => 0
...

So your change in the code to try to solve the problem is in the right direction, I think that if Ips4 was

julia> Ips4
2-element Vector{String}:
 "t4"
 "t5"

as it should be, then other error (or no error) should have happened. Did you wrap i[4:5] in brackets? If so, remove them.