{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b793601b-95bc-4d36-adfc-c9fc34ce45cd",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Etapas do transpiler\"\n",
        "description: \"As etapas padrão do pipeline de transpilagem do circuito quântico no Qiskit.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore fontsize */}\n",
        "\n",
        "<span id=\"transpiler-stages\" />\n",
        "\n",
        "# Etapas do transpiler\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4a38c84a-eed2-4fa4-9823-3d544e572398",
      "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": "9f2ecc4b-e6a3-418c-8a65-a9f3ac98c3dc",
      "metadata": {},
      "source": [
        "Esta página descreve os estágios do pipeline de transpilação pré-construído no Qiskit SDK. Há seis estágios:\n",
        "\n",
        "1. `init`\n",
        "2. `layout`\n",
        "3. `routing`\n",
        "4. `translation`\n",
        "5. `optimization`\n",
        "6. `scheduling`\n",
        "\n",
        "A função [`generate_preset_pass_manager`](/docs/api/qiskit/qiskit.transpiler.generate_preset_pass_manager#qiskit.transpiler.generate_preset_pass_manager) cria um [gerenciador de passagens em estágios](/docs/api/qiskit/qiskit.transpiler.StagedPassManager) predefinido composto por esses estágios. As passagens específicas que compõem cada estágio dependem dos argumentos passados para `generate_preset_pass_manager`. O `optimization_level` é um argumento posicional que deve ser especificado; é um número inteiro que pode ser 0, 1, 2 ou 3. Valores mais altos indicam uma otimização mais pesada, porém mais cara (consulte [Padrões de transpilação e opções de configuração](defaults-and-configuration-options) ).\n",
        "\n",
        "A maneira recomendada de transpilar um circuito é criar um gerenciador de passagens predefinido e, em seguida, executar esse gerenciador de passagens no circuito, conforme descrito em [Transpilar com gerenciadores de passagens](transpile-with-pass-managers). No entanto, uma alternativa mais simples, mas menos personalizável, é usar a função [`transpile`](/docs/api/qiskit/compiler#qiskit.compiler.transpile) função. Essa função aceita o circuito diretamente como um argumento. Assim como em `generate_preset_pass_manager`, as passagens específicas do transpilador usadas dependem dos argumentos, como `optimization_level`, passados para `transpile`. De fato, internamente, a função `transpile` chama `generate_preset_pass_manager` para criar um gerenciador de passagens em etapas predefinido e o executa no circuito.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "18140654-10ff-40c5-ab75-4d19b8a7f5dd",
      "metadata": {},
      "source": [
        "<span id=\"init-stage\" />\n",
        "\n",
        "## Fase inicial\n",
        "\n",
        "Esse primeiro estágio faz muito pouco por padrão e é útil principalmente se você quiser incluir suas próprias otimizações iniciais.  Como a maioria dos algoritmos de layout e roteamento só foi projetada para trabalhar com portas de um e dois qubits, esse estágio também é usado para traduzir todas as portas que operam em mais de dois qubits em portas que operam somente em um ou dois qubits.\n",
        "\n",
        "Para obter mais informações sobre a implementação de suas próprias otimizações iniciais para esse estágio, consulte a seção sobre plug-ins e personalização de gerenciadores de passes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "506a831f-b317-4335-8124-20ed994292cd",
      "metadata": {},
      "source": [
        "<span id=\"layout-stage\" />\n",
        "\n",
        "## Fase de layout\n",
        "\n",
        "A próxima etapa envolve a configuração ou a conectividade do backend para o qual o circuito será enviado.  Em geral, os circuitos quânticos são entidades abstratas cujos qubits são representações “virtuais” ou “lógicas” dos qubits reais utilizados nos cálculos.  Para executar uma sequência de portas, é necessário um mapeamento um-para-um entre os qubits “virtuais” e os qubits “físicos” em um dispositivo quântico real.  Esse mapeamento é armazenado como um `Layout` objeto e faz parte das restrições definidas na [arquitetura do conjunto de instruções (ISA)](/docs/guides/transpile#instruction-set-architecture) de um backend.\n",
        "\n",
        "![Esta imagem ilustra o mapeamento dos qubits da representação esquemática para um diagrama que mostra como os qubits estão conectados na QPU. Mapeamento](https://quantum.cloud.ibm.com/docs/images/guides/transpiler-stages/layout-mapping.svg \" de qubits\")\n",
        "\n",
        "A escolha do mapeamento é extremamente importante para minimizar o número de operações SWAP necessárias para mapear o circuito de entrada na topologia do dispositivo e garantir que os qubits mais bem calibrados sejam usados.  Devido à importância dessa etapa, os gerentes de passes predefinidos tentam alguns métodos diferentes para encontrar o melhor layout.  Normalmente, isso envolve duas etapas: primeiro, tentar encontrar um layout \"perfeito\" (um layout que não exija nenhuma operação SWAP) e, em seguida, uma passagem heurística que tenta encontrar o melhor layout a ser usado se não for possível encontrar um layout perfeito.  Há dois sites `Passes` normalmente usados para essa primeira etapa:\n",
        "\n",
        "* `TrivialLayout`: Mapeia ingenuamente cada qubit virtual para o mesmo qubit físico numerado no dispositivo (ou seja, \\[`0`,`1`,`1`,`3`] -> \\[`0`,`1`,`1`,`3`] ). Este é um comportamento histórico usado apenas em `optimzation_level=1` para tentar encontrar um layout perfeito.  Em caso de falha, `VF2Layout` é a próxima tentativa.\n",
        "* `VF2Layout`: Este é um `AnalysisPass` que seleciona um layout ideal tratando esse estágio como um problema de isomorfismo de subgrafo, resolvido pelo algoritmo VF2++.  Se mais de um layout for encontrado, uma heurística de pontuação será executada para selecionar o mapeamento com o menor erro médio.\n",
        "\n",
        "Em seguida, para o estágio heurístico, duas passagens são usadas por padrão:\n",
        "\n",
        "* `DenseLayout`: Encontra o subgrafo do dispositivo com a maior conectividade e que tem o mesmo número de qubits que o circuito (usado para o nível de otimização 1 se houver operações de fluxo de controle (como IfElseOp ) presentes no circuito).\n",
        "* `SabreLayout`: Esta passagem seleciona um layout a partir de um layout aleatório inicial e executando repetidamente o `SabreSwap` algoritmo.  Esta passagem só é usada nos níveis de otimização 1, 2 e 3 se um layout perfeito não for encontrado através da `VF2Layout` passagem.  Para obter mais detalhes sobre este algoritmo, consulte o artigo “ [arXiv:1809.02573](https://arxiv.org/abs/1809.02573) ” (Algoritmo de classificação de dados de vídeo baseado em características de movimento).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cf772b6c-2578-455d-8014-9a7de2f9db19",
      "metadata": {},
      "source": [
        "<span id=\"routing-stage\" />\n",
        "\n",
        "## Etapa de roteamento\n",
        "\n",
        "Para implementar uma porta de dois qubits entre qubits que não estejam diretamente conectados em um dispositivo quântico, uma ou mais portas SWAP devem ser inseridas no circuito para mover os estados dos qubits até que fiquem adjacentes no mapa de portas do dispositivo.  Cada porta SWAP representa uma operação cara e ruidosa a ser executada.  Portanto, encontrar o número mínimo de portas SWAP necessárias para mapear um circuito em um determinado dispositivo é uma etapa importante no processo de transpilação.  Para fins de eficiência, esse estágio é normalmente computado junto com o estágio de Layout por padrão, mas eles são logicamente distintos um do outro.  O estágio de *Layout* seleciona os qubits de hardware a serem usados, enquanto o estágio *de Roteamento* insere a quantidade adequada de portas SWAP para executar os circuitos usando o layout selecionado.\n",
        "\n",
        "No entanto, é difícil encontrar o mapeamento SWAP ideal.  De fato, é um problema NP difícil e, portanto, proibitivamente caro de calcular para todos os dispositivos quânticos e circuitos de entrada, exceto os menores.  Para contornar esse problema, o Qiskit usa um algoritmo heurístico estocástico chamado `SabreSwap` para calcular um mapeamento SWAP bom, mas não necessariamente ideal. O uso de um método estocástico significa que não há garantia de que os circuitos gerados sejam os mesmos em execuções repetidas.  De fato, a execução do mesmo circuito repetidamente resulta em uma distribuição de profundidades de circuito e contagens de portas na saída.  É por esse motivo que muitos usuários optam por executar a função de roteamento (ou todo o site `StagedPassManager`) várias vezes e selecionar os circuitos de menor profundidade na distribuição de saídas.\n",
        "\n",
        "Por exemplo, vamos considerar um circuito GHZ de 15 qubits executado 100 vezes, usando um circuito \"ruim\" (desconectado) `initial_layout`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "62479697-cef1-4a89-ac2a-20051dd294f4",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Text(0, 0.5, 'Counts')"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/62479697-cef1-4a89-ac2a-20051dd294f4-1.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.providers.fake_provider import GenericBackendV2\n",
        "\n",
        "backend = GenericBackendV2(15)\n",
        "\n",
        "\n",
        "ghz = QuantumCircuit(15)\n",
        "ghz.h(0)\n",
        "ghz.cx(0, range(1, 15))\n",
        "\n",
        "depths = []\n",
        "for seed in range(100):\n",
        "    pass_manager = generate_preset_pass_manager(\n",
        "        optimization_level=1,\n",
        "        backend=backend,\n",
        "        layout_method=\"trivial\",  # Fixed layout mapped in circuit order\n",
        "        seed_transpiler=seed,  # For reproducible results\n",
        "    )\n",
        "    depths.append(pass_manager.run(ghz).depth())\n",
        "\n",
        "plt.figure(figsize=(8, 6))\n",
        "plt.hist(depths, align=\"left\", color=\"#AC557C\")\n",
        "plt.xlabel(\"Depth\", fontsize=14)\n",
        "plt.ylabel(\"Counts\", fontsize=14)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ff31f484-a816-4479-8827-d56641501319",
      "metadata": {},
      "source": [
        "Essa ampla distribuição demonstra como é difícil para o mapeador SWAP calcular o melhor mapeamento.  Para ter uma ideia, vamos examinar o circuito que está sendo executado e os qubits que foram escolhidos no hardware.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "ab89c4ea-06c4-4320-b493-feb691b3570d",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/ab89c4ea-06c4-4320-b493-feb691b3570d-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ghz.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "f6a3a92a-8656-4518-ba2c-c3b0b038f507",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/f6a3a92a-8656-4518-ba2c-c3b0b038f507-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_circuit_layout\n",
        "\n",
        "# Plot the hardware graph and indicate which hardware qubits were chosen to run the circuit\n",
        "transpiled_circ = pass_manager.run(ghz)\n",
        "plot_circuit_layout(transpiled_circ, backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ec2818a-8087-42ba-990d-b3c1258dbf35",
      "metadata": {},
      "source": [
        "Como você pode ver, esse circuito precisa executar uma porta de dois qubits entre os qubits 0 e 14, que estão muito distantes no gráfico de conectividade.  Portanto, a execução desse circuito requer a inserção de portas SWAP para executar todas as portas de dois qubits usando a passagem `SabreSwap` .\n",
        "\n",
        "Observe também que o algoritmo `SabreSwap` é diferente do método `SabreLayout` maior do estágio anterior.  Por padrão, o site `SabreLayout` executa o layout e o roteamento e retorna o circuito transformado.  Isso é feito por alguns motivos técnicos específicos especificados na [página de referência da API](../api/qiskit/qiskit.transpiler.passes.SabreLayout) do passe.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "650f978b-d992-4d67-a356-5bf73902f212",
      "metadata": {},
      "source": [
        "<span id=\"translation-stage\" />\n",
        "\n",
        "## Fase de tradução\n",
        "\n",
        "Ao escrever um circuito quântico, você tem liberdade para usar qualquer porta quântica (operação unitária) que desejar, juntamente com um conjunto de operações que não sejam portas, como medição de qubits ou instruções de reinicialização.  No entanto, a maioria dos dispositivos quânticos suporta nativamente apenas um número limitado de operações de portas quânticas e de operações que não envolvem portas.  Essas portas nativas fazem parte da definição [da ISA](/docs/guides/transpile#instruction-set-architecture) de um destino, e esta etapa da pré-configuração `PassManagers` traduz (ou *desdobra* ) as portas especificadas em um circuito para as portas da base nativa de um backend especificado.  Este é um passo importante, pois permite que o circuito seja executado pelo backend, mas geralmente leva a um aumento na profundidade e no número de portas lógicas.\n",
        "\n",
        "É especialmente importante destacar dois casos especiais que ajudam a ilustrar o que esse estágio faz.\n",
        "\n",
        "1. Se uma porta SWAP não for uma porta nativa para o backend de destino, serão necessárias três portas CNOT:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "d4d1f65a-3336-4d70-9189-65ba010f2366",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "native gates:['cx', 'delay', 'id', 'measure', 'reset', 'rz', 'sx', 'x']\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/d4d1f65a-3336-4d70-9189-65ba010f2366-1.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "print(\"native gates:\" + str(sorted(backend.operation_names)))\n",
        "qc = QuantumCircuit(2)\n",
        "qc.swap(0, 1)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "56347603-8766-4165-af18-1f6fe4c61d4f",
      "metadata": {},
      "source": [
        "Como um produto de três portas CNOT, um SWAP é uma operação cara para ser executada em dispositivos quânticos com ruído.  No entanto, essas operações geralmente são necessárias para incorporar um circuito nas conectividades de porta limitadas de muitos dispositivos.  Assim, minimizar o número de portas SWAP em um circuito é um objetivo primordial no processo de transpilação.\n",
        "\n",
        "2. Um Toffoli, ou porta controlada-controlada-não controlada (`ccx`), é uma porta de três qubits.  Como nosso conjunto de portas de base inclui apenas portas de um e dois qubits, essa operação deve ser decomposta.  No entanto, ele é bastante caro:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "4552b367-75e9-4faa-a59d-8317e25ac145",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/4552b367-75e9-4faa-a59d-8317e25ac145-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(3)\n",
        "qc.ccx(0, 1, 2)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "70af8d85-84c2-43cf-96fa-37bcf68f89c9",
      "metadata": {},
      "source": [
        "Para cada porta Toffoli em um circuito quântico, o hardware pode executar até seis portas CNOT e um punhado de portas de um único qubit.  Esse exemplo demonstra que qualquer algoritmo que faça uso de várias portas Toffoli terminará como um circuito com grande profundidade e, portanto, será consideravelmente afetado pelo ruído.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8b396526-b14b-48a3-93ed-37e590b06caf",
      "metadata": {},
      "source": [
        "<span id=\"optimization-stage\" />\n",
        "\n",
        "## Fase de otimização\n",
        "\n",
        "Esse estágio se concentra na decomposição dos circuitos quânticos no conjunto de portas de base do dispositivo de destino e deve lutar contra o aumento da profundidade dos estágios de layout e roteamento.  Felizmente, há muitas rotinas para otimizar os circuitos combinando ou eliminando portas.  Em alguns casos, esses métodos são tão eficazes que os circuitos de saída têm uma profundidade menor do que as entradas, mesmo após o layout e o roteamento para a topologia do hardware.  Em outros casos, não é possível fazer muita coisa, e o cálculo pode ser difícil de ser realizado em dispositivos com ruído.  É nesse estágio que os vários níveis de otimização começam a se diferenciar.\n",
        "\n",
        "* Para `optimization_level=1`, esse estágio prepara [`Optimize1qGatesDecomposition`](../api/qiskit/qiskit.transpiler.passes.Optimize1qGatesDecomposition) e [`CXCancellation`](/docs/api/qiskit/1.4/qiskit.transpiler.passes.CXCancellation)que combinam cadeias de portas de um único qubit e cancelam quaisquer portas CNOT consecutivas.\n",
        "* Para `optimization_level=2`, esse estágio usa a passagem [`CommutativeCancellation`](../api/qiskit/qiskit.transpiler.passes.CommutativeCancellation) em vez de `CXCancellation`, que remove portas redundantes ao explorar as relações de comutação.\n",
        "* Para `optimization_level=3`, esse estágio prepara os seguintes passes:\n",
        "  * [`Collect2qBlocks`](../api/qiskit/qiskit.transpiler.passes.Collect2qBlocks)\n",
        "  * [`ConsolidateBlocks`](../api/qiskit/qiskit.transpiler.passes.ConsolidateBlocks)\n",
        "  * [`UnitarySynthesis`](../api/qiskit/qiskit.transpiler.passes.UnitarySynthesis)\n",
        "  * [`Optimize1qGateDecomposition`](../api/qiskit/qiskit.transpiler.passes.Optimize1qGatesDecomposition)\n",
        "  * [`CommutativeCancellation`](../api/qiskit/qiskit.transpiler.passes.CommutativeCancellation)\n",
        "\n",
        "Além disso, esse estágio também executa algumas verificações finais para garantir que todas as instruções no circuito sejam compostas pelas portas de base disponíveis no backend de destino.\n",
        "\n",
        "O exemplo abaixo, usando um estado GHZ, demonstra os efeitos de diferentes configurações de nível de otimização na profundidade do circuito e na contagem de portas.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  A saída da transpilação varia devido ao mapeador SWAP estocástico. Portanto, os números abaixo provavelmente mudarão cada vez que você executar o código.\n",
        "</Admonition>\n",
        "\n",
        "![estado GHZ de 15 qubits](https://quantum.cloud.ibm.com/docs/images/guides/transpiler-stages/transpiler-11.avif \"Estado GHZ de 15 qubits antes da transpilação\")\n",
        "\n",
        "O código a seguir constrói um estado GHZ de 15 qubits e compara o `optimization_levels` da transpilação em termos de profundidade do circuito resultante, contagem de portas e contagem de portas de vários qubits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "2700405a-f559-45d3-99a9-5b4447621743",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/2700405a-f559-45d3-99a9-5b4447621743-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "ghz = QuantumCircuit(15)\n",
        "ghz.h(0)\n",
        "ghz.cx(0, range(1, 15))\n",
        "\n",
        "depths = []\n",
        "gate_counts = []\n",
        "multiqubit_gate_counts = []\n",
        "levels = [str(x) for x in range(4)]\n",
        "for level in range(4):\n",
        "    pass_manager = generate_preset_pass_manager(\n",
        "        optimization_level=level,\n",
        "        backend=backend,\n",
        "        seed_transpiler=1234,\n",
        "    )\n",
        "    circ = pass_manager.run(ghz)\n",
        "    depths.append(circ.depth())\n",
        "    gate_counts.append(sum(circ.count_ops().values()))\n",
        "    multiqubit_gate_counts.append(circ.count_ops()[\"cx\"])\n",
        "\n",
        "fig, (ax1, ax2) = plt.subplots(2, 1)\n",
        "ax1.bar(levels, depths, label=\"Depth\")\n",
        "ax1.set_xlabel(\"Optimization Level\")\n",
        "ax1.set_ylabel(\"Depth\")\n",
        "ax1.set_title(\"Output Circuit Depth\")\n",
        "ax2.bar(levels, gate_counts, label=\"Number of Circuit Operations\")\n",
        "ax2.bar(levels, multiqubit_gate_counts, label=\"Number of CX gates\")\n",
        "ax2.set_xlabel(\"Optimization Level\")\n",
        "ax2.set_ylabel(\"Number of gates\")\n",
        "ax2.legend()\n",
        "ax2.set_title(\"Number of output circuit gates\")\n",
        "fig.tight_layout()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c870a48f-2bc4-4150-83ff-857a06e42ffb",
      "metadata": {},
      "source": [
        "<span id=\"scheduling\" />\n",
        "\n",
        "## Planejamento\n",
        "\n",
        "Esse último estágio só é executado se for explicitamente solicitado (semelhante ao estágio Init) e não é executado por padrão (embora um método possa ser especificado definindo o argumento `scheduling_method` ao chamar `generate_preset_pass_manager`).  O estágio de programação é normalmente usado depois que o circuito foi traduzido para a base de destino, mapeado para o dispositivo e otimizado.  Essas passagens se concentram na contabilização de todo o tempo ocioso em um circuito.  Em um nível mais alto, a passagem de agendamento pode ser considerada como a inserção explícita de instruções de atraso para levar em conta o tempo ocioso entre as execuções do portão e para inspecionar por quanto tempo o circuito será executado no backend.\n",
        "\n",
        "Aqui está\n",
        "um exemplo:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "ae2d9390-5c26-46f3-9418-a684ba8a406a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/ae2d9390-5c26-46f3-9418-a684ba8a406a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ghz = QuantumCircuit(5)\n",
        "ghz.h(0)\n",
        "ghz.cx(0, range(1, 5))\n",
        "\n",
        "\n",
        "# Use fake backend\n",
        "backend = GenericBackendV2(5)\n",
        "\n",
        "# Run with optimization level 3 and 'asap' scheduling pass\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=3,\n",
        "    backend=backend,\n",
        "    scheduling_method=\"asap\",\n",
        "    seed_transpiler=1234,\n",
        ")\n",
        "\n",
        "\n",
        "circ = pass_manager.run(ghz)\n",
        "circ.draw(output=\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "442cb546-3463-4044-8406-1c68d371a2c9",
      "metadata": {},
      "source": [
        "![Circuito com instruções de atraso](https://quantum.cloud.ibm.com/docs/images/guides/transpiler-stages/transpiler-16.avif)\n",
        "\n",
        "O transpilador inseriu `Delay` instruções para contabilizar o tempo ocioso em cada qubit. Para ter uma ideia melhor do tempo do circuito, também podemos examiná-lo com a função `timeline.draw()` :\n",
        "\n",
        "![timeline.draw (): visualização do mesmo circuito](https://quantum.cloud.ibm.com/docs/images/guides/transpiler-stages/transpiler-17.svg)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0b214bba-1f0e-49fc-be7e-29ccb57fff8a",
      "metadata": {},
      "source": [
        "O agendamento de um circuito envolve duas partes: análise e mapeamento de restrições, seguido de uma passagem de preenchimento.  A primeira parte requer a execução de uma passagem de análise de programação (por padrão, é [`ALAPSchedulingAnalysis`](../api/qiskit/qiskit.transpiler.passes.ALAPScheduleAnalysis)), que analisa o circuito e registra a hora de início de cada instrução no circuito em um cronograma.  Uma vez que o circuito tenha um cronograma inicial, passes adicionais podem ser executados para levar em conta quaisquer restrições de tempo no backend de destino.  Por fim, um passe de preenchimento, como [`PadDelay`](../api/qiskit/qiskit.transpiler.passes.PadDelay) ou [`PadDynamicalDecoupling`](../api/qiskit/qiskit.transpiler.passes.PadDynamicalDecoupling) pode ser executada.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "62c19c54-6dcc-4025-b800-7a74be69808d",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * Para saber como usar 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 with pass managers](transpile-with-pass-managers).\n",
        "  * Experimente o guia [Comparar configurações do transpiler](/docs/guides/circuit-transpilation-settings).\n",
        "  * Consulte [a documentação da API Transpile](https://docs.quantum-computing.ibm.com/api/qiskit/transpiler).\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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}