{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "72a56be1-db57-4364-acf3-57814453b64e",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"고전적 피드포워드 및 제어 흐름(동적 회로)\"\n",
        "description: \"고전적인 피드포워드 및 제어 흐름(동적 회로라고도 함)에는 Qiskit을 사용하십시오\"\n",
        "---\n",
        "\n",
        "<span id=\"classical-feedforward-and-control-flow-dynamic-circuits\" />\n",
        "\n",
        "# 고전적 피드포워드 및 제어 흐름(동적 회로)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7f636096-9a03-4f72-823b-4b9219d496f0",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"패키지 버전\">\n",
        "    이 페이지의 코드는 다음 요구 사항을 사용하여 개발되었습니다.\n",
        "    다음 버전 이상을 사용하는 것이 좋습니다.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.2\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ea7e102f-6e41-4bdd-95be-5dd13225952b",
      "metadata": {},
      "source": [
        "동적 회로는 양자 회로 실행 중간에 큐비트를 측정한 다음 이러한 중간 회로 측정 결과를 기반으로 회로 내에서 고전적인 논리 연산을 수행할 수 있는 강력한 도구입니다.  이 프로세스는 *고전적인 피드포워드라고도* 합니다. 동적 회로를 가장 잘 활용하는 방법을 이해하는 초기 단계이지만, 양자 연구 커뮤니티에서는 이미 다음과 같은 여러 가지 사용 사례를 확인했습니다:\n",
        "\n",
        "* 효율적인 양자 상태 준비, 예를 들어 [GHZ 상태](https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.5.030339), [W-상태](https://arxiv.org/abs/2403.07604) (W-상태에 대한 자세한 내용은 [\"피드 포워드를 이용한 얕은 회로에 의한 상태 준비\"](https://arxiv.org/abs/2307.14840) 도 참조), 그리고 광범위한 [행렬 곱 상태들](https://arxiv.org/abs/2404.16083)\n",
        "* 얕은 회로를 사용하여 동일한 칩에서 큐비트 간 [장거리 얽힘을 효율적으로 처리합니다](https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.5.030339)\n",
        "* [IQP 유사 회로의 효율적인 샘플링](https://arxiv.org/pdf/2505.04705)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b2953dd4-218e-4daa-a753-0d2aa5e0a0bb",
      "metadata": {},
      "source": [
        "[`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit)Qiskit은 고전적인 피드포워드(feedforward)를 위한 네 가지 제어 흐름 구조를 지원하며, 각각은 의 메서드로 구현되어 있습니다. 구성과 이에 대응하는 메서드는 다음과 같습니다:\n",
        "\n",
        "* if 문 - [`QuantumCircuit.if_test`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#if_test)\n",
        "* switch 문 - [`QuantumCircuit.switch`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#switch)\n",
        "* for 루프 - [`QuantumCircuit.for_loop`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#for_loop)\n",
        "* While 루프 - [`QuantumCircuit.while_loop`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#while_loop)\n",
        "\n",
        "`with` 이 방법들은 각각 [컨텍스트 매니저](https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers) 를 반환하며, 일반적으로 문에서 사용됩니다. 이 가이드의 나머지 부분에서는 이러한 각 구문과 그 사용법을 설명합니다.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  양자 하드웨어에서 고전적인 피드포워드 및 제어 흐름 연산에는 프로그램에 영향을 미칠 수 있는 몇 가지 제한 사항이 있습니다. 자세한 내용은 [‘동적 회로 실행’을](/docs/guides/execute-dynamic-circuits) 참조하십시오.\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"if-statement\" />\n",
        "\n",
        "## `if` 명령문\n",
        "\n",
        "`if` 문은 기존 비트 또는 레지스터 값에 따라 조건부로 연산을 수행하는 데 사용됩니다.\n",
        "\n",
        "아래 예시에서는 큐비트에 하다마드 게이트를 적용하고 측정합니다. 결과가 1이면 큐비트에 X 게이트를 적용하여 0 상태로 다시 뒤집는 효과를 냅니다. 그런 다음 큐비트를 다시 측정합니다. 측정 결과는 100% 확률로 0이 되어야 합니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "f0f191a7-d59d-415f-a11b-9f39e431269b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/f0f191a7-d59d-415f-a11b-9f39e431269b-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "\n",
        "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.if_test((c0, 1)):\n",
        "    circuit.x(q0)\n",
        "circuit.measure(q0, c0)\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'0': 1024}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "867d8f76-9cba-47fd-a341-ac40db6ee073",
      "metadata": {},
      "source": [
        "`with` 문에는 그 자체가 컨텍스트 관리자인 할당 대상을 지정할 수 있으며, 이 할당 대상은 저장된 후 `if` 블록의 내용이 *실행되지 않을* 때마다 실행되는 else 블록을 생성하는 데 사용될 수 있습니다.\n",
        "\n",
        "아래 예제에서는 2개의 큐비트와 2개의 클래식 비트로 레지스터를 초기화합니다. 첫 번째 큐비트에 하다마드 게이트를 적용하고 측정합니다. 결과가 1이면 두 번째 큐비트에 Hadamard 게이트를 적용하고, 그렇지 않으면 두 번째 큐비트에 X 게이트를 적용합니다. 마지막으로 두 번째 큐비트도 측정합니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "d40249f1-d951-49e4-9ee9-662d3568f32f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/d40249f1-d951-49e4-9ee9-662d3568f32f-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qubits = QuantumRegister(2)\n",
        "clbits = ClassicalRegister(2)\n",
        "circuit = QuantumCircuit(qubits, clbits)\n",
        "(q0, q1) = qubits\n",
        "(c0, c1) = clbits\n",
        "\n",
        "circuit.h(q0)\n",
        "circuit.measure(q0, c0)\n",
        "with circuit.if_test((c0, 1)) as else_:\n",
        "    circuit.h(q1)\n",
        "with else_:\n",
        "    circuit.x(q1)\n",
        "circuit.measure(q1, c1)\n",
        "\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'01': 260, '11': 272, '10': 492}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ba7b688a-e961-4361-9edf-47b387704f9d",
      "metadata": {},
      "source": [
        "단일 클래식 비트에 대한 컨디셔닝 외에도 여러 비트로 구성된 클래식 레지스터의 값을 컨디셔닝할 수도 있습니다.\n",
        "\n",
        "아래 예시에서는 두 큐비트에 하다마르 게이트를 적용하고 이를 측정합니다. 결과가 `01`, 즉 첫 번째 큐비트가 1이고 두 번째 큐비트가 0인 경우, 우리는 세 번째 큐비트에 X 게이트를 적용한다. 마지막으로, 우리는 세 번째 큐비트를 측정합니다. 명확성을 위해 조건에서 `if` 세 번째 클래식 비트(0)의 상태를 명시하기로 선택했음을 유의하십시오. 회로도에서 조건은 조건부로 설정된 클래식 비트 위의 원으로 표시됩니다. 실선 원은 1에 대한 조건부 확률을 나타내며, 윤곽선 원은 0에 대한 조건부 확률을 나타냅니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "6ccfd81b-0bda-409e-bd9a-116848df631b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/6ccfd81b-0bda-409e-bd9a-116848df631b-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "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.if_test((clbits, 0b001)):\n",
        "    circuit.x(q2)\n",
        "circuit.measure(q2, c2)\n",
        "\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'101': 269, '011': 260, '000': 252, '010': 243}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f85c34ed-bca6-40b9-9db2-e534f8c79010",
      "metadata": {},
      "source": [
        "<span id=\"switch-statement\" />\n",
        "\n",
        "## Switch문\n",
        "\n",
        "switch 문은 일반 비트나 레지스터의 값에 따라 수행할 작업을 선택하는 데 사용됩니다. if 문과 비슷하지만, 분기 논리에 더 많은 경우를 지정할 수 있습니다. 아래 예제에서는 큐비트에 하다마르 게이트를 적용한 후 이를 측정합니다. 결과가 0이면 큐비트에 X 게이트를 적용하고, 결과가 1이면 Z 게이트를 적용한다. 그 결과 측정값은 100%의 확률로 1이 되어야 합니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "04b82e33-7c95-4042-a5e9-d00ff075ca02",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/04b82e33-7c95-4042-a5e9-d00ff075ca02-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "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": [
        "위의 예제에서는 하나의 고전적 비트를 사용했기 때문에 가능한 경우가 두 가지뿐이었으므로, if-else 문을 사용해도 동일한 결과를 얻을 수 있었을 것입니다. switch 문은 주로 여러 비트로 구성된 일반 레지스터의 값에 따라 분기할 때 유용합니다. 다음 예제는 앞선 모든 조건이 충족되지 않을 경우 실행되는 기본 조건을 구성하는 방법을 보여줍니다. switch 문에서는 블록 중 오직 하나만 실행된다는 점에 유의하십시오. 폴스루는 발생하지 않습니다.\n",
        "\n",
        "아래 예제에서는 두 큐비트에 하다마르 게이트를 적용한 후 이를 측정합니다. 결과가 00이거나 11인 경우, 세 번째 큐비트에 Z 게이트를 적용한다. 결과가 01이면 Y 게이트를 적용하십시오. 앞서 언급한 경우 중 어느 것도 해당되지 않는다면, X 게이트를 적용하십시오. 마지막으로, 세 번째 큐비트를 측정합니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "6aaba57e-7841-47d3-8f31-f922cb2b81f7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/6aaba57e-7841-47d3-8f31-f922cb2b81f7-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "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": [
        "<span id=\"for-loop\" />\n",
        "\n",
        "## For 루프\n",
        "\n",
        "A for 루프는 일련의 값을 순차적으로 처리하며, 각 반복마다 특정 연산을 수행하는 데 사용됩니다.\n",
        "\n",
        "다음 예제에서는 for 루프를 사용하여 1개의 큐비트에 5개의 X 게이트를 적용한 다음, 그 상태를 측정합니다. 홀수 개의 X 게이트가 수행되기 때문에, 전체적인 효과는 큐비트를 0 상태에서 1 상태로 반전시키는 것입니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "c6c91715-7a98-46a8-885e-92d3d1f99557",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/c6c91715-7a98-46a8-885e-92d3d1f99557-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "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": [
        "<span id=\"while-loop\" />\n",
        "\n",
        "## While 루프\n",
        "\n",
        "while 루프는 특정 조건이 충족되는 동안 명령어를 반복하는 데 사용됩니다.\n",
        "\n",
        "아래 예제에서는 두 큐비트에 하다마르 게이트를 적용한 후 이를 측정합니다. 그런 다음 측정 결과가 11인 동안 이 절차를 반복하는 while 루프를 생성합니다. 따라서 최종 측정값이 11이 되어서는 절대 안 되며, 나머지 가능성들은 대략 동일한 빈도로 나타날 것입니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "c26465ff-5d3e-4799-8c68-c327abff5694",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/c26465ff-5d3e-4799-8c68-c327abff5694-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "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": [
        "<span id=\"classical-expressions\" />\n",
        "\n",
        "## 고전적 표현들\n",
        "\n",
        "Qiskit의 고전 표현 모듈에는 [`qiskit.circuit.classical`](/docs/api/qiskit/circuit_classical) 회로 실행 중 고전 값에 대한 런타임 연산을 탐색적으로 표현한 내용이 포함되어 있습니다.\n",
        "\n",
        "다음 예는 패리티 계산을 사용하여 동적 회로를 사용하여 n-쿼비트 GHZ 상태를 생성하는 방법을 보여줍니다. 먼저, 인접한 큐비트에 $n/2$ 벨 쌍을 생성합니다. 그런 다음 쌍 사이에 CNOT 게이트 층을 사용하여 이 쌍을 함께 붙입니다. 그런 다음 모든 이전 CNOT 게이트의 목표 큐비트를 측정하고 측정된 각 큐비트를 $\\vert 0 \\rangle$ 상태로 재설정합니다. 이전 모든 비트의 패리티가 홀수인 측정되지 않은 모든 사이트에 $X$ 을 적용합니다. 마지막으로, 측정된 큐비트에 CNOT 게이트를 적용하여 측정에서 손실된 얽힘을 다시 설정합니다.\n",
        "\n",
        "패리티 계산에서, 생성된 표현식의 첫 번째 요소는 Python 객체를 `mr[0]` 노드로 [`Value`](/docs/api/qiskit/circuit_classical#value) 변환하는 것을 포함한다 (`lift` 는 임의의 객체를 고전적 표현식으로 변환하는 데 사용된다). 이것은 및 이후에 올 수 있는 `mr[1]` 클래식 레지스터에 대해 필요하지 않습니다. 이들은 의 `expr.bit_xor`입력이며, 필요한 리프팅은 이러한 경우에 자동으로 수행되기 때문입니다. 이러한 표현은 루프 및 기타 구문에서 구축될 수 있습니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "8c8ad702-1097-411f-983d-b5654f75059f",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "from qiskit.circuit.classical import expr\n",
        "\n",
        "num_qubits = 8\n",
        "if num_qubits % 2 or num_qubits < 4:\n",
        "    raise ValueError(\"num_qubits must be an even integer ≥ 4\")\n",
        "meas_qubits = list(range(2, num_qubits, 2))  # qubits to measure and reset\n",
        "\n",
        "qr = QuantumRegister(num_qubits, \"qr\")\n",
        "mr = ClassicalRegister(len(meas_qubits), \"m\")\n",
        "qc = QuantumCircuit(qr, mr)\n",
        "\n",
        "# Create local Bell pairs\n",
        "qc.reset(qr)\n",
        "qc.h(qr[::2])\n",
        "for ctrl in range(0, num_qubits, 2):\n",
        "    qc.cx(qr[ctrl], qr[ctrl + 1])\n",
        "\n",
        "# Glue neighboring pairs\n",
        "for ctrl in range(1, num_qubits - 1, 2):\n",
        "    qc.cx(qr[ctrl], qr[ctrl + 1])\n",
        "\n",
        "# Measure boundary qubits between pairs,reset to 0\n",
        "for k, q in enumerate(meas_qubits):\n",
        "    qc.measure(qr[q], mr[k])\n",
        "    qc.reset(qr[q])\n",
        "\n",
        "# Parity-conditioned X corrections\n",
        "# Each non-measured qubit gets flipped iff the parity (XOR) of all\n",
        "# preceding measurement bits is 1\n",
        "for tgt in range(num_qubits):\n",
        "    if tgt in meas_qubits:  # skip measured qubits\n",
        "        continue\n",
        "    # all measurement registers whose physical qubit index < tgt\n",
        "    left_bits = [k for k, q in enumerate(meas_qubits) if q < tgt]\n",
        "    if not left_bits:  # skip if list empty\n",
        "        continue\n",
        "\n",
        "    # build XOR-parity expression\n",
        "    parity = expr.lift(\n",
        "        mr[left_bits[0]]\n",
        "    )  # lift the first bit to Value so it will be treated like a boolean.\n",
        "    for k in left_bits[1:]:\n",
        "        parity = expr.bit_xor(\n",
        "            mr[k], parity\n",
        "        )  # calculate parity with all other bits\n",
        "    with qc.if_test(parity):  # Add X if parity is 1\n",
        "        qc.x(qr[tgt])\n",
        "\n",
        "# Re-entangle measured qubits\n",
        "for ctrl in range(1, num_qubits - 1, 2):\n",
        "    qc.cx(qr[ctrl], qr[ctrl + 1])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "a5d808f5-d424-4133-a557-89d2f2a2c853",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/a5d808f5-d424-4133-a557-89d2f2a2c853-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.draw(output=\"mpl\", style=\"iqp\", idle_wires=False, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "62134a85-608f-4ad2-a76e-b0736bec9362",
      "metadata": {},
      "source": [
        "<span id=\"store\" />\n",
        "\n",
        "<span id=\"store\" />\n",
        "\n",
        "### `Store`\n",
        "\n",
        "해당 식을 반복해서 사용할 예정이라면, 명령을 [`store`](/docs/api/qiskit/circuit#store) 사용하여 그 결과를 저장할 수 있습니다. 작업이 자동으로 병렬화되어, 실행 시 코드의 효율성이 크게 향상됩니다.\n",
        "\n",
        "예를 들어, $(\\neg A[0]) \\oplus (\\neg A[1]) \\oplus (\\neg A[2]) \\ldots$ 보다 $B[0] \\oplus B[1] \\oplus B[2] \\ldots$ (여기서  $B = \\neg A$)를 작성하는 것이 실행 시 더 자연스럽고 효율적이다. 전자는 식 내부에서 각 부정 연산을 순차적으로 평가하는 대신, XOR 연산 체인 전에 단일 병렬 단계로 부정 연산을 계산한다.\n",
        "\n",
        "전체 예시:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "953fa3ca-f542-47ea-9cf2-36a616ecb7f7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/953fa3ca-f542-47ea-9cf2-36a616ecb7f7-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "from qiskit.circuit.classical import expr\n",
        "\n",
        "qregs = QuantumRegister(4, \"q\")\n",
        "creg = ClassicalRegister(3, \"c\")\n",
        "# temp is a plain ClassicalRegister used as the store target\n",
        "temp = ClassicalRegister(3, \"temp\")\n",
        "qc = QuantumCircuit(qregs, creg, temp)\n",
        "\n",
        "qc.h([0, 1, 2])\n",
        "qc.measure([0, 1, 2], creg)\n",
        "\n",
        "# Store bit-NOT of the full 3-bit register into temp\n",
        "qc.store(temp, expr.bit_not(creg))\n",
        "\n",
        "# Compute parity of temp using bit-indexed XOR\n",
        "parity = expr.bit_xor(\n",
        "    expr.bit_xor(expr.index(temp, 0), expr.index(temp, 1)),\n",
        "    expr.index(temp, 2),\n",
        ")\n",
        "\n",
        "# Flip q3 if parity of ~creg is 1\n",
        "with qc.if_test(parity):\n",
        "    qc.x(3)\n",
        "\n",
        "qc.measure([0, 1, 2], creg)\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f1b55508-04e8-4f53-9b13-33302102711d",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 다음 단계\n",
        "\n",
        "<Admonition type=\"tip\" title=\"권장사항\">\n",
        "  * [스트레치를](/docs/guides/stretch) 사용하여 정확한 동적 디커플링을 구현하는 방법을 알아보세요.\n",
        "  * [회로 스케줄 시각화](/docs/guides/qiskit-runtime-circuit-timing) 기능을 활용하여 동적 회로를 디버깅하고 최적화하세요.\n",
        "  * [동적 회로를 실행합니다](/docs/guides/execute-dynamic-circuits).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "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"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}