{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "ce3d197d-7b14-4c60-8d39-a202146d0663",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Entradas e saídas do executor\"\n",
        "description: \"Compreenda as entradas e saídas da primitiva Executor.\"\n",
        "---\n",
        "\n",
        "<span id=\"executor-inputs-and-outputs\" />\n",
        "\n",
        "# Entradas e saídas do executor\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=\"Versões do pacote\">\n",
        "    O código desta página foi desenvolvido com base nos seguintes requisitos.\n",
        "    Recomendamos o uso dessas versões ou versões mais recentes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.4.0\n",
        "    qiskit-ibm-runtime~=0.46.1\n",
        "    samplomatic~=0.18.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "43c044dc-259d-4759-b6a7-a05bd9d3667f",
      "metadata": {},
      "source": [
        "A primitiva Executor faz parte do [modelo de execução direcionada](/docs/guides/directed-execution-model), que oferece maior flexibilidade na personalização de um fluxo de trabalho de mitigação de erros.\n",
        "\n",
        "As entradas e saídas da primitiva Executor são muito diferentes das entradas e saídas das primitivas [Sampler](/docs/guides/sampler-input-output) e [Estimator](/docs/guides/estimator-input-output). Por exemplo, em vez de receber uma lista de PUBs como entrada, o Executor recebe um `QuantumProgram`objeto que contém uma lista de `QuantumProgramItem` objetos. Essas classes de contêineres oferecem mais flexibilidade do que um `PUB`, que é uma estrutura de dados simples do tipo tupla.\n",
        "\n",
        "A saída do executor é um `QuantumProgramResult`, que é um iterável e contém um elemento para cada entrada `QuantumProgramItem`.\n",
        "\n",
        "<span id=\"programs\" />\n",
        "\n",
        "<span id=\"inputs-quantum-programs\" />\n",
        "\n",
        "## Entradas: Programas Quantum\n",
        "\n",
        "Conforme mencionado anteriormente, a entrada para uma primitiva Executor é um [`QuantumProgram`](/docs/api/qiskit-ibm-runtime/quantum-program-quantum-program), que é uma coleção iterável de\n",
        "[`QuantumProgramItem`](/docs/api/qiskit-ibm-runtime/quantum-program-quantum-program-item) objetos.  Esses objetos podem ser de dois tipos:\n",
        "\n",
        "* `CircuitItem`, que normalmente armazena um circuito e os valores de seus parâmetros (se houver).\n",
        "* `SamplexItem`, que normalmente armazena o seguinte:\n",
        "  * Um circuito modelo\n",
        "  * Um objeto samplex, utilizado para gerar conjuntos aleatórios de parâmetros em tempo de execução (por exemplo, para realizar twirling ou injetar ruído)\n",
        "  * Argumentos para o samplex, que podem incluir valores de parâmetros do circuito original\n",
        "\n",
        "Cada um desses itens representa uma tarefa diferente a ser realizada pelo Executor.\n",
        "\n",
        "<span id=\"before-you-begin\" />\n",
        "\n",
        "### Antes de iniciar\n",
        "\n",
        "Alguns dos exemplos de código nesta página utilizam `samplex`, que faz parte do pacote Samplomatic.  Portanto, antes de executar esses blocos de código, é necessário instalar o Samplomatic, conforme mostrado no bloco de código a seguir.  Para mais informações, consulte a [documentação do 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",
        "### Exemplo: Criar um `QuantumProgram` com duas tarefas diferentes\n",
        "\n",
        "Primeiro, inicialize seu programa quântico e, em seguida, acrescente itens ao programa usando ou `append_samplex_item``append_circuit_item` (se houver um samplex), conforme mostrado nos exemplos a seguir.\n",
        "\n",
        "A célula a seguir inicializa um `QuantumProgram` e especifica que ele deve executar 1024 simulações para cada configuração de cada item do programa.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Ao contrário do Sampler, um `QuantumProgram` aceita apenas um único valor de amostra. `QuantumProgram`Se você quiser um valor de disparo diferente, precisará de um componente separado, o que seria um trabalho à parte.\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",
        "### Acrescentar um `CircuitItem`\n",
        "\n",
        "Em seguida, acrescente o circuito de destino, que foi transpilado de acordo com a arquitetura do conjunto de instruções (ISA) do backend, ao `QuantumProgram`. Como este circuito possui dois parâmetros, devemos também fornecer os valores desses parâmetros (10 conjuntos neste exemplo). A execução desta operação `CircuitItem` é a primeira tarefa que o programa realizará.\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",
        "### Acrescentar um `SamplexItem`\n",
        "\n",
        "Os itens do circuito são executados sem qualquer tipo de aleatoriedade. Pelo contrário, os itens do Samplex permitem que você especifique como randomizar seu conteúdo. A próxima célula usa a `generate_boxing_pass_manager()` função para agrupar as portas e as medições do circuito em caixas e adicionar uma anotação giratória a cada caixa. Em seguida, gera um circuito modelo e um par de amostras utilizando a `build()` função.\n",
        "\n",
        "A execução desta `SamplexItem` tarefa é a segunda que o programa realizará.\n",
        "\n",
        "Consulte a documentação [da API](https://github.com/Qiskit/samplomatic/) do Samplomatic para obter todos os detalhes sobre `samplex` e seus argumentos. Consulte o [guia](https://qiskit.github.io/samplomatic/guides/transpiler.html) do Samplomatic Transpiler para obter informações sobre como usar a `generate_boxing_pass_manager()` função.\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",
        "## Saídas\n",
        "\n",
        "A saída do executor é um [`QuantumProgramResult`](/docs/api/qiskit-ibm-runtime/results-quantum-program-result), que é um iterável. Ele contém uma entrada por entrada `QuantumProgramItem` , na mesma ordem em que os itens de entrada aparecem. Cada um desses itens de saída é um dicionário cujas chaves são strings que correspondem aos nomes dos registros clássicos nos circuitos de entrada (entre outros), de modo que você não precisa mais memorizar esses nomes como fazia com a saída do Sampler. Os valores do dicionário são do tipo `np.ndarray`.\n",
        "\n",
        "O resultado do exemplo anterior contém os seguintes itens:\n",
        "\n",
        "<span id=\"circuititem-result\" />\n",
        "\n",
        "### `CircuitItem` resultado\n",
        "\n",
        "O primeiro item contém os resultados da execução da primeira tarefa (a `CircuitItem`) do programa. Ele contém uma única chave, `meas`, que é o nome do registro clássico no circuito de entrada. O valor desta chave corresponde a um `np.ndarray` de formato `(parameter sets, shots, register bits)`, que é (10, 1024, 3) no exemplo acima.\n",
        "\n",
        "O código a seguir ilustra como acessar essas informações:\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` resultado\n",
        "\n",
        "O segundo item contém os resultados da execução da segunda tarefa (a `SamplexItem`) do programa. Este item contém várias chaves. A `meas` chave, que é o nome do registro clássico do circuito de entrada, remete à matriz de resultados desse registro. Essa matriz tem a forma `(randomizations, parameter sets, shots, classical bits)`, ou (28, 10, 1024, 3) neste exemplo. Além disso, a saída contém uma `measurement_flips.meas` chave, que corresponde às correções de inversão de bits necessárias para reverter a distorção da medição no `meas` registro.  No nosso exemplo, essa matriz de saída será (28, 10, 1, 3), pois basta um único passo para realizar a inversão de bits.\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",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * Explore [exemplos](/docs/guides/executor-examples) que utilizam o Executor.\n",
        "  * Saiba mais sobre o [modelo de execução direcionada](/docs/guides/directed-execution-model).\n",
        "  * Entenda [a transmissão do 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
}