from IPython.display import IFrame
IFrame(src="https://www.youtube.com/embed/yuDxHJOKsVA", width=1920/2, height=1080/2)

from qiskit import *

from qiskit.tools.visualization import plot_histogram
from qiskit.tools.monitor import job_monitor
from qiskit.ignis.mitigation.measurement import complete_meas_cal, CompleteMeasFitter

# let's create a circuit
n_qubits = 3
n_bits = 3
qc = QuantumCircuit(n_qubits, n_bits)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)

qc.measure([0,1,2], [0,1,2])
qc.draw('mpl')

# let's try to find what we have measured by simulating our circuit
simulator = Aer.get_backend('qasm_simulator')
result = execute(qc, backend=simulator, shots=1024).result()
plot_histogram(result.get_counts(qc))

## let's run this circuit on the real ibm quantum computer 
IBMQ.load_account()
provider = IBMQ.get_provider('ibm-q')
qcomp = provider.get_backend('ibmqx2')
job = execute(qc, backend=qcomp, shots=1024)
job_monitor(job)


job_result = qcomp.result()
plot_histogram(qcomp.get_counts(qc))

# lets calibrate the measurement error using ignis
cal_circuits, state_labels = complete_meas_cal(qr=qc.qregs[0], 
                                               circlabel='measurement_calibration')
cal_circuits[7].draw(output='mpl')

cal_job = execute(cal_circuits,
             backend=qcomp,
             shots=8192,
             optimization_level=0)
#print(cal_job.job_id())
job_monitor(cal_job)
cal_results = cal_job.result()

plot_histogram(cal_results.get_counts(cal_circuits[3]))

# Creating the Measurement Fitter Object in Ignis 
meas_fitter = CompleteMeasFitter(cal_results, state_labels)
meas_fitter.plot_calibration()


# Mitigating the measurement errors in our previous device run
meas_filter = meas_fitter.filter
mitigated_result = meas_filter.apply(device_result)

device_counts = device_result.get_counts(qc)
mitigated_counts = mitigated_result.get_counts(qc)
plot_histogram([device_counts, mitigated_counts], 
               legend=['device, noisy', 'device, mitigated'])

# Running error mitigation on a second circuit
circuit2 = QuantumCircuit(3,3)
circuit2.x(1)
circuit2.h(0)
circuit2.cx(0,1)
circuit2.cx(1,2)
circuit2.measure([0,1,2], [0,1,2])
circuit2.draw(output='mpl')

plot_histogram(
    execute(circuit2, backend=simulator, shots=1024).result().get_counts(circuit2)
)

device_counts_2 = execute(circuit2, backend=qcomp, shots=1024).result().get_counts(circuit2)
plot_histogram(device_counts_2)

mitigated_counts_2 = meas_filter.apply(device_counts_2)
plot_histogram([device_counts_2, mitigated_counts_2], legend=['device, noisy','device, mitigated'])