{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "a1b2c3d4",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Métodos de compilação para circuitos de simulação hamiltoniana\"\n",
        "description: \"Compare os métodos de compilação SABRE, o transpiler baseado em IA e o Rustiq em circuitos de simulação hamiltonianos do Hamlib.\"\n",
        "---\n",
        "\n",
        "<span id=\"compilation-methods-for-hamiltonian-simulation-circuits\" />\n",
        "\n",
        "# Métodos de compilação para circuitos de simulação hamiltoniana\n",
        "\n",
        "*Estimativa de tempo de execução: menos de 1 minuto em um processador Heron do IBM (NOTA: Trata-se apenas de uma estimativa.) (O tempo de execução pode variar.)*\n",
        "\n",
        "{/* cspell:ignore Rustiq, nshuffles, edgecolors, edgecolor, Hamlib, Benchpress, Brugiere, Goubault, Martiel, Dubal, Lishman, Ivrii, fontweight, fontsize, textprops, wedgeprops, startangle, autopct, Hellinger, iloc, ylabel, frameon, ylims, CMHSC */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b1c2d3e4",
      "metadata": {},
      "source": [
        "<span id=\"learning-outcomes\" />\n",
        "\n",
        "## Resultados do aprendizado\n",
        "\n",
        "Ao concluir este tutorial, você compreenderá:\n",
        "\n",
        "* Como usar o transpiler do Qiskit com o SABRE para otimização de layout e roteamento\n",
        "* Como aproveitar o transpiler baseado em IA para a otimização avançada de circuitos\n",
        "* Como usar o plug-in Rustiq para sintetizar `PauliEvolutionGate` operações em circuitos de simulação hamiltoniana\n",
        "* Como avaliar e comparar métodos de compilação usando a profundidade de dois qubits, o número total de portas e o tempo de execução\n",
        "\n",
        "<span id=\"prerequisites\" />\n",
        "\n",
        "## Pré-requisitos\n",
        "\n",
        "Sugerimos que você esteja familiarizado com os seguintes tópicos antes de seguir com este tutorial:\n",
        "\n",
        "* [Conceitos de transpilação](/docs/guides/transpile)\n",
        "* [Etapas do transpiler](/docs/guides/transpiler-stages)\n",
        "* [Transpile com gerenciadores de etapas](/docs/guides/transpile-with-pass-managers)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c1d2e3f4",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## Segundo plano\n",
        "\n",
        "A compilação de circuitos quânticos transforma um algoritmo quântico de alto nível em um circuito físico que respeita as restrições do hardware de destino. Uma compilação eficaz pode reduzir significativamente a profundidade do circuito e o número de portas, fatores que afetam diretamente a qualidade dos resultados em dispositivos quânticos no curto prazo.\n",
        "\n",
        "Este tutorial compara o desempenho de três métodos de compilação em circuitos de simulação hamiltoniana criados com `PauliEvolutionGate`. Esses circuitos modelam interações entre pares de qubits (como os termos $ZZ$, $XX$ e $YY$ ) e são comuns na química quântica, na física da matéria condensada e na ciência dos materiais.\n",
        "\n",
        "Os circuitos de referência fazem parte da coleção [Hamlib](https://github.com/SRI-International/QC-App-Oriented-Benchmarks/tree/master/qedcbench/hamlib#hamlib-simulation---benchmark-program), acessível por meio do repositório [Benchpress](https://github.com/Qiskit/benchpress). O Hamlib oferece um conjunto padronizado de hamiltonianos representativos, possibilitando a comparação de estratégias de compilação em cargas de trabalho de simulação realistas.\n",
        "\n",
        "<span id=\"compilation-methods-overview\" />\n",
        "\n",
        "### Visão geral dos métodos de compilação\n",
        "\n",
        "<span id=\"qiskit-transpiler-with-sabre\" />\n",
        "\n",
        "#### Transpilador do Qiskit com o SABRE\n",
        "\n",
        "O transpiler do Qiskit utiliza o algoritmo SABRE ( BidiREctional, com base no SWAP, para busca heurística) para otimizar o layout e o roteamento dos circuitos. O SABRE tem como objetivo minimizar os portões SWAP e seu impacto na profundidade do circuito, respeitando as restrições de conectividade do hardware. É um método de uso geral que oferece um bom equilíbrio entre desempenho e tempo de compilação. Para mais detalhes, consulte [\\[1\\]](https://arxiv.org/abs/2409.08368). As vantagens e a exploração dos parâmetros do SABRE são abordadas em profundidade em um [tutorial](/docs/tutorials/transpilation-optimizations-with-sabre) separado.\n",
        "\n",
        "<span id=\"ai-powered-transpiler\" />\n",
        "\n",
        "#### Transpilador baseado em IA\n",
        "\n",
        "O transpiler baseado em IA utiliza aprendizado de máquina para prever estratégias ideais de transpilagem, analisando padrões na estrutura dos circuitos e restrições de hardware. Ele também pode aplicar o `AIPauliNetworkSynthesis` pass, que tem como alvo os circuitos da rede Pauli por meio de uma abordagem de síntese baseada em aprendizado por reforço. Para mais informações, consulte [\\[2\\]](https://arxiv.org/abs/2405.13196) e [\\[3\\]](https://arxiv.org/abs/2503.14448).\n",
        "\n",
        "<span id=\"rustiq-plugin\" />\n",
        "\n",
        "#### Plugin Rustiq\n",
        "\n",
        "O plug-in Rustiq oferece técnicas avançadas de síntese específicas para `PauliEvolutionGate` operações que representam as rotações de Pauli comumente utilizadas na dinâmica de Trotter. Ele foi projetado para produzir decomposições de circuitos de baixa profundidade para cargas de trabalho de simulação hamiltoniana. Para mais detalhes, consulte [\\[4\\]](https://arxiv.org/abs/2404.03280).\n",
        "\n",
        "<span id=\"key-metrics\" />\n",
        "\n",
        "### Métricas principais\n",
        "\n",
        "Comparamos os três métodos com base nas seguintes métricas:\n",
        "\n",
        "* **Profundidade de dois qubits** : A profundidade do circuito, considerando apenas as portas de dois qubits. Isso costuma ser o gargalo para a fidelidade em hardware real.\n",
        "* **Tamanho do circuito (número total de portas)** : O número total de portas no circuito transpilado.\n",
        "* **Tempo de execução** : O tempo real gasto na transpilagem.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d1e2f3a4",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## Requisitos\n",
        "\n",
        "Antes de iniciar este tutorial, verifique se você tem os seguintes itens instalados:\n",
        "\n",
        "* Qiskit SDK v2.0 ou versão posterior, com suporte [à visualização](/docs/api/qiskit/visualization)\n",
        "* Qiskit Runtime v0.22 ou posterior (`pip install qiskit-ibm-runtime`)\n",
        "* Qiskit Aer (`pip install qiskit-aer`)\n",
        "* Qiskit IBM Transpiler (`pip install qiskit-ibm-transpiler`)\n",
        "* Modo local do Qiskit AI Transpiler (`pip install qiskit_ibm_ai_local_transpiler`)\n",
        "* Networkx (`pip install networkx`)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e1f2a3b4",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Instalação\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "f1a2b3c4",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit import QuantumCircuit\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2\n",
        "from qiskit.circuit.library import PauliEvolutionGate\n",
        "from qiskit_ibm_transpiler import generate_ai_pass_manager\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit_aer.noise import NoiseModel, depolarizing_error\n",
        "from collections import Counter\n",
        "from statistics import mean, stdev\n",
        "from scipy.sparse import SparseEfficiencyWarning\n",
        "import time\n",
        "import warnings\n",
        "import matplotlib.pyplot as plt\n",
        "import matplotlib.ticker as ticker\n",
        "import numpy as np\n",
        "import json\n",
        "import requests\n",
        "import logging\n",
        "\n",
        "# Suppress noisy loggers and warnings\n",
        "logging.getLogger(\n",
        "    \"qiskit_ibm_transpiler.wrappers.ai_local_synthesis\"\n",
        ").setLevel(logging.ERROR)\n",
        "warnings.filterwarnings(\"ignore\", category=FutureWarning)\n",
        "warnings.filterwarnings(\"ignore\", category=SparseEfficiencyWarning)\n",
        "\n",
        "seed = 42  # Seed for reproducibility"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a2b3c4d5",
      "metadata": {},
      "source": [
        "<span id=\"connect-to-a-backend\" />\n",
        "\n",
        "### Conectar-se a um backend\n",
        "\n",
        "Selecione um backend que será utilizado tanto para os exemplos em pequena escala quanto para os de grande escala. O backend determina o mapa de acoplamento e os portões de base aos quais o transpiler se destina.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b2c3d4e5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Using backend: ibm_pittsburgh\n"
          ]
        }
      ],
      "source": [
        "# QiskitRuntimeService.save_account(channel=\"ibm_quantum_platform\",\n",
        "# token=\"<YOUR-API-KEY>\", overwrite=True, set_as_default=True)\n",
        "service = QiskitRuntimeService(channel=\"ibm_quantum_platform\")\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "print(f\"Using backend: {backend.name}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c2d3e4f5",
      "metadata": {},
      "source": [
        "<span id=\"define-pass-managers\" />\n",
        "\n",
        "### Definir gerenciadores de passes\n",
        "\n",
        "Configure os três métodos de compilação.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "d2e3f4a5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# SABRE pass manager (Qiskit default at optimization level 3)\n",
        "pm_sabre = generate_preset_pass_manager(\n",
        "    optimization_level=3, backend=backend, seed_transpiler=seed\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "e2f3a4b5",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "e14d6bb64d3e4a399a645a5437a4a1cb",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Fetching 127 files:   0%|          | 0/127 [00:00<?, ?it/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# AI transpiler pass manager (local mode)\n",
        "pm_ai = generate_ai_pass_manager(\n",
        "    backend=backend, optimization_level=3, ai_optimization_level=3\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "f2a3b4c5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Rustiq pass manager for PauliEvolutionGate synthesis\n",
        "hls_config = HLSConfig(\n",
        "    PauliEvolution=[\n",
        "        (\n",
        "            \"rustiq\",\n",
        "            {\n",
        "                \"nshuffles\": 400,\n",
        "                \"upto_phase\": True,\n",
        "                \"fix_clifford\": True,\n",
        "                \"preserve_order\": False,\n",
        "                \"metric\": \"depth\",\n",
        "            },\n",
        "        )\n",
        "    ]\n",
        ")\n",
        "pm_rustiq = generate_preset_pass_manager(\n",
        "    optimization_level=3,\n",
        "    backend=backend,\n",
        "    hls_config=hls_config,\n",
        "    seed_transpiler=seed,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a3b4c5d6",
      "metadata": {},
      "source": [
        "<span id=\"define-helper-functions\" />\n",
        "\n",
        "### Definir funções auxiliares\n",
        "\n",
        "A função a seguir compila uma lista de circuitos utilizando um gerenciador de passagens determinado e registra as principais métricas (profundidade de dois qubits, tamanho do circuito e tempo de execução) para cada circuito.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "b3c4d5e6",
      "metadata": {},
      "outputs": [],
      "source": [
        "def capture_transpilation_metrics(\n",
        "    results, pass_manager, circuits, method_name\n",
        "):\n",
        "    \"\"\"\n",
        "    Transpile circuits and append one metrics record per circuit to\n",
        "    ``results``.\n",
        "\n",
        "    Args:\n",
        "        results (list): List of dicts to append the metrics records to.\n",
        "        pass_manager: Pass manager used for transpilation.\n",
        "        circuits (list): List of quantum circuits to transpile.\n",
        "        method_name (str): Name of the transpilation method.\n",
        "\n",
        "    Returns:\n",
        "        list: List of transpiled circuits.\n",
        "    \"\"\"\n",
        "    transpiled_circuits = []\n",
        "\n",
        "    for i, qc in enumerate(circuits):\n",
        "        start_time = time.time()\n",
        "        transpiled_qc = pass_manager.run(qc)\n",
        "        end_time = time.time()\n",
        "\n",
        "        # Decompose swaps for consistency across methods\n",
        "        transpiled_qc = transpiled_qc.decompose(gates_to_decompose=[\"swap\"])\n",
        "\n",
        "        transpilation_time = end_time - start_time\n",
        "        two_qubit_depth = transpiled_qc.depth(\n",
        "            lambda x: x.operation.num_qubits == 2\n",
        "        )\n",
        "        circuit_size = transpiled_qc.size()\n",
        "\n",
        "        results.append(\n",
        "            {\n",
        "                \"method\": method_name,\n",
        "                \"qc_name\": qc.name,\n",
        "                \"qc_index\": i,\n",
        "                \"num_qubits\": qc.num_qubits,\n",
        "                \"two_qubit_depth\": two_qubit_depth,\n",
        "                \"size\": circuit_size,\n",
        "                \"runtime\": transpilation_time,\n",
        "            }\n",
        "        )\n",
        "        transpiled_circuits.append(transpiled_qc)\n",
        "        print(\n",
        "            f\"[{method_name}] Circuit {i} ({qc.name}): \"\n",
        "            f\"2Q depth={two_qubit_depth}, size={circuit_size}, \"\n",
        "            f\"time={transpilation_time:.2f}s\"\n",
        "        )\n",
        "\n",
        "    return transpiled_circuits"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "summary_table_fn",
      "metadata": {},
      "outputs": [],
      "source": [
        "def _method_order(results):\n",
        "    \"\"\"Return the distinct method names in their first-seen order.\"\"\"\n",
        "    order = []\n",
        "    for r in results:\n",
        "        if r[\"method\"] not in order:\n",
        "            order.append(r[\"method\"])\n",
        "    return order\n",
        "\n",
        "\n",
        "def print_summary_table(results):\n",
        "    \"\"\"\n",
        "    Print the mean and standard deviation of each metric per compilation\n",
        "    method, followed by the mean percent improvement relative to SABRE.\n",
        "    \"\"\"\n",
        "    metrics = [\n",
        "        (\"two_qubit_depth\", \"2Q Depth\"),\n",
        "        (\"size\", \"Gate Count\"),\n",
        "        (\"runtime\", \"Runtime (s)\"),\n",
        "    ]\n",
        "    methods = _method_order(results)\n",
        "    by_method = {m: [r for r in results if r[\"method\"] == m] for m in methods}\n",
        "    sabre_by_index = {r[\"qc_index\"]: r for r in by_method.get(\"SABRE\", [])}\n",
        "\n",
        "    col_w = 22\n",
        "    name_w = max(len(m) for m in methods)\n",
        "    header = f\"{'Method':<{name_w}}\" + \"\".join(\n",
        "        f\"  {label:>{col_w}}\" for _, label in metrics\n",
        "    )\n",
        "\n",
        "    print(\"Mean +/- std per compilation method\")\n",
        "    print(header)\n",
        "    print(\"-\" * len(header))\n",
        "    for method in methods:\n",
        "        cells = []\n",
        "        for key, _ in metrics:\n",
        "            values = [r[key] for r in by_method[method]]\n",
        "            std = stdev(values) if len(values) > 1 else 0.0\n",
        "            cells.append(f\"{mean(values):,.1f} +/- {std:,.1f}\")\n",
        "        print(\n",
        "            f\"{method:<{name_w}}\" + \"\".join(f\"  {c:>{col_w}}\" for c in cells)\n",
        "        )\n",
        "\n",
        "    others = [m for m in methods if m != \"SABRE\"]\n",
        "    if others and sabre_by_index:\n",
        "        print()\n",
        "        print(\"Mean % improvement vs SABRE (positive = better than SABRE)\")\n",
        "        print(header)\n",
        "        print(\"-\" * len(header))\n",
        "        for method in others:\n",
        "            cells = []\n",
        "            for key, _ in metrics:\n",
        "                pct = [\n",
        "                    (sabre_by_index[r[\"qc_index\"]][key] - r[key])\n",
        "                    / sabre_by_index[r[\"qc_index\"]][key]\n",
        "                    * 100\n",
        "                    for r in by_method[method]\n",
        "                    if sabre_by_index.get(r[\"qc_index\"])\n",
        "                    and sabre_by_index[r[\"qc_index\"]][key]\n",
        "                ]\n",
        "                if pct:\n",
        "                    std = stdev(pct) if len(pct) > 1 else 0.0\n",
        "                    cells.append(f\"{mean(pct):+.1f}% +/- {std:.1f}%\")\n",
        "                else:\n",
        "                    cells.append(\"n/a\")\n",
        "            print(\n",
        "                f\"{method:<{name_w}}\"\n",
        "                + \"\".join(f\"  {c:>{col_w}}\" for c in cells)\n",
        "            )"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "per_circuit_table_fn",
      "metadata": {},
      "outputs": [],
      "source": [
        "def print_per_circuit_comparison(results, num_rows=5):\n",
        "    \"\"\"\n",
        "    Print a per-metric comparison of the compilation methods for the\n",
        "    first ``num_rows`` circuits (sorted by qubit count). The best\n",
        "    (lowest) value for each metric is marked with an asterisk.\n",
        "    \"\"\"\n",
        "    metrics = [\n",
        "        (\"two_qubit_depth\", \"2Q Depth\"),\n",
        "        (\"size\", \"Gate Count\"),\n",
        "        (\"runtime\", \"Runtime (s)\"),\n",
        "    ]\n",
        "    methods = _method_order(results)\n",
        "\n",
        "    by_index = {}\n",
        "    for r in results:\n",
        "        by_index.setdefault(r[\"qc_index\"], {})[r[\"method\"]] = r\n",
        "    ordered = sorted(\n",
        "        by_index.items(),\n",
        "        key=lambda kv: (next(iter(kv[1].values()))[\"num_qubits\"], kv[0]),\n",
        "    )[:num_rows]\n",
        "\n",
        "    for key, label in metrics:\n",
        "        print(f\"{label} (first {num_rows} circuits by qubit count); * = best\")\n",
        "        header = f\"{'Idx':>3}  {'Circuit':<16} {'Q':>3}\" + \"\".join(\n",
        "            f\"{m:>9}\" for m in methods\n",
        "        )\n",
        "        print(header)\n",
        "        print(\"-\" * len(header))\n",
        "        for idx, method_map in ordered:\n",
        "            any_record = next(iter(method_map.values()))\n",
        "            present = {\n",
        "                m: method_map[m][key] for m in methods if m in method_map\n",
        "            }\n",
        "            best = min(present.values())\n",
        "            line = (\n",
        "                f\"{idx:>3}  {any_record['qc_name'][:16]:<16} \"\n",
        "                f\"{any_record['num_qubits']:>3}\"\n",
        "            )\n",
        "            for m in methods:\n",
        "                value = method_map[m][key]\n",
        "                text = f\"{value:.2f}\" if key == \"runtime\" else f\"{int(value)}\"\n",
        "                if value == best:\n",
        "                    text += \"*\"\n",
        "                line += f\"{text:>9}\"\n",
        "            print(line)\n",
        "        print()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c3d4e5f6",
      "metadata": {},
      "source": [
        "<span id=\"load-hamiltonian-circuits-from-hamlib\" />\n",
        "\n",
        "### Carregar circuitos hamiltonianos do Hamlib\n",
        "\n",
        "Carregamos um conjunto representativo de hamiltonianos do repositório Benchpress e construímos `PauliEvolutionGate` circuitos. Os circuitos que excedem o número de qubits do backend são removidos, assim como os circuitos cujo tamanho, após a decomposição, exceda 1.500 portas (para manter os tempos de transpilagem dentro de limites razoáveis).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "d3e4f5a6",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total Hamiltonian circuits loaded: 42\n",
            "Qubit range: 2 to 112\n"
          ]
        }
      ],
      "source": [
        "# Obtain the Hamiltonian JSON from the benchpress repository\n",
        "url = (\n",
        "    \"https://raw.githubusercontent.com/Qiskit/benchpress/\"\n",
        "    \"e7b29ef7be4cc0d70237b8fdc03edbd698908eff/\"\n",
        "    \"benchpress/hamiltonian/hamlib/100_representative.json\"\n",
        ")\n",
        "response = requests.get(url)\n",
        "response.raise_for_status()\n",
        "ham_records = json.loads(response.text)\n",
        "\n",
        "# Remove circuits that are too large for the backend\n",
        "ham_records = [\n",
        "    h for h in ham_records if h[\"ham_qubits\"] <= backend.num_qubits\n",
        "]\n",
        "\n",
        "# Build PauliEvolutionGate circuits\n",
        "qc_ham_list = []\n",
        "for h in ham_records:\n",
        "    terms = h[\"ham_hamlib_hamiltonian_terms\"]\n",
        "    coeff = h[\"ham_hamlib_hamiltonian_coefficients\"]\n",
        "    num_qubits = h[\"ham_qubits\"]\n",
        "    name = h[\"ham_problem\"]\n",
        "\n",
        "    evo_gate = PauliEvolutionGate(SparsePauliOp(terms, coeff))\n",
        "    qc = QuantumCircuit(num_qubits)\n",
        "    qc.name = name\n",
        "    qc.append(evo_gate, range(num_qubits))\n",
        "    qc_ham_list.append(qc)\n",
        "\n",
        "# Remove circuits whose decomposed size exceeds 1500 gates so that\n",
        "# transpilation completes in a reasonable time frame\n",
        "qc_ham_list = [qc for qc in qc_ham_list if qc.decompose().size() <= 1500]\n",
        "\n",
        "print(f\"Total Hamiltonian circuits loaded: {len(qc_ham_list)}\")\n",
        "min_qubits = min(qc.num_qubits for qc in qc_ham_list)\n",
        "max_qubits = max(qc.num_qubits for qc in qc_ham_list)\n",
        "print(f\"Qubit range: {min_qubits} to {max_qubits}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e3f4a5b6",
      "metadata": {},
      "source": [
        "Divida os circuitos em grupos de pequena escala (menos de 20 qubits) e de grande escala (20 ou mais qubits).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "f3a4b5c6",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Small-scale circuits (<20 qubits): 20\n",
            "Large-scale circuits (>=20 qubits): 22\n"
          ]
        }
      ],
      "source": [
        "qc_small = [qc for qc in qc_ham_list if qc.num_qubits < 20]\n",
        "qc_large = [qc for qc in qc_ham_list if qc.num_qubits >= 20]\n",
        "\n",
        "print(f\"Small-scale circuits (<20 qubits): {len(qc_small)}\")\n",
        "print(f\"Large-scale circuits (>=20 qubits): {len(qc_large)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a4b5c6d7",
      "metadata": {},
      "source": [
        "Visualize um dos circuitos hamiltonianos de pequena escala antes da transpilacão.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "b4c5d6e7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/b4c5d6e7-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# We decompose the circuit here, otherwise it would just be a PauliEvolutionGate box,\n",
        "# which isn't very informative to look at!\n",
        "qc_small[0].decompose().draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "sec-small-scale",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-example\" />\n",
        "\n",
        "## Exemplo em pequena escala\n",
        "\n",
        "Nesta seção, comparamos os três métodos de compilação em circuitos hamiltonianos com menos de 20 qubits. Esses circuitos são compilados rapidamente e oferecem uma visão clara de como cada método lida com circuitos de complexidade moderada.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c4d5e6f7",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "### Passo 1: Mapear entradas clássicas para um problema quântico\n",
        "\n",
        "Cada hamiltoniano é codificado como um `PauliEvolutionGate` circuito. Os circuitos já haviam sido construídos na seção de configuração a partir dos dados de benchmark do Hamlib.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d4e5f6a7",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "### Etapa 2: Otimizar o problema para execução em hardware quântico\n",
        "\n",
        "Fazemos a transpilagem de todos os circuitos de pequena escala utilizando cada um dos três gerenciadores de passagem e, em seguida, coletamos as métricas.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "e4f5a6b7",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[SABRE] Circuit 0 (all-vib-bh): 2Q depth=3, size=30, time=2.09s\n",
            "[SABRE] Circuit 1 (all-vib-c2h): 2Q depth=18, size=111, time=0.01s\n",
            "[SABRE] Circuit 2 (all-vib-o3): 2Q depth=6, size=58, time=0.00s\n",
            "[SABRE] Circuit 3 (all-vib-c2h): 2Q depth=2, size=37, time=0.01s\n",
            "[SABRE] Circuit 4 (graph-gnp_k-2): 2Q depth=24, size=126, time=0.01s\n",
            "[SABRE] Circuit 5 (LiH): 2Q depth=66, size=285, time=0.01s\n",
            "[SABRE] Circuit 6 (all-vib-fccf): 2Q depth=66, size=339, time=0.01s\n",
            "[SABRE] Circuit 7 (all-vib-ch2): 2Q depth=88, size=413, time=0.01s\n",
            "[SABRE] Circuit 8 (all-vib-f2): 2Q depth=180, size=1000, time=0.02s\n",
            "[SABRE] Circuit 9 (all-vib-bhf2): 2Q depth=18, size=223, time=0.03s\n",
            "[SABRE] Circuit 10 (graph-gnp_k-4): 2Q depth=122, size=675, time=0.02s\n",
            "[SABRE] Circuit 11 (Be2): 2Q depth=343, size=1628, time=0.03s\n",
            "[SABRE] Circuit 12 (all-vib-fccf): 2Q depth=14, size=134, time=0.00s\n",
            "[SABRE] Circuit 13 (uf20-ham): 2Q depth=50, size=341, time=0.01s\n",
            "[SABRE] Circuit 14 (TSP_Ncity-4): 2Q depth=118, size=615, time=0.01s\n",
            "[SABRE] Circuit 15 (graph-complete_bipart): 2Q depth=232, size=1420, time=0.03s\n",
            "[SABRE] Circuit 16 (all-vib-cyclo_propene): 2Q depth=18, size=354, time=0.93s\n",
            "[SABRE] Circuit 17 (all-vib-hno): 2Q depth=6, size=174, time=0.14s\n",
            "[SABRE] Circuit 18 (all-vib-fccf): 2Q depth=30, size=286, time=0.01s\n",
            "[SABRE] Circuit 19 (tfim): 2Q depth=31, size=232, time=0.03s\n",
            "[AI] Circuit 0 (all-vib-bh): 2Q depth=3, size=30, time=0.01s\n"
          ]
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "cf50b939bf4141bcbc610275a514d6fd",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Fetching 4 files:   0%|          | 0/4 [00:00<?, ?it/s]"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[AI] Circuit 1 (all-vib-c2h): 2Q depth=18, size=101, time=0.18s\n",
            "[AI] Circuit 2 (all-vib-o3): 2Q depth=6, size=58, time=0.01s\n",
            "[AI] Circuit 3 (all-vib-c2h): 2Q depth=2, size=37, time=0.01s\n",
            "[AI] Circuit 4 (graph-gnp_k-2): 2Q depth=24, size=133, time=0.07s\n",
            "[AI] Circuit 5 (LiH): 2Q depth=62, size=267, time=8.00s\n",
            "[AI] Circuit 6 (all-vib-fccf): 2Q depth=65, size=300, time=0.18s\n",
            "[AI] Circuit 7 (all-vib-ch2): 2Q depth=79, size=353, time=0.16s\n",
            "[AI] Circuit 8 (all-vib-f2): 2Q depth=176, size=998, time=0.43s\n",
            "[AI] Circuit 9 (all-vib-bhf2): 2Q depth=18, size=194, time=0.11s\n",
            "[AI] Circuit 10 (graph-gnp_k-4): 2Q depth=114, size=668, time=0.18s\n",
            "[AI] Circuit 11 (Be2): 2Q depth=292, size=1382, time=0.88s\n",
            "[AI] Circuit 12 (all-vib-fccf): 2Q depth=14, size=134, time=0.01s\n",
            "[AI] Circuit 13 (uf20-ham): 2Q depth=40, size=330, time=0.16s\n",
            "[AI] Circuit 14 (TSP_Ncity-4): 2Q depth=96, size=600, time=0.29s\n",
            "[AI] Circuit 15 (graph-complete_bipart): 2Q depth=231, size=1531, time=0.46s\n",
            "[AI] Circuit 16 (all-vib-cyclo_propene): 2Q depth=18, size=309, time=0.25s\n",
            "[AI] Circuit 17 (all-vib-hno): 2Q depth=10, size=198, time=0.15s\n",
            "[AI] Circuit 18 (all-vib-fccf): 2Q depth=34, size=402, time=0.02s\n",
            "[AI] Circuit 19 (tfim): 2Q depth=44, size=311, time=0.15s\n",
            "[Rustiq] Circuit 0 (all-vib-bh): 2Q depth=3, size=30, time=0.01s\n",
            "[Rustiq] Circuit 1 (all-vib-c2h): 2Q depth=13, size=69, time=0.00s\n",
            "[Rustiq] Circuit 2 (all-vib-o3): 2Q depth=13, size=82, time=0.01s\n",
            "[Rustiq] Circuit 3 (all-vib-c2h): 2Q depth=2, size=40, time=0.01s\n",
            "[Rustiq] Circuit 4 (graph-gnp_k-2): 2Q depth=31, size=132, time=0.01s\n",
            "[Rustiq] Circuit 5 (LiH): 2Q depth=59, size=285, time=0.01s\n",
            "[Rustiq] Circuit 6 (all-vib-fccf): 2Q depth=34, size=193, time=0.00s\n",
            "[Rustiq] Circuit 7 (all-vib-ch2): 2Q depth=49, size=302, time=0.01s\n",
            "[Rustiq] Circuit 8 (all-vib-f2): 2Q depth=141, size=807, time=0.02s\n",
            "[Rustiq] Circuit 9 (all-vib-bhf2): 2Q depth=13, size=146, time=0.02s\n",
            "[Rustiq] Circuit 10 (graph-gnp_k-4): 2Q depth=129, size=683, time=0.02s\n",
            "[Rustiq] Circuit 11 (Be2): 2Q depth=220, size=1101, time=0.02s\n",
            "[Rustiq] Circuit 12 (all-vib-fccf): 2Q depth=53, size=333, time=0.01s\n",
            "[Rustiq] Circuit 13 (uf20-ham): 2Q depth=63, size=425, time=0.01s\n",
            "[Rustiq] Circuit 14 (TSP_Ncity-4): 2Q depth=123, size=767, time=0.02s\n",
            "[Rustiq] Circuit 15 (graph-complete_bipart): 2Q depth=309, size=2107, time=0.05s\n",
            "[Rustiq] Circuit 16 (all-vib-cyclo_propene): 2Q depth=16, size=283, time=0.32s\n",
            "[Rustiq] Circuit 17 (all-vib-hno): 2Q depth=19, size=291, time=0.32s\n",
            "[Rustiq] Circuit 18 (all-vib-fccf): 2Q depth=44, size=546, time=0.02s\n",
            "[Rustiq] Circuit 19 (tfim): 2Q depth=24, size=416, time=0.01s\n"
          ]
        }
      ],
      "source": [
        "results_small = []\n",
        "\n",
        "tqc_sabre_small = capture_transpilation_metrics(\n",
        "    results_small, pm_sabre, qc_small, \"SABRE\"\n",
        ")\n",
        "tqc_ai_small = capture_transpilation_metrics(\n",
        "    results_small, pm_ai, qc_small, \"AI\"\n",
        ")\n",
        "tqc_rustiq_small = capture_transpilation_metrics(\n",
        "    results_small, pm_rustiq, qc_small, \"Rustiq\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f4a5b6c7",
      "metadata": {},
      "source": [
        "A tabela abaixo resume a média e o desvio padrão de cada métrica em todos os circuitos de pequena escala, juntamente com a porcentagem de melhoria em relação ao SABRE. Como os tamanhos dos circuitos variam bastante, o desvio-padrão fornece um contexto importante para a interpretação das médias.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "a5b6c7d8",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean +/- std per compilation method\n",
            "Method                2Q Depth              Gate Count             Runtime (s)\n",
            "------------------------------------------------------------------------------\n",
            "SABRE            71.8 +/- 89.6         424.1 +/- 446.0             0.2 +/- 0.5\n",
            "AI               67.3 +/- 80.2         416.8 +/- 426.7             0.6 +/- 1.8\n",
            "Rustiq           67.9 +/- 80.0         451.9 +/- 484.7             0.0 +/- 0.1\n",
            "\n",
            "Mean % improvement vs SABRE (positive = better than SABRE)\n",
            "Method                2Q Depth              Gate Count             Runtime (s)\n",
            "------------------------------------------------------------------------------\n",
            "AI             -2.1% +/- 19.8%         -0.6% +/- 14.7%   -5635.1% +/- 20725.2%\n",
            "Rustiq        -25.3% +/- 85.4%        -16.3% +/- 50.4%         -7.0% +/- 60.6%\n"
          ]
        }
      ],
      "source": [
        "print_summary_table(results_small)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "per_circuit_small_md",
      "metadata": {},
      "source": [
        "A tabela por circuito mostra como cada método se comporta em circuitos individuais. O melhor valor para cada métrica está marcado com um asterisco. Observe que, nos circuitos mais simples, os três métodos costumam convergir para o mesmo resultado.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "per_circuit_small_code",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "2Q Depth (first 8 circuits by qubit count); * = best\n",
            "Idx  Circuit            Q    SABRE       AI   Rustiq\n",
            "----------------------------------------------------\n",
            "  0  all-vib-bh         2       3*       3*       3*\n",
            "  1  all-vib-c2h        3       18       18      13*\n",
            "  2  all-vib-o3         4       6*       6*       13\n",
            "  3  all-vib-c2h        4       2*       2*       2*\n",
            "  4  graph-gnp_k-2      4      24*      24*       31\n",
            "  5  LiH                4       66       62      59*\n",
            "  6  all-vib-fccf       4       66       65      34*\n",
            "  7  all-vib-ch2        4       88       79      49*\n",
            "\n",
            "Gate Count (first 8 circuits by qubit count); * = best\n",
            "Idx  Circuit            Q    SABRE       AI   Rustiq\n",
            "----------------------------------------------------\n",
            "  0  all-vib-bh         2      30*      30*      30*\n",
            "  1  all-vib-c2h        3      111      101      69*\n",
            "  2  all-vib-o3         4      58*      58*       82\n",
            "  3  all-vib-c2h        4      37*      37*       40\n",
            "  4  graph-gnp_k-2      4     126*      133      132\n",
            "  5  LiH                4      285     267*      285\n",
            "  6  all-vib-fccf       4      339      300     193*\n",
            "  7  all-vib-ch2        4      413      353     302*\n",
            "\n",
            "Runtime (s) (first 8 circuits by qubit count); * = best\n",
            "Idx  Circuit            Q    SABRE       AI   Rustiq\n",
            "----------------------------------------------------\n",
            "  0  all-vib-bh         2     2.09     0.01    0.01*\n",
            "  1  all-vib-c2h        3     0.01     0.18    0.00*\n",
            "  2  all-vib-o3         4    0.00*     0.01     0.01\n",
            "  3  all-vib-c2h        4     0.01     0.01    0.01*\n",
            "  4  graph-gnp_k-2      4    0.01*     0.07     0.01\n",
            "  5  LiH                4    0.01*     8.00     0.01\n",
            "  6  all-vib-fccf       4     0.01     0.18    0.00*\n",
            "  7  all-vib-ch2        4     0.01     0.16    0.01*\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print_per_circuit_comparison(results_small, num_rows=8)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b5c6d7e8",
      "metadata": {},
      "source": [
        "<span id=\"visualize-results\" />\n",
        "\n",
        "#### Visualizar os resultados\n",
        "\n",
        "Os gráficos abaixo comparam os três métodos em cada métrica, considerando cada circuito individualmente. Os circuitos são classificados pelo número de qubits e identificados por um índice no eixo x, já que vários circuitos podem compartilhar o mesmo número de qubits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "c5d6e7f8",
      "metadata": {},
      "outputs": [],
      "source": [
        "def plot_transpilation_comparison(results, title_prefix):\n",
        "    \"\"\"\n",
        "    Create a three-panel figure comparing compilation methods on\n",
        "    two-qubit depth, circuit size, and runtime.\n",
        "\n",
        "    Circuits are sorted by qubit count and plotted by circuit index.\n",
        "    \"\"\"\n",
        "    methods = _method_order(results)\n",
        "    palette = {\"SABRE\": \"#1f77b4\", \"AI\": \"#ff7f0e\", \"Rustiq\": \"#2ca02c\"}\n",
        "    markers = {\"SABRE\": \"o\", \"AI\": \"^\", \"Rustiq\": \"s\"}\n",
        "\n",
        "    # Order circuits by qubit count (then index) and map to plot positions\n",
        "    ref = sorted(\n",
        "        [r for r in results if r[\"method\"] == methods[0]],\n",
        "        key=lambda r: (r[\"num_qubits\"], r[\"qc_index\"]),\n",
        "    )\n",
        "    pos_map = {r[\"qc_index\"]: pos for pos, r in enumerate(ref)}\n",
        "    tick_positions = [pos_map[r[\"qc_index\"]] for r in ref]\n",
        "    tick_labels = [\n",
        "        f\"{pos_map[r['qc_index']]} ({r['num_qubits']}q)\" for r in ref\n",
        "    ]\n",
        "\n",
        "    metrics = [\n",
        "        (\"two_qubit_depth\", \"Two-Qubit Depth\"),\n",
        "        (\"size\", \"Total Gate Count (Circuit Size)\"),\n",
        "        (\"runtime\", \"Transpilation Runtime (s)\"),\n",
        "    ]\n",
        "\n",
        "    fig, axes = plt.subplots(1, 3, figsize=(20, 5.5))\n",
        "    fig.suptitle(title_prefix, fontsize=15, fontweight=\"bold\", y=1.02)\n",
        "\n",
        "    for ax, (metric, ylabel) in zip(axes, metrics):\n",
        "        for method in methods:\n",
        "            subset = sorted(\n",
        "                [r for r in results if r[\"method\"] == method],\n",
        "                key=lambda r: pos_map[r[\"qc_index\"]],\n",
        "            )\n",
        "            ax.plot(\n",
        "                [pos_map[r[\"qc_index\"]] for r in subset],\n",
        "                [r[metric] for r in subset],\n",
        "                marker=markers.get(method, \"o\"),\n",
        "                label=method,\n",
        "                color=palette.get(method, None),\n",
        "                linewidth=1.5,\n",
        "                markersize=6,\n",
        "                alpha=0.85,\n",
        "            )\n",
        "        ax.set_xlabel(\"Circuit Index (num qubits)\", fontsize=11)\n",
        "        ax.set_ylabel(ylabel, fontsize=11)\n",
        "        ax.legend(frameon=True, fontsize=9)\n",
        "        ax.grid(True, linestyle=\"--\", alpha=0.4)\n",
        "        step = max(1, len(tick_positions) // 15)\n",
        "        ax.set_xticks(tick_positions[::step])\n",
        "        ax.set_xticklabels(\n",
        "            [tick_labels[i] for i in range(0, len(tick_labels), step)],\n",
        "            fontsize=7,\n",
        "            rotation=45,\n",
        "            ha=\"right\",\n",
        "        )\n",
        "\n",
        "    plt.tight_layout()\n",
        "    plt.show()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "pct_improvement_plot_fn",
      "metadata": {},
      "outputs": [],
      "source": [
        "def plot_pct_improvement_vs_sabre(results, title_prefix):\n",
        "    \"\"\"\n",
        "    Plot the per-circuit percent improvement of each non-SABRE method\n",
        "    relative to SABRE, for each metric. A positive value means the\n",
        "    method improved on SABRE; negative means SABRE was better.\n",
        "    \"\"\"\n",
        "    metrics = [\n",
        "        (\"two_qubit_depth\", \"2Q Depth\"),\n",
        "        (\"size\", \"Gate Count\"),\n",
        "        (\"runtime\", \"Runtime\"),\n",
        "    ]\n",
        "    palette = {\"AI\": \"#ff7f0e\", \"Rustiq\": \"#2ca02c\"}\n",
        "    markers = {\"AI\": \"^\", \"Rustiq\": \"s\"}\n",
        "\n",
        "    methods = _method_order(results)\n",
        "    sabre = sorted(\n",
        "        [r for r in results if r[\"method\"] == \"SABRE\"],\n",
        "        key=lambda r: (r[\"num_qubits\"], r[\"qc_index\"]),\n",
        "    )\n",
        "    other_methods = [m for m in methods if m != \"SABRE\"]\n",
        "\n",
        "    tick_positions = list(range(len(sabre)))\n",
        "    tick_labels = [\n",
        "        f\"{i} ({sabre[i]['num_qubits']}q)\" for i in range(len(sabre))\n",
        "    ]\n",
        "\n",
        "    fig, axes = plt.subplots(1, 3, figsize=(20, 5.5))\n",
        "    fig.suptitle(\n",
        "        f\"{title_prefix}: % Improvement over SABRE\",\n",
        "        fontsize=15,\n",
        "        fontweight=\"bold\",\n",
        "        y=1.02,\n",
        "    )\n",
        "\n",
        "    for ax, (metric, label) in zip(axes, metrics):\n",
        "        ax.axhline(0, color=\"#1f77b4\", linewidth=2, label=\"SABRE (baseline)\")\n",
        "        for method in other_methods:\n",
        "            data = sorted(\n",
        "                [r for r in results if r[\"method\"] == method],\n",
        "                key=lambda r: (r[\"num_qubits\"], r[\"qc_index\"]),\n",
        "            )\n",
        "            pct = [\n",
        "                (sabre[i][metric] - data[i][metric]) / sabre[i][metric] * 100\n",
        "                for i in range(len(sabre))\n",
        "            ]\n",
        "            ax.plot(\n",
        "                tick_positions,\n",
        "                pct,\n",
        "                marker=markers.get(method, \"o\"),\n",
        "                label=method,\n",
        "                color=palette.get(method, None),\n",
        "                linewidth=1.5,\n",
        "                markersize=6,\n",
        "                alpha=0.85,\n",
        "            )\n",
        "        ax.set_xlabel(\"Circuit Index (num qubits)\", fontsize=11)\n",
        "        ax.set_ylabel(f\"% Improvement ({label})\", fontsize=11)\n",
        "        ax.legend(frameon=True, fontsize=9)\n",
        "        ax.grid(True, linestyle=\"--\", alpha=0.4)\n",
        "        step = max(1, len(tick_positions) // 15)\n",
        "        ax.set_xticks(tick_positions[::step])\n",
        "        ax.set_xticklabels(\n",
        "            [tick_labels[i] for i in range(0, len(tick_labels), step)],\n",
        "            fontsize=7,\n",
        "            rotation=45,\n",
        "            ha=\"right\",\n",
        "        )\n",
        "        ylims = ax.get_ylim()\n",
        "        ax.axhspan(0, max(ylims[1], 1), alpha=0.04, color=\"green\")\n",
        "        ax.axhspan(min(ylims[0], -1), 0, alpha=0.04, color=\"red\")\n",
        "\n",
        "    plt.tight_layout()\n",
        "    plt.show()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "d5e6f7a8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/d5e6f7a8-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plot_transpilation_comparison(\n",
        "    results_small,\n",
        "    \"Small-Scale Hamiltonian Circuits: Compilation Comparison\",\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "pct_improvement_small",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/pct_improvement_small-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plot_pct_improvement_vs_sabre(\n",
        "    results_small,\n",
        "    \"Small-Scale Hamiltonian Circuits\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d2a29d04",
      "metadata": {},
      "source": [
        "Nessa escala, os três gerenciadores de aprovação apresentam bom desempenho, e seus resultados médios são próximos uns dos outros. Isso se deve, em grande parte, ao fato de que circuitos pequenos oferecem espaço limitado para otimização adicional; por isso, os métodos tendem a convergir para soluções semelhantes.\n",
        "\n",
        "Neste exemplo, o Rustiq apresenta os resultados mais variáveis, com os maiores valores atípicos tanto na profundidade de dois qubits quanto no número de portas. Embora essa variabilidade signifique que, às vezes, ele fique para trás, também significa que o Rustiq, ocasionalmente, encontra soluções melhores do que os outros dois métodos. O transpiler de IA apresenta resultados mais estáveis em comparação com o SABRE e o Rustiq, acompanhando de perto os resultados na maioria dos circuitos, sem muitos valores atípicos.\n",
        "\n",
        "Em termos de tempo de execução, tanto o SABRE quanto o Rustiq são rápidos, enquanto o transpiler baseado em IA é visivelmente mais lento em certos circuitos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e5f6a7b8",
      "metadata": {},
      "source": [
        "<span id=\"best-performing-method-by-metric\" />\n",
        "\n",
        "#### Método com melhor desempenho por métrica\n",
        "\n",
        "O gráfico abaixo mostra com que frequência cada método alcançou o melhor (menor) valor para cada métrica. É possível haver empates: em circuitos mais simples, vários métodos podem atingir a mesma profundidade ideal de dois qubits ou o mesmo número de portas. Quando ocorre um empate, todos os métodos empatados recebem crédito; portanto, as porcentagens de uma determinada métrica podem somar mais de 100%.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "f5a6b7c8",
      "metadata": {},
      "outputs": [],
      "source": [
        "def plot_best_method_bars(results, metrics_list=None):\n",
        "    \"\"\"\n",
        "    Plot a grouped bar chart showing the percentage of circuits\n",
        "    where each method achieved the best (lowest) value for each metric.\n",
        "\n",
        "    Ties are counted for all tied methods, so percentages per metric\n",
        "    can sum to more than 100%.\n",
        "    \"\"\"\n",
        "    if metrics_list is None:\n",
        "        metrics_list = [\"two_qubit_depth\", \"size\", \"runtime\"]\n",
        "\n",
        "    labels = {\n",
        "        \"two_qubit_depth\": \"2Q Depth\",\n",
        "        \"size\": \"Gate Count\",\n",
        "        \"runtime\": \"Runtime\",\n",
        "    }\n",
        "    methods = _method_order(results)\n",
        "    palette = {\"SABRE\": \"#1f77b4\", \"AI\": \"#ff7f0e\", \"Rustiq\": \"#2ca02c\"}\n",
        "\n",
        "    by_index = {}\n",
        "    for r in results:\n",
        "        by_index.setdefault(r[\"qc_index\"], []).append(r)\n",
        "    n_circuits = len(by_index)\n",
        "\n",
        "    win_data = {m: [] for m in methods}\n",
        "    tie_counts = []\n",
        "    metric_labels = []\n",
        "\n",
        "    for metric in metrics_list:\n",
        "        metric_labels.append(\n",
        "            labels.get(metric, metric.replace(\"_\", \" \").title())\n",
        "        )\n",
        "        counts = Counter()\n",
        "        ties = 0\n",
        "        for group in by_index.values():\n",
        "            min_val = min(r[metric] for r in group)\n",
        "            best = [r[\"method\"] for r in group if r[metric] == min_val]\n",
        "            if len(best) > 1:\n",
        "                ties += 1\n",
        "            counts.update(best)\n",
        "        tie_counts.append(ties)\n",
        "        for m in methods:\n",
        "            win_data[m].append(counts.get(m, 0) / n_circuits * 100)\n",
        "\n",
        "    x = np.arange(len(metric_labels))\n",
        "    width = 0.22\n",
        "    fig, ax = plt.subplots(figsize=(8, 5))\n",
        "\n",
        "    for i, method in enumerate(methods):\n",
        "        bars = ax.bar(\n",
        "            x + i * width,\n",
        "            win_data[method],\n",
        "            width,\n",
        "            label=method,\n",
        "            color=palette.get(method, None),\n",
        "            edgecolor=\"black\",\n",
        "            linewidth=0.5,\n",
        "        )\n",
        "        for bar in bars:\n",
        "            height = bar.get_height()\n",
        "            if height > 0:\n",
        "                ax.text(\n",
        "                    bar.get_x() + bar.get_width() / 2,\n",
        "                    height + 1.5,\n",
        "                    f\"{height:.0f}%\",\n",
        "                    ha=\"center\",\n",
        "                    va=\"bottom\",\n",
        "                    fontsize=9,\n",
        "                )\n",
        "\n",
        "    # Annotate tie counts below each metric label\n",
        "    for j, ties in enumerate(tie_counts):\n",
        "        if ties > 0:\n",
        "            ax.text(\n",
        "                x[j] + width,\n",
        "                -8,\n",
        "                f\"({ties} tie{'s' if ties != 1 else ''})\",\n",
        "                ha=\"center\",\n",
        "                va=\"top\",\n",
        "                fontsize=8,\n",
        "                color=\"gray\",\n",
        "            )\n",
        "\n",
        "    ax.set_xticks(x + width)\n",
        "    ax.set_xticklabels(metric_labels, fontsize=11)\n",
        "    ax.set_ylabel(\"Circuits with best value (%)\", fontsize=11)\n",
        "    ax.set_title(\n",
        "        \"Best-Performing Method by Metric (ties counted for all tied methods)\",\n",
        "        fontsize=12,\n",
        "        fontweight=\"bold\",\n",
        "    )\n",
        "    ax.legend(frameon=True, fontsize=10)\n",
        "    ax.set_ylim(-12, 120)\n",
        "    ax.yaxis.set_major_formatter(ticker.PercentFormatter())\n",
        "    ax.grid(axis=\"y\", linestyle=\"--\", alpha=0.4)\n",
        "\n",
        "    plt.tight_layout()\n",
        "    plt.show()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "a6b7c8d9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/a6b7c8d9-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plot_best_method_bars(results_small)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "30687d7b",
      "metadata": {},
      "source": [
        "Neste exemplo, os três métodos apresentam desempenho muito semelhante nos circuitos de pequena escala. Em termos de profundidade de dois qubits e número de portas, a proporção de circuitos em que cada método é o melhor é semelhante (aproximadamente 35–55%), e muitos circuitos resultam em empate, pois os circuitos mais simples costumam ter uma única solução ótima que é encontrada por vários métodos. A diferença mais evidente é o tempo de execução: o SABRE e o Rustiq são os mais rápidos em cerca de metade dos circuitos, enquanto o transpiler baseado em IA raramente é o mais rápido. Levando em conta os três indicadores em conjunto, o Rustiq apresenta uma ligeira vantagem geral: é o vencedor mais frequente em profundidade de dois qubits e se mantém competitivo em número de portas e tempo de execução.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b6c7d8e9",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "### Passo 3: Execute usando Qiskit primitives\n",
        "\n",
        "Para avaliar como a qualidade da transpilagem afeta a execução em condições de ruído, utilizamos uma técnica **de circuito espelho**. Para cada circuito transpilado $U$, acrescentamos seu inverso $U^\\dagger$, de modo que o circuito combinado $U^\\dagger U$ seja, teoricamente, a identidade. Partindo do estado “ $|0\\rangle$ ”, uma execução perfeita (sem ruído) retornaria a sequência de bits composta inteiramente por zeros com probabilidade 1.\n",
        "\n",
        "Na prática, os erros nas portas se acumulam ao longo do circuito, de modo que a probabilidade de recuperar um $|0\\rangle^{\\otimes n}$ a diminui. Um método de compilação que gera um circuito menos profundo, com menos portas lógicas, acumulará menos ruído.\n",
        "\n",
        "A abordagem do circuito espelho é atraentemente simples e se adapta a circuitos de qualquer tamanho, uma vez que a saída esperada é sempre um $|0\\rangle^{\\otimes n}$ e e não é necessária nenhuma simulação clássica do estado ideal. No entanto, observe as seguintes ressalvas: o circuito espelho é um substituto do circuito real (não o próprio circuito); ele dobra o número de portas lógicas (o que exagera o efeito do ruído); e pode subestimar certos erros quando o ruído se cancela simetricamente ao longo da fronteira do espelho.\n",
        "\n",
        "Selecionamos o índice de circuito 6 do conjunto de pequena escala e executamos os circuitos espelhados em um simulador Aer com um modelo simples de ruído despolarizante.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "c6d7e8f9",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Test circuit: all-vib-fccf, 4 qubits\n",
            "\n",
            "Transpilation metrics for circuit index 6:\n",
            "  SABRE     2Q depth=   66  size=   339\n",
            "  AI        2Q depth=   65  size=   300\n",
            "  Rustiq    2Q depth=   34  size=   193\n"
          ]
        }
      ],
      "source": [
        "# Select circuit index 6 from the small-scale transpiled circuits\n",
        "test_idx = 6\n",
        "test_circuit = qc_small[test_idx]\n",
        "print(f\"Test circuit: {test_circuit.name}, {test_circuit.num_qubits} qubits\")\n",
        "\n",
        "# Get the transpiled versions\n",
        "tqc_methods_small = {\n",
        "    \"SABRE\": tqc_sabre_small[test_idx],\n",
        "    \"AI\": tqc_ai_small[test_idx],\n",
        "    \"Rustiq\": tqc_rustiq_small[test_idx],\n",
        "}\n",
        "\n",
        "# Show transpilation metrics for this circuit\n",
        "print(f\"\\nTranspilation metrics for circuit index {test_idx}:\")\n",
        "for method, tqc in tqc_methods_small.items():\n",
        "    depth_2q = tqc.depth(lambda x: x.operation.num_qubits == 2)\n",
        "    size = tqc.size()\n",
        "    print(f\"  {method:8s}  2Q depth={depth_2q:5d}  size={size:6d}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d6e7f8a9",
      "metadata": {},
      "source": [
        "Construa os circuitos espelho (acesse $U^\\dagger$ ), remapeie para índices de qubits contíguos, de modo que o simulador lide apenas com os qubits ativos, e execute em um simulador Aer com ruído.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "e6f7a8b9",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "SABRE     P(|00...0>) = 0.7796  (7796/10000)\n",
            "AI        P(|00...0>) = 0.8073  (8073/10000)\n",
            "Rustiq    P(|00...0>) = 0.8923  (8923/10000)\n"
          ]
        }
      ],
      "source": [
        "def remap_to_contiguous(tqc):\n",
        "    \"\"\"Remap a transpiled circuit to use contiguous qubit indices.\n",
        "\n",
        "    Transpiled circuits target specific physical qubits (e.g., qubit 45, 67)\n",
        "    on a large backend. This remaps them to 0, 1, 2, ... so Aer only\n",
        "    simulates the active qubits.\n",
        "    \"\"\"\n",
        "    active = sorted(\n",
        "        {tqc.find_bit(q).index for inst in tqc.data for q in inst.qubits}\n",
        "    )\n",
        "    qubit_map = {old: new for new, old in enumerate(active)}\n",
        "    new_qc = QuantumCircuit(len(active))\n",
        "    for inst in tqc.data:\n",
        "        old_indices = [tqc.find_bit(q).index for q in inst.qubits]\n",
        "        new_qc.append(inst.operation, [qubit_map[i] for i in old_indices])\n",
        "    return new_qc\n",
        "\n",
        "\n",
        "def build_mirror_circuit(tqc):\n",
        "    \"\"\"Build a mirror circuit: U followed by U-dagger, with measurements.\n",
        "\n",
        "    The combined circuit U-dagger @ U should be the identity, so measuring\n",
        "    all zeros indicates a noise-free execution.\n",
        "    \"\"\"\n",
        "    tqc_compact = remap_to_contiguous(tqc)\n",
        "    mirror = tqc_compact.compose(tqc_compact.inverse())\n",
        "    mirror.measure_all()\n",
        "    return mirror\n",
        "\n",
        "\n",
        "# Build a simple depolarizing noise model\n",
        "noise_model = NoiseModel()\n",
        "noise_model.add_all_qubit_quantum_error(\n",
        "    depolarizing_error(0.001, 1),\n",
        "    [\"sx\", \"x\", \"rz\"],  # ~0.1% per 1Q gate\n",
        ")\n",
        "noise_model.add_all_qubit_quantum_error(\n",
        "    depolarizing_error(0.01, 2),\n",
        "    [\"cx\", \"ecr\"],  # ~1% per 2Q gate\n",
        ")\n",
        "\n",
        "aer_sim = AerSimulator(noise_model=noise_model)\n",
        "\n",
        "shots = 10000\n",
        "fidelities = {}\n",
        "\n",
        "for method, tqc in tqc_methods_small.items():\n",
        "    mirror = build_mirror_circuit(tqc)\n",
        "\n",
        "    sampler = SamplerV2(mode=aer_sim)\n",
        "    job = sampler.run([mirror], shots=shots)\n",
        "    result = job.result()\n",
        "    counts = result[0].data.meas.get_counts()\n",
        "\n",
        "    # Fidelity = fraction of all-zeros (error-free) outcomes\n",
        "    n_qubits = mirror.num_qubits - mirror.num_clbits  # active qubits\n",
        "    all_zeros = \"0\" * mirror.num_qubits\n",
        "    fidelity = counts.get(all_zeros, 0) / shots\n",
        "    fidelities[method] = fidelity\n",
        "    print(\n",
        "        f\"{method:8s}  P(|00...0>) = {fidelity:.4f}  \"\n",
        "        f\"({counts.get(all_zeros, 0)}/{shots})\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "small_step4_plot",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/small_step4_plot-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "def plot_mirror_results(tqc_methods, fidelities, circuit_name):\n",
        "    \"\"\"\n",
        "    Plot a three-panel comparison: fidelity, 2Q depth,\n",
        "    and gate count for each compilation method.\n",
        "    \"\"\"\n",
        "    methods = list(tqc_methods.keys())\n",
        "    palette = {\"SABRE\": \"#1f77b4\", \"AI\": \"#ff7f0e\", \"Rustiq\": \"#2ca02c\"}\n",
        "    colors = [palette.get(m, \"gray\") for m in methods]\n",
        "\n",
        "    fidelity_vals = [fidelities[m] for m in methods]\n",
        "    depth_vals = [\n",
        "        tqc_methods[m].depth(lambda x: x.operation.num_qubits == 2)\n",
        "        for m in methods\n",
        "    ]\n",
        "    size_vals = [tqc_methods[m].size() for m in methods]\n",
        "\n",
        "    fig, axes = plt.subplots(1, 3, figsize=(16, 5))\n",
        "    fig.suptitle(\n",
        "        f\"Mirror Circuit Results: {circuit_name}\",\n",
        "        fontsize=14,\n",
        "        fontweight=\"bold\",\n",
        "        y=1.02,\n",
        "    )\n",
        "\n",
        "    def _annotate_bars(ax, bars, values, fmt=\"{}\"):\n",
        "        ymax = ax.get_ylim()[1]\n",
        "        for bar, val in zip(bars, values):\n",
        "            label = fmt.format(val)\n",
        "            y = val + ymax * 0.03\n",
        "            ax.text(\n",
        "                bar.get_x() + bar.get_width() / 2,\n",
        "                y,\n",
        "                label,\n",
        "                ha=\"center\",\n",
        "                va=\"bottom\",\n",
        "                fontsize=10,\n",
        "                fontweight=\"bold\",\n",
        "            )\n",
        "\n",
        "    # Panel 1: Survival Probability\n",
        "    bars = axes[0].bar(\n",
        "        methods, fidelity_vals, color=colors, edgecolor=\"black\", linewidth=0.5\n",
        "    )\n",
        "    axes[0].set_ylabel(\"Fidelity  P(|00...0>)\", fontsize=11)\n",
        "    axes[0].set_title(\"Fidelity (higher is better)\", fontsize=12)\n",
        "    axes[0].set_ylim(\n",
        "        0, max(fidelity_vals) * 1.18 if max(fidelity_vals) > 0 else 1.0\n",
        "    )\n",
        "    axes[0].grid(axis=\"y\", linestyle=\"--\", alpha=0.4)\n",
        "    _annotate_bars(axes[0], bars, fidelity_vals, fmt=\"{:.4f}\")\n",
        "\n",
        "    # Panel 2: Two-Qubit Depth\n",
        "    bars = axes[1].bar(\n",
        "        methods, depth_vals, color=colors, edgecolor=\"black\", linewidth=0.5\n",
        "    )\n",
        "    axes[1].set_ylabel(\"Two-Qubit Depth\", fontsize=11)\n",
        "    axes[1].set_title(\"2Q Depth (lower is better)\", fontsize=12)\n",
        "    axes[1].set_ylim(0, max(depth_vals) * 1.18)\n",
        "    axes[1].grid(axis=\"y\", linestyle=\"--\", alpha=0.4)\n",
        "    _annotate_bars(axes[1], bars, depth_vals)\n",
        "\n",
        "    # Panel 3: Gate Count\n",
        "    bars = axes[2].bar(\n",
        "        methods, size_vals, color=colors, edgecolor=\"black\", linewidth=0.5\n",
        "    )\n",
        "    axes[2].set_ylabel(\"Total Gate Count\", fontsize=11)\n",
        "    axes[2].set_title(\"Gate Count (lower is better)\", fontsize=12)\n",
        "    axes[2].set_ylim(0, max(size_vals) * 1.18)\n",
        "    axes[2].grid(axis=\"y\", linestyle=\"--\", alpha=0.4)\n",
        "    _annotate_bars(axes[2], bars, size_vals)\n",
        "\n",
        "    plt.tight_layout()\n",
        "    plt.show()\n",
        "\n",
        "\n",
        "plot_mirror_results(tqc_methods_small, fidelities, test_circuit.name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "small_mirror_commentary",
      "metadata": {},
      "source": [
        "<span id=\"observations\" />\n",
        "\n",
        "#### Observações\n",
        "\n",
        "O método com a menor profundidade de dois qubits e o menor número de portas alcança a maior fidelidade, o que está de acordo com a expectativa de que circuitos mais curtos acumulam menos ruído. Mesmo diferenças modestas na profundidade e no número de portas se traduzem em diferenças mensuráveis na fidelidade, de acordo com o modelo de ruído despolarizante.\n",
        "\n",
        "Lembre-se de que esses resultados se referem a um único circuito. A classificação relativa dos métodos pode variar de circuito para circuito, dependendo da estrutura do hamiltoniano.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "sec-large-scale",
      "metadata": {},
      "source": [
        "<span id=\"large-scale-hardware-example\" />\n",
        "\n",
        "## Exemplo de hardware em grande escala\n",
        "\n",
        "Nesta seção, comparamos os mesmos três métodos de compilação em circuitos hamiltonianos com 20 ou mais qubits. Esses circuitos são mais representativos das cargas de trabalho práticas de simulação hamiltoniana e testam como cada método se comporta em termos de qualidade do circuito e tempo de compilação.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f6a7b8c9",
      "metadata": {},
      "source": [
        "<span id=\"steps-1-4-combined\" />\n",
        "\n",
        "### Etapas 1 a 4 combinadas\n",
        "\n",
        "O fluxo de trabalho segue a mesma estrutura do exemplo em pequena escala. Transpilamos todos os circuitos de grande escala com cada método, coletamos métricas e enviamos um circuito espelho para um hardware quântico real.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "a7b8c9d0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[SABRE] Circuit 0 (all-vib-hc3h2cn): 2Q depth=2, size=258, time=0.16s\n",
            "[SABRE] Circuit 1 (ham-graph-gnp_k-5): 2Q depth=345, size=4036, time=0.08s\n",
            "[SABRE] Circuit 2 (TSP_Ncity-5): 2Q depth=187, size=2045, time=0.04s\n",
            "[SABRE] Circuit 3 (tfim): 2Q depth=100, size=489, time=0.21s\n",
            "[SABRE] Circuit 4 (all-vib-h2co): 2Q depth=30, size=570, time=0.18s\n",
            "[SABRE] Circuit 5 (uuf100-ham): 2Q depth=414, size=4779, time=0.09s\n",
            "[SABRE] Circuit 6 (uuf100-ham): 2Q depth=523, size=5667, time=0.11s\n",
            "[SABRE] Circuit 7 (graph-gnp_k-4): 2Q depth=3028, size=24885, time=0.39s\n",
            "[SABRE] Circuit 8 (uf100-ham): 2Q depth=700, size=8271, time=0.15s\n",
            "[SABRE] Circuit 9 (uf100-ham): 2Q depth=698, size=8957, time=0.15s\n",
            "[SABRE] Circuit 10 (TSP_Ncity-7): 2Q depth=432, size=6353, time=0.12s\n",
            "[SABRE] Circuit 11 (all-vib-cyclo_propene): 2Q depth=30, size=1144, time=0.20s\n",
            "[SABRE] Circuit 12 (TSP_Ncity-8): 2Q depth=704, size=10287, time=0.18s\n",
            "[SABRE] Circuit 13 (uf100-ham): 2Q depth=2454, size=30195, time=0.46s\n",
            "[SABRE] Circuit 14 (tfim): 2Q depth=245, size=3670, time=0.08s\n",
            "[SABRE] Circuit 15 (flat100-ham): 2Q depth=154, size=3836, time=0.12s\n",
            "[SABRE] Circuit 16 (graph-regular_reg-4): 2Q depth=863, size=14063, time=0.22s\n",
            "[SABRE] Circuit 17 (tfim): 2Q depth=581, size=8810, time=0.15s\n",
            "[SABRE] Circuit 18 (FH_D-1): 2Q depth=1704, size=9528, time=0.35s\n",
            "[SABRE] Circuit 19 (TSP_Ncity-10): 2Q depth=1091, size=22041, time=0.38s\n",
            "[SABRE] Circuit 20 (TSP_Ncity-10): 2Q depth=1091, size=22005, time=0.38s\n",
            "[SABRE] Circuit 21 (ham-unary-color02-queen13_13_k-4): 2Q depth=224, size=8321, time=0.17s\n",
            "[AI] Circuit 0 (all-vib-hc3h2cn): 2Q depth=2, size=258, time=0.17s\n",
            "[AI] Circuit 1 (ham-graph-gnp_k-5): 2Q depth=323, size=4418, time=3.13s\n",
            "[AI] Circuit 2 (TSP_Ncity-5): 2Q depth=161, size=2229, time=1.47s\n",
            "[AI] Circuit 3 (tfim): 2Q depth=20, size=402, time=0.34s\n",
            "[AI] Circuit 4 (all-vib-h2co): 2Q depth=38, size=661, time=0.19s\n",
            "[AI] Circuit 5 (uuf100-ham): 2Q depth=391, size=5130, time=3.27s\n",
            "[AI] Circuit 6 (uuf100-ham): 2Q depth=463, size=6095, time=4.23s\n",
            "[AI] Circuit 7 (graph-gnp_k-4): 2Q depth=3207, size=25641, time=15.15s\n",
            "[AI] Circuit 8 (uf100-ham): 2Q depth=637, size=8267, time=5.87s\n",
            "[AI] Circuit 9 (uf100-ham): 2Q depth=632, size=9330, time=7.29s\n",
            "[AI] Circuit 10 (TSP_Ncity-7): 2Q depth=452, size=7418, time=6.02s\n",
            "[AI] Circuit 11 (all-vib-cyclo_propene): 2Q depth=38, size=1323, time=0.27s\n",
            "[AI] Circuit 12 (TSP_Ncity-8): 2Q depth=609, size=11131, time=10.07s\n",
            "[AI] Circuit 13 (uf100-ham): 2Q depth=2251, size=31128, time=38.77s\n",
            "[AI] Circuit 14 (tfim): 2Q depth=165, size=3460, time=1.64s\n",
            "[AI] Circuit 15 (flat100-ham): 2Q depth=91, size=3497, time=2.49s\n",
            "[AI] Circuit 16 (graph-regular_reg-4): 2Q depth=664, size=15256, time=12.35s\n",
            "[AI] Circuit 17 (tfim): 2Q depth=583, size=9157, time=6.28s\n",
            "[AI] Circuit 18 (FH_D-1): 2Q depth=1193, size=7754, time=4.54s\n",
            "[AI] Circuit 19 (TSP_Ncity-10): 2Q depth=1134, size=22577, time=25.64s\n",
            "[AI] Circuit 20 (TSP_Ncity-10): 2Q depth=1172, size=23851, time=28.97s\n",
            "[AI] Circuit 21 (ham-unary-color02-queen13_13_k-4): 2Q depth=219, size=8600, time=8.85s\n",
            "[Rustiq] Circuit 0 (all-vib-hc3h2cn): 2Q depth=2, size=257, time=0.16s\n",
            "[Rustiq] Circuit 1 (ham-graph-gnp_k-5): 2Q depth=640, size=5831, time=0.13s\n",
            "[Rustiq] Circuit 2 (TSP_Ncity-5): 2Q depth=408, size=3985, time=0.08s\n",
            "[Rustiq] Circuit 3 (tfim): 2Q depth=31, size=688, time=0.07s\n",
            "[Rustiq] Circuit 4 (all-vib-h2co): 2Q depth=65, size=1058, time=2.91s\n",
            "[Rustiq] Circuit 5 (uuf100-ham): 2Q depth=633, size=6757, time=0.14s\n",
            "[Rustiq] Circuit 6 (uuf100-ham): 2Q depth=795, size=8495, time=0.17s\n",
            "[Rustiq] Circuit 7 (graph-gnp_k-4): 2Q depth=13768, size=139793, time=2.92s\n",
            "[Rustiq] Circuit 8 (uf100-ham): 2Q depth=1099, size=11878, time=0.25s\n",
            "[Rustiq] Circuit 9 (uf100-ham): 2Q depth=911, size=11111, time=0.22s\n",
            "[Rustiq] Circuit 10 (TSP_Ncity-7): 2Q depth=1183, size=13197, time=0.27s\n",
            "[Rustiq] Circuit 11 (all-vib-cyclo_propene): 2Q depth=67, size=2491, time=13.56s\n",
            "[Rustiq] Circuit 12 (TSP_Ncity-8): 2Q depth=1615, size=21358, time=0.48s\n",
            "[Rustiq] Circuit 13 (uf100-ham): 2Q depth=2920, size=40465, time=0.91s\n",
            "[Rustiq] Circuit 14 (tfim): 2Q depth=489, size=6552, time=0.15s\n",
            "[Rustiq] Circuit 15 (flat100-ham): 2Q depth=378, size=5906, time=0.14s\n",
            "[Rustiq] Circuit 16 (graph-regular_reg-4): 2Q depth=12163, size=168679, time=2.94s\n",
            "[Rustiq] Circuit 17 (tfim): 2Q depth=1208, size=17042, time=0.36s\n",
            "[Rustiq] Circuit 18 (FH_D-1): 2Q depth=1061, size=24000, time=0.47s\n",
            "[Rustiq] Circuit 19 (TSP_Ncity-10): 2Q depth=2565, size=41340, time=1.38s\n",
            "[Rustiq] Circuit 20 (TSP_Ncity-10): 2Q depth=2565, size=41275, time=1.38s\n",
            "[Rustiq] Circuit 21 (ham-unary-color02-queen13_13_k-4): 2Q depth=808, size=17548, time=0.42s\n"
          ]
        }
      ],
      "source": [
        "results_large = []\n",
        "\n",
        "tqc_sabre_large = capture_transpilation_metrics(\n",
        "    results_large, pm_sabre, qc_large, \"SABRE\"\n",
        ")\n",
        "tqc_ai_large = capture_transpilation_metrics(\n",
        "    results_large, pm_ai, qc_large, \"AI\"\n",
        ")\n",
        "tqc_rustiq_large = capture_transpilation_metrics(\n",
        "    results_large, pm_rustiq, qc_large, \"Rustiq\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "b7c8d9e0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean +/- std per compilation method\n",
            "Method                2Q Depth              Gate Count             Runtime (s)\n",
            "------------------------------------------------------------------------------\n",
            "SABRE          709.1 +/- 783.8     9,100.5 +/- 8,493.1             0.2 +/- 0.1\n",
            "AI             656.6 +/- 777.5     9,435.6 +/- 8,853.0            8.5 +/- 10.2\n",
            "Rustiq     2,062.5 +/- 3,631.1   26,804.8 +/- 43,403.1             1.3 +/- 2.9\n",
            "\n",
            "Mean % improvement vs SABRE (positive = better than SABRE)\n",
            "Method                2Q Depth              Gate Count             Runtime (s)\n",
            "------------------------------------------------------------------------------\n",
            "AI             +9.6% +/- 22.8%          -3.4% +/- 9.4%    -3620.0% +/- 2405.5%\n",
            "Rustiq      -154.5% +/- 273.9%      -137.1% +/- 233.2%     -527.0% +/- 1405.5%\n"
          ]
        }
      ],
      "source": [
        "print_summary_table(results_large)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "id": "per_circuit_large_code",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "2Q Depth (first 8 circuits by qubit count); * = best\n",
            "Idx  Circuit            Q    SABRE       AI   Rustiq\n",
            "----------------------------------------------------\n",
            "  0  all-vib-hc3h2cn   24       2*       2*       2*\n",
            "  1  ham-graph-gnp_k-  24      345     323*      640\n",
            "  2  TSP_Ncity-5       25      187     161*      408\n",
            "  3  tfim              26      100      20*       31\n",
            "  4  all-vib-h2co      32      30*       38       65\n",
            "  5  uuf100-ham        40      414     391*      633\n",
            "  6  uuf100-ham        40      523     463*      795\n",
            "  7  graph-gnp_k-4     40    3028*     3207    13768\n",
            "\n",
            "Gate Count (first 8 circuits by qubit count); * = best\n",
            "Idx  Circuit            Q    SABRE       AI   Rustiq\n",
            "----------------------------------------------------\n",
            "  0  all-vib-hc3h2cn   24      258      258     257*\n",
            "  1  ham-graph-gnp_k-  24    4036*     4418     5831\n",
            "  2  TSP_Ncity-5       25    2045*     2229     3985\n",
            "  3  tfim              26      489     402*      688\n",
            "  4  all-vib-h2co      32     570*      661     1058\n",
            "  5  uuf100-ham        40    4779*     5130     6757\n",
            "  6  uuf100-ham        40    5667*     6095     8495\n",
            "  7  graph-gnp_k-4     40   24885*    25641   139793\n",
            "\n",
            "Runtime (s) (first 8 circuits by qubit count); * = best\n",
            "Idx  Circuit            Q    SABRE       AI   Rustiq\n",
            "----------------------------------------------------\n",
            "  0  all-vib-hc3h2cn   24     0.16     0.17    0.16*\n",
            "  1  ham-graph-gnp_k-  24    0.08*     3.13     0.13\n",
            "  2  TSP_Ncity-5       25    0.04*     1.47     0.08\n",
            "  3  tfim              26     0.21     0.34    0.07*\n",
            "  4  all-vib-h2co      32    0.18*     0.19     2.91\n",
            "  5  uuf100-ham        40    0.09*     3.27     0.14\n",
            "  6  uuf100-ham        40    0.11*     4.23     0.17\n",
            "  7  graph-gnp_k-4     40    0.39*    15.15     2.92\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print_per_circuit_comparison(results_large, num_rows=8)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "c7d8e9f0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/c7d8e9f0-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plot_transpilation_comparison(\n",
        "    results_large,\n",
        "    \"Large-Scale Hamiltonian Circuits: Compilation Comparison\",\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "id": "pct_improvement_large",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/pct_improvement_large-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plot_pct_improvement_vs_sabre(\n",
        "    results_large,\n",
        "    \"Large-Scale Hamiltonian Circuits\",\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "id": "d7e8f9a0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/d7e8f9a0-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plot_best_method_bars(results_large)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "id": "f7a8b9c0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Test circuit: tfim, 26 qubits\n",
            "\n",
            "Transpilation metrics for circuit index 3:\n",
            "  SABRE     2Q depth=  100  size=   489\n",
            "  AI        2Q depth=   20  size=   402\n",
            "  Rustiq    2Q depth=   31  size=   688\n"
          ]
        }
      ],
      "source": [
        "# Select circuit index 3 from the large-scale transpiled circuits\n",
        "test_idx_large = 3\n",
        "test_circuit_large = qc_large[test_idx_large]\n",
        "print(\n",
        "    f\"Test circuit: {test_circuit_large.name}, {test_circuit_large.num_qubits} qubits\"\n",
        ")\n",
        "\n",
        "tqc_methods_large = {\n",
        "    \"SABRE\": tqc_sabre_large[test_idx_large],\n",
        "    \"AI\": tqc_ai_large[test_idx_large],\n",
        "    \"Rustiq\": tqc_rustiq_large[test_idx_large],\n",
        "}\n",
        "\n",
        "print(f\"\\nTranspilation metrics for circuit index {test_idx_large}:\")\n",
        "for method, tqc in tqc_methods_large.items():\n",
        "    depth_2q = tqc.depth(lambda x: x.operation.num_qubits == 2)\n",
        "    size = tqc.size()\n",
        "    print(f\"  {method:8s}  2Q depth={depth_2q:5d}  size={size:6d}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "id": "3cd3afa2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "SABRE transpiled circuit:\n",
            "OrderedDict({'sx': 211, 'rz': 163, 'cz': 104, 'x': 11})\n",
            "SABRE mirror circuit count ops:\n",
            "OrderedDict({'rz': 1170, 'sx': 422, 'cz': 208, 'measure': 156, 'x': 22, 'barrier': 1})\n",
            "\n",
            "AI transpiled circuit:\n",
            "OrderedDict({'sx': 165, 'rz': 162, 'cz': 68, 'x': 7})\n",
            "AI mirror circuit count ops:\n",
            "OrderedDict({'rz': 984, 'sx': 330, 'measure': 156, 'cz': 136, 'x': 14, 'barrier': 1})\n",
            "\n",
            "Rustiq transpiled circuit:\n",
            "OrderedDict({'sx': 316, 'rz': 225, 'cz': 140, 'x': 7})\n",
            "Rustiq mirror circuit count ops:\n",
            "OrderedDict({'rz': 1714, 'sx': 632, 'cz': 280, 'measure': 156, 'x': 14, 'barrier': 1})\n"
          ]
        }
      ],
      "source": [
        "pm_mirror = generate_preset_pass_manager(\n",
        "    optimization_level=0, backend=backend\n",
        ")\n",
        "\n",
        "for method, tqc in tqc_methods_large.items():\n",
        "    # print the count ops for each circuit\n",
        "    mirror = tqc.copy()\n",
        "    mirror.compose(tqc.inverse(), inplace=True)\n",
        "    mirror.measure_all()\n",
        "    mirror = pm_mirror.run(mirror)\n",
        "    print(f\"\\n{method} transpiled circuit:\")\n",
        "    print(tqc.count_ops())\n",
        "    print(f\"{method} mirror circuit count ops:\")\n",
        "    print(mirror.count_ops())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "id": "large_hw_submit",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "SABRE: submitted job d8gvgq66983c73dqe5og\n",
            "AI: submitted job d8gvgqe6983c73dqe5pg\n",
            "Rustiq: submitted job d8gvgqm6983c73dqe5q0\n"
          ]
        }
      ],
      "source": [
        "# Build mirror circuits and submit to real hardware\n",
        "# The inverse may introduce gates (e.g., sxdg) not in the backend's\n",
        "# basis gate set, so we re-transpile the mirror circuit.\n",
        "pm_mirror = generate_preset_pass_manager(\n",
        "    optimization_level=0, backend=backend\n",
        ")\n",
        "\n",
        "shots_hw = 10000\n",
        "hw_jobs = {}\n",
        "\n",
        "for method, tqc in tqc_methods_large.items():\n",
        "    mirror = tqc.copy()\n",
        "    mirror.compose(tqc.inverse(), inplace=True)\n",
        "    mirror.measure_all()\n",
        "\n",
        "    # Re-transpile at opt level 0 to decompose into basis gates\n",
        "    # without changing the layout or routing\n",
        "    mirror = pm_mirror.run(mirror)\n",
        "\n",
        "    sampler = SamplerV2(mode=backend)\n",
        "    sampler.options.environment.job_tags = [\"TUT_CMHSC\"]\n",
        "    job = sampler.run([mirror], shots=shots_hw)\n",
        "    hw_jobs[method] = job\n",
        "    print(f\"{method}: submitted job {job.job_id()}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "id": "large_hw_results",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "SABRE     P(|00...0>) = 0.0005  (5/10000)\n",
            "AI        P(|00...0>) = 0.3267  (3267/10000)\n",
            "Rustiq    P(|00...0>) = 0.1845  (1845/10000)\n"
          ]
        }
      ],
      "source": [
        "# Retrieve results and compute fidelities\n",
        "fidelities_large = {}\n",
        "\n",
        "for method, job in hw_jobs.items():\n",
        "    result = job.result()\n",
        "    counts = result[0].data.meas.get_counts()\n",
        "\n",
        "    n_qubits = backend.num_qubits\n",
        "    all_zeros = \"0\" * n_qubits\n",
        "    fidelity = counts.get(all_zeros, 0) / shots_hw\n",
        "    fidelities_large[method] = fidelity\n",
        "    print(\n",
        "        f\"{method:8s}  P(|00...0>) = {fidelity:.4f}  \"\n",
        "        f\"({counts.get(all_zeros, 0)}/{shots_hw})\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "id": "large_hw_plot",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/compilation-methods-for-hamiltonian-simulation-circuits/extracted-outputs/large_hw_plot-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plot_mirror_results(\n",
        "    tqc_methods_large, fidelities_large, test_circuit_large.name\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "sec-analysis",
      "metadata": {},
      "source": [
        "<span id=\"analysis-of-compilation-results\" />\n",
        "\n",
        "## Análise dos resultados da compilação\n",
        "\n",
        "Os testes de desempenho acima comparam o SABRE, o transpiler baseado em IA, e o Rustiq em circuitos de simulação hamiltonianos da coleção Hamlib, tanto em pequena quanto em grande escala.\n",
        "\n",
        "<span id=\"two-qubit-depth-and-gate-count\" />\n",
        "\n",
        "### Profundidade de dois qubits e número de portas\n",
        "\n",
        "Em grande escala, o SABRE e o transpiler baseado em IA são os dois que apresentam melhor desempenho, e cada um deles se destaca em um indicador diferente. Conforme mostra o gráfico *de métricas*, o método SABRE apresenta o menor número de portas na grande maioria dos circuitos e é o método mais rápido em quase todos eles, o que está de acordo com uma heurística projetada para minimizar as portas SWAP inseridas e com otimizações recentes em seu layout e roteamento. O transpiler baseado em IA produz a menor profundidade de dois qubits na maioria dos circuitos, o que está de acordo com a parte de seu objetivo de aprendizado por reforço que visa a profundidade do circuito. A tabela resumida reflete a mesma divisão: o SABRE apresenta a menor média de número de portas, enquanto o transpiler de IA apresenta a menor profundidade média de dois qubits. Ambos os métodos são consistentes e confiáveis em toda a gama de circuitos.\n",
        "\n",
        "O Rustiq, que foi desenvolvido especificamente para `PauliEvolutionGate` síntese, produz o melhor resultado em apenas uma pequena fração dos circuitos de grande escala. Suas métricas médias são fortemente distorcidas por alguns poucos valores atípicos significativos, visíveis como grandes picos no gráfico comparativo de compilação, no qual o Rustiq apresenta profundidade e número de portas substancialmente maiores do que os outros métodos. Sem esses valores atípicos, seu desempenho médio estaria muito mais próximo do SABRE e do transpiler baseado em IA.\n",
        "\n",
        "A principal constatação é que nenhum método, por si só, se destaca em todos os circuitos. Cada método apresenta melhor desempenho do que os demais em casos específicos, o que faz com que valha a pena experimentar todas as ferramentas disponíveis e selecionar o melhor resultado para cada circuito.\n",
        "\n",
        "<span id=\"runtime\" />\n",
        "\n",
        "### Tempo de execução\n",
        "\n",
        "O SABRE é, sem dúvida, o método mais rápido. O Rustiq geralmente é executado a uma velocidade semelhante, mas pode apresentar casos atípicos em que a compilação leva muito mais tempo. Isso fica especialmente evidente nos resultados em grande escala, onde alguns circuitos fazem com que o tempo de execução do Rustiq dispare. Esses valores atípicos afetam significativamente o tempo médio de execução; portanto, a mediana pode ser um indicador mais representativo para o Rustiq. O transpiler baseado em IA é o mais lento dos três, com tempo de execução que aumenta significativamente em circuitos maiores e mais complexos.\n",
        "\n",
        "<span id=\"mirror-circuit-results\" />\n",
        "\n",
        "### Resultados do circuito espelhado\n",
        "\n",
        "Os experimentos com circuitos espelho confirmam a tendência esperada: métodos que produzem menor profundidade de dois qubits e menos portas alcançam maior fidelidade em condições de ruído. Isso se aplica tanto ao simulador com ruído (em pequena escala) quanto ao hardware real (em grande escala).\n",
        "\n",
        "Lembre-se de que cada gráfico de circuito espelhado reflete um único circuito, e não o total. O exemplo de hardware acima utiliza um circuito de 26 qubits `tfim` , que, por acaso, é um caso em que o SABRE produz uma profundidade de dois qubits muito maior do que o transpiler baseado em IA e o Rustiq; portanto, sua fidelidade é, consequentemente, muito menor. Isso não é representativo dos resultados gerais: em todo o conjunto de circuitos de grande escala, a profundidade de dois qubits do SABRE costuma ser próxima à do transpiler baseado em IA, e os dois métodos se destacam em métricas diferentes (o transpiler baseado em IA na profundidade de dois qubits, e o SABRE no número de portas e no tempo de execução). Um único resultado de espelhamento testa uma versão duplicada de um circuito, em vez da carga de trabalho completa; portanto, não deve ser interpretado como um veredicto sobre a qualidade geral do método.\n",
        "\n",
        "<span id=\"recommendations\" />\n",
        "\n",
        "### Recomendações\n",
        "\n",
        "Não existe uma única estratégia de transpilagem ideal para todos os circuitos. A melhor escolha depende da estrutura do circuito, do objetivo de otimização e do tempo disponível para compilação:\n",
        "\n",
        "* **O SABRE** é a configuração padrão recomendada. É rápido e confiável, e apresenta excelentes resultados em uma ampla variedade de circuitos. Para um ajuste mais detalhado, os usuários podem aumentar o número de tentativas de layout e roteamento (consulte o [tutorial de otimização do SABRE](/docs/tutorials/transpilation-optimizations-with-sabre) ).\n",
        "* Vale a pena experimentar **o transpiler baseado em IA** quando o tempo de compilação não é uma restrição, especialmente quando a prioridade é minimizar a profundidade de dois qubits: ele produziu a menor profundidade de dois qubits na maioria dos circuitos de grande escala neste teste de desempenho.\n",
        "* **O Rustiq** foi desenvolvido especificamente para `PauliEvolutionGate` circuitos e é capaz de encontrar soluções com profundidade muito baixa e baixo número de portas lógicas, especialmente em circuitos menores. Em circuitos maiores, ele pode, ocasionalmente, gerar resultados muito maiores; por isso, é melhor utilizá-lo como um dos vários métodos a serem testados, em vez de como padrão.\n",
        "\n",
        "Na prática, a melhor abordagem é executar todos os métodos disponíveis e escolher o melhor resultado para cada circuito. A sobrecarga de compilação decorrente da tentativa de vários métodos é pequena em comparação com a melhoria potencial na qualidade da execução em hardware real.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "sec-next-steps",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximas etapas\n",
        "\n",
        "Se você achou este tutorial útil, talvez se interesse pelo seguinte:\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * [Otimizações de transpilação com o SABRE](/docs/tutorials/transpilation-optimizations-with-sabre)\n",
        "  * [O transpiler baseado em IA é aprovado](/docs/guides/ai-transpiler-passes)\n",
        "  * [Criar um plug-in de transpilação](/docs/guides/create-transpiler-plugin)\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "sec-references",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## Referências\n",
        "\n",
        "\\[1] \"\"LightSABRE: Um algoritmo SABRE leve e aprimorado\". H. Zou, M. Treinish, K. Hartman, A. Ivrii, J. Lishman et al. [https://arxiv.org/abs/2409.08368](https://arxiv.org/abs/2409.08368)\n",
        "\n",
        "\\[2] \"Síntese prática e eficiente de circuitos quânticos e transpilação com Reinforcement Learning\". P. Kremer, V. Villar, H. Paik, I. Duran, I. Faro, J. Cruz-Benito et al. [https://arxiv.org/abs/2405.13196](https://arxiv.org/abs/2405.13196)\n",
        "\n",
        "\\[3] “Síntese de circuitos da rede de Pauli com aprendizado por reforço”. R. Dubal, D. Kremer, S. Martiel, V. Villar, D. Wang, J. Cruz-Benito et al. [https://arxiv.org/abs/2503.14448](https://arxiv.org/abs/2503.14448)\n",
        "\n",
        "\\[4] “Síntese mais rápida e mais curta de circuitos de simulação hamiltonianos”. T. Goubault de Brugiere, S. Martiel e outros [ https://arxiv.org/abs/2404.03280](https://arxiv.org/abs/2404.03280)\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"
    },
    "hours": 1,
    "qpuSeconds": 60
  },
  "nbformat": 4,
  "nbformat_minor": 5
}