{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "066d7e4d-a975-4519-b56f-095f861be3ac",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"견적기의 입력 및 출력\"\n",
        "description: \"Estimator 기본 요소의 입력 및 출력 형식을 이해합니다\"\n",
        "---\n",
        "\n",
        "<span id=\"estimator-inputs-and-outputs\" />\n",
        "\n",
        "# 견적기의 입력 및 출력\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "23e7dff0-fde5-4c2d-89c2-fc5ab99240fe",
      "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": "90d0c1e0-28e7-48da-a35f-6016fddea82c",
      "metadata": {},
      "source": [
        "이 페이지에서는 IBM Quantum® 컴퓨팅 리소스에서 워크로드를 실행하는 ‘ IBM Quantum ’ 에스티메이터 프리미티브의 입력 및 출력에 대한 개요를 제공합니다. Estimator를 사용하면 [**‘Primitive Unified Bloc( PUB )**](/docs/guides/primitive-input-output#pubs) ’이라는 데이터 구조를 활용하여 벡터화된 워크로드를 효율적으로 정의할 수 있습니다. 이들은 Estimator 프리미티브의 [`run()`](/docs/api/qiskit-ibm-runtime/estimator-v2#run) 메서드에 입력으로 사용되며, 이 메서드는 정의된 워크로드를 작업으로 실행합니다. 그런 다음, 작업이 완료되면 결과는 사용된 PUB와 프리미티브에서 지정된 런타임 옵션 모두에 따라 달라지는 형식으로 반환됩니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "83a5fdd8-6547-47c7-9441-a7458edc7896",
      "metadata": {},
      "source": [
        "<span id=\"inputs\" />\n",
        "\n",
        "## 입력\n",
        "\n",
        "각 PUB 파일은 다음과 같은 형식을 따릅니다:\n",
        "\n",
        "(`<single circuit>`, `<one or more observables>`, `<optional one or more parameter values>`, `<optional precision>`),\n",
        "\n",
        "선택적 매개변수는 리스트이거나 `parameter values` 단일 매개변수일 수 있습니다. [‘기본 입력 및 출력](primitive-input-output#broadcasting-rules) ’ 항목에 설명된 대로, 관측 가능 객체(observables)의 요소와 매개변수 값은 NumPy 의 브로드캐스팅 규칙에 따라 결합되며, 브로드캐스팅된 형상의 각 요소에 대해 하나의 기대값 추정치가 반환됩니다.\n",
        "\n",
        "<Admonition types=\"note\">\n",
        "  입력값에 측정값이 포함되어 있으면 무시됩니다.\n",
        "</Admonition>\n",
        "\n",
        "Estimator 기본 요소의 경우, PUB 에는 최대 네 개의 값을 포함할 수 있습니다:\n",
        "\n",
        "* 하나 이상의 [`Parameter`](/docs/api/qiskit/qiskit.circuit.Parameter) 객체를 포함할 수 있는 단일 `QuantumCircuit`객체\n",
        "* 추정할 기대값을 지정하는 하나 이상의 관측값 목록으로, 배열 형태로 배열된 것(예를 들어, 단일 관측값은 0차원 배열로, 관측값 목록은 1차원 배열로 표현되는 등). 데이터는, `SparsePauliOp`, `PauliList`, 또는 `Pauli` 등의 형식 `ObservablesArrayLike` 중 `str`하나를 가질 수 있습니다.\n",
        "  <Admonition type=\"note\" title=\"통근 관련 관측 변수\">\n",
        "    * [이 방법을](/docs/api/qiskit/qiskit.quantum_info.PauliList#group_qubit_wise_commuting) 사용하면 **동일한 PUB 에 속한** 이동 관측값들이 한데 묶입니다.\n",
        "    * 서로 다른 PUB에 있는 통근 관측값은, 비록 동일한 회로를 공유하더라도, 동일한 측정값을 사용하여 추정되지 않습니다. 각 PUB 는 서로 다른 측정 기준을 나타내므로, 각 PUB 에 대해 별도의 측정이 필요합니다.\n",
        "    * 통근 관측값들이 동일한 측정값을 사용하여 추정되도록 하려면, 이를 동일한 PUB 내에 그룹화하십시오.\n",
        "  </Admonition>\n",
        "* 회로를 바인딩할 매개변수 값들의 모음. 이는 단일 배열형 객체로 지정할 수 있으며, 이 객체의 마지막 인덱스는 회로 `Parameter` 객체 수를 초과하거나, 회로에 객체가 `Parameter` 없는 경우 생략되거나(또는 동일하게 설정됨 `None`) 합니다.\n",
        "* (선택 사항) 추정할 기대값의 목표 정밀도\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "846b3109-02a1-4783-ad3f-1c22f753c324",
      "metadata": {},
      "source": [
        "***\n",
        "\n",
        "다음 코드는 프라이머리 `Estimator` (primitive)에 대한 벡터화된 입력 예시를 보여주고, 이를 IBM® 백엔드에서 단일 `RuntimeJobV2 ` 객체로 실행합니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "2f50a9f5-2cc1-4d83-9fe1-1b3a8be0d766",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit import (\n",
        "    Parameter,\n",
        "    QuantumCircuit,\n",
        ")\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "\n",
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    EstimatorV2 as Estimator,\n",
        ")\n",
        "\n",
        "import numpy as np\n",
        "\n",
        "# Instantiate runtime service and get\n",
        "# the least busy backend\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Define a circuit with two parameters.\n",
        "circuit = QuantumCircuit(2)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.ry(Parameter(\"a\"), 0)\n",
        "circuit.rz(Parameter(\"b\"), 0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.h(0)\n",
        "\n",
        "# Transpile the circuit\n",
        "pm = generate_preset_pass_manager(optimization_level=1, backend=backend)\n",
        "transpiled_circuit = pm.run(circuit)\n",
        "layout = transpiled_circuit.layout\n",
        "\n",
        "# Now define a sweep over parameter values, the last axis of dimension 2 is\n",
        "# for the two parameters \"a\" and \"b\"\n",
        "params = np.vstack(\n",
        "    [\n",
        "        np.linspace(-np.pi, np.pi, 100),\n",
        "        np.linspace(-4 * np.pi, 4 * np.pi, 100),\n",
        "    ]\n",
        ").T\n",
        "\n",
        "# Define three observables. The inner length-1 lists cause this array of\n",
        "# observables to have shape (3, 1), rather than shape (3,) if they were\n",
        "# omitted.\n",
        "observables = [\n",
        "    [SparsePauliOp([\"XX\", \"IY\"], [0.5, 0.5])],\n",
        "    [SparsePauliOp(\"XX\")],\n",
        "    [SparsePauliOp(\"IY\")],\n",
        "]\n",
        "# Apply the same layout as the transpiled circuit.\n",
        "observables = [\n",
        "    [observable.apply_layout(layout) for observable in observable_set]\n",
        "    for observable_set in observables\n",
        "]\n",
        "\n",
        "# Estimate the expectation value for all 300 combinations of observables\n",
        "# and parameter values, where the pub result will have shape (3, 100).\n",
        "#\n",
        "# This shape is due to our array of parameter bindings having shape\n",
        "# (100, 2), combined with our array of observables having shape (3, 1).\n",
        "estimator_pub = (transpiled_circuit, observables, params)\n",
        "\n",
        "# Instantiate the new Estimator object, then run the transpiled circuit\n",
        "# using the set of parameters and observables.\n",
        "estimator = Estimator(mode=backend)\n",
        "job = estimator.run([estimator_pub])\n",
        "result = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "90dccb20-1848-4367-a12d-434110ad5a5c",
      "metadata": {},
      "source": [
        "<span id=\"outputs\" />\n",
        "\n",
        "## 출력\n",
        "\n",
        "하나 이상의 PUB가 실행을 위해 QPU로 전송되고 작업이 성공적으로 완료되면, 데이터는 `RuntimeJobV2.result()` 메서드를 호출하여 액세스할 수 있는 [`PrimitiveResult`](/docs/api/qiskit/qiskit.primitives.PrimitiveResult) 컨테이너 객체로 반환됩니다.\n",
        "\n",
        "이 객체에는 각 [`PubResult`](/docs/api/qiskit/qiskit.primitives.PubResult)PUB 에 대한 `PrimitiveResult` 실행 결과를 포함하는 객체들의 반복 가능한 목록이 포함되어 있습니다.\n",
        "\n",
        "이 목록의 각 요소는 프라이머리(primitive)의 `run()` 메서드에 제출된 각 작업-유닛( PUB )에 해당합니다(예를 들어, 20개의 PUB로 제출된 작업은 각 작업-유닛( PUB )에 하나씩 대응하는 20개의 `PubResult` 객체 목록을 포함하는 객체를 `PrimitiveResult` 반환합니다).\n",
        "\n",
        "각 Estimator `PubResult` 기본 객체에는 최소한 기대값 배열(`PubResult.data.evs`)과 관련 표준편차(사용된 `resilience_level` 에 따라 `PubResult.data.ensemble_standard_error` 또는 `PubResult.data.stds` )가 포함되지만, 지정된 오차 완화 옵션에 따라 더 많은 데이터를 포함할 수도 있습니다.\n",
        "\n",
        "각 `PubResult` 객체는 속성과 `data` 속성을 `metadata` 모두 가지고 있습니다.\n",
        "\n",
        "* 이 `data` 속성은 실제 측정값, 표준 편차 등을 포함하는 사용자 [`DataBin`](/docs/api/qiskit/qiskit.primitives.DataBin) 정의된 데이터입니다.\n",
        "* 이 작업은 관련 작업 그룹( `DataBin`PUB )의 형태나 구조에 따라 다양한 속성을 가지며, 작업을 제출하는 데 사용된 기본 요소(primitive)에서 지정한 오류 완화 옵션(예: [ZNE](/docs/guides/error-mitigation-and-suppression-techniques#zero-noise-extrapolation-zne) 또는 [PEC](/docs/guides/error-mitigation-and-suppression-techniques#probabilistic-error-cancellation-pec) )에 따라서도 달라집니다.\n",
        "* 이 `metadata` 속성에는 사용된 런타임 및 오류 완화 옵션에 대한 정보가 포함되어 있습니다(이에 대해서는 이 페이지의 [‘결과 메타데이터](#result-metadata) ’ 섹션에서 나중에 설명합니다).\n",
        "\n",
        "다음은 Estimator 출력의 데이터 `PrimitiveResult` 구조에 대한 시각적 개요입니다:\n",
        "\n",
        "```\n",
        "└── PrimitiveResult\n",
        "    ├── PubResult[0]\n",
        "    │   ├── metadata\n",
        "    │   └── data  ## In the form of a DataBin object\n",
        "    │       ├── evs\n",
        "    │       │   └── List of estimated expectation values in the shape\n",
        "    |       |         specified by the first pub\n",
        "    │       └── stds\n",
        "    │           └── List of calculated standard deviations in the\n",
        "    |                 same shape as above\n",
        "    ├── PubResult[1]\n",
        "    |   ├── metadata\n",
        "    |   └── data  ## In the form of a DataBin object\n",
        "    |       ├── evs\n",
        "    |       │   └── List of estimated expectation values in the shape\n",
        "    |       |        specified by the second pub\n",
        "    |       └── stds\n",
        "    |           └── List of calculated standard deviations in the\n",
        "    |                same shape as above\n",
        "    ├── ...\n",
        "    ├── ...\n",
        "    └── ...\n",
        "```\n",
        "\n",
        "간단히 말해, 하나의 작업은 객체를 `PrimitiveResult` 반환하며 하나 이상의 `PubResult` 객체로 구성된 목록을 포함합니다. 그런 다음 이 `PubResult` 객체들은 해당 작업에 제출된 각 PUB 에 대한 측정 데이터를 저장합니다.\n",
        "\n",
        "아래 코드 조각은 앞서 생성한 작업의 (및 관련 `PubResult``PrimitiveResult` ) 형식을 설명합니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "53a4d5ae-109b-452b-bbc5-2d7940c5182c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The result of the submitted job had 1 PUBs and has a value:\n",
            " PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(3, 100), dtype=float64>), stds=np.ndarray(<shape=(3, 100), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(3, 100), dtype=float64>), shape=(3, 100)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})\n",
            "\n",
            "The associated PubResult of this job has the following data bins:\n",
            " {result[0].data}\n",
            "\n",
            "And this DataBin has attributes: dict_keys(['evs', 'stds', 'ensemble_standard_error'])\n",
            "Recall that this shape is due to our array of parameter binding setshaving shape (100, 2), where 2 is the number of parameters in the circuit, combined with our array of observables having shape (3, 1). \n",
            "\n",
            "The expectation values measured from this PUB are: \n",
            "{result[0].data.evs}\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    f\"The result of the submitted job had {len(result)} \"\n",
        "    f\"PUBs and has a value:\\n {result}\\n\"\n",
        ")\n",
        "print(\n",
        "    \"The associated PubResult of this job has the following data bins:\\n \"\n",
        "    \"{result[0].data}\\n\"\n",
        ")\n",
        "print(f\"And this DataBin has attributes: {result[0].data.keys()}\")\n",
        "print(\n",
        "    \"Recall that this shape is due to our array of parameter binding sets\"\n",
        "    \"having shape (100, 2), where 2 is the number of parameters in the \"\n",
        "    \"circuit, combined with our array of observables having shape (3, 1). \\n\"\n",
        ")\n",
        "with np.printoptions(threshold=200):\n",
        "    print(\n",
        "        \"The expectation values measured from this PUB are: \\n\"\n",
        "        \"{result[0].data.evs}\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "000ade51-d940-45f9-84ea-16ad283a930f",
      "metadata": {},
      "source": [
        "<span id=\"how-the-estimator-primitive-calculates-error\" />\n",
        "\n",
        "#### Estimator 기본 요소가 오차를 계산하는 방식\n",
        "\n",
        "Estimator는 입력 PUB에 전달된 관측값(의 `DataBin`필드 `evs` )의 평균을 추정하는 것 외에도, 해당 기대값과 관련된 오차의 추정치를 제공하려고 시도합니다. 모든 Estimator 쿼리는 각 기대값에 대해 평균의 표준오차와 같은 수치를 해당 `stds` 필드에 채워 넣지만, 일부 오차 완화 옵션은 와 같은 추가 정보를 `ensemble_standard_error`생성하기도 합니다.\n",
        "\n",
        "단일 관측량 $\\mathcal{O}$ 을 고려해 보자. [ZNE가](/docs/guides/error-mitigation-and-suppression-techniques#zero-noise-extrapolation-zne) 없는 경우, 추정기 실행의 각 샷(shot)은 기대값 $\\langle \\mathcal{O} \\rangle$ 에 대한 점 추정치를 제공하는 것으로 볼 수 있다. 만약 점 추정치들이 벡터에 포함되어 `Os` 있다면, 에서 반환되는 `ensemble_standard_error` 값은 다음과 같다(여기서 $\\sigma_{\\mathcal{O}}$ 는 [기대값](/docs/api/qiskit/qiskit.primitives.BackendEstimatorV2) 추정치의 표준편차이고, $N_{shots}$ 는 샷의 개수이다):\n",
        "\n",
        "$\\frac{ \\sigma_{\\mathcal{O}} }{ \\sqrt{N_{shots}} },$\n",
        "\n",
        "모든 샷을 하나의 앙상블로 간주하는 방식이다. 게이트 [트위링](/docs/guides/error-mitigation-and-suppression-techniques#pauli-twirling) (`twirling.enable_gates = True`)을 요청한 경우, $\\langle \\mathcal{O} \\rangle$ 의 점별 추정치를 공통된 트위링을 공유하는 집합들로 분류할 수 있습니다. 이 추정값의 집합들을 라고 `O_twirls` 부르며, 그 개수는 `num_randomizations` (회전 횟수) 개이다. 이때 `stds` 는 의 평균의 표준오차이며, `O_twirls`다음과 같이 정의된다\n",
        "\n",
        "$\\frac{ \\sigma_{\\mathcal{O}} }{ \\sqrt{N_{twirls}} },$\n",
        "\n",
        "여기서 $\\sigma_{\\mathcal{O}}$ 는 의 표준편차이며, $N_{twirls}$`O_twirls` 는 회전 횟수이다. 트위링 기능을 활성화하지 않으면, `stds` 와 `ensemble_standard_error` 는 동일합니다.\n",
        "\n",
        "ZNE를 활성화하면, 앞서 설명한 `stds` 요소들은 외삽 모델에 대한 비선형 회귀 분석의 가중치로 사용됩니다. 이 경우 함수가 `stds` 최종적으로 반환하는 값은 잡음 계수가 0일 때 평가된 적합 모델의 불확실성입니다. 적합도가 낮거나 적합도에 큰 불확실성이 존재할 경우, 보고된 값이 매우 `stds` 커질 수 있다. ZNE가 활성화되면 와 `pub_result.data.stds_noise_factors` 값도 함께 `pub_result.data.evs_noise_factors` 채워지므로, 사용자가 직접 외삽을 수행할 수 있습니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c4341184-a41a-4442-bc05-838c90ea93b8",
      "metadata": {},
      "source": [
        "<span id=\"result-metadata\" />\n",
        "\n",
        "## 결과 메타데이터\n",
        "\n",
        "실행 결과 외에도, 및 `PubResult` `PrimitiveResult` 객체 모두 제출된 작업에 대한 메타데이터 속성을 포함하고 있습니다. 제출된 모든 PUB에 대한 정보(예: 사용 가능한 다양한 [런타임 옵션](/docs/api/qiskit-ibm-runtime/options) 등)가 포함된 메타데이터는 에서 확인할 수 있으며 `PrimitiveResult.metatada`, 각 PUB 에 특화된 메타데이터는 에서 확인할 수 `PubResult.metadata` 있습니다.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  메타데이터 필드에서 기본 구현체는 자신과 관련된 실행 정보를 자유롭게 반환할 수 있으며, 기본 기본형에서 보장하는 키-값 쌍은 존재하지 않습니다. 따라서 메타데이터의 반환 결과는 각 기본 구현에 따라 다를 수 있습니다.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "626ba203-44e2-4b8f-b04d-04388b8b1fa1",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The metadata of the PrimitiveResult is:\n",
            "'dynamical_decoupling' : {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'},\n",
            "'twirling' : {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'},\n",
            "'resilience' : {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False},\n",
            "'version' : 2,\n",
            "\n",
            "The metadata of the PubResult result is:\n",
            "'shots' : 4096,\n",
            "'target_precision' : 0.015625,\n",
            "'circuit_metadata' : {},\n",
            "'resilience' : {},\n",
            "'num_randomizations' : 32,\n"
          ]
        }
      ],
      "source": [
        "# Print out the results metadata\n",
        "print(\"The metadata of the PrimitiveResult is:\")\n",
        "for key, val in result.metadata.items():\n",
        "    print(f\"'{key}' : {val},\")\n",
        "\n",
        "print(\"\\nThe metadata of the PubResult result is:\")\n",
        "for key, val in result[0].metadata.items():\n",
        "    print(f\"'{key}' : {val},\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "celltoolbar": "Raw Cell Format",
    "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
}