diff --git a/docs/tutorials/combine-error-mitigation-techniques.ipynb b/docs/tutorials/combine-error-mitigation-techniques.ipynb
index 65e36462c8d..51229cc8904 100644
--- a/docs/tutorials/combine-error-mitigation-techniques.ipynb
+++ b/docs/tutorials/combine-error-mitigation-techniques.ipynb
@@ -12,18 +12,32 @@
"\n",
"\n",
"# Combine error mitigation options with the Estimator primitive\n",
- "*Usage estimate: Seven minutes on a Heron r2 processor (NOTE: This is an estimate only. Your runtime might vary.)*"
+ "*Usage estimate: 7 minutes on a Heron r2 processor (NOTE: This is an estimate only. Your runtime might vary.)*"
]
},
{
"cell_type": "markdown",
- "id": "95263dce-783f-48a4-88f7-45426dfd5a49",
- "metadata": {
- "tags": [
- "version-info"
- ]
- },
- "source": []
+ "id": "39ba4396-9111-4421-9371-542f067bc816",
+ "metadata": {},
+ "source": [
+ "## Learning outcomes\n",
+ "\n",
+ "We suggest that users are familiar with the following topics before going through this tutorial:\n",
+ "- The basics of dynamical decoupling, measurement error mitigation, gate twirling, and zero-noise extrapolation, as described in this [guide](/docs/guides/error-mitigation-and-suppression-techniques)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b27cb482-b77a-4953-a0a4-39df33896d12",
+ "metadata": {},
+ "source": [
+ "## Prerequisites\n",
+ "\n",
+ "After going through this tutorial, users should understand:\n",
+ "\n",
+ "- How the aforementioned error mitigation techniques are selectively implemented on hardware.\n",
+ "- How they compare in terms of their ability to mitigate hardware noise."
+ ]
},
{
"cell_type": "markdown",
@@ -32,14 +46,20 @@
"source": [
"## Background\n",
"\n",
- "This walkthrough explores the error suppression and error mitigation options available with the Estimator primitive from Qiskit Runtime. You will construct a circuit and observable and submit jobs using the Estimator primitive using different combinations of error mitigation settings. Then, you will plot the results to observe the effects of the various settings. Most of the examples use a 10-qubit circuit to make visualizations easier, and at the end, you can scale up the workflow to 50 qubits.\n",
- "\n",
- "These are the error suppression and mitigation options you will use:\n",
+ "This tutorial explores the error suppression and error mitigation options available with the Estimator primitive from Qiskit Runtime. This tutorial shows how to implement each of the follow methods individually:\n",
"\n",
"- Dynamical decoupling\n",
"- Measurement error mitigation\n",
"- Gate twirling\n",
- "- Zero-noise extrapolation (ZNE)"
+ "- Zero-noise extrapolation (ZNE)\n",
+ "\n",
+ "Note that an alternative to implementing these techniques individually is to implement them using a [resilience level](https://quantum.cloud.ibm.com/docs/en/guides/configure-error-mitigation#example), whereby `resilience_level` takes values 0, 1, 2:\n",
+ "\n",
+ "- 0 : No mitigation is implemented.\n",
+ "- 1 : Measurement error mitigation is implemented.\n",
+ "- 2 : Gate twirling, measurement error mitigation, and ZNE are implemented.\n",
+ "\n",
+ "In this tutorial, you will construct a circuit and observable and submit jobs using the Estimator primitive using different combinations of error mitigation settings. Then, you will plot the results to observe the effects of the various settings. Most of the tutorial uses a 10-qubit circuit to make visualizations easier, and at the end, you will scale up the workflow to 50 qubits."
]
},
{
@@ -81,12 +101,23 @@
"from qiskit_ibm_runtime import Batch, EstimatorV2 as Estimator"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "d15c5fde-5046-4d86-86d8-72d1ed748c4e",
+ "metadata": {},
+ "source": [
+ "## Small-scale simulator example\n",
+ "We will forgo this step since runtime error mitigation is not supported on simulators."
+ ]
+ },
{
"cell_type": "markdown",
"id": "b2be0539-4f60-46e8-be1f-8869dae30888",
"metadata": {},
"source": [
- "## Step 1: Map classical inputs to a quantum problem\n",
+ "## Hardware example\n",
+ "\n",
+ "### Step 1: Map classical inputs to a quantum problem\n",
"\n",
"This walkthrough assumes that the classical problem has already been mapped to quantum. Begin by constructing a circuit and observable to measure. While the techniques used here apply to many different kinds of circuits, for simplicity this walkthrough uses the [`efficient_su2`](/docs/api/qiskit/qiskit.circuit.library.efficient_su2) circuit included in the Qiskit circuit library.\n",
"\n",
@@ -95,7 +126,7 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 8,
"id": "24abd7ba-bbb8-443b-9e81-866795d39a6c",
"metadata": {},
"outputs": [
@@ -105,18 +136,9 @@
""
]
},
- "execution_count": 4,
+ "execution_count": 8,
"metadata": {},
"output_type": "execute_result"
- },
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
}
],
"source": [
@@ -133,12 +155,13 @@
"id": "34fec53b-a8b2-461b-a20d-e8ad54b992fa",
"metadata": {},
"source": [
- "For our observable, let's take the Pauli $Z$ operator acting on the last qubit, $Z I \\cdots I$."
+ "As our observable, let's take the Pauli $Z$ operator acting on the last qubit, $Z I \\cdots I$.\n",
+ "Note that the fact that the last qubit corresponds to the first element of this string is due to Qiskit's use of little-endian notation."
]
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 9,
"id": "9500ba7b-4542-465f-a4e1-60165d6b6d1e",
"metadata": {},
"outputs": [],
@@ -160,12 +183,12 @@
"\n",
"In the mirror circuit technique, you concatenate the circuit with its inverse circuit, which is formed by inverting each gate of the circuit in reverse order. The resulting circuit implements the identity operator, which can trivially be simulated. Because the structure of the original circuit is preserved in the mirror circuit, executing the mirror circuit still gives an idea of how the quantum device would perform on the original circuit.\n",
"\n",
- "The following code cell assigns random parameters to your circuit, and then constructs the mirror circuit using the [`unitary_overlap`](/docs/api/qiskit/qiskit.circuit.library.unitary_overlap) class. Before mirroring the circuit, append a [barrier](/docs/api/qiskit/circuit#qiskit.circuit.Barrier) instruction to it to prevent the transpiler from merging the two parts of the circuit on either side of the barrier. Without the barrier, the transpiler would merge the original circuit with its inverse, resulting in a transpiled circuit without any gates."
+ "The following code cell assigns random parameters to your circuit, and then constructs the mirror circuit using the [`unitary_overlap`](/docs/api/qiskit/qiskit.circuit.library.unitary_overlap) class. Before mirroring the circuit, append a [barrier](/docs/api/qiskit/circuit#qiskit.circuit.Barrier) instruction to it to prevent the transpiler from merging the two parts of the circuit on either side of the barrier and resulting in a transpiled circuit without any gates."
]
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 10,
"id": "4dbde811-1ba9-47a8-85a0-dcaff054ed60",
"metadata": {},
"outputs": [
@@ -175,18 +198,9 @@
""
]
},
- "execution_count": 8,
+ "execution_count": 10,
"metadata": {},
"output_type": "execute_result"
- },
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
}
],
"source": [
@@ -211,7 +225,7 @@
"id": "a37c97de-c942-4419-9409-5bcaef9c6876",
"metadata": {},
"source": [
- "## Step 2: Optimize problem for quantum hardware execution\n",
+ "### Step 2: Optimize problem for quantum hardware execution\n",
"\n",
"You must optimize your circuit before running it on hardware. This process involves a few steps:\n",
"\n",
@@ -227,7 +241,7 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": null,
"id": "2c3ea768-0596-4db1-9b51-3ff78ec65818",
"metadata": {},
"outputs": [],
@@ -238,17 +252,35 @@
")"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "aeaf076c-1c0a-4ec4-af66-49eff621589d",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(backend)"
+ ]
+ },
{
"cell_type": "markdown",
"id": "46280e59-8c9f-4dd9-a365-6a230ceccf42",
"metadata": {},
"source": [
- "You can transpile your circuit for your chosen backend by creating a pass manager and then running the pass manager on the circuit. An easy way to create a pass manager is to use the [`generate_preset_pass_manager`](/docs/api/qiskit/qiskit.transpiler.generate_preset_pass_manager) function. See [Transpile with pass managers](/docs/guides/transpile-with-pass-managers) for a more detailed explanation of transpiling with pass managers."
+ "You can transpile your circuit to your chosen backend by creating a pass manager and then running the pass manager on the circuit. An easy way to create a pass manager is to use the [`generate_preset_pass_manager`](/docs/api/qiskit/qiskit.transpiler.generate_preset_pass_manager) function. See [Transpile with pass managers](/docs/guides/transpile-with-pass-managers) for a more detailed explanation of transpiling with pass managers."
]
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 13,
"id": "027e829a-44d3-455e-b2bf-8ce0d7e26b9b",
"metadata": {},
"outputs": [
@@ -258,18 +290,9 @@
""
]
},
- "execution_count": 10,
+ "execution_count": 13,
"metadata": {},
"output_type": "execute_result"
- },
- {
- "data": {
- "text/plain": [
- ""
- ]
- },
- "metadata": {},
- "output_type": "display_data"
}
],
"source": [
@@ -286,14 +309,14 @@
"id": "1865671e-2c7a-44dd-8938-fe4637bb5993",
"metadata": {},
"source": [
- "The transpiled circuit now contains only ISA instructions. The single-qubit gates have been decomposed in terms of $\\sqrt{X}$ gates and $R_z$ rotations, and the CX gates have been decomposed into [ECR gates](/docs/api/qiskit/qiskit.circuit.library.ECRGate#ecrgate) and single-qubit rotations.\n",
+ "The transpiled circuit now contains only ISA instructions. All gates have been decomposed in terms of $\\sqrt{X}$ gates and $R_z$ rotations, and [CZ gates](/docs/api/qiskit/qiskit.circuit.library.CZGate).\n",
"\n",
"The transpilation process has mapped the virtual qubits of the circuit to physical qubits on the hardware. The information about the qubit layout is stored in the `layout` attribute of the transpiled circuit. The observable was also defined in terms of the virtual qubits, so you need to apply this layout to the observable, which you can do with the [`apply_layout`](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp#apply_layout) method of `SparsePauliOp`."
]
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 14,
"id": "12338588-a2d0-4b9c-9e49-e25ec8617b93",
"metadata": {},
"outputs": [
@@ -306,7 +329,7 @@
" coeffs=[1.+0.j])\n",
"\n",
"Observable with layout applied:\n",
- "SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],\n",
+ "SparsePauliOp(['IIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],\n",
" coeffs=[1.+0.j])\n"
]
}
@@ -326,7 +349,7 @@
"id": "439d4edf-d1ad-49f3-b206-320958be4f82",
"metadata": {},
"source": [
- "## Step 3: Execute using Qiskit primitives\n",
+ "### Step 3: Execute using Qiskit primitives\n",
"\n",
"You are now ready to run your circuit using the Estimator primitive.\n",
"\n",
@@ -342,7 +365,7 @@
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": null,
"id": "1114d15b-1408-4f4c-a20f-60f0da722325",
"metadata": {},
"outputs": [],
@@ -353,6 +376,9 @@
"\n",
"with Batch(backend=backend) as batch:\n",
" estimator = Estimator(mode=batch)\n",
+ " estimator.options.environment.job_tags = [\n",
+ " \"TUT_CEM_SS\"\n",
+ " ] # add tag for this small scale job\n",
" # Set number of shots\n",
" estimator.options.default_shots = 100_000\n",
" # Disable runtime compilation and error mitigation\n",
@@ -392,14 +418,14 @@
"id": "919517c8-6f42-48d9-a976-53c715c00a4b",
"metadata": {},
"source": [
- "## Step 4: Post-process and return result in desired classical format\n",
+ "### Step 4: Post-process and return result in desired classical format\n",
"\n",
"Finally, you can analyze the data. Here you will retrieve the job results, extract the measured expectation values from them, and plot the values, including error bars of one standard deviation."
]
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 16,
"id": "eef38976-0ca2-429a-b2dc-41aac69605f7",
"metadata": {},
"outputs": [
@@ -459,14 +485,14 @@
"id": "958a5d23-ea09-4750-827c-e3bf6c3fa3f4",
"metadata": {},
"source": [
- "## Scale the experiment up\n",
+ "## Large-scale hardware example\n",
"\n",
"When developing an experiment, it's useful to start with a small circuit to make visualizations and simulations easier. Now that you've developed and tested our workflow on a 10-qubit circuit, you can scale it up to 50 qubits. The following code cell repeats all of the steps in this walkthrough, but now applies them to a 50-qubit circuit."
]
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 17,
"id": "d7d8408b-faf1-4eda-ab9c-bdeaab01ff53",
"metadata": {},
"outputs": [
@@ -509,6 +535,9 @@
"\n",
"with Batch(backend=backend) as batch:\n",
" estimator = Estimator(mode=batch)\n",
+ " estimator.options.environment.job_tags = [\n",
+ " \"TUT_CEM_LS\"\n",
+ " ] # add tag for this large scale job\n",
" # Set number of shots\n",
" estimator.options.default_shots = 100_000\n",
" # Disable runtime compilation and error mitigation\n",
@@ -581,13 +610,16 @@
"source": [
"When you compare the 50-qubit results with the 10-qubit results from earlier, you might note the following (your results might differ across runs):\n",
"\n",
- "- The results without error mitigation are worse. Running the larger circuit involves executing more gates, so there are more opportunities for errors to accumulate.\n",
- "- The addition of dynamical decoupling might have worsened performance. This is not surprising, because the circuit is very dense. Dynamical decoupling is primarily useful when there are large gaps in the circuit during which qubits sit idle without gates being applied to them. When these gaps are not present, dynamical decoupling is not effective, and can actually worsen performance due to errors in the dynamical decoupling pulses themselves. The 10-qubit circuit may have been too small for us to observe this effect.\n",
- "- With zero-noise extrapolation, the result is as good, or nearly as good, as the 10-qubit result, though the error bar is much larger. This demonstrates the power of the ZNE technique!\n",
- "\n",
- "## Conclusion\n",
+ "- All experiments give results closer to the ideal value and all the error bars are smaller.\n",
+ "- The addition of dynamical decoupling might have worsened performance compared to the no-mitigation case. This is not surprising, because the circuit is very dense. Dynamical decoupling is primarily useful when there are large gaps in the circuit during which qubits sit idle without gates being applied to them. When these gaps are not present, dynamical decoupling is not effective, and can actually worsen performance due to errors in the dynamical decoupling pulses themselves. The 10-qubit circuit may have been too small for us to observe this effect.\n",
+ "- With zero-noise extrapolation, the result is very close to the ideal value. This demonstrates the power of ZNE.\n",
"\n",
- "In this walkthrough, you investigated different error mitigation options available for the Qiskit Runtime Estimator primitive. You developed a workflow using a 10-qubit circuit, and then scaled it up to 50 qubits. You might have observed that enabling more error suppression and mitigation options doesn't always improve performance (specifically, enabling dynamical decoupling in this case). Most of the options accept additional configuration, which you can test out in your own work!"
+ "## Next steps\n",
+ "If you found this work interesting, you might be interested in the following material on some additional error mitigation and error suppression techniques that were not touched on in this tutorial\n",
+ "- [Probabilistic Error Cancellation (PEC)](/docs/guides/error-mitigation-and-suppression-techniques#probabilistic-error-cancellation-pec)\n",
+ "- [Matrix-free Measurement Mitigation (M3)](https://qiskit.github.io/qiskit-addon-mthree/), (see also [this tutorial](https://github.com/Qiskit/documentation/blob/main/docs/tutorials/readout-error-mitigation-sampler.ipynb/))\n",
+ "- [Shaded lightcones](https://qiskit.github.io/qiskit-addon-slc/)\n",
+ "- [Propagated Noise Absorption (PNA)](https://qiskit.github.io/qiskit-addon-pna/)"
]
}
],
diff --git a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/027e829a-44d3-455e-b2bf-8ce0d7e26b9b-0.avif b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/027e829a-44d3-455e-b2bf-8ce0d7e26b9b-0.avif
index ac1561cb6cf..7b4ffbe42a6 100644
Binary files a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/027e829a-44d3-455e-b2bf-8ce0d7e26b9b-0.avif and b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/027e829a-44d3-455e-b2bf-8ce0d7e26b9b-0.avif differ
diff --git a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/027e829a-44d3-455e-b2bf-8ce0d7e26b9b-1.avif b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/027e829a-44d3-455e-b2bf-8ce0d7e26b9b-1.avif
deleted file mode 100644
index ac1561cb6cf..00000000000
Binary files a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/027e829a-44d3-455e-b2bf-8ce0d7e26b9b-1.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/24abd7ba-bbb8-443b-9e81-866795d39a6c-0.avif b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/24abd7ba-bbb8-443b-9e81-866795d39a6c-0.avif
index bd0dc5d1ffd..809a3ecec3d 100644
Binary files a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/24abd7ba-bbb8-443b-9e81-866795d39a6c-0.avif and b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/24abd7ba-bbb8-443b-9e81-866795d39a6c-0.avif differ
diff --git a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/24abd7ba-bbb8-443b-9e81-866795d39a6c-1.avif b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/24abd7ba-bbb8-443b-9e81-866795d39a6c-1.avif
deleted file mode 100644
index bd0dc5d1ffd..00000000000
Binary files a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/24abd7ba-bbb8-443b-9e81-866795d39a6c-1.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/4dbde811-1ba9-47a8-85a0-dcaff054ed60-0.avif b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/4dbde811-1ba9-47a8-85a0-dcaff054ed60-0.avif
index 677254c076e..d1296061f3d 100644
Binary files a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/4dbde811-1ba9-47a8-85a0-dcaff054ed60-0.avif and b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/4dbde811-1ba9-47a8-85a0-dcaff054ed60-0.avif differ
diff --git a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/4dbde811-1ba9-47a8-85a0-dcaff054ed60-1.avif b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/4dbde811-1ba9-47a8-85a0-dcaff054ed60-1.avif
deleted file mode 100644
index 677254c076e..00000000000
Binary files a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/4dbde811-1ba9-47a8-85a0-dcaff054ed60-1.avif and /dev/null differ
diff --git a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/d7d8408b-faf1-4eda-ab9c-bdeaab01ff53-0.avif b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/d7d8408b-faf1-4eda-ab9c-bdeaab01ff53-0.avif
index d3ee1307472..4c7043cc7fe 100644
Binary files a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/d7d8408b-faf1-4eda-ab9c-bdeaab01ff53-0.avif and b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/d7d8408b-faf1-4eda-ab9c-bdeaab01ff53-0.avif differ
diff --git a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/eef38976-0ca2-429a-b2dc-41aac69605f7-0.avif b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/eef38976-0ca2-429a-b2dc-41aac69605f7-0.avif
index 63a500a6d2a..bfecc938801 100644
Binary files a/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/eef38976-0ca2-429a-b2dc-41aac69605f7-0.avif and b/public/docs/images/tutorials/combine-error-mitigation-techniques/extracted-outputs/eef38976-0ca2-429a-b2dc-41aac69605f7-0.avif differ