{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "4cb32582",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Trabalhe com DAGs em passagens do transpiler\"\n",
        "description: \"Como usar gráficos acíclicos direcionados (DAGs) para analisar e transformar circuitos quânticos nas passagens do transpiler Qiskit\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore subdag DAGOpNode qargs cargs dag_drawer couplinglist */}\n",
        "\n",
        "<span id=\"work-with-dags-in-transpiler-passes\" />\n",
        "\n",
        "# Trabalhe com DAGs em passagens do transpiler\n",
        "\n",
        "No Qiskit, nos estágios de transpilação, os circuitos são representados usando um DAG. Em geral, um DAG é composto de vértices (também conhecidos como \"nós\") e bordas direcionadas que conectam pares de vértices em uma orientação específica. Essa representação é armazenada usando objetos `qiskit.dagcircuit.DAGCircuit` que são compostos de objetos `DagNode` individuais. A vantagem dessa representação em relação a uma lista pura de portas (ou seja, uma lista de rede) é que o fluxo de informações entre as operações é explícito, o que facilita a tomada de decisões de transformação.\n",
        "\n",
        "Este guia demonstra como trabalhar com DAGs e usá-los para escrever passagens personalizadas do transpilador. Ele começará com a construção de um circuito simples e examinará sua representação DAG, depois explorará as operações DAG básicas e implementará uma passagem `BasicMapper` personalizada.\n",
        "\n",
        "<span id=\"build-a-circuit-and-examine-its-dag\" />\n",
        "\n",
        "## Construa um circuito e examine seu DAG\n",
        "\n",
        "O trecho de código abaixo ilustra o DAG criando um circuito simples que prepara um estado Bell e aplica uma rotação $R_Z$, dependendo do resultado da medição.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "version-info-cell",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Versões do pacote\">\n",
        "    O código desta página foi desenvolvido usando os seguintes requisitos.\n",
        "    Recomendamos o uso dessas versões ou de versões mais recentes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "1d16892a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/1d16892a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit\n",
        "from qiskit.converters import circuit_to_dag\n",
        "from qiskit.visualization import circuit_drawer\n",
        "from qiskit.visualization.dag_visualization import dag_drawer\n",
        "\n",
        "# Create circuit\n",
        "q = QuantumRegister(3, \"q\")\n",
        "c = ClassicalRegister(3, \"c\")\n",
        "circ = QuantumCircuit(q, c)\n",
        "circ.h(q[0])\n",
        "circ.cx(q[0], q[1])\n",
        "circ.measure(q[0], c[0])\n",
        "\n",
        "# Qiskit 2.0 uses if_test instead of c_if\n",
        "with circ.if_test((c, 2)):\n",
        "    circ.rz(0.5, q[1])\n",
        "\n",
        "circuit_drawer(circ, output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5971b6ed",
      "metadata": {},
      "source": [
        "No DAG, há três tipos de nós gráficos: nós de entrada de qubit/clbit (verde), nós de operação (azul) e nós de saída (vermelho). Cada borda indica o fluxo de dados (ou dependência) entre dois nós. Use a função qiskit.tools.visualization.dag\\_drawer () para visualizar o DAG desse circuito. (Instale a [biblioteca do Graphviz](https://graphviz.org/download/) para executá-lo.)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "e498faa3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/e498faa3-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Convert to DAG\n",
        "dag = circuit_to_dag(circ)\n",
        "dag_drawer(dag)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b728136",
      "metadata": {},
      "source": [
        "<span id=\"basic-dag-operations\" />\n",
        "\n",
        "## Operações básicas do DAG\n",
        "\n",
        "Os exemplos de código abaixo demonstram operações comuns com DAGs, incluindo acesso a nós, adição de operações e substituição de subcircuitos. Essas operações formam a base para a criação de passagens de transpiladores.\n",
        "\n",
        "<span id=\"get-all-operation-nodes-in-the-dag\" />\n",
        "\n",
        "## Obter todos os nós de operação no DAG\n",
        "\n",
        "O método `op_nodes()` retorna uma lista iterável de objetos `DAGOpNode` no circuito:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "4f848695",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[DAGOpNode(op=Instruction(name='h', num_qubits=1, num_clbits=0, params=[]), qargs=(<Qubit register=(3, \"q\"), index=0>,), cargs=()),\n",
              " DAGOpNode(op=Instruction(name='cx', num_qubits=2, num_clbits=0, params=[]), qargs=(<Qubit register=(3, \"q\"), index=0>, <Qubit register=(3, \"q\"), index=1>), cargs=()),\n",
              " DAGOpNode(op=Instruction(name='measure', num_qubits=1, num_clbits=1, params=[]), qargs=(<Qubit register=(3, \"q\"), index=0>,), cargs=(<Clbit register=(3, \"c\"), index=0>,)),\n",
              " DAGOpNode(op=Instruction(name='if_else', num_qubits=1, num_clbits=3, params=[<qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7f703fe0bd50>, None]), qargs=(<Qubit register=(3, \"q\"), index=1>,), cargs=(<Clbit register=(3, \"c\"), index=0>, <Clbit register=(3, \"c\"), index=1>, <Clbit register=(3, \"c\"), index=2>))]"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "dag.op_nodes()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8f2676b9",
      "metadata": {},
      "source": [
        "Cada nó é uma instância da classe `DAGOpNode` :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "5866159f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "node name: if_else\n",
            "op: Instruction(name='if_else', num_qubits=1, num_clbits=3, params=[<qiskit.circuit.quantumcircuit.QuantumCircuit object at 0x7f703facdb10>, None])\n",
            "qargs: (<Qubit register=(3, \"q\"), index=1>,)\n",
            "cargs: (<Clbit register=(3, \"c\"), index=0>, <Clbit register=(3, \"c\"), index=1>, <Clbit register=(3, \"c\"), index=2>)\n",
            "condition: (ClassicalRegister(3, 'c'), 2)\n"
          ]
        }
      ],
      "source": [
        "node = dag.op_nodes()[3]\n",
        "print(\"node name:\", node.name)\n",
        "print(\"op:\", node.op)\n",
        "print(\"qargs:\", node.qargs)\n",
        "print(\"cargs:\", node.cargs)\n",
        "print(\"condition:\", node.op.condition)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f2560cc1",
      "metadata": {},
      "source": [
        "<span id=\"add-an-operation-to-the-back\" />\n",
        "\n",
        "## Adicionar uma operação à parte traseira\n",
        "\n",
        "Uma operação é adicionada ao final do DAGCircuit usando o método `apply_operation_back()` . Isso acrescenta a porta especificada para atuar nos qubits fornecidos após todas as operações existentes no circuito.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "3c144b49",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/3c144b49-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit.library import HGate\n",
        "\n",
        "dag.apply_operation_back(HGate(), qargs=[q[0]])\n",
        "dag_drawer(dag)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "80af1d3d",
      "metadata": {},
      "source": [
        "<span id=\"add-an-operation-to-the-front\" />\n",
        "\n",
        "## Adicionar uma operação à frente\n",
        "\n",
        "Uma operação é adicionada ao início do DAGCircuit usando o método `apply_operation_front()` . Isso insere a porta especificada antes de todas as operações existentes no circuito, tornando-a efetivamente a primeira operação executada.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "ed80a69f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/ed80a69f-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit.library import CCXGate\n",
        "\n",
        "dag.apply_operation_front(CCXGate(), qargs=[q[0], q[1], q[2]])\n",
        "dag_drawer(dag)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4bcdf5fe",
      "metadata": {},
      "source": [
        "<span id=\"substitute-a-node-with-a-subcircuit\" />\n",
        "\n",
        "## Substitua um nó por um subcircuito\n",
        "\n",
        "Um nó que representa uma operação específica no DAGCircuit é substituído por um subcircuito. Primeiro, um novo sub-DAG é construído com a sequência desejada de portas e, em seguida, o nó de destino é substituído por esse sub-DAG usando `substitute_node_with_dag()`, preservando as conexões com o restante do circuito.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "fdb3dd70",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/fdb3dd70-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.dagcircuit import DAGCircuit\n",
        "from qiskit.circuit.library import CHGate, U2Gate, CXGate\n",
        "\n",
        "# Build sub-DAG\n",
        "mini_dag = DAGCircuit()\n",
        "p = QuantumRegister(2, \"p\")\n",
        "mini_dag.add_qreg(p)\n",
        "mini_dag.apply_operation_back(CHGate(), qargs=[p[1], p[0]])\n",
        "mini_dag.apply_operation_back(U2Gate(0.1, 0.2), qargs=[p[1]])\n",
        "\n",
        "# Replace CX with mini_dag\n",
        "cx_node = dag.op_nodes(op=CXGate).pop()\n",
        "dag.substitute_node_with_dag(cx_node, mini_dag, wires=[p[0], p[1]])\n",
        "dag_drawer(dag)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "028566f7",
      "metadata": {},
      "source": [
        "Após a conclusão de todas as transformações, o DAG pode ser convertido novamente em um objeto `QuantumCircuit` normal. É assim que o pipeline do transpilador funciona. Um circuito é obtido, processado na forma de DAG, e um circuito transformado é produzido como saída.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "786571f7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/786571f7-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.converters import dag_to_circuit\n",
        "\n",
        "new_circ = dag_to_circuit(dag)\n",
        "circuit_drawer(new_circ, output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f743bb3b",
      "metadata": {},
      "source": [
        "<span id=\"implement-a-basicmapper-pass\" />\n",
        "\n",
        "## Implementar uma passagem “ BasicMapper ”\n",
        "\n",
        "A estrutura do DAG pode ser aproveitada para escrever passagens do transpilador. No exemplo abaixo, uma passagem `BasicMapper` é implementada para mapear um circuito arbitrário em um dispositivo com conectividade de qubit restrita. Para obter orientação adicional, consulte o guia sobre [como escrever passes de transpiladores personalizados](/docs/guides/custom-transpiler-pass).\n",
        "\n",
        "O passe é definido como um `TransformationPass`, o que significa que ele modifica o circuito. Ele faz isso percorrendo o DAG camada por camada, verificando se cada instrução satisfaz as restrições impostas pelo mapa de acoplamento do dispositivo. Se uma violação for detectada, um caminho de troca é determinado e as portas SWAP necessárias são inseridas de acordo.\n",
        "\n",
        "Ao criar uma passagem de transpilador, a primeira decisão envolve selecionar se a passagem deve herdar de `TransformationPass` ou `AnalysisPass`. As passagens de transformação são projetadas para modificar o circuito, enquanto as passagens de análise destinam-se apenas a extrair informações para uso em passagens subsequentes. A funcionalidade principal é então implementada no método `run(dag)` . Por fim, o passe deve ser registrado no módulo `qiskit.transpiler.passes` .\n",
        "\n",
        "Nessa passagem específica, o DAG é percorrido camada por camada (em que cada camada contém operações que agem em conjuntos de qubits separados e, portanto, podem ser executadas independentemente). Para cada operação, se as restrições do mapa de acoplamento não forem atendidas, um caminho de troca adequado é identificado e as trocas necessárias são inseridas para colocar os qubits envolvidos em adjacência.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "8c0d7e5a",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler.basepasses import TransformationPass\n",
        "from qiskit.transpiler import Layout\n",
        "from qiskit.circuit.library import SwapGate\n",
        "\n",
        "\n",
        "class BasicSwap(TransformationPass):\n",
        "    def __init__(self, coupling_map, initial_layout=None):\n",
        "        super().__init__()\n",
        "        self.coupling_map = coupling_map\n",
        "        self.initial_layout = initial_layout\n",
        "\n",
        "    def run(self, dag):\n",
        "        new_dag = DAGCircuit()\n",
        "        for qreg in dag.qregs.values():\n",
        "            new_dag.add_qreg(qreg)\n",
        "        for creg in dag.cregs.values():\n",
        "            new_dag.add_creg(creg)\n",
        "\n",
        "        if self.initial_layout is None:\n",
        "            self.initial_layout = Layout.generate_trivial_layout(\n",
        "                *dag.qregs.values()\n",
        "            )\n",
        "\n",
        "        current_layout = self.initial_layout.copy()\n",
        "\n",
        "        for layer in dag.serial_layers():\n",
        "            subdag = layer[\"graph\"]\n",
        "            for gate in subdag.two_qubit_ops():\n",
        "                q0, q1 = gate.qargs\n",
        "                p0 = current_layout[q0]\n",
        "                p1 = current_layout[q1]\n",
        "\n",
        "                if self.coupling_map.distance(p0, p1) != 1:\n",
        "                    path = self.coupling_map.shortest_undirected_path(p0, p1)\n",
        "                    for i in range(len(path) - 2):\n",
        "                        wire1, wire2 = path[i], path[i + 1]\n",
        "                        qubit1 = current_layout[wire1]\n",
        "                        qubit2 = current_layout[wire2]\n",
        "                        new_dag.apply_operation_back(\n",
        "                            SwapGate(), qargs=[qubit1, qubit2]\n",
        "                        )\n",
        "                        current_layout.swap(wire1, wire2)\n",
        "\n",
        "            new_dag.compose(\n",
        "                subdag, qubits=current_layout.reorder_bits(new_dag.qubits)\n",
        "            )\n",
        "\n",
        "        return new_dag"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4a95eaab",
      "metadata": {},
      "source": [
        "A passagem pode agora ser testada em um pequeno circuito de exemplo. Um gerenciador de passes é construído com o passe recém-definido incluído. O circuito de exemplo é então fornecido a esse gerenciador de passagem, e um circuito novo e transformado é obtido como saída.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "2f35375f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/DAG-representation/extracted-outputs/2f35375f-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import CouplingMap, PassManager\n",
        "from qiskit import QuantumRegister, QuantumCircuit\n",
        "\n",
        "q = QuantumRegister(7, \"q\")\n",
        "in_circ = QuantumCircuit(q)\n",
        "in_circ.h(q[0])\n",
        "in_circ.cx(q[0], q[4])\n",
        "in_circ.cx(q[2], q[3])\n",
        "in_circ.cx(q[6], q[1])\n",
        "in_circ.cx(q[5], q[0])\n",
        "in_circ.rz(0.1, q[2])\n",
        "in_circ.cx(q[5], q[0])\n",
        "\n",
        "coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]\n",
        "coupling_map = CouplingMap(couplinglist=coupling)\n",
        "\n",
        "pm = PassManager()\n",
        "pm.append(BasicSwap(coupling_map))\n",
        "\n",
        "out_circ = pm.run(in_circ)\n",
        "\n",
        "in_circ.draw(output=\"mpl\")\n",
        "out_circ.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "56b80ce3",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * Consulte o guia sobre como criar uma [etapa personalizada do transpiler](/docs/guides/custom-transpiler-pass)\n",
        "  * Saiba como [criar e compilar para back-ends personalizados](/docs/guides/custom-backend)\n",
        "  * Experimente o guia [Comparar configurações do transpiler](/docs/guides/circuit-transpilation-settings).\n",
        "  * Consulte [a documentação da API do Circuito DAG](/docs/api/qiskit/dagcircuit).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}