I have two square matrices, a hermitian matrix h and an unitary matrix v. I am interested in the following function
step[h_,v_,n_]:=Map[Tr,Dot[NestList[MatrixExp[-I h].#.MatrixExp[I h]&,v,n-1],v]];
which generates a list of n real numbers. The dimensions of the matrices are not so big so MatrixExp
is still quite efficient. I want to make the above function faster by using Compile
,
stepcp:=Compile[{{m,_Complex,2},{v,_Complex,2},{n,_Integer}}, Map[Tr,Dot[NestList[m.#.ConjugateTranspose[m]&,v,n-1],v]]];
The compiled version is only a few times faster than the uncompiled version. As an example
l = 128;
v = KroneckerProduct[SparseArray[{{1, 1} -> 1., {2, 2} -> -1.}],SparseArray[{i_, i_} -> 1., l]];
h := 1/2 ArrayFlatten[{{PadLeft[1/2 SparseArray[{Band[{1, 2}] -> 1., Band[{2, 1}] -> -1.}, l], {l, 2 l}]}, {PadRight[-(1/2)SparseArray[{Band[{1, 2}] -> 1., Band[{2, 1}] -> -1.}, l], {l, 2 l}]}}] + 1/2 KroneckerProduct[SparseArray[{{1, 1} -> 1., {2, 2} -> -1.}, 2],DiagonalMatrix[SparseArray[Table[RandomReal[{-1., 1.}], {j, l}]]]];
step[m_, u_, n_] := 1/(2 l) Map[Tr,Dot[NestList[MatrixExp[-I m].#.MatrixExp[I m] &, v, n - 1],v]];
stepcp := Compile[{{m, _Complex, 2}, {u, _Complex, 2}, {n, _Integer}},1./(2 l) Map[Tr,Dot[NestList[m.#.ConjugateTranspose[m] &, u, n - 1], u]]];
step[h, v, 64]; // AbsoluteTiming
stepcp[Normal[MatrixExp[-I h]], Normal[v], 64]; // AbsoluteTiming
My questions are:
- How to compile this function more efficiently?
- The matrices h and v are SparseArray, why can't I directly pass them into compiled functions, why do I have to use Normal[]?
- The CompilePrint is shown below, is the MainEvaluate in line 1 and 29 a source of slowdown, if so can it be circumvented?
My eventual goal is to run an efficiently compiled version of step[h,v,n] 10000 times and take the Mean. Any suggestions are greatly appreciated.
NestList
; also the function that returns the complex conjugate is simplyConjugate
in Mathematica. Or have you redefined those function? If so you should give us your definition. $\endgroup$CompilePrint
output. It's very hard to hit a moving target. Your question won't attract many answers if you post incomplete and inconsistent code. Furthermore, the second version of your function, in context, contains a parameter $l$ that the first version of the function does not contain. You should include that parameter in the function definition as well. $\endgroup$