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
{'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 0x7fa47bb81b50>},
'dd': {'enabled': True,
'gate_sequences': [(9, 'XYXYYXYX', 'asap'),
(5, 'YXYX', 'asap'),
(2, 'XX', 'center')]},
'pauli_twirl': {'enabled': False, 'num_twirls': 0, 'gates_to_twirl': None}}
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.8712768367247805,
0.8712768367247805,
0.8712768367247805,
0.8712768367247805,
0.8712768367247805]]
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},
'dd': {'enabled': False, 'gate_sequences': []},
'pauli_twirl': {'enabled': False, 'num_twirls': 0, 'gates_to_twirl': 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.75537109375, 0.75537109375, 0.75537109375, 0.75537109375, 0.75537109375]]