Last active
January 11, 2024 17:28
-
-
Save marekyggdrasil/66a5b0d822eb60b27b68144045613bcd to your computer and use it in GitHub Desktop.
Tutorial covering the concept of geometric phase for a qubit, tutorial available under https://mareknarozniak.com/2021/01/09/qubit-berry-phase/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import matplotlib.pyplot as plt | |
def plotQubit(angles, refrel, refimag, resrel, resimag, title, x_axis, filename, url=''): | |
fig, ax = plt.subplots(1, 1, constrained_layout=True) | |
ax.set_title(title) | |
x_axis += '\n' + url | |
ax.set_xlabel(x_axis) | |
ax.set_ylabel('phase') | |
ax.plot(angles, refrel, color='tab:blue', label='ref real') | |
ax.plot(angles, refimag, color='tab:orange', label='ref imaginary') | |
ax.plot(angles, resrel, color='tab:blue', linestyle='--', label='res real') | |
ax.plot(angles, resimag, color='tab:orange', linestyle='--', label='res imaginary') | |
ax.grid() | |
ax.legend() | |
# fig.show() | |
fig.savefig(filename) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
from qutip import Options, mesolve, sigmax, sigmay, sigmaz | |
def sweepPhaseDown(psi0, theta_min, theta_max, phi, tau): | |
def angle(t): | |
return (1-(t/tau))*theta_max + (t/tau)*theta_min | |
res = 300 | |
times = np.linspace(0., tau, res) | |
opts = Options(store_final_state=True) | |
H = [ | |
[sigmax(), (lambda t, args: np.cos(-phi)*np.sin(angle(t)))], | |
[sigmay(), (lambda t, args: np.sin(-phi)*np.sin(angle(t)))], | |
[sigmaz(), (lambda t, args: np.cos(angle(t)))]] | |
return mesolve(H, psi0, times, options=opts) | |
def sweepPhaseUp(psi0, theta_min, theta_max, phi, tau): | |
def angle(t): | |
return (1-(t/tau))*theta_min + (t/tau)*theta_max | |
res = 300 | |
times = np.linspace(0., tau, res) | |
opts = Options(store_final_state=True) | |
H = [ | |
[sigmax(), (lambda t, args: np.cos(-phi)*np.sin(angle(t)))], | |
[sigmay(), (lambda t, args: np.sin(-phi)*np.sin(angle(t)))], | |
[sigmaz(), (lambda t, args: np.cos(angle(t)))]] | |
return mesolve(H, psi0, times, options=opts) | |
def sweepPhaseRound(psi0, theta, phi_min, phi_max, tau): | |
def angle(t): | |
return (1-(t/tau))*phi_min + (t/tau)*phi_max | |
res = 300 | |
times = np.linspace(0., tau, res) | |
opts = Options(store_final_state=True) | |
H = [ | |
[sigmax(), (lambda t, args: np.cos(-angle(t))*np.sin(theta))], | |
[sigmay(), (lambda t, args: np.sin(-angle(t))*np.sin(theta))], | |
[sigmaz(), (lambda t, args: np.cos(theta))]] | |
return mesolve(H, psi0, times, options=opts) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
from qutip import basis | |
from qm import sweepPhaseDown, sweepPhaseUp, sweepPhaseRound | |
from plotting import plotQubit | |
url = 'https://mareknarozniak.com/2021/01/09/qubit-berry-phase/' | |
tau = 16.*np.pi | |
res = 60 | |
angles = np.linspace(0., 2., res) | |
refrels = np.zeros(res) | |
refimag = np.zeros(res) | |
resrels = np.zeros(res) | |
resimag = np.zeros(res) | |
for i, angle in enumerate(angles): | |
theta = np.pi*angle | |
psi0 = np.cos(theta/2.)*basis(2, 0)+np.sin(theta/2.)*basis(2, 1) | |
result = sweepPhaseRound(psi0, theta, 0., 2.*np.pi, tau) | |
psif = result.final_state | |
gamma = -2.*np.pi*np.sin(theta/2.)**2. | |
dyn = np.pi | |
grefe = psif.overlap(psi0) | |
resrels[i] = grefe.real | |
resimag[i] = grefe.imag | |
ref = np.exp(1j*gamma) | |
refrels[i] = ref.real | |
refimag[i] = ref.imag | |
title = '$\\phi_f \\in [0, 2\\pi]$ and $\\theta$ fixed' | |
x_axis = '$\\theta$ [$\\pi$]' | |
filename = 'res_qubit.png' | |
plotQubit(angles, refrels, refimag, resrels, resimag, title, x_axis, filename, url=url) | |
refrels = np.zeros(res) | |
refimag = np.zeros(res) | |
resrels = np.zeros(res) | |
resimag = np.zeros(res) | |
# fix theta_min, vary phi | |
for i, angle in enumerate(angles): | |
theta_min = 3.*np.pi/4. | |
theta_max = 0. | |
phi_min = 0. | |
phi_max = np.pi*angle | |
psi0 = np.cos(theta_max/2.)*basis(2, 0)+np.sin(theta_max/2.)*basis(2, 1) | |
result = sweepPhaseDown(psi0, theta_min, theta_max, phi_min, tau) | |
psif = result.final_state | |
result = sweepPhaseRound(psif, theta_min, phi_min, phi_max, tau) | |
psif = result.final_state | |
result = sweepPhaseUp(psif, theta_min, theta_max, phi_max, tau) | |
psif = result.final_state | |
gamma = -(phi_max-phi_min)*np.sin(theta_min/2.)**2. | |
grefe = psif.overlap(psi0) | |
ref = np.exp(1j*gamma) | |
resrels[i] = grefe.real | |
resimag[i] = grefe.imag | |
refrels[i] = ref.real | |
refimag[i] = ref.imag | |
title = '$\\phi_f \\in [0, 2\\pi]$ and $\\theta = \\frac{3\\pi}{4}$ fixed' | |
x_axis = '$\\phi_f$ [$\\pi$]' | |
filename = 'res_qubit_2_1.png' | |
plotQubit(angles, refrels, refimag, resrels, resimag, title, x_axis, filename, url=url) | |
refrels = np.zeros(res) | |
refimag = np.zeros(res) | |
resrels = np.zeros(res) | |
resimag = np.zeros(res) | |
# fix phi_max, vary theta_min | |
for i, angle in enumerate(angles): | |
theta_min = np.pi*angle | |
theta_max = 0. | |
phi_min = 0. | |
phi_max = 3.*np.pi/4. | |
psi0 = np.cos(theta_max/2.)*basis(2, 0)+np.sin(theta_max/2.)*basis(2, 1) | |
result = sweepPhaseDown(psi0, theta_min, theta_max, phi_min, tau) | |
psif = result.final_state | |
result = sweepPhaseRound(psif, theta_min, phi_min, phi_max, tau) | |
psif = result.final_state | |
result = sweepPhaseUp(psif, theta_min, theta_max, phi_max, tau) | |
psif = result.final_state | |
gamma = -(phi_max-phi_min)*np.sin(theta_min/2.)**2. | |
grefe = psif.overlap(psi0) | |
ref = np.exp(1j*gamma) | |
resrels[i] = grefe.real | |
resimag[i] = grefe.imag | |
refrels[i] = ref.real | |
refimag[i] = ref.imag | |
title = '$\\theta \\in [0, 2\\pi]$ and $\\phi_f = \\frac{3\\pi}{4}$ fixed' | |
x_axis = '$\\theta$ [$\\pi$]' | |
filename = 'res_qubit_2_2.png' | |
plotQubit(angles, refrels, refimag, resrels, resimag, title, x_axis, filename, url=url) |
@marekyggdrasil Asking this for clarity, but does the Python function SweepRound correspond to a sweep of the polar angle across the Bloch sphere, where the angle phi remains parked on the equator? I am using your illustration of the Bloch sphere from your website as a visual for describing how this part of the simulation numerically evolves the state. Also, since this evolution is adiabatic, how does one quantify how slow or adiabatic the evolution is? Is there a formulaic relationship for quantum gates in the adiabatic limit using time-dependent quantum mechanics that is assumed here in the simulation?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@marekyggdrasil Is this particular variable to remind the reader that the dynamical phase will always be an even multiple of pi for this quantity to vanish? It seems the simulation is coded to make it cancel before addressing the geometric phase factor gamma. In my case, I think I need to figure out how to account for this dynamic phase in simulation and am unsure how to model it in your code. I envision that the inherent precession of the qubit will contribute to this dynamic phase for all time because the integral for the dynamic phase is a function of energy and time E(t) dt. On average a transmon qubit might have a frequency of approx 4 Ghz given the relationship theta= 2pi/T and f =1/T, my naive assumption is this amount of theta might need to be included in the simulation and not taken out of the simulation until the end of running program I can subtract this quantity out and hopefully be left with the acquired phase as only the geometric phase.