Skip to content

Instantly share code, notes, and snippets.

@datafatmunger
Created July 4, 2020 13:25
Show Gist options
  • Save datafatmunger/9f881d362a92b533af8400f6f85f8ffc to your computer and use it in GitHub Desktop.
Save datafatmunger/9f881d362a92b533af8400f6f85f8ffc to your computer and use it in GitHub Desktop.
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