{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "d53161ce",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"트랜스파일러 최적화 수준 설정\"\n",
        "description: \"Qiskit에서 양자 회로 트랜스파일링 최적화 수준 설정 방법.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Cartan's */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6f5a4641-5b7f-4841-8bec-60fa44429030",
      "metadata": {},
      "source": [
        "<span id=\"set-transpiler-optimization-level\" />\n",
        "\n",
        "# 트랜스파일러 최적화 수준 설정\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8a1db79c-9bee-4737-b8b5-13155062ca04",
      "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",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bd9eb973-430c-4450-8de2-c061aa0ff742",
      "metadata": {},
      "source": [
        "실제 양자 소자는 노이즈와 게이트 오류가 발생할 수 있으므로 회로를 최적화하여 깊이와 게이트 수를 줄이면 해당 회로를 실행하여 얻은 결과를 크게 향상시킬 수 있습니다.\n",
        "함수에는 [`generate_preset_pass_manager`](/docs/api/qiskit/qiskit.transpiler.generate_preset_pass_manager#qiskit.transpiler.generate_preset_pass_manager) 함수에는 트랜스파일러가 회로를 최적화하는 데 얼마나 많은 노력을 기울이는지 제어하는 하나의 필수 위치 인수( `optimization_level`)가 있습니다. 이 인수는 0, 1, 2, 3 중 하나의 값을 취하는 정수일 수 있습니다.\n",
        "최적화 수준이 높을수록 컴파일 시간이 길어지는 대신 더 최적화된 회로를 생성합니다.\n",
        "다음 표에서는 각 설정에서 수행되는 최적화에 대해 설명합니다.\n",
        "\n",
        "<Table>\n",
        "  <thead>\n",
        "    <Tr>\n",
        "      <Th>최적화 레벨</Th>\n",
        "      <Th>설명</Th>\n",
        "    </Tr>\n",
        "  </thead>\n",
        "\n",
        "  <tbody>\n",
        "    <Tr>\n",
        "      <Td>0</Td>\n",
        "\n",
        "      <Td>\n",
        "        최적화 없음: 일반적으로 하드웨어 특성 분석에 사용됩니다\n",
        "\n",
        "        * 기본 번역\n",
        "        * 레이아웃/라우팅: `TrivialLayout` 에서 가상과 동일한 물리적 큐비트 번호를 선택하고 SWAP을 삽입하여 작동하도록 합니다( `SabreSwap` 사용)\n",
        "      </Td>\n",
        "    </Tr>\n",
        "\n",
        "    <Tr>\n",
        "      <Td>1</Td>\n",
        "\n",
        "      <Td>\n",
        "        조명 최적화:\n",
        "\n",
        "        * 레이아웃/라우팅: 레이아웃은 `TrivialLayout` 으로 처음 시도됩니다. 추가 스왑이 필요한 경우 `SabreSwap` 을 사용하여 최소 스왑 수를 가진 레이아웃을 찾은 다음 `VF2LayoutPostLayout` 을 사용하여 그래프에서 최적의 큐비트를 선택하려고 시도합니다.\n",
        "        * `InverseCancellation`\n",
        "        * 1Q 게이트 최적화\n",
        "      </Td>\n",
        "    </Tr>\n",
        "\n",
        "    <Tr>\n",
        "      <Td>2</Td>\n",
        "\n",
        "      <Td>\n",
        "        중간 최적화:\n",
        "\n",
        "        * 레이아웃/라우팅: 최적화 레벨 1(사소하지 않음) + 휴리스틱 최적화 + 더 큰 검색 깊이와 검색 깊이 및 최적화 기능의 시험.  `TrivialLayout` 을 사용하지 않으므로 동일한 물리적 큐비트 번호와 가상 큐비트 번호를 사용하려고 시도하지 않습니다.\n",
        "        * `CommutativeCancellation`\n",
        "      </Td>\n",
        "    </Tr>\n",
        "\n",
        "    <Tr>\n",
        "      <Td>3</Td>\n",
        "\n",
        "      <Td>\n",
        "        높은 최적화:\n",
        "\n",
        "        * 최적화 레벨 2 + 더 많은 노력/시도를 통해 레이아웃/라우팅에 최적화된 휴리스틱 최적화\n",
        "        * [카르탄의 KAK 분해를](https://arxiv.org/abs/quant-ph/0507171) 사용한 2큐비트 블록 재합성.\n",
        "        * 균일성 파괴 패스:\n",
        "          * `OptimizeSwapBeforeMeasure`: 스왑을 피하기 위해 측정값을 이동합니다\n",
        "          * `RemoveDiagonalGatesBeforeMeasure`: 측정에 영향을 미치지 않는 측정 전 게이트를 제거합니다\n",
        "      </Td>\n",
        "    </Tr>\n",
        "  </tbody>\n",
        "</Table>\n",
        "\n",
        "<span id=\"optimization-level-in-action\" />\n",
        "\n",
        "## 최적화 수준 적용 사례\n",
        "\n",
        "일반적으로 2큐비트 게이트가 가장 큰 오류의 원인이므로, 결과 회로에서 2큐비트 게이트의 수를 세어 트랜스필레이션의 '하드웨어 효율성'을 대략적으로 정량화할 수 있습니다.\n",
        "여기서는 무작위 유니티와 SWAP 게이트로 구성된 입력 회로에서 다양한 최적화 수준을 시도해 보겠습니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "81173ebc-8359-48a6-b585-0477907b3b93",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/81173ebc-8359-48a6-b585-0477907b3b93-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.circuit.library import UnitaryGate\n",
        "from qiskit.quantum_info import Operator, random_unitary\n",
        "\n",
        "UU = random_unitary(4, seed=12345)\n",
        "rand_U = UnitaryGate(UU)\n",
        "\n",
        "qc = QuantumCircuit(2)\n",
        "qc.append(rand_U, range(2))\n",
        "qc.swap(0, 1)\n",
        "qc.draw(\"mpl\", style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "34509d07-7804-46cb-b508-130436d9b01d",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\">\n",
        "  이 예제에서는 의 모의 `FakeSherbrooke``qiskit_ibm_runtime` 백엔드를 사용하지만, Qiskit과 호환되는 실제 또는 모의 백엔드라면 어떤 것이든 사용해 볼 수 있습니다.  결과는 다를 수 있습니다.\n",
        "</Admonition>\n",
        "\n",
        "먼저, 최적화 수준 0을 사용하여 트랜스파일해 봅시다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "40cdd173-b437-48b1-8928-741e8411342e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/40cdd173-b437-48b1-8928-741e8411342e-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=0, backend=backend, seed_transpiler=12345\n",
        ")\n",
        "qc_t1_exact = pass_manager.run(qc)\n",
        "qc_t1_exact.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a5169cb2-cd2a-40c0-93e5-c526580f84aa",
      "metadata": {},
      "source": [
        "트랜스파일된 회로에는 2쿼비트 ECR 게이트 6개가 있습니다.\n",
        "\n",
        "최적화 레벨 1에 대해 반복합니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "2dab5def-a017-42e9-92d6-e043ac4065b2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/2dab5def-a017-42e9-92d6-e043ac4065b2-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=1, backend=backend, seed_transpiler=12345\n",
        ")\n",
        "qc_t1_exact = pass_manager.run(qc)\n",
        "qc_t1_exact.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "69d5d04b-746f-41c4-92e8-62a7eaffb5b2",
      "metadata": {},
      "source": [
        "트랜스파일된 회로에는 여전히 6개의 ECR 게이트가 있지만 단일 큐비트 게이트의 수가 줄었습니다.\n",
        "\n",
        "최적화 레벨 2에 대해 반복합니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "77d76048-b1e8-4225-b35f-80dc9d458e8d",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/77d76048-b1e8-4225-b35f-80dc9d458e8d-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=2, backend=backend, seed_transpiler=12345\n",
        ")\n",
        "qc_t2_exact = pass_manager.run(qc)\n",
        "qc_t2_exact.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4818fb06-88bd-43cb-b23c-eba5a3537e67",
      "metadata": {},
      "source": [
        "이렇게 하면 최적화 레벨 1과 동일한 결과가 나옵니다. 최적화 수준을 높인다고 해서 항상 달라지는 것은 아닙니다.\n",
        "\n",
        "최적화 레벨 3으로 다시 반복합니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "4109d0e2-df37-4850-8409-6b860c48595c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/4109d0e2-df37-4850-8409-6b860c48595c-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=3, backend=backend, seed_transpiler=12345\n",
        ")\n",
        "qc_t3_exact = pass_manager.run(qc)\n",
        "qc_t3_exact.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c9cf6dcf-733f-494f-a571-43d47d3908ce",
      "metadata": {},
      "source": [
        "이제 ECR 게이트는 세 개뿐입니다. 최적화 레벨 3에서 키스킷은 2큐비트 블록의 게이트를 재합성하려고 시도하고, 최대 3개의 ECR 게이트를 사용하여 2큐비트 게이트를 구현할 수 있기 때문에 이러한 결과를 얻을 수 있습니다. `approximation_degree` 을 1보다 작은 값으로 설정하면 트랜스파일러가 게이트 분해에 약간의 오차가 발생할 수 있는 근사치를 만들 수 있으므로 더 적은 수의 ECR 게이트를 얻을 수 있습니다( [트랜스파일에 일반적으로 사용되는 매개변수](common-parameters#approximation-degree) 참조):\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "bf239116-b8bb-42aa-a27a-89206d9e108a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/bf239116-b8bb-42aa-a27a-89206d9e108a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=3,\n",
        "    approximation_degree=0.99,\n",
        "    backend=backend,\n",
        "    seed_transpiler=12345,\n",
        ")\n",
        "qc_t3_approx = pass_manager.run(qc)\n",
        "qc_t3_approx.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "247f60a9-b0ad-4e83-85ea-008dc808267f",
      "metadata": {},
      "source": [
        "이 회로에는 두 개의 ECR 게이트만 있지만 대략적인 회로입니다. 그 효과가 정확한 회로와 어떻게 다른지 이해하기 위해 이 회로가 구현하는 단항 연산자와 정확한 단항 사이의 충실도를 계산할 수 있습니다. 계산을 수행하기 전에 먼저 127개의 큐비트를 포함하는 트랜스파일된 회로를 활성 큐비트만 포함하는 회로로 축소하고, 이 중 두 개의 큐비트만 포함합니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "56988ecd-8a78-42ca-90eb-fc956674c64d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Synthesis fidelity\n",
            "Exact: 1.000+0.000j\n",
            "Approximate: 0.992+0.000j\n"
          ]
        }
      ],
      "source": [
        "import numpy as np\n",
        "\n",
        "\n",
        "def trace_to_fidelity_2q(trace: float) -> float:\n",
        "    return (4.0 + trace * trace.conjugate()) / 20.0\n",
        "\n",
        "\n",
        "# Reduce circuits down to 2 qubits so they are easy to simulate\n",
        "qc_t3_exact_small = QuantumCircuit.from_instructions(qc_t3_exact)\n",
        "qc_t3_approx_small = QuantumCircuit.from_instructions(qc_t3_approx)\n",
        "\n",
        "# Compute the fidelity\n",
        "exact_fid = trace_to_fidelity_2q(\n",
        "    np.trace(np.dot(Operator(qc_t3_exact_small).adjoint().data, UU))\n",
        ")\n",
        "approx_fid = trace_to_fidelity_2q(\n",
        "    np.trace(np.dot(Operator(qc_t3_approx_small).adjoint().data, UU))\n",
        ")\n",
        "print(\n",
        "    f\"Synthesis fidelity\\nExact: {exact_fid:.3f}\\nApproximate: {approx_fid:.3f}\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "382f6ffc-1d17-4c4b-8ea1-2f828c705793",
      "metadata": {
        "jp-MarkdownHeadingCollapsed": true
      },
      "source": [
        "최적화 수준을 조정하면 ECR 게이트의 수뿐만 아니라 회로의 다른 측면에도 변화가 생길 수 있습니다. 최적화 수준 설정이 레이아웃에 어떤 영향을 미치는지 확인하려면 [‘양자 컴퓨터 표현’을](/docs/guides/represent-quantum-computers) 참조하십시오.\n",
        "\n",
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 다음 단계\n",
        "\n",
        "<Admonition type=\"tip\" title=\"권장사항\">\n",
        "  * `generate_preset_passmanager` 기능에 대해 자세히 알아보려면 [번역 기본 설정 및 구성 옵션](defaults-and-configuration-options) 항목부터 시작하세요.\n",
        "  * [트랜스파일러 단계](transpiler-stages) 주제에서 트랜스필레이션에 대해 계속 알아보세요.\n",
        "  * [Compare 트랜스파일러 설정](/docs/guides/circuit-transpilation-settings) 가이드를 시도해 보세요.\n",
        "  * [반복 코드 작성](/docs/tutorials/repetition-codes) 튜토리얼을 사용해 보세요.\n",
        "  * [Transpile API](/docs/api/qiskit/transpiler) 문서를 참조하십시오.\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": 5
}