Modeling errors in a simulator

In an ideal quantum computing simulation, an X gate flips the sign of a qubit and a Z gate flips the phase. So, one way to model errors–qubit flips and phase flips—in an ideal quantum computing simulation, which would otherwise not have them, is to have the error modeling process randomly introduce X and/or Z gate(s) to the simulated circuit, that is, to randomly introduce bit flips and/or phase flips. This also is an instructive way to think about error correction: if we could tell just where the bit flip was introduced via an X gate, we could undo the flip by introducing another X gate, because the X gate is its own inverse. Two applications of the X gate would get us back to the original bit. Likewise with the Z gate. To undo a phase-flip introduced via a Z gate, we can simply apply another Z gate.

Qiskit Aer offers the possibility of simulating noise as well. We can choose a real-world IBM QX device, extract its properties, generate a noise model, and then run the simulation. Let's try it out with our repeated identity gate code from earlier. The following code will allow us to run it in the local simulator or on remote hardware, starting from either |"0"> or |"1"> and choosing how many identity gates to apply. If we run it on the local simulator, we can then choose whether that simulator should be noisy or not:

import time
from qiskit import Aer
from qiskit.tools.visualization import plot_histogram, plot_state_city
from qiskit import compile,execute
from qiskit.tools.monitor import job_monitor

def apply_identity_gate(qubit_val,apply_times=10,noisy=True,simulator=True):
shots=1000
qr = qiskit.QuantumRegister(1)
cr = qiskit.ClassicalRegister(1)
qc = qiskit.QuantumCircuit(qr, cr)
if qubit_val not in [0,1]:
raise Exception("initial qubit must be either 0 or 1")
if qubit_val==1:
# Setting q0=|"1">
qc.x(qr[0])
# Applying the identity gate 10 times.
for i in range(apply_times):
qc.iden(qr[0])
# Measuring the result. If our hardware was perfect,
# it should always yield the same value as qubit_val
qc.measure(qr[0],cr[0])

if simulator:
backend = Aer.get_backend('qasm_simulator') # Local simulator
if noisy:
device = IBMQ.get_backend('ibmqx4')
properties = device.properties()
coupling_map = device.configuration().coupling_map
noise_model =
noise.device.basic_device_noise_model(properties)
basis_gates = noise_model.basis_gates
exp_job = execute(qc, backend,
coupling_map=coupling_map,
noise_model=noise_model,
basis_gates=basis_gates)
else:
exp_job = execute(qc,backend,shots=shots)
else:
if noisy:
# Preparing to run
backend = IBMQ.backends(name='ibmqx4')[0] # remote hardware
exp_job = execute(qc,backend,shots=shots)
else:
raise Exception("Hardware is always noisy,
to use hardware keep noise=True")
job_monitor(exp_job)
exp_result = exp_job.result()
final=exp_result.get_counts(qc)
print(final)
plot_histogram(final)