mirror of
https://github.com/quantumjim/Quantum-Computation-course-Basel.git
synced 2026-11-15 18:26:27 +01:00
17 KiB
17 KiB
In [2]:
from qiskit import QuantumCircuit, transpile
from qiskit_aer import AerSimulator
from qiskit.visualization import plot_histogram
import numpy as npIn [3]:
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 [ ]:
for inp in ['0', '1']:
qc, out = NOT(inp)
print('NOT with input',inp,'gives output',out)
display(qc.draw())
print('\n')In [5]:
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
# 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, outputIn [ ]:
## 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')In [7]:
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.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, outputIn [ ]:
## 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')In [9]:
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.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, outputIn [ ]:
## 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')In [11]:
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.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, outputIn [ ]:
## 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')In [ ]:
from qiskit_ibm_runtime.fake_provider import FakeYorktown
backend = FakeYorktown()In [ ]:
backend.configuration().coupling_mapIn [ ]:
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()In [16]:
# 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 [17]:
# Assign your choice of the initial_layout to the variable layout1 as a list
# For example
# layout = [0,2,4]
layout = In [ ]:
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())