I was running the IBM qiskit sample code and noticed that the results vary on different backends. I thought it was quantum noise, so I repeated the same calculation on many different backends and got this figure:
The results are very consistent within the same backend but vary quite a bit between backends, particularly on fake_manila, fake_kyoto, and ibm_kyoto. So, the cause does not seem to be quantum noise.
BTW, The theoretical result (from matrix multiplication) is shown on the right most point as $\langle v|H|v\rangle$.
Did I do something wrong?
Here is my code:
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Session, EstimatorV2 as Estimator
from qiskit_ibm_runtime.fake_provider import (FakeAlgiers, FakeAthensV2, FakeBelemV2, FakeManilaV2,
FakeAuckland, FakeBrisbane, FakeOsaka, FakeKyoto)
from qiskit.quantum_info import Statevector
import numpy as np
psi = RealAmplitudes(num_qubits=2, reps=2)
theta = [0, 1, 1, 2, 3, 5]
hamiltonian = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
service = QiskitRuntimeService()
fake_backends = [FakeAlgiers(), FakeAthensV2(), FakeBelemV2(), FakeManilaV2(), FakeAuckland(),
FakeBrisbane(), FakeOsaka(), FakeKyoto()]
real_backends = service.backends(simulator=False, operational=True)
all_backends = real_backends
results = {} # keep track all the results
repeats = 10
for backend in fake_backends:
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_psi = pm.run(psi)
isa_observables = hamiltonian.apply_layout(isa_psi.layout)
estimator = Estimator(backend=backend)
values = results.get(backend.name, [])
for r in range(repeats):
job = estimator.run([(isa_psi, isa_observables, [theta])])
pub_result = job.result()[0]
print(f"Expected values from {backend.name}: {pub_result.data.evs}")
values.append(pub_result.data.evs)
results[backend.name] = values
repeats = 3
for backend in real_backends:
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_psi = pm.run(psi)
isa_observables = hamiltonian.apply_layout(isa_psi.layout)
with Session(service=service, backend=backend):
estimator = Estimator(backend=backend)
values = results.get(backend.name, [])
for r in range(repeats):
job = estimator.run([(isa_psi, isa_observables, [theta])])
pub_result = job.result()[0]
print(f"Expected values from {backend.name}: {pub_result.data.evs}")
values.append(pub_result.data.evs)
results[backend.name] = values
compute <psi|H|psi> using matrices
statevector = Statevector(psi.assign_parameters(theta))
v = np.matrix(statevector.data).transpose()
h = hamiltonian.to_matrix()
results['<v|H|v>'] = v.getH() @ h @ v
print(f"<v|H|v> = {v.getH() @ h @ v}")
