430 lines
21 KiB
Plaintext
430 lines
21 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "dde95705",
|
||
"metadata": {},
|
||
"source": [
|
||
"# IBM Circuit function\n",
|
||
"\n",
|
||
"<Admonition type=\"note\">\n",
|
||
"Qiskit Functions are an experimental feature available only to IBM Quantum™ Premium Plan users. They are in preview release status and subject to change.\n",
|
||
"</Admonition>\n",
|
||
"\n",
|
||
"## Overview\n",
|
||
"\n",
|
||
"The IBM® Circuit function takes [abstract PUBs](./primitive-input-output) as inputs, and returns mitigated expectation values as outputs. This circuit function includes an automated and customized pipeline to enable researchers to focus on algorithm and application discovery."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "5f761442",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Description\n",
|
||
"\n",
|
||
"After submitting your PUB, your abstract circuits and observables are automatically transpiled, executed on hardware, and post-processed to return mitigated expectation values. To do so, this combines the following tools:\n",
|
||
"\n",
|
||
"- [Qiskit Transpiler Service](./qiskit-transpiler-service), including auto-selection of AI-driven and heuristic transpilation passes to translate your abstract circuits to [hardware-optimized ISA circuits](/guides/optimize-for-hardware)\n",
|
||
"- [Error suppression and mitigation required for utility-scale computation](./error-mitigation-and-suppression-techniques), including measurement and gate twirling, dynamical decoupling, Twirled Readout Error eXtinction (TREX), Zero-Noise Extrapolation (ZNE), and Probabilistic Error Amplification (PEA)\n",
|
||
"- [Qiskit Runtime Estimator](./get-started-with-primitives), to execute ISA PUBs on hardware and return mitigated expectation values\n",
|
||
"\n",
|
||
"![IBM Circuit function](/images/guides/ibm-circuit-function/ibm-circuit-function.svg)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "73390a19",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Get started"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "f46c531c",
|
||
"metadata": {},
|
||
"source": [
|
||
"Authenticate using your [IBM Quantum Platform API token](http://quantum.ibm.com/), and select the Qiskit Function as follows:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"id": "95a715d2",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
|
||
"\n",
|
||
"catalog = QiskitFunctionsCatalog()\n",
|
||
"function = catalog.load(\"ibm/circuit-function\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "e8837f5f",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Example\n",
|
||
"\n",
|
||
" To get started, try this basic example:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"id": "d56e1440",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"from qiskit.circuit.random import random_circuit\n",
|
||
"from qiskit_ibm_runtime import QiskitRuntimeService\n",
|
||
"\n",
|
||
"# You can skip this step if you have a target backend, e.g.\n",
|
||
"# backend_name = \"ibm_sherbrooke\"\n",
|
||
"# You'll need to specify the credentials when initializing QiskitRuntimeService, if they were not previously saved.\n",
|
||
"service = QiskitRuntimeService()\n",
|
||
"backend = service.least_busy(operational=True, simulator=False)\n",
|
||
"\n",
|
||
"circuit = random_circuit(num_qubits=2, depth=2, seed=42)\n",
|
||
"observable = \"Z\" * circuit.num_qubits\n",
|
||
"pubs = [(circuit, observable)]\n",
|
||
"\n",
|
||
"job = function.run(\n",
|
||
" # Use `backend_name=backend_name` if you didn't initialize a backend object\n",
|
||
" backend_name=backend.name,\n",
|
||
" pubs=pubs,\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "03998691",
|
||
"metadata": {},
|
||
"source": [
|
||
"Check your Qiskit Function workload's [status](/guides/functions#check-job-status) or return [results](/guides/functions#retrieve-results) as follows:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"id": "856fe992",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"QUEUED\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"print(job.status())\n",
|
||
"result = job.result()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "eda36356",
|
||
"metadata": {},
|
||
"source": [
|
||
"The results have the same format as an [Estimator result](https://docs.quantum.ibm.com/guides/primitive-input-output#estimator-output):"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"id": "765f3207",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"The result of the submitted job had 1 PUB\n",
|
||
"\n",
|
||
"The associated PubResult of this job has the following DataBins:\n",
|
||
" DataBin(evs=np.ndarray(<shape=(), dtype=float64>), stds=np.ndarray(<shape=(), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(), dtype=float64>))\n",
|
||
"\n",
|
||
"And this DataBin has attributes: dict_keys(['evs', 'stds', 'ensemble_standard_error'])\n",
|
||
"The expectation values measured from this PUB are: \n",
|
||
"0.07302231237322515\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"print(f\"The result of the submitted job had {len(result)} PUB\\n\")\n",
|
||
"print(\n",
|
||
" f\"The associated PubResult of this job has the following DataBins:\\n {result[0].data}\\n\"\n",
|
||
")\n",
|
||
"print(f\"And this DataBin has attributes: {result[0].data.keys()}\")\n",
|
||
"print(\n",
|
||
" f\"The expectation values measured from this PUB are: \\n{result[0].data.evs}\"\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "73815ae7",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Inputs\n",
|
||
"\n",
|
||
"See the following table for all input parameters the IBM Circuit function accepts. The subsequent [Options](#options) section goes into more details about the available `options`."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "19eafc4c",
|
||
"metadata": {},
|
||
"source": [
|
||
"| Name | Type | Description | Required | Default | Example |\n",
|
||
"|-----------|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|--------------------------------------------------------------------------|------------------------------------------|\n",
|
||
"| backend_name | str | Name of the backend to make the query. | Yes | N/A | `ibm_fez` |\n",
|
||
"| pubs | Iterable[EstimatorPubLike] | An iterable of abstract PUB-like (primitive unified bloc) objects, such as tuples `(circuit, observables)` or `(circuit, observables, parameter_values)`. See [Overview of PUBs](/guides/primitive-input-output#overview-of-pubs) for more information. The circuits can be abstract (non-ISA). | Yes | N/A | (circuit, observables, parameter_values) |\n",
|
||
"| options | dict | Input options. See the **Options** section for more details. | No | See the **Options** section for details. | `{\"optimization_level\": 3}` |\n",
|
||
"| instance | str | The hub/group/project to use in that format. | No | One is randomly picked if your account has access to multiple instances. | `hub1/group1/project1` |"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "a1072bd6",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Options\n",
|
||
"\n",
|
||
"#### Structure\n",
|
||
"\n",
|
||
"Similar to Qiskit Runtime primitives, options for IBM Circuit function can be specified as a nested dictionary. Commonly used options, such as ``optimization_level`` and ``mitigation_level``, are at the first level. Other, more advanced options are grouped into different categories, such as ``resilience``.\n",
|
||
"\n",
|
||
"#### Defaults\n",
|
||
"\n",
|
||
"If you do not specify a value for an option, the default value specified by the service is used.\n",
|
||
"\n",
|
||
"#### Mitigation level\n",
|
||
"\n",
|
||
"IBM Circuit function also supports `mitigation_level`. The mitigation level specifies how much error suppression and mitigation to apply to the job. Higher levels generate more accurate results, at the expense of longer processing times. The degree of error reduction depends on the method applied. The mitigation level abstracts the detailed choice of error mitigation and suppression methods to allow users to reason about the cost/accuracy trade-off appropriate to their application. The following table shows the corresponding methods for each level.\n",
|
||
"\n",
|
||
"<Admonition type=\"note\">\n",
|
||
"While the names are similar, `mitigation_level` applies different techniques than the ones used by Estimator’s `resilience_level`.\n",
|
||
"</Admonition>\n",
|
||
"\n",
|
||
"Similar to ``resilience_level`` in Qiskit Runtime Estimator, ``mitigation_level`` specifies a base set of curated options. Any options you manually specify in addition to the mitigation level are applied on top of the base set of options defined by the mitigation level. Therefore, in principle, you could set the mitigation level to 1, but then turn off measurement mitigation, although this is not advised.\n",
|
||
"\n",
|
||
"| **Mitigation Level** | **Technique** |\n",
|
||
"|:-:|:-:|\n",
|
||
"| 1 [Default] | Dynamical decoupling + measurement twirling + TREX |\n",
|
||
"| 2 | Level 1 + gate twirling + ZNE via gate folding |\n",
|
||
"| 3 | Level 1 + gate twirling + ZNE via PEA |\n",
|
||
"\n",
|
||
"The following example demonstrates setting the mitigation level:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"id": "13443be4",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"options = {\"mitigation_level\": 2}\n",
|
||
"\n",
|
||
"job = function.run(backend_name=backend.name, pubs=pubs, options=options)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "c823d7b3",
|
||
"metadata": {},
|
||
"source": [
|
||
"#### All available options\n",
|
||
"\n",
|
||
"In addition to `mitigation_level`, the IBM Circuit function also provides a select number of advanced options that allow you to fine-tune the cost/accuracy trade-off. The following table shows all the available options:\n",
|
||
"\n",
|
||
"| Option | Sub-option | Sub-sub-option | Description | Choices | Default |\n",
|
||
"|-|-|-|-|-|-|\n",
|
||
"| default_precision | | | The default precision to use for any PUB or `run()`<br/>call that does not specify one.<br/>Each input PUB can specify its own precision. If the `run()` method is given a precision, then that value is used for all PUBs in the `run()` call that do not specify their own. | float > 0 | 0.015625 |\n",
|
||
"| max_execution_time | | | Maximum execution time in seconds, which is based<br/>on QPU usage (not wall clock time). QPU usage is the<br/>amount of time that the QPU is dedicated to processing your job. If a job exceeds this time limit, it is forcibly canceled. | Integer number of seconds in the range [1, 10800] | |\n",
|
||
"| mitigation_level | | | How much error suppression and mitigation to apply. Refer to the [Mitigation level](#mitigation-level) section for more information about the methods used at each level. | 1 / 2 / 3 | 1 |\n",
|
||
"| optimization_level | | | How much optimization to perform on the circuits. [Higher levels](/guides/set-optimization) generate more optimized circuits, at the expense of longer transpilation time. | 0 / 1 / 2 / 3 | 2 |\n",
|
||
"| dynamical_decoupling | enable | | Whether to enable dynamical decoupling. Refer to [Error suppression and mitigation techniques](/guides/error-mitigation-and-suppression-techniques#dynamical-decoupling) for the explanation of the method. | True/False | True |\n",
|
||
"| | sequence_type | | Which dynamical decoupling sequence to use.<br/>* `XX`: use the sequence `tau/2 - (+X) - tau - (+X) - tau/2`<br/>* `XpXm`: use the sequence `tau/2 - (+X) - tau - (-X) - tau/2`<br/>* `XY4`: use the sequence<br/>`tau/2 - (+X) - tau - (+Y) - tau (-X) - tau - (-Y) - tau/2` | 'XX'/'XpXm'/'XY4' | 'XX' |\n",
|
||
"| twirling | enable_gates | | Whether to apply 2-qubit Clifford gate twirling. | True/False | False |\n",
|
||
"| | enable_measure | | Whether to enable twirling of measurements. | True/False | True |\n",
|
||
"| resilience | measure_mitigation | | Whether to enable TREX measurement error mitigation method. Refer to [Error suppression and mitigation techniques](/guides/error-mitigation-and-suppression-techniques#twirled-readout-error-extinction-trex) for the explanation of the method. | True/False | True |\n",
|
||
"| | zne_mitigation | | Whether to turn on Zero Noise Extrapolation error mitigation method. Refer to [Error suppression and mitigation techniques](/guides/error-mitigation-and-suppression-techniques#zero-noise-extrapolation-zne) for the explanation of the method. | True/False | False |\n",
|
||
"| | zne | amplifier | Which technique to use for amplifying noise. One of: <br/> - `gate_folding` (default) uses 2-qubit gate folding to amplify noise. If the noise factor requires amplifying only a subset of the gates, then these gates are chosen randomly.<br/><br/> - `gate_folding_front` uses 2-qubit gate folding to amplify noise. If the noise factor requires amplifying only a subset of the gates, then these gates are selected from the front of the topologically ordered DAG circuit.<br/><br/> - `gate_folding_back` uses 2-qubit gate folding to amplify noise. If the noise factor requires amplifying only a subset of the gates, then these gates are selected from the back of the topologically ordered DAG circuit.<br/><br/> - `pea` uses a technique called Probabilistic error amplification (PEA) to amplify noise. Refer to [Error suppression and mitigation techniques](/guides/error-mitigation-and-suppression-techniques#probabilistic-error-amplification-pea) for the explanation of the method. | gate_folding / gate_folding_front / gate_folding_back / pea | gate_folding |\n",
|
||
"| | | noise_factors | Noise factors to use for noise amplification. | list of floats; each float >= 1 | (1, 1.5, 2) for PEA, and (1, 3, 5) otherwise. |\n",
|
||
"| | | extrapolator | Noise factors to evaluate the fit extrapolation models at. This option does not affect execution or model fitting in any way; it only determines the points at which the `extrapolator`s are evaluated to be returned in the data fields called `evs_extrapolated` and `stds_extrapolated`. | one or more of `exponential`,`linear`, `double_exponential`,`polynomial_degree_(1 <= k <= 7)` | (`exponential`, `linear`) |\n",
|
||
"| | pec_mitigation | | Whether to turn on Probabilistic Error Cancellation error mitigation method. Refer to [Error suppression and mitigation techniques](/guides/error-mitigation-and-suppression-techniques#probabilistic-error-cancellation-pec) for the explanation of the method. | True/False | False |\n",
|
||
"| | pec | max_overhead | The maximum circuit sampling overhead allowed, or `None` for no maximum. | None/ integer >1 | 100 |\n",
|
||
"\n",
|
||
"In the following example, setting the mitigation level to 1 initially turns off ZNE mitigation, but setting `zne_mitigation` to `True` overrides the relevent setup from `mitigation_level`."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"id": "b2632bd9",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"options = {\"mitigation_level\": 1, \"resilience\": {\"zne_mitigation\": True}}"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "997c3779",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Outputs"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "75d7cbba",
|
||
"metadata": {},
|
||
"source": [
|
||
"The output of a Circuit function is a [PrimitiveResult](/api/qiskit/qiskit.primitives.PrimitiveResult), which contains two fields:\n",
|
||
"\n",
|
||
"- One or more [PubResult](/api/qiskit/qiskit.primitives.PubResult) objects. These can be indexed directly from the `PrimitiveResult`.\n",
|
||
"\n",
|
||
"- Job-level metadata.\n",
|
||
"\n",
|
||
"Each `PubResult` contains a `data` and a `metadata` field.\n",
|
||
"\n",
|
||
"- The `data` field contains at least an array of expectation values (`PubResult.data.evs`) and an array of standard errors (`PubResult.data.stds`). It can also contain more data, depending on the options used.\n",
|
||
"\n",
|
||
"- The `metadata` field contains PUB-level metadata (`PubResult.metadata`).\n",
|
||
"\n",
|
||
"The following code snippet describes the `PrimitiveResult` (and associated `PubResult`) format."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"id": "6e3f86aa",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"The result of the submitted job had 1 PUB\n",
|
||
"The expectation values measured from this PUB are: \n",
|
||
"0.07302231237322515\n",
|
||
"And the associated metadata is: \n",
|
||
"{'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"print(f\"The result of the submitted job had {len(result)} PUB\")\n",
|
||
"print(\n",
|
||
" f\"The expectation values measured from this PUB are: \\n{result[0].data.evs}\"\n",
|
||
")\n",
|
||
"print(f\"And the associated metadata is: \\n{result[0].metadata}\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "02295f5d",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Fetching error messages\n",
|
||
"\n",
|
||
"If your workload status is `ERROR`, use `job.result()` to fetch the error message to help debug as follows:"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"id": "4070e592",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Traceback (most recent call last):\n",
|
||
" File \"/runner/runner.py\", line 10, in run\n",
|
||
" func = CircuitFunction(**arguments)\n",
|
||
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
|
||
" File \"/runner/circuit_function/circuit_function.py\", line 86, in __init__\n",
|
||
" self._backend = self._service.backend(\n",
|
||
" ^^^^^^^^^^^^^^^^^^^^^^\n",
|
||
" File \"/usr/local/lib/python3.11/site-packages/qiskit_ibm_runtime/qiskit_runtime_service.py\", line 787, in backend\n",
|
||
" backends = self.backends(name, instance=instance, use_fractional_gates=use_fractional_gates)\n",
|
||
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
|
||
" File \"/usr/local/lib/python3.11/site-packages/qiskit_ibm_runtime/qiskit_runtime_service.py\", line 536, in backends\n",
|
||
" raise QiskitBackendNotFoundError(\"No backend matches the criteria.\")\n",
|
||
"qiskit.providers.exceptions.QiskitBackendNotFoundError: 'No backend matches the criteria.'\n",
|
||
"\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"job = function.run(\n",
|
||
" backend_name=\"bad_backend_name\", pubs=pubs, options=options\n",
|
||
")\n",
|
||
"\n",
|
||
"print(job.result())"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "32db1269",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Get support\n",
|
||
"\n",
|
||
"Reach out to [IBM Quantum support](https://docs.quantum.ibm.com/support), and include the following information:\n",
|
||
"\n",
|
||
"- Qiskit Function Job ID (`qiskit-ibm-catalog`), `job.job_id`\n",
|
||
"- A detailed description of the issue\n",
|
||
"- Any relevant error messages or codes\n",
|
||
"- Steps to reproduce the issue"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "0439eef4",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Next steps\n",
|
||
"\n",
|
||
"<Admonition type=\"tip\" title=\"Recommendations\">\n",
|
||
"\n",
|
||
"- Try the [Building workflows with the IBM Circuit function](https://learning.quantum.ibm.com/tutorial/building-workflows-with-the-ibm-circuit-function) tutorial.\n",
|
||
"\n",
|
||
"</Admonition>"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"description": "Explore how to use the IBM Circuit function, with AI-driven transpilation and advanced error mitigation (TREX, ZNE, PEA)",
|
||
"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": "IBM Circuit function"
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|