0

I'm working with the pulse module in Pennylane, specifically focusing on the architecture of transmon qubits. I have a slight suspicion that there might be missing or extra $\hbar$ in the source code. Let me explain:

According to the documentation for transmon_interaction, it seems to assume the convention $\hbar = 1$. The same happens with qml.evolve. Therefore, in my code, I am following this convention and ignoring all factors of $\hbar$. However, this approach doesn't seem consistent with the results I get.

Specifically, if I create a 2-qubit transmon_interaction with a minimal coupling to isolate the qubits and add a simple constant pulse on the first qubit of the form $A \sigma_0^X$, the first qubit should undergo an $X$-rotation. The rotation angle after evolving the system for a duration $T$ should be $\theta = A T$, while the second qubit should remain unchanged. Thus, if I evolve the system with $A$ and $T$ satisfying $AT = \pi$, I expect to get the state $|1\rangle$. However, this is not what I observe. To illustrate this, I use the following code:

I create an instance of the Hamiltonian with transmon_interaction and make a copy of it. In this copy, I multiply all coefficients by hbar. Then, I add the same pulse to both Hamiltonians and evolve with the described amplitude and duration. Here is the code:

import pennylane as qml
from copy import copy
from pennylane import numpy as np

hbar = 1.05457182e-34

w0 = 2

pennylane hamiltonian without hbar

h_no_hbar = qml.pulse.transmon_interaction(w0, wires=range(2), connections=[[0,1]], coupling=1e-10)

pennylane hamiltonian with hbar

h_hbar = copy(h_no_hbar) h_hbar.coeffs_fixed = [x * hbar for x in h_hbar.coeffs_fixed]

pulse

angle = np.pi/2 # from 0 to 1 amplitude = 5 duration = angle / amplitude # evolve to |1> pulse = qml.X(0) * amplitude

dev = qml.device('default.qubit', wires=range(2))

@qml.qnode(dev) def circuit(hamiltonian_base): qml.evolve(hamiltonian_base + pulse)(params=[], t=duration) return qml.density_matrix(0)

dm_no_hbar = circuit(h_no_hbar) dm_hbar = circuit(h_hbar)

print(f'{dm_no_hbar = }\n', f'{dm_hbar = }')

These are the results:

dm_no_hbar = tensor([[ 0.86949015+0.j       , -0.16400325-0.2942445j],
                     [-0.16400325+0.2942445j,  0.13050969+0.j       ]],
             dtype=complex64, requires_grad=True)

dm_hbar = tensor([[ 0.0000000e+00+0.j, -1.3252368e-34+0.j], [-1.3252368e-34+0.j, 9.9999881e-01+0.j]], dtype=complex64, requires_grad=True)

As seen, the expected behavior is obtained only when the Hamiltonian coefficients are multiplied by $\hbar$. I have inspected the source code but couldn’t find where an extra $\hbar$ factor might have been included, which I would need to compensate for externally, as it appears I am currently doing. This makes me wonder if I am missing something important here.

Does anyone have any idea? Thanks in advance!

kernel123
  • 37
  • 6

1 Answers1

1

You are getting your expected behavior because multiplying by 1.05457182e-34 is effectively setting the interaction term to zero, thereby leaving you with just the pure pulse drive (=Rabi oscillation). This is what you would get when you go to the rotating frame.

Please note that the transmon_interaction + transmon_drive pulse is not in the rotating frame, but rather the lab frame. If you want to do "pure" Rabi oscillations, you need to go to the rotating frame, this is explained e.g. from eq. (79) and the following in 1904.06560.

In the lab frame you have the natural $\omega_q$ oscillation of the qubit on its Z axis superimposed with the Y rotation from the drive.

I think this is the same problem as has been discussed in your previous thread :P