Nested loops

Hi,

I need a program where I’m computing a 2D NxN lattice, and for that I need N^2 nested loops, for N=2 would be:

for S[1,1] in [-1,1], S[1,2] in [-1,1], S[2,1] in [-1,1], S[2,2] in [-1,1]
    ...
end

But I need to compute N in the range 2:5, and doing like that I would need 1 code for each N. Is there a way to optimize that, so I can use just one program?

I tried something like that:

for i in 1:N, j in 1:N, S[i,j] in [-1,1]
    ...
end

but didn’t work as I wanted.

Thanks for the help.

Edit: It was N^2 not N^N

I am not entirely sure what you want. The loop you describe does what it is expected to do, for each position (i, j) it first set S[i, j] value to -1 and execute the body, then it sets S[i, j] to 1 and execute the body.

Do you want to run the body for every possible matrix of values 1 and -1? If so, I would recommend looking at Combinatorics.jl.

2 Likes

Yep, I want to run on all the 2^(N*N) possibilities, so I would need N^2 nested loops with [-1,1].

I’ll take a look, thanks for the recommendation.

Edit: N^2 not N^N

If I’m getting this right, it sounds like you want all NxN matrices S for which Sᵢⱼ ∈ {-1, 1}. You can create these in a loop over i in 2^(N*N) using the binary representation of i to set the values of S.

S′ = ones(Int, N, N)
digs = zeros(Bool, N*N) # a vector to hold the bit representation of `i`.
for i in 1:2^(N*N)
    digits!(digs, i-1, base=2)
    S = S′ .- 2reshape(digs, size(S′))
    # use S
end

Above I use two different matrices for the process, but that’s not important. You can just as easily do the whole thing in-place if you preferred. Note that it’s easy for 2^(N*N) to overflow (you literally can’t go past N=7…). You can use big(2)^(N*N) to get around that, but at that point the problem would be intractable anyway.

2 Likes

Turns out you can also use multiset_permutations from Combinatorics. The input set needs N² 1 values and the same number of -1 values. Choosing any N² subset of these (in every permutation) will give the same as the above solution.

for perm in multiset_permutations([ones(Int, N^2); -ones(Int, N^2)], N^2)
    S = reshape(perm, N, N)
end
2 Likes

In addition to the combinatorics solutions suggested above, I also want to point out the Cartesian indices facilities in Base and the lower-level @nloops macro. These allow you to effectively have N efficient nested loops in such a way that the code is generic over N.

4 Likes