# easiest way to construct the following determinant

What is the easiest way to construct the following determinant? ]

p is variable, I want to vary value of p each time and get the appropriate determinant.

One way to do it would be

mat[p_] := SparseArray[{
{i_, i_} :> B[i - 1],
{i_, j_} /; i == j + 1 :> A[j - 1],
{i_, j_} /; i == j - 1 :> CC[j - 1]
},
p + 1
]
Det@mat[p]


For example

With[{p = 2},
SparseArray[{
{i_, i_} :> B[i - 1],
{i_, j_} /; i == j + 1 :> A[j - 1],
{i_, j_} /; i == j - 1 :> CC[j - 1]
},
p + 1
]
]
Det@%


$$\left( \begin{array}{ccc} B(0) & \text{CC}(1) & 0 \\ A(0) & B(1) & \text{CC}(2) \\ 0 & A(1) & B(2) \\ \end{array} \right)$$

B B B - A B CC - A B CC

But the computation time quickly increases with p since the elements are symbolic. For example, with p = 17,

With[{p = 17},
SparseArray[{
{i_, i_} :> B[i - 1],
{i_, j_} /; i == j + 1 :> A[j - 1],
{i_, j_} /; i == j - 1 :> CC[j - 1]
},
p + 1
]
] // Det // RepeatedTiming // First


2.7

But, if the elements are numeric quantities,

SeedRandom
With[{p = 17},
SparseArray[{
{i_, i_} :> RandomReal[],
{i_, j_} /; i == j + 1 :> RandomReal[],
{i_, j_} /; i == j - 1 :> RandomReal[]
},
p + 1
]
] // Det // RepeatedTiming // First


0.0020

the calculation is no problem.

• thanks a lot. In fact A,B and C are some functions which become determined by initial values. Oct 15, 2019 at 6:14

Since you indicate you're interested only in the determinant, a recursive procedure is faster:

ClearAll[det];
det = 1;
det = b;
mem : det[p_] := mem = b[p - 1] det[p - 1] - a[p - 2] c[p - 1] det[p - 2];

d1 = det; // AbsoluteTiming
d3 = With[{n = 15},  (* J.M.'s RecurrenceTable[] idea *)
First[RecurrenceTable[{d[p] ==
b[p - 1] d[p - 1] - a[p - 2] c[p - 1] d[p - 2], d == 1,
d == b}, d, {p, n, n}]]]; // AbsoluteTiming
d2 = Det@sa; // AbsoluteTiming (*sa[p] = SparseArray solution (I used @kglr's)*)

d1 - d2 // Simplify
d1 - d3 // Simplify
(*
{0.000188, Null}
{0.000936, Null}
{0.391194, Null}

0
0
*)


The results are memoized, so that if you need to compute the determinant for another value of p, the new result is built on top of any previous computations. As long as storing the results is not a problem (in terms of RAM), it should make things faster.

• You'd think this method would be built into M somewhere, but I can't find it. Oct 15, 2019 at 21:30
• Of course, you can use RecurrenceTable[] for this as well: With[{n = 15}, First[RecurrenceTable[{d[p] == b[p - 1] d[p - 1] - a[p - 2] c[p - 1] d[p - 2], d == 1, d == b}, d, {p, n, n}]]] Nov 13, 2019 at 22:49

An alternative, and faster, way to construct the SparseArray using Band:

sa[n_] := SparseArray[{
Band[{1, 1}] -> Array[b, n, 0],
Band[{2, 1}] -> Array[a, n - 1, 0],
Band[{1, 2}] -> Array[c, n - 1]},
{n, n}]

sa // MatrixForm // TeXForm


$$\left( \begin{array}{cccccccccc} b(0) & c(1) & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ a(0) & b(1) & c(2) & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & a(1) & b(2) & c(3) & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & a(2) & b(3) & c(4) & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & a(3) & b(4) & c(5) & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & a(4) & b(5) & c(6) & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & a(5) & b(6) & c(7) & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & a(6) & b(7) & c(8) & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & a(7) & b(8) & c(9) \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & a(8) & b(9) \\ \end{array} \right)$$

• Originally I thought to use your Band method (from the other very similar question recently), but didn't think to create the element vectors. Oct 15, 2019 at 21:21