[2]:
import quanguru as qg
import numpy as np

16b - Jaynes-Cummings Hamiltonian (in QuanGuru)#

The Jaynes-Cummings Hamiltonian is written as

\(H_{JC} = \hbar\omega_{c} a^{\dagger}a + \frac{1}{2}\hbar\omega_{q}\sigma_{z} + \hbar g(a^{\dagger}\sigma_{-} + a\sigma_{+})\)

where \(\sigma_{\pm} = (\sigma_{x} \pm i\sigma_{y})/2\) are raising/lowering operators for a two-level system, \(\sigma_{\mu}\) are the Pauli spin operators with \(\mu\in\{x,y,z\}\), \(a^{\dagger}\) and \(a\) are the creation and annihilation operators for the field mode, and \(\omega_{c}\), \(\omega_{q}\), and \(g\) are the cavity-field, qubit, and coupling (angular-) frequencies, respectively. Note that the above Hamiltonian is written in a common notation where the order of the sub-system Hilbert spaces is implicitly defined by the ordering in the coupling. This means, for example, that the composite form of the number operator is written explicitly as \((a^{\dagger}a)\otimes 1_{2,2}\) (similarly, \(a^{\dagger}\otimes\sigma_{-}\) and \(1_{d,d}\otimes\sigma_{z}\), where \(d\) is the truncation dimension for the cavity operators and \(\otimes\) is the tensor product).

In this tutorial, we describe/create the Jaynes-Cummings Hamiltonian using QuanGuru. For the parameters of the Hamiltonian, we will take \(\omega_{c} = \omega_{q} = g = 1/2\pi\) for simplicity. Since, QuanGuru uses frequencies (instead of angular-frequencies), frequencies are all 1. Also, instead of \(\sigma_{\pm} = (\sigma_{x} \pm i\sigma_{y})/2\), we will use \(J_{\pm} = (J_{x} \pm iJ_{y})/2\), where \(J_{\mu}\) (with \(\mu\in\{x,y,z\}\)) are the operators for larges spins. With this approach, we will be able to extend the Jaynes-Cummings Hamiltonian to Tavis-Cumming Hamiltonian by simply setting a different j-value to our Qubit object.

[3]:
# create a composite system with a qubit and cavity
JCSystem = qg.Cavity(frequency=1, dimension=5, alias="JC_Cavity") + qg.Qubit(frequency=1, alias="JC_Qubit")

# couple the qubit and the cavity using their alias
MC = JCSystem.createTerm(qSystem=["JC_Qubit", "JC_Cavity"], operator=[qg.sigmam, qg.create], frequency=1)
PD = JCSystem.createTerm(qSystem=["JC_Qubit", "JC_Cavity"], operator=[qg.sigmap, qg.destroy], frequency=1)
[4]:
print(np.round(JCSystem.totalHamiltonian.toarray(), 1))
[[ 0.5  0.   0.   1.   0.   0.   0.   0.   0.   0. ]
 [ 0.  -0.5  0.   0.   0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   1.5  0.   0.   1.4  0.   0.   0.   0. ]
 [ 1.   0.   0.   0.5  0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   2.5  0.   0.   1.7  0.   0. ]
 [ 0.   0.   1.4  0.   0.   1.5  0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   3.5  0.   0.   2. ]
 [ 0.   0.   0.   0.   1.7  0.   0.   2.5  0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   0.   0.   4.5  0. ]
 [ 0.   0.   0.   0.   0.   0.   2.   0.   0.   3.5]]
[5]:
print(np.round(JCSystem._subSysHamiltonian.toarray(), 1))
[[ 0.5  0.   0.   0.   0.   0.   0.   0.   0.   0. ]
 [ 0.  -0.5  0.   0.   0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   1.5  0.   0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.5  0.   0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   2.5  0.   0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   0.   1.5  0.   0.   0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   3.5  0.   0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   0.   2.5  0.   0. ]
 [ 0.   0.   0.   0.   0.   0.   0.   0.   4.5  0. ]
 [ 0.   0.   0.   0.   0.   0.   0.   0.   0.   3.5]]
[6]:
print(np.round(JCSystem._termHamiltonian.toarray(), 1))
[[0.  0.  0.  1.  0.  0.  0.  0.  0.  0. ]
 [0.  0.  0.  0.  0.  0.  0.  0.  0.  0. ]
 [0.  0.  0.  0.  0.  1.4 0.  0.  0.  0. ]
 [1.  0.  0.  0.  0.  0.  0.  0.  0.  0. ]
 [0.  0.  0.  0.  0.  0.  0.  1.7 0.  0. ]
 [0.  0.  1.4 0.  0.  0.  0.  0.  0.  0. ]
 [0.  0.  0.  0.  0.  0.  0.  0.  0.  2. ]
 [0.  0.  0.  0.  1.7 0.  0.  0.  0.  0. ]
 [0.  0.  0.  0.  0.  0.  0.  0.  0.  0. ]
 [0.  0.  0.  0.  0.  0.  2.  0.  0.  0. ]]
[ ]: