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

16 - 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.A, 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.A, 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.A, 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. ]]
[ ]: