{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "3b140909-ace6-4665-a0bf-f3bb9bd094c0",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Simulação exata com primitivas d Qiskit SDK\"\n",
        "description: \"Como realizar simulações exatas de circuitos quânticos usando primitivas no Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"exact-simulation-with-qiskit-sdk-primitives\" />\n",
        "\n",
        "# Simulação exata com primitivas d Qiskit SDK\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b820ca5f-60cc-41c7-98db-4b41df4534cc",
      "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": "867f73c6-dd57-4755-9bbd-55ffffe7e09e",
      "metadata": {},
      "source": [
        "As primitivas de referência no `Qiskit SDK` realizam simulações com vetores de estado locais. Essas simulações não permitem\n",
        "modelar o ruído do dispositivo, mas são úteis para a prototipagem rápida de algoritmos antes de se explorar técnicas de simulação\n",
        "mais avançadas ( [usando o Qiskit Aer](/docs/guides/simulate-stabilizer-circuits) ) ou de executá-los em dispositivos reais ( [primitivas do Qiskit Runtime](primitives) ).\n",
        "\n",
        "A primitiva Estimator pode calcular os valores de expectativa dos circuitos, e a primitiva Sampler pode fazer uma amostragem das distribuições de saída dos circuitos.\n",
        "\n",
        "As seções a seguir mostram como usar as primitivas de referência para executar seu fluxo de trabalho localmente.\n",
        "\n",
        "<span id=\"use-the-reference-estimator\" />\n",
        "\n",
        "## Use o Estimador de referência\n",
        "\n",
        "A implementação de referência do `EstimatorV2` em `qiskit.primitives` que é executada em um simulador de vetor de estado local é a classe [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) classe. Ele pode receber circuitos, observáveis e parâmetros como entradas e retorna os valores de expectativa computados localmente.\n",
        "\n",
        "O código a seguir prepara os dados de entrada que serão utilizados nos exemplos a seguir. O tipo de entrada esperado para os\n",
        "observáveis é [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Observe que\n",
        "o circuito do exemplo é parametrizado, mas você também pode executar o Estimator em circuitos não parametrizados.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Qualquer circuito passado para um Estimador **não** deve incluir nenhuma **medida**.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "5b41a52d-8f15-4ce4-b3f6-effd91946d9c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/simulate-with-qiskit-sdk-primitives/extracted-outputs/5b41a52d-8f15-4ce4-b3f6-effd91946d9c-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.circuit import Parameter\n",
        "\n",
        "# circuit for which you want to obtain the expected value\n",
        "circuit = QuantumCircuit(2)\n",
        "circuit.ry(Parameter(\"theta\"), 0)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.draw(\"mpl\", style=\"iqp\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "18658518-304a-49a7-8958-82adef366de6",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.quantum_info import SparsePauliOp\n",
        "import numpy as np\n",
        "\n",
        "# observable(s) whose expected values you want to compute\n",
        "\n",
        "observable = SparsePauliOp([\"II\", \"XX\", \"YY\", \"ZZ\"], coeffs=[1, 1, -1, 1])\n",
        "\n",
        "# value(s) for the circuit parameter(s)\n",
        "parameter_values = [[0], [np.pi / 6], [np.pi / 2]]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4c39904c-d586-41b9-ade0-e6a508ef7c2e",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\" title=\"Transpile para circuitos ISA e observáveis\">\n",
        "  O fluxo de trabalho das primitivas Qiskit Runtime exige que os circuitos e observáveis sejam transformados para usar somente as instruções compatíveis com a QPU (denominadas circuitos e observáveis *da arquitetura do conjunto de instruções (ISA)* ). As primitivas de referência ainda aceitam instruções abstratas, pois dependem de simulações de vetores de estado locais, mas a transpilação do circuito ainda pode ser benéfica em termos de otimização do circuito.\n",
        "\n",
        "  ```python\n",
        "  # Generate a pass manager without providing a backend\n",
        "  from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "  pm = generate_preset_pass_manager(optimization_level=1)\n",
        "  isa_circuit = pm.run(circuit)\n",
        "  isa_observable = observable.apply_layout(isa_circuit.layout)\n",
        "  ```\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"initialize-estimator\" />\n",
        "\n",
        "### Inicializar Estimador\n",
        "\n",
        "Instanciar a [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "56f39026-7874-4f14-8529-b97df373eaf5",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.primitives import StatevectorEstimator\n",
        "\n",
        "estimator = StatevectorEstimator()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9c4c81b1-8b87-450d-9a93-4f209364ee83",
      "metadata": {},
      "source": [
        "<span id=\"run-and-get-results\" />\n",
        "\n",
        "### Corra e obtenha resultados\n",
        "\n",
        "Este exemplo usa apenas um circuito (do tipo [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) e um observável.\n",
        "\n",
        "Execute a estimativa chamando o método [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) que retorna uma instância de um objeto [`PrimitiveJob`](/docs/api/qiskit/qiskit.primitives.PrimitiveJob) objeto. Você pode obter os resultados do trabalho (como um objeto [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) objeto) com o método [`qiskit.primitives.PrimitiveJob.result`](../api/qiskit/qiskit.primitives.PrimitiveJob#result) método.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "0c424291-abb3-420c-80e1-a09ecbd6c035",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " > Result class: <class 'qiskit.primitives.containers.primitive_result.PrimitiveResult'>\n"
          ]
        }
      ],
      "source": [
        "job = estimator.run([(circuit, observable, parameter_values)])\n",
        "result = job.result()\n",
        "print(f\" > Result class: {type(result)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "871ce7d6-402c-417f-8a83-805d92fa0298",
      "metadata": {},
      "source": [
        "<span id=\"get-the-expected-value-from-the-result\" />\n",
        "\n",
        "#### Obtenha o valor esperado do resultado\n",
        "\n",
        "O resultado das primitivas gera uma matriz de [`PubResult`](/docs/api/qiskit/qiskit.primitives.PubResult#pubresult) objetos, em que cada item da matriz é um `PubResult` objeto que contém em seus dados a matriz de avaliações correspondentes a cada combinação observável do circuito no PUB.\n",
        "\n",
        "Para recuperar os valores de expectativa e os metadados da primeira (e, neste caso, única) avaliação de circuito, devemos acessar a avaliação [`data`](/docs/api/qiskit/qiskit.primitives.PubResult#data) para PUB 0:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "145b3f62-dfaf-4288-8764-f2ecb90e38a1",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " > Expectation value: [4.         3.73205081 2.        ]\n",
            " > Metadata: {'target_precision': 0.0, 'circuit_metadata': {}}\n"
          ]
        }
      ],
      "source": [
        "print(f\" > Expectation value: {result[0].data.evs}\")\n",
        "print(f\" > Metadata: {result[0].metadata}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e29ec8cc-2c38-464a-a8b3-8f05b282c807",
      "metadata": {},
      "source": [
        "<span id=\"set-estimator-run-options\" />\n",
        "\n",
        "### Definir opções de execução do Estimador\n",
        "\n",
        "Por padrão, o Estimador de referência executa um cálculo exato do vetor de estado com base no [`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) classe.\n",
        "No entanto, isso pode ser modificado para introduzir o efeito da sobrecarga de amostragem (também conhecido como \"ruído de disparo\").\n",
        "\n",
        "O Estimator aceita um argumento `precision` que expressa as barras de erro que a implementação primitiva deve visar para estimativas de valores de expectativa.  Essa é a sobrecarga de amostragem e é definida exclusivamente no método `.run()` . Isso permite que você faça o ajuste fino da opção até o nível PUB.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "04047e7a-23f4-431b-8e3a-11edf035e8fc",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Estimate expectation values for two PUBs, both with 0.05 precision.\n",
        "precise_job = estimator.run(\n",
        "    [(circuit, observable, parameter_values)], precision=0.05\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d54f110f-004a-4337-8b4d-7d4287f22be9",
      "metadata": {},
      "source": [
        "Para ver um exemplo completo, consulte a página [de exemplos do Estimator](/docs/guides/estimator-examples).\n",
        "\n",
        "<span id=\"use-the-reference-sampler\" />\n",
        "\n",
        "## Use o Sampler de referência\n",
        "\n",
        "A implementação de referência de `SamplerV2` em `qiskit.primitives` é a classe [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) classe. Ele usa circuitos e parâmetros como entradas e retorna os resultados da amostragem das distribuições de probabilidade de saída como uma distribuição de quase-probabilidade dos estados de saída.\n",
        "\n",
        "O código a seguir prepara as entradas utilizadas nos exemplos a seguir. Observe que\n",
        "esses exemplos executam um único circuito parametrizado, mas você também pode executar o Sampler\n",
        "em circuitos não parametrizados.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "d4c0ac3b-8e5b-4cde-bb26-256324982c2c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/simulate-with-qiskit-sdk-primitives/extracted-outputs/d4c0ac3b-8e5b-4cde-bb26-256324982c2c-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "\n",
        "circuit = QuantumCircuit(2)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.measure_all()\n",
        "circuit.draw(\"mpl\", style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b34ae490-9efb-45f5-937d-3ce86afa445f",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\">\n",
        "  Qualquer circuito quântico passado para um Sampler **deve** incluir medições.\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Transpile para circuitos ISA e observáveis\">\n",
        "  O fluxo de trabalho das primitivas Qiskit Runtime exige que os circuitos sejam transformados para usar somente as instruções compatíveis com a QPU (chamadas de circuitos ISA). As primitivas de referência ainda aceitam instruções abstratas, pois dependem de simulações de vetores de estado locais, mas a transpilação do circuito ainda pode ser benéfica em termos de otimização do circuito.\n",
        "\n",
        "  ```python\n",
        "  # Generate a pass manager without providing a backend\n",
        "  from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "  pm = generate_preset_pass_manager(optimization_level=1)\n",
        "  isa_circuit = pm.run(qc)\n",
        "  ```\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"initialize-samplerv2\" />\n",
        "\n",
        "### Inicializar `SamplerV2`\n",
        "\n",
        "Instanciar [`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler):\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "626177e7-f06a-4216-89c8-daf703520457",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.primitives import StatevectorSampler\n",
        "\n",
        "sampler = StatevectorSampler()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "626fb8d6-75ae-47b2-ac0b-00acc4ce5afe",
      "metadata": {},
      "source": [
        "<span id=\"run-and-get-results\" />\n",
        "\n",
        "### Corra e obtenha resultados\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "19659756-a01d-42ec-8fa7-d7a1bf2303d5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " > Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>\n"
          ]
        }
      ],
      "source": [
        "# execute 1 circuit with Sampler\n",
        "job = sampler.run([circuit])\n",
        "pub_result = job.result()[0]\n",
        "print(f\" > Result class: {type(pub_result)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ee6d88f3-0115-4ea9-a2c5-633906841d9f",
      "metadata": {},
      "source": [
        "As primitivas aceitam vários PUBs como entradas, e cada PUB obtém seu próprio resultado. Portanto, você pode executar diferentes circuitos com várias combinações de parâmetros/observáveis e recuperar os resultados PUB :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "fb91dbfc-0340-4ea6-8d33-95357d7907e3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " > Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>\n"
          ]
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "# create two circuits\n",
        "circuit1 = circuit.copy()\n",
        "circuit2 = circuit.copy()\n",
        "\n",
        "# transpile circuits\n",
        "pm = generate_preset_pass_manager(optimization_level=1)\n",
        "isa_circuit1 = pm.run(circuit1)\n",
        "isa_circuit2 = pm.run(circuit2)\n",
        "# execute 2 circuits using Sampler\n",
        "job = sampler.run([(isa_circuit1), (isa_circuit2)])\n",
        "pub_result_1 = job.result()[0]\n",
        "pub_result_2 = job.result()[1]\n",
        "print(f\" > Result class: {type(pub_result)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6e7b2199-3c00-477a-a248-824b442431b5",
      "metadata": {},
      "source": [
        "<span id=\"get-the-probability-distribution-or-measurement-outcome\" />\n",
        "\n",
        "### Obtenha a distribuição de probabilidade ou o resultado da medição\n",
        "\n",
        "As amostras de resultados de medição são retornadas como **cadeias de bits** ou **contagens**. As cadeias de bits mostram os resultados da medição, preservando a ordem de disparo em que foram medidos. Os objetos de resultado do Sampler organizam os dados em termos dos nomes de registros clássicos dos circuitos de entrada, para compatibilidade com circuitos dinâmicos.\n",
        "\n",
        "<Admonition>\n",
        "  O nome do registro clássico tem como padrão `\"meas\"`. Esse nome será usado posteriormente para acessar os bitstrings de medição.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "1dc395b4-5716-44be-9622-7c99df95616b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "        ┌───┐      ░ ┌─┐   \n",
              "   q_0: ┤ H ├──■───░─┤M├───\n",
              "        └───┘┌─┴─┐ ░ └╥┘┌─┐\n",
              "   q_1: ─────┤ X ├─░──╫─┤M├\n",
              "             └───┘ ░  ║ └╥┘\n",
              "meas: 2/══════════════╩══╩═\n",
              "                      0  1 "
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Define quantum circuit with 2 qubits\n",
        "circuit = QuantumCircuit(2)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.measure_all()\n",
        "circuit.draw()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "27a2847b-6553-4c73-9b8a-85ba28725ed8",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The number of bitstrings is: 1024\n",
            "The counts are: {'11': 519, '00': 505}\n"
          ]
        }
      ],
      "source": [
        "# Transpile circuit\n",
        "pm = generate_preset_pass_manager(optimization_level=1)\n",
        "isa_circuit = pm.run(circuit)\n",
        "# Run using Sampler\n",
        "result = sampler.run([circuit]).result()\n",
        "# Access result data for PUB 0\n",
        "data_pub = result[0].data\n",
        "# Access bitstring for the classical register \"meas\"\n",
        "bitstrings = data_pub.meas.get_bitstrings()\n",
        "print(f\"The number of bitstrings is: {len(bitstrings)}\")\n",
        "# Get counts for the classical register \"meas\"\n",
        "counts = data_pub.meas.get_counts()\n",
        "print(f\"The counts are: {counts}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "de705fab-e718-4924-a03f-f19bdf6578d8",
      "metadata": {},
      "source": [
        "<span id=\"change-run-options\" />\n",
        "\n",
        "### Alterar opções de execução\n",
        "\n",
        "Por padrão, o Sampler de referência executa um cálculo exato do vetor de estado com base no [`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) classe.\n",
        "No entanto, isso pode ser modificado para introduzir o efeito da sobrecarga de amostragem (também conhecido como \"ruído de disparo\"). Para ajudar a gerenciar essa sobrecarga, a interface do Sampler aceita um argumento `shots` que pode ser definido no nível PUB.\n",
        "\n",
        "Este exemplo pressupõe que você tenha definido dois circuitos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "927faaab-60c0-4b73-bf53-72f7c4c9ad65",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<qiskit.primitives.primitive_job.PrimitiveJob at 0x7fab09442490>"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Sample two circuits at 128 shots each.\n",
        "sampler.run([isa_circuit1, isa_circuit2], shots=128)\n",
        "# Sample two circuits at different amounts of shots. The \"None\"s are necessary\n",
        "# as placeholders\n",
        "# for the lack of parameter values in this example.\n",
        "sampler.run([(isa_circuit1, None, 123), (isa_circuit2, None, 456)])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1c0e76fe-4b5d-4fd4-9eec-da5332d76cfb",
      "metadata": {},
      "source": [
        "Para ver um exemplo completo, consulte a página [de exemplos do Sampler](/docs/guides/sampler-examples).\n",
        "\n",
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * Para obter uma simulação de maior desempenho que possa lidar com circuitos maiores ou para incorporar modelos de ruído em sua simulação, consulte [Simulação exata e com ruído com primitivas Qiskit Aer](simulate-with-qiskit-aer).\n",
        "  * Para saber como usar o Quantum Composer para simulação, consulte o guia [IBM Quantum Composer](/docs/guides/composer).\n",
        "  * Leia a referência [da API do Qiskit Estimator](/docs/api/qiskit/1.4/qiskit.primitives.Estimator).\n",
        "  * Leia a referência [da API do Qiskit Sampler](/docs/api/qiskit/1.4/qiskit.primitives.Sampler).\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
}