qiskit-documentation/docs/guides/noise-learning.ipynb

314 lines
16 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "1b2370f0-a4ee-49b1-9e53-e4527d37bc6f",
"metadata": {},
"source": [
"# Noise learning helper"
]
},
{
"cell_type": "markdown",
"id": "b5e65fb2-8556-4477-81a5-9b6bf551ca7e",
"metadata": {
"tags": [
"version-info"
]
},
"source": []
},
{
"cell_type": "markdown",
"id": "cabee439-d0f2-4079-a47d-b6d96ce78332",
"metadata": {},
"source": [
"The error mitigation techniques [PEA](./error-mitigation-and-suppression-techniques#probabilistic-error-amplification-pea) and [PEC](./error-mitigation-and-suppression-techniques#probabilistic-error-cancellation-pec) both utilize a noise learning component based on a [Pauli-Lindblad noise model](https://arxiv.org/abs/2201.09866), which is typically managed during execution after submitting one or more jobs through `qiskit-ibm-runtime` without any local access to the fitted noise model. However, as of `qiskit-ibm-runtime` 0.27.1, a [`NoiseLearner`](../api/qiskit-ibm-runtime/noise_learner) and associated [`NoiseLearnerOptions`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.NoiseLearnerOptions) class have been created to obtain the results of these noise learning experiments. These results can then be stored locally as a `NoiseLearnerResult` and used as input in later experiments. This page provides an overview of its usage and the associated options available.\n",
"\n",
"\n",
"## Overview\n",
"\n",
"The `NoiseLearner` class performs experiments that characterize noise processes based on a Pauli-Lindblad noise model for one (or more) circuits. It possesses a `run()` method that executes the learning experiments and takes as input either a list of circuits or a [PUB](./primitive-input-output#overview-of-pubs), and returns a `NoiseLearnerResult` containing the learned noise channels and metadata about the job(s) submitted. Below is a code snippet demonstrating the usage of the helper program."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "c5118119-5892-4ad9-9908-107795a1f1fa",
"metadata": {},
"outputs": [],
"source": [
"from qiskit import QuantumCircuit\n",
"from qiskit.transpiler import CouplingMap\n",
"from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
"\n",
"from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2\n",
"from qiskit_ibm_runtime.noise_learner import NoiseLearner\n",
"from qiskit_ibm_runtime.options import (\n",
" NoiseLearnerOptions,\n",
" ResilienceOptionsV2,\n",
" EstimatorOptions,\n",
")\n",
"\n",
"# Build a circuit with two entangling layers\n",
"num_qubits = 27\n",
"edges = list(CouplingMap.from_line(num_qubits, bidirectional=False))\n",
"even_edges = edges[::2]\n",
"odd_edges = edges[1::2]\n",
"\n",
"circuit = QuantumCircuit(num_qubits)\n",
"for pair in even_edges:\n",
" circuit.cx(pair[0], pair[1])\n",
"for pair in odd_edges:\n",
" circuit.cx(pair[0], pair[1])\n",
"\n",
"# Choose a backend to run on\n",
"service = QiskitRuntimeService()\n",
"backend = service.least_busy()\n",
"\n",
"# Transpile the circuit for execution\n",
"pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
"circuit_to_learn = pm.run(circuit)\n",
"\n",
"# Instantiate a NoiseLearner object and execute the noise learning program\n",
"learner = NoiseLearner(mode=backend)\n",
"job = learner.run([circuit_to_learn])\n",
"noise_model = job.result()"
]
},
{
"cell_type": "markdown",
"id": "1859540c-a597-411a-ab98-1b436b284f8a",
"metadata": {},
"source": [
"The resulting `NoiseLearnerResult.data` is a list of [`LayerError`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.utils.noise_learner_result.LayerError) objects containing the [noise model](https://arxiv.org/abs/2201.09866) for each individual entangling layer that belongs to the target circuit(s). Each `LayerError` stores the layer information, in the form of a circuit and a set of qubit labels, alongside the [`PauliLindBladError`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.utils.noise_learner_result.PauliLindbladError) for the noise model that was learned for the given layer."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "33d8cc11-6c6f-4838-8038-dd9994476db4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Noise learner result contains 2 entries and has the following type:\n",
" <class 'qiskit_ibm_runtime.utils.noise_learner_result.NoiseLearnerResult'>\n",
"\n",
"Each element of `NoiseLearnerResult` then contains an object of type:\n",
" <class 'qiskit_ibm_runtime.utils.noise_learner_result.LayerError'>\n",
"\n",
"And each of these `LayerError` objects possess the following data: \n",
"PauliLindbladError(generators=['IIIIIIIIIIIIIIIIIIIIIIIIIIX', 'IIIIIIIIIIIIIIIIIIIIIIIIIIY',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIIIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIXI',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIIXX', 'IIIIIIIIIIIIIIIIIIIIIIIIIXY',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIIXZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIYI',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIIYX', 'IIIIIIIIIIIIIIIIIIIIIIIIIYY',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIIYZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIZI',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIIZX', 'IIIIIIIIIIIIIIIIIIIIIIIIIZY',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIIZZ', 'IIIIIIIIIIIIIIIIIIIIIIIIXII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIXXI', 'IIIIIIIIIIIIIIIIIIIIIIIIXYI',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIXZI', 'IIIIIIIIIIIIIIIIIIIIIIIIYII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIYXI', 'IIIIIIIIIIIIIIIIIIIIIIIIYYI',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIYZI', 'IIIIIIIIIIIIIIIIIIIIIIIIZII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIZXI', 'IIIIIIIIIIIIIIIIIIIIIIIIZYI',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIIZZI', 'IIIIIIIIIIIIIIIIIIIIIIIXIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIXXII', 'IIIIIIIIIIIIIIIIIIIIIIIXYII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIXZII', 'IIIIIIIIIIIIIIIIIIIIIIIYIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIYXII', 'IIIIIIIIIIIIIIIIIIIIIIIYYII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIYZII', 'IIIIIIIIIIIIIIIIIIIIIIIZIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIZXII', 'IIIIIIIIIIIIIIIIIIIIIIIZYII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIIZZII', 'IIIIIIIIIIIIIIIIIIIIIIXIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIXXIII', 'IIIIIIIIIIIIIIIIIIIIIIXYIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIXZIII', 'IIIIIIIIIIIIIIIIIIIIIIYIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIYXIII', 'IIIIIIIIIIIIIIIIIIIIIIYYIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIYZIII', 'IIIIIIIIIIIIIIIIIIIIIIZIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIZXIII', 'IIIIIIIIIIIIIIIIIIIIIIZYIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIZZIII', 'IIIIIIIIIIIIIIIIIIIIIXIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIXXIIII', 'IIIIIIIIIIIIIIIIIIIIIXYIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIXZIIII', 'IIIIIIIIIIIIIIIIIIIIIYIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIYXIIII', 'IIIIIIIIIIIIIIIIIIIIIYYIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIYZIIII', 'IIIIIIIIIIIIIIIIIIIIIZIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIZXIIII', 'IIIIIIIIIIIIIIIIIIIIIZYIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIZZIIII', 'IIIIIIIIIIIIIIIIIIIIXIIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIXXIIIII', 'IIIIIIIIIIIIIIIIIIIIXYIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIXZIIIII', 'IIIIIIIIIIIIIIIIIIIIYIIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIYXIIIII', 'IIIIIIIIIIIIIIIIIIIIYYIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIYZIIIII', 'IIIIIIIIIIIIIIIIIIIIZIIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIZXIIIII', 'IIIIIIIIIIIIIIIIIIIIZYIIIII', ...], rates=[0.00084, 0.00089, 0.00054, 0.00156, 0.00089, 0.00084, 0.00023, 0.0, 0.0, 0.0, 0.00102, 0.00015, 0.0, 3e-05, 0.00082, 0.0013, 0.0, 6e-05, 9e-05, 0.0, 5e-05, 0.00044, 0.00029, 0.00027, 0.00013, 0.00034, 0.00056, 0.00181, 0.00135, 0.0, 0.0, 0.00132, 0.00184, 0.0, 5e-05, 0.00096, 0.00013, 0.00119, 0.00078, 0.00069, 0.0, 3e-05, 0.0, 0.00047, 3e-05, 0.0, 0.0, 0.00061, 0.0, 0.0, 0.00481, 0.00074, 0.0005, 0.00072, 0.00022, 0.00025, 0.0, 0.00028, 0.00086, 0.00057, 0.0, 0.0, 0.00054, 0.00084, 0.0, 0.0, 0.00025, 0.00081, 0.0, 0.00025, 0.0, 0.00764, 0.0, 3e-05, 3e-05, 0.00133, 0.00106, 0.00109, 0.0, 0.00027, 3e-05, 0.0, 0.00132, 0.00061, 0.00036, 5e-05, 0.00098, 0.00124, 7e-05, 0.0, 0.0, 0.00062, 1e-05, 0.00059, 0.00012, 0.00272, 1e-05, 0.00012, 0.00059, 0.00032, 0.00173, 0.00029, 0.0, 0.00118, 0.00087, 0.00036, 0.00057, 0.00462, 0.00021, 0.00343, 0.00134, 0.00103, 9e-05, 0.00023, 0.0, 0.00127, 0.00023, 9e-05, 0.0, 0.00218, 0.00023, 0.00023, 0.00582, 0.0, 0.0, 0.00193, 0.00049, 0.00514, 0.00501, 0.0006, 0.0, 0.0, 0.0, 0.00149, 0.00045, 0.0005, 0.0, 0.00057, 0.00153, 0.0, 0.0, 0.0, 0.00017, 0.0, 0.00053, 0.00048, 0.0, 0.0, 0.00012, 0.00086, 0.00154, 0.00207, 0.00018, 0.0001, 0.00179, 0.00181, 0.00012, 0.0, 0.00106, 0.00047, 0.00098, 0.00117, 0.00171, 0.0, 0.0, 0.0, 3e-05, 0.0, 5e-05, 0.00035, 0.0002, 5e-05, 0.0, 0.00035, 0.00061, 0.00101, 0.0, 0.0, 0.00049, 0.00113, 0.0, 3e-05, 0.00036, 0.00022, 0.0006, 0.00044, 0.0, 0.00028, 0.00028, 0.00012, 0.0, 5e-05, 1e-05, 0.0004, 0.0, 0.00019, 0.00023, 0.00058, 0.00211, 0.00248, 0.00024, 0.0, 0.00248, 0.00211, 0.00068, 0.0, 0.0043, 0.00072, 0.00062, 0.00032, 0.00206, 0.0, 0.0, 0.0, 0.00117, 0.0, 0.0, 0.0, 0.00344, 0.0, 0.0, 0.00263, 0.00047, 0.00117, 0.00206, 0.00072, 0.0, 0.00055, 0.0, 0.00194, 0.00087, 0.00059, 0.0, 0.00095, 0.00153, 0.00158, 0.00135, 0.00043, 0.0, 0.0, 0.0, 0.0007, 4e-05, 6e-05, 0.00196, 0.00017, 0.00052, 0.00043, 0.00083, 0.0, 0.00035, 0.00183, 0.00017, 0.00033, 0.00062, 0.00201, 0.00042, 9e-05, 0.0, 5e-05, 1e-05, 0.0005, 0.0, 0.00274, 0.00509, 0.00517, 0.00163, 0.00261, 0.00056, 0.00252, 0.0, 0.00143, 0.00018, 7e-05, 0.00174, 0.00124, 0.0, 0.00038, 0.00194, 0.00027, 0.0, 0.0, 0.00043, 0.00028, 0.0, 0.00043, 0.0, 0.00056, 0.00014, 0.0, 0.0, 0.00197, 0.00071, 0.0007, 0.00037, 0.00011, 0.00031, 0.00018, 0.0006, 0.00028, 0.0, 0.0, 0.00044, 0.00142, 0.0, 6e-05, 6e-05, 0.00198, 0.0, 4e-05, 4e-05, 0.00851, 0.0, 0.00022, 0.00022])\n",
"\n"
]
}
],
"source": [
"print(\n",
" f\"Noise learner result contains {len(noise_model.data)} entries\"\n",
" f\" and has the following type:\\n {type(noise_model)}\\n\"\n",
")\n",
"print(\n",
" f\"Each element of `NoiseLearnerResult` then contains\"\n",
" f\" an object of type:\\n {type(noise_model.data[0])}\\n\"\n",
")\n",
"print(\n",
" f\"And each of these `LayerError` objects possess the\"\n",
" f\" following data: \\n{noise_model.data[0].error}\\n\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "a27a38f1-393d-49f9-92c3-a8634bfb1a60",
"metadata": {},
"source": [
"The `LayerError.error` attribute of the noise learning result contains the generators and error rates of the fitted Pauli Lindblad model, which has the form\n",
"\n",
"$$ \\Lambda(\\rho) = \\exp{\\sum_j r_j \\left(P_j \\rho P_j^\\dagger - \\rho\\right)}, $$\n",
"\n",
"where the $r_j$ are the `LayerError.rates` and $P_j$ are the Pauli operators specified in `LayerError.generators`."
]
},
{
"cell_type": "markdown",
"id": "7ebb4b7d-ef45-4996-bf5a-125d0831ebca",
"metadata": {},
"source": [
"## Noise learning options\n",
"\n",
"You can choose among several options to input when you instantiate a `NoiseLearner` object. These options are encapsulated by the `qiskit_ibm_runtime.options.NoiseLearnerOptions` class and include the ability to specify the maximum layers to learn, number of randomizations, and the twirling strategy, among others. Refer to the API documentation about [`NoiseLearnerOptions`](../api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.NoiseLearnerOptions) for more detailed information.\n",
"\n",
"Below is a simple example showing how to use the `NoiseLearnerOptions` in a `NoiseLeaner` experiment:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "8f35d68a-b459-4f1c-ae44-a01bbe700ed0",
"metadata": {},
"outputs": [],
"source": [
"# Build a GHZ circuit\n",
"circuit = QuantumCircuit(10)\n",
"circuit.h(0)\n",
"circuit.cx(range(0, 9), range(1, 10))\n",
"# Choose a backend to run on\n",
"service = QiskitRuntimeService()\n",
"backend = service.least_busy()\n",
"\n",
"# Transpile the circuit for execution\n",
"pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
"circuit_to_run = pm.run(circuit_to_learn)\n",
"\n",
"# Instantiate a noise learner options object\n",
"learner_options = NoiseLearnerOptions(\n",
" max_layers_to_learn=3, num_randomizations=32, twirling_strategy=\"all\"\n",
")\n",
"\n",
"# Instantiate a NoiseLearner object and execute the noise learning program\n",
"learner = NoiseLearner(mode=backend, options=learner_options)\n",
"job = learner.run([circuit_to_run])\n",
"noise_model = job.result()"
]
},
{
"cell_type": "markdown",
"id": "694b0e38-7aeb-48e0-8598-b64cff395bc2",
"metadata": {},
"source": [
"## Input noise model to a primitive\n",
"\n",
"The noise model learned on the circuit can also be used as an input to the `EstimatorV2` primitive implemented in Qiskit IBM Runtime. This can be passed into the primitive a few different ways. The next three examples show how you can pass the noise model to the `estimator.options` attribute directly, via a `ResilienceOptionsV2` object before instantiating an Estimator primitive, and by passing in an appropriately formatted dictionary."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "d8b504c1-17ad-4e23-b508-eac1955bd1d6",
"metadata": {},
"outputs": [],
"source": [
"# pass the noise model to the `estimator.options` attribute directly\n",
"estimator = EstimatorV2(mode=backend)\n",
"estimator.options.resilience.layer_noise_model = noise_model"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "8aa753bc-915d-4d47-ba56-5179ec9cf4ca",
"metadata": {},
"outputs": [],
"source": [
"# Specify options via a ResilienceOptionsV2 object\n",
"resilience_options = ResilienceOptionsV2(layer_noise_model=noise_model)\n",
"estimator_options = EstimatorOptions(resilience=resilience_options)\n",
"estimator = EstimatorV2(mode=backend, options=estimator_options)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "6dcb70fe-e291-4b5a-a79b-14cace921905",
"metadata": {},
"outputs": [],
"source": [
"# Specify options via a dictionary\n",
"options_dict = {\n",
" \"resilience_level\": 2,\n",
" \"resilience\": {\"layer_noise_model\": noise_model},\n",
"}\n",
"\n",
"estimator = EstimatorV2(mode=backend, options=options_dict)"
]
},
{
"cell_type": "markdown",
"id": "8fc627b2-fee5-4275-9895-a48d65ef26f1",
"metadata": {},
"source": [
"Once the noise model is passed into the `EstimatorV2` object, it can be used to run workloads and perform error mitigation as normal."
]
},
{
"cell_type": "markdown",
"id": "6bcd1032-a674-466a-b40b-87f0c4d85984",
"metadata": {},
"source": [
"## Next steps\n",
"\n",
"<Admonition type=\"tip\" title=\"Recommendations\">\n",
" - Read more about [configuring error mitigation](configure-error-mitigation).\n",
" - Review the [EstimatorOptions API reference](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.EstimatorOptions) and [ResilienceOptionsV2 API reference](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.ResilienceOptionsV2).\n",
" - Learn more about [Error mitigation and suppression techniques](error-mitigation-and-suppression-techniques) that are available through Qiskit Runtime.\n",
" - Review how to [Specify options](specify-runtime-options) for the Qiskit Runtime primitives.\n",
" - Read [Migrate to V2 primitives](/migration-guides/v2-primitives).\n",
"</Admonition>"
]
}
],
"metadata": {
"description": "Get started with the noise learning helper program to save the noise models created when executing workloads in Qiskit IBM Runtime",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3"
},
"title": "Noise learning helper"
},
"nbformat": 4,
"nbformat_minor": 2
}