{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "ba5ec3d7-2a51-4ffa-b270-cbe18e98a454",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Transpiler com tecnologia de IA aprovado\"\n",
        "description: \"O que são as passagens do transpiler de IA e como usá-las\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Eprint */}\n",
        "\n",
        "<span id=\"ai-powered-transpiler-passes\" />\n",
        "\n",
        "# Transpiler com tecnologia de IA aprovado\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3c78c2c0-7afc-4cf3-988d-9e044b5d0fca",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7244dd08-62a0-4c10-8c0d-0bd01eebe68f",
      "metadata": {},
      "source": [
        "As etapas de transpilagem baseadas em IA são etapas que funcionam como um substituto direto das etapas “tradicionais” do Qiskit para algumas tarefas de transpilagem. Frequentemente, eles produzem melhores resultados do que os algoritmos heurísticos existentes (como menor profundidade e menor contagem de CNOT), mas também são muito mais rápidos do que algoritmos de otimização, como os solucionadores de satisfatibilidade booleana. O transpiler de IA é executado no seu ambiente local.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Os passes do transpilador acionado por IA estão em status de versão beta, sujeitos a alterações.\n",
        "  Se tiver comentários ou quiser entrar em contato com a equipe de desenvolvedores, use este [canal do Qiskit Slack Workspace](https://qiskit.slack.com/archives/C06KF8YHUAU).\n",
        "</Admonition>\n",
        "\n",
        "Os seguintes passes estão disponíveis no momento:\n",
        "\n",
        "**Passes de roteamento**\n",
        "\n",
        "* `AIRouting`: Seleção de layout e roteamento de circuitos\n",
        "\n",
        "**A síntese de circuitos passa**\n",
        "\n",
        "* `AICliffordSynthesis`: Síntese de circuitos Clifford\n",
        "* `AILinearFunctionSynthesis`: Síntese de circuitos de função linear\n",
        "* `AIPermutationSynthesis`: Síntese de circuitos de permutação\n",
        "\n",
        "Para usar as etapas do transpiler de IA, instale primeiro o `qiskit-ibm-transpiler` pacote. Consulte a [documentação da API do qiskit-ibm-transpiler](/docs/api/qiskit-ibm-transpiler) para obter mais informações sobre as diferentes opções disponíveis.\n",
        "\n",
        "```sh\n",
        "pip install qiskit-ibm-transpiler\n",
        "```\n",
        "\n",
        "<span id=\"ai-routing-pass\" />\n",
        "\n",
        "## Passe de roteamento de IA\n",
        "\n",
        "A passagem `AIRouting` atua como um estágio de layout e um estágio de roteamento. Ele pode ser usado em um `PassManager` da seguinte forma:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "c104fcd0-4a85-4927-b026-93f4a6fdab51",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import PassManager\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "from qiskit_ibm_transpiler.ai.routing import AIRouting\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "import logging\n",
        "\n",
        "backend = QiskitRuntimeService().backend(\"ibm_fez\")\n",
        "ai_passmanager = PassManager(\n",
        "    [\n",
        "        AIRouting(\n",
        "            backend=backend,\n",
        "            optimization_level=2,\n",
        "            layout_mode=\"optimize\",\n",
        "        )\n",
        "    ]\n",
        ")\n",
        "\n",
        "\n",
        "circuit = efficient_su2(101, entanglement=\"circular\", reps=1)\n",
        "logging.getLogger(\n",
        "    \"qiskit_ibm_transpiler.wrappers.ai_local_synthesis\"\n",
        ").setLevel(logging.WARNING)\n",
        "transpiled_circuit = ai_passmanager.run(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "28c2cfa3-e4d8-48d5-9d6c-b02fcf548ef1",
      "metadata": {},
      "source": [
        "Aqui, o `backend` determina qual mapa de acoplamento deve ser roteado, o `optimization_level` (1, 2 ou 3) determina o esforço computacional a ser despendido no processo (um valor mais alto geralmente oferece melhores resultados, mas leva mais tempo) e o `layout_mode` especifica como lidar com a seleção do layout.\n",
        "O site `layout_mode` inclui as seguintes opções:\n",
        "\n",
        "* `keep`: Respeita o layout definido pelas passagens anteriores do transpilador (ou usa o layout trivial se não estiver definido). Normalmente, ele só é usado quando o circuito precisa ser executado em qubits específicos do dispositivo. Geralmente produz resultados piores porque tem menos espaço para otimização.\n",
        "* `improve`: Usa o layout definido pelas passagens anteriores do transpilador como ponto de partida. É útil quando você tem uma boa estimativa inicial do layout; por exemplo, para circuitos que são construídos de uma forma que segue aproximadamente o mapa de acoplamento do dispositivo. Também é útil se você quiser experimentar outros passes de layout específicos combinados com o passe `AIRouting` .\n",
        "* `optimize`: Esse é o modo padrão. Ele funciona melhor para circuitos gerais em que você pode não ter boas estimativas de layout. Esse modo ignora as seleções de layout anteriores.\n",
        "\n",
        "<span id=\"ai-circuit-synthesis-passes\" />\n",
        "\n",
        "## A síntese do circuito de IA é aprovada\n",
        "\n",
        "Os passes de síntese de circuitos de IA permitem que você otimize peças de diferentes tipos de circuitos ([Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford), [Função Linear](/docs/api/qiskit/qiskit.circuit.library.LinearFunction), [Permutação](/docs/api/qiskit/qiskit.circuit.library.Permutation#permutation), Rede Pauli) ao sintetizá-los novamente. Uma maneira típica de usar a passagem de síntese é a seguinte:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "8655f68d-f88a-4a15-ad89-f39f2ba3fe71",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import PassManager\n",
        "\n",
        "from qiskit_ibm_transpiler.ai.routing import AIRouting\n",
        "from qiskit_ibm_transpiler.ai.synthesis import AILinearFunctionSynthesis\n",
        "from qiskit_ibm_transpiler.ai.collection import CollectLinearFunctions\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "ibm_kingston = QiskitRuntimeService().backend(\"ibm_kingston\")\n",
        "ai_passmanager = PassManager(\n",
        "    [\n",
        "        AIRouting(\n",
        "            backend=ibm_kingston,\n",
        "            optimization_level=3,\n",
        "            layout_mode=\"optimize\",\n",
        "            local_mode=True,\n",
        "        ),  # Route circuit\n",
        "        CollectLinearFunctions(),  # Collect Linear Function blocks\n",
        "        AILinearFunctionSynthesis(\n",
        "            backend=ibm_kingston, local_mode=True\n",
        "        ),  # Re-synthesize Linear Function blocks\n",
        "    ]\n",
        ")\n",
        "\n",
        "circuit = efficient_su2(10, entanglement=\"full\", reps=1)\n",
        "\n",
        "transpiled_circuit = ai_passmanager.run(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "779f180e-c29f-4a96-b4b0-e3d2a4c8a1b9",
      "metadata": {},
      "source": [
        "A síntese respeita o mapa de acoplamento do dispositivo: ela pode ser executada com segurança após outras passagens de roteamento sem perturbar o circuito, de modo que o circuito geral ainda seguirá as restrições do dispositivo. Por padrão, a síntese substituirá o subcircuito original somente se o subcircuito sintetizado melhorar o original (atualmente, verificando apenas a contagem de CNOT), mas isso pode ser forçado a sempre substituir o circuito definindo `replace_only_if_better=False`.\n",
        "\n",
        "Os seguintes passes de síntese estão disponíveis em `qiskit_ibm_transpiler.ai.synthesis`:\n",
        "\n",
        "* *AICliffordSynthesis* : Síntese para circuitos [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford) (blocos de portas `H`, `S` e `CX` ). Atualmente, até nove blocos de qubit.\n",
        "* *AILinearFunctionSynthesis* : Síntese para circuitos de [função linear](/docs/api/qiskit/qiskit.circuit.library.LinearFunction) (blocos de `CX` e `SWAP` gates). Atualmente, até nove blocos de qubit.\n",
        "* *AIPermutationSynthesis* : Síntese para circuitos [de permutação](/docs/api/qiskit/qiskit.circuit.library.Permutation#permutation) (blocos de `SWAP` gates). Atualmente disponível para blocos de 65, 33 e 27 qubits.\n",
        "* *AIPauliNetworkSynthesis* : Síntese para circuitos de rede Pauli (blocos de portas `H`, `S`, `SX`, `CX`, `RX`, `RY` e `RZ` ). Atualmente, até seis blocos de qubit.\n",
        "\n",
        "Esperamos aumentar gradualmente o tamanho dos blocos suportados.\n",
        "\n",
        "Todos os passes usam um pool de threads para enviar várias solicitações em paralelo. Por padrão, o número máximo de threads é o número de núcleos mais quatro (valores padrão para o objeto `ThreadPoolExecutor` Python ). No entanto, você pode definir seu próprio valor com o argumento `max_threads` na instanciação do passe. Por exemplo, a linha a seguir instancia a passagem `AILinearFunctionSynthesis` , o que permite que ela use um máximo de 20 threads.\n",
        "\n",
        "```python\n",
        "AILinearFunctionSynthesis(backend=ibm_torino, max_threads=20)  # Re-synthesize Linear Function blocks using 20 threads max\n",
        "```\n",
        "\n",
        "Você também pode definir a variável de ambiente `AI_TRANSPILER_MAX_THREADS` como o número desejado de threads máximos, e todas as passagens de síntese instanciadas depois disso usarão esse valor.\n",
        "\n",
        "Para que as passagens de síntese de IA sintetizem um subcircuito, ele deve estar em um subgráfico conectado do mapa de acoplamento (uma maneira de fazer isso é com uma passagem de roteamento antes de coletar os blocos, mas essa não é a única maneira de fazer isso). Os passes de síntese verificarão automaticamente se o subgrafo específico é compatível e, se não for, emitirão um aviso e deixarão o subcircuito original inalterado.\n",
        "\n",
        "Os seguintes passes de coleção personalizados para Cliffords, Funções Lineares e Permutações que podem ser importados do site `qiskit_ibm_transpiler.ai.collection` também complementam os passes de síntese:\n",
        "\n",
        "* *CollectCliffords* : Coleta blocos Clifford como objetos `Instruction` e armazena o subcircuito original para compará-lo após a síntese.\n",
        "* *CollectLinearFunctions* : Coleta blocos de `SWAP` e `CX` como objetos `LinearFunction` e armazena o subcircuito original para comparar com ele após a síntese.\n",
        "* *CollectPermutations* : Coleta blocos de circuitos `SWAP` como `Permutations`.\n",
        "* *CollectPauliNetworks* : Coleta blocos de rede Pauli e armazena o subcircuito original para comparar com ele após a síntese.\n",
        "\n",
        "Esses passes de coleta personalizados limitam os tamanhos dos subcircuitos coletados para que sejam compatíveis com os passes de síntese com tecnologia de IA. Portanto, recomenda-se usá-los após as passagens de roteamento e antes das passagens de síntese para uma melhor otimização geral.\n",
        "\n",
        "<span id=\"hybrid-heuristic-ai-circuit-transpilation\" />\n",
        "\n",
        "## Transpilação híbrida de circuitos heurísticos-IA\n",
        "\n",
        "O site `qiskit-ibm-transpiler` permite que você configure um gerenciador de passes híbrido que combina o melhor da heurística do Qiskit e os passes do transpilador com tecnologia de IA. Esse recurso se comporta de forma semelhante ao método do Qiskit `generate_pass_manager` . Uma maneira típica de usar o site `generate_ai_pass_manager` é a seguinte:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "2f5bbf22-22cd-46fa-885c-851f769552f0",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_transpiler import generate_ai_pass_manager\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "\n",
        "backend = QiskitRuntimeService().backend(\"ibm_kingston\")\n",
        "kingston_coupling_map = backend.coupling_map\n",
        "\n",
        "\n",
        "su2_circuit = efficient_su2(101, entanglement=\"circular\", reps=1)\n",
        "\n",
        "ai_transpiler_pass_manager = generate_ai_pass_manager(\n",
        "    coupling_map=kingston_coupling_map,\n",
        "    ai_optimization_level=3,\n",
        "    optimization_level=3,\n",
        "    ai_layout_mode=\"optimize\",\n",
        ")\n",
        "\n",
        "ai_su2_transpiled_circuit = ai_transpiler_pass_manager.run(su2_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7f34294b-c520-439a-b1d7-2962af07aced",
      "metadata": {},
      "source": [
        "As opções a seguir são usadas neste exemplo:\n",
        "\n",
        "* `coupling_map` - Especifica o mapa de acoplamento a ser usado para a transpilação.\n",
        "* `ai_optimization_level` - Especifica o nível de otimização (1-3) a ser usado para os componentes de IA do site PassManager.\n",
        "* `optimization_level` - Especifica a quantidade de otimização a ser executada no circuito para os componentes heurísticos do site PassManager.\n",
        "* `ai_layout_mode` - Especifica como a parte de roteamento de IA do site PassManager lida com o layout. Consulte a seção de [passagem de roteamento de IA](#ai-routing-pass) para analisar as opções de configuração desse parâmetro `ai_layout_mode` .\n",
        "\n",
        "<span id=\"citation\" />\n",
        "\n",
        "## Citação\n",
        "\n",
        "Citação\n",
        "Caso utilize qualquer recurso baseado em IA do `qiskit-ibm-transpiler` pacote em sua pesquisa, utilize a seguinte citação recomendada:\n",
        "\n",
        "```\n",
        "@misc{2405.13196,\n",
        "Author = {David Kremer and Victor Villar and Hanhee Paik and Ivan Duran and Ismael Faro and Juan Cruz-Benito},\n",
        "Title = {Practical and efficient quantum circuit synthesis and transpiling with Reinforcement Learning},\n",
        "Year = {2024},\n",
        "Eprint = {arXiv:2405.13196},\n",
        "}\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}