from qiskit import QuantumCircuit, execute, IBMQ, Aer
from qiskit.visualization import plot_histogram
from qiskit.providers.aer.noise import NoiseModel

# contruir modelo de ruido a partir das propriedades do chip
nshots = 8192
provider = IBMQ.load_account()
device = provider.get_backend('ibmq_bogota')
simulator = Aer.get_backend('qasm_simulator')
noise_model = NoiseModel.from_backend(device) # essa funcao constroi o modelo de ruido

print(noise_model)

# obter mapa de acoplamento do chip
coupling_map = device.configuration().coupling_map
print(coupling_map)

# obter base de portas logicas a partir do modelo de ruido
basis_gates = noise_model.basis_gates
print(basis_gates)

# construir o circuit
qc = QuantumCircuit(3, 3)
qc.h(0); qc.cx(0, 1); qc.cx(0, 2); qc.measure([0, 1, 2], [0, 1, 2])
qc.draw(output = 'mpl')

jobS = execute(qc, backend = simulator, shots = nshots)
plot_histogram(jobS.result().get_counts())

# faz a simulacao com o ruido ja incluido
jobNS = execute(qc, backend = simulator, coupling_map = coupling_map, basis_gates = basis_gates, 
              noise_model = noise_model, shots = nshots)
plot_histogram(jobNS.result().get_counts())

from qiskit.tools.monitor import job_monitor
jobE = execute(qc, backend = device, shots = nshots)
job_monitor(jobE)
plot_histogram(jobE.result().get_counts())

plot_histogram([jobS.result().get_counts(0), jobNS.result().get_counts(0), jobE.result().get_counts(0)], 
               bar_labels = False, legend = ['sim', 'noise_sim', 'exp'])

