{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "fad91a68",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Mitigação de erros\"\n",
        "description: \"Ao longo desta lição, examinaremos o ruído e como ele pode ser mitigado em computadores quânticos.\"\n",
        "---\n",
        "\n",
        "<span id=\"quantum-noise-and-error-mitigation\" />\n",
        "\n",
        "# Ruído quântico e mitigação de erros\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Toshinari Itoko (28 de junho de 2024)\n",
        "\n",
        "  [Baixe o pdf](https://ibm.ent.box.com/public/static/a0zgies7bh91hm2lwev9o0bfeybxc6n6.zip) da palestra original. Observe que alguns trechos de código podem se tornar obsoletos, pois são imagens estáticas.\n",
        "\n",
        "  *O tempo aproximado da QPU para executar esse experimento é de 1 m 40 s.*\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e936adb0-bc31-41a8-b988-02ce7e68b902",
      "metadata": {},
      "source": [
        "<span id=\"1-introduction\" />\n",
        "\n",
        "## 1. Introdução\n",
        "\n",
        "Ao longo desta lição, examinaremos o ruído e como ele pode ser atenuado em computadores quânticos. Começaremos analisando os efeitos do ruído usando um simulador que pode simular o ruído de algumas maneiras, inclusive usando perfis de ruído de computadores quânticos reais. Em seguida, passaremos para os computadores quânticos reais, nos quais o ruído é inerente. Examinaremos os efeitos da atenuação de erros, incluindo combinações de elementos como extrapolação de ruído zero (ZNE) e gate-twirling.\n",
        "\n",
        "Começaremos carregando alguns pacotes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "38cf024b",
      "metadata": {},
      "outputs": [],
      "source": [
        "# !pip install qiskit qiskit_aer qiskit_ibm_runtime\n",
        "# !pip install jupyter\n",
        "# !pip install matplotlib pylatexenc"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "897008ea",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'2.0.2'"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import qiskit\n",
        "\n",
        "qiskit.__version__"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "486b4d35",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'0.17.1'"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import qiskit_aer\n",
        "\n",
        "qiskit_aer.__version__"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "994c44e5",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'0.40.1'"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import qiskit_ibm_runtime\n",
        "\n",
        "qiskit_ibm_runtime.__version__"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ee48a826-fda3-4fb4-b50b-d69c38eb887f",
      "metadata": {
        "editable": true,
        "slideshow": {
          "slide_type": "slide"
        },
        "tags": []
      },
      "source": [
        "<span id=\"2-noisy-simulation-without-error-mitigation\" />\n",
        "\n",
        "## 2. Simulação ruidosa sem mitigação de erros\n",
        "\n",
        "O Qiskit Aer é um simulador clássico para computação quântica. Ele pode simular não apenas a execução ideal, mas também a execução ruidosa de circuitos quânticos. Este notebook demonstra como executar uma simulação com ruído usando o Qiskit Aer:\n",
        "\n",
        "1. Criar um modelo de ruído\n",
        "2. Crie um amostrador de ruído (simulador) com o modelo de ruído\n",
        "3. Execute um circuito quântico no amostrador com ruído\n",
        "\n",
        "```\n",
        "noise_model = NoiseModel()\n",
        "...\n",
        "noisy_sampler = Sampler(options={\"backend_options\": {\"noise_model\": noise_model}})\n",
        "job = noisy_sampler.run([circuit])\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d1490ab8",
      "metadata": {},
      "source": [
        "<span id=\"21-build-a-test-circuit\" />\n",
        "\n",
        "### 2.1 Construa um circuito de teste\n",
        "\n",
        "Consideramos circuitos de 1 qubit de brinquedo que apenas repetem portas X `d` vezes (`d`=0... 100) e medir o observável `Z` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "b4863c66",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/error-mitigation/extracted-outputs/b4863c66-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "from qiskit.circuit import QuantumCircuit\n",
        "\n",
        "MAX_DEPTH = 100\n",
        "circuits = []\n",
        "for d in range(MAX_DEPTH + 1):\n",
        "    circ = QuantumCircuit(1)\n",
        "    for _ in range(d):\n",
        "        circ.x(0)\n",
        "        circ.barrier(0)\n",
        "    circ.measure_all()\n",
        "    circuits.append(circ)\n",
        "\n",
        "display(circuits[3].draw(output=\"mpl\"))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "a366502c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "SparsePauliOp(['Z'],\n",
              "              coeffs=[1.+0.j])"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.quantum_info import SparsePauliOp\n",
        "\n",
        "obs = SparsePauliOp.from_list([(\"Z\", 1.0)])\n",
        "obs"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6200c2ed",
      "metadata": {},
      "source": [
        "<span id=\"22-build-a-noise-model\" />\n",
        "\n",
        "### 2.2 Crie um modelo de ruído\n",
        "\n",
        "Para fazer uma simulação com ruído, precisamos especificar `NoiseModel`. Nesta seção, mostraremos como criar o site `NoiseModel` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dae0c070",
      "metadata": {},
      "source": [
        "Primeiro, precisamos definir erros quânticos (ou de leitura) para adicionar a um modelo de ruído.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "1e0f1c12",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_aer.noise.errors import (\n",
        "    coherent_unitary_error,\n",
        "    amplitude_damping_error,\n",
        "    ReadoutError,\n",
        ")\n",
        "from qiskit.circuit.library import RXGate\n",
        "\n",
        "# Coherent (unitary) error: Over X-rotation error\n",
        "# https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.coherent_unitary_error.html#qiskit_aer.noise.coherent_unitary_error\n",
        "OVER_ROTATION_ANGLE = 0.05\n",
        "coherent_error = coherent_unitary_error(RXGate(OVER_ROTATION_ANGLE).to_matrix())\n",
        "\n",
        "# Incoherent error: Amplitude dumping error\n",
        "# https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.amplitude_damping_error.html#qiskit_aer.noise.amplitude_damping_error\n",
        "AMPLITUDE_DAMPING_PARAM = 0.02  # in [0, 1] (0: no error)\n",
        "incoherent_error = amplitude_damping_error(AMPLITUDE_DAMPING_PARAM)\n",
        "\n",
        "# Readout (measurement) error: Readout error\n",
        "# https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.ReadoutError.html#qiskit_aer.noise.ReadoutError\n",
        "PREP0_MEAS1 = 0.03  # P(1|0): Probability of preparing 0 and measuring 1\n",
        "PREP1_MEAS0 = 0.08  # P(0|1): Probability of preparing 1 and measuring 0\n",
        "readout_error = ReadoutError(\n",
        "    [[1 - PREP0_MEAS1, PREP0_MEAS1], [PREP1_MEAS0, 1 - PREP1_MEAS0]]\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "e23c26ba",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_aer.noise import NoiseModel\n",
        "\n",
        "noise_model = NoiseModel()\n",
        "noise_model.add_quantum_error(coherent_error.compose(incoherent_error), \"x\", (0,))\n",
        "noise_model.add_readout_error(readout_error, (0,))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a786224",
      "metadata": {},
      "source": [
        "<span id=\"23-build-a-noisy-sampler-with-the-noise-model\" />\n",
        "\n",
        "### 2.3 Construa um sampler ruidoso com o modelo de ruído\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "f8aded6f",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_aer.primitives import SamplerV2 as Sampler\n",
        "\n",
        "noisy_sampler = Sampler(options={\"backend_options\": {\"noise_model\": noise_model}})"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "922ba1ac",
      "metadata": {},
      "source": [
        "<span id=\"24-run-quantum-circuits-on-the-noisy-sampler\" />\n",
        "\n",
        "### 2.4 Execute circuitos quânticos no amostrador ruidoso\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "4ae504e7",
      "metadata": {},
      "outputs": [],
      "source": [
        "job = noisy_sampler.run(circuits, shots=400)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "3b2fff25",
      "metadata": {},
      "outputs": [],
      "source": [
        "result = job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "4dc12337",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'0': 389, '1': 11}"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "result[0].data.meas.get_counts()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7e654c5e",
      "metadata": {},
      "source": [
        "<span id=\"25-plot-results\" />\n",
        "\n",
        "### 2.5 Resultados do gráfico\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1a25e394",
      "metadata": {},
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "plt.title(\"Noisy simulation\")\n",
        "ds = list(range(MAX_DEPTH + 1))\n",
        "plt.plot(\n",
        "    ds,\n",
        "    [result[d].data.meas.expectation_values([\"Z\"]) for d in ds],\n",
        "    color=\"gray\",\n",
        "    linestyle=\"-\",\n",
        ")\n",
        "plt.scatter(ds, [result[d].data.meas.expectation_values([\"Z\"]) for d in ds], marker=\"o\")\n",
        "plt.hlines(0, xmin=0, xmax=MAX_DEPTH, colors=\"black\")\n",
        "plt.ylim(-1, 1)\n",
        "plt.xlabel(\"Circuit depth\")\n",
        "plt.ylabel(\"Measured <Z>\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "09ef68bb",
      "metadata": {},
      "source": [
        "<span id=\"26-ideal-simulation\" />\n",
        "\n",
        "### 2.6 Simulação ideal\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "041abc81",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/error-mitigation/extracted-outputs/041abc81-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "ideal_sampler = Sampler()\n",
        "job_ideal = ideal_sampler.run(circuits)\n",
        "result_ideal = job_ideal.result()\n",
        "plt.title(\"Ideal simulation\")\n",
        "ds = list(range(MAX_DEPTH + 1))\n",
        "plt.plot(\n",
        "    ds,\n",
        "    [result_ideal[d].data.meas.expectation_values([\"Z\"]) for d in ds],\n",
        "    color=\"gray\",\n",
        "    linestyle=\"-\",\n",
        ")\n",
        "plt.scatter(\n",
        "    ds, [result_ideal[d].data.meas.expectation_values([\"Z\"]) for d in ds], marker=\"o\"\n",
        ")\n",
        "plt.hlines(0, xmin=0, xmax=MAX_DEPTH, colors=\"black\")\n",
        "plt.xlabel(\"Circuit depth\")\n",
        "plt.ylabel(\"Measured <Z>\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a1e1b6e6",
      "metadata": {},
      "source": [
        "<span id=\"27-exercise\" />\n",
        "\n",
        "### 2.7 Exercício\n",
        "\n",
        "Ajustando o código abaixo,\n",
        "\n",
        "* [ ] Experimente 25x número de disparos (= 10\\_000 disparos) e verifique se é obtido um gráfico mais suave\n",
        "* [ ] Altere os parâmetros de ruído (OVER\\_ROTATION\\_ANGLE, AMPLITUDE\\_DAMPING\\_PARAM, PREP0\\_MEAS1 ou PREP1\\_MEAS0 ) e veja como o gráfico muda\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "502b9cfe",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/error-mitigation/extracted-outputs/502b9cfe-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "OVER_ROTATION_ANGLE = 0.05\n",
        "coherent_error = coherent_unitary_error(RXGate(OVER_ROTATION_ANGLE).to_matrix())\n",
        "AMPLITUDE_DAMPING_PARAM = 0.02  # in [0, 1] (0: no error)\n",
        "incoherent_error = amplitude_damping_error(AMPLITUDE_DAMPING_PARAM)\n",
        "PREP0_MEAS1 = 0.1  # P(1|0): Probability of preparing 0 and measuring 1\n",
        "PREP1_MEAS0 = 0.05  # P(0|1): Probability of preparing 1 and measuring 0\n",
        "readout_error = ReadoutError(\n",
        "    [[1 - PREP0_MEAS1, PREP0_MEAS1], [PREP1_MEAS0, 1 - PREP1_MEAS0]]\n",
        ")\n",
        "noise_model = NoiseModel()\n",
        "noise_model.add_quantum_error(coherent_error.compose(incoherent_error), \"x\", (0,))\n",
        "noise_model.add_readout_error(readout_error, (0,))\n",
        "options = {\n",
        "    \"backend_options\": {\"noise_model\": noise_model},\n",
        "}\n",
        "noisy_sampler = Sampler(options=options)\n",
        "job = noisy_sampler.run(circuits, shots=400)\n",
        "result = job.result()\n",
        "plt.title(\"Noisy simulation\")\n",
        "ds = list(range(MAX_DEPTH + 1))\n",
        "plt.plot(\n",
        "    ds,\n",
        "    [result[d].data.meas.expectation_values([\"Z\"]) for d in ds],\n",
        "    marker=\"o\",\n",
        "    linestyle=\"-\",\n",
        ")\n",
        "plt.hlines(0, xmin=0, xmax=MAX_DEPTH, colors=\"black\")\n",
        "plt.ylim(-1, 1)\n",
        "plt.xlabel(\"Depth\")\n",
        "plt.ylabel(\"Measured <Z>\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3cfe1a93",
      "metadata": {},
      "source": [
        "<span id=\"28-more-realistic-noisy-simulation\" />\n",
        "\n",
        "### 2.8 Simulação ruidosa mais realista\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "8d607bb5",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<IBMBackend('ibm_strasbourg')>"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit_aer import AerSimulator\n",
        "from qiskit_ibm_runtime import SamplerV2 as Sampler, QiskitRuntimeService\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "real_backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")  # Eagle"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "81a67f2f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/error-mitigation/extracted-outputs/81a67f2f-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "aer = AerSimulator.from_backend(real_backend)\n",
        "noisy_sampler = Sampler(mode=aer)\n",
        "job = noisy_sampler.run(circuits)\n",
        "result = job.result()\n",
        "plt.title(\"Noisy simulation with noise model from real backend\")\n",
        "ds = list(range(MAX_DEPTH + 1))\n",
        "plt.plot(\n",
        "    ds,\n",
        "    [result[d].data.meas.expectation_values([\"Z\"]) for d in ds],\n",
        "    marker=\"o\",\n",
        "    linestyle=\"-\",\n",
        ")\n",
        "plt.hlines(0, xmin=0, xmax=MAX_DEPTH, colors=\"black\")\n",
        "plt.ylim(-1, 1)\n",
        "plt.xlabel(\"Depth\")\n",
        "plt.ylabel(\"Measured <Z>\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "567d30e9",
      "metadata": {},
      "source": [
        "<span id=\"3-real-quantum-computation-with-error-mitigation\" />\n",
        "\n",
        "## 3. Computação quântica real com mitigação de erros\n",
        "\n",
        "Nesta parte, demonstramos como obter resultados com atenuação de erros (valores de expectativa) usando o Qiskit Estimator.\n",
        "Consideramos circuitos Trotterizados de 6 qubits para simular a evolução do tempo do modelo de Ising unidimensional e observamos como o erro é dimensionado em relação ao número de etapas de tempo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "2d301499",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<IBMBackend('ibm_strasbourg')>"
            ]
          },
          "execution_count": 20,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")  # Eagle\n",
        "backend"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "6c90b89c",
      "metadata": {},
      "outputs": [],
      "source": [
        "NUM_QUBITS = 6\n",
        "NUM_TIME_STEPS = list(range(8))\n",
        "RX_ANGLE = 0.1\n",
        "RZZ_ANGLE = 0.1"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b1489739",
      "metadata": {},
      "source": [
        "<span id=\"31-build-circuits\" />\n",
        "\n",
        "### 3.1 Construa circuitos\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "1a77956e",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Build circuits with different number of time steps\n",
        "circuits = []\n",
        "for n_steps in NUM_TIME_STEPS:\n",
        "    circ = QuantumCircuit(NUM_QUBITS)\n",
        "    for i in range(n_steps):\n",
        "        # rx layer\n",
        "        for q in range(NUM_QUBITS):\n",
        "            circ.rx(RX_ANGLE, q)\n",
        "        # 1st rzz layer\n",
        "        for q in range(1, NUM_QUBITS - 1, 2):\n",
        "            circ.rzz(RZZ_ANGLE, q, q + 1)\n",
        "        # 2nd rzz layer\n",
        "        for q in range(0, NUM_QUBITS - 1, 2):\n",
        "            circ.rzz(RZZ_ANGLE, q, q + 1)\n",
        "    circ.barrier()  # need not to optimize the circuit\n",
        "    # Uncompute stage\n",
        "    for i in range(n_steps):\n",
        "        for q in range(0, NUM_QUBITS - 1, 2):\n",
        "            circ.rzz(-RZZ_ANGLE, q, q + 1)\n",
        "        for q in range(1, NUM_QUBITS - 1, 2):\n",
        "            circ.rzz(-RZZ_ANGLE, q, q + 1)\n",
        "        for q in range(NUM_QUBITS):\n",
        "            circ.rx(-RX_ANGLE, q)\n",
        "    circuits.append(circ)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "94eb9062",
      "metadata": {},
      "source": [
        "Para conhecer o resultado ideal com antecedência, usamos circuitos de computação-descomputação que consistem em um primeiro estágio em que o circuito original $U$ é aplicado e um segundo estágio em que ele é revertido $U^\\dagger$. Observe que o resultado ideal de tais circuitos será trivialmente o estado de entrada $|000000\\rangle$, que tem os valores de expectativa triviais para quaisquer observáveis de Pauli, por exemplo, $\\langle IIIIIZ \\rangle = 1$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "20296b5a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/error-mitigation/extracted-outputs/20296b5a-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Print the circuit with 2 time steps\n",
        "circuits[2].draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cde8d3ea",
      "metadata": {},
      "source": [
        "Observação: Como mostrado acima, o circuito com $k$ etapas de tempo terá $4k$ camadas de porta de dois qubits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "af0d03e9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "SparsePauliOp(['IIIIIZ'],\n",
              "              coeffs=[1.+0.j])"
            ]
          },
          "execution_count": 24,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "obs = SparsePauliOp.from_sparse_list([(\"Z\", [0], 1.0)], num_qubits=NUM_QUBITS)\n",
        "obs"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ebd6ea9b",
      "metadata": {},
      "source": [
        "<span id=\"32-transpile-the-circuits\" />\n",
        "\n",
        "### 3.2 Transpilar os circuitos\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8eaa552e",
      "metadata": {},
      "source": [
        "Transpilamos os circuitos para o backend com otimização (`optimization_level=1`).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "87b861e2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/error-mitigation/extracted-outputs/87b861e2-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "pm = generate_preset_pass_manager(optimization_level=1, backend=backend)\n",
        "isa_circuits = pm.run(circuits)\n",
        "display(isa_circuits[2].draw(\"mpl\", idle_wires=False, fold=-1))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "743ad427",
      "metadata": {},
      "source": [
        "<span id=\"33-execute-using-estimator-with-different-resilience-levels\" />\n",
        "\n",
        "### 3.3 Executar usando o Estimador (com diferentes níveis de resiliência)\n",
        "\n",
        "Definir o nível de resiliência (`estimator.options.resilience_level`) é a maneira mais fácil de aplicar a mitigação de erros ao usar o Qiskit Estimator. O Estimator suporta os seguintes níveis de resiliência (em 28/06/2024). Veja mais detalhes no guia [de configuração da mitigação de erros](/docs/guides/error-mitigation-and-suppression-techniques).\n",
        "\n",
        "![image.png](https://eu-de.quantum.cloud.ibm.com/learning/images/courses/utility-scale-quantum-computing/error-mitigation/res_level.avif)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "328f71f2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID (rl=0): d146vcnmya70008emprg\n",
            "Job ID (rl=1): d146vdnqf56g0081sva0\n",
            "Job ID (rl=2): d146ven5z6q00087c61g\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import Batch\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "jobs = []\n",
        "job_ids = []\n",
        "with Batch(backend=backend):\n",
        "    for resilience_level in [0, 1, 2]:\n",
        "        estimator = Estimator()\n",
        "        estimator.options.resilience_level = resilience_level\n",
        "        job = estimator.run(\n",
        "            [(circ, obs.apply_layout(circ.layout)) for circ in isa_circuits]\n",
        "        )\n",
        "        job_ids.append(job.job_id())\n",
        "        print(f\"Job ID (rl={resilience_level}): {job.job_id()}\")\n",
        "        jobs.append(job)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "id": "1dd804e4-0d7d-4782-9559-7b3796cab121",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "DONE\n",
            "DONE\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "# check job status\n",
        "for job in jobs:\n",
        "    print(job.status())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "id": "d138e1e9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# REPLACE WITH YOUR OWN JOB IDS\n",
        "jobs = [service.job(job_id) for job_id in job_ids]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "id": "ea820e98",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Get results\n",
        "results = [job.result() for job in jobs]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e3691462",
      "metadata": {},
      "source": [
        "<span id=\"34-plot-results\" />\n",
        "\n",
        "### 3.4 Resultados do gráfico\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "id": "7527976e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/error-mitigation/extracted-outputs/7527976e-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plt.title(\"Error mitigation with different resilience levels\")\n",
        "labels = [\"0 (No mitigation)\", \"1 (TREX)\", \"2 (ZNE + Gate twirling)\"]\n",
        "steps = NUM_TIME_STEPS\n",
        "for result, label in zip(results, labels):\n",
        "    plt.errorbar(\n",
        "        x=steps,\n",
        "        y=[result[s].data.evs for s in steps],\n",
        "        yerr=[result[s].data.stds for s in steps],\n",
        "        marker=\"o\",\n",
        "        linestyle=\"-\",\n",
        "        capsize=4,\n",
        "        label=label,\n",
        "    )\n",
        "plt.hlines(\n",
        "    1.0, min(steps), max(steps), linestyle=\"dashed\", label=\"Ideal\", colors=\"black\"\n",
        ")\n",
        "plt.xlabel(\"Time steps\")\n",
        "plt.ylabel(\"Mitigated <IIIIIZ>\")\n",
        "plt.legend()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e4def30b",
      "metadata": {},
      "source": [
        "<span id=\"4-optional-customize-error-mitigation-options\" />\n",
        "\n",
        "## 4 (Opcional) Personalizar opções de mitigação de erros\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f099e16c",
      "metadata": {},
      "source": [
        "Podemos personalizar a aplicação de técnicas de atenuação de erros por meio de opções, conforme mostrado abaixo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 35,
      "id": "a22e6b8c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# TREX\n",
        "estimator.options.twirling.enable_measure = True\n",
        "estimator.options.twirling.num_randomizations = \"auto\"\n",
        "estimator.options.twirling.shots_per_randomization = \"auto\"\n",
        "\n",
        "# Gate twirling\n",
        "estimator.options.twirling.enable_gates = True\n",
        "# ZNE\n",
        "estimator.options.resilience.zne_mitigation = True\n",
        "estimator.options.resilience.zne.noise_factors = [1, 3, 5]\n",
        "estimator.options.resilience.zne.extrapolator = (\"exponential\", \"linear\")\n",
        "\n",
        "# Dynamical decoupling\n",
        "estimator.options.dynamical_decoupling.enable = True  # Default: False\n",
        "estimator.options.dynamical_decoupling.sequence_type = \"XX\"\n",
        "\n",
        "# Other options\n",
        "estimator.options.default_shots = 10_000"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "79dd06fb",
      "metadata": {},
      "source": [
        "Consulte os guias e a referência de API a seguir para obter detalhes sobre as opções de atenuação de erros.\n",
        "\n",
        "* [Configurar mitigação de erros](/docs/guides/error-mitigation-and-suppression-techniques)\n",
        "* [Introdução às opções](/docs/guides/runtime-options-overview)\n",
        "* [EstimatorOptions](/docs/api/qiskit-ibm-runtime/options-estimator-options)\n",
        "* [SamplerOptions](/docs/api/qiskit-ibm-runtime/options-sampler-options)\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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}