{
  "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 propagação de Pauli\"\n",
        "---\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a9320fa8-31c5-4248-96b0-3549a13dda6f",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Iniciação rápida\"\n",
        "description: \"Um guia de início rápido para o pacote de complementos pauli-prop do Qiskit\"\n",
        "---\n",
        "\n",
        "<span id=\"quickstart\" />\n",
        "\n",
        "# Iniciação rápida\n",
        "\n",
        "Neste guia, utilizamos o pacote `pauli-prop` para simular, de forma clássica, a dinâmica temporal de um modelo de Ising com 10 qubits e efeito “kicked” em uma cadeia de spins do tipo “ 1D ”.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3b5bf7dc-1cd8-41d3-b8ce-cc75a66fed8d",
      "metadata": {},
      "source": [
        "<span id=\"prepare-the-inputs-for-pauli-propagation\" />\n",
        "\n",
        "## Prepare os dados de entrada para a propagação de Pauli\n",
        "\n",
        "O hamiltoniano considerado é:\n",
        "\n",
        "$H = -J\\sum\\limits_{\\langle i,j \\rangle} Z_iZ_j + h\\sum\\limits_iX_i$\n",
        "\n",
        "onde $J>0$ descreve o acoplamento entre os spins vizinhos mais próximos, $i<j$, e $h$ é o campo transversal global. Uma decomposição de Trotter de primeira ordem do operador evoluído no tempo será implementada como um circuito quântico, $U$, ao longo de $20$ etapas de Trotter. A constante de acoplamento, $J$, será fixada em $J=-\\frac{\\pi}{2}$, e $h$ será fixada em $\\frac{\\pi}{6}$. As interações $ZZ$ serão implementadas utilizando portas de Clifford ( $CX$, $Sdg$, $\\sqrt{Y}$ ).\n",
        "\n",
        "Implementamos a evolução temporal de Trotter como um circuito quântico e utilizamos a função “ $\\frac{\\pi}{6}$ ” para as rotações não-Clifford em torno do eixo x. Quanto mais esses ângulos se afastarem dos ângulos de Clifford (por exemplo, $\\theta=n\\frac{\\pi}{2}, n \\in \\mathbb{Z}$ ), mais difícil será simular o sistema utilizando métodos de propagação de Pauli.\n",
        "\n",
        "Para a escolha da grandeza observável, consideramos a magnetização média de um único sítio, $\\frac{1}{N} \\sum_{i=1}^{N} \\langle z_i \\rangle$, onde $N$ é o número de spins.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "15d5eccf-eef0-4435-b67a-98a8038c400e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/pauli-prop/guides/quickstart/extracted-outputs/15d5eccf-eef0-4435-b67a-98a8038c400e-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import numpy as np\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.transpiler import CouplingMap\n",
        "\n",
        "num_qubits = 10\n",
        "coupling_map = CouplingMap.from_line(num_qubits, bidirectional=False)\n",
        "\n",
        "# Num Trotter steps\n",
        "num_steps = 20\n",
        "theta_rx = np.pi / 6\n",
        "\n",
        "# Average single-site magnetization\n",
        "observable = (\n",
        "    SparsePauliOp(\n",
        "        [\n",
        "            \"I\" * iq + \"Z\" + \"I\" * (num_qubits - iq - 1)\n",
        "            for iq in range(num_qubits)\n",
        "        ]\n",
        "    )\n",
        "    / num_qubits\n",
        ")\n",
        "\n",
        "# Create the Trotter circuit\n",
        "num_qubits = 10\n",
        "num_steps = 20\n",
        "theta_rx = np.pi / 6\n",
        "circuit = QuantumCircuit(num_qubits)\n",
        "edges = CouplingMap.from_line(num_qubits, bidirectional=False).get_edges()\n",
        "for _ in range(num_steps):\n",
        "    circuit.rx(theta_rx, [i for i in range(num_qubits)])\n",
        "    for edge in edges:\n",
        "        circuit.sdg(edge)\n",
        "        circuit.ry(np.pi / 2, edge[1])\n",
        "        circuit.cx(edge[0], edge[1])\n",
        "        circuit.ry(-np.pi / 2, edge[1])\n",
        "circuit.draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c05fa0f8-605e-4172-8880-0de89360f27d",
      "metadata": {},
      "source": [
        "<span id=\"simulate-the-time-evolution-of-the-system-with-pauli-propagation\" />\n",
        "\n",
        "## Simule a evolução temporal do sistema com a propagação de Pauli\n",
        "\n",
        "Assim que tivermos nosso circuito, $U$, e nossa observável, $O$, podemos simular facilmente o sistema em algumas etapas:\n",
        "\n",
        "* Separe $U$ em suas partes Clifford, $C$, e não-Clifford, $P$, de modo que $U=PC$ utilizando `evolve_through_cliffords`\n",
        "* Propague $O$ por meio de $P$, resultando em um novo operador, $O^\\prime$, utilizando `pauli_prop.propagate_through_circuit`\n",
        "* Evolua um $O^\\prime$ o na parte do circuito relacionada ao Clifford, utilizando o suporte à evolução do Clifford integrado ao Qiskit\n",
        "* Aproxime o valor esperado como $\\langle0|O^\\prime|0\\rangle \\approx \\langle0|U^\\dagger OU|0\\rangle$, somando os coeficientes em $O^\\prime$ associados aos termos de Pauli totalmente diagonais (termos de Pauli que contêm ou `I` `Z` em todos os qubits). Lembre-se de que essa é uma aproximação, pois truncamos termos de $O^\\prime$ à medida que o propagávamos pela parte não-Clifford do circuito.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "c8a27469-ab72-4d50-9544-d446af847da5",
      "metadata": {},
      "outputs": [],
      "source": [
        "import time\n",
        "\n",
        "from pauli_prop import evolve_through_cliffords, propagate_through_circuit\n",
        "\n",
        "cliff, non_cliff = evolve_through_cliffords(circuit)\n",
        "\n",
        "max_terms_list = [10**i for i in range(8)]\n",
        "approx_evs = []\n",
        "durations = []\n",
        "for max_terms in max_terms_list:\n",
        "    st = time.perf_counter()\n",
        "    evolved_obs = propagate_through_circuit(\n",
        "        observable, non_cliff, max_terms=max_terms, atol=1e-12, frame=\"h\"\n",
        "    )[0]\n",
        "    evolved_obs.paulis = evolved_obs.paulis.evolve(cliff, frame=\"h\")\n",
        "    durations.append(time.perf_counter() - st)\n",
        "    approx_evs.append(\n",
        "        float(evolved_obs.coeffs[~evolved_obs.paulis.x.any(axis=1)].sum())\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7fb3e72f-20fb-4fd0-a301-2fcc6c0ddad5",
      "metadata": {},
      "source": [
        "À medida que realizamos cálculos mais complexos, as aproximações do valor esperado tornam-se mais precisas. Neste exemplo, saturamos todo o espaço de Pauli em torno de $4^{10}\\approx10^6$, o que se reflete no achatamento da curva entre os dois últimos pontos.\n",
        "\n",
        "Embora o gráfico abaixo mostre uma convergência monotônica, as simulações de propagação de Pauli geralmente não convergem de forma monotônica. Não é incomum observar um comportamento “irregular” nesse tipo de gráfico.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "f12410aa-ef3b-4ee6-ab35-f7e9001a92b8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Text(0.5, 1.0, 'Simulating 20-step 1D Ising Model')"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/addons/pauli-prop/guides/quickstart/extracted-outputs/f12410aa-ef3b-4ee6-ab35-f7e9001a92b8-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "from qiskit_aer import AerSimulator\n",
        "\n",
        "sim_circ = circuit.copy()\n",
        "sim_circ.save_statevector()\n",
        "backend = AerSimulator(method=\"statevector\")\n",
        "psi = backend.run(sim_circ).result().data()[\"statevector\"]\n",
        "exact_ev = psi.expectation_value(observable)\n",
        "\n",
        "ax1 = plt.gca()\n",
        "ax1.plot(max_terms_list, approx_evs, marker=\"o\", label=\"Approximate\")\n",
        "ax1.axhline(exact_ev, linestyle=\"--\", color=\"green\", label=\"Exact\")\n",
        "ax1.set_xscale(\"log\")\n",
        "ax1.set_xlabel(\"# terms kept\")\n",
        "ax1.set_ylabel(r\"$\\frac{1}{N} \\sum_{i=1}^{N} \\langle z_i \\rangle$\")\n",
        "\n",
        "ax2 = ax1.twinx()\n",
        "ax2.plot(\n",
        "    max_terms_list, durations, marker=\".\", label=\"Runtime\", color=\"orange\"\n",
        ")\n",
        "ax2.set_ylabel(\"Runtime (s)\", color=\"orange\")\n",
        "ax2.set_yscale(\"log\")\n",
        "\n",
        "handles1, labels1 = ax1.get_legend_handles_labels()\n",
        "handles2, labels2 = ax2.get_legend_handles_labels()\n",
        "ax1.legend(handles1 + handles2, labels1 + labels2, loc=\"lower right\")\n",
        "\n",
        "plt.title(f\"Simulating {num_steps}-step 1D Ising Model\")"
      ]
    },
    {
      "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
}