Kjf/noise learning (#1847)

Closes #1830

---------

Co-authored-by: Samuele Ferracin <sam.ferracin@ibm.com>
This commit is contained in:
Kaelyn Ferris 2024-08-29 10:58:29 -04:00 committed by GitHub
parent 0c3fa1cb7c
commit c4ea4ebe5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 311 additions and 0 deletions

View File

@ -299,6 +299,10 @@
{
"title": "Primitives with REST API",
"url": "/guides/primitives-rest-api"
},
{
"title": "Noise learning",
"url": "/guides/noise-learning"
}
]
},

View File

@ -31,6 +31,7 @@ expectation values of observables corresponding to physical quantities or cost f
* [PUBs and primitive results](./primitive-input-output)
* [Primitives examples](./primitives-examples)
* [Primitives with REST API](./primitives-rest-api)
* [Noise learning helper](./noise-learning)
### Configure runtime options
* [Overview](./runtime-options-overview)

View File

@ -0,0 +1,303 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "1b2370f0-a4ee-49b1-9e53-e4527d37bc6f",
"metadata": {},
"source": [
"# Noise learning helper\n",
"\n",
"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 which characterizes noise processes based on a Pauli-Lindblad noise model for one (or more) circuits. It possesses a `run()` method which will execute 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": null,
"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",
"from qiskit.quantum_info import SparsePauliOp\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 NoiseLearnerOptions, ResilienceOptionsV2, EstimatorOptions\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": 30,
"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",
" 'IIIIIIIIIIIIIIIIIIIIIIIYIII', 'IIIIIIIIIIIIIIIIIIIIIIIZIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIXIIII', 'IIIIIIIIIIIIIIIIIIIIIIXXIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIXYIII', 'IIIIIIIIIIIIIIIIIIIIIIXZIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIYIIII', 'IIIIIIIIIIIIIIIIIIIIIIYXIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIYYIII', 'IIIIIIIIIIIIIIIIIIIIIIYZIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIIIIIIIIIZXIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIIZYIII', 'IIIIIIIIIIIIIIIIIIIIIIZZIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIXIIIII', 'IIIIIIIIIIIIIIIIIIIIIXIIXII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIXIIYII', 'IIIIIIIIIIIIIIIIIIIIIXIIZII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIXXIIII', 'IIIIIIIIIIIIIIIIIIIIIXYIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIXZIIII', 'IIIIIIIIIIIIIIIIIIIIIYIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIYIIXII', 'IIIIIIIIIIIIIIIIIIIIIYIIYII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIYIIZII', 'IIIIIIIIIIIIIIIIIIIIIYXIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIYYIIII', 'IIIIIIIIIIIIIIIIIIIIIYZIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIIIIIIIIIZIIXII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIZIIYII', 'IIIIIIIIIIIIIIIIIIIIIZIIZII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIZXIIII', 'IIIIIIIIIIIIIIIIIIIIIZYIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIIZZIIII', 'IIIIIIIIIIIIIIIIIIIIXIIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIXIIXIII', 'IIIIIIIIIIIIIIIIIIIIXIIYIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIXIIZIII', 'IIIIIIIIIIIIIIIIIIIIYIIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIYIIXIII', 'IIIIIIIIIIIIIIIIIIIIYIIYIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIYIIZIII', 'IIIIIIIIIIIIIIIIIIIIZIIIIII',\n",
" 'IIIIIIIIIIIIIIIIIIIIZIIXIII', 'IIIIIIIIIIIIIIIIIIIIZIIYIII', ...], rates=[0.00067, 0.00083, 0.00523, 0.00044, 0.00011, 2e-05, 7e-05, 0.00031, 0.00011, 2e-05, 7e-05, 0.0, 0.0, 0.0, 0.0, 0.00092, 0.00052, 0.00065, 9e-05, 0.0, 0.0, 0.0, 0.00205, 0.0, 0.0, 0.0, 0.0017, 8e-05, 0.00083, 0.00251, 0.00059, 0.0002, 0.0, 0.0, 0.00064, 0.0, 0.0002, 0.0, 0.0005, 0.0, 0.0, 0.00314, 0.00065, 0.0, 0.0, 0.00012, 0.00083, 0.00079, 0.00027, 0.00053, 0.0, 0.0012, 0.00075, 0.0, 0.0, 0.00194, 0.0, 0.0, 0.00051, 0.00142, 0.0, 5e-05, 0.00248, 0.00204, 0.00102, 0.00027, 4e-05, 0.00122, 2e-05, 0.00027, 0.00044, 0.0, 0.0, 0.0, 0.00175, 0.00083, 0.00087, 0.00116, 0.00081, 0.0, 0.0, 0.0, 0.00104, 0.0, 0.00013, 9e-05, 0.00048, 0.00013, 0.0, 9e-05, 0.00037, 1e-05, 8e-05, 6e-05, 0.00062, 0.0, 0.0, 0.00046, 1e-05, 0.00012, 2e-05, 0.00053, 7e-05, 0.0, 0.00134, 0.0, 0.00041, 0.00035, 0.00018, 0.00071, 0.00126, 0.00087, 0.00089, 0.00073, 0.00093, 0.00123, 0.00122, 0.0, 0.00056, 0.0, 0.0, 0.0009, 0.00077, 0.0002, 0.00013, 0.00068, 0.00068, 0.0, 0.00011, 0.0, 0.00079, 0.0, 0.0, 0.00011, 0.00062, 7e-05, 2e-05, 2e-05, 0.00131, 0.0009, 0.00079, 0.00031, 0.00033, 0.00023, 0.00015, 0.00045, 0.00024, 0.0, 0.00013, 0.00054, 0.00116, 0.0, 0.0, 0.00021, 0.00189, 0.0, 0.00021, 0.0, 0.00188, 0.0, 0.0, 0.0, 0.00076, 0.001, 0.00097, 0.00017, 0.00046, 0.0, 0.0, 0.00064, 0.00056, 0.00013, 0.0, 0.00055, 0.00111, 4e-05, 4e-05, 0.0, 0.00076, 0.0, 0.00031, 0.00017, 0.00188, 0.00031, 0.0, 0.00017, 0.00148, 0.00211, 0.00138, 0.0001, 0.00052, 0.00027, 0.00012, 0.00087, 0.00068, 0.0, 4e-05, 0.00071, 0.00059, 0.0, 2e-05, 1e-05, 0.0007, 0.0, 1e-05, 2e-05, 0.00109, 0.00023, 5e-05, 5e-05, 0.00094, 0.00072, 0.00061, 0.0, 0.00028, 2e-05, 1e-05, 0.00081, 0.00028, 0.0, 0.0, 0.00081, 0.00123, 0.0, 0.00027, 0.00027, 0.00181, 0.00046, 0.00026, 0.0, 0.00706, 0.00046, 0.0, 0.00026, 0.00012, 0.00061, 0.00039, 0.00034, 0.00048, 0.00025, 0.00021, 0.00172, 0.00073, 0.00079, 0.00778, 0.00253, 0.00016, 0.00317, 0.0, 0.00094, 0.0, 0.00013, 0.00037, 0.00267, 0.00066, 0.00046, 0.0, 0.00013, 0.0, 0.00037, 0.0011, 0.00128, 0.00236, 0.00124, 0.0, 0.0, 0.00518, 0.00067, 3e-05, 3e-05, 2e-05, 0.00095, 3e-05, 2e-05, 3e-05, 0.00079, 0.0, 0.00014, 0.00014, 0.00176, 0.00103, 0.00074, 0.00035, 0.0, 0.0, 0.0, 0.00121, 3e-05, 0.00019, 0.00016, 0.00112, 0.00114, 0.0, 0.0, 0.0, 0.0, 0.0, 0.00109, 0.0, 0.0, 0.0, 0.0, 0.00124, 0.0036, 0.00357, 0.0, 0.0, 0.00357, 0.0036, 0.0, 0.0, 0.00066, 0.00052, 0.00093, 0.00079])\n",
"\n"
]
}
],
"source": [
"print(f'Noise learner result contains {len(noise_model.data)} entries'\\\n",
" f' and has the following type:\\n {type(noise_model)}\\n')\n",
"print(f'Each element of `NoiseLearnerResult` then contains'\\\n",
" f' an object of type:\\n {type(noise_model.data[0])}\\n')\n",
"print(f'And each of these `LayerError` objects possess the'\\\n",
" f' following data: \\n{noise_model.data[0].error}\\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",
"There are a few options available to input into a `NoiseLearner` object when instantiated. These 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": null,
"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,\n",
" num_randomizations = 32,\n",
" 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 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. For example, you can pass the noise model to the `estimator.options` attribute directly"
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "d8b504c1-17ad-4e23-b508-eac1955bd1d6",
"metadata": {},
"outputs": [],
"source": [
"estimator = EstimatorV2(mode=backend)\n",
"estimator.options.resilience.layer_noise_model = noise_model"
]
},
{
"cell_type": "markdown",
"id": "3892248e-5221-455d-ba74-e75ffb917a0e",
"metadata": {},
"source": [
"via a `ResilienceOptionsV2` object before instantiating an Estimator primitive"
]
},
{
"cell_type": "code",
"execution_count": 34,
"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": "markdown",
"id": "199d18c8-5eba-44db-a6cf-a9a7a8018734",
"metadata": {},
"source": [
"or by passing in an appropriately formatted dictionary"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "6dcb70fe-e291-4b5a-a79b-14cace921905",
"metadata": {},
"outputs": [],
"source": [
"# Specify options via a dictionary\n",
"options_dict = {'resilience_level':2,\n",
" 'resilience':{'layer_noise_model':result}}\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
}

View File

@ -274,3 +274,5 @@ notifications:
- "@johannesgreiner"
- "@pacomf"
- "@Bagherpoor"
"docs/guides/noise-learning":
- "@kaelynj"

View File

@ -47,4 +47,5 @@ notebooks_that_submit_jobs = [
# memory on a reasonable device.
notebooks_no_mock = [
"docs/guides/hello-world.ipynb",
"docs/guides/noise-learning.ipynb"
]