# How to selectively apply noise in Qiskit simulations?

In Qiskit it is possible to specify noise models to apply to simulations. This allows noise to be defined for certain operations, like measurement or each type of gate.

Is it also possible to change the noise for different parts of the circuit. Such as turning noise on only for specific parts of the circuit?

Yes you can: When you build a noise model the noise is defined with respect to the name or label of gate objects, so you can use the labelto create multiple versions of a single gate but reference different errors in a noise model (NB: the transpiler strips away label information when it unrolls a gate not in the basis gates set).

### Selective noise on standard gates

For example: Suppose I wanted to create two version of a XGate gate.

from qiskit import *
from qiskit.extensions import XGate
from qiskit.providers.aer.noise import NoiseModel, errors

x_gate = XGate()  # regular X gate
x1_gate = XGate(label="x1")  # first labelled X gate
x2_gate = XGate(label="x2")  # second labelled X gate

x1_error = errors.depolarizing_error(0.1, 1)
x2_error = errors.depolarizing_error(0.01, 1)

noise_model = NoiseModel()
print(noise_model)



This makes the noise model:

NoiseModel:
Basis gates: ['cx', 'id', 'u3', 'x']
Instructions with noise: ['x2', 'x1']
All-qubits errors: ['x1', 'x2']


Notice the line noise_model.add_basis_gates(['x']), since we added a label that isn't recognised as a standard basis gate, we have to tell the noise model that x should be in our basis gates (Aside: I hope to streamline this a bit in future versions)

Now to use this in a circuit I could have:

qc = QuantumCircuit(3, 3)
qc.append(x_gate, [0])  # regular noise-free x gate
qc.append(x1_gate, [1])  # noisy x1 gate
qc.append(x2_gate, [2])  # noisy x2 gate
qc.measure([0, 1, 2], [0, 1, 2])

result = execute(qc, Aer.get_backend('qasm_simulator'),
basis_gates=basis_gates,
noise_model=noise_model).result()
result.get_counts(0)

# Returns something like:

{'101': 40, '111': 980, '011': 4}


So we can see that we have different noise for all 3 X gates.

### Selective noise on arbitrary unitary gates

You can use this to build noisy or ideal versions of any standard gate, and for custom gates using the unitary gate object. Below I will do same example but with the X gates applied as a unitary matrix using the same labels for the noise model. Note that I need to add 'unitary' to the noise model basis gates so that the unitaries aren't converted into u3 gates:

from qiskit.extensions import UnitaryGate

x_mat = XGate().to_matrix()

qc = QuantumCircuit(3, 3)
qc.unitary(x_mat, [0], label='x')
qc.unitary(x_mat, [1], label='x1')
qc.unitary(x_mat, [2], label='x2')
qc.measure([0, 1, 2], [0, 1, 2])

# We need to add unitary to noise model basis gates
basis_gates = noise_model.basis_gates

result = execute(qc, Aer.get_backend('qasm_simulator'),
basis_gates=basis_gates,
noise_model=noise_model).result()
result.get_counts(0)

# Returns something like

{'101': 37, '111': 983, '011': 4}


### Selective noise on reset and measurement

You can also make ideal / noisy measurements or resets using the above trick with a custom gate before measurement or after reset. Eg:

# Make a noisy measure instruction
from qiskit.extensions import IdGate
tmp = QuantumCircuit(1, 1)
tmp.append(IdGate(label='noise_meas'), [0])
tmp.measure(0, 0)
noise_meas = tmp.to_instruction()  # convert tmp circuit to instruction

# Create a noise model
noise_model = NoiseModel()
meas_error = errors.depolarizing_error(0.1, 1)
basis_gates = noise_model.basis_gates

# Example circuit
circuit = QuantumCircuit(2, 2)
circuit.measure([0], [0])
circuit.append(noise_meas, [1], [1])

result = execute(circuit, Aer.get_backend("qasm_simulator"),
basis_gates=basis_gates,
noise_model=noise_model).result()
result.get_counts(0)

# Returns something like
{'10': 55, '00': 969}


### Selective noise with basic_device_noise_model

Finally a comment on using this with basic device noise model. This is a little tricky but can be done. The problem is that if you are not building a noise model from scratch (and so choosing your own labels) the standard unlabelled gates u1,u2,u3,cx will be the noisy gates, and you can add custom labels for the ideal u1, u2, u3, cx gates.

The transpiler will always convert gates to the noisy u3 etc (eg x->u3) So if you want ideal x you must insert as u3 gate, because all labels of x gates will get unrolled to the noisy u3.