# Traces of products of Pauli matrices

Given a matrix $M$ of shape $2^L*2^L$, I would like to compute all the traces $\text{Tr}( M.(\sigma^{n_1}\otimes\sigma^{n_2}\otimes\ldots\otimes\sigma^{n_L}))$ for $n_1=1...4$, $n_2=1...4$, ..., $n_{L}=1...4.$, where $\sigma^n$ are the Pauli Matrices for $n=1..3$ and the identity for $n=4$. I can do this for specific values of $L$, but how do I write a function of $M$ and $L$ only that will perform this computation?

You could define a function that constructs the product of Pauli matrices as follows. I use KroneckerProduct here because you are planning to form the matrix product with a $2L\times2L$ matrix, so we have to have the Pauli matrices arranged in a corresponding block matrix:

pauliProduct[n_] := Module[{l = Length[n]},
Total@MapIndexed[
KroneckerProduct[
DiagonalMatrix[
UnitVector[
l, #] & @@ #2],
PauliMatrix[#]] &, n]
]

MatrixForm[pauliProduct[{1, 2, 3, 4}]]


$$\left( \begin{array}{cccccccc} 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & -i & 0 & 0 & 0 & 0 \\ 0 & 0 & i & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & -1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ \end{array} \right)$$

This has dimension $2L$, where $L$ is the length of the list $\{n_1, \ldots, n_L\}$. Then doing the trace with your matrix is easy with Tr, and the final thing is to loop over all possible lists.

The matrix above has all the 4 matrices of your basis in a row as blocks on the diagonal because I chose the list of indices to be {1, 2, 3, 4}.

Here I define a function that collects the results for all possible Tuples of indices from the range {1,2,3,4}. Although you asked for it to be a function of the matrix and $L$, it really doesn't need $L$ as an extra argument because we can assume that the matrix is of dimension $2L$. So let's just define the desired function like this:

traces[m_] :=
Table[{n, Tr[m.pauliProduct[n]]}, {n, Tuples[{1, 2, 3, 4}, Length[m]/2]}]


As an example matrix, I simply choose one of the outputs of pauliProduct itself:

m = pauliProduct[{2, 1}];


Now compute all possible traces for $L=2$:

traces[m]

(*
==> {{{1, 1}, 2}, {{1, 2}, 4}, {{1, 3}, 2}, {{1, 4}, 2}, {{2, 1},
0}, {{2, 2}, 2}, {{2, 3}, 0}, {{2, 4}, 0}, {{3, 1}, 0}, {{3, 2},
2}, {{3, 3}, 0}, {{3, 4}, 0}, {{4, 1}, 0}, {{4, 2}, 2}, {{4, 3},
0}, {{4, 4}, 0}}
*)


I wrote it so that it outputs the list of indices together with the result for the trace in one list.