{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "492d7cec",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Desigualdade CHSH\"\n",
        "description: \"Execute um experimento em um computador quântico para demonstrar a violação da desigualdade CHSH com a primitiva Estimador.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore zorder Tsirelson */}\n",
        "\n",
        "<span id=\"chsh-inequality\" />\n",
        "\n",
        "# Desigualdade CHSH\n",
        "\n",
        "*Estimativa de tempo de execução: Dois minutos em um processador Heron r3 (NOTA: Trata-se apenas de uma estimativa.) (O tempo de execução pode variar.)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a57d9139",
      "metadata": {},
      "source": [
        "<span id=\"learning-outcomes\" />\n",
        "\n",
        "## Resultados do aprendizado\n",
        "\n",
        "Ao concluir este tutorial, você deverá compreender as seguintes informações:\n",
        "\n",
        "* Como construir um circuito CHSH em estado de Bell parametrizado e medir os quatro valores esperados que compõem as testemunhas CHSH.\n",
        "* Como calcular os valores esperados de múltiplas variáveis observáveis em uma varredura de parâmetros em uma única chamada à primitiva [`EstimatorV2`](/docs/api/qiskit-ibm-runtime/estimator-v2) .\n",
        "* Como validar um fluxo de trabalho quântico em um simulador local sujeito a ruídos antes de `AerSimulator.from_backend` enviá-lo para o hardware.\n",
        "* Como ampliar um experimento CHSH para um teste de referência de entrelaçamento em todo o dispositivo, executando muitos pares de Bell independentes em paralelo em um hardwar IBM Quantum®.\n",
        "\n",
        "<span id=\"prerequisites\" />\n",
        "\n",
        "## Pré-requisitos\n",
        "\n",
        "Recomenda-se que você se familiarize com estes tópicos:\n",
        "\n",
        "* [O entrelaçamento em ação](/learning/courses/basics-of-quantum-information/entanglement-in-action/chsh-game) : uma aula sobre os estados de Bell e o jogo CHSH.\n",
        "* [`SparsePauliOp`](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp) e a [introdução do livro “](/docs/guides/primitives)Qiskit primitives ”.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f956eda1",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## Segundo plano\n",
        "\n",
        "Neste tutorial, você executará um experimento em um computador quântico para demonstrar a violação da desigualdade CHSH com a primitiva Estimator.\n",
        "\n",
        "A desigualdade de CHSH, cujo nome é uma referência a Clauser, Horne, Shimony e Holt, é utilizada para testar experimentalmente o teorema de Bell (1969). O teorema afirma que as teorias locais de variáveis ocultas não conseguem explicar algumas consequências do entrelaçamento na mecânica quântica. A demonstração de uma violação da desigualdade de CHSH mostra que a mecânica quântica é incompatível com as teorias locais de variáveis ocultas — um experimento que é fundamental para nossa compreensão da mecânica quântica.\n",
        "\n",
        "O Prêmio Nobel de Física de 2022 foi concedido a Alain Aspect, John Clauser e Anton Zeilinger, em parte por seu trabalho pioneiro na ciência da informação quântica e, em particular, por seus experimentos com fótons entrelaçados que demonstraram a violação das desigualdades de Bell.\n",
        "\n",
        "Para este experimento, criaremos um par entrelaçado no qual mediremos cada qubit em duas bases diferentes. Vamos designar as bases do primeiro qubit como $A$ e $a$, e as bases do segundo qubit como $B$ e $b$. Isso nos permite calcular a quantidade CHSH $S_1$ :\n",
        "\n",
        "$$\n",
        "S_1 = A(B-b) + a(B+b).\n",
        "$$\n",
        "\n",
        "Cada observável é $+1$ ou $-1$. É evidente que um dos termos $B\\pm b$ deve ser $0$, e o outro deve ser $\\pm 2$. Portanto, $S_1 = \\pm 2$. O valor médio de $S_1$ deve satisfazer a desigualdade:\n",
        "\n",
        "$$\n",
        "|\\langle S_1 \\rangle|\\leq 2.\n",
        "$$\n",
        "\n",
        "Ao expandir $S_1$ em termos de $A$, $a$, $B$ e $b$, obtém-se:\n",
        "\n",
        "$$\n",
        "|\\langle S_1 \\rangle| = |\\langle AB \\rangle - \\langle Ab \\rangle + \\langle aB \\rangle + \\langle ab \\rangle| \\leq 2.\n",
        "$$\n",
        "\n",
        "Você pode definir outra quantidade de CHSH $S_2$ :\n",
        "\n",
        "$$\n",
        "S_2 = A(B+b) - a(B-b),\n",
        "$$\n",
        "\n",
        "o que leva a outra desigualdade:\n",
        "\n",
        "$$\n",
        "|\\langle S_2 \\rangle| = |\\langle AB \\rangle + \\langle Ab \\rangle - \\langle aB \\rangle + \\langle ab \\rangle| \\leq 2.\n",
        "$$\n",
        "\n",
        "Se a mecânica quântica pudesse ser descrita por teorias de variáveis ocultas locais, essas desigualdades seriam sempre válidas. Conforme demonstrado neste tutorial, essas propriedades podem ser violadas em um computador quântico; portanto, a mecânica quântica não é compatível com as teorias de variáveis ocultas locais.\n",
        "\n",
        "Criamos o par entrelaçado preparando o estado de Bell $|\\Phi^+\\rangle = \\frac{|00\\rangle + |11\\rangle}{\\sqrt{2}}$. Utilizando a primitiva Estimadora, obtemos os valores esperados $\\langle AB \\rangle, \\langle Ab \\rangle, \\langle aB \\rangle$ e $\\langle ab \\rangle$ diretamente, sem precisar reconstruí-los a partir das contagens brutas. Medimos o segundo qubit nas bases $Z$ e $X$. O primeiro qubit também é medido em bases ortogonais, mas com um ângulo de rotação $\\theta$ que variamos entre $0$ e $2\\pi$. A primitiva Estimator avalia essa variação de parâmetros em um único [bloco unificado de primitivas ( PUB )](/docs/guides/primitive-input-output).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c7346a67",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## Requisitos\n",
        "\n",
        "Antes de iniciar este tutorial, certifique-se de ter os seguintes itens instalados:\n",
        "\n",
        "* Qiskit SDK v2.0 ou versão posterior, com suporte [à visualização](/docs/api/qiskit/visualization)\n",
        "* Qiskit Runtime v0.40 ou posterior (`pip install qiskit-ibm-runtime`)\n",
        "* Qiskit Aer v0.17 ou versão posterior (`pip install qiskit-aer`)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d5ffeb42",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Instalação\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "323b27db",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:49.177326Z",
          "iopub.status.busy": "2026-05-19T22:38:49.177203Z",
          "iopub.status.idle": "2026-05-19T22:38:49.804694Z",
          "shell.execute_reply": "2026-05-19T22:38:49.804154Z"
        }
      },
      "outputs": [],
      "source": [
        "# General\n",
        "import numpy as np\n",
        "\n",
        "# Qiskit imports\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.circuit import Parameter\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "# Qiskit Runtime imports\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "# Qiskit Aer for local noisy simulation\n",
        "from qiskit_aer import AerSimulator\n",
        "\n",
        "# Plotting routines\n",
        "import matplotlib.pyplot as plt\n",
        "import matplotlib.ticker as tck"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fd284a0f",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:49.806301Z",
          "iopub.status.busy": "2026-05-19T22:38:49.806113Z",
          "iopub.status.idle": "2026-05-19T22:38:53.208796Z",
          "shell.execute_reply": "2026-05-19T22:38:53.208025Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'ibm_pittsburgh'"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Select an IBM Quantum backend.\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    min_num_qubits=127, operational=True, simulator=False\n",
        ")\n",
        "backend.name"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ca035271",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-simulator-example\" />\n",
        "\n",
        "## Exemplo de simulador em pequena escala\n",
        "\n",
        "Antes de enviar uma tarefa de hardware, validamos todo o fluxo de trabalho em um simulador local com ruído. Utilizamos `AerSimulator.from_backend(backend)` para criar um simulador que herda o modelo de ruído e o mapa de acoplamento do backend selecionado por você, de modo que a resposta do simulador seja qualitativamente semelhante à que esperamos do hardware.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0539a796",
      "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",
        "Escrevemos o circuito CHSH com um único parâmetro $\\theta$, que varre a base de medição do primeiro qubit. A [`Estimator`](/docs/api/qiskit-ibm-runtime/estimator-v2) primitiva simplifica a análise: ela retorna diretamente os valores esperados das grandezas observáveis e pode avaliar um circuito parametrizado para vários valores de parâmetros em uma única chamada.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "c3f57d25",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:53.210931Z",
          "iopub.status.busy": "2026-05-19T22:38:53.210786Z",
          "iopub.status.idle": "2026-05-19T22:38:53.349189Z",
          "shell.execute_reply": "2026-05-19T22:38:53.348782Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/c3f57d25-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "theta = Parameter(r\"$\\theta$\")\n",
        "\n",
        "chsh_circuit = QuantumCircuit(2)\n",
        "chsh_circuit.h(0)\n",
        "chsh_circuit.cx(0, 1)\n",
        "chsh_circuit.ry(theta, 0)\n",
        "chsh_circuit.draw(output=\"mpl\", idle_wires=False, style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af999dde",
      "metadata": {},
      "source": [
        "Em seguida, criamos uma lista de 21 valores de fase, que vão de $0$ a $2\\pi$, nos quais avaliaremos o circuito parametrizado ( $0$, $0.1\\pi$, $0.2\\pi$,..., $1.9\\pi$, $2\\pi$ ).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9d587e2f",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:53.350400Z",
          "iopub.status.busy": "2026-05-19T22:38:53.350337Z",
          "iopub.status.idle": "2026-05-19T22:38:53.352045Z",
          "shell.execute_reply": "2026-05-19T22:38:53.351729Z"
        }
      },
      "outputs": [],
      "source": [
        "number_of_phases = 21\n",
        "phases = np.linspace(0, 2 * np.pi, number_of_phases)\n",
        "# Phases need to be expressed as a list of lists for the Estimator PUB\n",
        "individual_phases = [[ph] for ph in phases]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af917afb",
      "metadata": {},
      "source": [
        "Por fim, definimos as grandezas observáveis. O primeiro qubit é medido ao longo de eixos girados em $\\theta$; o segundo qubit é medido em $Z$ e $X$. Com essas escolhas, os quatro correladores CHSH correspondem aos operadores de Pauli $ZZ$, $ZX$, $XZ$ e $XX$ :\n",
        "\n",
        "$$\n",
        "\\langle S_1 \\rangle = \\langle ZZ \\rangle - \\langle ZX \\rangle + \\langle XZ \\rangle + \\langle XX \\rangle,\n",
        "$$\n",
        "\n",
        "$$\n",
        "\\langle S_2 \\rangle = \\langle ZZ \\rangle + \\langle ZX \\rangle - \\langle XZ \\rangle + \\langle XX \\rangle.\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "21ae6238",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:53.353007Z",
          "iopub.status.busy": "2026-05-19T22:38:53.352948Z",
          "iopub.status.idle": "2026-05-19T22:38:53.355217Z",
          "shell.execute_reply": "2026-05-19T22:38:53.354857Z"
        }
      },
      "outputs": [],
      "source": [
        "# <S_1> = <ZZ> - <ZX> + <XZ> + <XX>\n",
        "observable1 = SparsePauliOp.from_list(\n",
        "    [(\"ZZ\", 1), (\"ZX\", -1), (\"XZ\", 1), (\"XX\", 1)]\n",
        ")\n",
        "\n",
        "# <S_2> = <ZZ> + <ZX> - <XZ> + <XX>\n",
        "observable2 = SparsePauliOp.from_list(\n",
        "    [(\"ZZ\", 1), (\"ZX\", 1), (\"XZ\", -1), (\"XX\", 1)]\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2d571aa2",
      "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",
        "V2 As primitivas aceitam apenas circuitos e observáveis que estejam em conformidade com as instruções e a conectividade suportadas pelo sistema de destino (arquitetura de conjunto de instruções, ou ISA, circuitos e observáveis). Nós compilamos o `AerSimulator` no backend e fazemos a transpilagem para o destino do simulador, de modo que o mesmo gerenciador de passagens seja executado de ponta a ponta.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "3e139a89",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:53.356197Z",
          "iopub.status.busy": "2026-05-19T22:38:53.356140Z",
          "iopub.status.idle": "2026-05-19T22:38:56.713188Z",
          "shell.execute_reply": "2026-05-19T22:38:56.712683Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/3e139a89-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Build a noisy simulator from the ibm_pittsburgh backend\n",
        "aer_sim = AerSimulator.from_backend(backend)\n",
        "\n",
        "pm = generate_preset_pass_manager(target=aer_sim.target, optimization_level=3)\n",
        "chsh_isa_circuit = pm.run(chsh_circuit)\n",
        "chsh_isa_circuit.draw(output=\"mpl\", idle_wires=False, style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2817b069",
      "metadata": {},
      "source": [
        "Também transformamos os observáveis para que correspondam ao layout de qubits do circuito transpilado usando `SparsePauliOp.apply_layout`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "d1faa7ab",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:56.714405Z",
          "iopub.status.busy": "2026-05-19T22:38:56.714288Z",
          "iopub.status.idle": "2026-05-19T22:38:56.716319Z",
          "shell.execute_reply": "2026-05-19T22:38:56.715992Z"
        }
      },
      "outputs": [],
      "source": [
        "isa_observable1 = observable1.apply_layout(layout=chsh_isa_circuit.layout)\n",
        "isa_observable2 = observable2.apply_layout(layout=chsh_isa_circuit.layout)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e734572e",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "### Passo 3: Execute usando Qiskit primitives\n",
        "\n",
        "Execute a varredura de parâmetros no `aer_sim``EstimatorV2` modo. O método `Estimator `run()` ` recebe um iterável de PUBs. Cada PUB tem o formato `(circuit, observables, parameter_values, precision)`. Passamos os dois observáveis juntos para que compartilhem a mesma variação de parâmetros.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "7f954aeb",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:56.717549Z",
          "iopub.status.busy": "2026-05-19T22:38:56.717473Z",
          "iopub.status.idle": "2026-05-19T22:38:58.217539Z",
          "shell.execute_reply": "2026-05-19T22:38:58.217000Z"
        }
      },
      "outputs": [],
      "source": [
        "# Use the AerSimulator-backed Estimator to validate the workflow locally\n",
        "estimator_sim = Estimator(mode=aer_sim)\n",
        "\n",
        "pub = (\n",
        "    chsh_isa_circuit,  # ISA circuit\n",
        "    [[isa_observable1], [isa_observable2]],  # ISA observables\n",
        "    individual_phases,  # Parameter values\n",
        ")\n",
        "\n",
        "sim_result = estimator_sim.run(pubs=[pub]).result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9c5230fc",
      "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",
        "O Estimador retorna os valores esperados para ambas as variáveis observáveis. Nós as representamos graficamente em $\\theta$, juntamente com o limite clássico ( $\\pm 2$ ) e o limite de Tsirelson ( $\\pm 2\\sqrt{2}$ ). As regiões sombreadas em cinza indicam a diferença entre os dois. Os pontos que se encontram dentro dessas faixas violam a desigualdade de CHSH.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "c8fd5140",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:58.219407Z",
          "iopub.status.busy": "2026-05-19T22:38:58.219306Z",
          "iopub.status.idle": "2026-05-19T22:38:58.285202Z",
          "shell.execute_reply": "2026-05-19T22:38:58.284609Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/c8fd5140-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "chsh1_sim = sim_result[0].data.evs[0]\n",
        "chsh2_sim = sim_result[0].data.evs[1]\n",
        "\n",
        "\n",
        "def plot_chsh(phases, chsh1, chsh2, title):\n",
        "    fig, ax = plt.subplots(figsize=(10, 6))\n",
        "\n",
        "    ax.plot(\n",
        "        phases / np.pi, chsh1, \"o-\", label=r\"$\\langle S_1 \\rangle$\", zorder=3\n",
        "    )\n",
        "    ax.plot(\n",
        "        phases / np.pi, chsh2, \"o-\", label=r\"$\\langle S_2 \\rangle$\", zorder=3\n",
        "    )\n",
        "\n",
        "    # classical bound +-2\n",
        "    ax.axhline(y=2, color=\"0.9\", linestyle=\"--\")\n",
        "    ax.axhline(y=-2, color=\"0.9\", linestyle=\"--\")\n",
        "\n",
        "    # quantum bound, +-2*sqrt(2)\n",
        "    ax.axhline(y=np.sqrt(2) * 2, color=\"0.9\", linestyle=\"-.\")\n",
        "    ax.axhline(y=-np.sqrt(2) * 2, color=\"0.9\", linestyle=\"-.\")\n",
        "    ax.fill_between(phases / np.pi, 2, 2 * np.sqrt(2), color=\"0.6\", alpha=0.7)\n",
        "    ax.fill_between(\n",
        "        phases / np.pi, -2, -2 * np.sqrt(2), color=\"0.6\", alpha=0.7\n",
        "    )\n",
        "\n",
        "    ax.xaxis.set_major_formatter(tck.FormatStrFormatter(\"%g $\\\\pi$\"))\n",
        "    ax.xaxis.set_major_locator(tck.MultipleLocator(base=0.5))\n",
        "\n",
        "    ax.set_xlabel(r\"$\\theta$\")\n",
        "    ax.set_ylabel(\"CHSH witness\")\n",
        "    ax.set_title(title)\n",
        "    ax.legend()\n",
        "    plt.show()\n",
        "\n",
        "\n",
        "plot_chsh(\n",
        "    phases,\n",
        "    chsh1_sim,\n",
        "    chsh2_sim,\n",
        "    \"CHSH witnesses from AerSimulator (ibm_pittsburgh noise model)\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9744b84",
      "metadata": {},
      "source": [
        "Os testemunhos CHSH do simulador já excedem o limite clássico de $\\pm 2$ em vários valores de $\\theta$, mesmo com o modelo de ruído do backend. Os picos ficam um pouco abaixo do limite de Tsirelson $\\pm 2\\sqrt{2}$ devido ao ruído simulado do dispositivo. Com o fluxo de trabalho validado, passamos para o hardware propriamente dito.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "747e948d",
      "metadata": {},
      "source": [
        "<span id=\"large-scale-hardware-example\" />\n",
        "\n",
        "## Exemplo de hardware em grande escala\n",
        "\n",
        "Um teste CHSH é, por natureza, um experimento *com dois qubits*; portanto, não é possível aumentá-lo simplesmente ampliando um circuito. Em vez disso, ele alcança escalabilidade executando **muitos testes em paralelo**. Aqui, dividimos o backend em tantos pares de Bell disjuntos quanto sua conectividade permitir (uma *correspondência* do mapa de acoplamento) e executamos um subcircuito CHSH independente em cada par, tudo em um único trabalho.\n",
        "\n",
        "Isso transforma o CHSH em um **parâmetro de referência para a qualidade do entrelaçamento em todo o dispositivo** : em vez de um único par selecionado manualmente, testamos o entrelaçamento em uma grande parte do chip de uma só vez, em condições realistas nas quais cada par enfrenta a interferência dos vizinhos e erros de portas paralelas. A violação *simultânea* da desigualdade em todos os pares comprova que o entrelaçamento genuíno está presente em todos os pontos do dispositivo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "3376bc73",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:58.286726Z",
          "iopub.status.busy": "2026-05-19T22:38:58.286656Z",
          "iopub.status.idle": "2026-05-19T22:38:59.198086Z",
          "shell.execute_reply": "2026-05-19T22:38:59.197690Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Tiling ibm_pittsburgh with 64 parallel Bell pairs (128 of 156 qubits)\n",
            "Job ID: d86efd5g7okc73el0rp0\n",
            "63/64 Bell pairs violated the CHSH inequality (mean peak witness 2.75, classical bound 2)\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/3376bc73-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# -------------------------Step 1: Map classical inputs to a quantum problem-------------------------\n",
        "# A CHSH test is bipartite, so we scale up by running one independent CHSH\n",
        "# experiment on every disjoint Bell pair the device can host. A greedy\n",
        "# matching of the coupling map gives a set of edges that share no qubits.\n",
        "num_qubits = backend.num_qubits\n",
        "used = set()\n",
        "pairs = []\n",
        "for qa, qb in backend.coupling_map.get_edges():\n",
        "    if qa not in used and qb not in used:\n",
        "        pairs.append((qa, qb))\n",
        "        used.update((qa, qb))\n",
        "num_pairs = len(pairs)\n",
        "print(\n",
        "    f\"Tiling {backend.name} with {num_pairs} parallel Bell pairs \"\n",
        "    f\"({2 * num_pairs} of {num_qubits} qubits)\"\n",
        ")\n",
        "\n",
        "# One parameterized CHSH sub-circuit per pair, all sharing the angle theta\n",
        "theta = Parameter(r\"$\\theta$\")\n",
        "chsh_circuit = QuantumCircuit(num_qubits)\n",
        "for qa, qb in pairs:\n",
        "    chsh_circuit.h(qa)\n",
        "    chsh_circuit.cx(qa, qb)\n",
        "    chsh_circuit.ry(theta, qa)\n",
        "\n",
        "# Embed the two CHSH observables onto each pair's qubits (identity elsewhere)\n",
        "obs1 = SparsePauliOp.from_list([(\"ZZ\", 1), (\"ZX\", -1), (\"XZ\", 1), (\"XX\", 1)])\n",
        "obs2 = SparsePauliOp.from_list([(\"ZZ\", 1), (\"ZX\", 1), (\"XZ\", -1), (\"XX\", 1)])\n",
        "observables = []\n",
        "for qa, qb in pairs:\n",
        "    observables.append([obs1.apply_layout([qa, qb], num_qubits)])\n",
        "    observables.append([obs2.apply_layout([qa, qb], num_qubits)])\n",
        "\n",
        "number_of_phases = 21\n",
        "phases = np.linspace(0, 2 * np.pi, number_of_phases)\n",
        "individual_phases = [[ph] for ph in phases]\n",
        "\n",
        "# -------------------------Step 2: Optimize problem for quantum hardware execution-------------------------\n",
        "pm = generate_preset_pass_manager(target=backend.target, optimization_level=3)\n",
        "chsh_isa_circuit = pm.run(chsh_circuit)\n",
        "isa_observables = [\n",
        "    [o[0].apply_layout(chsh_isa_circuit.layout)] for o in observables\n",
        "]\n",
        "\n",
        "# -------------------------Step 3: Execute using Qiskit primitives-------------------------\n",
        "estimator_hw = Estimator(mode=backend)\n",
        "estimator_hw.options.environment.job_tags = [\"TUT_CI\"]\n",
        "\n",
        "pub = (chsh_isa_circuit, isa_observables, individual_phases)\n",
        "job = estimator_hw.run(pubs=[pub])\n",
        "print(f\"Job ID: {job.job_id()}\")\n",
        "hw_result = job.result()\n",
        "\n",
        "# -------------------------Step 4: Post-process and return result in desired classical format-------------------------\n",
        "# evs has shape (2 * num_pairs, number_of_phases); rows alternate S1, S2\n",
        "evs = np.asarray(hw_result[0].data.evs)\n",
        "chsh1_all = evs[0::2]\n",
        "chsh2_all = evs[1::2]\n",
        "\n",
        "# A pair \"violates\" CHSH if its strongest witness exceeds the classical bound\n",
        "peak = np.maximum(\n",
        "    np.abs(chsh1_all).max(axis=1), np.abs(chsh2_all).max(axis=1)\n",
        ")\n",
        "n_violate = int(np.sum(peak > 2))\n",
        "print(\n",
        "    f\"{n_violate}/{num_pairs} Bell pairs violated the CHSH inequality \"\n",
        "    f\"(mean peak witness {peak.mean():.2f}, classical bound 2)\"\n",
        ")\n",
        "\n",
        "fig, ax = plt.subplots(figsize=(10, 6))\n",
        "\n",
        "# Faint individual per-pair curves\n",
        "for row in chsh1_all:\n",
        "    ax.plot(phases / np.pi, row, color=\"#1f77b4\", alpha=0.2, lw=1)\n",
        "for row in chsh2_all:\n",
        "    ax.plot(phases / np.pi, row, color=\"#ff7f0e\", alpha=0.2, lw=1)\n",
        "\n",
        "# Bold mean curves across all pairs\n",
        "ax.plot(\n",
        "    phases / np.pi,\n",
        "    chsh1_all.mean(axis=0),\n",
        "    color=\"#1f77b4\",\n",
        "    lw=2.5,\n",
        "    label=r\"$\\langle S_1 \\rangle$ (mean)\",\n",
        ")\n",
        "ax.plot(\n",
        "    phases / np.pi,\n",
        "    chsh2_all.mean(axis=0),\n",
        "    color=\"#ff7f0e\",\n",
        "    lw=2.5,\n",
        "    label=r\"$\\langle S_2 \\rangle$ (mean)\",\n",
        ")\n",
        "\n",
        "# classical bound +-2 and Tsirelson bound +-2*sqrt(2)\n",
        "ax.axhline(y=2, color=\"0.9\", linestyle=\"--\")\n",
        "ax.axhline(y=-2, color=\"0.9\", linestyle=\"--\")\n",
        "ax.axhline(y=np.sqrt(2) * 2, color=\"0.9\", linestyle=\"-.\")\n",
        "ax.axhline(y=-np.sqrt(2) * 2, color=\"0.9\", linestyle=\"-.\")\n",
        "ax.fill_between(phases / np.pi, 2, 2 * np.sqrt(2), color=\"0.6\", alpha=0.7)\n",
        "ax.fill_between(phases / np.pi, -2, -2 * np.sqrt(2), color=\"0.6\", alpha=0.7)\n",
        "\n",
        "ax.xaxis.set_major_formatter(tck.FormatStrFormatter(\"%g $\\\\pi$\"))\n",
        "ax.xaxis.set_major_locator(tck.MultipleLocator(base=0.5))\n",
        "ax.set_xlabel(r\"$\\theta$\")\n",
        "ax.set_ylabel(\"CHSH witness\")\n",
        "ax.set_title(\n",
        "    f\"CHSH witnesses for {num_pairs} parallel Bell pairs on {backend.name}\"\n",
        ")\n",
        "ax.legend()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3c32f01c",
      "metadata": {},
      "source": [
        "As curvas mais tênues representam os pares de Bell individuais, e as curvas em negrito representam a média deles em todo o dispositivo. Cada par traça a mesma sinusoide prevista pela mecânica quântica, e a dispersão entre as curvas pouco marcantes reflete a variação no ruído de um par para outro. Sempre que uma curva entra nas faixas cinzas, isso significa que ela ultrapassou o limite clássico de $\\pm 2$, e o resumo impresso confirma que, essencialmente, todos os pares violam a desigualdade de CHSH ao mesmo tempo.\n",
        "\n",
        "Os picos ficam aquém do limite de Tsirelson $\\pm 2\\sqrt{2}$ devido ao ruído do dispositivo, mas a conclusão é inequívoca: o backend mantém um entrelaçamento genuíno em todo o chip simultaneamente, e não apenas em um único par selecionado manualmente. É nesse sentido que o experimento do CHSH “se expande”: não como um único circuito maior, mas como um parâmetro de referência paralelo que certifica o entrelaçamento em todos os lugares ao mesmo tempo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "86e635a3",
      "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",
        "  * [O entrelaçamento em ação](/learning/courses/basics-of-quantum-information/entanglement-in-action/chsh-game) : uma aula ministrada por John Watrous sobre os estados de Bell e o jogo CHSH.\n",
        "  * [Comece a usar a primitiva Estimator](/docs/guides/primitives) : um guia sobre PUBs e varreduras de parâmetros.\n",
        "  * [Avaliação comparativa em tempo real para seleção de qubits](/docs/tutorials/real-time-benchmarking-for-qubit-selection) : outra maneira de caracterizar a qualidade dos qubits e do entrelaçamento em um dispositivo.\n",
        "  * [`SparsePauliOp` Referência da API](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp).\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"
    },
    "hours": 1,
    "qpuSeconds": 120
  },
  "nbformat": 4,
  "nbformat_minor": 5
}