{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "a10c2a41-ab48-4da5-bbe1-a16fd47906fe",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Transição de fase de Nishimori\"\n",
        "description: \"Este tutorial demonstra como realizar uma transição de fase Nishimori em um processador quântico IBM.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Verresen Layden Tantivasadakarn Vishwanath Trebst */}\n",
        "\n",
        "<span id=\"nishimori-phase-transition\" />\n",
        "\n",
        "# Transição de fase de Nishimori\n",
        "\n",
        "*Estimativa de tempo de execução: 3 minutos em um processador Heron r2 (NOTA: Trata-se apenas de uma estimativa.) (O tempo de execução pode variar.)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6113a1ff-5cc0-433a-afd7-5aadc97bb28f",
      "metadata": {},
      "source": [
        "<span id=\"learning-outcomes\" />\n",
        "\n",
        "## Resultados do aprendizado\n",
        "\n",
        "Após concluir este tutorial, os usuários devem esperar os seguintes resultados:\n",
        "\n",
        "* Compreender a transição de fase de Nishimori e como ela se manifesta como o surgimento de entrelaçamento de longo alcance no modelo de Ising com ligações aleatórias.\n",
        "* Implementar o protocolo *de* geração de entrelaçamento por medição (GEM) em hardware quântico, utilizando medições no meio do circuito e circuitos de profundidade constante.\n",
        "* Caracterize a transição por meio da extração da correlação de dois pontos e da variância normalizada da magnetização a partir dos dados experimentais.\n",
        "\n",
        "<span id=\"prerequisites\" />\n",
        "\n",
        "## Pré-requisitos\n",
        "\n",
        "Recomendamos que você esteja familiarizado com os seguintes tópicos antes de seguir com este tutorial:\n",
        "\n",
        "* O guia [sobre qubits de medição](/docs/guides/measure-qubits), em especial a seção sobre medição no meio do circuito, na qual o protocolo GEM se baseia.\n",
        "* [Simulação exata e com ruído utilizando primitivas do Qiskit Aer](/docs/guides/simulate-with-qiskit-aer), que é como a seção em pequena escala é executada.\n",
        "* [Entrelaciamento de longo alcance com circuitos dinâmicos](/docs/tutorials/long-range-entanglement), um tutorial complementar que utiliza o mesmo paradigma de entrelaciamento baseado em medição.\n",
        "* [Rede hexagonal pesada](https://www.ibm.com/quantum/blog/heavy-hex-lattice), a topologia de hardware do “ IBM® ” na qual a rede de plaquetas se baseia.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "838ac5c7-0819-4482-8875-c57db88ba82a",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## Segundo plano\n",
        "\n",
        "Este tutorial demonstra como realizar uma transição de fase de Nishimori em um processador quântico. Este experimento foi descrito originalmente no artigo [*“Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits*](https://arxiv.org/abs/2309.02863) ”.\n",
        "\n",
        "A transição de fase de Nishimori refere-se à transição entre as fases ordenadas de curto e longo alcance no modelo de Ising com ligações aleatórias. Em um computador quântico, a fase ordenada de longo alcance se manifesta como um estado no qual os qubits estão entrelaçados em todo o dispositivo. Esse estado altamente entrelaçado é preparado por meio do protocolo *de* geração de entrelaçamento por medição (GEM). Ao utilizar medições no meio do circuito, o protocolo GEM é capaz de entrelaçar qubits em todo o dispositivo utilizando circuitos de profundidade constante. Este tutorial utiliza a implementação do protocolo GEM do pacote de software [GEM Suite](https://github.com/qiskit-community/gem-suite).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4091005d-ecd5-40c9-b90f-263e49a4cc16",
      "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 v1.0 ou posterior, com suporte [para visualização](/docs/api/qiskit/visualization)\n",
        "* Qiskit Runtime v0.22 ou posterior (`pip install qiskit-ibm-runtime`)\n",
        "* Qiskit Aer v0.14 ou versão posterior (`pip install qiskit-aer`)\n",
        "* GEM Suite (`pip install gem-suite`)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "210b8730-ca3e-46d9-b8b0-64c36f13df8e",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Instalação\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "4ad70734-54f8-400a-8399-188ee8a0f3ac",
      "metadata": {},
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "import warnings\n",
        "\n",
        "from collections import defaultdict\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_aer import AerSimulator\n",
        "\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "from gem_suite import PlaquetteLattice\n",
        "from gem_suite.experiments import GemExperiment"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "281ec87e-3f50-44b6-8e6f-a906b92fba74",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-simulator-example\" />\n",
        "\n",
        "## Exemplo de simulador em pequena escala\n",
        "\n",
        "`AerSimulator`Nesta seção, é apresentado passo a passo todo o fluxo de trabalho no noiseless. A rede de plaquetas é restrita a uma única plaqueta (12 qubits), de modo que a simulação permanece pequena e rápida, ao mesmo tempo em que abrange todas as etapas do protocolo GEM: medição no meio do circuito, varredura do ângulo de $R_{ZZ}$, decodificação e análise da variância normalizada. Posteriormente, esse mesmo fluxo de trabalho é ampliado para várias plaquetas e para toda a rede em hardware real.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "39f59f3a-eb2a-4160-9da2-2bb83c58771c",
      "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",
        "O protocolo GEM opera em um processador quântico cuja conectividade entre qubits é descrita por uma rede. Os processadores “ IBM Quantum® ” atuais utilizam a [rede hexagonal pesada](https://www.ibm.com/quantum/blog/heavy-hex-lattice). Os qubits no processador são agrupados em *plaquetas,* dependendo da célula unitária da rede que ocupam. Como um qubit pode ocorrer em mais de uma célula unitária, as plaquetas não são disjuntas. Na rede hexagonal densa, uma plaqueta contém 12 qubits. As próprias plaquetas também formam redes, nas quais duas plaquetas estão conectadas se compartilharem quaisquer qubits. Na rede hexagonal pesada, as plaquetas vizinhas compartilham três qubits.\n",
        "\n",
        "No pacote de software GEM Suite, a classe fundamental para a implementação do protocolo GEM é `PlaquetteLattice`, que representa a rede de plaquetas (que é distinta da rede de hexágonos pesados). A `PlaquetteLattice` pode ser inicializada a partir de um mapa de acoplamento de qubits. Atualmente, apenas mapas de acoplamento do tipo “heavy-hex” são suportados.\n",
        "\n",
        "A célula de código a seguir inicializa uma rede de plaquetas a partir do mapa de acoplamento de uma unidade de processamento quântico (QPU). A malha de placas nem sempre abrange todo o hardware. Por exemplo, `ibm_torino` possui 133 qubits no total, mas a maior rede de plaquetas que cabe no dispositivo utiliza apenas 125 deles, compreendendo 18 plaquetas; `ibm_pittsburgh` (156 qubits) também acomoda 144 qubits em 21 plaquetas. O mesmo padrão se aplica a outras QPUs com hexágonos pesados e números diferentes de qubits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "553dbafe-1778-4971-83c3-0408605b701d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"<YOUR_API_KEY>\", overwrite=True,\n",
        "# set_as_default=True)\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")\n",
        "aer_backend = AerSimulator.from_backend(backend)\n",
        "plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)\n",
        "\n",
        "print(f\"Number of qubits in backend: {backend.num_qubits}\")\n",
        "print(\n",
        "    f\"Number of qubits in plaquette lattice: {len(list(plaquette_lattice.qubits()))}\"\n",
        ")\n",
        "print(f\"Number of plaquettes: {len(list(plaquette_lattice.plaquettes()))}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0bf43539-d782-44a9-ba4e-a1b6c7510803",
      "metadata": {},
      "source": [
        "Você pode visualizar a rede de plaquetas gerando um diagrama de sua representação gráfica. No diagrama, as plaquetas são representadas por hexágonos rotulados, e duas plaquetas são conectadas por uma borda se compartilharem qubits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "625882a4-faeb-4d96-b441-c989f43c4dea",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/625882a4-faeb-4d96-b441-c989f43c4dea-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "plaquette_lattice.draw_plaquettes()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2f0a6b73-d1d2-4117-80cf-6fe3adbb82c5",
      "metadata": {},
      "source": [
        "Você pode recuperar informações sobre plaquetas individuais, como os qubits que elas contêm, usando o método `plaquettes` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "e412a612-c7d5-4689-840a-2383dd538f06",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "PyPlaquette(index=0, qubits=[3, 4, 5, 6, 7, 16, 17, 23, 24, 25, 26, 27], neighbors=[4, 3, 1])"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Get a list of the plaquettes\n",
        "plaquettes = list(plaquette_lattice.plaquettes())\n",
        "# Display information about plaquette 0\n",
        "plaquettes[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "75edf1b4-f95f-4ff7-9e3c-2e810711636f",
      "metadata": {},
      "source": [
        "Você também pode produzir um diagrama dos qubits subjacentes que formam a rede de plaquetas.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "a19d63ce-3572-4081-a008-c1332fbbe303",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/a19d63ce-3572-4081-a008-c1332fbbe303-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "plaquette_lattice.draw_qubits()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e7b0f54b-5bc2-42bb-b4d4-1346f0a902e3",
      "metadata": {},
      "source": [
        "Além dos rótulos dos qubits e das bordas que indicam quais qubits estão conectados, o diagrama contém três informações adicionais que são relevantes para o protocolo GEM:\n",
        "\n",
        "* Cada qubit é sombreado (cinza) ou não sombreado. Os qubits sombreados são qubits de \"local\" que representam os locais do modelo de Ising, e os qubits não sombreados são qubits de \"ligação\" usados para mediar as interações entre os qubits de local.\n",
        "* Cada qubit de local é rotulado como (A) ou (B), indicando uma das duas funções que um qubit de local pode desempenhar no protocolo GEM (as funções são explicadas posteriormente).\n",
        "* Cada aresta é colorida com uma das seis cores, dividindo assim as arestas em seis grupos. Essa divisão determina como as portas de dois qubits podem ser paralelizadas, bem como os diferentes padrões de agendamento que provavelmente resultarão em diferentes níveis de erro em um processador quântico sujeito a ruído. Como as arestas de um grupo são disjuntas, é possível aplicar uma camada de portas de dois qubits nessas arestas simultaneamente. De fato, é possível dividir as seis cores em três grupos de duas cores, de modo que a união de cada grupo de duas cores continue sendo disjunta. Portanto, são necessárias apenas três camadas de portas de dois qubits para ativar cada borda. Existem 12 maneiras de dividir as seis cores dessa forma, e cada uma dessas divisões resulta em uma programação de portas de três camadas diferente.\n",
        "\n",
        "Agora que você criou uma rede de plaquetas, o próximo passo é inicializar um `GemExperiment` objeto, passando tanto a rede de plaquetas quanto o backend no qual você pretende executar o experimento. A `GemExperiment` classe gerencia a implementação propriamente dita do protocolo GEM, incluindo a geração de circuitos, o envio de tarefas e a análise dos dados. A célula de código a seguir inicializa a classe de experimento, restringindo a rede de plaquetas a uma única plaqueta (12 qubits), o que mantém a simulação pequena e rápida. A rede completa de plaquetas é utilizada posteriormente, na hora de fazer a transição para o hardware real.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "02357c6e-5c83-4ac0-811d-22602d9f33d5",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/02357c6e-5c83-4ac0-811d-22602d9f33d5-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Filter the plaquette lattice down to a single plaquette (12 qubits)\n",
        "# so the AerSimulator run stays fast. The full lattice is used later\n",
        "# in the large-scale hardware example.\n",
        "gem_exp = GemExperiment(plaquette_lattice.filter([9]), backend=aer_backend)\n",
        "\n",
        "# visualize the plaquette lattice after filtering\n",
        "plaquette_lattice.filter([9]).draw_qubits()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3234e018-a1a8-47b7-b10c-57d6f7f77ff1",
      "metadata": {},
      "source": [
        "Um circuito de protocolo GEM é construído usando as seguintes etapas:\n",
        "\n",
        "1. Prepare o estado $|+\\rangle$ aplicando uma porta Hadamard a cada qubit.\n",
        "2. Aplique uma porta “ $R_{ZZ}$ ” entre cada par de qubits conectados. Você pode fazer isso usando três camadas de portas. Cada porta “ $R_{ZZ}$ ” atua sobre um qubit de local e um qubit de ligação. Se o qubit de local for identificado com (B), o ângulo é fixado em $\\frac{\\pi}{2}$. Se o qubit de local for identificado com (A), o ângulo pode variar, gerando circuitos diferentes. Por padrão, o intervalo de ângulos é definido como 21 pontos igualmente espaçados entre $0$ e $\\frac{\\pi}{2}$, inclusive.\n",
        "3. Meça cada qubit de ligação na base de Pauli $X$. Como os qubits são medidos na base de Pauli $Z$, é possível fazer isso aplicando uma porta de Hadamard antes de medir o qubit.\n",
        "\n",
        "Observe que o documento citado na introdução deste tutorial usa uma convenção diferente para o ângulo $R_{ZZ}$, que difere da convenção usada neste tutorial por um fator de 2.\n",
        "\n",
        "Na terceira etapa, apenas os qubits de ligação são medidos. Para compreender em que estado os qubits de site permanecem, é esclarecedor considerar o caso em que o ângulo de $R_{ZZ}$ o aplicado aos qubits de site (A) na segunda etapa seja igual a $\\frac{\\pi}{2}$. Nesse caso, os qubits de site permanecem em um estado altamente entrelaçado, semelhante ao estado GHZ,\n",
        "\n",
        "$$\n",
        "\\lvert \\text{GHZ} \\rangle = \\lvert 00 \\cdots 00 \\rangle + \\lvert 11 \\cdots 11 \\rangle.\n",
        "$$\n",
        "\n",
        "Devido à aleatoriedade nos resultados das medições, o estado real dos qubits do sistema pode ser um estado diferente com ordem de longo alcance, por exemplo, $\\lvert 00110 \\rangle + \\lvert 11001 \\rangle$. No entanto, o estado GHZ pode ser recuperado por meio da aplicação de uma operação de decodificação baseada nos resultados das medições. Quando o ângulo “ $R_{ZZ}$ ” é reduzido a partir de $\\frac{\\pi}{2}$, a ordem de longo alcance ainda pode ser recuperada até um ângulo crítico, que, na ausência de ruído, é aproximadamente $0.3 \\pi$. Abaixo desse ângulo, o estado resultante não apresenta mais entrelaçamento de longo alcance. Essa transição entre a presença e a ausência de ordem de longo alcance é a transição de fase de Nishimori.\n",
        "\n",
        "Na descrição acima, os qubits do sistema não foram medidos, e a operação de decodificação pode ser realizada por meio da aplicação de portas quânticas. No experimento, tal como implementado no pacote GEM, os qubits do local são de fato medidos, e a operação de decodificação é aplicada em uma etapa clássica de pós-processamento.\n",
        "\n",
        "Na descrição acima, a operação de decodificação pode ser realizada por meio da aplicação de portas quânticas aos qubits do local, a fim de recuperar o estado quântico. No entanto, se o objetivo for medir imediatamente o estado (por exemplo, para fins de caracterização), é possível medir os qubits de sítio juntamente com os qubits de ligação e aplicar a operação de decodificação em uma etapa clássica de pós-processamento.\n",
        "\n",
        "Além de depender do ângulo de $R_{ZZ}$, na etapa dois — que, por padrão, varia entre 21 valores —, o circuito do protocolo GEM também depende do padrão de agendamento utilizado para implementar as três camadas de portas de $R_{ZZ}$. Conforme discutido anteriormente, existem 12 desses padrões de programação. Portanto, o número total de circuitos no experimento é $21 \\times 12 = 252$ o.\n",
        "\n",
        "Os circuitos do experimento podem ser gerados usando o `circuits` método da `GemExperiment` classe.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "8e2ade62-9a57-42c3-9a85-3fe2dec3c426",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total number of circuits: 252\n"
          ]
        }
      ],
      "source": [
        "circuits = gem_exp.circuits()\n",
        "print(f\"Total number of circuits: {len(circuits)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "56c3c656-dcfa-4ca0-9df9-2d97c187c685",
      "metadata": {},
      "source": [
        "Para os fins deste tutorial, basta considerar apenas um único padrão de agendamento. A célula de código a seguir restringe o experimento ao primeiro padrão de agendamento. Como resultado, o experimento tem apenas 21 circuitos, um para cada ângulo de $R_{ZZ}$ varrido.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "4f8a2c73-752d-47b9-95d5-83439933fc08",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total number of circuits: 21\n",
            "RZZ angles:\n",
            "[0.         0.07853982 0.15707963 0.23561945 0.31415927 0.39269908\n",
            " 0.4712389  0.54977871 0.62831853 0.70685835 0.78539816 0.86393798\n",
            " 0.9424778  1.02101761 1.09955743 1.17809725 1.25663706 1.33517688\n",
            " 1.41371669 1.49225651 1.57079633]\n"
          ]
        }
      ],
      "source": [
        "# Restrict experiment to the first scheduling pattern\n",
        "gem_exp.set_experiment_options(schedule_idx=0)\n",
        "\n",
        "# There are less circuits now\n",
        "circuits = gem_exp.circuits()\n",
        "print(f\"Total number of circuits: {len(circuits)}\")\n",
        "\n",
        "# Print the RZZ angles swept over\n",
        "print(f\"RZZ angles:\\n{gem_exp.parameters()}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7011dc79-8561-42ef-909b-00fd8be9ef34",
      "metadata": {},
      "source": [
        "A célula de código a seguir desenha um diagrama do circuito no índice 5. Para reduzir o tamanho do diagrama, as portas de medição no final do circuito foram removidas.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "fd57d483-c70b-4ad5-b309-15750ad38bac",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/fd57d483-c70b-4ad5-b309-15750ad38bac-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Get the circuit at index 5\n",
        "circuit = circuits[5]\n",
        "# Remove the final measurements to ease visualization\n",
        "circuit.remove_final_measurements()\n",
        "# Draw the circuit\n",
        "circuit.draw(\"mpl\", fold=-1, scale=0.5)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a3aa063b-44cf-49f3-9e12-23b2f6a1c85b",
      "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",
        "A transpilagem de circuitos quânticos para execução em hardware geralmente envolve [várias etapas](/docs/guides/transpiler-stages). Normalmente, as etapas que exigem maior carga computacional são a escolha do layout dos qubits, o roteamento das portas de dois qubits para se adequarem à conectividade dos qubits do hardware e a otimização do circuito para minimizar o número de portas e a profundidade. No protocolo GEM, as etapas de layout e roteamento são desnecessárias, pois a conectividade do hardware já está incorporada ao projeto do protocolo. Os circuitos já possuem um layout de qubits, e as portas de dois qubits já estão mapeadas nas conexões nativas. Além disso, para preservar a estrutura do circuito à medida que o ângulo $R_{ZZ}$ é alterado, deve-se realizar apenas uma otimização muito básica do circuito.\n",
        "\n",
        "A classe `GemExperiment` transpila circuitos de forma transparente ao executar o experimento. Os estágios de layout e roteamento já são substituídos por padrão para não fazer nada, e a otimização do circuito é realizada em um nível que otimiza apenas portas de um único qubit. No entanto, você pode substituir ou passar opções adicionais usando o método `set_transpile_options` . Para fins de visualização, a célula de código a seguir transpila manualmente o circuito exibido anteriormente e desenha o circuito transpilado.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "e9b99d48-8d33-46b5-bff5-480ab1c1c1f2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/e9b99d48-8d33-46b5-bff5-480ab1c1c1f2-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Demonstrate setting transpile options\n",
        "gem_exp.set_transpile_options(\n",
        "    optimization_level=1  # This is the default optimization level\n",
        ")\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    backend=aer_backend,\n",
        "    initial_layout=list(gem_exp.physical_qubits),\n",
        "    **dict(gem_exp.transpile_options),\n",
        ")\n",
        "transpiled = pass_manager.run(circuit)\n",
        "transpiled.draw(\"mpl\", idle_wires=False, fold=-1, scale=0.5)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8d0dcd59-54ef-4af8-9213-0784ef94b838",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "### Passo 3: Execute usando Qiskit primitives\n",
        "\n",
        "Para executar os circuitos do protocolo GEM no hardware, chame o método `run` do objeto `GemExperiment` . Você pode especificar o número de fotos que deseja amostrar de cada circuito. O método `run` retorna um objeto [ExperimentData](https://qiskit-community.github.io/qiskit-experiments/stubs/qiskit_experiments.framework.ExperimentData.html) que você deve salvar em uma variável. Observe que o método `run` somente envia trabalhos sem esperar que eles terminem, portanto, é uma chamada sem bloqueio.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "6171a383-dd58-4e3f-88aa-bbec7b5870df",
      "metadata": {},
      "outputs": [],
      "source": [
        "exp_data = gem_exp.run(shots=10_000)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "71e81552-0d33-4950-8d45-e6c0a8a056c9",
      "metadata": {},
      "source": [
        "Para aguardar os resultados, chame o método `block_for_results` do objeto `ExperimentData` . Essa chamada fará com que o interpretador fique suspenso até que os trabalhos sejam concluídos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "ed14a067-35ba-4ffc-8534-4ae5ec6bc4c9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "ExperimentData(GemExperiment, 90bf2a90-f729-4c4e-a6da-664aecb11039, job_ids=['04a7c405-47fd-46ca-aa4b-aaf7e339cfbe'], metadata=<5 items>, figure_names=['two_point_correlation.svg', 'normalized_variance.svg', 'plaquette_ops.svg', 'bond_ops.svg'])"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# The noiseless AerSimulator produces zero-variance UFloat objects in the\n",
        "# analysis, which triggers a harmless warning from the `uncertainties`\n",
        "# library. Suppress it so the output stays clean.\n",
        "with warnings.catch_warnings():\n",
        "    warnings.filterwarnings(\n",
        "        \"ignore\", message=\"Using UFloat objects with std_dev==0\"\n",
        "    )\n",
        "    exp_data.block_for_results()\n",
        "exp_data"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "36e0570b-f091-45f2-bb83-143edbc3b433",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-result-in-desired-classical-format\" />\n",
        "\n",
        "### Etapa 4: Pós-processamento e retorno do resultado no formato clássico desejado\n",
        "\n",
        "Em um ângulo de $R_{ZZ}$ de $\\frac{\\pi}{2}$, o estado decodificado seria o estado GHZ na ausência de ruído. A ordem de longo alcance do estado GHZ pode ser visualizada plotando a magnetização das cadeias de bits medidas. A magnetização $M$ é definida como a soma dos operadores de Pauli $Z$ de um único qubit,\n",
        "\n",
        "$$\n",
        "M = \\sum_{j=1}^N Z_j,\n",
        "$$\n",
        "\n",
        "onde $N$ é o número de qubits do sistema. Seu valor, para uma sequência de bits, é igual à diferença entre o número de zeros e o número de uns. A medição do estado GHZ resulta, com igual probabilidade, no estado de zeros ou no estado de uns; portanto, a magnetização estaria em $+N$ na metade do tempo e em $-N$ na outra metade do tempo. Na presença de erros causados por ruído, outros valores também apareceriam, mas, se o ruído não for muito intenso, a distribuição ainda atingiria seu pico próximo a $+N$ e $-N$.\n",
        "\n",
        "Para as cadeias de bits brutas antes da decodificação, a distribuição da magnetização seria equivalente à de cadeias de bits uniformemente aleatórias, na ausência de ruído.\n",
        "\n",
        "A célula de código a seguir representa a magnetização das cadeias de bits brutas e as cadeias de bits decodificadas no ângulo $R_{ZZ}$ de $\\frac{\\pi}{2}$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "8ead3582-16df-4616-836c-bdce867ad6b8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Text(0.5, 1.0, 'Magnetization distribution with and without decoding')"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/8ead3582-16df-4616-836c-bdce867ad6b8-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "def magnetization_distribution(\n",
        "    counts_dict: dict[str, int],\n",
        ") -> dict[str, float]:\n",
        "    \"\"\"Compute magnetization distribution from counts dictionary.\"\"\"\n",
        "    # Construct dictionary from magnetization to count\n",
        "    mag_dist = defaultdict(float)\n",
        "    for bitstring, count in counts_dict.items():\n",
        "        mag = bitstring.count(\"0\") - bitstring.count(\"1\")\n",
        "        mag_dist[mag] += count\n",
        "    # Normalize\n",
        "    shots = sum(counts_dict.values())\n",
        "    for mag in mag_dist:\n",
        "        mag_dist[mag] /= shots\n",
        "    return mag_dist\n",
        "\n",
        "\n",
        "# Get counts dictionaries with and without decoding\n",
        "data = exp_data.data()\n",
        "# Get the last data point, which is at the angle for the GHZ state\n",
        "raw_counts = data[-1][\"counts\"]\n",
        "# Without decoding\n",
        "site_indices = [\n",
        "    i for i, q in enumerate(gem_exp.plaquettes.qubits()) if q.role == \"Site\"\n",
        "]\n",
        "site_raw_counts = defaultdict(int)\n",
        "for key, val in raw_counts.items():\n",
        "    site_str = \"\".join(key[-1 - i] for i in site_indices)\n",
        "    site_raw_counts[site_str] += val\n",
        "# With decoding\n",
        "_, site_decoded_counts = gem_exp.plaquettes.decode_outcomes(\n",
        "    raw_counts, return_counts=True\n",
        ")\n",
        "\n",
        "# Compute magnetization distribution\n",
        "raw_magnetization = magnetization_distribution(site_raw_counts)\n",
        "decoded_magnetization = magnetization_distribution(site_decoded_counts)\n",
        "\n",
        "# Plot\n",
        "plt.bar(*zip(*raw_magnetization.items()), label=\"raw\")\n",
        "plt.bar(*zip(*decoded_magnetization.items()), label=\"decoded\", width=0.3)\n",
        "plt.legend()\n",
        "plt.xlabel(\"Magnetization\")\n",
        "plt.ylabel(\"Frequency\")\n",
        "plt.title(\"Magnetization distribution with and without decoding\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "90a7ae7a-5175-421f-bda9-bc6b986bdf5f",
      "metadata": {},
      "source": [
        "Para caracterizar com mais rigor a ordem de longo alcance, você pode examinar a correlação média de dois pontos $f$, definida como\n",
        "\n",
        "$$\n",
        "f = \\frac{1}{N^2} \\left(\\langle M^2 \\rangle - \\langle M \\rangle ^2\\right).\n",
        "$$\n",
        "\n",
        "Um valor mais alto indica um grau maior de emaranhamento. A classe `GemExperiment` calcula automaticamente esse valor para as cadeias de bits decodificadas como parte do processamento dos dados experimentais. Ele armazena uma figura que pode ser acessada pelo método `figure` da classe de dados do experimento. Nesse caso, o nome da figura é `two_point_correlation`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "4ecb25c8-e572-49af-a879-9943039db131",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/4ecb25c8-e572-49af-a879-9943039db131-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "exp_data.figure(\"two_point_correlation\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f2f3e7e2-2a8b-4790-8ba7-b190c4ed1049",
      "metadata": {},
      "source": [
        "Para determinar o ponto crítico da transição de fase de Nishimori, você pode observar a variação normalizada de $M^2 / N$, definida como\n",
        "\n",
        "$$\n",
        "g = \\frac{1}{N^3} \\left(\\langle M^4 \\rangle - \\langle M^2 \\rangle^2\\right),\n",
        "$$\n",
        "\n",
        "que quantifica a quantidade de flutuação na magnetização ao quadrado. Esse valor é maximizado no ponto crítico da transição de fase de Nishimori. Na ausência de ruído, o ponto crítico ocorre aproximadamente em $0.3 \\pi$. Na presença de ruído, o ponto crítico é deslocado para cima, mas a transição de fase ainda é observada, desde que o ponto crítico ocorra abaixo de $0.5 \\pi$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "2b351d68-3924-445a-94ef-047b16214e8a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/2b351d68-3924-445a-94ef-047b16214e8a-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "exp_data.figure(\"normalized_variance\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a94e0cbe-8429-487c-b203-50a8b2eacee3",
      "metadata": {},
      "source": [
        "<span id=\"large-scale-hardware-example\" />\n",
        "\n",
        "## Exemplo de hardware em grande escala\n",
        "\n",
        "Depois de validar o protocolo em um simulador, agora você pode ampliar a escala do experimento e executá-lo no hardware quântico real selecionado na seção “[Configuração](#setup) ”. Este exemplo utiliza dois problemas de maior dimensão:\n",
        "\n",
        "* **Seis plaquetas (cerca de 49 qubits)** : uma série de tamanho médio que já mostra o deslocamento para a direita do ponto crítico sob ruído de hardware.\n",
        "* **A malha completa de plaquetas** : todas as plaquetas que a topologia “heavy-hex” do dispositivo suporta (por exemplo, 18 plaquetas / 125 qubits em `ibm_torino` ou 21 plaquetas / 144 qubits em `ibm_pittsburgh`), entrelaçando qubits em todo o dispositivo com circuitos de profundidade constante.\n",
        "\n",
        "A célula de código única abaixo é autônoma: ela constrói a rede de plaquetas a partir do mapa de acoplamento do backend e executa ambos os experimentos; portanto, esta seção pode ser executada após as células [de configuração,](#setup) sem a necessidade de executar primeiro a seção em pequena escala.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "08581c09-a6a5-4a56-9fc4-abf22b063c6a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Total number of circuits (full lattice): 21\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-2.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-3.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# -------------------------Step 1-------------------------\n",
        "# Initialize the runtime service, pick a real quantum hardware backend,\n",
        "# and build the plaquette lattice from its coupling map. This is repeated\n",
        "# from the small-scale example so this cell can run standalone after the\n",
        "# Setup section. The full plaquette lattice is the \"large-scale\" target;\n",
        "# a six-plaquette subset (range(3, 9)) is also used to show an intermediate\n",
        "# scaling step.\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")\n",
        "plaquette_lattice = PlaquetteLattice.from_coupling_map(backend.coupling_map)\n",
        "\n",
        "# Build a GemExperiment for the full plaquette lattice and one for the\n",
        "# six-plaquette subset, each restricted to a single scheduling pattern so\n",
        "# the experiment has one circuit per RZZ angle (21 circuits total).\n",
        "gem_exp_full = GemExperiment(plaquette_lattice, backend=backend)\n",
        "gem_exp_full.set_experiment_options(schedule_idx=0)\n",
        "gem_exp_6 = GemExperiment(\n",
        "    plaquette_lattice.filter(range(3, 9)), backend=backend\n",
        ")\n",
        "gem_exp_6.set_experiment_options(schedule_idx=0)\n",
        "\n",
        "circuits = gem_exp_full.circuits()\n",
        "print(f\"Total number of circuits (full lattice): {len(circuits)}\")\n",
        "\n",
        "# -------------------------Step 2-------------------------\n",
        "# GemExperiment transpiles internally for the target backend: the layout\n",
        "# and routing stages are overridden because the plaquette lattice already\n",
        "# matches the hardware connectivity, and optimization is restricted so the\n",
        "# RZZ angle structure is preserved. The code below manually transpiles one\n",
        "# circuit from the six-plaquette experiment with the same settings this\n",
        "# experiment will use, and draws it for inspection. (The full-lattice\n",
        "# transpiled circuit has too many qubits to visualize cleanly, so the\n",
        "# six-plaquette circuit is used here as a representative example.)\n",
        "gem_exp_6.set_transpile_options(optimization_level=1)\n",
        "circuits_6 = gem_exp_6.circuits()\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend,\n",
        "    initial_layout=list(gem_exp_6.physical_qubits),\n",
        "    **dict(gem_exp_6.transpile_options),\n",
        ")\n",
        "transpiled = pass_manager.run(circuits_6[5])\n",
        "display(transpiled.draw(\"mpl\", idle_wires=False, fold=-1, scale=0.5))\n",
        "\n",
        "# -------------------------Step 3-------------------------\n",
        "# Run both problem sizes on real hardware:\n",
        "#   1. Six plaquettes (~49 qubits) — an intermediate scale-up.\n",
        "#   2. The full plaquette lattice — every plaquette the device supports.\n",
        "exp_data_6 = gem_exp_6.run(shots=10_000, job_tags=[\"TUT_NPT\"])\n",
        "exp_data_full = gem_exp_full.run(shots=10_000, job_tags=[\"TUT_NPT\"])\n",
        "exp_data_6.block_for_results()\n",
        "exp_data_full.block_for_results()\n",
        "\n",
        "# -------------------------Step 4-------------------------\n",
        "# Plot the normalized variance at each scale. The peak marks the critical\n",
        "# point of the Nishimori transition; as the system grows, hardware noise\n",
        "# shifts the peak rightward.\n",
        "display(exp_data_6.figure(\"normalized_variance\"))\n",
        "exp_data_full.figure(\"normalized_variance\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "da03c8eb-5ec5-4c9c-8eb7-d44c5948b43c",
      "metadata": {},
      "source": [
        "Observe que, dependendo do nível de ruído do backend utilizado, as curvas de variância normalizada em tamanhos maiores podem não apresentar um pico nítido dentro da faixa de ângulo varrida. Nas simulações acima, o pico foi empurrado até o valor de $0.5 \\pi$, que corresponde à borda direita do intervalo de variação (conforme os relatórios `critical_angle = 0.5000` de análise tanto para as simulações com seis plaquetas quanto para as de rede completa). Isso significa que o ruído do hardware deslocou o ponto crítico para (ou um pouco além) do limite do intervalo de ângulos fisicamente significativo do protocolo; portanto, a transição ocorre no limite do que essa varredura é capaz de resolver.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6abd9701-58e4-43a8-a1d7-279506570de4",
      "metadata": {},
      "source": [
        "<span id=\"conclusion\" />\n",
        "\n",
        "## Conclusão\n",
        "\n",
        "Neste tutorial, você realizou uma transição de fase de Nishimori em um processador quântico utilizando o protocolo GEM. As métricas que você analisou durante o pós-processamento — em particular, a correlação de dois pontos e a variância normalizada — servem como parâmetros de referência para avaliar a capacidade do dispositivo de gerar estados entrelaçados de longo alcance. Esses testes de desempenho ampliam a utilidade do protocolo GEM para além da investigação de fenômenos físicos interessantes. Como parte do protocolo, você entrelaçou qubits em todo o dispositivo utilizando circuitos de profundidade constante. Essa conquista só é possível graças ao uso de medições no meio do circuito pelo protocolo. Nesta experiência, o estado entrelaçado foi medido imediatamente, mas considere a possibilidade de aprofundar a pesquisa utilizando esse estado em outros processos quânticos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "717f22c6-4945-4719-b9ba-ae44cde58da8",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  Se você achou este trabalho interessante, talvez se interesse pelo material a seguir:\n",
        "\n",
        "  * [Entrelacamento de longo alcance com circuitos dinâmicos](/docs/tutorials/long-range-entanglement)\n",
        "  * [Códigos de repetição](/docs/tutorials/repetition-codes)\n",
        "  * [Feedforward clássico e fluxo de controle](/docs/guides/classical-feedforward-and-control-flow)\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bf0dc8db-004f-4567-8162-f09be453b434",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## Referências\n",
        "\n",
        "\\[1] E. H. Chen, G.-Y. Zhu, R. Verresen, A. Seif, E. Bäumer, D. Layden, N. Tantivasadakarn, G. Zhu, S. Sheldon, A. Vishwanath, S. Trebst, A. Kandala. *Realização da transição de Nishimori além do limiar de erros para circuitos quânticos de profundidade constante.* [arXiv:2309.02863](https://arxiv.org/abs/2309.02863) (2023).\n",
        "\n",
        "\\[2] Pacote de software [GEM Suite](https://github.com/qiskit-community/gem-suite).\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": 180
  },
  "nbformat": 4,
  "nbformat_minor": 4
}