# Efficient method to generate Tridiagonal 50 by 50 Matrix? [duplicate]

I'm looking to generate a tridiagonal 50x50 matrix, ideally without using loops. Suggestions on most efficient code for this?

• DiagonalMatrix[list,k] – Gregory Rut Sep 14 '14 at 17:15
• I think this question is a duplicate of: (13004) -- please review that question and if you feel this is not a duplicate explain why. – Mr.Wizard Sep 15 '14 at 5:18
• Your question is closed because its a duplicate , probably you should read the policy about that. – rhermans Sep 15 '14 at 16:49

As Gregory Rut mentioned, DiagonalMatrix already has built-in support for generating banded matrices from lists:

Inner[DiagonalMatrix, RandomInteger[{0, 5}, #] & /@ {49, 50, 49}, {-1, 0, 1}]


which yields the following (when ArrayPlot is applied): • I just start writing that Inner will be more elegant then explicit sum! :) – ybeltukov Sep 14 '14 at 17:50
• @ybeltukov I believe a disadvantage of Inner is that more memory will be used. – Mr.Wizard Sep 15 '14 at 5:24
diag = RandomChoice[CharacterRange["a", "z"], #] & /@ {49, 50, 49};
m = SparseArray[Inner[Rule, {Band[{1, 2}], Band[{1, 1}], Band[{2, 1}]}, diag, List]]

MatrixPlot[m, Mesh -> True] Timings: for a 50X50 matrix the timings of two methods based on Band and DiagonalMatrix are both 0. For larger matrices, Band is much faster:

ClearAll[f1, f2];
f1 = SparseArray[Inner[Rule, {Band[{1, 2}], Band[{1, 1}], Band[{2, 1}]}, #, List]] &;
f2 = Inner[DiagonalMatrix, #, {1, 0, -1}] &;
functions = {f1, f2};

testdata1 = RandomReal[5, #] & /@ {49, 50, 49};
testdata2 = RandomReal[5, #] & /@ {499, 500, 499};
testdata3 = RandomReal[5, #] & /@ {4999, 5000, 4999};
testdata4 = RandomReal[5, #] & /@ {9999, 10000, 9999};

(Equal @@ (Through@functions@#)) & /@ {testdata1, testdata2, testdata3, testdata4}
(* {True,True,True, True} *)

timings = Outer[N[First[AbsoluteTiming[#@#2;]], 5] &,
functions, {testdata1, testdata2, testdata3, testdata4}, 1];
{"n = 50", "n = 500", "n = 5000", "n = 10000"}}] • Unfortunately, Band is not so efficient. For example, f3 = Inner[DiagonalMatrix[SparseArray@#, #2] &, #, {1, 0, -1}] & is 10 times faster. – ybeltukov Sep 14 '14 at 20:33
• @ybeltukov, really nice! I suggest you should post that as an answer. – kglr Sep 14 '14 at 20:49
• Done! I went further :) – ybeltukov Sep 14 '14 at 21:36
• @ybeltukov and kguler: I marked this question as a duplicate. Please review my action. If you disagree or feel another action should be taken let me know. – Mr.Wizard Sep 15 '14 at 5:22
• @Mr.Wizard, i agree. Btw, do you remember if the linked q/a was on the Related list on the right before you linked to it? – kglr Sep 15 '14 at 5:39

Here is my expanded response to kguler.

I noticed that usually Band is less effective then DiagonalMatrix@SparseArray or manual constructing of the resulting SparseArray

f1 = SparseArray[Inner[Rule, {Band[{1, 2}], Band[{1, 1}], Band[{2, 1}]}, #, List]] &;
f2 = Inner[DiagonalMatrix, #, {1, 0, -1}] &;;
f3 = Inner[DiagonalMatrix[SparseArray@#, #2] &, #, {1, 0, -1}] &;
f4 = SparseArray[Join[Transpose@{Most@#, Rest@#}, Transpose@{#, #},
Transpose@{Rest@#, Most@#}] &@Range@Length@#[] -> Join @@ #] &;
f5 = With[{n = Length@#[]}, SparseArray @@ {Automatic, {n, n}, 0.,
{1,
{Join[{0}, Range[2, 3 n - 3, 3], {3 n - 2}],
Transpose@{Flatten[Transpose@Range[{0, 1, 2}, {n - 1, n, n + 1}]][[2 ;; -2]]}},
Flatten[Transpose@{Prepend[#[], 0.], #[], Append[#[], 0.]}][[2 ;; -2]]
}}] &;
functions = {f1, f2, f3, f4, f5};

testdata = RandomReal[5, #] & /@ {# - 1, #, # - 1} & /@ {50, 500, 5000, 10000};

(Equal @@ (Through@functions@#)) & /@ testdata
(* {True, True, True, True} *)

timings = Outer[N[First[AbsoluteTiming[#@#2;]], 5] &, functions, testdata, 1];
TableForm[timings, TableHeadings -> {{"f1", "f2", "f3", "f4", "f5"}, {"n = 50",
"n = 500", "n = 5000", "n = 10000"}}] Functions:

1. kguler's solution with SparseArray and Band

2. DumpsterDoofus's DiagonalMatrix with dense matrices

3. DiagonalMatrix with SparseArray

4. Manual creating of Sparse array with SparseArray[indexes -> values]

5. Completely manual creating of SparseArray as SparseArray[Automatic, dimensions, defaultElement, {1, {splitting, columns}, values}]. You can learn this format by investigating InputForm of any available SparseArray.

• So the most ridiculously complex and labored solution is the fastest? Just avoid functions that are supposed to be optimized for this? Yikes! – Zibadawa Sep 15 '14 at 4:09