Created
July 4, 2020 13:25
-
-
Save datafatmunger/9f881d362a92b533af8400f6f85f8ffc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, execute, Aer, IBMQ, Aer | |
def apply_secret_unitary(secret_unitary, qubit, quantum_circuit, dagger): | |
functionmap = { | |
'x': quantum_circuit.x, | |
'y': quantum_circuit.y, | |
'z': quantum_circuit.z, | |
'h': quantum_circuit.h, | |
't': quantum_circuit.t | |
} | |
if dagger == 1: | |
functionmap['t'] = quantum_circuit.tdg | |
if dagger: | |
[functionmap[unitary](qubit) for unitary in secret_unitary] | |
else: | |
[functionmap[unitary](qubit) for unitary in secret_unitary[::-1]] | |
secret_unitary = 'hzxhzhx' | |
def create_bell_pair(qc, a, b): | |
"""Creates a bell pair in qc using qubits a & b""" | |
qc.h(a) # Put qubit a into state |+> | |
qc.cx(a,b) # CNOT with a as control and b as target | |
def alice_gates(qc, psi, a): | |
qc.cx(psi, a) | |
qc.h(psi) | |
def measure_and_send(qc, a, b): | |
"""Measures qubits a & b and 'sends' the results to Bob""" | |
qc.barrier() | |
qc.measure(a, 0) | |
qc.measure(b, 1) | |
# This function takes a QuantumCircuit (qc), integer (qubit) | |
# and ClassicalRegisters (crz & crx) to decide which gates to apply | |
def bob_gates(qc, qubit, crz, crx): | |
# Here we use c_if to control our gates with a classical | |
# bit instead of a qubit | |
qc.x(qubit).c_if(crx, 1) # Apply gates if the registers | |
qc.z(qubit).c_if(crz, 1) # are in the state '1' | |
## SETUP | |
# Protocol uses 4 qubits and 2 classical bits in 2 different registers | |
qr = QuantumRegister(4) | |
crz, crx = ClassicalRegister(1), ClassicalRegister(1) | |
teleportation_circuit = QuantumCircuit(qr, crz, crx) | |
# Encrypt Alice's bit - JBG | |
apply_secret_unitary(secret_unitary, teleportation_circuit.qubits[0], teleportation_circuit, dagger = 0) | |
teleportation_circuit.barrier() | |
## STEP 1 | |
# In our case, Eve entangles qubits q1 and q2 | |
# Let's apply this to our circuit: | |
create_bell_pair(teleportation_circuit, 1, 2) | |
teleportation_circuit.barrier() # Use barrier to separate steps | |
## STEP 2 | |
alice_gates(teleportation_circuit, 0, 1) | |
## STEP 3 | |
measure_and_send(teleportation_circuit, 0 ,1) | |
teleportation_circuit.barrier() # Use barrier to separate steps | |
## STEP 4 | |
# Bob puts the qubit in the correct state - JBG | |
bob_gates(teleportation_circuit, 2, crz, crx) | |
create_bell_pair(teleportation_circuit, 2, 3) | |
## STEP 5 | |
# Perform some opperation on bob's qubit, in this case flip the bit back - JBG | |
# Naming here is a bit confusing - JBG | |
alice_gates(teleportation_circuit, 2, 3) | |
## STEP 6 | |
# Send it back to Alice - JBG | |
measure_and_send(teleportation_circuit, 2 ,3) | |
teleportation_circuit.barrier() # Use barrier to separate steps | |
## STEP 7 | |
# Alice put qubit 0 into Bob's state - JBG | |
# Can I just reuse qubit 0 here? ... looks like it. - JBG | |
bob_gates(teleportation_circuit, 0, crz, crx) | |
## STEP 8 | |
# Alice can decrypt now - JBG | |
apply_secret_unitary(secret_unitary, teleportation_circuit.qubits[0], teleportation_circuit, dagger=1) | |
teleportation_circuit.barrier() | |
## STEP 9 | |
# Did it work? - JBG | |
teleportation_circuit.measure(0, 0) | |
counts = execute(teleportation_circuit, Aer.get_backend('qasm_simulator')).result().get_counts() | |
print(counts) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment