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.
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityOne 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[0] B[1] B[2] - A[0] B[2] CC[1] - A[1] B[0] CC[2]
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[1234]
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.
Since you indicate you're interested only in the determinant, a recursive procedure is faster:
ClearAll[det];
det[0] = 1;
det[1] = b[0];
mem : det[p_] := mem = b[p - 1] det[p - 1] - a[p - 2] c[p - 1] det[p - 2];
d1 = det[15]; // 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[0] == 1,
d[1] == b[0]}, d, {p, n, n}]]]; // AbsoluteTiming
d2 = Det@sa[15]; // 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.
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[0] == 1, d[1] == b[0]}, d, {p, n, n}]]]
$\endgroup$
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[10] // 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)$
Band
method (from the other very similar question recently), but didn't think to create the element vectors.
$\endgroup$
Oct 15, 2019 at 21:21