{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "0ff6f833-f5fb-4e9e-a572-445f2ff9ad64",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Entradas e saídas de primitivos\"\n",
        "description: \"Compreender os formatos de entrada e saída (incluindo os Blocos Primitivos Unificados, ou PUBs) do Qiskit primitives\"\n",
        "---\n",
        "\n",
        "<span id=\"primitive-inputs-and-outputs\" />\n",
        "\n",
        "# Entradas e saídas de primitivos\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "36a00905-1855-4fce-9686-20eb01ba72b6",
      "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 usando os seguintes requisitos.\n",
        "    Recomendamos o uso dessas versões ou de versões mais recentes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "203951dd-4da7-4e0d-93f7-3ed7e2cd624b",
      "metadata": {},
      "source": [
        "Esta página apresenta uma visão geral das entradas e saídas do Qiskit primitives. Com essas primitivas, é possível utilizar uma estrutura de dados conhecida como **Bloco Unificado Primitivo ( PUB )** para definir com eficiência cargas de trabalho vetorizadas. Esses PUBs são a unidade fundamental de trabalho para a execução da carga de trabalho. Elas são utilizadas como entradas para o `run()` método das primitivas Sampler e Estimator, que executam a carga de trabalho definida como um trabalho. Em seguida, após a conclusão do trabalho, os resultados são retornados em um formato que depende dos PUBs utilizados e de quaisquer opções especificadas.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c7bc7444-eada-42ec-8f9a-6ec848c40014",
      "metadata": {},
      "source": [
        "<span id=\"pubs\" />\n",
        "\n",
        "<span id=\"overview-of-pubs\" />\n",
        "\n",
        "## Visão geral dos PUBs\n",
        "\n",
        "Ao invocar o método `run()` de uma primitiva, o principal argumento exigido é um conjunto `list` de uma ou mais tuplas — uma para cada circuito que está sendo executado pela primitiva. Cada uma dessas tuplas é considerada um `PUB`, e os elementos necessários de cada tupla na lista dependem do tipo primitivo utilizado. Os dados fornecidos a essas tuplas também podem ser organizados de diversas formas para proporcionar flexibilidade a uma carga de trabalho por meio da difusão — cujas regras são descritas na [seção](#broadcasting-rules) a seguir.\n",
        "\n",
        "<span id=\"estimator-pub\" />\n",
        "\n",
        "### Estimador PUB\n",
        "\n",
        "Para a primitiva Estimator, o formato do site PUB deve conter no máximo quatro valores:\n",
        "\n",
        "* Um único `QuantumCircuit`, que pode conter um ou mais [`Parameter`](/docs/api/qiskit/qiskit.circuit.Parameter) objetos\n",
        "* Uma lista de um ou mais observáveis, que especifica os valores de expectativa a serem estimados, organizados em uma matriz (por exemplo, um único observável representado como uma matriz 0-d, uma lista de observáveis como uma matriz 1-d e assim por diante). Os dados podem estar em qualquer um dos formatos `ObservablesArrayLike` , como `Pauli`, `SparsePauliOp`, `PauliList`, ou `str`.\n",
        "  <Admonition type=\"note\">\n",
        "    Se você tiver dois observáveis de comutação em PUBs diferentes, mas com o mesmo circuito, eles não serão estimados usando a mesma medição. Cada PUB representa uma base diferente para medição e, portanto, são necessárias medições separadas para cada PUB. Para garantir que os observáveis de deslocamento sejam estimados usando a mesma medida, eles devem ser agrupados dentro do mesmo e PUB o.\n",
        "  </Admonition>\n",
        "* Uma coleção de valores de parâmetros para vincular o circuito. Isso pode ser especificado como um único objeto do tipo array em que o último índice está sobre os objetos `Parameter` do circuito, ou omitido (ou, de forma equivalente, definido como `None`) se o circuito não tiver objetos `Parameter` .\n",
        "* (Opcionalmente) uma precisão de destino para os valores de expectativa a serem estimados\n",
        "\n",
        "<span id=\"sampler-pub\" />\n",
        "\n",
        "### Amostrador PUB\n",
        "\n",
        "Para a primitiva Sampler, o formato da tupla PUB contém no máximo três valores:\n",
        "\n",
        "* Um único circuito `QuantumCircuit`, que pode conter um ou mais [`Parameter`](/docs/api/qiskit/qiskit.circuit.Parameter) objetos\n",
        "  *Observação: Esses circuitos também devem incluir instruções de medição para cada um dos qubits a serem amostrados.*\n",
        "* Uma coleção de valores de parâmetros para vincular o circuito ao site $\\theta_k$ (necessário somente se forem usados objetos `Parameter` que devem ser vinculados em tempo de execução)\n",
        "* (Opcionalmente) um número de disparos para medir o circuito com\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2bdb4618-e59f-4627-81b6-6828b40258f7",
      "metadata": {},
      "source": [
        "***\n",
        "\n",
        "O código a seguir mostra um exemplo de conjunto de entradas vetorizadas para a `Estimator` primitiva.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "e84f14f0-7190-4ab6-ba49-2746c515238c",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit import (\n",
        "    Parameter,\n",
        "    QuantumCircuit,\n",
        "    ClassicalRegister,\n",
        "    QuantumRegister,\n",
        ")\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.primitives.containers import BitArray\n",
        "from qiskit.primitives import StatevectorEstimator\n",
        "\n",
        "\n",
        "import numpy as np\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 without providing a backend\n",
        "pm = generate_preset_pass_manager(optimization_level=1)\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, 10),\n",
        "        np.linspace(-4 * np.pi, 4 * np.pi, 10),\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 = StatevectorEstimator()\n",
        "estimator_pub = (transpiled_circuit, observables, params)\n",
        "\n",
        "# Run the transpiled circuit\n",
        "# using the set of parameters and observables.\n",
        "\n",
        "job = estimator.run([estimator_pub])\n",
        "result = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3acc54a9-ab50-4155-9c2d-c6a75dba816d",
      "metadata": {},
      "source": [
        "<span id=\"broadcasting\" />\n",
        "\n",
        "<span id=\"broadcasting-rules\" />\n",
        "\n",
        "### Regras de transmissão\n",
        "\n",
        "Os PUBs agregam elementos de várias matrizes (observáveis e valores de parâmetros) seguindo as mesmas regras de transmissão do site NumPy. Esta seção resume brevemente essas regras.  Para obter uma explicação detalhada, consulte a [documentação de regras de transmissão do site NumPy](https://numpy.org/doc/stable/user/basics.broadcasting.html).\n",
        "\n",
        "Regras:\n",
        "\n",
        "* As matrizes de entrada não precisam ter o mesmo número de dimensões.\n",
        "  * A matriz resultante terá o mesmo número de dimensões que a matriz de entrada com a maior dimensão.\n",
        "  * O tamanho de cada dimensão é o maior tamanho da dimensão correspondente.\n",
        "  * Supõe-se que as dimensões ausentes tenham o tamanho um.\n",
        "* As comparações de formas começam com a dimensão mais à direita e continuam para a esquerda.\n",
        "* Duas dimensões são compatíveis se seus tamanhos forem iguais ou se uma delas for 1.\n",
        "\n",
        "Exemplos de pares de matrizes que transmitem:\n",
        "\n",
        "```text\n",
        "A1     (1d array):      1\n",
        "A2     (2d array):  3 x 5\n",
        "Result (2d array):  3 x 5\n",
        "\n",
        "\n",
        "A1     (3d array):  11 x 2 x 7\n",
        "A2     (3d array):  11 x 1 x 7\n",
        "Result (3d array):  11 x 2 x 7\n",
        "```\n",
        "\n",
        "Exemplos de pares de matrizes que não transmitem:\n",
        "\n",
        "```text\n",
        "A1     (1d array):  5\n",
        "A2     (1d array):  3\n",
        "\n",
        "A1     (2d array):      2 x 1\n",
        "# The following would work if the middle dimension were 2,\n",
        "# instead of 5.\n",
        "A2     (3d array):  6 x 5 x 4\n",
        "```\n",
        "\n",
        "`Estimator` retorna uma estimativa do valor esperado para cada elemento da forma transmitida.\n",
        "\n",
        "Aqui estão alguns exemplos de padrões comuns expressos em termos de transmissão de matriz.  A representação visual que os acompanha é mostrada na figura a seguir:\n",
        "\n",
        "Os conjuntos de valores de parâmetros são representados por matrizes n x m, e as matrizes observáveis são representadas por uma ou mais matrizes de coluna única. Para cada exemplo no código anterior, os conjuntos de valores de parâmetros são combinados com sua matriz observável para criar as estimativas de valores de expectativa resultantes.\n",
        "\n",
        "* *Exemplo 1* : (broadcast single observable) tem um conjunto de valores de parâmetro que é uma matriz 5x1 e uma matriz 1x1 observables.  O item na matriz de observáveis é combinado com cada item no conjunto de valores de parâmetros para criar uma única matriz 5x1 em que cada item é uma combinação do item original no conjunto de valores de parâmetros com o item na matriz de observáveis.\n",
        "\n",
        "* *Exemplo 2* : (zip) tem um conjunto de valores de parâmetro 5x1 e uma matriz de observáveis 5x1.  O resultado é uma matriz 5x1 em que cada item é uma combinação do enésimo item no conjunto de valores de parâmetros com o enésimo item na matriz de observáveis.\n",
        "\n",
        "* *Exemplo 3* : (outer/product) tem um conjunto de valores de parâmetro 1x6 e uma matriz de observáveis 4x1.  Sua combinação resulta em uma matriz 4x6 criada pela combinação de cada item no conjunto de valores de parâmetro com *cada* item na matriz de observáveis e, portanto, cada valor de parâmetro se torna uma coluna inteira na saída.\n",
        "\n",
        "* *Exemplo 4* : (Padrão e generalização) tem uma matriz de conjunto de valores de parâmetros 3x6 e duas matrizes de observáveis 3x1.  Eles se combinam para criar duas matrizes de saída 3x6 de forma semelhante ao exemplo anterior.\n",
        "\n",
        "![Esta imagem ilustra várias representações visuais da difusão de matrizes.](https://quantum.cloud.ibm.com/docs/images/guides/primitive-input-output/broadcasting.avif \" Representação visual da difusão\")\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "37aa226f-d550-42fd-9ab0-60e27757722a",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Broadcast single observable\n",
        "parameter_values = np.random.uniform(size=(5,))  # shape (5,)\n",
        "observables = SparsePauliOp(\"ZZZ\")  # shape ()\n",
        "# >> pub result has shape (5,)\n",
        "\n",
        "# Zip\n",
        "parameter_values = np.random.uniform(size=(5,))  # shape (5,)\n",
        "observables = [\n",
        "    SparsePauliOp(pauli) for pauli in [\"III\", \"XXX\", \"YYY\", \"ZZZ\", \"XYZ\"]\n",
        "]  # shape (5,)\n",
        "# >> pub result has shape (5,)\n",
        "\n",
        "# Outer/Product\n",
        "parameter_values = np.random.uniform(size=(1, 6))  # shape (1, 6)\n",
        "observables = [\n",
        "    [SparsePauliOp(pauli)] for pauli in [\"III\", \"XXX\", \"YYY\", \"ZZZ\"]\n",
        "]  # shape (4, 1)\n",
        "# >> pub result has shape (4, 6)\n",
        "\n",
        "# Standard nd generalization\n",
        "parameter_values = np.random.uniform(size=(3, 6))  # shape (3, 6)\n",
        "observables = [\n",
        "    [\n",
        "        [SparsePauliOp([\"XII\"])],\n",
        "        [SparsePauliOp([\"IXI\"])],\n",
        "        [SparsePauliOp([\"IIX\"])],\n",
        "    ],\n",
        "    [\n",
        "        [SparsePauliOp([\"ZII\"])],\n",
        "        [SparsePauliOp([\"IZI\"])],\n",
        "        [SparsePauliOp([\"IIZ\"])],\n",
        "    ],\n",
        "]  # shape (2, 3, 1)\n",
        "# >> pub result has shape (2, 3, 6)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "408e47b0-24ca-45b5-b71b-080d8ccf30a6",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\" title=\"SparsePauliOp\">\n",
        "  Cada `SparsePauliOp` conta como um único elemento nesse contexto, independentemente do número de Paulis contidos no `SparsePauliOp`. Portanto, para fins dessas regras de transmissão, todos os elementos a seguir têm o mesmo formato:\n",
        "\n",
        "  ```text\n",
        "  a = SparsePauliOp(\"Z\") # shape ()\n",
        "  b = SparsePauliOp(\"IIIIZXYIZ\") # shape ()\n",
        "  c = SparsePauliOp.from_list([\"XX\", \"XY\", \"IZ\"]) # shape ()\n",
        "  ```\n",
        "\n",
        "  As seguintes listas de operadores, embora equivalentes em termos de informações contidas, têm formatos diferentes:\n",
        "\n",
        "  ```text\n",
        "  list1 = SparsePauliOp.from_list([\"XX\", \"XY\", \"IZ\"])\n",
        "      # list1 has shape ()\n",
        "  list2 = [SparsePauliOp(\"XX\"), SparsePauliOp(\"XY\"), SparsePauliOp(\"IZ\")]\n",
        "      # list2 has shape (3, )\n",
        "  ```\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f548b270-afa7-480c-a457-c5260791d55b",
      "metadata": {},
      "source": [
        "<span id=\"overview-of-primitive-outputs\" />\n",
        "\n",
        "## Visão geral das saídas primitivas\n",
        "\n",
        "Assim que um ou mais PUBs forem enviados a uma QPU para execução e um trabalho for concluído com sucesso, os dados são retornados como um objeto [`PrimitiveResult`](/docs/api/qiskit/qiskit.primitives.PrimitiveResult) contêiner. O `PrimitiveResult` contém uma lista iterável de [`PubResult`](/docs/api/qiskit/qiskit.primitives.PubResult) objetos que contêm os resultados da execução de cada PUB. Por exemplo, um trabalho enviado com 20 PUBs retornará um `PrimitiveResult` objeto que contém uma lista de 20 `PubResults`, sendo que cada um corresponde a um PUB.\n",
        "\n",
        "Cada um desses `PubResult` objetos possui um atributo `data` e um `metadata` atributo opcional. O `data` atributo é um objeto personalizado [`DataBin`](/docs/api/qiskit/qiskit.primitives.DataBin) que contém as estimativas do valor esperado, no caso do Estimador, ou amostras da saída do circuito, no caso do Amostrador.\n",
        "\n",
        "O `data` atributo também pode incluir outras informações específicas da implementação, como desvios-padrão. O `metadata` atributo pode conter informações adicionais específicas da implementação sobre a execução do `PUB` associado.\n",
        "\n",
        "A seguir, um esboço visual da estrutura de dados do site `PrimitiveResult` :\n",
        "\n",
        "<Tabs>\n",
        "  <TabItem value=\"estimator\" label=\"Estimator output\">\n",
        "    ```\n",
        "    └── PrimitiveResult\n",
        "        ├── PubResult[0]\n",
        "        │   ├── metadata\n",
        "        │   └── data  ## In the form of a DataBin object,\n",
        "        |       |     ## which includes data such as the following:\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",
        "        |       |     ## which includes data such as the following:\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",
        "    <Admonition type=\"note\">\n",
        "      O texto acima é um exemplo dos dados que podem ser retornados.  Os dados efetivamente retornados dependem da implementação.\n",
        "    </Admonition>\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"sampler\" label=\"Sampler output\">\n",
        "    ```\n",
        "    └── PrimitiveResult\n",
        "        ├── PubResult[0]\n",
        "        │   ├── metadata\n",
        "        │   └── data  ## In the form of a DataBin object\n",
        "        │       ├── NAME_OF_CLASSICAL_REGISTER\n",
        "        │       │   └── BitArray of count data for first PUB (default is 'meas')\n",
        "        |       |\n",
        "        │       └── NAME_OF_ANOTHER_CLASSICAL_REGISTER\n",
        "        │           └── BitArray of count data (exists only if more than one\n",
        "        |                 ClassicalRegister was specified in the circuit)\n",
        "        ├── PubResult[1]\n",
        "        |   ├── metadata\n",
        "        |   └── data  ## In the form of a DataBin object\n",
        "        |       └── NAME_OF_CLASSICAL_REGISTER\n",
        "        |           └── BitArray of count data for second PUB\n",
        "        ├── ...\n",
        "        ├── ...\n",
        "        └── ...\n",
        "    ```\n",
        "  </TabItem>\n",
        "</Tabs>\n",
        "\n",
        "<span id=\"estimator-output\" />\n",
        "\n",
        "### Saída do estimador\n",
        "\n",
        "Conforme mencionado anteriormente, os dados retornados pela `PubResult` primitiva Estimator dependem da implementação. Por exemplo, pode conter uma matriz de valores esperados (`PubResult.data.evs`) e desvios-padrão associados (`PubResult.data.stds`).\n",
        "\n",
        "O trecho de código abaixo descreve o formato `PrimitiveResult` (e `PubResult` associado) para o trabalho criado acima.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "7b3ac687-8197-4c50-831c-a349fd8e90a2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The result of the submitted job had 1 PUB and has a value:\n",
            " PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(3, 10), dtype=float64>), stds=np.ndarray(<shape=(3, 10), dtype=float64>), shape=(3, 10)), metadata={'target_precision': 0.0, 'circuit_metadata': {}})], metadata={'version': 2})\n",
            "\n",
            "The associated PubResult of this job has the following data bins:\n",
            " DataBin(evs=np.ndarray(<shape=(3, 10), dtype=float64>), stds=np.ndarray(<shape=(3, 10), dtype=float64>), shape=(3, 10))\n",
            "\n",
            "And this DataBin has attributes: dict_keys(['evs', 'stds'])\n",
            "Recall that this shape is due to our array of parameter binding sets having shape (100, 2) -- where 2 is the number of parameters in the circuit -- combined with our array of observables having shape (3, 1).\n",
            "The expectation values measured from this PUB are: \n",
            "[[ 3.06161700e-16  4.52395120e-01  4.36594428e-01  2.16506351e-01\n",
            "   6.33718361e-01 -6.33718361e-01 -2.16506351e-01 -4.36594428e-01\n",
            "  -4.52395120e-01 -3.06161700e-16]\n",
            " [ 1.22464680e-16  6.42787610e-01  9.84807753e-01  8.66025404e-01\n",
            "   3.42020143e-01 -3.42020143e-01 -8.66025404e-01 -9.84807753e-01\n",
            "  -6.42787610e-01 -1.22464680e-16]\n",
            " [ 4.89858720e-16  2.62002630e-01 -1.11618897e-01 -4.33012702e-01\n",
            "   9.25416578e-01 -9.25416578e-01  4.33012702e-01  1.11618897e-01\n",
            "  -2.62002630e-01 -4.89858720e-16]]\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    f\"The result of the submitted job had {len(result)} PUB and \"\n",
        "    f\"has a value:\\n {result}\\n\"\n",
        ")\n",
        "print(\n",
        "    f\"The associated PubResult of this job has the following data bins:\"\n",
        "    f\"\\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 circuit -- \"\n",
        "    \"combined with our array of observables having shape (3, 1).\"\n",
        ")\n",
        "\n",
        "print(\n",
        "    f\"The expectation values measured from this PUB are: \\n{result[0].data.evs}\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af092cd2-4388-4cb4-ba2a-a95b0d6b6c1e",
      "metadata": {},
      "source": [
        "<span id=\"sampler-output\" />\n",
        "\n",
        "### Saída do sampler\n",
        "\n",
        "Quando uma tarefa do Sampler é concluída com sucesso, o objeto [`PrimitiveResult`](/docs/api/qiskit/qiskit.primitives.PrimitiveResult) retornado contém uma lista de [`SamplerPubResult`](/docs/api/qiskit/qiskit.primitives.SamplerPubResult)s, um por PUB. Os compartimentos de dados desses `SamplerPubResult` objetos são objetos semelhantes a dicionários que contêm um `BitArray` por `ClassicalRegister` circuito.\n",
        "\n",
        "A classe `BitArray` é um contêiner para dados de disparo ordenados. Em mais detalhes, ele armazena as cadeias de bits amostradas como bytes em uma matriz bidimensional. O eixo mais à esquerda dessa matriz percorre os disparos ordenados, enquanto o eixo mais à direita percorre os bytes.\n",
        "\n",
        "Como primeiro exemplo, vejamos o seguinte circuito de dez qubits:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "f2902d44-e97e-450f-9290-e9a8e1a5b287",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Databin: DataBin(meas=BitArray(<shape=(), num_shots=1024, num_bits=10>))\n",
            "\n",
            "BitArray: BitArray(<shape=(), num_shots=1024, num_bits=10>)\n",
            "\n",
            "The shape of register `meas` is (1024, 2).\n",
            "\n",
            "The bytes in register `alpha`, shot by shot:\n",
            "[[  3 255]\n",
            " [  0   0]\n",
            " [  3 255]\n",
            " ...\n",
            " [  0   0]\n",
            " [  3 255]\n",
            " [  0   0]]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "from qiskit.primitives import StatevectorSampler\n",
        "\n",
        "# generate a ten-qubit GHZ circuit\n",
        "circuit = QuantumCircuit(10)\n",
        "circuit.h(0)\n",
        "circuit.cx(range(0, 9), range(1, 10))\n",
        "\n",
        "# append measurements with the `measure_all` method\n",
        "circuit.measure_all()\n",
        "\n",
        "# transpile the circuit\n",
        "transpiled_circuit = pm.run(circuit)\n",
        "\n",
        "sampler = StatevectorSampler()\n",
        "\n",
        "# run the Sampler job and retrieve the results\n",
        "\n",
        "job = sampler.run([transpiled_circuit])\n",
        "result = job.result()\n",
        "\n",
        "# the data bin contains one BitArray\n",
        "data = result[0].data\n",
        "print(f\"Databin: {data}\\n\")\n",
        "\n",
        "# to access the BitArray, use the key \"meas\", which is the default name of\n",
        "# the classical register when this is added by the `measure_all` method\n",
        "array = data.meas\n",
        "print(f\"BitArray: {array}\\n\")\n",
        "print(f\"The shape of register `meas` is {data.meas.array.shape}.\\n\")\n",
        "print(f\"The bytes in register `alpha`, shot by shot:\\n{data.meas.array}\\n\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8d7e1188-d7a9-4e1a-a783-25e49a5fa1a2",
      "metadata": {},
      "source": [
        "Às vezes, pode ser conveniente converter o formato de bytes do `BitArray` em cadeias de bits. O `get_count` método retorna um dicionário que mapeia sequências de bits para o número de vezes que elas ocorreram.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "0eb3a383-30cd-4a32-8d8d-740264587079",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Counts: {'1111111111': 507, '0000000000': 517}\n"
          ]
        }
      ],
      "source": [
        "# optionally convert the native BitArray format to a dictionary format\n",
        "counts = data.meas.get_counts()\n",
        "print(f\"Counts: {counts}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f02341ca-4d0f-421b-9817-47f7b339d057",
      "metadata": {},
      "source": [
        "Quando um circuito contém mais de um registro clássico, os resultados são armazenados em diferentes `BitArray` objetos. O exemplo a seguir modifica o trecho anterior, dividindo o registro clássico em dois registros distintos:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "5b294da8-b6b2-4313-aa98-efa4a1903ba4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "BitArray for register 'alpha': BitArray(<shape=(), num_shots=1024, num_bits=1>)\n",
            "BitArray for register 'beta': BitArray(<shape=(), num_shots=1024, num_bits=9>)\n"
          ]
        }
      ],
      "source": [
        "# generate a ten-qubit GHZ circuit with two classical registers\n",
        "circuit = QuantumCircuit(\n",
        "    qreg := QuantumRegister(10),\n",
        "    alpha := ClassicalRegister(1, \"alpha\"),\n",
        "    beta := ClassicalRegister(9, \"beta\"),\n",
        ")\n",
        "circuit.h(0)\n",
        "circuit.cx(range(0, 9), range(1, 10))\n",
        "\n",
        "# append measurements with the `measure_all` method\n",
        "circuit.measure([0], alpha)\n",
        "circuit.measure(range(1, 10), beta)\n",
        "\n",
        "# transpile the circuit\n",
        "transpiled_circuit = pm.run(circuit)\n",
        "\n",
        "# run the Sampler job and retrieve the results\n",
        "\n",
        "job = sampler.run([transpiled_circuit])\n",
        "result = job.result()\n",
        "\n",
        "# the data bin contains two BitArrays, one per register, and can be accessed\n",
        "# as attributes using the registers' names\n",
        "data = result[0].data\n",
        "print(f\"BitArray for register 'alpha': {data.alpha}\")\n",
        "print(f\"BitArray for register 'beta': {data.beta}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e384e005-24fe-4d7a-922a-39ae0d9089ab",
      "metadata": {},
      "source": [
        "<span id=\"leveraging-bitarray-objects-for-performant-post-processing\" />\n",
        "\n",
        "#### Aproveitando `BitArray` objetos para pós-processamento de alto desempenho\n",
        "\n",
        "Como as matrizes geralmente oferecem melhor desempenho em comparação com os dicionários, é aconselhável realizar qualquer pós-processamento diretamente nos `BitArray` objetos, em vez de nos dicionários de contagens. A `BitArray` classe oferece uma variedade de métodos para realizar algumas operações comuns de pós-processamento:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "44c7ee14-2b22-488e-bc58-164099855210",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The shape of register `alpha` is (1024, 1).\n",
            "The bytes in register `alpha`, shot by shot:\n",
            "[[0]\n",
            " [1]\n",
            " [1]\n",
            " ...\n",
            " [0]\n",
            " [0]\n",
            " [0]]\n",
            "\n",
            "The shape of register `beta` is (1024, 2).\n",
            "The bytes in register `beta`, shot by shot:\n",
            "[[  0   0]\n",
            " [  1 255]\n",
            " [  1 255]\n",
            " ...\n",
            " [  0   0]\n",
            " [  0   0]\n",
            " [  0   0]]\n",
            "\n",
            "The shape of `beta` after post-selection is (0, 2).\n",
            "The bytes in `beta` after post-selection:\n",
            "[]\n",
            "The shape of `beta` after bit-wise slicing is (1024, 1).\n",
            "The bytes in `beta` after bit-wise slicing:\n",
            "[[0]\n",
            " [7]\n",
            " [7]\n",
            " ...\n",
            " [0]\n",
            " [0]\n",
            " [0]]\n",
            "\n",
            "The shape of `beta` after shot-wise slicing is (5, 2).\n",
            "The bytes in `beta` after shot-wise slicing:\n",
            "[[  0   0]\n",
            " [  1 255]\n",
            " [  1 255]\n",
            " [  1 255]\n",
            " [  0   0]]\n",
            "\n",
            "Exp. val. for observable `SparsePauliOp(['ZZZZZZZZZ'],\n",
            "              coeffs=[1.+0.j])` is: -0.03515625\n",
            "Exp. val. for observable `SparsePauliOp(['IIIIIIIIZ'],\n",
            "              coeffs=[1.+0.j])` is: -0.03515625\n",
            "\n",
            "The shape of the merged results is (1024, 2).\n",
            "The bytes of the merged results:\n",
            "[[  0   0]\n",
            " [  3 255]\n",
            " [  3 255]\n",
            " ...\n",
            " [  0   0]\n",
            " [  0   0]\n",
            " [  0   0]]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(f\"The shape of register `alpha` is {data.alpha.array.shape}.\")\n",
        "print(f\"The bytes in register `alpha`, shot by shot:\\n{data.alpha.array}\\n\")\n",
        "\n",
        "print(f\"The shape of register `beta` is {data.beta.array.shape}.\")\n",
        "print(f\"The bytes in register `beta`, shot by shot:\\n{data.beta.array}\\n\")\n",
        "\n",
        "# post-select the bitstrings of `beta` based on having sampled \"1\" in `alpha`\n",
        "mask = data.alpha.array == \"0b1\"\n",
        "ps_beta = data.beta[mask[:, 0]]\n",
        "print(f\"The shape of `beta` after post-selection is {ps_beta.array.shape}.\")\n",
        "print(f\"The bytes in `beta` after post-selection:\\n{ps_beta.array}\")\n",
        "\n",
        "# get a slice of `beta` to retrieve the first three bits\n",
        "beta_sl_bits = data.beta.slice_bits([0, 1, 2])\n",
        "print(\n",
        "    f\"The shape of `beta` after bit-wise slicing is {beta_sl_bits.array.shape}.\"\n",
        ")\n",
        "print(f\"The bytes in `beta` after bit-wise slicing:\\n{beta_sl_bits.array}\\n\")\n",
        "\n",
        "# get a slice of `beta` to retrieve the bytes of the first five shots\n",
        "beta_sl_shots = data.beta.slice_shots([0, 1, 2, 3, 4])\n",
        "print(\n",
        "    f\"The shape of `beta` after shot-wise slicing is {beta_sl_shots.array.shape}.\"\n",
        ")\n",
        "print(\n",
        "    f\"The bytes in `beta` after shot-wise slicing:\\n{beta_sl_shots.array}\\n\"\n",
        ")\n",
        "\n",
        "# calculate the expectation value of diagonal operators on `beta`\n",
        "ops = [SparsePauliOp(\"ZZZZZZZZZ\"), SparsePauliOp(\"IIIIIIIIZ\")]\n",
        "exp_vals = data.beta.expectation_values(ops)\n",
        "for o, e in zip(ops, exp_vals):\n",
        "    print(f\"Exp. val. for observable `{o}` is: {e}\")\n",
        "\n",
        "# concatenate the bitstrings in `alpha` and `beta` to \"merge\" the results\n",
        "# of the two registers\n",
        "merged_results = BitArray.concatenate_bits([data.alpha, data.beta])\n",
        "print(f\"\\nThe shape of the merged results is {merged_results.array.shape}.\")\n",
        "print(f\"The bytes of the merged results:\\n{merged_results.array}\\n\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6863da3a-77bd-4b7c-ac95-e5b4dd116180",
      "metadata": {},
      "source": [
        "<span id=\"result-metadata\" />\n",
        "\n",
        "## Metadados do resultado\n",
        "\n",
        "Além dos resultados da execução, os `PrimitiveResult` objetos `PubResult` e contêm um atributo de metadados opcional sobre o trabalho que foi enviado. Os metadados retornados (se houver) dependem da implementação.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "5c08eeaa-8857-4fb6-aa8d-c4916f7354e8",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The metadata of the PrimitiveResult is:\n",
            "'version' : 2,\n",
            "\n",
            "The metadata of the PubResult result is:\n",
            "'shots' : 1024,\n",
            "'circuit_metadata' : {},\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",
      "id": "75c67c45-102e-41dd-aebc-9e139b71a02f",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * Consulte a API do [Qiskit primitives](/docs/api/qiskit/primitives).\n",
        "  * Consulte a API [de primitivas do Qiskit Aer](https://qiskit.github.io/qiskit-aer/apidocs/aer_primitives.html).\n",
        "  * Saiba mais sobre as [primitivas do `Qiskit Runtime`](/docs/guides/qiskit-runtime-primitives).\n",
        "  * Consulte a API [do Estimador](/docs/api/qiskit-ibm-runtime/estimator-v2) do Qiskit Runtime.\n",
        "  * Consulte a API [do Sampler](/docs/api/qiskit-ibm-runtime/sampler-v2) do Qiskit Runtime.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "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
}