{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "frontmatter",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Iniciação rápida\"\n",
        "description: \"Guia rápido para a versão mais recente da retropropagação por operadores (OBP)\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "intro",
      "metadata": {},
      "source": [
        "<span id=\"quick-start\" />\n",
        "\n",
        "# Iniciação rápida\n",
        "\n",
        "Este guia apresenta um exemplo mínimo funcional do `qiskit-addon-obp` pacote. Utilizamos a retropropagação de operadores (OBP) para reduzir a profundidade de um circuito quântico, incorporando as portas finais ao observável.\n",
        "\n",
        "Um valor esperado $\\langle O \\rangle = \\langle \\psi | U^\\dagger O U | \\psi \\rangle$ permanece inalterado se retirarmos um bloco de portas no final do circuito $U$ e conjugarmos a observável por ele, classicamente. O OBP aplica esse procedimento repetidamente, avaliando parte do circuito de forma clássica, de modo que apenas um circuito mais simples seja executado no hardware. O preço a pagar é que cada porta absorvida pode expandir o observável em mais termos de Pauli; portanto, a profundidade economizada deve ser ponderada em relação ao aumento do observável.\n",
        "\n",
        "Para ver exemplos de como criar fluxos de trabalho realistas com essa ferramenta e executá-los em hardware quântico, confira os tutoriais na Plataforma de Computação Quântica Aberta ( IBM Quantum Platform, [OBP Tutorial](/docs/tutorials/operator-back-propagation) ).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "inputs-header",
      "metadata": {},
      "source": [
        "<span id=\"prepare-inputs-for-obp\" />\n",
        "\n",
        "## Preparar os dados para o OBP\n",
        "\n",
        "O OBP recebe como entrada uma lista de fatias de circuito e um observável. Ele retropropaga as fatias, uma de cada vez, a partir do final do circuito até o observável, reduzindo a profundidade do circuito à custa de termos de Pauli adicionais no observável. Aqui, geramos um circuito de evolução temporal para um modelo de Heisenberg de 10 qubits e o dividimos por tipo de porta.\n",
        "\n",
        "A seguir, desenhamos o circuito original e, em seguida, o mesmo circuito reorganizado com barreiras que marcam os limites das fatias — cada fatia é uma unidade que pode ser incorporada ao observável em uma única etapa de retropropagação.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "setup-inputs",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Original circuit depth: 18\n",
            "Number of slices: 18\n",
            "Observable terms: 1\n"
          ]
        }
      ],
      "source": [
        "import numpy as np\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.synthesis import LieTrotter\n",
        "from qiskit.transpiler import CouplingMap\n",
        "from qiskit_addon_utils.problem_generators import (\n",
        "    generate_time_evolution_circuit,\n",
        "    generate_xyz_hamiltonian,\n",
        ")\n",
        "from qiskit_addon_utils.slicing import combine_slices, slice_by_gate_types\n",
        "\n",
        "# Generate a circuit to reduce\n",
        "coupling_map = CouplingMap.from_heavy_hex(3, bidirectional=False)\n",
        "reduced_coupling_map = coupling_map.reduce(\n",
        "    [0, 13, 1, 14, 10, 16, 5, 12, 8, 18]\n",
        ")\n",
        "\n",
        "hamiltonian = generate_xyz_hamiltonian(\n",
        "    reduced_coupling_map,\n",
        "    coupling_constants=(np.pi / 8, np.pi / 4, np.pi / 2),\n",
        "    ext_magnetic_field=(np.pi / 3, np.pi / 6, np.pi / 9),\n",
        ")\n",
        "\n",
        "circuit = generate_time_evolution_circuit(\n",
        "    hamiltonian,\n",
        "    time=0.2,\n",
        "    synthesis=LieTrotter(reps=2),\n",
        ")\n",
        "\n",
        "# Slice the circuit and define an observable\n",
        "slices = slice_by_gate_types(circuit)\n",
        "observable = SparsePauliOp(\"IIIIIIIIIZ\")\n",
        "\n",
        "print(f\"Original circuit depth: {circuit.depth()}\")\n",
        "print(f\"Number of slices: {len(slices)}\")\n",
        "print(f\"Observable terms: {len(observable)}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "46efdcfc",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Original circuit:\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-obp/guides/quickstart/extracted-outputs/46efdcfc-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Sliced circuit (recombined with barriers for visualization)\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-obp/guides/quickstart/extracted-outputs/46efdcfc-3.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Recombine the slices with barriers to make the slice boundaries visible\n",
        "sliced_circuit = combine_slices(slices, include_barriers=True)\n",
        "\n",
        "print(\"Original circuit:\")\n",
        "display(circuit.draw(\"mpl\", scale=0.6, fold=-1))\n",
        "print(\"Sliced circuit (recombined with barriers for visualization)\")\n",
        "sliced_circuit.draw(\"mpl\", scale=0.6, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "obp-header",
      "metadata": {},
      "source": [
        "<span id=\"reduce-circuit-depth-with-obp\" />\n",
        "\n",
        "## Reduza a profundidade do circuito com o OBP\n",
        "\n",
        "Chamamos essa função `backpropagate` para incorporar fatias ao observável. A função retorna o observável expandido, as fatias do circuito pelas quais a propagação não ocorreu e os metadados sobre o procedimento.\n",
        "\n",
        "Se não for controlada, a observável pode crescer na direção de termos d $2^n$ -Pauli. Isso `operator_budget` limita esse crescimento — aqui, permitimos, no máximo, 8 grupos comutativos em termos de qubits, o que define, aproximadamente, o número de tentativas necessárias para avaliar o observável na QPU. A retropropagação é interrompida assim que a absorção da próxima fatia exceder o orçamento, que é exatamente o que ocorre a seguir: apenas 7 das 18 fatias são absorvidas antes que o observável preencha todos os 8 grupos comutativos e o procedimento seja interrompido.\n",
        "\n",
        "Para aprofundar a análise do circuito, o argumento de `truncation_error_budget` palavra-chave da função pode `backpropagate` ser usado para eliminar termos de Pauli com coeficientes pequenos do observável à medida que este cresce. Isso atenua o crescimento da grandeza observável em troca de um erro proporcional à magnitude dos termos de Pauli que estão sendo truncados. Os dois orçamentos são complementares e podem ser utilizados em conjunto: `operator_budget` controla a *magnitude* da variável observável, enquanto `truncation_error_budget` controla o *erro* resultante da omissão de termos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "run-obp",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Backpropagated 7 of 18 slices.\n",
            "Reduced circuit depth: 11 (was 18)\n",
            "Observable grew from 1 to 18 Pauli terms.\n",
            "Filled 8 of 8 commuting groups, exhausting the budget.\n"
          ]
        }
      ],
      "source": [
        "from qiskit_addon_obp import backpropagate\n",
        "from qiskit_addon_obp.utils.simplify import OperatorBudget\n",
        "\n",
        "max_qwc_groups = 8\n",
        "bp_obs, remaining_slices, metadata = backpropagate(\n",
        "    observable,\n",
        "    slices,\n",
        "    operator_budget=OperatorBudget(max_qwc_groups=max_qwc_groups),\n",
        ")\n",
        "\n",
        "reduced_circuit = combine_slices(remaining_slices)\n",
        "num_groups = len(bp_obs.group_commuting(qubit_wise=True))\n",
        "\n",
        "print(\n",
        "    f\"Backpropagated {metadata.num_backpropagated_slices} of {len(slices)} slices.\"\n",
        ")\n",
        "print(\n",
        "    f\"Reduced circuit depth: {reduced_circuit.depth()} (was {circuit.depth()})\"\n",
        ")\n",
        "print(f\"Observable grew from {len(observable)} to {len(bp_obs)} Pauli terms.\")\n",
        "print(\n",
        "    f\"Filled {num_groups} of {max_qwc_groups} commuting groups, exhausting the budget.\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "b006625e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/qiskit-addon-obp/guides/quickstart/extracted-outputs/b006625e-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "reduced_circuit.draw(\"mpl\", scale=0.6, fold=-1)"
      ]
    },
    {
      "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
}