If I use V2 fake backends, I can set a certain noise equal to 0 with
backend.target['measure'][(0,)].error = 0
and I can do that for each kind of instruction ('id', 'rz', 'sx', 'x', 'cx', 'measure') and for each qubit.
If I do that, I still have noisy expectation values. The noise is not due to the fine amount of shots since with ideal quantum circuits with the same amount of shots I get much better results.
Which kind of noise is still acting on the circuit?
EDIT: a reproducible example:
import numpy as np
from qiskit import QuantumCircuit, Aer, transpile
from qiskit_aer import AerSimulator
from qiskit.opflow import CircuitStateFn, Z, I
from sklearn.metrics import mean_absolute_error
from qiskit.providers.fake_provider import FakeAthensV2
op = I^I^I^I^Z
backend = FakeAthensV2()
for k in backend.target.keys():
for i in backend.target[k].keys():
if k != 'reset' and k != 'delay':
backend.target[k][i].error = 0 # Put the noise equal to 0 for each instruction
sim = AerSimulator.from_backend(backend) # Fake backend with 0 noise simulator
sim_ideal = Aer.get_backend('aer_simulator') # Ideal simulator
shot = 10000 # number of shots per circuit
ideal_expval = []
ideal_shots_expval = []
fake_backend_expval = []
for samples in range(10): # I calculate the mean absolute error of the expectation value over 10 circuits
theta = np.random.uniform(0,1)
qc = QuantumCircuit(5)
for j in range(30):
for i in range(5):
qc.rx(theta,i)
for i in range(4):
qc.cx(i,i+1)
qc = transpile(qc, sim, optimization_level=0)
psi = CircuitStateFn(qc)
exact_expval = psi.adjoint().compose(op).compose(psi).eval().real # exact expectation value
ideal_expval.append(exact_expval)
qc.measure_all()
# Fake Backend
result = sim.run(qc, shots=shot).result()
key = [list(i) for i in (list(result.get_counts().keys()))] # output bit strings
key = np.array(key)
val = np.array(list(result.get_counts().values())) # output bit strings probabilities
indices_plus = np.where(key[:, -1] == '0')
indices_minus = np.where(key[:, -1] != '0')
expval_fake = np.sum(val[indices_plus]) - np.sum(val[indices_minus])
fake_backend_expval.append(expval_fake/shot)
# Ideal Backend with shots
result = sim_ideal.run(qc, shots=shot).result()
key = [list(i) for i in (list(result.get_counts().keys()))] # output bit strings
key = np.array(key)
val = np.array(list(result.get_counts().values())) # output bit strings probabilities
indices_plus = np.where(key[:, -1] == '0')
indices_minus = np.where(key[:, -1] != '0')
expval_ideal_shots = np.sum(val[indices_plus]) - np.sum(val[indices_minus])
ideal_shots_expval.append(expval_ideal_shots/shot)
print('MAE between exact expectation values and expectation value calculated with ideal backend with 10000 shots:',mean_absolute_error(ideal_expval, ideal_shots_expval))
print('MAE between exact expectation values and expectation value calculated with fake backend with 0 noise:',mean_absolute_error(ideal_expval, fake_backend_expval))
The output is:
MAE between exact expectation values and expectation value calculated with ideal backend with 10000 shots: 0.006748880604561936
MAE between exact expectation values and expectation value calculated with fake backend with 0 noise: 0.06720803337803631