Add tutorials to notebook tests (#1155)

Adds the new tutorial notebooks to the same tests as the documentation
notebooks. Most tutorials run jobs on IBM Quantum so will only be tested
fortnightly in the cron job workflow.

Part of #1136
This commit is contained in:
Frank Harkins 2024-04-11 14:07:00 +01:00 committed by GitHub
parent d96bd1ac09
commit 0bcf81330b
12 changed files with 103 additions and 55 deletions

View File

@ -14,6 +14,7 @@ name: Test notebooks
on:
pull_request:
paths:
- "tutorials/**/*.ipynb"
- "docs/**/*.ipynb"
- "!docs/api/**/*"
workflow_dispatch:
@ -28,7 +29,7 @@ jobs:
id: all-changed-files
uses: tj-actions/changed-files@af2816c65436325c50621100d67f6e853cd1b0f1
with:
files: docs/**/*.ipynb
files: "{tutorials,docs}/**/*.ipynb"
separator: "\n"
- name: Check for notebooks that require Linux

View File

@ -6,4 +6,5 @@ ipykernel~=6.29.2
qiskit[all]~=1.0
qiskit-aer~=0.14.0.1
qiskit-ibm-runtime~=0.22.0
qiskit-ibm-provider~=0.10.0
squeaky==0.7.0

View File

@ -25,7 +25,7 @@ import nbformat
from qiskit_ibm_runtime import QiskitRuntimeService
from squeaky import clean_notebook
NOTEBOOKS_GLOB = "docs/**/*.ipynb"
NOTEBOOKS_GLOB = "{tutorials,docs}/**/*.ipynb"
NOTEBOOKS_EXCLUDE = [
"docs/api/**",
"**/.ipynb_checkpoints/**",
@ -33,6 +33,13 @@ NOTEBOOKS_EXCLUDE = [
NOTEBOOKS_THAT_SUBMIT_JOBS = [
"docs/start/hello-world.ipynb",
"docs/analyze/saving-and-retrieving.ipynb",
"tutorials/build-repitition-codes/notebook.ipynb",
"tutorials/chsh-inequality/notebook.ipynb",
"tutorials/grovers-algorithm/notebook.ipynb",
"tutorials/quantum-approximate-optimization-algorithm/notebook.ipynb",
"tutorials/repeat-until-success/notebook.ipynb",
"tutorials/submitting-transpiled-circuits/notebook.ipynb",
"tutorials/variational-quantum-eigensolver/notebook.ipynb",
]

View File

@ -9,7 +9,7 @@ setenv = PYDEVD_DISABLE_FILE_VALIDATION=1
commands = python scripts/nb-tester/test-notebook.py {posargs}
[testenv:lint]
commands = squeaky --check --no-advice {posargs:docs/}
commands = squeaky --check --no-advice {posargs:docs tutorials}
[testenv:fix]
commands = squeaky {posargs:docs/}
commands = squeaky {posargs:docs tutorials}

View File

@ -14,7 +14,7 @@
"\n",
"## Background\n",
"\n",
"To enable real-time quantum error correction (QEC), we require the capability to dynamically control quantum program flow during execution so that quantum gates may be conditioned on measurement results. In this tutorial, we will run the bit-flip code, which is a very simple form of QEC. We will demonstrate a dynamic quantum circuit that can protect an encoded qubit from a single bit-flip error, and then evaluate the performance of the bit-flip code. \n",
"To enable real-time quantum error correction (QEC), we require the capability to dynamically control quantum program flow during execution so that quantum gates may be conditioned on measurement results. In this tutorial, we will run the bit-flip code, which is a very simple form of QEC. We will demonstrate a dynamic quantum circuit that can protect an encoded qubit from a single bit-flip error, and then evaluate the performance of the bit-flip code.\n",
"\n",
"We can exploit additional ancilla qubits and entanglement to measure what are known as *stabilizers* that do not transform our encoded quantum information, while still informing us of some classes of errors that may have occurred. A quantum stabilizer code encodes $k$ logical qubits into $n$ physical qubits. Stabilizer codes critically focus on correcting a discrete error set with support from the Pauli group $\\Pi^n$. Assume the set of possible errors are $ \\epsilon \\subset \\Pi^n$. For example, in a bit-flip code with three qubits encoding the quantum state, we will have $\\epsilon = \\{IIX, IXI, XII\\}$. We can measure the stabilizers and observing their eigenvalues to dete"
]
@ -115,14 +115,14 @@
"\n",
"def measure_syndrome_bit(circuit, qreg_data, qreg_measure, creg_measure):\n",
" \"\"\"\n",
" Measure the syndrome by measuring the parity. \n",
" Measure the syndrome by measuring the parity.\n",
" We reset our ancilla qubits after measuring the stabilizer\n",
" so we can reuse them for repeated stabilizer measurements. \n",
" Because we have already observed the state of the qubit, \n",
" we can write the conditional reset protocol directly to \n",
" avoid another round of qubit measurement if we used \n",
" so we can reuse them for repeated stabilizer measurements.\n",
" Because we have already observed the state of the qubit,\n",
" we can write the conditional reset protocol directly to\n",
" avoid another round of qubit measurement if we used\n",
" the `reset` instruction.\n",
" \"\"\" \n",
" \"\"\"\n",
" circuit.cx(qreg_data[0], qreg_measure[0])\n",
" circuit.cx(qreg_data[1], qreg_measure[0])\n",
" circuit.cx(qreg_data[0], qreg_measure[1])\n",
@ -179,10 +179,10 @@
" circuit = initialize_qubits(circuit)\n",
" circuit = encode_bit_flip(circuit, state_data, ancillas_data)\n",
" circuit = measure_syndrome_bit(circuit, qreg_data, qreg_measure, creg_syndrome)\n",
" \n",
"\n",
" if apply_correction:\n",
" circuit = apply_correction_bit(circuit, qreg_data, creg_syndrome)\n",
" \n",
"\n",
" circuit = apply_final_readout(circuit, qreg_data, creg_data)\n",
" return circuit\n",
"\n",
@ -423,7 +423,7 @@
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
@ -437,7 +437,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3"
},
"vscode": {
"interpreter": {

View File

@ -13,9 +13,9 @@
"id": "fb089249",
"metadata": {},
"source": [
"In this tutorial, you will run an experiment on a quantum computer to demonstrate the violation of the CHSH inequality with the Estimator primitive. \n",
"In this tutorial, you will run an experiment on a quantum computer to demonstrate the violation of the CHSH inequality with the Estimator primitive.\n",
"\n",
"The CHSH inequality, named after the authors Clauser, Horne, Shimony, and Holt, is used to experimentally prove Bell's theorem (1969). This theorem asserts that local hidden variable theories cannot account for some consequences of entanglement in quantum mechanics. The violation of the CHSH inequality is used to show that quantum mechanics is incompatible with local hidden-variable theories. This is an important experiment for understanding the foundation of quantum mechanics. \n",
"The CHSH inequality, named after the authors Clauser, Horne, Shimony, and Holt, is used to experimentally prove Bell's theorem (1969). This theorem asserts that local hidden variable theories cannot account for some consequences of entanglement in quantum mechanics. The violation of the CHSH inequality is used to show that quantum mechanics is incompatible with local hidden-variable theories. This is an important experiment for understanding the foundation of quantum mechanics.\n",
"\n",
"The 2022 Nobel Prize for Physics was awarded to Alain Aspect, John Clauser and Anton Zeilinger in part for their pioneering work in quantum information science, and in particular, for their experiments with entangled photons demonstrating violation of Bells inequalities."
]
@ -152,7 +152,7 @@
"id": "1ab329f2",
"metadata": {},
"source": [
"### Create a parameterized CHSH circuit \n",
"### Create a parameterized CHSH circuit\n",
"\n",
"First, we write the circuit with the parameter $\\theta$, which we call `theta`. The [`Estimator` primitive](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.EstimatorV2) can enormously simplify circuit building and output analysis by directly providing expectation values of observables. Many problems of interest, especially for near-term applications on noisy systems, can be formulated in terms of expectation values. `Estimator` (V2) primitive can automatically change measurement basis based on the supplied observable."
]
@ -218,7 +218,7 @@
"id": "6e559aed",
"metadata": {},
"source": [
"### Observables \n",
"### Observables\n",
"\n",
"Now we need observables from which to compute the expectation values. In our case we are looking at orthogonal bases for each qubit, letting the parameterized $Y-$ rotation for the first qubit sweep the measurement basis nearly continuously with respect to the second qubit basis. We will therefore choose the observables $ZZ$, $ZX$, $XZ$, and $XX$."
]
@ -336,7 +336,7 @@
"id": "2d8ad9e1",
"metadata": {},
"source": [
"We can create a [Qiskit Runtime `Estimator`](https://docs.quantum.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.EstimatorV2) primitive to compute our expectation values. The `EstimatorV2.run()` method takes an iterable of `primitive unified blocs (PUBs)`. Each PUB is an iterable in the format `(circuit, observables, parameter_values: Optional, precision: Optional)`. "
"We can create a [Qiskit Runtime `Estimator`](https://docs.quantum.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.EstimatorV2) primitive to compute our expectation values. The `EstimatorV2.run()` method takes an iterable of `primitive unified blocs (PUBs)`. Each PUB is an iterable in the format `(circuit, observables, parameter_values: Optional, precision: Optional)`."
]
},
{
@ -487,7 +487,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
@ -501,7 +501,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
"version": "3"
},
"vscode": {
"interpreter": {

View File

@ -3,6 +3,7 @@
{
"attachments": {},
"cell_type": "markdown",
"id": "b27d7770-0fd4-4173-9b52-99a0898634db",
"metadata": {},
"source": [
"## What is it?\n",
@ -27,6 +28,7 @@
{
"attachments": {},
"cell_type": "markdown",
"id": "477a3b86-e25f-4966-ae9f-0831482d202f",
"metadata": {},
"source": [
"## Tour of the interface\n",
@ -65,12 +67,13 @@
"\n",
"11. **Visualizations** - Visualizations characterize your circuit as you build it. They use a single-shot statevector simulator, which is different from the system specified in the Setup and run settings. Note that the visualizations ignore any measurement operations you add. Sign in and click **Setup and run** to get results from the specified backend instead.\n",
"\n",
" To learn about the visualizations, see [Visualizations](#visualizations).\n"
" To learn about the visualizations, see [Visualizations](#visualizations)."
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "e9207850-523d-410b-9df4-27cd6b320e3e",
"metadata": {},
"source": [
"## Build, edit, and inspect quantum circuits\n",
@ -191,6 +194,7 @@
{
"attachments": {},
"cell_type": "markdown",
"id": "d106f427-c7f6-4c7e-9f5f-b7dfcca515cb",
"metadata": {},
"source": [
"### 3. Build your circuit with OpenQASM code\n",
@ -230,6 +234,7 @@
{
"attachments": {},
"cell_type": "markdown",
"id": "8b6551de-ad4e-4b95-bb8a-56b43575764e",
"metadata": {},
"source": [
"#### Create a custom operation in OpenQASM\n",
@ -284,6 +289,7 @@
{
"attachments": {},
"cell_type": "markdown",
"id": "d4ed95f2-15ad-4e9a-add3-57e227270a5d",
"metadata": {},
"source": [
"## Run circuits and view results\n",
@ -321,6 +327,7 @@
{
"attachments": {},
"cell_type": "markdown",
"id": "b37d5709-a82a-4453-9cba-6d3cd2b475aa",
"metadata": {},
"source": [
"## Visualizations\n",
@ -441,12 +448,13 @@
"\n",
"The statevector at the terminus of the above circuit. The color wheel maps phase angle to color. The output state is expressed as a list of complex numbers.\n",
"\n",
"The circuit puts the two qubits into the state $|\\psi\\rangle = (|00\\rangle + |01\\rangle+ |10\\rangle-|11\\rangle) / 2$. The computational basis states are $|00\\rangle$, $|10\\rangle$, $|01\\rangle$, and $|11\\rangle$. The magnitudes of the amplitudes are $1/2$, and the quantum phases with respect to the ground state are $0$ for $|01\\rangle$ and $|10\\rangle$, and $\\pi$ for $|11\\rangle$.\n"
"The circuit puts the two qubits into the state $|\\psi\\rangle = (|00\\rangle + |01\\rangle+ |10\\rangle-|11\\rangle) / 2$. The computational basis states are $|00\\rangle$, $|10\\rangle$, $|01\\rangle$, and $|11\\rangle$. The magnitudes of the amplitudes are $1/2$, and the quantum phases with respect to the ground state are $0$ for $|01\\rangle$ and $|10\\rangle$, and $\\pi$ for $|11\\rangle$."
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "9c47c5d8-7447-4cc3-b5bb-09cd2f1689bc",
"metadata": {},
"source": [
"## Composer operations glossary\n",
@ -744,10 +752,23 @@
}
],
"metadata": {
"language_info": {
"name": "python"
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"orig_nbformat": 4
"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"
}
},
"nbformat": 4,
"nbformat_minor": 2

View File

@ -8,7 +8,7 @@
"source": [
"## Background\n",
"\n",
"Amplitude amplification is a general purpose quantum algorithm, or subroutine, that can be used to obtain a quadratic speedup over a handful of classical algorithms. [Grovers algorithm](https://arxiv.org/abs/quant-ph/9605043) was the first to demonstrate this speedup on unstructured search problems. Formulating a Grover's search problem requires an oracle function that marks one or more computational basis states as the states we are interested in finding, and an amplification circuit that increases the amplitude of marked states, consequently suppressing the remaining states. \n",
"Amplitude amplification is a general purpose quantum algorithm, or subroutine, that can be used to obtain a quadratic speedup over a handful of classical algorithms. [Grovers algorithm](https://arxiv.org/abs/quant-ph/9605043) was the first to demonstrate this speedup on unstructured search problems. Formulating a Grover's search problem requires an oracle function that marks one or more computational basis states as the states we are interested in finding, and an amplification circuit that increases the amplitude of marked states, consequently suppressing the remaining states.\n",
"\n",
"Here, we demonstrate how to construct Grover oracles and use the `GroverOperator` from the Qiskit circuit library to easily set up a Grover's search instance. The runtime `Sampler` primitive allows seamless execution of Grover circuits."
]
@ -419,7 +419,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
@ -433,7 +433,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
"version": "3"
}
},
"nbformat": 4,

View File

@ -169,7 +169,7 @@
"id": "da92068c",
"metadata": {},
"source": [
"The previous image illustrates the ansatz in basic gates for clarity. However, it can be expressed in multiple levels of decomposition by changing the `reps` argument or by drawing the circuit without the `decompose` method. For example, the following representation directly shows the QAOA structure with the default `reps` value, which is `reps=1`. "
"The previous image illustrates the ansatz in basic gates for clarity. However, it can be expressed in multiple levels of decomposition by changing the `reps` argument or by drawing the circuit without the `decompose` method. For example, the following representation directly shows the QAOA structure with the default `reps` value, which is `reps=1`."
]
},
{
@ -366,7 +366,7 @@
"source": [
"Any classical optimizer can be used to minimize the cost function. On a real quantum system, an optimizer designed for non-smooth cost function landscapes usually does better. Here we use the [COBYLA routine from SciPy through the minimize function](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html).\n",
"\n",
"Because we are iteratively executing many calls to Runtime, we use a [`Session`](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.Session) to execute all calls within a single block. Moreover, for QAOA, the solution is encoded in the output distribution of the ansatz circuit bound with the optimal parameters from the minimization. Therefore, we will need a [`Sampler`](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.SamplerV2) primitive as well, and will instantiate it with the same [`Session`](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.Session).\n"
"Because we are iteratively executing many calls to Runtime, we use a [`Session`](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.Session) to execute all calls within a single block. Moreover, for QAOA, the solution is encoded in the output distribution of the ansatz circuit bound with the optimal parameters from the minimization. Therefore, we will need a [`Sampler`](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.SamplerV2) primitive as well, and will instantiate it with the same [`Session`](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.Session)."
]
},
{
@ -658,7 +658,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
@ -672,7 +672,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
"version": "3"
}
},
"nbformat": 4,

View File

@ -10,9 +10,9 @@
"source": [
"# Repeat until success\n",
"\n",
"## Background \n",
"## Background\n",
"\n",
"This tutorial demonstrates the current capabilities of IBM dynamic-circuit backends to use mid-circuit measurements to produce a circuit that repeatedly attempts its setup until a syndrome measurement reveals that it has been successful. \n",
"This tutorial demonstrates the current capabilities of IBM dynamic-circuit backends to use mid-circuit measurements to produce a circuit that repeatedly attempts its setup until a syndrome measurement reveals that it has been successful.\n",
"\n",
"We will build an abstract circuit that uses the non-parametrized gate set $\\{H,\\,X,\\,S,\\,\\text{Toffoli}\\}$ to construct a heralded $R_X(\\theta)$ gate on a target qubit, where $\\theta$ satisfies $\\cos\\theta = \\frac35$. Each iteration of the circuit only has a finite chance of success, but successes are heralded, so we will use our dynamic-circuit capabilities to repeat the setup until it succeeds."
]
@ -402,13 +402,13 @@
" state.\"\"\"\n",
" successes = collections.defaultdict(int)\n",
" failures = collections.defaultdict(int)\n",
" \n",
"\n",
" for key, value in counts.items():\n",
" if key.endswith(\"00\"):\n",
" successes[key[0]] += value\n",
" else:\n",
" failures[key[0]] += value\n",
" \n",
"\n",
" return successes, failures"
]
},
@ -511,7 +511,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
@ -525,7 +525,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3"
},
"vscode": {
"interpreter": {

View File

@ -2,6 +2,7 @@
"cells": [
{
"cell_type": "markdown",
"id": "96e7739a-b193-4286-be05-d7416da3cb38",
"metadata": {},
"source": [
"# Submit pre-transpiled circuits\n",
@ -12,12 +13,13 @@
"\n",
"For example, we may know better than the transpiler in some cases, or want to target a specific subset of qubits on a specific device. In this tutorial, we'll disable automatic transpilation to test the performance of different transpiler settings. This example will take you through the full process of creating, transpiling, and submitting circuits.\n",
"\n",
"## Setup\n"
"## Setup"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "5bd13972-0a36-4d5d-9d04-6817fbf73203",
"metadata": {},
"outputs": [],
"source": [
@ -41,6 +43,7 @@
{
"cell_type": "code",
"execution_count": 3,
"id": "86d62a41-4c55-4cd3-be4e-22d64be62f91",
"metadata": {},
"outputs": [
{
@ -63,16 +66,18 @@
},
{
"cell_type": "markdown",
"id": "aa76326e-48ee-4db1-83d0-0432cf9d4514",
"metadata": {},
"source": [
"## Step 1: Map classical inputs to a quantum problem\n",
"\n",
"In the following code cell, we create a small circuit that our transpiler will try to optimize. In this example, we create a circuit that carries out Grover's algorithm, with an oracle that marks the state `111`. We then simulate the ideal distribution (what we'd expect to measure if we ran this on a perfect quantum computer, an infinite number of times) for comparison later.\n"
"In the following code cell, we create a small circuit that our transpiler will try to optimize. In this example, we create a circuit that carries out Grover's algorithm, with an oracle that marks the state `111`. We then simulate the ideal distribution (what we'd expect to measure if we ran this on a perfect quantum computer, an infinite number of times) for comparison later."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "d0f2ea04-1c01-4bd4-97f1-ae82c6163e0d",
"metadata": {},
"outputs": [
{
@ -99,6 +104,7 @@
{
"cell_type": "code",
"execution_count": 5,
"id": "e9dffe14-838c-4943-acd5-112183137b30",
"metadata": {},
"outputs": [
{
@ -121,18 +127,20 @@
},
{
"cell_type": "markdown",
"id": "10904031-f64b-420a-aa02-00878e003895",
"metadata": {},
"source": [
"## Step 2: Optimize problem for quantum execution.\n",
"\n",
"Next, we transpile the circuits for our backend. We're going to compare the performance of the transpiler with `optimization_level` set to `0` (lowest) against `3` (highest). The lowest optimization level just does the bare minimum needed to get the circuit running on the device; it maps the circuit qubits to the device qubits, and adds swaps gates to allow all 2-qubit operations. The highest optimization level is much smarter and uses lots of tricks to reduce the overall gate count. Since multi-qubit gates have high error rates, and qubits decohere over time, the shorter circuits should give better results.\n",
"\n",
"In the following cell, we transpile `qc` for both values of `optimization_level`, print the number of CNOT gates, and add the transpiled circuits to a list. Some of the transpiler's algorithms are randomized, so we set a seed for reproducibility.\n"
"In the following cell, we transpile `qc` for both values of `optimization_level`, print the number of CNOT gates, and add the transpiled circuits to a list. Some of the transpiler's algorithms are randomized, so we set a seed for reproducibility."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "70f8abdd-9c8b-481d-8fea-8d50b1771be0",
"metadata": {},
"outputs": [
{
@ -157,16 +165,18 @@
},
{
"cell_type": "markdown",
"id": "46890930-54c4-4eee-9e07-d0acd74f7807",
"metadata": {},
"source": [
"Since CNOTs usually have a high error rate, the circuit transpiled with `optimization_level=3` should perform much better.\n",
"\n",
"Another way we can improve performance is through [dynamic decoupling](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-provider/qiskit_ibm_provider.transpiler.passes.scheduling.PadDynamicalDecoupling#paddynamicaldecoupling), where we apply a sequence of gates to idling qubits. This cancels out some unwanted interactions with the environment. In the following cell, we add dynamic decoupling to the circuit transpiled with `optimization_level=3`, and add it to our list.\n"
"Another way we can improve performance is through [dynamic decoupling](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-provider/qiskit_ibm_provider.transpiler.passes.scheduling.PadDynamicalDecoupling#paddynamicaldecoupling), where we apply a sequence of gates to idling qubits. This cancels out some unwanted interactions with the environment. In the following cell, we add dynamic decoupling to the circuit transpiled with `optimization_level=3`, and add it to our list."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "e9d91b65-4a32-4996-82e8-824dbd22567f",
"metadata": {},
"outputs": [],
"source": [
@ -194,6 +204,7 @@
{
"cell_type": "code",
"execution_count": 8,
"id": "c5e9a2a5-01aa-48be-89c4-aea6d91bdcc4",
"metadata": {},
"outputs": [
{
@ -214,18 +225,20 @@
},
{
"cell_type": "markdown",
"id": "215dff39-5d47-4479-a216-b3d2bfc174e4",
"metadata": {},
"source": [
"## Step 3: Execute using Qiskit Primitives.\n",
"\n",
"At this point, we have a list of circuits transpiled for our system. In the following cell, we create an instance of the sampler primitive, and start a batched job using the context manager (`with ...:`), which automatically opens and closes the Batch for us. This is where we pass the `skip_transpilation=True` argument.\n",
"\n",
"Within the context manager, we sample the circuits and store the results to `result`.\n"
"Within the context manager, we sample the circuits and store the results to `result`."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "74437abd-fca9-4d5b-bf15-0055498690ae",
"metadata": {},
"outputs": [],
"source": [
@ -241,16 +254,18 @@
},
{
"cell_type": "markdown",
"id": "edbf6c8f-786a-4e73-8524-fb608b8b3e87",
"metadata": {},
"source": [
"## Step 4: Post-process, return result in classical format.\n",
"\n",
"Finally, we can plot the results from the device runs against the ideal distribution. You can see the results with `optimization_level=3` are closer to the ideal distribution due to the lower gate count, and `optimization_level=3 + dd` is even closer due to the dynamic decoupling we applied.\n"
"Finally, we can plot the results from the device runs against the ideal distribution. You can see the results with `optimization_level=3` are closer to the ideal distribution due to the lower gate count, and `optimization_level=3 + dd` is even closer due to the dynamic decoupling we applied."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "c4f72f53-b5f7-451f-8713-fa2f563aa90f",
"metadata": {},
"outputs": [
{
@ -281,14 +296,16 @@
},
{
"cell_type": "markdown",
"id": "ca9c0298-b80e-4154-b56e-2466f765b9e2",
"metadata": {},
"source": [
"We can confirm this by computing the [Hellinger fidelity](https://docs.quantum-computing.ibm.com/api/qiskit/quantum_info) between each set of results and the ideal distribution (higher is better, and 1 is perfect fidelity).\n"
"We can confirm this by computing the [Hellinger fidelity](https://docs.quantum-computing.ibm.com/api/qiskit/quantum_info) between each set of results and the ideal distribution (higher is better, and 1 is perfect fidelity)."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "1754bad6-6756-4f97-949e-7ea8e25debc9",
"metadata": {},
"outputs": [
{
@ -311,6 +328,7 @@
{
"cell_type": "code",
"execution_count": 12,
"id": "df6cc2cf-1eb7-40f7-9cf6-4dac11fd7506",
"metadata": {},
"outputs": [
{
@ -333,6 +351,7 @@
{
"cell_type": "code",
"execution_count": 13,
"id": "65d54642-6d16-4c36-b03e-7618db856911",
"metadata": {},
"outputs": [
{
@ -355,7 +374,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "env",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
@ -369,7 +388,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3"
}
},
"nbformat": 4,

View File

@ -16,8 +16,8 @@
" 1. Hamiltonian and ansatz (problem specification)\n",
" 2. Qiskit Runtime estimator\n",
" 3. Classical optimizer\n",
" \n",
"Although the Hamiltonian and ansatz require domain specific knowledge to construct, these details are immaterial to the Runtime, and we can execute a wide class of VQE problems in the same manner. "
"\n",
"Although the Hamiltonian and ansatz require domain specific knowledge to construct, these details are immaterial to the Runtime, and we can execute a wide class of VQE problems in the same manner."
]
},
{
@ -334,7 +334,7 @@
"source": [
"### Creating a callback function\n",
"\n",
"Callback functions are a standard way for users to obtain additional information about the status of an iterative algorithm. The standard SciPy callback routine allows for returning only the interim vector at each iteration. However, it is possible to do much more than this. Here, we show how to use a mutable object, such as a dictionary, to store the current vector at each iteration, for example in case we need to restart the routine due to failure, and also return the current iteration number and average time per iteration. "
"Callback functions are a standard way for users to obtain additional information about the status of an iterative algorithm. The standard SciPy callback routine allows for returning only the interim vector at each iteration. However, it is possible to do much more than this. Here, we show how to use a mutable object, such as a dictionary, to store the current vector at each iteration, for example in case we need to restart the routine due to failure, and also return the current iteration number and average time per iteration."
]
},
{
@ -452,7 +452,6 @@
"id": "67d09ca9",
"metadata": {},
"source": [
"\n",
"Because we are sending a large number of jobs that we would like to execute together, we use a [`Session`](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.Session) to execute all the generated circuits in one block. Here `args` is the standard SciPy way to supply the additional parameters needed by the cost function."
]
},
@ -671,7 +670,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
@ -685,7 +684,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
"version": "3"
}
},
"nbformat": 4,