diff --git a/docs/guides/classical-feedforward-and-control-flow.ipynb b/docs/guides/classical-feedforward-and-control-flow.ipynb
index 4d774c4b483..6d052d5387c 100644
--- a/docs/guides/classical-feedforward-and-control-flow.ipynb
+++ b/docs/guides/classical-feedforward-and-control-flow.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "96086a58-1a50-4af1-b76e-5d490157efe4",
+ "id": "72a56be1-db57-4364-acf3-57814453b64e",
"metadata": {},
"source": [
"---\n",
@@ -16,7 +16,7 @@
},
{
"cell_type": "markdown",
- "id": "ef85eedb-3040-4cb0-9ae4-e6825d0b8b99",
+ "id": "7f636096-9a03-4f72-823b-4b9219d496f0",
"metadata": {
"tags": [
"version-info"
@@ -45,7 +45,7 @@
},
{
"cell_type": "markdown",
- "id": "99f0e64b-a94a-416b-8162-30b1a9862e19",
+ "id": "ea7e102f-6e41-4bdd-95be-5dd13225952b",
"metadata": {},
"source": [
"Dynamic circuits are powerful tools with which you can measure qubits in the middle of a quantum circuit execution and then perform classical logic operations within the circuit, based on the outcome of those mid-circuit measurements. This process is also known as _classical feedforward_. While these are early days of understanding how best to take advantage of dynamic circuits, the quantum research community has already identified a number of use cases, such as the following:\n",
@@ -57,9 +57,22 @@
},
{
"cell_type": "markdown",
- "id": "5627c18e-0bb7-48c0-b91e-a0d7e731fb5c",
+ "id": "b2953dd4-218e-4daa-a753-0d2aa5e0a0bb",
"metadata": {},
"source": [
+ "This guide demonstrates the functionality available in the Qiskit SDK for performing classical feedforward and control flow. These features are sometimes referred to collectively as \"dynamic circuits.\" Classical feedforward refers to the ability to measure qubits in the middle of a circuit and perform additional quantum operations that depend on the measurement outcome. Qiskit supports four control flow constructs for classical feedforward, each implemented as a method on [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit). The constructs and their corresponding methods are:\n",
+ "\n",
+ "- If statement - [`QuantumCircuit.if_test`](../api/qiskit/qiskit.circuit.QuantumCircuit#if_test)\n",
+ "- Switch statement - [`QuantumCircuit.switch`](../api/qiskit/qiskit.circuit.QuantumCircuit#switch)\n",
+ "- For loop - [`QuantumCircuit.for_loop`](../api/qiskit/qiskit.circuit.QuantumCircuit#for_loop)\n",
+ "- While loop - [`QuantumCircuit.while_loop`](../api/qiskit/qiskit.circuit.QuantumCircuit#while_loop)\n",
+ "\n",
+ "Each of these methods returns a [context manager](https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers) and is typically used in a `with` statement. In the rest of this guide, we will explain each of these constructs and how to use them.\n",
+ "\n",
+ "\n",
+ " There are some limitations of classical feedforward and control flow operations on quantum hardware that might impact your program. For more information, see [Job limits](/docs/guides/job-limits).\n",
+ "\n",
+ "\n",
"## `if` statement\n",
"\n",
"The `if` statement is used to conditionally perform operations based on the value of a classical bit or register.\n",
@@ -70,13 +83,13 @@
{
"cell_type": "code",
"execution_count": 1,
- "id": "9173934e-d09d-40ae-bcff-8a582be22dcd",
+ "id": "f0f191a7-d59d-415f-a11b-9f39e431269b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 1,
@@ -105,7 +118,7 @@
},
{
"cell_type": "markdown",
- "id": "6286036e-300d-48a9-aa89-158d181a6eff",
+ "id": "867d8f76-9cba-47fd-a341-ac40db6ee073",
"metadata": {},
"source": [
"The `with` statement can be given an assignment target which is itself a context manager that can be stored and subsequently used to create an else block, which is executed whenever the contents of the `if` block are *not* executed.\n",
@@ -116,13 +129,13 @@
{
"cell_type": "code",
"execution_count": 2,
- "id": "fcbd6923-b2bf-455b-bced-84aa539f8ac6",
+ "id": "d40249f1-d951-49e4-9ee9-662d3568f32f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 2,
@@ -152,7 +165,7 @@
},
{
"cell_type": "markdown",
- "id": "649aa80e-31f1-460a-b12d-7a451bea7851",
+ "id": "ba7b688a-e961-4361-9edf-47b387704f9d",
"metadata": {},
"source": [
"In addition to conditioning on a single classical bit, it's also possible to condition on the value of a classical register composed of multiple bits.\n",
@@ -163,13 +176,13 @@
{
"cell_type": "code",
"execution_count": 3,
- "id": "686c8c5f-330a-4aae-b42a-852d4c4730e4",
+ "id": "6ccfd81b-0bda-409e-bd9a-116848df631b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 3,
@@ -198,7 +211,201 @@
},
{
"cell_type": "markdown",
- "id": "9ff45446-8c18-414f-ae88-2718f5bf7d3f",
+ "id": "f85c34ed-bca6-40b9-9db2-e534f8c79010",
+ "metadata": {},
+ "source": [
+ "## Switch statement\n",
+ "\n",
+ "The switch statement is used to select actions based on the value of a classical bit or register. It is similar to an if statement, but allows one to specify more cases for the branching logic. In the example below, we apply a Hadamard gate to a qubit and measure it. If the result is 0, we apply an X gate on the qubit, and if the result is 1, we apply a Z gate. The resulting measurement outcome should be 1 with 100% probability."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "04b82e33-7c95-4042-a5e9-d00ff075ca02",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "qubits = QuantumRegister(1)\n",
+ "clbits = ClassicalRegister(1)\n",
+ "circuit = QuantumCircuit(qubits, clbits)\n",
+ "(q0,) = qubits\n",
+ "(c0,) = clbits\n",
+ "\n",
+ "circuit.h(q0)\n",
+ "circuit.measure(q0, c0)\n",
+ "with circuit.switch(c0) as case:\n",
+ " with case(0):\n",
+ " circuit.x(q0)\n",
+ " with case(1):\n",
+ " circuit.z(q0)\n",
+ "circuit.measure(q0, c0)\n",
+ "\n",
+ "circuit.draw(\"mpl\")\n",
+ "\n",
+ "# example output counts: {'1': 1024}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e0da6aa3-736e-4eb5-ad36-8626236f7604",
+ "metadata": {},
+ "source": [
+ "Because the example above used a single classical bit, there were only two possible cases, so we could have achieved the same result using an if-else statement. The switch case is mainly useful when branching on the value of a classical register composed of multiple bits, as demonstrated in the following example. Here, we also show how to construct a default case, which is executed if none of the preceding cases are. Note that in a switch statement, only one of the blocks are ever executed. There is no fallthrough.\n",
+ "\n",
+ "In the example below, we apply Hadamard gates to two qubits and measure them. If the result is either 00 or 11, we apply a Z gate to the third qubit. If the result is 01, we apply a Y gate. If none of the preceding cases matched, we apply an X gate. Finally, measure the third qubit."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "6aaba57e-7841-47d3-8f31-f922cb2b81f7",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "qubits = QuantumRegister(3)\n",
+ "clbits = ClassicalRegister(3)\n",
+ "circuit = QuantumCircuit(qubits, clbits)\n",
+ "(q0, q1, q2) = qubits\n",
+ "(c0, c1, c2) = clbits\n",
+ "\n",
+ "circuit.h([q0, q1])\n",
+ "circuit.measure(q0, c0)\n",
+ "circuit.measure(q1, c1)\n",
+ "with circuit.switch(clbits) as case:\n",
+ " with case(0b000, 0b011):\n",
+ " circuit.z(q2)\n",
+ " with case(0b001):\n",
+ " circuit.y(q2)\n",
+ " with case(case.DEFAULT):\n",
+ " circuit.x(q2)\n",
+ "circuit.measure(q2, c2)\n",
+ "\n",
+ "circuit.draw(\"mpl\")\n",
+ "\n",
+ "# example output counts: {'101': 267, '110': 249, '011': 265, '000': 243}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e5f1da75-abcc-42de-8aa6-6f2a6d450ddd",
+ "metadata": {},
+ "source": [
+ "## For loop\n",
+ "\n",
+ "A for loop is used to iterate over a sequence of classical values and perform some operations during each iteration.\n",
+ "\n",
+ "In the example below, we use a for loop to apply 5 X gates to a qubit and then measure it. Because we perform an odd number of X gates, the overall effect is to flip the qubit from the 0 state to the 1 state."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "c6c91715-7a98-46a8-885e-92d3d1f99557",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "qubits = QuantumRegister(1)\n",
+ "clbits = ClassicalRegister(1)\n",
+ "circuit = QuantumCircuit(qubits, clbits)\n",
+ "(q0,) = qubits\n",
+ "(c0,) = clbits\n",
+ "\n",
+ "with circuit.for_loop(range(5)) as _:\n",
+ " circuit.x(q0)\n",
+ "circuit.measure(q0, c0)\n",
+ "\n",
+ "circuit.draw(\"mpl\")\n",
+ "\n",
+ "# example output counts: {'1': 1024}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "98e7b4f3-e73e-4caf-9326-11b45bd6cfcf",
+ "metadata": {},
+ "source": [
+ "## While loop\n",
+ "\n",
+ "A while loop is used to repeat instructions while some condition is satisfied.\n",
+ "\n",
+ "In the example below, we apply Hadamard gates to two qubits and measure them. Then, we create a while loop that repeats this procedure while the measurement outcome is 11. As a result, the final measurement should never be 11, with the remaining possibilities appearing with approximately equal frequency."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "c26465ff-5d3e-4799-8c68-c327abff5694",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "qubits = QuantumRegister(2)\n",
+ "clbits = ClassicalRegister(2)\n",
+ "circuit = QuantumCircuit(qubits, clbits)\n",
+ "\n",
+ "q0, q1 = qubits\n",
+ "c0, c1 = clbits\n",
+ "\n",
+ "circuit.h([q0, q1])\n",
+ "circuit.measure(q0, c0)\n",
+ "circuit.measure(q1, c1)\n",
+ "with circuit.while_loop((clbits, 0b11)):\n",
+ " circuit.h([q0, q1])\n",
+ " circuit.measure(q0, c0)\n",
+ " circuit.measure(q1, c1)\n",
+ "\n",
+ "circuit.draw(\"mpl\")\n",
+ "\n",
+ "# example output counts: {'01': 334, '10': 368, '00': 322}"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "672080db-913d-4511-ab63-48ca48b60fa5",
"metadata": {},
"source": [
"## Classical expressions\n",
@@ -213,8 +420,8 @@
},
{
"cell_type": "code",
- "execution_count": 4,
- "id": "c90c4755-947c-4503-9bee-0237c2b2103b",
+ "execution_count": 8,
+ "id": "8c8ad702-1097-411f-983d-b5654f75059f",
"metadata": {},
"outputs": [],
"source": [
@@ -274,17 +481,17 @@
},
{
"cell_type": "code",
- "execution_count": 5,
- "id": "b5fdd320-da61-4fc5-86ed-8eefa104965e",
+ "execution_count": 9,
+ "id": "a5d808f5-d424-4133-a557-89d2f2a2c853",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
- "execution_count": 5,
+ "execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
@@ -295,7 +502,7 @@
},
{
"cell_type": "markdown",
- "id": "0d9cb9a0-c8dc-44ba-8cb2-416bf3748c45",
+ "id": "62134a85-608f-4ad2-a76e-b0736bec9362",
"metadata": {},
"source": [
"\n",
@@ -310,17 +517,17 @@
},
{
"cell_type": "code",
- "execution_count": 1,
- "id": "e64ec241-41e8-40f8-ab64-af236c6c7802",
+ "execution_count": 10,
+ "id": "953fa3ca-f542-47ea-9cf2-36a616ecb7f7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
- "execution_count": 1,
+ "execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
@@ -358,7 +565,7 @@
},
{
"cell_type": "markdown",
- "id": "9688221f-3da3-4a5b-aac9-aabf7b518d82",
+ "id": "f1b55508-04e8-4f53-9b13-33302102711d",
"metadata": {},
"source": [
"## Next steps\n",
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/101aaa8f-7061-4924-9b50-806d7e1ab728-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/101aaa8f-7061-4924-9b50-806d7e1ab728-0.avif
new file mode 100644
index 00000000000..52d18bc29e6
Binary files /dev/null and b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/101aaa8f-7061-4924-9b50-806d7e1ab728-0.avif differ
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/174a9675-3c8b-4b5e-808e-f7e0f8b9c805-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/174a9675-3c8b-4b5e-808e-f7e0f8b9c805-0.avif
new file mode 100644
index 00000000000..b922f2fde46
Binary files /dev/null and b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/174a9675-3c8b-4b5e-808e-f7e0f8b9c805-0.avif differ
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/1f6737fe-bc45-4d0c-b7b4-1096e2d7e14a-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/1f6737fe-bc45-4d0c-b7b4-1096e2d7e14a-0.avif
new file mode 100644
index 00000000000..f2c75a1b2b7
Binary files /dev/null and b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/1f6737fe-bc45-4d0c-b7b4-1096e2d7e14a-0.avif differ
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/20f0640a-a3f7-41b3-aada-b66bc89b0555-0.svg b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/20f0640a-a3f7-41b3-aada-b66bc89b0555-0.svg
deleted file mode 100644
index 0d66b12693e..00000000000
--- a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/20f0640a-a3f7-41b3-aada-b66bc89b0555-0.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/37ec3fa6-04b5-4165-b8d2-bae5fd238331-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/37ec3fa6-04b5-4165-b8d2-bae5fd238331-0.avif
new file mode 100644
index 00000000000..8cb4d3a0c97
Binary files /dev/null and b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/37ec3fa6-04b5-4165-b8d2-bae5fd238331-0.avif differ
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/53a26ce5-3564-47a0-8803-c9c46db86923-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/53a26ce5-3564-47a0-8803-c9c46db86923-0.avif
new file mode 100644
index 00000000000..d332870b2ba
Binary files /dev/null and b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/53a26ce5-3564-47a0-8803-c9c46db86923-0.avif differ
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/60924bfa-50ed-4d9d-a17b-9d64f2cc053f-0.svg b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/60924bfa-50ed-4d9d-a17b-9d64f2cc053f-0.svg
deleted file mode 100644
index 65f5f15ffbe..00000000000
--- a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/60924bfa-50ed-4d9d-a17b-9d64f2cc053f-0.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/98e8f552-4169-42a3-8182-e14e9ffb59e2-0.svg b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/98e8f552-4169-42a3-8182-e14e9ffb59e2-0.svg
deleted file mode 100644
index ee624b8b10f..00000000000
--- a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/98e8f552-4169-42a3-8182-e14e9ffb59e2-0.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/a5d43b4c-c538-4f34-8cf3-92c2c0d26fdd-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/a5d43b4c-c538-4f34-8cf3-92c2c0d26fdd-0.avif
new file mode 100644
index 00000000000..754e44c630b
Binary files /dev/null and b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/a5d43b4c-c538-4f34-8cf3-92c2c0d26fdd-0.avif differ
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/d0f0abdb-50d5-408d-a704-a1a555acdd85-0.svg b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/d0f0abdb-50d5-408d-a704-a1a555acdd85-0.svg
deleted file mode 100644
index 427fa3c3cde..00000000000
--- a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/d0f0abdb-50d5-408d-a704-a1a555acdd85-0.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/d2fdf38a-e874-4de1-9a79-08aab97f9ecc-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/d2fdf38a-e874-4de1-9a79-08aab97f9ecc-0.avif
new file mode 100644
index 00000000000..2985894d232
Binary files /dev/null and b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/d2fdf38a-e874-4de1-9a79-08aab97f9ecc-0.avif differ
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/e64ec241-41e8-40f8-ab64-af236c6c7802-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/f76db731-afa1-4777-9482-25376aa86175-0.avif
similarity index 100%
rename from public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/e64ec241-41e8-40f8-ab64-af236c6c7802-0.avif
rename to public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/f76db731-afa1-4777-9482-25376aa86175-0.avif
diff --git a/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/fc2bc3c3-eab1-41f0-b696-5e8b30155d55-0.avif b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/fc2bc3c3-eab1-41f0-b696-5e8b30155d55-0.avif
new file mode 100644
index 00000000000..c00904074f9
Binary files /dev/null and b/public/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/fc2bc3c3-eab1-41f0-b696-5e8b30155d55-0.avif differ