# conditional rules for sparse matrix

why does the following not work (Table isn't plugging in values for k):

m = 3;
n = 5;
SparseArray[Table[{i_, j_} /; j == i + k n -> 1, {k, 0, m - 1}], {n, m (n + 1)}]


instead one seemingly has to jump through hoops and do:

SparseArray[Table[{i_, j_} /; j == i + k n -> 1 /. {k -> t}, {t, 0, m - 1}], {n, m (n + 1)}]

• If speed on large creation is important, methods posted so far can be handily beat, look at using ArrayPad on an appropriate base... – ciao Apr 30 '15 at 19:20

Condition (/;) has attribute HoldAll, so j == i + k n is not evaluated and the value of k never gets there. Rule is not held, so t in {k -> t} is evaluated before replacing k in the Condition.

But it turns out you don't actually need the Table here, you can do something like:

 SparseArray[{i_, j_} /; (i == Mod[j, n, 1] && j <= m n) -> 1, {n, m (n + 1)}]


This is slower than the original for large matrices through. We can replace the pattern with Band to get even faster than the original:

SparseArray[Table[Band[{1, (k - 1) n + 1}] -> 1, {k, m}], {n, m (n + 1)}]

• looks nice, but for large m and n the mod solution seems to be considerably slower (by a factor of 50) – Peter Apr 30 '15 at 16:47
• @Peter You're right, I guess the Mod breaks some of the optimizations so it has to loop over all of the possible {i,j} pairs? – 2012rcampion Apr 30 '15 at 17:24

Not sure how large of m and n you deem "large", but certainly it should be obvious that creating a Table for the purposes of populating a SparseArray is, to be charitable, counterproductive (I'd use something much more colorful were an engineer working for me to do such things).

Take advantage of the sparse-aware Mathematica functions:

ArrayPad[ArrayPad[SparseArray@IdentityMatrix[{n, n}], {{0, 0}, {0, n (m - 1)}}, "Periodic"], {{0, 0}, {0, m}}]


Produces same results as yours and the current (only) answer, vastly faster (~60X faster than yours on 500x500 and well over order of magnitude faster than only answer so far). Side benefit - its sparse result needs only about 1/3 the storage compared to your method and existing answer.

N.B. The double padding is a bit faster than re-sparsifying to end dimensions...