Example: Zero Noise Extrapolation#
For folding methods, extrapolation options, and parameter details, see the ZNE guide.
Import everything needed#
from fiqci.ems import FiQCIEstimator
from iqm.qiskit_iqm import IQMProvider
from qiskit import QuantumCircuit, transpile
from qiskit.quantum_info import SparsePauliOp
Setup Estimator#
url = None
quantum_computer = None
# Connect to an IQM quantum computer using the provider
if url is not None and quantum_computer is not None:
provider = IQMProvider(url=url, quantum_computer=quantum_computer)
backend = provider.get_backend()
else:
# Or using a noisy simulator
from iqm.qiskit_iqm import IQMFakeAdonis
backend = IQMFakeAdonis()
# Initialise FiQCI estimator with mitigation level 3 (readout error mitigation + zero-noise extrapolation)
estimator = FiQCIEstimator(backend=backend, mitigation_level=3)
# We can view the default settings enabled for mitigation level 3
estimator.mitigator_options
/home/runner/work/fiqci-ems/fiqci-ems/src/fiqci/ems/fiqci_backend.py:89: UserWarning: Mitigation level 2 (M3 + Dynamical Decoupling) not implemented yet. Level 2 will currently only apply M3 readout error mitigation without dynamical decoupling.
warnings.warn(
{'zne': {'enabled': True,
'fold_gates': None,
'scale_factors': [1, 3, 5],
'folding_method': 'local',
'extrapolation_method': 'exponential',
'extrapolation_degree': None},
'rem': {'enabled': True,
'calibration_shots': 1000,
'calibration_file': None,
'mitigator': <fiqci.ems.mitigators.rem.M3IQM at 0x7f4081b7bf50>}}
Example circuit with ZNE + REM#
# Define a simple 5-qubit circuit
qc = QuantumCircuit(5)
qc.rx(0.5, 0)
qc.cx(0, 1)
qc.cx(0, 2)
qc.cx(0, 3)
qc.cx(0, 4)
qc.cx(1, 2)
qc.cx(1, 3)
# Transpile for backend
qc_transpiled = transpile(qc, backend=backend)
qc_transpiled.draw("mpl")
# Define observables to calculate expectation values for (here Z on each qubit)
observables = SparsePauliOp.from_list([("ZIIII", 1), ("IZIII", 1), ("IIZII", 1), ("IIIZI", 1), ("IIIIZ", 1)])
# Map observables to the layout of the transpiled circuit
observables_device = observables.apply_layout(qc_transpiled.layout)
# Execute on FiQCI Estimator with specified observables and shots
job = estimator.run([qc_transpiled], observables=observables_device, shots=2**10)
# Retrieve mitigated expectation values
job.expectation_values()
[[0.9728054013268412,
0.9728054013268412,
0.9728054013268412,
0.9728054013268412,
0.9728054013268412]]
Manual Configuration#
# Initialise FiQCI estimator
estimator = FiQCIEstimator(backend=backend, mitigation_level=0)
# Configure ZNE
estimator.zne(enabled=True, scale_factors=[1, 5], extrapolation_method="richardson", folding_method="global")
# Print ZNE settings
estimator.mitigator_options
{'zne': {'enabled': True,
'fold_gates': None,
'scale_factors': [1, 5],
'folding_method': 'local',
'extrapolation_method': 'richardson',
'extrapolation_degree': None},
'rem': {'enabled': False,
'calibration_shots': 1000,
'calibration_file': None,
'mitigator': None}}
# Execute the same circuit as above with only ZNE enabled (no readout error mitigation)
job = estimator.run([qc_transpiled], observables=observables_device, shots=2**10)
job.expectation_values()
[[0.7890625, 0.7890625, 0.7890625, 0.7890625, 0.7890625]]