{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "d53161ce",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Definir o nível de otimização do transpiler\"\n",
        "description: \"Como definir o nível de otimização para transpilagem de circuitos quânticos no Qiskit.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Cartan's */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6f5a4641-5b7f-4841-8bec-60fa44429030",
      "metadata": {},
      "source": [
        "<span id=\"set-transpiler-optimization-level\" />\n",
        "\n",
        "# Definir o nível de otimização do transpiler\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8a1db79c-9bee-4737-b8b5-13155062ca04",
      "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",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bd9eb973-430c-4450-8de2-c061aa0ff742",
      "metadata": {},
      "source": [
        "Os dispositivos quânticos reais estão sujeitos a ruídos e erros de porta, portanto, a otimização dos circuitos para reduzir sua profundidade e contagem de portas pode melhorar significativamente os resultados obtidos com a execução desses circuitos.\n",
        "A função [`generate_preset_pass_manager`](/docs/api/qiskit/qiskit.transpiler.generate_preset_pass_manager#qiskit.transpiler.generate_preset_pass_manager) tem um argumento posicional obrigatório, `optimization_level`, que controla o esforço que o transpilador faz para otimizar os circuitos. Esse argumento pode ser um número inteiro com um dos valores 0, 1, 2 ou 3.\n",
        "Níveis de otimização mais altos geram circuitos mais otimizados à custa de tempos de compilação mais longos.\n",
        "A tabela a seguir explica as otimizações realizadas com cada configuração.\n",
        "\n",
        "<Table>\n",
        "  <thead>\n",
        "    <Tr>\n",
        "      <Th>Nível de Otimização</Th>\n",
        "      <Th>Descrição</Th>\n",
        "    </Tr>\n",
        "  </thead>\n",
        "\n",
        "  <tbody>\n",
        "    <Tr>\n",
        "      <Td>0</Td>\n",
        "\n",
        "      <Td>\n",
        "        Sem otimização: normalmente usado para caracterização de hardware\n",
        "\n",
        "        * Tradução básica\n",
        "        * Layout/Roteamento: `TrivialLayout`, em que ele seleciona os mesmos números de qubit físicos que os virtuais e insere SWAPs para fazê-lo funcionar (usando `SabreSwap`)\n",
        "      </Td>\n",
        "    </Tr>\n",
        "\n",
        "    <Tr>\n",
        "      <Td>1</Td>\n",
        "\n",
        "      <Td>\n",
        "        Otimização da luz:\n",
        "\n",
        "        * Layout/Roteamento: O layout é tentado primeiro com `TrivialLayout`. Se forem necessários SWAPs adicionais, um layout com um número mínimo de SWAPs é encontrado usando `SabreSwap` e, em seguida, ele usa `VF2LayoutPostLayout` para tentar selecionar os melhores qubits no gráfico.\n",
        "        * `InverseCancellation`\n",
        "        * 1Q otimização de portões\n",
        "      </Td>\n",
        "    </Tr>\n",
        "\n",
        "    <Tr>\n",
        "      <Td>2</Td>\n",
        "\n",
        "      <Td>\n",
        "        Otimização média:\n",
        "\n",
        "        * Layout/Roteamento: Nível de otimização 1 (sem trivial) + heurística otimizada com maior profundidade de pesquisa e testes da função de otimização.  Como o `TrivialLayout` não é usado, não há nenhuma tentativa de usar os mesmos números de qubit físico e virtual.\n",
        "        * `CommutativeCancellation`\n",
        "      </Td>\n",
        "    </Tr>\n",
        "\n",
        "    <Tr>\n",
        "      <Td>3</Td>\n",
        "\n",
        "      <Td>\n",
        "        Alta otimização:\n",
        "\n",
        "        * Nível de otimização 2 + heurística otimizada no layout/roteiro com mais esforço/tentativas\n",
        "        * Ressíntese de blocos de dois qubits usando [a decomposição KAK de Cartan](https://arxiv.org/abs/quant-ph/0507171).\n",
        "        * Passes de quebra de unidade:\n",
        "          * `OptimizeSwapBeforeMeasure`: Move as medições para evitar SWAPs\n",
        "          * `RemoveDiagonalGatesBeforeMeasure`: Remove as portas antes das medições que não afetariam as medições\n",
        "      </Td>\n",
        "    </Tr>\n",
        "  </tbody>\n",
        "</Table>\n",
        "\n",
        "<span id=\"optimization-level-in-action\" />\n",
        "\n",
        "## Nível de otimização em ação\n",
        "\n",
        "Como as portas de dois qubits normalmente são a fonte mais significativa de erros, podemos quantificar aproximadamente a \"eficiência de hardware\" da transpilação contando o número de portas de dois qubits no circuito resultante.\n",
        "Aqui, tentaremos os diferentes níveis de otimização em um circuito de entrada que consiste em uma unidade aleatória seguida por uma porta SWAP.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "81173ebc-8359-48a6-b585-0477907b3b93",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/81173ebc-8359-48a6-b585-0477907b3b93-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.library import UnitaryGate\n",
        "from qiskit.quantum_info import Operator, random_unitary\n",
        "\n",
        "UU = random_unitary(4, seed=12345)\n",
        "rand_U = UnitaryGate(UU)\n",
        "\n",
        "qc = QuantumCircuit(2)\n",
        "qc.append(rand_U, range(2))\n",
        "qc.swap(0, 1)\n",
        "qc.draw(\"mpl\", style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "34509d07-7804-46cb-b508-130436d9b01d",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\">\n",
        "  Nestes exemplos, é utilizado o backend `FakeSherbrooke``qiskit_ibm_runtime` simulado do, mas você pode testá-lo em qualquer backend real ou simulado compatível com o Qiskit.  Seus resultados podem ser diferentes.\n",
        "</Admonition>\n",
        "\n",
        "Primeiro, vamos fazer a transpilagem usando o nível de otimização 0.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "40cdd173-b437-48b1-8928-741e8411342e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/40cdd173-b437-48b1-8928-741e8411342e-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=0, backend=backend, seed_transpiler=12345\n",
        ")\n",
        "qc_t1_exact = pass_manager.run(qc)\n",
        "qc_t1_exact.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a5169cb2-cd2a-40c0-93e5-c526580f84aa",
      "metadata": {},
      "source": [
        "O circuito transpilado tem seis portas ECR de dois qubits.\n",
        "\n",
        "Repita o procedimento para o nível de otimização 1:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "2dab5def-a017-42e9-92d6-e043ac4065b2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/2dab5def-a017-42e9-92d6-e043ac4065b2-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=1, backend=backend, seed_transpiler=12345\n",
        ")\n",
        "qc_t1_exact = pass_manager.run(qc)\n",
        "qc_t1_exact.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "69d5d04b-746f-41c4-92e8-62a7eaffb5b2",
      "metadata": {},
      "source": [
        "O circuito transpilado ainda tem seis portas ECR, mas o número de portas de um único qubit foi reduzido.\n",
        "\n",
        "Repita o procedimento para o nível de otimização 2:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "77d76048-b1e8-4225-b35f-80dc9d458e8d",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/77d76048-b1e8-4225-b35f-80dc9d458e8d-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=2, backend=backend, seed_transpiler=12345\n",
        ")\n",
        "qc_t2_exact = pass_manager.run(qc)\n",
        "qc_t2_exact.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4818fb06-88bd-43cb-b23c-eba5a3537e67",
      "metadata": {},
      "source": [
        "Isso produz os mesmos resultados do nível de otimização 1. Observe que aumentar o nível de otimização nem sempre faz diferença.\n",
        "\n",
        "Repita novamente, com o nível de otimização 3:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "4109d0e2-df37-4850-8409-6b860c48595c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/4109d0e2-df37-4850-8409-6b860c48595c-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=3, backend=backend, seed_transpiler=12345\n",
        ")\n",
        "qc_t3_exact = pass_manager.run(qc)\n",
        "qc_t3_exact.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c9cf6dcf-733f-494f-a571-43d47d3908ce",
      "metadata": {},
      "source": [
        "Agora, há apenas três portões ECR. Obtivemos esse resultado porque, no nível de otimização 3, o Qiskit tenta sintetizar novamente blocos de portas de dois qubits, e qualquer porta de dois qubits pode ser implementada usando no máximo três portas ECR. Podemos obter ainda menos portas ECR se definirmos `approximation_degree` como um valor menor que 1, permitindo que o transpilador faça aproximações que podem introduzir algum erro na decomposição da porta (consulte [Parâmetros comumente usados para transpilação](common-parameters#approximation-degree) ):\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "bf239116-b8bb-42aa-a27a-89206d9e108a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/set-optimization/extracted-outputs/bf239116-b8bb-42aa-a27a-89206d9e108a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=3,\n",
        "    approximation_degree=0.99,\n",
        "    backend=backend,\n",
        "    seed_transpiler=12345,\n",
        ")\n",
        "qc_t3_approx = pass_manager.run(qc)\n",
        "qc_t3_approx.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "247f60a9-b0ad-4e83-85ea-008dc808267f",
      "metadata": {},
      "source": [
        "Esse circuito tem apenas duas portas ECR, mas é um circuito aproximado. Para entender como seu efeito difere do circuito exato, podemos calcular a fidelidade entre o operador unitário que esse circuito implementa e o unitário exato. Antes de realizar o cálculo, primeiro reduzimos o circuito transpilado, que contém 127 qubits, para um circuito que contém apenas os qubits ativos, que são dois.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "56988ecd-8a78-42ca-90eb-fc956674c64d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Synthesis fidelity\n",
            "Exact: 1.000+0.000j\n",
            "Approximate: 0.992+0.000j\n"
          ]
        }
      ],
      "source": [
        "import numpy as np\n",
        "\n",
        "\n",
        "def trace_to_fidelity_2q(trace: float) -> float:\n",
        "    return (4.0 + trace * trace.conjugate()) / 20.0\n",
        "\n",
        "\n",
        "# Reduce circuits down to 2 qubits so they are easy to simulate\n",
        "qc_t3_exact_small = QuantumCircuit.from_instructions(qc_t3_exact)\n",
        "qc_t3_approx_small = QuantumCircuit.from_instructions(qc_t3_approx)\n",
        "\n",
        "# Compute the fidelity\n",
        "exact_fid = trace_to_fidelity_2q(\n",
        "    np.trace(np.dot(Operator(qc_t3_exact_small).adjoint().data, UU))\n",
        ")\n",
        "approx_fid = trace_to_fidelity_2q(\n",
        "    np.trace(np.dot(Operator(qc_t3_approx_small).adjoint().data, UU))\n",
        ")\n",
        "print(\n",
        "    f\"Synthesis fidelity\\nExact: {exact_fid:.3f}\\nApproximate: {approx_fid:.3f}\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "382f6ffc-1d17-4c4b-8ea1-2f828c705793",
      "metadata": {
        "jp-MarkdownHeadingCollapsed": true
      },
      "source": [
        "Ajustar o nível de otimização também pode alterar outros aspectos do circuito, não apenas o número de portas ECR. Para ver exemplos de como a definição do nível de otimização altera o layout, consulte [Representação de computadores quânticos](/docs/guides/represent-quantum-computers).\n",
        "\n",
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * Para saber mais sobre a função `generate_preset_passmanager` , comece pelo tópico [Definições padrão de transpilação e opções de configuração](defaults-and-configuration-options).\n",
        "  * Continue aprendendo sobre transpilação com o tópico [Transpiler stages](transpiler-stages).\n",
        "  * Experimente o guia [Comparar configurações do transpiler](/docs/guides/circuit-transpilation-settings).\n",
        "  * Experimente o tutorial [Construir códigos de repetição](/docs/tutorials/repetition-codes).\n",
        "  * Consulte [a documentação da API Transpile](/docs/api/qiskit/transpiler).\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": 5
}