# Import required librariesimportnumpyasnpimportmatplotlib.pyplotaspltfromIPython.displayimportdisplay,Latexfromdatetimeimportdatetimefrompytzimporttimezone# Install and import QuTiP if neededtry:fromqutipimport*exceptImportError:%pipinstallqutipfromqutipimport*# Configure matplotlib for LaTeX renderingplt.rcParams.update({"text.usetex":True,"text.latex.preamble":r"\usepackage{amsmath} \usepackage{physics}","font.family":"serif",})%configInlineBackend.figure_format='svg'# Print version and execution time infoprint(f"QuTiP version: {qutip.__version__}")print("Time of execution: ",datetime.now(timezone("America/Chicago")).strftime("%Y-%m-%d %H:%M:%S"),)
12
QuTiP version: 5.1.1
Time of execution: 2025-04-02 14:04:19
Show that \(e^{-i \frac{\theta}{2} \vec{n} \cdot \vec{\sigma}}=\mathbb{I} \cos \left(\frac{\theta}{2}\right)-i \vec{n} \cdot \vec{\sigma} \sin \left(\frac{\theta}{2}\right)\), with \(\vec{n}\) being a normalized vector. Hint: \(\sigma_{x, y, z}^2=\mathbb{I}\).
Solution:
First of all we can show that \((\vec{n} \cdot \vec{\sigma})^2=\mathbb{I}\).
It is convenient to be able to decompose operations into discrete pulses about orthogonal axes. Show that you can realize an arbitrary unitary in the form:
which satisfy the condition of Eq.\(~\ref{eq:phi_relation}\). Thus we verify that \(\hat{U}=e^{i \alpha} R_z(\beta) R_y(\gamma) R_z(\delta)\) gives us an arbitrary unitary \(2 \times 2\) matrix.
The matrix representation of the SWAP gate, \(\left(\begin{array}{llll}1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1\end{array}\right)\) at a glance appears similar to that of the CNOT gate, \(\left(\begin{array}{cccc}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0\end{array}\right)\), in the standard two-qubit basis \(\{|00\rangle,|01\rangle,|10\rangle,|11\rangle\}\). However, unlike the CNOT gate, the SWAP gate cannot generate entanglement. There are several qubit systems in which you can apply a SWAP operation for a variable time. This allows you to perform a "half-SWAP", also called a \(\sqrt{S W A P}\), with \(\sqrt{S W A P} \sqrt{S W A P}=S W A P\). The \(\sqrt{S W A P}\) is an entangling gate!
So, we simply aim to compute the eigenvalues and eigenvectors of the normal \(S W A P\) matrix. Observe that the eigenvalues and eigenvectors are as follows:
Show that the \(\sqrt{S W A P}\) gate can generate entanglement by creating the \(\left|\phi^{+}\right\rangle=(|00\rangle+|11\rangle) / \sqrt{2}\) Bell state from the two-qubit input state \(|00\rangle\). (Hint: you may need to use the \(\sqrt{S W A P}\) gate more than once along with several single qubit operations)
Spin review and intro to QuTiP. Please submit, \(\textbf{via Canvas}\), a Jupyter notebook for this problem along with your pen/paper work.
The Hamiltonian for a spin-\(1 / 2\) in a magnetic field, \(\boldsymbol{B}\), is given by
\[
H=-\vec{\mu} \cdot \vec{B}=-\frac{1}{2} g \mu_B \vec{\sigma} \cdot \vec{B},
\]
where \(g\) is the Landé g -factor, \(\mu_B\) is the Bohr magneton, and \(\vec{\sigma}=\left(\sigma_x, \sigma_y, \sigma_z\right)\) is a vector of Pauli spin operators.
Find the expectation value of the spin projection, \(\langle\vec{\sigma}\rangle=\left(\left\langle\sigma_x\right\rangle,\left\langle\sigma_y\right\rangle,\left\langle\sigma_z\right\rangle\right)\), for each of the following quantum states in (1) Dirac braket notation, (2) matrix notation, and (3) on QuTiP:
(i) \(|\psi\rangle=|0\rangle\)
(ii) \(|\psi\rangle=(|0\rangle+|1\rangle) / \sqrt{2}\)
defplot_states_on_bloch_sphere(states_dict):"""Plot quantum states on the Bloch sphere with annotations."""b=Bloch()# Extract states and prepare annotationsstate_list=list(states_dict.values())annotations=["(i)","(ii)","(iii)"]# Add states to Bloch sphereb.add_states(state_list)b.vector_color=["r","g","b"]b.vector_width=2# Add annotationsfori,stateinenumerate(state_list):b.add_annotation(state,annotations[i])returnb# Plot our states on the Bloch spherebloch=plot_states_on_bloch_sphere(states)bloch.show()
Evaluate the spin Hamiltonian in matrix form assuming the magnetic field points along the \(x\) direction, \(\vec{B}=\left(B_x, 0,0\right)\). Find its eigenvalues and the corresponding eigenvectors.
Solution:
\[
\begin{equation}
H = -\vec{\mu} \cdot \vec{B} = -\frac{1}{2} g \mu_B \vec{\sigma} \cdot \vec{B} =
-\frac{1}{2} g \mu_B B_x \sigma_x =
-\frac{1}{2} g \mu_B B_x
\begin{pmatrix}
0 & 1 \\
1 & 0
\end{pmatrix}.
\end{equation}
\]
Finding the eigenvalues and eigenvectors of this Hamiltonian means finding them for \(\sigma_x\). Since \(\sigma_x^2 = \mathbb{I}\), its eigenvalues must be \(\pm 1\), because, if \(\lambda\) is an eigenvalue to eigenvector \(\ket{\psi_\lambda}\):
Now define the spin Hamiltonian in QuTiP and use it to find the eigenvalues and eigenvectors. For this, use natural units (set \(h=1\) such that your Hamiltonian takes on units of frequency (not radial frequency!) instead of energy), let \(g=2, \mu_B=1.4\)\(\mathrm{MHz} /\) gauss, and \(B_x=200\) gauss.
defconstruct_spin_hamiltonian(g,mu_B,B_field):"""Construct spin-1/2 Hamiltonian in a magnetic field: H = -½ g μB B·σ."""return-0.5*g*mu_B*B_field*sigmax()defanalyze_hamiltonian(hamiltonian):"""Analyze a Hamiltonian by computing eigenvalues and eigenstates."""# Diagonalize the Hamiltonianevals,ekets=hamiltonian.eigenstates()# Display Hamiltonianprint("Hamiltonian matrix:")print(hamiltonian)# Display eigenvaluesprint("\nEnergy eigenvalues:")fori,valinenumerate(evals):state_type="Ground state"ifval<0else"Excited state"print(f"{state_type}: {val:.2f} MHz")# Display eigenvectorsprint("\nEigenvectors (in the computational basis |0⟩, |1⟩):")fori,vecinenumerate(ekets):state_type="Ground state"ifevals[i]<0else"Excited state"print(f"\n{state_type} eigenvector:")print(vec)vec_data=vec.full().flatten()vec_str=f"{vec_data[0]:.5f}|0⟩ + {vec_data[1]:.5f}|1⟩"print(f"In ket notation: {vec_str}")# Add theoretical expressionifnp.isclose(abs(vec_data[0]),1/np.sqrt(2))andnp.isclose(abs(vec_data[1]),1/np.sqrt(2)):sign="+"ifvec_data[0]*vec_data[1]>0else"-"print(f"Theoretical form: 1/√2(|0⟩ {sign} |1⟩)")# Calculate the energy gapenergy_gap=abs(evals[1]-evals[0])print(f"\nEnergy gap between levels: {energy_gap:.2f} MHz")returnevals,ekets,energy_gap# Parameters (in natural units: h = 1, output in MHz)PARAMS={"g":2.0,# Landé g-factor"mu_B":1.4,# Bohr magneton in MHz/G"B_x":200,# Magnetic field in Gauss}# Construct and analyze the HamiltonianH=construct_spin_hamiltonian(PARAMS["g"],PARAMS["mu_B"],PARAMS["B_x"])evals,ekets,energy_gap=analyze_hamiltonian(H)# Verify energy gap matches theorytheoretical_gap=PARAMS["g"]*PARAMS["mu_B"]*PARAMS["B_x"]print(f"This equals g*μB*B = {theoretical_gap:.2f} MHz")
Using QuTiP, plot the spectrum (i.e. the eigenenergies) as a function of the magnetic field strength \(B_x\). Make sure that your axes are labeled and have units.
defplot_energy_spectrum(g,mu_B,B_range,num_points=100):"""Plot energy spectrum of spin-1/2 in magnetic field as function of field strength."""# Create an array of magnetic field valuesB_values=np.linspace(B_range[0],B_range[1],num_points)# Calculate eigenvalues for each B valueeigenvalues=np.zeros((len(B_values),2))fori,Binenumerate(B_values):H_B=construct_spin_hamiltonian(g,mu_B,B)eigenvalues[i,:]=H_B.eigenenergies()# Plot the resultsplt.figure(figsize=(8,5))# Ground stateplt.plot(B_values,eigenvalues[:,0],"b-",linewidth=2,label=r"Ground state: $\ket{\psi} = \frac{\ket{0} + \ket{1}}{\sqrt{2}}$",)# Excited stateplt.plot(B_values,eigenvalues[:,1],"r-",linewidth=2,label=r"Excited state: $\ket{\psi} = \frac{\ket{0} - \ket{1}}{\sqrt{2}}$",)# Stylingplt.xlabel("Magnetic Field $B_x$ (Gauss)",fontsize=14)plt.ylabel("Energy (MHz)",fontsize=14)plt.title("Energy Spectrum of Spin-1/2 in x-directed Magnetic Field",fontsize=16)plt.axhline(y=0,color="k",linestyle="--",alpha=0.3)plt.fill_between(B_values,eigenvalues[:,0],eigenvalues[:,1],color="gray",alpha=0.2)plt.legend(fontsize=12)plt.grid(True,alpha=0.3)plt.tight_layout()returnplt# Plot the energy spectrum for field range 0-400 Gaussplot_energy_spectrum(PARAMS["g"],PARAMS["mu_B"],[0,400],100)plt.show()