from qiskit import *
from qiskit.tools.jupyter import *
from qiskit.visualization import *
import matplotlib.pyplot as plotter
import numpy as np
from IPython.display import display, Math, Latex
%matplotlib inline
# Loading your IBM Q account(s)
provider = IBMQ.load_account()

qr = QuantumRegister(3)
crz = ClassicalRegister(1)
crx = ClassicalRegister(2)  # we will need seperates registers for using 'c_if' later.
qc = QuantumCircuit(qr,crz,crx)
qc.x(0)
qc.h(0) # 'psi' can't be unknown to us as we are creating it here. Let us take '-' state as our 'psi'
# We will verify later if the '-' is been teleported.

qc.h(1)
qc.cx(1,2) # creating a bell state
qc.barrier() # Use barrier to separate steps, everything till this barrier is just intialisation.

qc.cx(0,1) # '0' and '1' are with Alice and '2' is with Bob.
# psi_1 prepared.

qc.h(0)
# psi_2 prepared.
qc.barrier()

qc.measure(0,0)
qc.measure(1,1)
qc.draw (output = 'mpl')

qc.x(2).c_if(crx,1)  # 'c_if' compares a classical register with a value (either 0 or 1) and performs the 
qc.z(2).c_if(crz,1)  # operation if they are equal.

qc.draw('mpl')
# be careful of the order of applying X and Z!

qc.h(2)
qc.measure(2,crx[1])

def run_circuit(qc):
    backend = Aer.get_backend('qasm_simulator') # we choose the simulator as our backend
    result = execute(qc, backend, shots = 10000).result() # we run the simulation
    counts = result.get_counts() # we get the counts
    return counts

counts = run_circuit(qc)
print(counts)
plot_histogram(counts)
# the output should be '1xx' if the teleportation is successful.

# Refer to above cell for a detailed explanation of the strategy.

qc1 = QuantumCircuit(2, 2)

# Preparing Alice's Bell state: \beta_{00}
qc1.h(0)
qc1.cx(0, 1)

# Skyler's mischief:
# Suppose for this example that she applied Pauli-Y.
# You can change 'y' to 'x' or 'z' in the following line for other cases.
qc1.y(0)

# Alice's strategy:
qc1.cx(0, 1)
qc1.h(0)
qc1.measure(0, 0)
qc1.measure(1, 1)

qc1.draw('mpl')

def run_circuit(qc):
    backend = Aer.get_backend('qasm_simulator') # we choose the simulator as our backend
    result = execute(qc, backend, shots = 10000).result() # we run the simulation
    counts = result.get_counts() # we get the counts
    return counts

counts = run_circuit(qc1)
print(counts)
if '10' in counts:
    print('Skyler used Pauli-X!')
if '11' in counts:
    print('Skyler used Pauli-Y!')
if '01' in counts:
    print('Skyler used Pauli-Z!')
plot_histogram(counts)