diff --git a/docs/guides/classical-feedforward-and-control-flow.ipynb b/docs/guides/classical-feedforward-and-control-flow.ipynb
index 4d774c4b483..039eb6a4c3f 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": [
+ "Qiskit supports four control flow constructs for classical feedforward, each implemented as a method on [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit). The constructs and their corresponding methods are:\n",
+ "\n",
+ "- If statement - [`QuantumCircuit.if_test`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#if_test)\n",
+ "- Switch statement - [`QuantumCircuit.switch`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#switch)\n",
+ "- For loop - [`QuantumCircuit.for_loop`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#for_loop)\n",
+ "- While loop - [`QuantumCircuit.while_loop`](/docs/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. The remainder of this guide explains 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 [Execute dynamic circuits](/docs/guides/execute-dynamic-circuits).\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,12 +211,206 @@
},
{
"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 you can specify more cases for the branching logic. The example below applies a Hadamard gate to a qubit and measures it. If the result is 0, apply an X gate on the qubit, and if the result is 1, 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 you 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. The following example shows 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",
+ "The example below applies Hadamard gates to two qubits and measures them. If the result is either 00 or 11, apply a Z gate to the third qubit. If the result is 01, apply a Y gate. If none of the preceding cases matched, 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",
+ "The following example uses a for loop to apply 5 X gates to a qubit and then measures it. Because it performs 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",
+ "The example below applies Hadamard gates to two qubits and measures them. Then it creates 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",
"\n",
- "The Qiskit classical expression module [`qiskit.circuit.classical`](/docs/api/qiskit/circuit_classical) contains an exploratory representation of runtime operations on classical values during circuit execution. Due to hardware limitations, only `QuantumCircuit.if_test()` conditions are currently supported.\n",
+ "The Qiskit classical expression module [`qiskit.circuit.classical`](/docs/api/qiskit/circuit_classical) contains an exploratory representation of runtime operations on classical values during circuit execution.\n",
"\n",
"The following example shows that you can use the calculation of the parity to create an n-qubit GHZ state using dynamic circuits. First, generate $n/2$ Bell pairs on adjacent qubits. Then, glue these pairs together using a layer of CNOT gates in between pairs. You then measure the target qubit of all prior CNOT gates and reset each measured qubit to the state $\\vert 0 \\rangle$. You apply $X$ to every unmeasured site for which the parity of all preceding bits is odd. Finally, CNOT gates are applied to the measured qubits to re-establish the entanglement lost in the measurement.\n",
"\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