{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Iniciação rápida\"\n",
        "description: \"Guia rápido para a versão mais recente do Qiskit: absorção de ruído propagado\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0b3182b6",
      "metadata": {},
      "source": [
        "<span id=\"quickstart\" />\n",
        "\n",
        "# Iniciação rápida\n",
        "\n",
        "`qiskit-addon-pna` Este guia apresenta um exemplo mínimo funcional do pacote. Utilizamos a absorção de ruído propagada (PNA) para construir um observável de mitigação de ruído. Dado um circuito e um modelo de ruído de Pauli-Lindblad, a PNA propaga, de forma clássica, a observável através do canal de ruído inverso. A medição da grandeza observável resultante na QPU com ruído atenua o ruído das portas aprendidas.\n",
        "\n",
        "Para saber como criar um fluxo de trabalho realista e executá-lo em hardware quântico com o [modelo de execução direcionada](/docs/guides/directed-execution-model), incluindo o aprendizado do modelo de ruído com `NoiseLearnerV3`, confira o [tutorial](/docs/tutorials/propagated-noise-absorption) do PNA no site IBM Quantum Platform.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a4068f26",
      "metadata": {},
      "source": [
        "<span id=\"1-prepare-the-inputs-for-pna\" />\n",
        "\n",
        "## 1. Preparar os dados de entrada para o PNA\n",
        "\n",
        "O PNA recebe como entrada um circuito, um modelo de ruído e uma variável observável. Aqui, construímos um modelo de Ising de campo transversal com Trotterização de 10 qubits em uma cadeia de 1D. Geramos um modelo aleatório de ruído de Pauli-Lindblad de 2 locais para cada porta de entrelaçamento e o incorporamos como uma instrução do Qiskit Aer `PauliLindbladError` imediatamente antes dessa porta. Escolhemos um observável de Pauli-Z weight-4 para medir.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "4a9a3ced",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-pna/guides/quickstart/extracted-outputs/4a9a3ced-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import numpy as np\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import SparsePauliOp, pauli_basis\n",
        "from qiskit_aer.noise import PauliLindbladError\n",
        "\n",
        "\n",
        "def random_pauli_lindblad_noise(generators, seed, noise_scale=2e-3):\n",
        "    rates = np.random.default_rng(seed).random(len(generators)) * noise_scale\n",
        "    return PauliLindbladError(generators, rates)\n",
        "\n",
        "\n",
        "def ising_circuit(\n",
        "    num_qubits,\n",
        "    layers,\n",
        "    edge_noise=None,\n",
        "    *,\n",
        "    num_steps=3,\n",
        "    rx_angle=np.pi / 8,\n",
        "    rzz_angle=-np.pi / 2,\n",
        "):\n",
        "    \"\"\"Trotterized transverse-field Ising model; edge_noise=None gives the noiseless circuit.\"\"\"\n",
        "    qc = QuantumCircuit(num_qubits)\n",
        "    for _ in range(num_steps):\n",
        "        qc.rx(rx_angle, range(num_qubits))\n",
        "        for layer in layers:\n",
        "            for edge in layer:\n",
        "                if edge_noise is not None:\n",
        "                    qc.append(\n",
        "                        edge_noise[edge], edge\n",
        "                    )  # inject synthetic gate noise\n",
        "                qc.rzz(rzz_angle, *edge)\n",
        "    return qc\n",
        "\n",
        "\n",
        "num_qubits = 10\n",
        "\n",
        "# Two entangling layers per Trotter step: even and odd bonds of a 1D chain\n",
        "layers = [\n",
        "    [(i, i + 1) for i in range(0, num_qubits - 1, 2)],\n",
        "    [(i, i + 1) for i in range(1, num_qubits - 1, 2)],\n",
        "]\n",
        "edges = [edge for layer in layers for edge in layer]\n",
        "\n",
        "# Random 2-local Pauli-Lindblad noise, one instance per entangling gate\n",
        "two_qubit_paulis = SparsePauliOp(\n",
        "    [p for p in pauli_basis(2) if np.sum(p.x + p.z)]\n",
        ").paulis\n",
        "edge_noise = {\n",
        "    edge: random_pauli_lindblad_noise(two_qubit_paulis, seed=1234 + j)\n",
        "    for j, edge in enumerate(edges)\n",
        "}\n",
        "\n",
        "noisy_circuit = ising_circuit(num_qubits, layers, edge_noise)\n",
        "\n",
        "# A single weight-4 observable: <Z3 Z4 Z5 Z6>\n",
        "observable = SparsePauliOp.from_sparse_list(\n",
        "    [(\"ZZZZ\", [3, 4, 5, 6], 1.0)], num_qubits=num_qubits\n",
        ")\n",
        "\n",
        "noisy_circuit.draw(\"mpl\", fold=-1, scale=0.6)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b99617c3",
      "metadata": {},
      "source": [
        "<span id=\"2-generate-the-noise-mitigating-observable\" />\n",
        "\n",
        "## 2. Gerar o observável de mitigação de ruído\n",
        "\n",
        "[O generate\\_noise\\_mitigating\\_observable](/docs/api/qiskit-addon-pna/qiskit-addon-pna#generate_noise_mitigating_observable) propaga cada gerador de Pauli do canal de ruído inverso até o final do circuito. A observável é então submetida à retropropagação pelo canal de ruído inverso, retornando uma nova observável $\\tilde{O}$. Três parâmetros principais afetam o custo computacional:\n",
        "\n",
        "* `max_err_terms`: o número de termos mantidos em cada gerador antirruído à medida que ele é propagado para a frente.\n",
        "* `max_obs_terms`: o número de termos armazenados em $\\tilde{O}$.\n",
        "* `atol`: os termos cuja magnitude do coeficiente for inferior a esse limite são descartados.\n",
        "\n",
        "Para esse pequeno circuito próximo de Clifford, definimos limites altos para os termos e usamos um valor modesto `atol`de, de modo que $\\tilde{O}$ permaneça pequeno e possamos medir todos os seus termos.\n",
        "\n",
        "***Observação: Esta função utiliza Python `multiprocessing`. Ao executá-lo como um script, chame-o dentro de um `if __name__ == \"__main__\":` `guard`.***\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "39891ec7",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Original observable:         1 term\n",
            "Noise-mitigating observable: 207 terms\n"
          ]
        }
      ],
      "source": [
        "from qiskit_addon_pna import generate_noise_mitigating_observable\n",
        "\n",
        "mitigating_observable = generate_noise_mitigating_observable(\n",
        "    noisy_circuit,\n",
        "    observable,\n",
        "    max_err_terms=100_000,\n",
        "    max_obs_terms=100_000,\n",
        "    atol=1e-5,\n",
        "    num_processes=4,\n",
        ")\n",
        "\n",
        "print(f\"Original observable:         {len(observable)} term\")\n",
        "print(f\"Noise-mitigating observable: {len(mitigating_observable)} terms\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f7881a9e",
      "metadata": {},
      "source": [
        "<span id=\"3-mitigate-gate-errors-by-measuring-the-noise-mitigating-observable\" />\n",
        "\n",
        "## 3. Mitigar erros de porta medindo o observável de mitigação de ruído\n",
        "\n",
        "Aqui vemos que o novo observável atenua efetivamente o ruído do gate que afeta o experimento.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "a56dd204",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Ideal (noiseless):   0.8073\n",
            "Noisy (unmitigated): 0.6431\n",
            "Mitigated (PNA):     0.8071\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-pna/guides/quickstart/extracted-outputs/a56dd204-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "from qiskit_aer.primitives import EstimatorV2\n",
        "\n",
        "noiseless_circuit = ising_circuit(num_qubits, layers)\n",
        "\n",
        "# density_matrix method at zero precision -> exact expectation values (no shot noise)\n",
        "estimator = EstimatorV2(\n",
        "    options={\n",
        "        \"backend_options\": {\"method\": \"density_matrix\"},\n",
        "        \"default_precision\": 0.0,\n",
        "    }\n",
        ")\n",
        "\n",
        "ideal, noisy, mitigated = (\n",
        "    result.data.evs\n",
        "    for result in estimator.run(\n",
        "        [\n",
        "            (noiseless_circuit, observable),\n",
        "            (noisy_circuit, observable),\n",
        "            (noisy_circuit, mitigating_observable),\n",
        "        ]\n",
        "    ).result()\n",
        ")\n",
        "\n",
        "print(f\"Ideal (noiseless):   {ideal:.4f}\")\n",
        "print(f\"Noisy (unmitigated): {noisy:.4f}\")\n",
        "print(f\"Mitigated (PNA):     {mitigated:.4f}\")\n",
        "\n",
        "fig, ax = plt.subplots()\n",
        "ax.bar(\n",
        "    [\"Noisy\", \"Mitigated\"],\n",
        "    [noisy, mitigated],\n",
        "    width=0.6,\n",
        "    color=[\"#b0b0b0\", \"#4c4c4c\"],\n",
        ")\n",
        "ax.axhline(ideal, color=\"green\", linestyle=\"--\", label=\"Ideal (noiseless)\")\n",
        "ax.set_ylabel(r\"$\\langle Z_3 Z_4 Z_5 Z_6 \\rangle$\")\n",
        "ax.legend()\n",
        "plt.show()"
      ]
    },
    {
      "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": 5
}