{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "ce3d197d-7b14-4c60-8d39-a202146d0663",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"실행기의 입력과 출력\"\n",
        "description: \"Executor 기본 구성 요소의 입력 및 출력을 이해하십시오.\"\n",
        "---\n",
        "\n",
        "<span id=\"executor-inputs-and-outputs\" />\n",
        "\n",
        "# 실행기의 입력과 출력\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "44219323-9419-471a-86c4-488ef0162420",
      "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",
        "    samplomatic~=0.21.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "43c044dc-259d-4759-b6a7-a05bd9d3667f",
      "metadata": {},
      "source": [
        "Executor 기본 요소는 [방향성 실행](/docs/guides/directed-execution-model) 모델의 일부로, 오류 완화 워크플로를 사용자 정의할 때 더 큰 유연성을 제공합니다.\n",
        "\n",
        "Executor 기본 요소의 입력과 출력은 [Sampler](/docs/guides/sampler-input-output) 및 [Estimator](/docs/guides/estimator-input-output) 기본 요소의 입력과 출력과 매우 다릅니다. 예를 들어, Executor는 펍(PUB) 목록을 입력으로 받는 대신, 객체 목록을 `QuantumProgramItem` 포함하는 객체를 `QuantumProgram`입력으로 받습니다. 이러한 컨테이너 클래스는 단순한 튜플 데이터 구조인 PUB 보다 더 큰 유연성을 제공합니다.\n",
        "\n",
        "`QuantumProgramItem``QuantumProgramResult`실행자의 출력은 이며, 이는 반복 가능한 객체로, 각 입력에 대해 하나의 요소를 포함합니다.\n",
        "\n",
        "<span id=\"programs\" />\n",
        "\n",
        "<span id=\"inputs-quantum-programs\" />\n",
        "\n",
        "## 입력: 양자 프로그램\n",
        "\n",
        "앞서 언급했듯이, Executor 기본 객체의 입력은 객체들의\n",
        "[`QuantumProgramItem`](/docs/api/qiskit-ibm-runtime/quantum-program-quantum-program-item) 반복 가능한 집합인[`QuantumProgram`](/docs/api/qiskit-ibm-runtime/quantum-program-quantum-program) 입니다.  이러한 객체는 두 가지 유형으로 나눌 수 있습니다:\n",
        "\n",
        "* `CircuitItem`, 일반적으로 회로와 해당 매개변수 값(있는 경우)을 저장합니다.\n",
        "* `SamplexItem`, 일반적으로 다음 내용을 저장합니다:\n",
        "  * 회로 도면\n",
        "  * 런타임 시 무작위 매개변수 집합을 생성하는 데 사용되는 샘플렉스 객체(예: 트위링 수행 또는 노이즈 주입)\n",
        "  * samplex에 전달되는 인자들로, 여기에는 원래 회로의 매개변수 값이 포함될 수 있습니다\n",
        "\n",
        "이 항목들은 각각 집행자가 수행해야 할 서로 다른 업무를 나타냅니다.\n",
        "\n",
        "<span id=\"before-you-begin\" />\n",
        "\n",
        "### 시작하기 전에\n",
        "\n",
        "`samplex`이 페이지의 일부 코드 예제에서는 Samplomatic 패키지의 일부인 를 사용합니다.  따라서, 해당 코드 블록을 실행하기 전에 다음 코드 블록에 표시된 대로 Samplomatic을 설치해야 합니다.  자세한 내용은 [Samplomatic](https://qiskit.github.io/samplomatic) 설명서를 참조하십시오.\n",
        "\n",
        "```python\n",
        "pip install samplomatic\n",
        "\n",
        "# For visualization support, include the visualization dependencies.\n",
        "# pip install samplomatic[vis]\n",
        "```\n",
        "\n",
        "<span id=\"example-create-a-quantumprogram-with-two-different-tasks\" />\n",
        "\n",
        "### `QuantumProgram` 예시: 두 가지 다른 작업이 포함된 만들기\n",
        "\n",
        "먼저 양자 프로그램을 초기화한 다음, 다음 예시와 같이 또는 `append_samplex_item` (samplex가 있는 경우)를 `append_circuit_item` 사용하여 프로그램 항목을 추가하십시오.\n",
        "\n",
        "다음 셀은 를 `QuantumProgram` 초기화하고, 프로그램 내 각 항목의 모든 구성에 대해 1024회의 시뮬레이션을 실행하도록 지정합니다.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Sampler와 달리, 는 `QuantumProgram` 단 하나의 샷 값만 사용합니다. `QuantumProgram`다른 샷 값을 원하신다면 별도의 작업이 필요하며, 이는 별도의 작업으로 처리됩니다.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "81fc7c9e-2cc9-416a-b3d5-74f45eab48fc",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime.quantum_program import QuantumProgram\n",
        "from qiskit_ibm_runtime import Executor, QiskitRuntimeService\n",
        "from qiskit.circuit import Parameter, QuantumCircuit\n",
        "import numpy as np\n",
        "from samplomatic import build\n",
        "from samplomatic.transpiler import generate_boxing_pass_manager\n",
        "\n",
        "# Initialize an empty program\n",
        "program = QuantumProgram(shots=1024)\n",
        "\n",
        "# Initialize and transpile a 3-qubit quantum circuit with 2 parameters.\n",
        "circuit = QuantumCircuit(3)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.cx(1, 2)\n",
        "circuit.rz(Parameter(\"theta\"), 0)\n",
        "circuit.rz(Parameter(\"phi\"), 1)\n",
        "\n",
        "# `measure_all` adds a 3-bit classical register named \"meas\"\n",
        "circuit.measure_all()\n",
        "\n",
        "# Choose the least busy backend\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Generate a preset pass manager\n",
        "# This will be used to convert the abstract circuit to an\n",
        "# equivalent Instruction Set Architecture (ISA) circuit.\n",
        "preset_pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend, optimization_level=0\n",
        ")\n",
        "\n",
        "# Transpile the circuit\n",
        "isa_circuit = preset_pass_manager.run(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a1cc6580-3f31-4322-b0ea-f6bcf032a872",
      "metadata": {},
      "source": [
        "<span id=\"append-a-circuititem\" />\n",
        "\n",
        "### 추가하기 `CircuitItem`\n",
        "\n",
        "`QuantumProgram`다음으로, 백엔드의 명령어 집합 아키텍처(ISA)에 따라 트랜스파일된 대상 회로를.에 추가합니다. 이 회로에는 두 개의 매개변수가 있으므로, 매개변수 값도 함께 지정해야 합니다(이 예시에서는 10세트). 이 `CircuitItem` 코드를 실행하는 것이 프로그램이 수행할 첫 번째 작업입니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "e6f6762f-1627-450a-b74b-96ad4a3b1c9c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Append the transpiled circuit and an array\n",
        "# containing 10 sets of parameter values to the program\n",
        "program.append_circuit_item(\n",
        "    isa_circuit,\n",
        "    circuit_arguments=np.random.rand(\n",
        "        10, 2\n",
        "    ),  # 10 sets of parameter values and 2 parameters\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "96f9ac43-8ce4-4389-bff4-5bd68b799974",
      "metadata": {},
      "source": [
        "<span id=\"append-a-samplexitem\" />\n",
        "\n",
        "### 추가하기 `SamplexItem`\n",
        "\n",
        "회로 항목들은 어떠한 무작위화 과정도 없이 실행됩니다. 반대로, 샘플렉스 항목은 내용을 무작위로 배열하는 방식을 직접 지정할 수 있게 해줍니다. 다음 셀에서는 함수를 `generate_boxing_pass_manager()` 사용하여 회로의 게이트와 측정값을 상자로 묶고, 각 상자에 회전하는 주석을 추가합니다. 그런 다음 해당 `build()` 함수를 사용하여 템플릿 회로와 샘플렉스 쌍을 생성합니다.\n",
        "\n",
        "이 `SamplexItem` 작업을 실행하는 것이 프로그램이 수행할 두 번째 작업입니다.\n",
        "\n",
        "및 그 인자에 대한 `samplex` 자세한 내용은 Samplomatic [API](https://github.com/Qiskit/samplomatic/) 문서를 참조하십시오. 함수 `generate_boxing_pass_manager()` 사용법에 대한 자세한 내용은 Samplomatic [Transpiler](https://qiskit.github.io/samplomatic/guides/transpiler.html) 가이드를 참조하십시오.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "4ac19f46-226b-4b13-b278-1e39e719484b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TensorInterface(<\n",
            "  - 'parameter_values' <float64[2]>: Input parameter values to use during sampling.\n",
            ">)\n"
          ]
        }
      ],
      "source": [
        "# Transpile the circuit, additionally grouping gates and measurements into annotated boxes\n",
        "preset_pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend, optimization_level=0\n",
        ")\n",
        "\n",
        "# Use the boxing pass manager to group gates\n",
        "# and measurements into boxes and add\n",
        "# a`Twirl` annotation.\n",
        "preset_pass_manager.post_scheduling = generate_boxing_pass_manager(\n",
        "    # Add gate twirling\n",
        "    enable_gates=True,\n",
        "    # Add measurement twirling\n",
        "    enable_measures=True,\n",
        ")\n",
        "boxed_circuit = preset_pass_manager.run(circuit)\n",
        "\n",
        "# Build the template circuit and the samplex.  The template circuit has parametric gates\n",
        "# without fixed values and the samplex randomly generates the parameter\n",
        "# values on the server side at runtime to perform twirling.\n",
        "template_circuit, samplex = build(boxed_circuit)\n",
        "\n",
        "# Determine what arguments are required by the samplex.\n",
        "# Input the arguments in samplex_arguments.\n",
        "print(samplex.inputs())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "0e3b4d3d-12ea-47f2-a605-b64eed03cf95",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Append the template circuit and samplex as a samplex item\n",
        "program.append_samplex_item(\n",
        "    template_circuit,\n",
        "    samplex=samplex,\n",
        "    samplex_arguments={\n",
        "        # the arguments required by the samplex.sample method\n",
        "        \"parameter_values\": np.random.rand(10, 2),\n",
        "    },\n",
        "    shape=(28, 10),  # 28 randomizations and 10 sets of parameter values\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "eb850401-3d4f-4fac-8965-fb9ac4827ebd",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Initialize an Executor with the default options\n",
        "executor = Executor(mode=backend)\n",
        "\n",
        "# Submit the job\n",
        "job = executor.run(program)\n",
        "\n",
        "# Retrieve the result\n",
        "result = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "541f5d2d-b974-4ae5-81e0-ef2b6e1dbe82",
      "metadata": {},
      "source": [
        "<span id=\"outputs\" />\n",
        "\n",
        "## 출력\n",
        "\n",
        "[`QuantumProgramResult`](/docs/api/qiskit-ibm-runtime/results-quantum-program-result)Executor의 출력값은 반복 가능한 객체인 입니다. 입력 `QuantumProgramItem` 항목 하나당 하나의 항목이 포함되며, 입력 항목과 동일한 순서로 정렬되어 있습니다. 이러한 각 출력 항목은 사전(dictionary) 형태로, 키는 입력 회로(그 밖의 요소들 포함)에 있는 기존 레지스터의 이름에 해당하는 문자열입니다. 따라서 샘플러 출력에서 그랬던 것처럼 더 이상 이러한 이름을 외울 필요가 없습니다. `np.ndarray`사전 값의 데이터 형식은 입니다.\n",
        "\n",
        "이전 예제의 결과에는 다음 항목들이 포함되어 있습니다:\n",
        "\n",
        "<span id=\"circuititem-result\" />\n",
        "\n",
        "### `CircuitItem`개의 결과\n",
        "\n",
        "`CircuitItem`첫 번째 항목에는 프로그램의 첫 번째 작업(a)을 실행한 결과가 포함되어 있습니다. 여기에는 입력 회로의 클래식 레지스터 이름인 단일 `meas` 키가 포함되어 있습니다. `(parameter sets, shots, register bits)`이 키의 값은 형식의 배열에 `np.ndarray` 매핑되며, 위 예제의 경우 (10, 1024, 3)입니다.\n",
        "\n",
        "다음 코드는 이 정보에 접근하는 방법을 보여줍니다:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "d652d69a-7a4e-4e5c-8469-97cb9ec92010",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Result shape: (10, 1024, 3)\n"
          ]
        }
      ],
      "source": [
        "# Access the results of the classical register of task #0, a CircuitItem\n",
        "result_0 = result[0][\"meas\"]\n",
        "print(f\"Result shape: {result_0.shape}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7185353a-e7a0-4bb2-b605-664184e684ed",
      "metadata": {},
      "source": [
        "<span id=\"samplexitem-result\" />\n",
        "\n",
        "### `SamplexItem`개의 결과\n",
        "\n",
        "`SamplexItem`두 번째 항목에는 프로그램의 두 번째 작업(a)을 실행한 결과가 포함되어 있습니다. 이 항목에는 여러 개의 키가 포함되어 있습니다. 'key'는 `meas` 입력 회로의 클래식 레지스터 이름이며, 해당 레지스터의 결과 배열에 매핑됩니다. `(randomizations, parameter sets, shots, classical bits)`이 배열의 차원은 이 예시에서 (28, 10, 1024, 3)입니다. 또한, 출력값에는 레지스터에 `meas` 대한 측정 왜곡을 보정하기 위한 비트 반전 보정값을 나타내는 key가 `measurement_flips.meas` 포함되어 있습니다.  이 예제의 경우 비트 반전을 수행하는 데 단 한 번의 연산만 필요하므로, 출력 형식은 (28, 10, 1, 3)이 됩니다.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "884af6e2-614a-4b18-83dc-04505ddbc488",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Result shape: (28, 10, 1024, 3)\n",
            "Bit-flip corrections shape: (28, 10, 1, 3)\n"
          ]
        }
      ],
      "source": [
        "# Access the results of the classical register of task #1\n",
        "result_1 = result[1][\"meas\"]\n",
        "print(f\"Result shape: {result_1.shape}\")\n",
        "\n",
        "# Access the bit-flip corrections\n",
        "flips_1 = result[1][\"measurement_flips.meas\"]\n",
        "print(f\"Bit-flip corrections shape: {flips_1.shape}\")\n",
        "\n",
        "# Undo the bit flips via classical XOR\n",
        "unflipped_result_1 = result_1 ^ flips_1"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bb0c9225-9a52-4d94-b75d-6ae408f4e029",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 다음 단계\n",
        "\n",
        "<Admonition type=\"tip\" title=\"권장사항\">\n",
        "  * Executor를 사용한 [예제를](/docs/guides/executor-examples) 살펴보세요.\n",
        "  * [지시형 실행 모델](/docs/guides/directed-execution-model) 에 대해 알아보세요.\n",
        "  * [Executor 브로드캐스팅을](/docs/guides/executor-broadcasting) 이해합니다.\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
}