mirror of
https://github.com/quantumjim/Quantum-Computation-course-Basel.git
synced 2026-09-30 06:18:23 +02:00
96 KiB
96 KiB
In [1]:
!pip install qiskit
!pip install qiskit-aer
!pip install qiskit-ibm-runtimeRequirement already satisfied: qiskit in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (2.2.1)
Requirement already satisfied: rustworkx>=0.15.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit) (0.17.1)
Requirement already satisfied: numpy<3,>=1.17 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit) (2.2.2)
Requirement already satisfied: scipy>=1.5 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit) (1.16.2)
Requirement already satisfied: dill>=0.3 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit) (0.4.0)
Requirement already satisfied: stevedore>=3.0.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit) (5.5.0)
Requirement already satisfied: typing-extensions in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit) (4.12.2)
Collecting qiskit-aer
Downloading qiskit_aer-0.17.2-cp313-cp313-macosx_11_0_arm64.whl.metadata (8.3 kB)
Requirement already satisfied: qiskit>=1.1.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-aer) (2.2.1)
Requirement already satisfied: numpy>=1.16.3 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-aer) (2.2.2)
Requirement already satisfied: scipy>=1.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-aer) (1.16.2)
Requirement already satisfied: psutil>=5 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-aer) (6.1.1)
Requirement already satisfied: python-dateutil>=2.8.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-aer) (2.9.0.post0)
Requirement already satisfied: six>=1.5 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from python-dateutil>=2.8.0->qiskit-aer) (1.16.0)
Requirement already satisfied: rustworkx>=0.15.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit>=1.1.0->qiskit-aer) (0.17.1)
Requirement already satisfied: dill>=0.3 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit>=1.1.0->qiskit-aer) (0.4.0)
Requirement already satisfied: stevedore>=3.0.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit>=1.1.0->qiskit-aer) (5.5.0)
Requirement already satisfied: typing-extensions in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit>=1.1.0->qiskit-aer) (4.12.2)
Downloading qiskit_aer-0.17.2-cp313-cp313-macosx_11_0_arm64.whl (2.1 MB)
[2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m2.1/2.1 MB[0m [31m24.6 MB/s[0m eta [36m0:00:00[0m
Installing collected packages: qiskit-aer
Successfully installed qiskit-aer-0.17.2
Collecting qiskit-ibm-runtime
Downloading qiskit_ibm_runtime-0.42.0-py3-none-any.whl.metadata (21 kB)
Requirement already satisfied: requests>=2.19 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-ibm-runtime) (2.32.3)
Collecting requests-ntlm>=1.1.0 (from qiskit-ibm-runtime)
Downloading requests_ntlm-1.3.0-py3-none-any.whl.metadata (2.4 kB)
Requirement already satisfied: numpy>=1.13 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-ibm-runtime) (2.2.2)
Requirement already satisfied: urllib3>=1.21.1 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-ibm-runtime) (2.3.0)
Requirement already satisfied: python-dateutil>=2.8.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-ibm-runtime) (2.9.0.post0)
Collecting ibm-platform-services>=0.22.6 (from qiskit-ibm-runtime)
Downloading ibm_platform_services-0.69.0-py3-none-any.whl.metadata (9.0 kB)
Collecting pydantic>=2.5.0 (from qiskit-ibm-runtime)
Downloading pydantic-2.11.10-py3-none-any.whl.metadata (68 kB)
Requirement already satisfied: qiskit>=1.4.1 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-ibm-runtime) (2.2.1)
Requirement already satisfied: packaging in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit-ibm-runtime) (24.2)
Collecting ibm_cloud_sdk_core<4.0.0,>=3.24.2 (from ibm-platform-services>=0.22.6->qiskit-ibm-runtime)
Downloading ibm_cloud_sdk_core-3.24.2-py3-none-any.whl.metadata (8.7 kB)
Collecting annotated-types>=0.6.0 (from pydantic>=2.5.0->qiskit-ibm-runtime)
Downloading annotated_types-0.7.0-py3-none-any.whl.metadata (15 kB)
Collecting pydantic-core==2.33.2 (from pydantic>=2.5.0->qiskit-ibm-runtime)
Downloading pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl.metadata (6.8 kB)
Requirement already satisfied: typing-extensions>=4.12.2 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from pydantic>=2.5.0->qiskit-ibm-runtime) (4.12.2)
Collecting typing-inspection>=0.4.0 (from pydantic>=2.5.0->qiskit-ibm-runtime)
Downloading typing_inspection-0.4.2-py3-none-any.whl.metadata (2.6 kB)
Requirement already satisfied: six>=1.5 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from python-dateutil>=2.8.0->qiskit-ibm-runtime) (1.16.0)
Requirement already satisfied: rustworkx>=0.15.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit>=1.4.1->qiskit-ibm-runtime) (0.17.1)
Requirement already satisfied: scipy>=1.5 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit>=1.4.1->qiskit-ibm-runtime) (1.16.2)
Requirement already satisfied: dill>=0.3 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit>=1.4.1->qiskit-ibm-runtime) (0.4.0)
Requirement already satisfied: stevedore>=3.0.0 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from qiskit>=1.4.1->qiskit-ibm-runtime) (5.5.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from requests>=2.19->qiskit-ibm-runtime) (3.4.1)
Requirement already satisfied: idna<4,>=2.5 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from requests>=2.19->qiskit-ibm-runtime) (3.10)
Requirement already satisfied: certifi>=2017.4.17 in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from requests>=2.19->qiskit-ibm-runtime) (2025.1.31)
Collecting cryptography>=1.3 (from requests-ntlm>=1.1.0->qiskit-ibm-runtime)
Downloading cryptography-46.0.2-cp311-abi3-macosx_10_9_universal2.whl.metadata (5.7 kB)
Collecting pyspnego>=0.4.0 (from requests-ntlm>=1.1.0->qiskit-ibm-runtime)
Downloading pyspnego-0.12.0-py3-none-any.whl.metadata (4.1 kB)
Collecting cffi>=2.0.0 (from cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibm-runtime)
Downloading cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl.metadata (2.6 kB)
Collecting requests>=2.19 (from qiskit-ibm-runtime)
Downloading requests-2.32.5-py3-none-any.whl.metadata (4.9 kB)
Collecting urllib3>=1.21.1 (from qiskit-ibm-runtime)
Downloading urllib3-2.5.0-py3-none-any.whl.metadata (6.5 kB)
Collecting PyJWT<3.0.0,>=2.10.1 (from ibm_cloud_sdk_core<4.0.0,>=3.24.2->ibm-platform-services>=0.22.6->qiskit-ibm-runtime)
Downloading PyJWT-2.10.1-py3-none-any.whl.metadata (4.0 kB)
Requirement already satisfied: pycparser in /Users/zoemcintyre/miniconda3/envs/qenv/lib/python3.13/site-packages (from cffi>=2.0.0->cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibm-runtime) (2.22)
Downloading qiskit_ibm_runtime-0.42.0-py3-none-any.whl (1.4 MB)
[2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m1.4/1.4 MB[0m [31m6.7 MB/s[0m eta [36m0:00:00[0ma [36m0:00:01[0m
[?25hDownloading ibm_platform_services-0.69.0-py3-none-any.whl (368 kB)
Downloading pydantic-2.11.10-py3-none-any.whl (444 kB)
Downloading pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl (1.8 MB)
[2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m1.8/1.8 MB[0m [31m12.3 MB/s[0m eta [36m0:00:00[0m
Downloading requests_ntlm-1.3.0-py3-none-any.whl (6.6 kB)
Downloading annotated_types-0.7.0-py3-none-any.whl (13 kB)
Downloading cryptography-46.0.2-cp311-abi3-macosx_10_9_universal2.whl (7.3 MB)
[2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m7.3/7.3 MB[0m [31m18.4 MB/s[0m eta [36m0:00:00[0ma [36m0:00:01[0m
[?25hDownloading ibm_cloud_sdk_core-3.24.2-py3-none-any.whl (75 kB)
Downloading requests-2.32.5-py3-none-any.whl (64 kB)
Downloading urllib3-2.5.0-py3-none-any.whl (129 kB)
Downloading pyspnego-0.12.0-py3-none-any.whl (130 kB)
Downloading typing_inspection-0.4.2-py3-none-any.whl (14 kB)
Downloading cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl (181 kB)
Downloading PyJWT-2.10.1-py3-none-any.whl (22 kB)
Installing collected packages: urllib3, typing-inspection, PyJWT, pydantic-core, cffi, annotated-types, requests, pydantic, cryptography, pyspnego, ibm_cloud_sdk_core, requests-ntlm, ibm-platform-services, qiskit-ibm-runtime
Attempting uninstall: urllib3
Found existing installation: urllib3 2.3.0
Uninstalling urllib3-2.3.0:
Successfully uninstalled urllib3-2.3.0
Attempting uninstall: cffi
Found existing installation: cffi 1.17.1
Uninstalling cffi-1.17.1:
Successfully uninstalled cffi-1.17.1
Attempting uninstall: requests
Found existing installation: requests 2.32.3
Uninstalling requests-2.32.3:
Successfully uninstalled requests-2.32.3
Successfully installed PyJWT-2.10.1 annotated-types-0.7.0 cffi-2.0.0 cryptography-46.0.2 ibm-platform-services-0.69.0 ibm_cloud_sdk_core-3.24.2 pydantic-2.11.10 pydantic-core-2.33.2 pyspnego-0.12.0 qiskit-ibm-runtime-0.42.0 requests-2.32.5 requests-ntlm-1.3.0 typing-inspection-0.4.2 urllib3-2.5.0
In [31]:
from qiskit import QuantumCircuit, transpile
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
import numpy as np
from tests1 import *In [32]:
def NOT(inp):
"""An NOT gate.
Parameters:
inp (str): Input, encoded in qubit 0.
Returns:
QuantumCircuit: Output NOT circuit.
str: Output value measured from qubit 0.
"""
qc = QuantumCircuit(1, 1) # A quantum circuit with a single qubit and a single classical bit
qc.reset(0)
# We encode '0' as the qubit state |0⟩, and '1' as |1⟩
# Since the qubit is initially |0⟩, we don't need to do anything for an input of '0'
# For an input of '1', we do an x to rotate the |0⟩ to |1⟩
if inp=='1':
qc.x(0)
# barrier between input state and gate operation
qc.barrier()
# Now we've encoded the input, we can do a NOT on it using x
qc.x(0)
#barrier between gate operation and measurement
qc.barrier()
# Finally, we extract the |0⟩/|1⟩ output of the qubit and encode it in the bit c[0]
qc.measure(0,0)
# We'll run the program on a simulator
backend = AerSimulator()
# Since the output will be deterministic, we can use just a single shot to get it
job = backend.run(qc, shots=1, memory=True)
output = job.result().get_memory()[0]
return qc, outputIn [33]:
for inp in ['0', '1']:
qc, out = NOT(inp)
print('NOT with input',inp,'gives output',out)
display(qc.draw())
print('\n')NOT with input 0 gives output 1
░ ┌───┐ ░ ┌─┐
q: ─|0>──░─┤ X ├─░─┤M├
░ └───┘ ░ └╥┘
c: 1/═════════════════╩═
0 NOT with input 1 gives output 0
┌───┐ ░ ┌───┐ ░ ┌─┐
q: ─|0>─┤ X ├─░─┤ X ├─░─┤M├
└───┘ ░ └───┘ ░ └╥┘
c: 1/══════════════════════╩═
0 In [34]:
qc = QuantumCircuit(2,1)
qc.h(0)
qc.x(0)
qc.cx(0,1)
qc.measure(0,0)
qc.draw()
backend = AerSimulator()
job = backend.run(qc, shots = 1056)
output = job.result()
counts = output.get_counts()
plot_histogram(counts)Out [34]:
In [35]:
### BEGIN SOLUTION
def XOR(inp1,inp2):
"""An XOR gate.
Parameters:
inpt1 (str): Input 1, encoded in qubit 0.
inpt2 (str): Input 2, encoded in qubit 1.
Returns:
QuantumCircuit: Output XOR circuit.
str: Output value measured from qubit 1.
"""
qc = QuantumCircuit(2, 1)
qc.reset(range(2))
if inp1=='1':
qc.x(0)
if inp2=='1':
qc.x(1)
# barrier between input state and gate operation
qc.barrier()
# this is where your program for quantum XOR gate goes
qc.cx(0,1)
# barrier between input state and gate operation
qc.barrier()
qc.measure(1,0) # output from qubit 1 is measured
#We'll run the program on a simulator
backend = AerSimulator()
#Since the output will be deterministic, we can use just a single shot to get it
job = backend.run(qc, shots=1, memory=True)
output = job.result().get_memory()[0]
return qc, output
### END SOLUTIONIn [36]:
XOR('0','0')[1]
Out [36]:
'0'
In [37]:
## Test the function
for inp1 in ['0', '1']:
for inp2 in ['0', '1']:
qc, output = XOR(inp1, inp2)
print('XOR with inputs',inp1,inp2,'gives output',output)
display(qc.draw())
print('\n')
test_xor(XOR) # DO NOT EDIT THIS LINEXOR with inputs 0 0 gives output 0
░ ░
q_0: ─|0>──░───■───░────
░ ┌─┴─┐ ░ ┌─┐
q_1: ─|0>──░─┤ X ├─░─┤M├
░ └───┘ ░ └╥┘
c: 1/═════════════════╩═
0 XOR with inputs 0 1 gives output 1
░ ░
q_0: ─|0>───────░───■───░────
┌───┐ ░ ┌─┴─┐ ░ ┌─┐
q_1: ─|0>─┤ X ├─░─┤ X ├─░─┤M├
└───┘ ░ └───┘ ░ └╥┘
c: 1/══════════════════════╩═
0 XOR with inputs 1 0 gives output 1
┌───┐ ░ ░
q_0: ─|0>─┤ X ├─░───■───░────
└───┘ ░ ┌─┴─┐ ░ ┌─┐
q_1: ─|0>───────░─┤ X ├─░─┤M├
░ └───┘ ░ └╥┘
c: 1/══════════════════════╩═
0 XOR with inputs 1 1 gives output 0
┌───┐ ░ ░
q_0: ─|0>─┤ X ├─░───■───░────
├───┤ ░ ┌─┴─┐ ░ ┌─┐
q_1: ─|0>─┤ X ├─░─┤ X ├─░─┤M├
└───┘ ░ └───┘ ░ └╥┘
c: 1/══════════════════════╩═
0 ✅ All XOR gate tests passed.
In [38]:
### BEGIN SOLUTION
def AND(inp1,inp2):
"""An AND gate.
Parameters:
inpt1 (str): Input 1, encoded in qubit 0.
inpt2 (str): Input 2, encoded in qubit 1.
Returns:
QuantumCircuit: Output XOR circuit.
str: Output value measured from qubit 2.
"""
qc = QuantumCircuit(3, 1)
qc.reset(range(2))
if inp1=='1':
qc.x(0)
if inp2=='1':
qc.x(1)
qc.barrier()
# this is where your program for quantum AND gate goes
qc.ccx(0,1,2)
qc.barrier()
qc.measure(2, 0) # output from qubit 2 is measured
# We'll run the program on a simulator
backend = AerSimulator()
#Since the output will be deterministic, we can use just a single shot to get it
job = backend.run(qc, shots=1, memory=True)
output = job.result().get_memory()[0]
return qc, output
# Test AND gate outputs using assert statements
### END SOLUTIONIn [39]:
AND('0','0')[1]Out [39]:
'0'
In [40]:
## Test the function
for inp1 in ['0', '1']:
for inp2 in ['0', '1']:
qc, output = AND(inp1, inp2)
print('AND with inputs',inp1,inp2,'gives output',output)
display(qc.draw())
print('\n')
test_and(AND) # DO NOT EDIT THIS LINEAND with inputs 0 0 gives output 0
░ ░
q_0: ─|0>──░───■───░────
░ │ ░
q_1: ─|0>──░───■───░────
░ ┌─┴─┐ ░ ┌─┐
q_2: ──────░─┤ X ├─░─┤M├
░ └───┘ ░ └╥┘
c: 1/═════════════════╩═
0 AND with inputs 0 1 gives output 0
░ ░
q_0: ─|0>───────░───■───░────
┌───┐ ░ │ ░
q_1: ─|0>─┤ X ├─░───■───░────
└───┘ ░ ┌─┴─┐ ░ ┌─┐
q_2: ───────────░─┤ X ├─░─┤M├
░ └───┘ ░ └╥┘
c: 1/══════════════════════╩═
0 AND with inputs 1 0 gives output 0
┌───┐ ░ ░
q_0: ─|0>─┤ X ├─░───■───░────
└───┘ ░ │ ░
q_1: ─|0>───────░───■───░────
░ ┌─┴─┐ ░ ┌─┐
q_2: ───────────░─┤ X ├─░─┤M├
░ └───┘ ░ └╥┘
c: 1/══════════════════════╩═
0 AND with inputs 1 1 gives output 1
┌───┐ ░ ░
q_0: ─|0>─┤ X ├─░───■───░────
├───┤ ░ │ ░
q_1: ─|0>─┤ X ├─░───■───░────
└───┘ ░ ┌─┴─┐ ░ ┌─┐
q_2: ───────────░─┤ X ├─░─┤M├
░ └───┘ ░ └╥┘
c: 1/══════════════════════╩═
0 ✅ All AND gate tests passed.
In [41]:
### BEGIN SOLUTION
def NAND(inp1,inp2):
"""An NAND gate.
Parameters:
inpt1 (str): Input 1, encoded in qubit 0.
inpt2 (str): Input 2, encoded in qubit 1.
Returns:
QuantumCircuit: Output NAND circuit.
str: Output value measured from qubit 2.
"""
qc = QuantumCircuit(3, 1)
qc.reset(range(3))
if inp1=='1':
qc.x(0)
if inp2=='1':
qc.x(1)
qc.barrier()
# this is where your program for quantum NAND gate goes
qc.ccx(0, 1, 2)
qc.x(2)
qc.barrier()
qc.measure(2, 0) # output from qubit 2 is measured
# We'll run the program on a simulator
backend = AerSimulator()
#Since the output will be deterministic, we can use just a single shot to get it
job = backend.run(qc, shots=1, memory=True)
output = job.result().get_memory()[0]
return qc, output
# Test NAND gate outputs using assert statements
### END SOLUTIONIn [42]:
NAND('1','0')[1]Out [42]:
'1'
In [43]:
## Test the function
for inp1 in ['0', '1']:
for inp2 in ['0', '1']:
qc, output = NAND(inp1, inp2)
print('NAND with inputs',inp1,inp2,'gives output',output)
display(qc.draw())
print('\n')
test_nand(NAND) # DO NOT EDIT THIS LINENAND with inputs 0 0 gives output 1
░ ░
q_0: ─|0>──░───■────────░────
░ │ ░
q_1: ─|0>──░───■────────░────
░ ┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>──░─┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/══════════════════════╩═
0 NAND with inputs 0 1 gives output 1
░ ░
q_0: ─|0>───────░───■────────░────
┌───┐ ░ │ ░
q_1: ─|0>─┤ X ├─░───■────────░────
└───┘ ░ ┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>───────░─┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/═══════════════════════════╩═
0 NAND with inputs 1 0 gives output 1
┌───┐ ░ ░
q_0: ─|0>─┤ X ├─░───■────────░────
└───┘ ░ │ ░
q_1: ─|0>───────░───■────────░────
░ ┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>───────░─┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/═══════════════════════════╩═
0 NAND with inputs 1 1 gives output 0
┌───┐ ░ ░
q_0: ─|0>─┤ X ├─░───■────────░────
├───┤ ░ │ ░
q_1: ─|0>─┤ X ├─░───■────────░────
└───┘ ░ ┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>───────░─┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/═══════════════════════════╩═
0 ✅ All NAND gate tests passed.
In [44]:
### BEGIN SOLUTION
def OR(inp1,inp2):
"""An OR gate.
Parameters:
inpt1 (str): Input 1, encoded in qubit 0.
inpt2 (str): Input 2, encoded in qubit 1.
Returns:
QuantumCircuit: Output XOR circuit.
str: Output value measured from qubit 2.
"""
qc = QuantumCircuit(3, 1)
qc.reset(range(3))
if inp1=='1':
qc.x(0)
if inp2=='1':
qc.x(1)
qc.barrier()
# this is where your program for quantum OR gate goes
qc.x(0)
qc.x(1)
qc.ccx(0,1,2)
qc.x(2)
qc.barrier()
qc.measure(2, 0) # output from qubit 2 is measured
# We'll run the program on a simulator
backend = AerSimulator()
#Since the output will be deterministic, we can use just a single shot to get it
job = backend.run(qc, shots=1, memory=True)
output = job.result().get_memory()[0]
return qc, output
### END SOLUTIONIn [45]:
OR('1','0')[0].draw()Out [45]:
┌───┐ ░ ┌───┐ ░
q_0: ─|0>─┤ X ├─░─┤ X ├──■────────░────
└───┘ ░ ├───┤ │ ░
q_1: ─|0>───────░─┤ X ├──■────────░────
░ └───┘┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>───────░──────┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/════════════════════════════════╩═
0 In [46]:
## Test the function
for inp1 in ['0', '1']:
for inp2 in ['0', '1']:
qc, output = OR(inp1, inp2)
print('OR with inputs',inp1,inp2,'gives output',output)
display(qc.draw())
print('\n')
test_or(OR) # DO NOT EDIT THIS LINEOR with inputs 0 0 gives output 0
░ ┌───┐ ░
q_0: ─|0>──░─┤ X ├──■────────░────
░ ├───┤ │ ░
q_1: ─|0>──░─┤ X ├──■────────░────
░ └───┘┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>──░──────┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/═══════════════════════════╩═
0 OR with inputs 0 1 gives output 1
░ ┌───┐ ░
q_0: ─|0>───────░─┤ X ├──■────────░────
┌───┐ ░ ├───┤ │ ░
q_1: ─|0>─┤ X ├─░─┤ X ├──■────────░────
└───┘ ░ └───┘┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>───────░──────┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/════════════════════════════════╩═
0 OR with inputs 1 0 gives output 1
┌───┐ ░ ┌───┐ ░
q_0: ─|0>─┤ X ├─░─┤ X ├──■────────░────
└───┘ ░ ├───┤ │ ░
q_1: ─|0>───────░─┤ X ├──■────────░────
░ └───┘┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>───────░──────┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/════════════════════════════════╩═
0 OR with inputs 1 1 gives output 1
┌───┐ ░ ┌───┐ ░
q_0: ─|0>─┤ X ├─░─┤ X ├──■────────░────
├───┤ ░ ├───┤ │ ░
q_1: ─|0>─┤ X ├─░─┤ X ├──■────────░────
└───┘ ░ └───┘┌─┴─┐┌───┐ ░ ┌─┐
q_2: ─|0>───────░──────┤ X ├┤ X ├─░─┤M├
░ └───┘└───┘ ░ └╥┘
c: 1/════════════════════════════════╩═
0 ✅ All OR gate tests passed.
In [47]:
from qiskit_ibm_runtime.fake_provider import FakeYorktownV2
backend = FakeYorktownV2()In [48]:
backend.configuration().coupling_mapOut [48]:
[[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1], [2, 3], [2, 4], [3, 2], [3, 4], [4, 2], [4, 3]]
In [49]:
qc_and = QuantumCircuit(3)
qc_and.ccx(0,1,2)
print('AND gate')
display(qc_and.draw())
print('\n\nTranspiled AND gate for hardware with the required connectiviy')
qc_and.decompose().draw()Out [49]:
AND gate
q_0: ──■──
│
q_1: ──■──
┌─┴─┐
q_2: ┤ X ├
└───┘Transpiled AND gate for hardware with the required connectiviy
┌───┐
q_0: ───────────────────■─────────────────────■────■───┤ T ├───■──
│ ┌───┐ │ ┌─┴─┐┌┴───┴┐┌─┴─┐
q_1: ───────■───────────┼─────────■───┤ T ├───┼──┤ X ├┤ Tdg ├┤ X ├
┌───┐┌─┴─┐┌─────┐┌─┴─┐┌───┐┌─┴─┐┌┴───┴┐┌─┴─┐├───┤└┬───┬┘└───┘
q_2: ┤ H ├┤ X ├┤ Tdg ├┤ X ├┤ T ├┤ X ├┤ Tdg ├┤ X ├┤ T ├─┤ H ├──────
└───┘└───┘└─────┘└───┘└───┘└───┘└─────┘└───┘└───┘ └───┘ In [50]:
# run the cell to define AND gate for real quantum system
def AND(inp1, inp2, backend, layout):
qc = QuantumCircuit(3, 1)
qc.reset(range(3))
if inp1=='1':
qc.x(0)
if inp2=='1':
qc.x(1)
qc.barrier()
qc.ccx(0, 1, 2)
qc.barrier()
qc.measure(2, 0)
qc_trans = transpile(qc, backend, initial_layout=layout, optimization_level=3)
return qc_transIn [63]:
# Assign your choice of the initial_layout to the variable layout1 as a list
# For example
# layout = [0,2,4]
layout = [0,1,2]In [64]:
for input1 in ['0','1']:
for input2 in ['0','1']:
qc_trans1 = AND(input1, input2, backend, layout)
print('For input '+input1+input2)
print('# of nonlocal gates =',qc_trans1.num_nonlocal_gates())
test_compilation(layout) # DO NOT EDIT THIS LINEFor input 00 # of nonlocal gates = 6 For input 01 # of nonlocal gates = 6 For input 10 # of nonlocal gates = 6 For input 11 # of nonlocal gates = 6 For input 00 For input 01 For input 10 For input 11 ✅ Ideal transpilation acheived.
In [117]:
ket_0 = np.array([[1], [0]], dtype=complex)
ket_1 = np.array([[0], [1]], dtype=complex)
### BEGIN SOLUTION
def find_orthogonal_state(ket_zero_bar, theta):
"""
Calculates the orthogonal state |ψ1⟩ for a given |ψ0⟩.
Args:
ket_zero_bar: A NumPy array representing the state |ψ0⟩.
theta: The angle theta in radians.
Returns:
A NumPy array representing the orthogonal state |ψ1⟩.
"""
# --- YOUR CODE HERE ---
# Hint: An orthogonal state can be found by swapping the amplitudes
# of the original state and changing the sign of one of them.
# For |ψ0⟩ = a|0⟩ + b|1⟩, an orthogonal state is |ψ1⟩ = b|0⟩ - a|1⟩.
# Another valid orthogonal state is |ψ1⟩ = -b|0⟩ + a|1⟩.
state = -np.sin(theta)*ket_0 + np.cos(theta)*ket_1
return state # Replace this with your implementation
def find_mutually_unbiased_basis_plus(ket_zero_bar, ket_one_bar):
"""
Calculates the |ψ+⟩ state for the mutually unbiased basis.
Args:
ket_zero_bar: A NumPy array representing the state |ψ0⟩.
ket_one_bar: A NumPy array representing the state |ψ1⟩.
Returns:
A NumPy array representing the |ψ+⟩ state.
"""
# --- YOUR CODE HERE ---
# Hint: The |+⟩ state in the standard basis is (|0⟩ + |1⟩) / sqrt(2).
# In a new basis, it will be a superposition of the new basis vectors.
state = 1/np.sqrt(2)*(ket_zero_bar + ket_one_bar)
return state # Replace this with your implementation
def find_mutually_unbiased_basis_minus(ket_zero_bar, ket_one_bar):
"""
Calculates the |ψ-⟩ state for the mutually unbiased basis.
Args:
ket_zero_bar: A NumPy array representing the state |ψ0⟩.
ket_one_bar: A NumPy array representing the state |ψ1⟩.
Returns:
A NumPy array representing the |ψ-⟩ state.
"""
# --- YOUR CODE HERE ---
# Hint: The |-⟩ state in the standard basis is (|0⟩ - |1⟩) / sqrt(2).
# In a new basis, it will also be a superposition of the new basis vectors.
state = 1/np.sqrt(2)*(ket_zero_bar - ket_one_bar)
return state # Replace this with your implementation
### END SOLTUIONIn [118]:
# Test your solutions
test_alt(find_orthogonal_state,find_mutually_unbiased_basis_plus,find_mutually_unbiased_basis_minus) # DO NOT EDIT THIS LINE✅ Test (a) passed: |ψ0⟩ and |ψ1⟩ are orthogonal. ✅ Test (b) passed: The bases are mutually unbiased. Congratulations! All tests passed!
In [127]:
### BEGIN SOLUTION
# --- Part 1: Define the Matrices ---
# Define the Pauli matrices and the Identity matrix as NumPy arrays.
# Use dtype=complex for matrices with complex entries.
X = np.array([[0,1],[1,0]]) # Replace None with the definition of the X matrix
Y = np.array([[0,-1.j],[1.j,0]]) # Replace None with the definition of the Y matrix
Z = np.array([[1,0],[0,-1]]) # Replace None with the definition of the Z matrix
I = np.array([[1,0],[0,1]]) # Replace None with the definition of the Identity matrix
# This dictionary is used by the test functions.
paulis = {'X': X, 'Y': Y, 'Z': Z}
# --- Part 2: Implement the Test Functions ---
# Complete the following functions to test the properties of the Pauli matrices.
def test_square_to_identity(P):
"""
(a) Check if each Pauli matrix squares to the identity matrix.
Returns:
np.array: matrix of your results
"""
# Hint:
# calculate P @ P
return P@P # Your implementation here
def test_anticommutation(P1, P2):
"""
(b) Check if P1 @ P2 = -P2 @ P1 for any pair of distinct Paulis.
Returns:
[np.array1,np.array2]: list of the left and right side of the equation for one pair
"""
# Hint: You can check the pairs (X, Y), (Y, Z), and (Z, X).
# For each pair (P1, P2), check if P1 @ P2 is close to -(P2 @ P1).
return [P1@P2,-P2@P1] # Your implementation here
def test_product_relation():
"""
(c) Check if the Pauli product relations hold (XY=iZ, YZ=iX, ZX=iY).
Returns:
list[np.array]: The 3 matrices resulting from your calculations in the order above
"""
# Hint: Check each of the three relations separately. For example,
# check if np.allclose(X @ Y, 1j * Z).
# All three must be correct for the function to pass.
return [X@Y, Y@Z, Z@X] # Your implementation here
def get_eigenvalues_and_eigenvectors():
"""
(d) Calculate the eigenvalues and eigenvectors for each Pauli matrix.
Returns:
tuple: A tuple containing two dictionaries:
(eigenvalues_dict, eigenvectors_dict)
- eigenvalues_dict: A dictionary where keys are the names
('X', 'Y', 'Z') and values are the corresponding eigenvalues.
- eigenvectors_dict: A dictionary where keys are the names
and values are the corresponding eigenvectors.
"""
# Hint: Use a loop and np.linalg.eig() for each Pauli matrix. This
# function returns a tuple of (eigenvalues, eigenvectors). Store these
# in the two dictionaries with the correct keys ('X', 'Y', 'Z').
eigenvalues_dict = {}
eigenvectors_dict = {}
for key, value in paulis.items():
eigenvalues, eigenvectors = np.linalg.eig(value)
eigenvalues_dict[key] = eigenvalues
eigenvectors_dict[key] = eigenvectors
return eigenvalues_dict, eigenvectors_dict
### END SOLUTION
In [128]:
# Test your solutions
test_paulis(I,X,Y,Z,test_square_to_identity,test_anticommutation,test_product_relation,get_eigenvalues_and_eigenvectors) # DO NOT EDIT THIS LINE✅ PASS (a): Your function `test_square_to_identity` works correctly. ✅ PASS (b): Your function `test_anticommutation` works correctly. ✅ PASS (c): Your function `test_product_relation` works correctly. ✅ PASS (d): Your function `get_eigenvalues_and_eigenvectors` has the correct return type and keys. ✅ PASS (d): Eigenvalues and eigenvectors are correct for all Pauli matrices. Congratulations! All tests passed!
In [142]:
### BEGIN SOLUTION
# --- Part 1: Define the Matrices ---
# Define the Hadamard and Identity matrices as NumPy arrays.
H = 1/np.sqrt(2)*np.array([[1,1],[1,-1]]) # Replace None with the definition of the Hadamard matrix
# --- Part 2: Implement the Test Functions ---
# Complete the following functions to test the properties of the Hadamard matrix.
def get_hadamard_eigen_system():
"""
(a) Find the eigenvectors and eigenvalues of the Hadamard matrix.
Returns:
tuple: A tuple of (eigenvalues, eigenvectors)
"""
return np.linalg.eig(H)
def test_hadamard_squares_to_identity():
"""
(b) Show that H squares to the identity matrix.
Returns:
np.array: Result of the calculation asked for
"""
return H@H
def test_hadamard_pauli_transformation():
"""
(c) Show that conjugating a Pauli with H results in another Pauli.
Specifically, verify:
1. H X H† =?
2. H Y H† = ?
3. H Z H† =?
Returns:
[str1,str2,str3]: strings must be a X Y Z or I and must be written as
iP, -P, -iP or P, where P is the correct Pauli.
"""
return ['Z', '-Y','X']
### END SOLTUIONIn [143]:
# Test your solutions
test_hadamard(H,get_hadamard_eigen_system,test_hadamard_squares_to_identity,test_hadamard_pauli_transformation) # DO NOT EDIT THIS LINE--- Running Verification --- ✅ PASS (a): Your function `get_hadamard_eigen_system` works correctly. ✅ PASS (b): Your function `test_hadamard_squares_to_identity` works correctly. ✅ PASS (c): Your answers are correct. Congratulations! All tests passed!
In [ ]: