Symbolic manipulation of infinite-dimensional band matrices in Mathematica
There are some symbolic calculations in infinite-dimensional Hilbert spaces that can still be done entirely in Mathematica. Assume one has an operator whose infinite-dimensional matrix in some basis vanishes outside some finite number of off-diagonals, and assume there is a closed expression for the corresponding entries: then, polynomial equations in such matrices can be simplified analytically in Mathematica.
The trick is to work with finite-size matrices (sufficiently large to accomodate the finite band width) with symbolic entries, whose ‘middle’ column represents an arbitrary column of our polynomial equation. Since everything is symbolic and all nonzero entries can be accounted for by finiteness of the band width, this allows for analytic equation solving in Mathematica.
Example: generators of .
Let’s take the generators of the smooth functions on the sphere as
example. The algebra
Now, there are two irreducible representations of the algebra
generated by
Let’s take our Hilbert space
Now, crucially, the generators
Then Mathematica can represent
First, setup the space of
(* width of the band matrices *)
maxorder = 2;
(* the set of |l,m,s> in play *)
basis = Flatten[
Table[{myl, mym, S},
{myl, L - 2, L + 2}, {mym, M - 2, M + 2}]
, 1];
(* obtain l, m, s as functions of the entry number *)
l[i_] := basis[[i, 1]];
m[i_] := basis[[i, 2]];
s[i_] := basis[[i, 3]];
Now, construct the arrays representing
dims = Length[basis];
(* construct array. input: boolean function that specifies nonzero entries and coefficient function *)
bandarray[supportQ_, coeff_] := SparseArray[
{i_, j_}/; supportQ[i,j] :> coeff[j],
{dims, dims}];
(* coefficients for a, b *)
fa0[i_] := 2*s[i]*Sqrt[(l[i]+m[i]+1) (l[i]-m[i])] / (2 l[i] (2 l[i]+2));
faplus[i_] := Sqrt[(l[i]+m[i]+1) (l[i]+m[i]+2)] / (2 l[i]+2);
famin[i_] := -Sqrt[(l[i]-m[i]) (l[i]-m[i]-1)] / (2 l[i]);
fb0[i_] := s[i] (
(l[i]-m[i]+1) (l[i]+m[i])-(l[i]-m[i]) (l[i]+m[i]+ 1)
)/(2 l[i] (2 l[i]+2));
fbplus[i_] := -Sqrt[(l[i]-m[i]+1) (l[i]+m[i]+1)] / (2 l[i]+2);
fbmin[i_] := -Sqrt[(l[i]-m[i]) (l[i]+m[i])] / (2 l[i]);
a0 = bandarray[(l[#1]==l[#2] && m[#1]==m[#2] + 1 && s[#1]==s[#2]) &,
fa0[#1] &];
aplus = bandarray[(l[#1]==l[#2] + 1 && m[#1]==m[#2] + 1 && s[#1]==s[#2]) &,
faplus[#1] &];
amin = bandarray[(l[#1]==l[#2] - 1 && m[#1]==m[#2] + 1 && s[#1]==s[#2]) &,
famin[#1] &];
b0 = bandarray[(l[#1]==l[#2] && m[#1]==m[#2] && s[#1]==s[#2]) &,
fb0[#1] &];
bplus = bandarray[(l[#1]==l[#2] + 1 && m[#1]==m[#2] && s[#1]==s[#2]) &,
fbplus[#1] &];
bmin = bandarray[(l[#1]==l[#2] - 1 && m[#1]==m[#2] && s[#1]==s[#2]) &,
fbmin[#1] &];
a = (a0 + aplus + amin);
b = (b0 + bplus + bmin);
Due to the usage of sparse arrays and
the symbolic nature of
In order to use Mathematica’s built-in simplification (the main point of the exercise, after all), we’ll set up some assumptions:
(* assume we don't take (nonzero) square roots of negative numbers *)
mypairs = Flatten[
Table[
{(myl+mym+1) (myl-mym),
(myl+mym+1) (myl+mym+2),
(myl-mym) (myl-mym-1),
(myl-mym+1) (myl+mym+1),
(myl-mym) (myl+mym)} /. {myl -> L+x, mym -> M+y}
, {x, -maxorder, maxorder}, {y, -maxorder, maxorder}]];
possqrts = Map[# >= 0 &, mypairs];
assmptns =
FullSimplify[
Element[S,Integers] && S^2==1
&& Element[L + 1/2, Integers]
&& Element[M + 1/2, Integers]
&& L > 0 && M + L >= 0 && L - M >= 0
&& Apply[And, possqrts]
];
We can recover the
(* ArrayRules on a column returns {i} -> v[i], ..., so the argument should be {index_} *)
stringform[{index_}] := "|" <>
ToString[l[index]] <> "," <>
ToString[m[index]] <> "," <>
ToString[s[index]] <> "⟩";
Let’s set up the simplification procedure. Given an operator
lmsindex = Position[basis, {L,M,S}][[1,1]];
(* turn matrix into dictionary {entry -> value} *)
associationform[mat_] := Association[ ArrayRules[mat] ];
(* get the column A|e_n> *)
roughlmscolumn[mat_] := mat[[All,lmsindex]];
(* simplified column association *)
simpleassoc[mat_] := Map[
FullSimplify[#,Assumptions->assmptns, TimeConstraint->10]&,
associationform[mat]
]
nonzeropart[assoc_] := Select[#=!=0&][assoc];
(* simplified columns, only the nonzero part *)
simplecolumn[mat_] := nonzeropart[simpleassoc[roughlmscolumn[mat]]];
(* print simplified |l,m,s> column in our basis *)
lmscolumn[mat_] := KeyMap[stringform, simplecolumn[mat]];
Now, let’s implement the generating equations of
id = bandarray[(#1 == #2)&, 1&];
abcomm = b.a - b.a;
bminbst = b-ConjugateTranspose[b];
absphere = ConjugateTranspose[a].a + b.b - id;
Test the result:
lmscolumn[abcomm]
lmscolumn[bminbst]
lmscolumn[abspere]
Although abcomm et al, even simplified, are certainly not zero (due to
boundary effects), the output is three empty associations. Since the
column was selected symbolically and we know maxorder
was large
enough (i.e. all other coefficients in the column must be zero), we’ve
now analytically checked the generating equations in our
representations for all