Skip to content

Instantly share code, notes, and snippets.

@marekyggdrasil
Last active January 11, 2024 17:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marekyggdrasil/66a5b0d822eb60b27b68144045613bcd to your computer and use it in GitHub Desktop.
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/
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)
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)
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)
@jtucker532
Copy link

jtucker532 commented Jan 10, 2024

@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.

@jtucker532
Copy link

jtucker532 commented Jan 10, 2024

@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