6
$\begingroup$

I am interested in working with the names of matrices as opposed to the actual matrices themselves. I would like Mathematica to recognise the content of a matrix and output its name rather than its matrix form.

For example, suppose I have the matrices:

xpauli = {{0,1},{1,0}}
zpauli={{1,0},{0,-1}}

Then say I have an operator

hadoperator= 1/Sqrt[2]{{1,1},{1,-1}}

and I want to apply this operator by conjugation:

hadoperator.xpauli.Transpose[Conjugate[hadoperator]]

This returns \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}

Which is zpauli.

How would I get mathematica to return "Zpauli" instead of the matrix.

Additionally, what I am really interested in is whether this can be done for a Kronecker product.

For example, say I do:

logicalhadoperator=KroneckerProduct[hadoperator, hadoperator, hadoperator, hadoperator] 

and I want to apply that to some kronecker product of the xpauli and zpauli states

kroneckerexample= KroneckerProduct[xpauli, xpauli, zpauli, zpauli]

logicalhadoperator.kroneckerexample.Transpose[Conjugate[logicalhadoperator]]

This returns a $16*16$ matrix with entries $\pm \frac{1}{4}$. However, I am wondering, is there a way that Mathematica could output this value as its kronecker product of xpauli and zpauli i.e KroneckerProduct[zpauli, zpauli, xpauli, xpauli]?

$\endgroup$
3
  • 2
    $\begingroup$ How would Mathematica "know" which name to use for two numerically equal matrices? $\endgroup$ Commented Jun 20 at 16:12
  • 1
    $\begingroup$ You first need to specify a "basis" of your vector space as a list of Kronecker products of xpauli and zpauli's. Then it is very easy (for MMA) to express any given matrix as a linear combination of the basis vectors --- just solve system of linear equations for the (unknown) coefficients. $\endgroup$
    – A. Kato
    Commented Jun 21 at 2:00
  • 2
    $\begingroup$ Have you seen Pauli matrices — simplify expressions without printing out the raw matrix? $\endgroup$
    – Jens
    Commented Jun 21 at 2:30

4 Answers 4

10
$\begingroup$

You can decompose any Hermitian 2×2 matrix $A$ into a sum over Pauli matrices,

$$ A=c_1\mathbb{1}+c_x\sigma_x+c_y\sigma_y+c_z\sigma_z $$

and the coefficients $(c_1,c_x,c_y,c_z)$ can be computed by the trace-normality:

decompose[a_?MatrixQ] := Table[Tr[a . PauliMatrix[i]]/2, {i, 0, 3}]

Example: the matrix $\sigma_z$ has $(c_1,c_x,c_y,c_z)=(0,0,0,1)$:

decompose[{{1, 0}, {0, -1}}]
(*    {0, 0, 0, 1}    *)

If you want a pretty-printed form, you can multiply this result with symbols of your choice, for example

pretty[m_?MatrixQ] := decompose[m] .
    {Subscript[σ, 1], Subscript[σ, x], Subscript[σ, y], Subscript[σ, z]}

pretty[{{1, 0}, {0, -1}}]

$$ \sigma _z $$

pretty[{{1, 0}, {0, -2}}]

$$ \frac{3 \sigma _z}{2}-\frac{\sigma _1}{2} $$

Reverse substitution proves that this is correct:

% /. {Subscript[σ, 1] -> PauliMatrix[0], Subscript[σ, x] -> PauliMatrix[1],
      Subscript[σ, y] -> PauliMatrix[2], Subscript[σ, z] -> PauliMatrix[3]}
(*    {{1, 0}, {0, -2}}    *)

Another example:

hadoperator = {{1, 1}, {1, -1}}/Sqrt[2];
pretty[hadoperator]

$$ \frac{\sigma _x}{\sqrt{2}}+\frac{\sigma _z}{\sqrt{2}} $$

Generalization to larger Kronecker products

The same procedure works for larger Kronecker products of $n$ 2×2 matrices: all the $4^n$ possible Pauli Kronecker products form an ortho-normal basis of the Hermitian $2^n\times2^n$ matrices (where normality is defined with respect to the trace of the dot product)!

Clear[pretty];
pretty[m_?HermitianMatrixQ /; Length[m] == 2] :=
  Sum[Tr[m . PauliMatrix[i]/2] * Subscript[σ, i], {i, 0, 3}]
pretty[m_?HermitianMatrixQ /; IntegerQ[Log[2, Length[m]]] && Length[m] >= 4] :=
  Total[(Tr[m . (KroneckerProduct @@ ((PauliMatrix /@ #)/2))] *
         (Dot @@ (Subscript[σ, #] & /@ #))) & /@
        Tuples[Range[0, 3], Log[2, Length[m]]]]

Here I've used the convention $\sigma_0=\mathbb{1}$, $\sigma_1=\sigma_x$, $\sigma_2=\sigma_y$, $\sigma_3=\sigma_z$, as Mathematica uses it too.

Examples:

pretty[KroneckerProduct[PauliMatrix[1], PauliMatrix[2], PauliMatrix[3]]]

$$ \sigma_1\cdot\sigma_2\cdot\sigma_3 $$

Your example:

pretty[KroneckerProduct[PauliMatrix[3], PauliMatrix[3], PauliMatrix[1], PauliMatrix[1]]]

$$ \sigma_3\cdot\sigma_3\cdot\sigma_1\cdot\sigma_1 $$

And if that's not pretty enough, we can use other symbols:

prettier[m_?HermitianMatrixQ /; IntegerQ[Log[2, Length[m]]]] := 
  pretty[m] /. {Subscript[σ, 0] -> \[DoubleStruckOne],
                Subscript[σ, 1] -> Subscript[σ, x], 
                Subscript[σ, 2] -> Subscript[σ, y], 
                Subscript[σ, 3] -> Subscript[σ, z]}

prettier[KroneckerProduct[PauliMatrix[3], PauliMatrix[3], PauliMatrix[1], PauliMatrix[1]]]

$$ \sigma_z\cdot\sigma_z\cdot\sigma_x\cdot\sigma _x $$

Table[prettier[IdentityMatrix[2^n]], {n, 1, 5}]

$$ \{ \mathbb{1}, \mathbb{1}\cdot\mathbb{1}, \mathbb{1}\cdot\mathbb{1}\cdot\mathbb{1}, \mathbb{1}\cdot\mathbb{1}\cdot\mathbb{1}\cdot\mathbb{1}, \mathbb{1}\cdot\mathbb{1}\cdot\mathbb{1}\cdot\mathbb{1}\cdot\mathbb{1} \} $$

prettier[KroneckerProduct[hadoperator, hadoperator]]

$$ \frac{\sigma _x\cdot\sigma _x}{2}+\frac{\sigma _x\cdot\sigma _z}{2}+\frac{\sigma _z\cdot\sigma _x}{2}+\frac{\sigma _z\cdot\sigma _z}{2} $$

$\endgroup$
7
$\begingroup$

This is a partial answer addressing only the first example given.

If you Set the value of a symbol, the symbol can never appear in the output, only its value.

$Version

(* "14.0.0 for Mac OS X ARM (64-bit) (December 13, 2023)" *)

Clear["Global`*"]

Rather than setting values, use replacement rules.

rules = {
   xpauli -> {{0, 1}, {1, 0}},
   zpauli -> {{1, 0}, {0, -1}},
   hadoperator -> 1/Sqrt[2] {{1, 1}, {1, -1}}
   };

repl[expr_] := expr /. rules /. (Reverse /@ rules)

Then,

hadoperator . xpauli . Transpose[Conjugate[hadoperator]] // repl

(* zpauli *)
$\endgroup$
5
$\begingroup$

To print some name instead of an object may be achieved by $PrePrint. E.g. your example:

xpauli = {{0, 1}, {1, 0}};
zpauli = {{1, 0}, {0, -1}};
hadoperator = 1/Sqrt[2] {{1, 1}, {1, -1}};

$PrePrint := (# /. {{1, 0}, {0, -1}} -> Zpauli) &

Now if we write:

hadoperator.xpauli.Transpose[Conjugate[hadoperator]]

Zpauli

I think the second question can not be done with a reasonable effort. Every output would have to be analyzed if it can be written as some Kronecker product. Here the effort exceeds the return.

$\endgroup$
4
$\begingroup$

My original idea was to use MakeBoxes[] to accomplish the formatting of the OP's example:

enter image description here

You can, in fact, have Mathematica output a certain variable name when the value of the variable shows up in the output. Line 10 shows that if you input the variable, its value is returned but formatted as the variable name. So it looks like the variable is undefined. In this case, MatrixForm will show a different output, confirming that the variable is defined.

I considered this mainly as a response to @BobHanlon's assertion that it can't be done. I hesitated because I have never used Pauli matrices and did not know what they were about, except that they are used in physics or chemistry, I think. In any case, it seemed that the OP probably had more in mind than these specific examples, and I felt I did not understand the scope of the question. The OP failed to reply to my now-deleted comment exposing my ignorance. Then @Roman replied (and @Jen in a comment) and put the problem in a clear perspective.

The following combines the MakeBoxes[] approach with @Roman's pretty[] functions. I hope that is okay. @Roman deserved the credit for the decompose[] and pretty[] codes. The latter is rewritten below as codes for MakeBoxes[].

Quit[]  (* To test MakeBoxes[], I start with a fresh kernel *)

(* decompose[] and code for MakeBoxes from pretty[] in answer
    https://mathematica.stackexchange.com/a/304435 (@Roman) *) 
decompose[a_?MatrixQ] := Table[Tr[a . PauliMatrix[i]]/2, {i, 0, 3}];
MakeBoxes[
    m_?HermitianMatrixQ /; 
     IntegerQ[Log[2, Length[m]]] && Length[m] >= 4, form_] /; 
   TrueQ@$pauliForm := Block[{\[Sigma], $pauliForm = False},
   With[{decomp = 
      Total[(Tr[m . (KroneckerProduct @@ ((PauliMatrix /@ #)/
                 2))]*(Dot @@ (Subscript[\[Sigma], #] & /@ #))) & /@ 
        Tuples[Range[0, 3], Log[2, Length[m]]]]},
    InterpretationBox[#, m] &@MakeBoxes[decomp, form]
    ]];
MakeBoxes[m_?MatrixQ, form_] /; TrueQ@$pauliForm := 
  Block[{\[Sigma], $pauliForm = False},
   With[{decomp = decompose[m] . Array[Subscript[\[Sigma], #] &, 4, 0]},
    InterpretationBox[#, m] &@MakeBoxes[decomp, form]
    ]];

xpauli = {{0, 1}, {1, 0}};
zpauli = {{1, 0}, {0, -1}};
hadoperator = 1/Sqrt[2] {{1, 1}, {1, -1}};
logicalhadoperator = 
  KroneckerProduct[hadoperator, hadoperator, hadoperator, hadoperator];
kroneckerexample = KroneckerProduct[xpauli, xpauli, zpauli, zpauli];

$pauliForm = True;
logicalhadoperator . kroneckerexample . 
 Transpose[Conjugate[logicalhadoperator]]
KroneckerProduct[xpauli, xpauli, zpauli, zpauli]
hadoperator . xpauli . Transpose[Conjugate[hadoperator]]

Here is a screenshot of the output. I thought it better to show what happens in the front end, as this Q&A is about formatting output.

enter image description here

Turn on the formatting with $pauliForm = True; turn it off with $pauliForm = False (or clear it). The code for MakeBoxes[] and the OP's xpauli etc. are hidden. Just the example output is shown. In line 13, I copy-pasted the output of line 10, which still represents the 16x16 matrix, as shown by MatrixForm. (Magnify[] was so that the whole would show in the window on my screen.)

I thought this approach seems to allow one to get the desired output form and use it in ways one usually uses Mathematica. One little glitch: TexForm usually formats in TraditionalForm, which in turn formats matrices in MatrixForm. To get the sigma version use StandardForm:

kroneckerexample // StandardForm // TeXForm
(*  \sigma _3.\sigma _3.\sigma _1.\sigma _1  *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.