Note
This page was generated from docs/tutorials/Error-Suppression-and-Error-Mitigation.ipynb.
Error suppression and error mitigation with Qiskit Runtime¶
To illustrate the need for error suppression and mitigation, we will start by taking a look at some results without error suppression or error mitigation. After setting up our environment, we will use a noiseless simulator to get an idea of what ideal results look like. Next, we are going to run the same experiment in a real backend without using error suppression or error mitigation.
[ ]:
import datetime
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.rcParams.update({"text.usetex": True})
plt.rcParams["figure.figsize"] = (6, 4)
mpl.rcParams["figure.dpi"] = 200
from qiskit_ibm_runtime import Estimator, Session, QiskitRuntimeService, Options
from qiskit.quantum_info import SparsePauliOp
from qiskit import QuantumCircuit
service = QiskitRuntimeService()
Create a Trotter circuit¶
The following code cell defines a list of Trotter circuits for use in the experiments.
[2]:
backend_simulator = "ibmq_qasm_simulator"
backend = "ibmq_montreal"
qubits = 4
trotter_layer = QuantumCircuit(qubits)
trotter_layer.rx(0.1, range(qubits))
trotter_layer.cx(0, 1)
trotter_layer.cx(2, 3)
trotter_layer.rz(-0.2, [1, 3])
trotter_layer.cx(0, 1)
trotter_layer.cx(2, 3)
trotter_layer.cx(1, 2)
trotter_layer.rz(-0.2, 2)
trotter_layer.cx(1, 2)
num_steps = 6
trotter_circuit_list = []
for i in range(1, num_steps):
trotter_circuit = QuantumCircuit(qubits)
for _ in range(i):
trotter_circuit = trotter_circuit.compose(trotter_layer)
trotter_circuit_list.append(trotter_circuit)
print(f"Trotter circuit with {i} Trotter steps")
display(trotter_circuit.draw(fold=-1))
obs = SparsePauliOp("Z" * qubits)
obs_list = [obs] * len(trotter_circuit_list)
Trotter circuit with 1 Trotter steps
┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘
Trotter circuit with 2 Trotter steps
┌─────────┐ ┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘
Trotter circuit with 3 Trotter steps
┌─────────┐ ┌─────────┐ ┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘
Trotter circuit with 4 Trotter steps
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘
Trotter circuit with 5 Trotter steps
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ q_0: ┤ Rx(0.1) ├──■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──┤ Rx(0.1) ├──────────────────────────────■────────────────■──────────────────────── ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐└─────────┘ ┌─────────┐┌─┴─┐┌──────────┐┌─┴─┐ q_1: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├─────■───────────────────■──┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├──■────────────────■── ├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘ ┌─┴─┐ ┌──────────┐┌─┴─┐├─────────┤└───┘└──────────┘└───┘┌─┴─┐┌──────────┐┌─┴─┐ q_2: ┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■─────┤ X ├───┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├──■────────────────■──┤ X ├┤ Rz(-0.2) ├┤ X ├ ├─────────┤┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐┌──┴───┴──┐└──────────┘└───┘└─────────┘┌─┴─┐┌──────────┐┌─┴─┐└───┘└──────────┘└───┘ q_3: ┤ Rx(0.1) ├┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├┤ Rx(0.1) ├────────────────────────────┤ X ├┤ Rz(-0.2) ├┤ X ├────────────────────── └─────────┘└───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘└─────────┘ └───┘└──────────┘└───┘
Simulator run¶
[4]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 0 # No optimization
options.resilience_level = 0 # No mitigation
with Session(service=service, backend=backend_simulator) as session:
estimator_sim = Estimator(session=session, options=options)
job_sim = estimator_sim.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_sim.job_id)
print(job_sim.result())
expvals_ideal = job_sim.result().values
expvals_ideal_variance = [
metadata["variance"] / metadata["shots"] for metadata in job_sim.result().metadata
]
std_error_ideal = np.sqrt(expvals_ideal_variance)
job id: cdkrpbpg1234sbmtrt3g
EstimatorResult(values=array([0.98 , 0.926, 0.872, 0.796, 0.68 ]), metadata=[{'variance': 0.03960000000000008, 'shots': 1000}, {'variance': 0.14252399999999987, 'shots': 1000}, {'variance': 0.23961600000000005, 'shots': 1000}, {'variance': 0.36638399999999993, 'shots': 1000}, {'variance': 0.5375999999999999, 'shots': 1000}])
Unmitigated, real backend¶
[5]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 0 # No optimization
options.resilience_level = 0 # No error mitigation
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
job = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job.job_id)
print(job.result())
expvals_unmit = job.result().values
expvals_unmit_variance = [
metadata["variance"] / metadata["shots"] for metadata in job.result().metadata
]
std_error_unmit = np.sqrt(expvals_unmit_variance)
job id: cdkrpeaan60ka16e8340
EstimatorResult(values=array([0.786, 0.74 , 0.636, 0.562, 0.446]), metadata=[{'variance': 0.382204, 'shots': 1000}, {'variance': 0.4524, 'shots': 1000}, {'variance': 0.595504, 'shots': 1000}, {'variance': 0.684156, 'shots': 1000}, {'variance': 0.801084, 'shots': 1000}])
Theory and background¶
IBM Quantum¶
We want to build a tool which, beginning in 2024, is capable of estimating noise-free observables of 100-qubit circuits, with depth 100, within one day.
Although this is not a promise for quantum advantage per-se, the goal is to get to the point where we can solve interesting or relevant problems faster, more accurately, or more cheaply in a practical time frame as compared to efficient classical computations.
The threshold for simulability seems to be at around 100 qubits. However, this is not enough qubits, as we also need a sufficiently complex quantum circuit to ensure that it cannot be reproduced classically. For example, deep, non-clifford.
With errors per gate of order 1E-3
, we estimate a final fidelity of such a computation of about 1E-6
, which implies totally meaningless results.
Fault tolerant quantum computing¶
Errors are a natural occurrence in any computer. In quantum computers, these errors are usually more complex and happen when the quantum states are not prepared exactly how they should. For example, overshooting their target values or drifting away. Furthermore, the disturbances that generate these issues are typically unavoidable.
There are several ways to handle these errors. The terminology can get confusing, as there is disagreement even within the field. We will break it into three core pieces:
Suppression
Mitigation
Correction
Let’s start with the error correction, since it was the first one to be formally discovered within the field.
Error correction¶
Error correction in classical computers is the standard procedure of encoding information in redundant ways to make it resilient to unwanted noise —allowing us to detect and correct errors as they occur.
It has being known for a long time that the coupling of quantum systems to their environment sets a limit for any quantum computation, both in time and size. Nonetheless, theoretical discoveries in the form of Quantum error correction solved this issue early on.
THRESHOLD THEOREM
If errors in quantum computers can be reduced below certain (finite) level, a fault-tolerant quantum computation could be carried out arbitrarily long even in noisy hardware.
Reference: M.A. Nielsen, and I.L. Chuang, Quantum Computation and Quantum Information.
This is how we hope to achieve the ultimate goal of fault-tolerant quantum computation. However, even if we build hardware that can achieve the prescribed threshold, the overhead for performing full error correction, such as the necessary qubit count, makes it infeasible in the short term; as we will try to encode single qubit logical values across multiple physical qubits:
\[n/d = 100/100 \quad\]
|
\[p = \text{1E-3} \quad\]
|
\[p = \text{1E-4} \quad\]
|
\[p = \text{1E-5} \quad\]
|
---|---|---|---|
Runtime [\(s\)] |
2.3 |
1.2 |
0.8 |
Physical qubits |
140k |
40k |
16k |
Distance |
21 |
11 |
7 |
These surface code resources* are well beyond our 2025 roadmap plans, although we are working hard in this area to make it feasible as soon as possible.
* The data in the previous table is based on simulations for surface codes with certain conditions. The code distance was chosen so that none of the T-gates, or 100 logical qubits at the end of runtime, had error greater than \(1\text{E}-2\). The number of T-gates is \(n \times d\) and each parity check cycle takes \(1 \mu s\).
Reference: Daniel Litinski, A Game of Surface Codes: Large-Scale Quantum Computing with Lattice Surgery, arXiv:1808.02892
Error suppression¶
Error suppression is the most basic level of error handling. It often refers to a set of techniques performed close to hardware, such as altering control signals (that is, at Qiskit Pulse level). To make it simpler, we define these techniques as introducing classical overhead, usually within the transpilation/compilation process.
These techniques are very old and were first developed outside of the field at the same time as some of the first controllable quantum systems such as magnetic resonance imaging devices.
Dynamical decoupling (DD)¶
Quantum computers have adopted some of these techniques like spin echos (a sequence of pulses that can help refocus the state of a qubit). As a matter of fact, spin echos play a big role in a class of techniques known as Dynamical Decoupling (DD), which sends pulses to idle qubits to reset their value to their original states, undoing the potentially harmful effects of nearby qubits that are being used for the calculation.
Reference: Lorenza Viola, and Seth Lloyd , Dynamical suppression of decoherence in two-state quantum systems, arXiv:quant-ph/9803057
[6]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 3 # Dynamical decoupling
options.resilience_level = 0 # No error mitigation
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
job_dd = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_dd.job_id)
print(job_dd.result())
expvals_unmit_dd = job_dd.result().values
expvals_unmit_dd_variance = [
metadata["variance"] / metadata["shots"] for metadata in job_dd.result().metadata
]
std_error_dd = np.sqrt(expvals_unmit_dd_variance)
job id: cdkrpk5f14jb6brgbmt0
EstimatorResult(values=array([0.87 , 0.752, 0.598, 0.484, 0.396]), metadata=[{'variance': 0.24309999999999998, 'shots': 1000}, {'variance': 0.434496, 'shots': 1000}, {'variance': 0.642396, 'shots': 1000}, {'variance': 0.765744, 'shots': 1000}, {'variance': 0.8431839999999999, 'shots': 1000}])
[7]:
plt.title("Trotter circuits expectation value")
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_dd,
std_error_dd,
fmt="o",
linestyle="-",
capsize=4,
c="blue",
label="Dynamical decoupling",
)
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xlabel("No. Trotter Steps")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Error mitigation¶
Error mitigation introduces quantum overhead to our calculations.
Typically, error correction uses the outputs of multiple ensembles of noisy calculations to reduce or eliminate the noise in estimating quantities like expectation values — commonly by using classical post-processing. In this regard, error mitigation is different from error correction. Rather than fixing errors in every circuit run, errors are allowed to occur, then better results are inferred from several of these noisy calculations.
Since there is no threshold that one must surpass before quantum error mitigation becomes practical, we see error mitigation as the key to realizing useful quantum computers in the near term.
We are developing a portfolio of different error mitigation techniques, looking for three main things:
Small overhead (speed)
Improved accuracy (quality)
Few assumptions (scale)
Each method come with their own associated overhead: a trade-off between the number of quantum computations needed (time) and the accuracy of our results. The level of accuracy that can be achieved is also specific to each method, and is usually inversely proportional to the previously mentioned overhead. Defining \(\lambda\) as the base noise in our computation:
Methods |
T-REx |
ZNE |
PEC |
---|---|---|---|
Assumptions |
None |
Ability to scale the noise |
Full knowledge of the noise |
Qubit overhead |
\(1\) |
\(1\) |
\(1\) |
Sampling overhead |
\(2\) |
\(N_\text{noise-factors}\) |
\(\mathcal{O}(e^{\lambda N_\text{layers}})\) |
Bias |
\(0\) |
\(\mathcal{O}(\lambda^{N_\text{noise-factors}})\) |
\(0\) |
More detailed information is available at:
T-REx: arXiv:2012.09738
ZNE: arXiv:1612.02058
PEC: arXiv:1612.02058
By having a portfolio of methods, users can choose which technique makes the most sense for their problem of interest, based on accuracy demands and how much overhead they are willing to accept. We are excited about this because, in the best scenarios, we can achieve unbiased results (that is, noise-free); and we want to make this capability accessible all across the stack: from kernel to algorithm and model developers.
Why is error mitigation important?¶
We need improvements in scale, quality, and speed.
The promise of error mitigation is to translate the continuous progress in quantum hardware into continuous improvements in quantum computations and quantum information processing. We expect that, while insufficient to fully overcome imperfections, every advancement should incrementally push the frontier of what can be achieved practically; as opposed to a scenario where little to no progress is made until we suddenly overcome the fault-tolerant threshold.
Beyond the 100x100 circuit, we envision a future where error correction and error mitigation can work in a hybrid way. In that regard, this approach has proven to be both practically effective and intellectually challenging.
Concepts¶
The following terms are used in this section.
TERMINOLOGY
As with every nascent field, terminology is sometimes incosistent: people use the same terms to refer to (slightly) different things.
Estimators: Strategies for approximating certain physical values that are fundamentally unknown.
Sampling: The process of taking several measurements of one or several things.
Overhead: Extra costs introduced by new techniques, relative to a base implementation.
Bias: A systematic drift in the measured quantities, usually caused by errors.
Shot/sample noise: Uncertainty in the obtained results due to a lack of infinite precision (that is, a finite number of samples).
Implications¶
When implementing any error mitigation technique, we expect the bias in our results to be reduced with respect to the previous, unmitigated, bias; in some cases even disappearing. However, this comes at a cost. As we reduce the bias in our estimated quantities, the statistical variability will increase (that is, variance), which we can account for by further increasing the number of shots per circuit in our sampling process. This will introduce overhead beyond that needed to reduce the bias,
therefore it is not done by default. The user can easily opt in to this behavior by adjusting the amount of shots
per circuit in run_options
.
In mathematical terms, we expect our error mitigated estimator to be such that:
Twirled readout error extinction¶
Twirled readout error extinction (T-REx) uses a technique known as Pauli twirling to reduce the noise introduced during the process of quantum measurement. This technique assumes no specific form of noise, which makes it very general and effective.
Overall workflow¶
Acquire data for the zero state with randomized bit flips (Pauli X before measurement)
Acquire data for the desired (noisy) state with randomized bit flips (Pauli X before measurement)
Compute the special function for each data set, and divide.
Reference: E. van den Berg, Z. Minev, and K. Temme, Model-free readout-error mitigation for quantum expectation values arXiv:2012.09738
[8]:
options = Options()
options.resilience_level = 1 # T-REx
options.optimization_level = 0 # No optimization
options.execution.shots = 1000
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
job_trex = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_trex.job_id)
print(job_trex.result())
expvals_unmit_trex = job_trex.result().values
expvals_unmit_trex_variance = [
metadata["variance"] / metadata["shots"] for metadata in job_trex.result().metadata
]
std_error_trex = np.sqrt(expvals_unmit_trex_variance)
job id: cdkrpq7tlcfkm5f0demg
EstimatorResult(values=array([0.95941791, 0.81652588, 0.68894371, 0.55625825, 0.45674416]), metadata=[{'variance': 0.733385959939609, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 0.9871541699414397, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.1792252443219302, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.3444454335924159, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}, {'variance': 1.4452534486647257, 'shots': 1008, 'readout_mitigation_num_twirled_circuits': 16, 'readout_mitigation_shots_calibration': 8192}])
[9]:
plt.title("Trotter circuits expectation value")
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_trex,
std_error_trex,
fmt="o",
linestyle="-",
capsize=4,
c="violet",
label="T-REx",
)
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xlabel("No. Trotter Steps")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Zero noise extrapolation¶
Zero noise extrapolation (ZNE) works by first amplifying the noise in the circuit that is preparing the desired quantum state, obtaining measurements for several different levels of noise, and using those measurements to infer the noiseless result.
Overall workflow¶
Amplify circuit noise for several noise factors
Run every noise amplified circuit
Extrapolate back to the zero noise limit
[10]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 0 # No optimization
options.resilience_level = 2 # ZNE
with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
job_zne = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_zne.job_id)
print(job_zne.result())
expvals_unmit_zne = job_zne.result().values
# Standard error: coming soon!
job id: cdkrq4i2h6kvivdb2an0
EstimatorResult(values=array([0.896 , 0.86833333, 0.82716667, 0.63116667, 0.58366667]), metadata=[{'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.84, 0.788, 0.664], 'variance': [0.2944000000000001, 0.37905599999999995, 0.5591039999999999], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.778, 0.614, 0.43], 'variance': [0.39471599999999996, 0.623004, 0.8151], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.718, 0.498, 0.28], 'variance': [0.484476, 0.751996, 0.9216], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.54, 0.376, 0.19], 'variance': [0.7083999999999999, 0.858624, 0.9639], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<TwoQubitAmplifier:{'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 3, 5], 'values': [0.498, 0.31, 0.142], 'variance': [0.751996, 0.9039, 0.979836], 'shots': [1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'LinearExtrapolator'}}}])
[11]:
plt.title("Trotter circuits expectation value")
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_zne,
[0] * (num_steps - 1),
fmt="o",
linestyle="-",
capsize=4,
c="cyan",
label="ZNE",
)
plt.xlabel("No. Trotter Steps")
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Probabilistic error cancellation¶
Probabilistic error cancellation (PEC) samples for a collection of circuits that, on average mimics a noise inverting channel to cancel out the noise in the desired computation. This process is a bit like how noise-cancelling headphones work, and produces great results; however, it is not as general as other methods, and the sampling overhead is exponential.
Reference: E. van den Berg, Z. Minev, A. Kandala, and K. Temme, Probabilistic error cancellation with sparse Pauli-Lindblad models on noisy quantum processors arXiv:2201.09866
Overall workflow¶
Step 1: Pauli twirling¶
Step 2: Repeat layer and learn the noise¶
Step 3: Derive a fidelity (error for each noise channel)¶
[ ]:
def interim_results_callback(job_id, result):
now = datetime.datetime.now()
print(now, "*** Callback ***", result, "\n")
options = Options()
options.optimization_level = 0 # No optimization
options.execution.shots = 100
options.resilience_level = 3 # PEC
options.environment.callback = interim_results_callback
with Session(service=service, backend=backend) as session:
estimator_pec = Estimator(session=session, options=options)
job_pec = estimator_pec.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_pec.job_id)
expvals_pec = job_pec.result().values
std_error_pec = [metadata["standard_error"] for metadata in job_pec.result().metadata]
job id: cdkqv522h6kvivdat0vg
2022-11-07 20:23:43.013816 *** Callback *** {'unique_layers_detected': 2, 'total_layers': 60}
2022-11-07 20:30:41.251325 *** Callback *** {'msg': 'Sampling overhead for layer 1/2: 1.0263820029324646'}
2022-11-07 20:37:38.920151 *** Callback *** {'msg': 'Sampling overhead for layer 2/2: 1.0692954781746'}
2022-11-07 20:37:39.334815 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 1.4508651011392564}
2022-11-07 20:37:39.336883 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 1.2045186180127132}
2022-11-07 20:37:39.336983 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 1.7475940265471324}
2022-11-07 20:37:39.337099 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 2.105009541703825}
2022-11-07 20:37:39.338120 *** Callback *** {'sampling_overhead_by_layer': [1.0692954781746, 1.0263820029324646], 'unique_layers': 2, 'total_sampling_overhead': 2.5355231840766654}
2022-11-07 20:44:17.157534 *** Callback *** {'values': array([0.96681631, 0.96346463, 0.81458917, 0.83279075, 0.71165489]), 'metadata': [{'standard_error': 0.04741526161355738, 'confidence_interval': [0.6946850904749993, 1.2389475260753755], 'confidence_level': 0.95, 'shots': 15360, 'samples': 120, 'sampling_overhead': 1.2045186180127132, 'total_mitigated_layers': 4}, {'standard_error': 0.06003453067758544, 'confidence_interval': [0.6917633123010369, 1.235165948939192], 'confidence_level': 0.95, 'shots': 18560, 'samples': 145, 'sampling_overhead': 1.4508651011392564, 'total_mitigated_layers': 8}, {'standard_error': 0.07893102265063534, 'confidence_interval': [0.5423767896024972, 1.086801560321982], 'confidence_level': 0.95, 'shots': 22272, 'samples': 174, 'sampling_overhead': 1.7475940265471324, 'total_mitigated_layers': 12}, {'standard_error': 0.08198342212333354, 'confidence_interval': [0.5608466609152284, 1.104734830411759], 'confidence_level': 0.95, 'shots': 26880, 'samples': 210, 'sampling_overhead': 2.105009541703825, 'total_mitigated_layers': 16}, {'standard_error': 0.08955468433998504, 'confidence_interval': [0.43973826826406204, 0.9835715192472465], 'confidence_level': 0.95, 'shots': 32384, 'samples': 253, 'sampling_overhead': 2.5355231840766654, 'total_mitigated_layers': 20}]}
[ ]:
plt.title("Trotter circuits expectation value")
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_pec,
std_error_pec,
fmt="d",
linestyle="-",
capsize=4,
c="orange",
label="PEC",
)
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xlabel("No. Trotter Steps")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

PEC callback messages explained¶
Layers detected:
2022-11-07 20:23:43.013816 *** Callback *** {'unique_layers_detected': 2, 'total_layers': 60}
In the list of circuits passed to the Estimator, a total of 60 layers were detected and two of them were unique. Qiskit Runtime will learn the noise model for the two unique layers.
Sampling overhead for layers:
2022-11-07 20:30:41.251325 *** Callback *** {'msg': 'Sampling overhead for layer 1/2: 1.0263820029324646'}
2022-11-07 20:37:38.920151 *** Callback *** {'msg': 'Sampling overhead for layer 2/2: 1.0692954781746'}
These messages show the sampling overhead for each of the unique layers. Notice that it took roughly 7 minutes to learn the noise model of each layer.
PEC callback messages explained¶
Layers detected:
2022-11-07 20:23:43.013816 *** Callback *** {'unique_layers_detected': '2, total_layers: 60'}
In the list of circuits passed to Estimator, a total of 60 layers were detected and two of them were unique. Qiskit Runtime will learn the noise model for the two unique layers.
Sampling overhead for layers:
2022-11-07 20:30:41.251325 *** Callback *** {'msg': 'Sampling overhead for layer 1/2: 1.0263820029324646'}
2022-11-07 20:37:38.920151 *** Callback *** {'msg': 'Sampling overhead for layer 2/2: 1.0692954781746'}
These messages show the sampling overhead for each of the unique layers. Notice that it took roughly 7 minutes to learn the noise model of each layer.
Circuit total sampling overhead
Circuit 1 total sampling overhead:
1.2045186180127132
2022-11-07 20:37:39.336883 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 1.2045186180127132}
Circuit 2 total sampling overhead:
1.4508651011392564
2022-11-07 20:37:39.334815 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 1.4508651011392564}
Circuit 3 total sampling overhead:
1.7475940265471324
2022-11-07 20:37:39.336983 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 1.7475940265471324}
Circuit 4 total sampling overhead:
2.105009541703825
2022-11-07 20:37:39.337099 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 2.105009541703825}
Circuit 5 total sampling overhead:
2.5355231840766654
2022-11-07 20:37:39.338120 *** Callback *** {sampling_overhead_by_layer: [1.0692954781746, 1.0263820029324646], unique_layers: 2, total_sampling_overhead: 2.5355231840766654}
The sampling overhead increases when there are more layers to mitigate.
[ ]:
print(job_pec.result())
EstimatorResult(values=array([0.96681631, 0.96346463, 0.81458917, 0.83279075, 0.71165489]), metadata=[{'standard_error': 0.04741526161355738, 'confidence_interval': [0.6946850904749993, 1.2389475260753755], 'confidence_level': 0.95, 'shots': 15360, 'samples': 120, 'sampling_overhead': 1.2045186180127132, 'total_mitigated_layers': 4}, {'standard_error': 0.06003453067758544, 'confidence_interval': [0.6917633123010369, 1.235165948939192], 'confidence_level': 0.95, 'shots': 18560, 'samples': 145, 'sampling_overhead': 1.4508651011392564, 'total_mitigated_layers': 8}, {'standard_error': 0.07893102265063534, 'confidence_interval': [0.5423767896024972, 1.086801560321982], 'confidence_level': 0.95, 'shots': 22272, 'samples': 174, 'sampling_overhead': 1.7475940265471324, 'total_mitigated_layers': 12}, {'standard_error': 0.08198342212333354, 'confidence_interval': [0.5608466609152284, 1.104734830411759], 'confidence_level': 0.95, 'shots': 26880, 'samples': 210, 'sampling_overhead': 2.105009541703825, 'total_mitigated_layers': 16}, {'standard_error': 0.08955468433998504, 'confidence_interval': [0.43973826826406204, 0.9835715192472465], 'confidence_level': 0.95, 'shots': 32384, 'samples': 253, 'sampling_overhead': 2.5355231840766654, 'total_mitigated_layers': 20}])
PEC metadata¶
Circuit 1:
{
"standard_error": 0.04741526161355738,
"confidence_interval": [
0.6946850904749993,
1.2389475260753755
],
"confidence_level": 0.95,
"shots": 15360,
"samples": 120,
"sampling_overhead": 1.2045186180127132,
"total_mitigated_layers": 4
}
Circuit 2:
{
"standard_error": 0.06003453067758544,
"confidence_interval": [
0.6917633123010369,
1.235165948939192
],
"confidence_level": 0.95,
"shots": 18560,
"samples": 145,
"sampling_overhead": 1.4508651011392564,
"total_mitigated_layers": 8
}
Circuit 3:
{
"standard_error": 0.07893102265063534,
"confidence_interval": [
0.5423767896024972,
1.086801560321982
],
"confidence_level": 0.95,
"shots": 22272,
"samples": 174,
"sampling_overhead": 1.7475940265471324,
"total_mitigated_layers": 12
}
Circuit 4:
{
"standard_error": 0.08198342212333354,
"confidence_interval": [
0.5608466609152284,
1.104734830411759
],
"confidence_level": 0.95,
"shots": 26880,
"samples": 210,
"sampling_overhead": 2.105009541703825,
"total_mitigated_layers": 16
}
Circuit 5
{
"standard_error": 0.08955468433998504,
"confidence_interval": [
0.43973826826406204,
0.9835715192472465
],
"confidence_level": 0.95,
"shots": 32384,
"samples": 253,
"sampling_overhead": 2.5355231840766654,
"total_mitigated_layers": 20
}
[ ]:
pec_metadata = job_pec.result().metadata
fig, ax = plt.subplots()
fig.subplots_adjust(right=0.75)
twin1 = ax.twinx()
twin2 = ax.twinx()
twin3 = ax.twinx()
twin2.spines.right.set_position(("axes", 1.2))
twin3.spines.right.set_position(("axes", 1.4))
(p1,) = ax.plot(
range(1, num_steps),
[m["total_mitigated_layers"] for m in pec_metadata],
"b-",
label="Total mitigated layers",
)
(p2,) = twin1.plot(
range(1, num_steps),
[m["sampling_overhead"] for m in pec_metadata],
"r-",
label="Sampling overhead",
)
(p3,) = twin2.plot(range(1, num_steps), [m["samples"] for m in pec_metadata], "g-", label="Samples")
(p4,) = twin3.plot(range(1, num_steps), [m["shots"] for m in pec_metadata], "c-", label="Shots")
ax.set_ylim(0, 20)
twin1.set_ylim(0, 2.8)
twin2.set_ylim(0, 300)
twin3.set_ylim(0, 35000)
ax.set_xlabel("No. Trotter Steps")
ax.set_ylabel("Total mitigated layers")
twin1.set_ylabel("Sampling overhead")
twin2.set_ylabel("Samples")
twin3.set_ylabel("Shots")
ax.yaxis.label.set_color(p1.get_color())
twin1.yaxis.label.set_color(p2.get_color())
twin2.yaxis.label.set_color(p3.get_color())
twin3.yaxis.label.set_color(p4.get_color())
tkw = dict(size=4, width=1.5)
ax.tick_params(axis="y", colors=p1.get_color(), **tkw)
twin1.tick_params(axis="y", colors=p2.get_color(), **tkw)
twin2.tick_params(axis="y", colors=p3.get_color(), **tkw)
twin3.tick_params(axis="y", colors=p4.get_color(), **tkw)
plt.xticks([1, 2, 3, 4, 5])
ax.legend(handles=[p1, p2, p3, p4])
plt.title("PEC metadata")
plt.show()

Combined plot¶
[ ]:
from matplotlib.pyplot import figure
plt.errorbar(
range(1, num_steps),
expvals_ideal,
std_error_ideal,
fmt="o",
linestyle="--",
capsize=4,
c="red",
label="Ideal",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit,
std_error_unmit,
fmt="o",
linestyle="-",
capsize=4,
c="green",
label="No mitigation",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_trex,
std_error_trex,
fmt="o",
linestyle="-",
capsize=4,
c="violet",
label="T-REx",
)
plt.errorbar(
range(1, num_steps),
expvals_unmit_zne,
[0] * (num_steps - 1),
fmt="o",
linestyle="-",
capsize=4,
c="cyan",
label="ZNE",
)
plt.errorbar(
range(1, num_steps),
expvals_pec,
std_error_pec,
fmt="d",
linestyle="-",
capsize=4,
c="orange",
label="PEC",
)
plt.title("Trotter circuits expectation value")
plt.ylabel(f"$\langle ZZZZ \\rangle$")
plt.xlabel("No. Trotter Steps")
plt.xticks([1, 2, 3, 4, 5])
plt.legend()
plt.show()

Advanced ZNE options¶
Noise amplification¶
As a first approach, we provide a noise amplification technique known as unitary folding.
Reference: Tudor Giurgica-Tiron, Yousef Hindy, Ryan LaRose, Andrea Mari, and William J. Zeng, Digital zero noise extrapolation for quantum error mitigation arXiv:2005.10921.
Digital vs analog¶
Local vs global¶
Extrapolation¶
Useful noise profiles¶
Useless noise profiles¶
[ ]:
options = Options()
options.execution.shots = 1000
options.optimization_level = 0 # no optimization
options.resilience_level = 2 # ZNE
options.resilience.noise_factors = [1, 2, 3, 4]
options.resilience.noise_amplifier = "LocalFoldingAmplifier"
options.resilience.extrapolator = "QuadraticExtrapolator"
with Session(service=service, backend="ibmq_montreal") as session:
estimator = Estimator(session=session, options=options)
job_zne_options = estimator.run(circuits=trotter_circuit_list, observables=obs_list)
print("job id:", job_zne_options.job_id)
print(job_zne_options.result())
job id: cdkrqbdf14jb6brgbrl0
EstimatorResult(values=array([0.9285, 0.8165, 0.835 , 0.6815, 0.4945]), metadata=[{'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.838, 0.798, 0.738, 0.752], 'variance': [0.297756, 0.36319599999999996, 0.455356, 0.434496], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.732, 0.676, 0.572, 0.522], 'variance': [0.46417600000000003, 0.543024, 0.6728160000000001, 0.727516], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.674, 0.51, 0.436, 0.328], 'variance': [0.5457239999999999, 0.7399, 0.809904, 0.892416], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.512, 0.372, 0.266, 0.188], 'variance': [0.7378560000000001, 0.8616159999999999, 0.929244, 0.964656], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}, {'zne': {'noise_amplification': {'noise_amplifier': "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>", 'noise_factors': [1, 2, 3, 4], 'values': [0.442, 0.35, 0.268, 0.13], 'variance': [0.804636, 0.8775000000000001, 0.928176, 0.9831], 'shots': [1000, 1000, 1000, 1000]}, 'extrapolation': {'extrapolator': 'QuadraticExtrapolator'}}}])
{
"values": [
0.928499999999999,
0.8165,
0.835,
0.6815000000000001,
0.49449999999999983
],
"metadata": [
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.838,
0.798,
0.738,
0.752
],
"variance": [
0.297756,
0.36319599999999996,
0.455356,
0.434496
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
},
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.732,
0.676,
0.572,
0.522
],
"variance": [
0.46417600000000003,
0.543024,
0.6728160000000001,
0.727516
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
},
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.674,
0.51,
0.436,
0.328
],
"variance": [
0.5457239999999999,
0.7399,
0.809904,
0.892416
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
},
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.512,
0.372,
0.266,
0.188
],
"variance": [
0.7378560000000001,
0.8616159999999999,
0.929244,
0.964656
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
},
{
"zne": {
"noise_amplification": {
"noise_amplifier": "<LocalFoldingAmplifier:{'gates_to_fold': None, 'noise_factor_relative_tolerance': 0.01, 'random_seed': None, 'sub_folding_option': 'from_first'}>",
"noise_factors": [
1,
2,
3,
4
],
"values": [
0.442,
0.35,
0.268,
0.13
],
"variance": [
0.804636,
0.8775000000000001,
0.928176,
0.9831
],
"shots": [
1000,
1000,
1000,
1000
]
},
"extrapolation": {
"extrapolator": "QuadraticExtrapolator"
}
}
}
]
}
[1]:
import qiskit_ibm_runtime
qiskit_ibm_runtime.version.get_version_info()
[1]:
'0.11.1'
[ ]:
from qiskit.tools import jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
qiskit-terra | 0.22.2 |
qiskit-aer | 0.11.0 |
qiskit-ibmq-provider | 0.19.2 |
System information | |
Python version | 3.10.4 |
Python compiler | Clang 12.0.0 |
Python build | main, Mar 31 2022 03:38:35 |
OS | Darwin |
CPUs | 4 |
Memory (Gb) | 16.0 |
Tue Nov 08 12:15:46 2022 EST |
This code is a part of Qiskit
© Copyright IBM 2017, 2022.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.