Density operator and matrix


In [59]:
from sympy import *
from sympy.physics.quantum import *
from sympy.physics.quantum.density import *
from sympy.physics.quantum.spin import (
    Jx, Jy, Jz, Jplus, Jminus, J2,
    JxBra, JyBra, JzBra,
    JxKet, JyKet, JzKet,
)
from IPython.core.display import display_pretty

In [60]:
%load_ext sympyprinting

Create n density matrix using symbolic states


In [61]:
psi = Ket('psi')
phi = Ket('phi')

In [62]:
d = Density((psi,0.5),(phi,0.5)); d


Out[62]:
$$\rho\left(\begin{pmatrix}{\left|\psi\right\rangle }, & 0.5\end{pmatrix},\begin{pmatrix}{\left|\phi\right\rangle }, & 0.5\end{pmatrix}\right)$$

In [63]:
display_pretty(d)


ρ((❘ψ⟩, 0.5),(❘φ⟩, 0.5))

In [64]:
d.states()


Out[64]:
$$\begin{pmatrix}{\left|\psi\right\rangle }, & {\left|\phi\right\rangle }\end{pmatrix}$$

In [65]:
d.probs()


Out[65]:
$$\begin{pmatrix}0.5, & 0.5\end{pmatrix}$$

In [66]:
d.doit()


Out[66]:
$$0.5 {\left|\phi\right\rangle }{\left\langle \phi\right|} + 0.5 {\left|\psi\right\rangle }{\left\langle \psi\right|}$$

In [67]:
Dagger(d)


Out[67]:
$$\rho\left(\begin{pmatrix}{\left|\psi\right\rangle }, & 0.5\end{pmatrix},\begin{pmatrix}{\left|\phi\right\rangle }, & 0.5\end{pmatrix}\right)$$

In [68]:
A = Operator('A')

In [69]:
d.apply_op(A)


Out[69]:
$$\rho\left(\begin{pmatrix}A {\left|\psi\right\rangle }, & 0.5\end{pmatrix},\begin{pmatrix}A {\left|\phi\right\rangle }, & 0.5\end{pmatrix}\right)$$

Now create a density matrix using spin states


In [70]:
up = JzKet(S(1)/2,S(1)/2)
down = JzKet(S(1)/2,-S(1)/2)

In [71]:
d2 = Density((up,0.5),(down,0.5)); d2


Out[71]:
$$\rho\left(\begin{pmatrix}{\left|\frac{1}{2},\frac{1}{2}\right\rangle }, & 0.5\end{pmatrix},\begin{pmatrix}{\left|\frac{1}{2},- \frac{1}{2}\right\rangle }, & 0.5\end{pmatrix}\right)$$

In [72]:
represent(d2)


Out[72]:
$$\left[\begin{smallmatrix}0.5 & 0\\0 & 0.5\end{smallmatrix}\right]$$

In [73]:
d2.apply_op(Jz)


Out[73]:
$$\rho\left(\begin{pmatrix}J_z {\left|\frac{1}{2},\frac{1}{2}\right\rangle }, & 0.5\end{pmatrix},\begin{pmatrix}J_z {\left|\frac{1}{2},- \frac{1}{2}\right\rangle }, & 0.5\end{pmatrix}\right)$$

In [74]:
qapply(_)


Out[74]:
$$\rho\left(\begin{pmatrix}\frac{1}{2} \hbar {\left|\frac{1}{2},\frac{1}{2}\right\rangle }, & 0.5\end{pmatrix},\begin{pmatrix}- \frac{1}{2} \hbar {\left|\frac{1}{2},- \frac{1}{2}\right\rangle }, & 0.5\end{pmatrix}\right)$$

In [75]:
qapply((Jy*d2).doit())


Out[75]:
$$0.5 J_y {\left|\frac{1}{2},- \frac{1}{2}\right\rangle }{\left\langle \frac{1}{2},- \frac{1}{2}\right|} + 0.5 J_y {\left|\frac{1}{2},\frac{1}{2}\right\rangle }{\left\langle \frac{1}{2},\frac{1}{2}\right|}$$

Evaluate entropy of the density matrices


In [76]:
entropy(d2)


Out[76]:
$$\frac{1}{2} \log{\left (2 \right )}$$

In [77]:
entropy(represent(d2))


Out[77]:
$$\frac{1}{2} \log{\left (2 \right )}$$

In [78]:
entropy(represent(d2,format="numpy"))


Out[78]:
(0.69314718056-0j)

In [79]:
entropy(represent(d2,format="scipy.sparse"))


Out[79]:
(0.69314718056-0j)

Density operators with Tensor Products as args


In [80]:
from sympy.core.trace import Tr

A, B, C, D = symbols('A B C D',commutative=False)

t1 = TensorProduct(A,B,C)

d = Density([t1, 1.0])
d.doit()

t2 = TensorProduct(A,B)
t3 = TensorProduct(C,D)

d = Density([t2, 0.5], [t3, 0.5])
d.doit()


Out[80]:
$$0.5 \left({A A^{\dagger}}\right)\otimes \left({B B^{\dagger}}\right) + 0.5 \left({C C^{\dagger}}\right)\otimes \left({D D^{\dagger}}\right)$$

In [81]:
#mixed states
d = Density([t2+t3, 1.0])
d.doit()


Out[81]:
$$1.0 \left({A A^{\dagger}}\right)\otimes \left({B B^{\dagger}}\right) + 1.0 \left({A C^{\dagger}}\right)\otimes \left({B D^{\dagger}}\right) + 1.0 \left({C A^{\dagger}}\right)\otimes \left({D B^{\dagger}}\right) + 1.0 \left({C C^{\dagger}}\right)\otimes \left({D D^{\dagger}}\right)$$

Trace operators on Density Operators with Spin States


In [82]:
from sympy.physics.quantum.density import Density
from sympy.physics.quantum.spin import (
    Jx, Jy, Jz, Jplus, Jminus, J2,
    JxBra, JyBra, JzBra,
    JxKet, JyKet, JzKet,
)
from sympy.core.trace import Tr

d = Density([JzKet(1,1),0.5],[JzKet(1,-1),0.5]);
t = Tr(d); 

display_pretty(t)
print t.doit()


Tr(ρ((❘1,1⟩, 0.5),(❘1,-1⟩, 0.5)))
1.00000000000000

Partial Trace on Density Operators with Mixed State


In [83]:
#Partial trace on mixed state
from sympy.core.trace import Tr

A, B, C, D = symbols('A B C D',commutative=False)

t1 = TensorProduct(A,B,C)

d = Density([t1, 1.0])
d.doit()

t2 = TensorProduct(A,B)
t3 = TensorProduct(C,D)

d = Density([t2, 0.5], [t3, 0.5])


tr = Tr(d,[1])
tr.doit()


Out[83]:
$$0.5 A A^{\dagger} \mbox{Tr}\left(B B^{\dagger}\right) + 0.5 C C^{\dagger} \mbox{Tr}\left(D D^{\dagger}\right)$$

Partial Trace on Density Operators with Spin states


In [84]:
from sympy.physics.quantum.density import Density
from sympy.physics.quantum.spin import (
    Jx, Jy, Jz, Jplus, Jminus, J2,
    JxBra, JyBra, JzBra,
    JxKet, JyKet, JzKet,
)
from sympy.core.trace import Tr

tp1 = TensorProduct(JzKet(1,1), JzKet(1,-1))

#trace out 0 index
d = Density([tp1,1]);
t = Tr(d,[0]); 

display_pretty(t)
display_pretty(t.doit())

#trace out 1 index
t = Tr(d,[1])
display_pretty(t)
t.doit()


Tr((❘1,1⟩⨂ ❘1,-1⟩, 1))
❘1,-1⟩⟨1,-1❘
Tr((❘1,1⟩⨂ ❘1,-1⟩, 1))
Out[84]:
$${\left|1,1\right\rangle }{\left\langle 1,1\right|}$$

Examples of qapply() on Density matrices with spin states


In [85]:
psi = Ket('psi')
phi = Ket('phi')

u = UnitaryOperator()
d = Density((psi,0.5),(phi,0.5)); d

display_pretty(qapply(u*d))
 
# another example
up = JzKet(S(1)/2, S(1)/2)
down = JzKet(S(1)/2, -S(1)/2)
d = Density((up,0.5),(down,0.5))

uMat = Matrix([[0,1],[1,0]])
display_pretty(qapply(uMat*d))


ρ((O⋅❘ψ⟩, 0.5),(O⋅❘φ⟩, 0.5))
⎡                  0                    ρ((❘1/2,1/2⟩, 0.5),(❘1/2,-1/2⟩, 0.5))⎤
⎢                                                                            ⎥
⎣ρ((❘1/2,1/2⟩, 0.5),(❘1/2,-1/2⟩, 0.5))                    0                  ⎦

Example of qapply() on Density Matrices with qubits


In [90]:
from sympy.physics.quantum.gate import UGate
from sympy.physics.quantum.qubit import Qubit

uMat = UGate((0,), Matrix([[0,1],[1,0]]))
d = Density([Qubit('0'),0.5],[Qubit('1'), 0.5])

display_pretty(d)

#after applying Not gate
display_pretty(qapply(uMat*d) )


ρ((❘0⟩, 0.5),(❘1⟩, 0.5))
ρ((❘1⟩, 0.5),(❘0⟩, 0.5))

In [86]: