# useful additional packages 
import matplotlib.pyplot as plt
%matplotlib inline

# importing Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit import BasicAer, IBMQ, execute

# import basic plot tools
from qiskit.tools.visualization import plot_histogram

backend = BasicAer.get_backend('qasm_simulator') # run on local simulator by default

# Uncomment the following lines to run on a real device
# IBMQ.load_accounts()
# from qiskit.backends.ibmq import least_busy
# backend = least_busy(IBMQ.backends(operational=True, simulator=False))
# print("the best backend is " + backend.name())

# Creating registers
q2 = QuantumRegister(2)
c1 = ClassicalRegister(1)
c2 = ClassicalRegister(2)

# quantum circuit to make an entangled bell state 
bell = QuantumCircuit(q2)
bell.h(q2[0])
bell.cx(q2[0], q2[1])

# quantum circuit to measure q0 in the standard basis
measureIZ = QuantumCircuit(q2, c1)
measureIZ.measure(q2[0], c1[0])
bellIZ = bell+measureIZ

# quantum circuit to measure q0 in the superposition basis 
measureIX = QuantumCircuit(q2, c1)
measureIX.h(q2[0])
measureIX.measure(q2[0], c1[0])
bellIX = bell+measureIX

# quantum circuit to measure q1 in the standard basis
measureZI = QuantumCircuit(q2, c1)
measureZI.measure(q2[1], c1[0])
bellZI = bell+measureZI

# quantum circuit to measure q1 in the superposition basis 
measureXI = QuantumCircuit(q2, c1)
measureXI.h(q2[1])
measureXI.measure(q2[1], c1[0])
bellXI = bell+measureXI

# quantum circuit to measure q in the standard basis 
measureZZ = QuantumCircuit(q2, c2)
measureZZ.measure(q2[0], c2[0])
measureZZ.measure(q2[1], c2[1])
bellZZ = bell+measureZZ

# quantum circuit to measure q in the superposition basis 
measureXX = QuantumCircuit(q2, c2)
measureXX.h(q2[0])
measureXX.h(q2[1])
measureXX.measure(q2[0], c2[0])
measureXX.measure(q2[1], c2[1])
bellXX = bell+measureXX

bellIZ.draw(output='mpl')

bellIX.draw(output='mpl')

bellZI.draw(output='mpl')

bellXI.draw(output='mpl')

bellZZ.draw(output='mpl')

bellXX.draw(output='mpl')

circuits = [bellIZ,bellIX,bellZI,bellXI,bellZZ,bellXX]
job = execute(circuits, backend)
result = job.result()

plot_histogram(result.get_counts(bellIZ))

result.get_counts(bellIZ)

plot_histogram(result.get_counts(bellIX))

plot_histogram(result.get_counts(bellZI))

plot_histogram(result.get_counts(bellXI))

plot_histogram(result.get_counts(bellZZ))

plot_histogram(result.get_counts(bellXX))

# quantum circuit to make a mixed state 
mixed1 = QuantumCircuit(q2, c2)
mixed2 = QuantumCircuit(q2, c2)
mixed2.x(q2)
mixed1.measure(q2[0], c2[0])
mixed1.measure(q2[1], c2[1])
mixed2.measure(q2[0], c2[0])
mixed2.measure(q2[1], c2[1])

mixed1.draw(output='mpl')

mixed2.draw(output='mpl')

mixed_state = [mixed1,mixed2]
job = execute(mixed_state, backend)
result = job.result()

counts1 = result.get_counts(mixed_state[0])
counts2 = result.get_counts(mixed_state[1])

from collections import Counter
ground = Counter(counts1)
excited = Counter(counts2)
plot_histogram(ground+excited)

