{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "fd07a3db-1aa2-4884-98db-6f68765c3edc",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"소음 모델 구축\"\n",
        "description: \"오류 관리를 위한 노이즈 모델을 구축하는 방법을 알아보세요.\"\n",
        "---\n",
        "\n",
        "<span id=\"build-noise-models\" />\n",
        "\n",
        "# 소음 모델 구축\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "35e9a88b-6872-42b0-ac4f-36bf8898f2fa",
      "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",
        "    qiskit-aer~=0.17\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "19c35f2c-437a-48b7-8c9f-9ac3526811a7",
      "metadata": {},
      "source": [
        "이 페이지는 키스킷 Aer [`noise`](https://qiskit.org/ecosystem/aer/apidocs/aer_noise.html) 모듈을 사용하여 오류가 있는 양자 회로를 시뮬레이션하기 위한 노이즈 모델을 구축하는 방법을 설명합니다. 이는 노이즈가 많은 양자 프로세서를 에뮬레이션하고 양자 알고리즘 실행에 대한 노이즈의 영향을 연구하는 데 유용합니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "85a94e7b-6b43-4a4a-a3b6-a412e1d66c7d",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.403378Z",
          "start_time": "2019-08-19T17:00:41.139269Z"
        }
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import Kraus, SuperOp\n",
        "from qiskit.visualization import plot_histogram\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_aer import AerSimulator\n",
        "\n",
        "# Import from Qiskit Aer noise module\n",
        "from qiskit_aer.noise import (\n",
        "    NoiseModel,\n",
        "    QuantumError,\n",
        "    ReadoutError,\n",
        "    depolarizing_error,\n",
        "    pauli_error,\n",
        "    thermal_relaxation_error,\n",
        ")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "da49be49-d174-413c-b05d-20236817aac2",
      "metadata": {
        "slideshow": {
          "slide_type": "slide"
        }
      },
      "source": [
        "<span id=\"qiskit-aer-noise-module\" />\n",
        "\n",
        "## Qiskit Aer `noise` 모듈\n",
        "\n",
        "키스킷 에어 `noise` 모듈에는 시뮬레이션을 위한 맞춤형 노이즈 모델을 구축할 수 있는 Python 클래스가 포함되어 있습니다. 세 가지 주요 클래스가 있습니다:\n",
        "\n",
        "1. 노이즈 시뮬레이션에 사용되는 노이즈 모델을 저장하는 `NoiseModel` 클래스입니다.\n",
        "\n",
        "2. CPTP 게이트 오류를 설명하는 `QuantumError` 클래스입니다. 이를 적용할 수 있습니다:\n",
        "   * *게이트* 또는 *재설정* 지침 후\n",
        "   * *측정* 전 지침.\n",
        "\n",
        "3. 일반적인 판독 오류를 설명하는 `ReadoutError` 클래스입니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ea2762d5-7260-4ce9-9e44-2950331ba3e7",
      "metadata": {},
      "source": [
        "<span id=\"initialize-a-noise-model-from-a-backend\" />\n",
        "\n",
        "## 백엔드에서 노이즈 모델 초기화\n",
        "\n",
        "물리적 백엔드의 최신 보정 데이터를 기반으로 매개변수를 설정하여 노이즈 모델을 초기화할 수 있습니다.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  이 예제에서는 의 모의 `FakeSherbrooke``qiskit_ibm_runtime` 백엔드를 사용하지만, Qiskit과 호환되는 실제 또는 모의 백엔드라면 어떤 것이든 사용해 볼 수 있습니다.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "b47efd06-6a64-455a-be12-07054e800a34",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "noise_model = NoiseModel.from_backend(backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "54f7cb42-dd95-4089-afbb-db9e83d41b50",
      "metadata": {},
      "source": [
        "이렇게 하면 해당 백엔드를 사용할 때 발생할 수 있는 오류를 대략적으로 추정할 수 있는 노이즈 모델이 생성됩니다. 노이즈 모델의 파라미터를 더 자세히 제어하려면 이 페이지의 나머지 부분에서 설명하는 대로 자체 노이즈 모델을 만들어야 합니다.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a4940a81-d6ab-4f15-8505-05282c67d823",
      "metadata": {},
      "source": [
        "<span id=\"quantum-errors\" />\n",
        "\n",
        "## 양자 오류\n",
        "\n",
        "객체를 `QuantumError` 직접 다루기보다는, 특정 유형의 매개변수화된 양자 오류를 자동으로 생성하는 많은 보조 함수들이 존재합니다. 이들은 `noise` 모듈에 포함되어 있으며 양자 컴퓨팅 연구에서 사용되는 다양한 일반적인 오류 유형에 대한 함수를 포함합니다. 함수명과 해당 함수가 반환하는 오류 유형은 다음과 같습니다:\n",
        "\n",
        "| 표준 오류 함수                        | 세부사항                                                                                                  |\n",
        "| ------------------------------- | ----------------------------------------------------------------------------------------------------- |\n",
        "| `kraus_error`                   | 크라우스 행렬의 목록으로 주어진 일반적인 n-쿼비트 CPTP 오류 채널 $[K_0, ...]$.                                                 |\n",
        "| `mixed_unitary_error`           | 단일 행렬과 확률의 목록으로 주어진 n-쿼비트 혼합 단일 오차 $[(U_0, p_0),...]$.                                                |\n",
        "| `coherent_unitary_error`        | 단일 유니타리 행렬로 주어진 n-큐비트 코히어런트 유니타리 오류 $U$.                                                              |\n",
        "| `pauli_error`                   | 폴리와 확률의 목록으로 주어진 n-큐비트 폴리 오류 채널(혼합 단일) $[(P_0, p_0),...]$                                             |\n",
        "| `depolarizing_error`            | 탈분극 확률로 파라미터화된 n-큐비트 탈분극 오류 채널 $p$.                                                                   |\n",
        "| `reset_error`                   | 확률 $p_0, p_1$ 에 의해 매개변수화된 상태로의 $\\vert1\\rangle$ 재설정 오류가 있는 $\\vert0\\rangle$ 단일 큐비트 재설정.                 |\n",
        "| `thermal_relaxation_error`      | 이완 시간 상수 $T_1$, $T_2$, 게이트 시간 $t$, 여기 상태 열 인구 $p_1$ 로 파라미터화된 단일 큐비트 열 이완 채널입니다.                       |\n",
        "| `phase_amplitude_damping_error` | 진폭 감쇠 파라미터 $\\lambda$, 위상 감쇠 파라미터 $\\gamma$, 여기 상태 열 인구 $p_1$ 로 주어진 단일 큐비트 일반화된 결합 위상 및 진폭 감쇠 오류 채널입니다. |\n",
        "| `amplitude_damping_error`       | 진폭 감쇠 파라미터 $\\lambda$ 와 여기 상태 열 인구 $p_1$ 로 주어진 단일 큐비트 일반화 진폭 감쇠 오류 채널입니다.                              |\n",
        "| `phase_damping_error`           | 위상 감쇠 매개변수 로 주어지는 단일 큐비트 $\\gamma$ 위상 감쇠 오류 채널.                                                        |\n",
        "\n",
        "<span id=\"combine-quantum-errors\" />\n",
        "\n",
        "### 양자 오류를 합산하다\n",
        "\n",
        "`QuantumError` 인스턴스를 구성, 텐서 곱, 텐서 확장(역순 텐서 곱)을 사용하여 결합하여 새로운 `QuantumErrors` 으로 생성할 수 있습니다:\n",
        "\n",
        "* 구성: $\\cal{E}(\\rho)=\\cal{E_2}(\\cal{E_1}(\\rho))$ as `error = error1.compose(error2)`\n",
        "* 텐서곱: $\\cal{E}(\\rho) =(\\cal{E_1}\\otimes\\cal{E_2})(\\rho)$ as `error = error1.tensor(error2)`\n",
        "* 제품 확장: $\\cal{E}(\\rho) =(\\cal{E_2}\\otimes\\cal{E_1})(\\rho)$ as `error = error1.expand(error2)`\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "cd42ec1c-a971-4dd8-913c-2a4fd4f4a845",
      "metadata": {},
      "source": [
        "<span id=\"example\" />\n",
        "\n",
        "### 예\n",
        "\n",
        "5% 단일 큐비트 비트 플립 오류를 구성합니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "437a8576-084c-499f-af7e-12b0a2fbfcd0",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.420358Z",
          "start_time": "2019-08-19T17:00:43.416062Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QuantumError on 1 qubits. Noise circuits:\n",
            "  P(0) = 0.05, Circuit = \n",
            "   ┌───┐\n",
            "q: ┤ X ├\n",
            "   └───┘\n",
            "  P(1) = 0.95, Circuit = \n",
            "   ┌───┐\n",
            "q: ┤ I ├\n",
            "   └───┘\n",
            "QuantumError on 1 qubits. Noise circuits:\n",
            "  P(0) = 0.05, Circuit = \n",
            "   ┌───┐\n",
            "q: ┤ Z ├\n",
            "   └───┘\n",
            "  P(1) = 0.95, Circuit = \n",
            "   ┌───┐\n",
            "q: ┤ I ├\n",
            "   └───┘\n"
          ]
        }
      ],
      "source": [
        "# Construct a 1-qubit bit-flip and phase-flip errors\n",
        "p_error = 0.05\n",
        "bit_flip = pauli_error([(\"X\", p_error), (\"I\", 1 - p_error)])\n",
        "phase_flip = pauli_error([(\"Z\", p_error), (\"I\", 1 - p_error)])\n",
        "print(bit_flip)\n",
        "print(phase_flip)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "d71ef2d9-e386-4649-9e1c-a7bfe7342687",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.435843Z",
          "start_time": "2019-08-19T17:00:43.432211Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QuantumError on 1 qubits. Noise circuits:\n",
            "  P(0) = 0.0025000000000000005, Circuit = \n",
            "   ┌───┐┌───┐\n",
            "q: ┤ X ├┤ Z ├\n",
            "   └───┘└───┘\n",
            "  P(1) = 0.0475, Circuit = \n",
            "   ┌───┐┌───┐\n",
            "q: ┤ X ├┤ I ├\n",
            "   └───┘└───┘\n",
            "  P(2) = 0.0475, Circuit = \n",
            "   ┌───┐┌───┐\n",
            "q: ┤ I ├┤ Z ├\n",
            "   └───┘└───┘\n",
            "  P(3) = 0.9025, Circuit = \n",
            "   ┌───┐┌───┐\n",
            "q: ┤ I ├┤ I ├\n",
            "   └───┘└───┘\n"
          ]
        }
      ],
      "source": [
        "# Compose two bit-flip and phase-flip errors\n",
        "bitphase_flip = bit_flip.compose(phase_flip)\n",
        "print(bitphase_flip)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "ffa9fd9c-3d98-4285-8daf-ee22ca2b0d55",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.460191Z",
          "start_time": "2019-08-19T17:00:43.456782Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QuantumError on 2 qubits. Noise circuits:\n",
            "  P(0) = 0.0025000000000000005, Circuit = \n",
            "     ┌───┐\n",
            "q_0: ┤ X ├\n",
            "     ├───┤\n",
            "q_1: ┤ Z ├\n",
            "     └───┘\n",
            "  P(1) = 0.0475, Circuit = \n",
            "     ┌───┐\n",
            "q_0: ┤ I ├\n",
            "     ├───┤\n",
            "q_1: ┤ Z ├\n",
            "     └───┘\n",
            "  P(2) = 0.0475, Circuit = \n",
            "     ┌───┐\n",
            "q_0: ┤ X ├\n",
            "     ├───┤\n",
            "q_1: ┤ I ├\n",
            "     └───┘\n",
            "  P(3) = 0.9025, Circuit = \n",
            "     ┌───┐\n",
            "q_0: ┤ I ├\n",
            "     ├───┤\n",
            "q_1: ┤ I ├\n",
            "     └───┘\n"
          ]
        }
      ],
      "source": [
        "# Tensor product two bit-flip and phase-flip errors with\n",
        "# bit-flip on qubit-0, phase-flip on qubit-1\n",
        "error2 = phase_flip.tensor(bit_flip)\n",
        "print(error2)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "80e275c7-b856-4301-9266-0eb7a783e0f8",
      "metadata": {},
      "source": [
        "<span id=\"convert-to-and-from-quantumchannel-operators\" />\n",
        "\n",
        "### QuantumChannel 연산자 간 변환\n",
        "\n",
        "또한 키스킷 에어의 `QuantumError` 객체와 키스킷의 `QuantumChannel` 객체 사이를 오가며 변환할 수 있습니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "2006e158-bea6-4e18-a06c-31b567401b6c",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.482424Z",
          "start_time": "2019-08-19T17:00:43.473779Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Kraus([[[-9.74679434e-01+0.j,  0.00000000e+00+0.j],\n",
            "        [ 0.00000000e+00+0.j, -9.74679434e-01+0.j]],\n",
            "\n",
            "       [[ 0.00000000e+00+0.j,  2.23606798e-01+0.j],\n",
            "        [ 2.23606798e-01+0.j, -4.96506831e-17+0.j]]],\n",
            "      input_dims=(2,), output_dims=(2,))\n"
          ]
        }
      ],
      "source": [
        "# Convert to Kraus operator\n",
        "bit_flip_kraus = Kraus(bit_flip)\n",
        "print(bit_flip_kraus)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "425a9b6f-e078-4a48-ab1c-a5621a8b773a",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.509521Z",
          "start_time": "2019-08-19T17:00:43.503976Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "SuperOp([[1. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n",
            "         [0. +0.j, 0.9+0.j, 0. +0.j, 0. +0.j],\n",
            "         [0. +0.j, 0. +0.j, 0.9+0.j, 0. +0.j],\n",
            "         [0. +0.j, 0. +0.j, 0. +0.j, 1. +0.j]],\n",
            "        input_dims=(2,), output_dims=(2,))\n"
          ]
        }
      ],
      "source": [
        "# Convert to Superoperator\n",
        "phase_flip_sop = SuperOp(phase_flip)\n",
        "print(phase_flip_sop)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "97624c98-f1c0-4a9b-be5b-2c664d368e9f",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.794037Z",
          "start_time": "2019-08-19T17:00:43.778223Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QuantumError on 1 qubits. Noise circuits:\n",
            "  P(0) = 1.0, Circuit = \n",
            "   ┌───────┐\n",
            "q: ┤ kraus ├\n",
            "   └───────┘\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Convert back to a quantum error\n",
        "print(QuantumError(bit_flip_kraus))\n",
        "\n",
        "# Check conversion is equivalent to original error\n",
        "QuantumError(bit_flip_kraus) == bit_flip"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "7f663dfe-e238-418c-bff4-c751468a6678",
      "metadata": {},
      "source": [
        "<span id=\"readout-error\" />\n",
        "\n",
        "### 읽기 오류\n",
        "\n",
        "고전적 판독 오류는 할당 확률 벡터 목록으로 $P(A|B)$ 지정됩니다:\n",
        "\n",
        "* $A$ 는 *기록된* 클래식 비트 값입니다\n",
        "* $B$ 는 측정에서 반환된 *실제* 비트 값입니다\n",
        "\n",
        "예를 들어, 1 큐비트의 경우: $ P(A|B) = [P(A|0), P(A|1)]$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "f70f39f8-dec5-46cb-a194-4768cffbd6db",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:44.659598Z",
          "start_time": "2019-08-19T17:00:44.654818Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "ReadoutError([[0.95 0.05]\n",
              " [0.1  0.9 ]])"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Measurement misassignment probabilities\n",
        "p0given1 = 0.1\n",
        "p1given0 = 0.05\n",
        "\n",
        "ReadoutError([[1 - p1given0, p1given0], [p0given1, 1 - p0given1]])"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "e77fcdcd-346c-4f78-83eb-0c32359ba62c",
      "metadata": {},
      "source": [
        "양자 오류와 마찬가지로 `compose`, `tensor` 및 `expand` 를 사용하여 판독 오류를 결합할 수도 있습니다.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "b2258427-2283-435c-b964-60423c3b0f39",
      "metadata": {},
      "source": [
        "<span id=\"add-errors-to-a-noise-model\" />\n",
        "\n",
        "## 노이즈 모델에 오류를 추가하다\n",
        "\n",
        "노이즈 모델에 양자 오류를 추가할 때는 양자 오류가 작용하는 *명령어* 유형과 이를 적용할 큐비트를 지정해야 합니다. 양자 오류에는 두 가지 경우가 있습니다:\n",
        "\n",
        "1. 모든 큐비트 양자 오류\n",
        "2. 특정 큐비트 양자 오류\n",
        "\n",
        "<span id=\"1-all-qubit-quantum-error\" />\n",
        "\n",
        "### 1. 모든 큐비트 양자 오류\n",
        "\n",
        "이는 명령어가 어떤 큐비트에 작용하는지에 관계없이 모든 명령어 발생에 동일한 오류를 적용합니다.\n",
        "\n",
        "`noise_model.add_all_qubit_quantum_error(error, instructions)` 로 추가됩니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "0a5ae501-87e5-4930-96c1-b0af2d6993ce",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:45.882254Z",
          "start_time": "2019-08-19T17:00:45.877630Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "NoiseModel:\n",
            "  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']\n",
            "  Instructions with noise: ['u3', 'u1', 'u2']\n",
            "  All-qubits errors: ['u1', 'u2', 'u3']\n"
          ]
        }
      ],
      "source": [
        "# Create an empty noise model\n",
        "noise_model = NoiseModel()\n",
        "\n",
        "# Add depolarizing error to all single qubit u1, u2, u3 gates\n",
        "error = depolarizing_error(0.05, 1)\n",
        "noise_model.add_all_qubit_quantum_error(error, [\"u1\", \"u2\", \"u3\"])\n",
        "\n",
        "# Print noise model info\n",
        "print(noise_model)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "f2f360be-5d7b-435d-980a-e20450a0267f",
      "metadata": {},
      "source": [
        "<span id=\"2-specific-qubit-quantum-error\" />\n",
        "\n",
        "### 2. 특정 큐비트 양자 오류\n",
        "\n",
        "이렇게 하면 지정된 큐비트 목록에 작용하는 모든 명령어 발생에 오류가 적용됩니다. 예를 들어, 2큐비트 게이트의 경우 큐비트 \\[0, 1에] 적용되는 오류는 큐비트 \\[1, 0에] 적용되는 오류와 다르므로 큐비트의 순서가 중요하다는 점에 유의하세요.\n",
        "\n",
        "`noise_model.add_quantum_error(error, instructions, qubits)` 로 추가됩니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "05d7e61f-75dc-488b-bfab-c00ad87fe1ea",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:46.615959Z",
          "start_time": "2019-08-19T17:00:46.612055Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "NoiseModel:\n",
            "  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']\n",
            "  Instructions with noise: ['u3', 'u1', 'u2']\n",
            "  Qubits with noise: [0]\n",
            "  Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]\n"
          ]
        }
      ],
      "source": [
        "# Create an empty noise model\n",
        "noise_model = NoiseModel()\n",
        "\n",
        "# Add depolarizing error to all single qubit u1, u2, u3 gates on qubit 0 only\n",
        "error = depolarizing_error(0.05, 1)\n",
        "noise_model.add_quantum_error(error, [\"u1\", \"u2\", \"u3\"], [0])\n",
        "\n",
        "# Print noise model info\n",
        "print(noise_model)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "c2dc1bb3-66a9-4d63-8341-0c4c45ed89d6",
      "metadata": {},
      "source": [
        "<span id=\"note-on-non-local-qubit-quantum-error\" />\n",
        "\n",
        "### 비국소 큐비트 양자 오류에 관한 참고 사항\n",
        "\n",
        "`NoiseModel` 비국소 큐비트 양자 오류의 추가를 지원하지 않습니다. 이는. `NoiseModel`외부에서 처리해야 합니다. 즉, [특정](/docs/guides/custom-transpiler-pass) 조건 하에서 회로에 양자 오류를 삽입해야 한다면, 직접 트랜스파일러 패스(`TransformationPass`)를 작성하여 시뮬레이터를 실행하기 직전에 해당 패스를 실행해야 합니다.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "2617effb-ae2e-44a3-8a7b-28b68b756ac6",
      "metadata": {},
      "source": [
        "<span id=\"execute-a-noisy-simulation-with-a-noise-model\" />\n",
        "\n",
        "### 노이즈 모델을 사용하여 노이즈 시뮬레이션을 실행합니다\n",
        "\n",
        "`AerSimulator(noise_model=noise_model)` 명령은 주어진 노이즈 모델에 맞게 구성된 시뮬레이터를 반환합니다. 시뮬레이터의 노이즈 모델을 설정하는 것 외에도 노이즈 모델의 게이트에 따라 시뮬레이터의 기본 게이트도 오버라이드합니다.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "7df257fd-424b-486e-a607-7d4c392b4c98",
      "metadata": {
        "slideshow": {
          "slide_type": "subslide"
        }
      },
      "source": [
        "<span id=\"noise-model-examples\" />\n",
        "\n",
        "## 소음 모델 예시\n",
        "\n",
        "이제 소음 모델의 몇 가지 예를 들어 보겠습니다. 시연을 위해 우리는 n-큐비트 GHZ 상태를 생성하는 간단한 테스트 회로를 사용합니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "43df6b1f-b07a-4bf2-bba6-c7ec35eec620",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:48.817405Z",
          "start_time": "2019-08-19T17:00:48.806966Z"
        },
        "slideshow": {
          "slide_type": "fragment"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "        ┌───┐                ░ ┌─┐         \n",
            "   q_0: ┤ H ├──■─────────────░─┤M├─────────\n",
            "        └───┘┌─┴─┐           ░ └╥┘┌─┐      \n",
            "   q_1: ─────┤ X ├──■────────░──╫─┤M├──────\n",
            "             └───┘┌─┴─┐      ░  ║ └╥┘┌─┐   \n",
            "   q_2: ──────────┤ X ├──■───░──╫──╫─┤M├───\n",
            "                  └───┘┌─┴─┐ ░  ║  ║ └╥┘┌─┐\n",
            "   q_3: ───────────────┤ X ├─░──╫──╫──╫─┤M├\n",
            "                       └───┘ ░  ║  ║  ║ └╥┘\n",
            "meas: 4/════════════════════════╩══╩══╩══╩═\n",
            "                                0  1  2  3 \n"
          ]
        }
      ],
      "source": [
        "# System Specification\n",
        "n_qubits = 4\n",
        "circ = QuantumCircuit(n_qubits)\n",
        "\n",
        "# Test Circuit\n",
        "circ.h(0)\n",
        "for qubit in range(n_qubits - 1):\n",
        "    circ.cx(qubit, qubit + 1)\n",
        "circ.measure_all()\n",
        "print(circ)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "eea319ec-8764-4d77-8863-c5a2e9ae370a",
      "metadata": {},
      "source": [
        "<span id=\"ideal-simulation\" />\n",
        "\n",
        "### 이상적인 시뮬레이션\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "bc713d11-755e-41e4-94f0-1ed76e3c2469",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:50.560988Z",
          "start_time": "2019-08-19T17:00:50.415545Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/build-noise-models/extracted-outputs/bc713d11-755e-41e4-94f0-1ed76e3c2469-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Ideal simulator and execution\n",
        "sim_ideal = AerSimulator()\n",
        "result_ideal = sim_ideal.run(circ).result()\n",
        "plot_histogram(result_ideal.get_counts(0))"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "ac7111a6-04dc-4068-9044-54d93e745116",
      "metadata": {
        "slideshow": {
          "slide_type": "subslide"
        }
      },
      "source": [
        "<span id=\"noise-example-1-basic-bit-flip-error-noise-model\" />\n",
        "\n",
        "## 잡음 예시 1: 기본 비트 플립 오류 잡음 모델\n",
        "\n",
        "양자 정보 이론 연구에서 흔히 볼 수 있는 간단한 장난감 잡음 모델을 예로 들어 보겠습니다:\n",
        "\n",
        "* 단일 큐비트 게이트를 적용할 때, 큐비트의 상태를 확률로 뒤집습니다 `p_gate1`.\n",
        "* 2큐비트 게이트를 적용할 때는 각 큐비트에 단일 큐비트 오류를 적용합니다.\n",
        "* 큐비트를 재설정할 때 0이 아닌 1로 재설정할 확률 `p_reset`.\n",
        "* 큐비트를 측정할 때 큐비트의 상태를 확률로 뒤집습니다 `p_meas`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "fee3c383-0499-4d1f-be9f-32b41a31f561",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:51.543615Z",
          "start_time": "2019-08-19T17:00:51.536564Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "NoiseModel:\n",
            "  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']\n",
            "  Instructions with noise: ['u1', 'u2', 'cx', 'measure', 'reset', 'u3']\n",
            "  All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']\n"
          ]
        }
      ],
      "source": [
        "# Example error probabilities\n",
        "p_reset = 0.03\n",
        "p_meas = 0.1\n",
        "p_gate1 = 0.05\n",
        "\n",
        "# QuantumError objects\n",
        "error_reset = pauli_error([(\"X\", p_reset), (\"I\", 1 - p_reset)])\n",
        "error_meas = pauli_error([(\"X\", p_meas), (\"I\", 1 - p_meas)])\n",
        "error_gate1 = pauli_error([(\"X\", p_gate1), (\"I\", 1 - p_gate1)])\n",
        "error_gate2 = error_gate1.tensor(error_gate1)\n",
        "\n",
        "# Add errors to noise model\n",
        "noise_bit_flip = NoiseModel()\n",
        "noise_bit_flip.add_all_qubit_quantum_error(error_reset, \"reset\")\n",
        "noise_bit_flip.add_all_qubit_quantum_error(error_meas, \"measure\")\n",
        "noise_bit_flip.add_all_qubit_quantum_error(error_gate1, [\"u1\", \"u2\", \"u3\"])\n",
        "noise_bit_flip.add_all_qubit_quantum_error(error_gate2, [\"cx\"])\n",
        "\n",
        "print(noise_bit_flip)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "dbf3f5ee-0f66-4a37-b512-038a21ce2ed2",
      "metadata": {},
      "source": [
        "<span id=\"execute-the-noisy-simulation\" />\n",
        "\n",
        "### 잡음이 있는 시뮬레이션을 실행하십시오\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "abeb9f09-d762-406d-983e-0357ade59636",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:52.951874Z",
          "start_time": "2019-08-19T17:00:52.687440Z"
        },
        "slideshow": {
          "slide_type": "-"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/build-noise-models/extracted-outputs/abeb9f09-d762-406d-983e-0357ade59636-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create noisy simulator backend\n",
        "sim_noise = AerSimulator(noise_model=noise_bit_flip)\n",
        "\n",
        "# Transpile circuit for noisy basis gates\n",
        "passmanager = generate_preset_pass_manager(\n",
        "    optimization_level=3, backend=sim_noise\n",
        ")\n",
        "circ_tnoise = passmanager.run(circ)\n",
        "\n",
        "# Run and get counts\n",
        "result_bit_flip = sim_noise.run(circ_tnoise).result()\n",
        "counts_bit_flip = result_bit_flip.get_counts(0)\n",
        "\n",
        "# Plot noisy output\n",
        "plot_histogram(counts_bit_flip)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "ced838fa-105d-4bdf-b240-51b78ff18e29",
      "metadata": {},
      "source": [
        "<span id=\"example-2-t1/t2-thermal-relaxation\" />\n",
        "\n",
        "## 예시 2: T1/T2 열적 이완\n",
        "\n",
        "이제 큐비트 환경에서 열 완화를 기반으로 하는 보다 현실적인 오류 모델을 고려해 보겠습니다:\n",
        "\n",
        "* 각 큐비트는 열 완화 시간 상수 $T_1$ 와 디페이징 시간 상수 $T_2$ 로 파라미터화됩니다.\n",
        "* $T_2 \\le 2 T_1$ 이 있어야 합니다.\n",
        "* 명령어의 오류율은 게이트 시간과 큐비트 $T_1$, $T_2$ 값에 의해 결정됩니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "b2ab3829-98fa-4b5d-b622-25c155abfdf0",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:54.577456Z",
          "start_time": "2019-08-19T17:00:54.491018Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "NoiseModel:\n",
            "  Basis gates: ['cx', 'id', 'rz', 'sx', 'u2', 'u3']\n",
            "  Instructions with noise: ['u2', 'cx', 'measure', 'reset', 'u3']\n",
            "  Qubits with noise: [0, 1, 2, 3]\n",
            "  Specific qubit errors: [('reset', (0,)), ('reset', (1,)), ('reset', (2,)), ('reset', (3,)), ('measure', (0,)), ('measure', (1,)), ('measure', (2,)), ('measure', (3,)), ('u2', (0,)), ('u2', (1,)), ('u2', (2,)), ('u2', (3,)), ('u3', (0,)), ('u3', (1,)), ('u3', (2,)), ('u3', (3,)), ('cx', (0, 0)), ('cx', (0, 1)), ('cx', (0, 2)), ('cx', (0, 3)), ('cx', (1, 0)), ('cx', (1, 1)), ('cx', (1, 2)), ('cx', (1, 3)), ('cx', (2, 0)), ('cx', (2, 1)), ('cx', (2, 2)), ('cx', (2, 3)), ('cx', (3, 0)), ('cx', (3, 1)), ('cx', (3, 2)), ('cx', (3, 3))]\n"
          ]
        }
      ],
      "source": [
        "# T1 and T2 values for qubits 0-3\n",
        "T1s = np.random.normal(\n",
        "    50e3, 10e3, 4\n",
        ")  # Sampled from normal distribution mean 50 microsec\n",
        "T2s = np.random.normal(\n",
        "    70e3, 10e3, 4\n",
        ")  # Sampled from normal distribution mean 50 microsec\n",
        "\n",
        "# Truncate random T2s <= T1s\n",
        "T2s = np.array([min(T2s[j], 2 * T1s[j]) for j in range(4)])\n",
        "\n",
        "# Instruction times (in nanoseconds)\n",
        "time_u1 = 0  # virtual gate\n",
        "time_u2 = 50  # (single X90 pulse)\n",
        "time_u3 = 100  # (two X90 pulses)\n",
        "time_cx = 300\n",
        "time_reset = 1000  # 1 microsecond\n",
        "time_measure = 1000  # 1 microsecond\n",
        "\n",
        "# QuantumError objects\n",
        "errors_reset = [\n",
        "    thermal_relaxation_error(t1, t2, time_reset) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_measure = [\n",
        "    thermal_relaxation_error(t1, t2, time_measure) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_u1 = [\n",
        "    thermal_relaxation_error(t1, t2, time_u1) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_u2 = [\n",
        "    thermal_relaxation_error(t1, t2, time_u2) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_u3 = [\n",
        "    thermal_relaxation_error(t1, t2, time_u3) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_cx = [\n",
        "    [\n",
        "        thermal_relaxation_error(t1a, t2a, time_cx).expand(\n",
        "            thermal_relaxation_error(t1b, t2b, time_cx)\n",
        "        )\n",
        "        for t1a, t2a in zip(T1s, T2s)\n",
        "    ]\n",
        "    for t1b, t2b in zip(T1s, T2s)\n",
        "]\n",
        "\n",
        "# Add errors to noise model\n",
        "noise_thermal = NoiseModel()\n",
        "for j in range(4):\n",
        "    noise_thermal.add_quantum_error(errors_reset[j], \"reset\", [j])\n",
        "    noise_thermal.add_quantum_error(errors_measure[j], \"measure\", [j])\n",
        "    noise_thermal.add_quantum_error(errors_u1[j], \"u1\", [j])\n",
        "    noise_thermal.add_quantum_error(errors_u2[j], \"u2\", [j])\n",
        "    noise_thermal.add_quantum_error(errors_u3[j], \"u3\", [j])\n",
        "    for k in range(4):\n",
        "        noise_thermal.add_quantum_error(errors_cx[j][k], \"cx\", [j, k])\n",
        "\n",
        "print(noise_thermal)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a3dd27c5-c032-44b9-ada9-19280e8a0140",
      "metadata": {},
      "source": [
        "<span id=\"execute-the-noisy-simulation\" />\n",
        "\n",
        "### 잡음이 있는 시뮬레이션을 실행하십시오\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "ff52bf52-1323-40fc-a631-2b1889b21b20",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:55.689241Z",
          "start_time": "2019-08-19T17:00:55.515394Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/build-noise-models/extracted-outputs/ff52bf52-1323-40fc-a631-2b1889b21b20-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Run the noisy simulation\n",
        "sim_thermal = AerSimulator(noise_model=noise_thermal)\n",
        "\n",
        "# Transpile circuit for noisy basis gates\n",
        "passmanager = generate_preset_pass_manager(\n",
        "    optimization_level=3, backend=sim_thermal\n",
        ")\n",
        "circ_tthermal = passmanager.run(circ)\n",
        "\n",
        "# Run and get counts\n",
        "result_thermal = sim_thermal.run(circ_tthermal).result()\n",
        "counts_thermal = result_thermal.get_counts(0)\n",
        "\n",
        "# Plot noisy output\n",
        "plot_histogram(counts_thermal)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0df436e1-b43c-41b1-9581-a4d530e51a7b",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 다음 단계\n",
        "\n",
        "<Admonition type=\"tip\" title=\"권장사항\">\n",
        "  * 노이즈가 있는 회로를 시뮬레이션하려면 [‘Qiskit Aer 기본 요소를 사용한 정확한 시뮬레이션 및 노이즈가 있는 시뮬레이션’을](/docs/guides/simulate-with-qiskit-sdk-primitives) 참조하십시오.\n",
        "  * [키스킷 에어 노이즈 모듈](https://qiskit.org/ecosystem/aer/apidocs/aer_noise.html) 레퍼런스를 검토하세요.\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
}