A study of superoperators in QuTiP

and some notes about computer implementations in general

Useful references:


In [2]:
import numpy as np
from qutip import *

In [6]:
# prototype density matrix (i.e. nonsense)
rho = Qobj([[1,2],[3,4]])
rho


Out[6]:
Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}1.0 & 2.0\\3.0 & 4.0\\\end{array}\right)\end{equation*}

In [31]:
rho_v = operator_to_vector(rho)
rho_v


Out[31]:
Quantum object: dims = [[[2], [2]], [1]], shape = (4, 1), type = operator-ket\begin{equation*}\left(\begin{array}{*{11}c}1.0\\3.0\\2.0\\4.0\\\end{array}\right)\end{equation*}

This is where I got confused. By hand I write this as 1,2,3,4 in order from top to bottom, based on the notation: $$\rho = \sum_{i,j}\rho_{ij}|i\rangle\langle j| \rightarrow |\rho\rangle\rangle = \sum_{i,j}\rho_{ij}|i\rangle \otimes |j\rangle$$

I'll let $$|1\rangle = \begin{pmatrix}1\\0\end{pmatrix}$$ and $$|2\rangle = \begin{pmatrix}0\\1\end{pmatrix}$$ so $i=j=1,2$ in the sums. The outer products are: $$|1\rangle\langle 1| = \begin{pmatrix}1&0\\0&0\end{pmatrix}$$ $$|1\rangle\langle 2| = \begin{pmatrix}0&1\\0&0\end{pmatrix}$$ $$|2\rangle\langle 1| = \begin{pmatrix}0&0\\1&0\end{pmatrix}$$ $$|2\rangle\langle 2| = \begin{pmatrix}0&0\\0&1\end{pmatrix}$$ And the tensor products are: $$|1\rangle \otimes |1\rangle = \begin{pmatrix}1\\0\\0\\0\end{pmatrix}$$ $$|1\rangle \otimes |2\rangle = \begin{pmatrix}0\\1\\0\\0\end{pmatrix}$$ $$|2\rangle \otimes |1\rangle = \begin{pmatrix}0\\0\\1\\0\end{pmatrix}$$ $$|2\rangle \otimes |2\rangle = \begin{pmatrix}0\\0\\0\\1\end{pmatrix}$$

I see the code for operator_to_vector takes the transpose, but I'm not sure why that is? Maybe to align to the underlying Fortran-style column-major data in the underlying implementation?

So, the bottom line is: Either trust and use the QuTiP functions or roll your own. Mixing and matching builds you a world that will be ripe with transpose errors :-)


In [17]:
one = Qobj([[1],[0]])
one


Out[17]:
Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}1.0\\0.0\\\end{array}\right)\end{equation*}

In [19]:
two = Qobj([[0],[1]])
two


Out[19]:
Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\1.0\\\end{array}\right)\end{equation*}

In [24]:
rho == 1*one*one.dag() + 2*one*two.dag() + 3*two*one.dag() + 4*two*two.dag()


Out[24]:
True

So this is consistent with my prototype $\rho$


In [28]:
tensor(one,one)


Out[28]:
Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}1.0\\0.0\\0.0\\0.0\\\end{array}\right)\end{equation*}

In [25]:
tensor(one,two)


Out[25]:
Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\1.0\\0.0\\0.0\\\end{array}\right)\end{equation*}

In [26]:
tensor(two,one)


Out[26]:
Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\0.0\\1.0\\0.0\\\end{array}\right)\end{equation*}

In [27]:
tensor(two,two)


Out[27]:
Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\0.0\\0.0\\1.0\\\end{array}\right)\end{equation*}

These are also consistent with "by hand" notation. So everything individually works as it would "by hand" but the operator_to_vector takes a transpose first... presumably to align the numpy arrays?

Ok, so knowing that, it's a bit hard to compare to by-hand results, but we can check a few. First, the left-multiplication should be the same as spre. Defined as $\mathcal{L}(A) = A\otimes I$:


In [70]:
spre(destroy(2))


Out[70]:
Quantum object: dims = [[[2], [2]], [[2], [2]]], shape = (4, 4), type = super, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 1.0\\0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}

In [76]:
tensor(destroy(2),identity(2))


Out[76]:
Quantum object: dims = [[2, 2], [2, 2]], shape = (4, 4), type = oper, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 1.0 & 0.0\\0.0 & 0.0 & 0.0 & 1.0\\0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}

In [78]:
tensor(identity(2),destroy(2))


Out[78]:
Quantum object: dims = [[2, 2], [2, 2]], shape = (4, 4), type = oper, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 1.0\\0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}

But this is instead showing that left-multiplication is $\mathcal{L}(A) = I\otimes A$, doesn't match the expected definition.

I think this is generally known, as we're mixing notation with a particular (matrix) representation. MATLAB does a similar thing (I suspect for the same Fortran-roots reason): https://physics.stackexchange.com/questions/163546/finding-the-matrix-representation-of-a-superoperator


In [ ]: