Building a Physical Qubit#

  • Author:

  • Date:

  • Time spent on this assignment:

!pip install scqubits
!pip install qiskit
!pip install qiskit[visualization];
!pip install qiskit_aer;
!pip install qutip
Collecting scqubits
  Downloading scqubits-4.1.0-py3-none-any.whl.metadata (2.5 kB)
Requirement already satisfied: cycler in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from scqubits) (0.12.1)
Collecting cython>=0.29.20 (from scqubits)
  Downloading Cython-3.0.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.2 kB)
Requirement already satisfied: matplotlib>=3.5.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from scqubits) (3.7.5)
Requirement already satisfied: numpy>=1.14.2 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from scqubits) (1.24.4)
Requirement already satisfied: scipy>=1.5 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from scqubits) (1.10.1)
Requirement already satisfied: dill in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from scqubits) (0.3.9)
Requirement already satisfied: sympy in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from scqubits) (1.13.3)
Collecting tqdm (from scqubits)
  Downloading tqdm-4.67.1-py3-none-any.whl.metadata (57 kB)
Requirement already satisfied: typing-extensions in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from scqubits) (4.12.2)
Collecting qutip<5.0 (from scqubits)
  Downloading qutip-4.7.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (7.7 kB)
Requirement already satisfied: contourpy>=1.0.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.5.1->scqubits) (1.1.1)
Requirement already satisfied: fonttools>=4.22.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.5.1->scqubits) (4.55.2)
Requirement already satisfied: kiwisolver>=1.0.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.5.1->scqubits) (1.4.7)
Requirement already satisfied: packaging>=20.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.5.1->scqubits) (24.2)
Requirement already satisfied: pillow>=6.2.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.5.1->scqubits) (10.4.0)
Requirement already satisfied: pyparsing>=2.3.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.5.1->scqubits) (3.1.4)
Requirement already satisfied: python-dateutil>=2.7 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.5.1->scqubits) (2.9.0.post0)
Requirement already satisfied: importlib-resources>=3.2.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.5.1->scqubits) (6.4.5)
Requirement already satisfied: mpmath<1.4,>=1.1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from sympy->scqubits) (1.3.0)
Requirement already satisfied: zipp>=3.1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from importlib-resources>=3.2.0->matplotlib>=3.5.1->scqubits) (3.20.2)
Requirement already satisfied: six>=1.5 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from python-dateutil>=2.7->matplotlib>=3.5.1->scqubits) (1.17.0)
Downloading scqubits-4.1.0-py3-none-any.whl (6.5 MB)
?25l   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/6.5 MB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.5/6.5 MB 64.7 MB/s eta 0:00:00
?25hDownloading Cython-3.0.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.6 MB)
?25l
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/3.6 MB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.6/3.6 MB 91.4 MB/s eta 0:00:00
?25h
Downloading qutip-4.7.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (16.8 MB)
?25l   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/16.8 MB ? eta -:--:--
   ━━╸━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.0/16.8 MB 256.1 MB/s eta 0:00:01
   ━━━━━━━━━━━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━ 6.3/16.8 MB 15.3 MB/s eta 0:00:01
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸━━ 15.7/16.8 MB 25.7 MB/s eta 0:00:01
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 16.8/16.8 MB 25.0 MB/s eta 0:00:00
?25hDownloading tqdm-4.67.1-py3-none-any.whl (78 kB)
Installing collected packages: tqdm, cython, qutip, scqubits
Successfully installed cython-3.0.11 qutip-4.7.6 scqubits-4.1.0 tqdm-4.67.1
Requirement already satisfied: qiskit in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (1.2.4)
Requirement already satisfied: rustworkx>=0.15.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (0.15.1)
Requirement already satisfied: numpy<3,>=1.17 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (1.24.4)
Requirement already satisfied: scipy>=1.5 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (1.10.1)
Requirement already satisfied: sympy>=1.3 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (1.13.3)
Requirement already satisfied: dill>=0.3 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (0.3.9)
Requirement already satisfied: python-dateutil>=2.8.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (2.9.0.post0)
Requirement already satisfied: stevedore>=3.0.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (5.3.0)
Requirement already satisfied: typing-extensions in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (4.12.2)
Requirement already satisfied: symengine<0.14,>=0.11 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit) (0.13.0)
Requirement already satisfied: six>=1.5 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from python-dateutil>=2.8.0->qiskit) (1.17.0)
Requirement already satisfied: pbr>=2.0.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from stevedore>=3.0.0->qiskit) (6.1.0)
Requirement already satisfied: mpmath<1.4,>=1.1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from sympy>=1.3->qiskit) (1.3.0)
Requirement already satisfied: qiskit[visualization] in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (1.2.4)
Requirement already satisfied: rustworkx>=0.15.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (0.15.1)
Requirement already satisfied: numpy<3,>=1.17 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (1.24.4)
Requirement already satisfied: scipy>=1.5 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (1.10.1)
Requirement already satisfied: sympy>=1.3 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (1.13.3)
Requirement already satisfied: dill>=0.3 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (0.3.9)
Requirement already satisfied: python-dateutil>=2.8.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (2.9.0.post0)
Requirement already satisfied: stevedore>=3.0.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (5.3.0)
Requirement already satisfied: typing-extensions in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (4.12.2)
Requirement already satisfied: symengine<0.14,>=0.11 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (0.13.0)
Requirement already satisfied: matplotlib>=3.3 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (3.7.5)
Requirement already satisfied: pydot in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (3.0.3)
Requirement already satisfied: Pillow>=4.2.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (10.4.0)
Requirement already satisfied: pylatexenc>=1.4 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (2.10)
Requirement already satisfied: seaborn>=0.9.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit[visualization]) (0.13.2)
Requirement already satisfied: contourpy>=1.0.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.3->qiskit[visualization]) (1.1.1)
Requirement already satisfied: cycler>=0.10 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.3->qiskit[visualization]) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.3->qiskit[visualization]) (4.55.2)
Requirement already satisfied: kiwisolver>=1.0.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.3->qiskit[visualization]) (1.4.7)
Requirement already satisfied: packaging>=20.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.3->qiskit[visualization]) (24.2)
Requirement already satisfied: pyparsing>=2.3.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.3->qiskit[visualization]) (3.1.4)
Requirement already satisfied: importlib-resources>=3.2.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from matplotlib>=3.3->qiskit[visualization]) (6.4.5)
Requirement already satisfied: six>=1.5 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from python-dateutil>=2.8.0->qiskit[visualization]) (1.17.0)
Requirement already satisfied: pandas>=1.2 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from seaborn>=0.9.0->qiskit[visualization]) (2.0.3)
Requirement already satisfied: pbr>=2.0.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from stevedore>=3.0.0->qiskit[visualization]) (6.1.0)
Requirement already satisfied: mpmath<1.4,>=1.1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from sympy>=1.3->qiskit[visualization]) (1.3.0)
Requirement already satisfied: zipp>=3.1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from importlib-resources>=3.2.0->matplotlib>=3.3->qiskit[visualization]) (3.20.2)
Requirement already satisfied: pytz>=2020.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from pandas>=1.2->seaborn>=0.9.0->qiskit[visualization]) (2024.2)
Requirement already satisfied: tzdata>=2022.1 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from pandas>=1.2->seaborn>=0.9.0->qiskit[visualization]) (2024.2)
Requirement already satisfied: qiskit_aer in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (0.15.1)
Requirement already satisfied: qiskit>=1.1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit_aer) (1.2.4)
Requirement already satisfied: numpy>=1.16.3 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit_aer) (1.24.4)
Requirement already satisfied: scipy>=1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit_aer) (1.10.1)
Requirement already satisfied: psutil>=5 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit_aer) (6.1.0)
Requirement already satisfied: rustworkx>=0.15.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit>=1.1.0->qiskit_aer) (0.15.1)
Requirement already satisfied: sympy>=1.3 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit>=1.1.0->qiskit_aer) (1.13.3)
Requirement already satisfied: dill>=0.3 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit>=1.1.0->qiskit_aer) (0.3.9)
Requirement already satisfied: python-dateutil>=2.8.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit>=1.1.0->qiskit_aer) (2.9.0.post0)
Requirement already satisfied: stevedore>=3.0.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit>=1.1.0->qiskit_aer) (5.3.0)
Requirement already satisfied: typing-extensions in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit>=1.1.0->qiskit_aer) (4.12.2)
Requirement already satisfied: symengine<0.14,>=0.11 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qiskit>=1.1.0->qiskit_aer) (0.13.0)
Requirement already satisfied: six>=1.5 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from python-dateutil>=2.8.0->qiskit>=1.1.0->qiskit_aer) (1.17.0)
Requirement already satisfied: pbr>=2.0.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from stevedore>=3.0.0->qiskit>=1.1.0->qiskit_aer) (6.1.0)
Requirement already satisfied: mpmath<1.4,>=1.1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from sympy>=1.3->qiskit>=1.1.0->qiskit_aer) (1.3.0)
Requirement already satisfied: qutip in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (4.7.6)
Requirement already satisfied: numpy>=1.16.6 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qutip) (1.24.4)
Requirement already satisfied: scipy<1.13.0,>=1.0 in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qutip) (1.10.1)
Requirement already satisfied: packaging in /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages (from qutip) (24.2)
import numpy as np
import matplotlib.pyplot as plt
import random
import pylab as plt
import scipy.linalg
import scqubits
import matplotlib.animation as animation
from IPython.display import HTML
import scqubits

import numpy as np
from qiskit import QuantumCircuit, QuantumRegister, transpile
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
from qiskit.circuit.library.standard_gates import ZGate, XGate
from qiskit.visualization import plot_bloch_vector
from qiskit.visualization import plot_distribution
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
import qutip
from qiskit.circuit.quantumregister import AncillaRegister
import pylab as plt
from qiskit.circuit.library import MCMT
import numpy as np
import scipy
from qiskit import *


def resetMe(keepList=[]):
    ll=%who_ls
    keepList=keepList+['resetMe','np','plt','random']
    for iiii in keepList:
        if iiii in ll:
            ll.remove(iiii)
    for iiii in ll:
        jjjj="^"+iiii+"$"
        %reset_selective -f {jjjj}
    ll=%who_ls
    return
import datetime;datetime.datetime.now()

sigma_x=np.matrix([[0,1],[1,0]],dtype=complex)
sigma_z=np.matrix([[1,0],[0,-1]],dtype=complex)

def PrintDirac(out_state_a):
  out_state=np.asarray(out_state_a)
  l=len(out_state)
  num_qubits=int(round(np.log(len(out_state))/np.log(2)))
  for i in range(0,l):
    if not np.isclose(out_state[i],0):
      print(str(out_state[i])+'|'+bin(i)[2:].zfill(num_qubits)[::-1]+'>',end=' + ')
  print()

def MakeState(v):
  numWires=int(round(np.log2(len(v))))
  qc1=QuantumCircuit(numWires,numWires)
  qc1.initialize(v)
  a,_=RunCircuit(qc1)
  return a

def PlotBloch(v,bb):
  vv=np.asarray(v)
  #print(vv)
  a=vv[0]*np.conj(vv[0])
  b=vv[1]*np.conj(vv[0])
  x = np.real(2.0 * b.real)
  y = np.real(2.0 * b.imag)
  z = np.real(2.0 * a - 1.0)
  #print(x,y,z)
  bb.add_vectors([x,y,z])
  return  #plot_bloch_vector([x,y,z])

def RunCircuit(circuit,a=None):
  numQubits=circuit.num_qubits
  if a!=None:
    numQubits=max(numQubits,a.num_qubits)
    initCircuit=QuantumCircuit(a.num_qubits,a.num_qubits)
    initCircuit.initialize(a)
    circuit=AddCircuits([initCircuit,circuit])
  circuit.save_statevector(label='myStateVector')
  compiled_circuit = transpile(circuit, simulator)
  resultA = simulator.run(compiled_circuit).result()
  forward=list(range(0,numQubits))
  reverse=forward[::-1]
  circuit.measure(forward,reverse)
  compiled_circuit = transpile(circuit, simulator)
  resultB = simulator.run(compiled_circuit).result()
  return resultA.data()['myStateVector'],resultB.data()['counts']


def AddCircuits(theCircuits):
  numQubits=np.array([c.num_qubits for c in theCircuits])
  numQubits=np.max(numQubits)
  circuit=QuantumCircuit(numQubits,numQubits)
  for i in range(0,len(theCircuits)):
    circuit=circuit.compose(theCircuits[i],qubits=list(range(0,theCircuits[i].num_qubits)))
  return circuit



def AddBlochSphere(overlap,ax,withArrow=False):
    rho = np.outer(overlap.conj(), overlap)
    bvec=(2 * np.real(rho[0,1]), 2 * np.imag(rho[0,1]), np.real(rho[0,0]) - np.real(rho[1,1]))
    if withArrow:
        sf = ax.quiver([0,], [0,],[0,],bvec[0], bvec[1], bvec[2])
    ax.scatter(bvec[0],bvec[1],bvec[2], color='r')
    return ax

def MakeBlochSphere():
    fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
    ax.set_zlim([0,1])
    ax.clear()
    ax.set_xlim([-1.1,1.1])
    ax.set_ylim([-1.1,1.1])
    ax.set_zlim([-1.1,1.1])
    u, v = np.mgrid[0:2*np.pi:100j, 0:np.pi:100j]
    x = np.cos(u)*np.sin(v)
    y = np.sin(u)*np.sin(v)
    z = np.cos(v)
    ax.plot_surface(x, y, z, color="yellow", alpha = 0.3)
    ax.set_box_aspect((2,2,2))
    return ax

simulator = AerSimulator()
UserWarning: The new version of Cython, (>= 3.0.0) is not supported.
 /opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/site-packages/qutip/__init__.py: 66

Overview#

So far we’ve learned about quantum computing as an abstract model of computation. We can represent a qubit as a vector of length 2 (and can represent \(n\) qubits as a vector of length \(2^n\)).

In this section our goal is to understand how we actually build a quantum computer in the real world (and here we will only focus on 1 qubit).

Our goal will be to understand how you represent one qubit and apply a gate to it.

There are various different physical realizations of a qubit. In this assignment, we will look at quantum electronic circuits.

Exericise 0: What Abstract Gate are you trying to implement?#

a. Abstract Model of Computation#

Our target here is we want to go ahead and implement a gate using electronics. The gate we are going to implement is the following gate:

circuit.rx(1./50.)
circuit.rz(1./50.)

Let’s start by implementing this in qiskit.

Run the gate \(k\) times (from \(0 \leq k < 400\)) and graph (with two lines) the probability you would measure “0” and the probability you would measure “1” as a function of \(k\).

## ANSWER HERE

We know that the state of a single qubit is \(\alpha |0\rangle + \beta |1\rangle\) where \(|\alpha|^2 + |\beta|^2=1\). We might think that we could then represent the qubit by a point \((\alpha, \beta)\) which is on a circle of radius 1. But \(\alpha\) and \(\beta\) are complex numbers so it’s not quite that simple - instead you can represent the qubit as a point on a sphere. This is called the Bloch sphere. (Technical point: You might think that you need four numbers to represent two complex numbers but it’s actually only three because of the normalization and relative phase).

At the moment, it’s not important that you know how to perform this mapping but to understand for every qubit there is a point that it appears on the bloch sphere.

Plot a qubit on the Bloch sphere using a numpy array of overlap that correspond to the overlap with \(|0\rangle\) and the overlap with \(|1\rangle\) (you’ve done it in QC1)

overlap = np.array([np.sqrt(0.8), np.sqrt(0.2)])
state = MakeState(overlap)
b = qutip.Bloch()
PlotBloch(state, b)
b.render()
b.show()
### ANSWER HERE

Exercise 1: Particle in a box#

  • List of collaborators:

  • References you used in developing your code:

We will need to begin by learning or recalling some aspects about quantum mechanics. There are three key things that you need to know about quantum mechanics:

  • In quantum mechanics, the “rules” of the physical system are represented by a matrix called the Hamiltonian \(H\) (in many ways, the classical analogue of the energy) and the state of your system is represented by a vector \(\Psi\).

  • If your quantum is in state \(\Psi(0)\) at time 0, you can figure out what your Hamiltonian is at time \(t\) by $\(\Psi(t) = \exp[-i t H] \Psi(0).\)$ In order to do that matrix exponential you can use

expH = scipy.linalg.expm(-1.j * H * t)

If you are going to a large time \(t\), it will often make sense to break it apart into a number of \(T/\delta t\) smaller time steps each of size \(\delta t\). This will let you record information about your quantum state at each time step \(\delta t\) - i.e. something like

for step in ts:
    psi = scipy.linalg.expm(-1.j * H * delta_t) @ psi
  • There are special quantum states \(\Psi_i\) which don’t change in time under time evolution. These states are the eigenstates of \(H\). You can get the i’th eigenstate of \(H\) by doing

np.linalg.eigh(H)[1][:,i]

a. Hamiltonian for a Particle in a Box#

We can start by working with a particle in a box. Consider a particle in a box of length 20 spanning \(-10 \leq x \leq 10\).

The Hamiltonian for a particle in a box is $\( H=-\frac{\partial^2 }{\partial x^2} \)\( with hard walls for any \)|x|\geq 20$ outside the box.

We need to convert this into a matrix. To do that, we should know from calculus that the stencil for a second derivative is $\( \frac{\partial^2 }{\partial x^2} \equiv \frac{f(x+\delta) - 2 f(x) + f(x-\delta)}{\delta^2} \)$

We can let the rows and columns of the matrix \(H\) be indexed by the values of \(x\) - to get the values of \(x\), we can do

L = 20
delta_x = 0.01
xs = np.arange(-L/2, L/2+delta_x, delta_x)

Then the above stencil corresponds to the matrix $\( H[i,j] = \begin{cases} 2/(\delta x)^2 & \text{if } i == j \\ -1/(\delta x)^2 & \text{if } \textrm{abs}(i-j)== 1\\ 0 & \text{otherwise } \end{cases} \)$

  • Make the Hamiltonian matrix H

  • diagonalize it and

  • plot the first four eigenstates \(v_a, v_b, v_c, v_d\) You should recognize the solutions to the particle in a box.

Answer (start)
## ANSWER HERE
Answer (start)

The eigenvalues for a particle in a box are quantized. They should be equal to $\(E_n = \frac{\pi^2}{L^2}n^2\)\( for \)n={1,2,…}$.

Plot the lowest five eigen-energies and compare them against this formula.

Answer (start)
### ANSWER HERE
Answer (start)

b. Time Evolution#

Our next step will be to implement time evolution. Let us start by trying to time-evolve \(v_a\) under the Hamiltonian \(H\). Recall that eigenstates should be stationary (and so don’t evolve in time). Therefore, under time evolution we should find that this state always looks the same. Let’s check this.

Using

  • a total time of \(T=5\)

  • a time step of \(\delta t=0.1\)

Plot the value of \(|v(t)|\) at time steps \(t=\{0,1,3,5\}\). The absolute value is necessary because under time-evolution the wave-function can become complex (one could also plot the phase of the wave-function if desired but don’t worry about this).

Answer (start)
### ANSWER HERE
Answer (start)

You should have noticed that our previous time evolution was pretty uninteresting as nothing changed under the time evolution. Our next step will be to implement time evolution on a more complicated state.

We will consider two states:

\[v_0=\frac{1}{\sqrt{2}}(v_a+v_b)\]
\[v_1=\frac{1}{\sqrt{2}}(v_a-v_b)\]

These two states are orthogonal on each other - i.e. np.vdot(v0,v1)=0. You can check this.

We want to do time evolution with our Hamiltonian on the state \(v_0\).
Perform time evolution

  • starting at \(v_0\)

  • \(\delta t=0.1\)

  • for time \(T=50\)

  • and graph the result at \(T=\{4.0,18.3,41.0\}\)

  • Also graph (with dotted lines - linestyle="--") \(v_0\) and \(v_1\)

Answer (start)
### ANSWER HERE
Answer (start)

c. State overlaps#

We’ve seen that our time evolution slowly moves us from state \(v_0\) to state \(v_1\) over a time over a time of \(T=41\). In between, \(T=0\) and \(T=41\), the state is a little bit of \(v_0\) and a little bit of \(v_1\). We would like to quantify this better by computing the overlap with these two states as a function of time.

We have a state \(v(t)\). To compute the overlap with \(v_0\) we can just do np.vdot(v , v_0).

This overlap is a complex number. We can only plot real numbers so if we want to plot it, we need to plot something like

  • the absolute value np.abs(...) (or its square) and

  • phase np.angle(...) or

Plot as a function of time from \(T=0\) to \(T=100\) the absolute value squared of the overlap of \(v(t)\) with both \(v_0\) and \(v_1\).

Answer (start)
### ANSWER HERE
Answer (start)

Now we can get our first inkling of how you might build a qubit and a (always-on and hence not-very-useful) gate.

Suppose someone comes to you with a particle in a box. There are many eigenstates for that particle in the box: \(v_0, v_1, v_2, v_3, ...\)

You pick two of those eigenstates (let’s say \(v_0\) and \(v_1\)) and claim that those are the states that correspond to \(|0\rangle\) and \(|1\rangle\).

This particle-in-a-box is now a qubit. The other eigenstates we ignore (and are hoping that you never accidentally get stuck in - this would cause an error).

Now a gate is something that takes you from one quantum state to another. For example, a not gate should take

\[|0\rangle \rightarrow |1\rangle\]
\[|1\rangle \rightarrow |0\rangle\]

Looking at our previous results, we can see that if we just have a particle-in-a-box that it implements a not-gate every \(T=41.0\) seconds.

This is a little bit unsatsifying because it’s not like we can turn our Hamiltonian on and off. We really need a Hamiltonian \(H(\theta)\) where we have some knob \(\theta\) that we can change so we can turn gates on and off.

In the next exercise, we will see how to go about this.

Exercise 2: Fluxonium#

In the previous exercise, we worked on a particle-in-a-box. Unfortuantely, you don’t run into such physical systems particular often. In this exercise, we will work with something more realistic: a fluxonium built out of various electronic components.

Here is the electronic circuit for a fluxonium qubit:

Answer (start)

The fluxoinum qubit consists of three electronic components: a capacitor, an inductor, and a Josephson junction. You’re probably familiar with capacitors and inductors. You regularly run into them in classical circuits. A Josephson junction is an electronic component which sandwhiches an insulator between two superconducting materials. Across the Josephson junction there is a change in the phase \(\phi\).

Typically in a circuit you need to keep track of the voltage and current. When you have a Josephson Junction you need to keep track also of the phase.

In electronics you might have treated the circuit classically righting out the classical energy of the circuit - i.e. \(E=\frac{1}{2}CV^2+ \frac{1}{2}LI^2\) In quantum mechanics, instead of writing out an energy for our circuit, we write out a Hamiltonian \(H\).

a. Fluxonium Hamiltonian#

The relevant Hamiltonian for this circuit is

\[H=-4E_\text{C}\frac{\partial^2 }{\partial \phi^2}+\frac{1}{2}E_L \phi^2 -E_\text{J}\cos(\phi-\varphi_\text{ext}) \]

where \(E_C\) is the charging energy, \(E_J\) the Josephson energy and \(E_L\) the inductive energy.

In the particle-in-a-box we were working with \(x\). Here you should just mentally replace \(\phi\) with \(x\). Just like earlier we will let \(-10\leq \phi \leq 10\).

Now we can look at this Hamiltonian. The first term, \(-4E_\text{C}\frac{\partial^2 }{\partial \phi^2}\) you’ve already seen; this is the particle-in-a-box term (notice the extra factor of \(4E_C\)). You already know how to build the matrix for this term. This term is caused by the capacitor. Essentially the capacitor would like the wave-function (when drawn in the \(\phi\) basis) to be more spread out.

We will then need to add a matrix for the the inductor term and the Josephson junction term. Both of these terms will be diagonal matrices.

The term \(\frac{1}{2}E_L \phi^2\) is the Hamiltonian for the inductor and has the matrix \(H[\phi,\phi] = \frac{1}{2}E_L \phi^2\) (and zero otherwise)

The term \(E_\text{J}\cos(\phi-\varphi_\text{ext})\) is the Hamiltonian for the inductor and has the matrix \(H[\phi,\phi] = E_\text{J}\cos(\phi-\varphi_\text{ext})\) (and zero otherwise).

\(\varphi_\text{ext}\) is a number that you (as an experimentalist) get to control as a knob. It corresponds to the amount of magnetic flux (caused by sticking a manget in the right place) you drive through a hole in the circuit.

By changing this we will be able to turn circuit elements on and off.

Build this Hamiltonian for \(H\). Use the following parameters:

  • Ec=0.5

  • El=0.8

  • Ej=4

  • \(\varphi_\text{ext}=\pi\)

As in the previous case, we want to diagonalize our Hamiltonian and find some number of eigenstates. Plot the first three eigenstates as well as eigenvalues.

Answer (start)
### ANSWER HERE
Answer (end)

b. Time Evolution#

We are going to use the first two eigenstates \(v_0\) and \(v_1\) as the \(|0\rangle\) and \(|1\rangle\) states for our qubit. Then we are going to see how manipulating \(\varphi_\textrm{ext}\) allows us to turn on and off different gates.

We have already decided what our eigenstates are \(|0\rangle\) and \(|1\rangle\) are going to be. Let’s imagine that we have set up our eigenstate into state \(|0\rangle\). Now, we imagine that we change our magnetic field to \(\pi + 0.00360 \times 2\pi\). Then the eigenstate (from the previous external field) is going to change based on our new field. Do time evolution with this Hamiltonian for a

  • time \(T=100\) with

  • \(\delta t=0.1\) and

  • plot the overlap squared with the states \(|0\rangle\) and \(|1\rangle\).

Answer (start)
### ANSWER HERE
Answer (end)

You will notice that by changing the magnetic field by a tiny amount and waiting for about 24 seconds, we’ve implemented a gate which takes \(|0\rangle\) to half \(|0\rangle\) and half \(|1\rangle\). Because this is probabilities that you are measuring, actually this gate is taking \(|0\rangle \rightarrow \frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)\) (actually the plot you made isn’t sufficient information to distinguish between \(+|1\rangle\) and \(-|1\rangle\).

Actually, if you want more seconds (or less seconds) you actually get a whole manifold of states. In the next two sections, we will better understand the manifold of gates we’ve made.

c. The Bloch Sphere#

Using your results from (b), plot on the Bloch sphere your gate. Identify where on the Bloch sphere the initial point is and the point at \(T=44\) seconds.

Answer (start)
### ANSWER HERE
Answer (end)

Exercise 3: Fluxonium with scqubits (Extra credit: 10 points)#

a.#

In this exercise, we are going to replicate the above results using a python package called scqubits. scqubits already knows about the fluxonium Hamiltonian and so we can just tell it that we want to have a fluxonium molecule by doing

fluxonium = scqubits.Fluxonium(EJ = 4,
                               EC = 0.5,
                               EL = 0.8,
                               flux = 0.5,
                               cutoff = 110)

The flux is in units of \(2\pi\) so previously we had a flux of \(\pi\). Now we have a flux of 0.5

To get the Hamiltonian of the fluxonium molecule, you should use fluxonium.hamiltonian()

You may notice that if you print the Hamiltonian it looks different then the Hamiltonian that you generated in previous sections. This is because the Hamiltonian is in a different basis. You can essentially ignore this and do the same steps that you did before. Use it to generate the absolute value and bloch sphere plots.

There is an ambiguity here in the sign of the eigenstates. Use this to change the eigenstate:

if vvv[1,1]>0:
    vvv[:,1]=vvv[:,1]*-1
Answer (start)
### ANSWER HERE
Answer (end)