diff --git a/docs/tutorials/nishimori-phase-transition.ipynb b/docs/tutorials/nishimori-phase-transition.ipynb index a5b3ac16fcf..f9d3f9398d9 100644 --- a/docs/tutorials/nishimori-phase-transition.ipynb +++ b/docs/tutorials/nishimori-phase-transition.ipynb @@ -11,8 +11,29 @@ "---\n", "\n", "\n", + "{/* cspell:ignore Verresen Layden Tantivasadakarn Vishwanath Trebst */}\n", + "\n", "# Nishimori phase transition\n", - "*Usage estimate: 3 minutes on a Heron r2 processor (NOTE: This is an estimate only. Your runtime might vary.)*" + "*Usage estimate: 3 minutes on a Heron r2 processor (NOTE: This is an estimate only. Your runtime may vary.)*" + ] + }, + { + "cell_type": "markdown", + "id": "6113a1ff-5cc0-433a-afd7-5aadc97bb28f", + "metadata": {}, + "source": [ + "## Learning outcomes\n", + "After going through this tutorial, users should expect the following outcomes:\n", + "- Understand the Nishimori phase transition and how it manifests as the appearance of long-range entanglement in the random-bond Ising model.\n", + "- Implement the *generation of entanglement by measurement* (GEM) protocol on quantum hardware using mid-circuit measurements and constant-depth circuits.\n", + "- Characterize the transition by extracting the two-point correlation and the normalized variance of the magnetization from experimental data.\n", + "\n", + "## Prerequisites\n", + "We recommend familiarity with the following topics before going through this tutorial:\n", + "- [Measure qubits](/docs/guides/measure-qubits), in particular the section on mid-circuit measurement that the GEM protocol relies on.\n", + "- [Exact and noisy simulation with Qiskit Aer primitives](/docs/guides/simulate-with-qiskit-aer), which is how the small-scale section is executed.\n", + "- [Long-range entanglement with dynamic circuits](/docs/tutorials/long-range-entanglement), a companion tutorial that uses the same measurement-based-entanglement paradigm.\n", + "- [Heavy hex lattice](https://www.ibm.com/quantum/blog/heavy-hex-lattice), the IBM hardware topology the plaquette lattice is built on." ] }, { @@ -21,7 +42,7 @@ "metadata": {}, "source": [ "## Background\n", - "This tutorial demonstrates how to realize a Nishimori phase transition on an IBM® quantum processor. This experiment was originally described in [*Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits*](https://arxiv.org/abs/2309.02863).\n", + "This tutorial demonstrates how to realize a Nishimori phase transition on a quantum processor. This experiment was originally described in [*Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits*](https://arxiv.org/abs/2309.02863).\n", "\n", "The Nishimori phase transition refers to the transition between short- and long-range ordered phases in the random-bond Ising model. On a quantum computer, the long-range ordered phase manifests as a state in which qubits are entangled across the entire device. This highly entangled state is prepared using the *generation of entanglement by measurement* (GEM) protocol. By utilizing mid-circuit measurements, the GEM protocol is able to entangle qubits across the entire device using circuits of only constant depth. This tutorial uses the implementation of the GEM protocol from the [GEM Suite](https://github.com/qiskit-community/gem-suite) software package." ] @@ -35,8 +56,9 @@ "Before starting this tutorial, be sure you have the following installed:\n", "\n", "- Qiskit SDK v1.0 or later, with [visualization](/docs/api/qiskit/visualization) support\n", - "- Qiskit Runtime v0.22 or later ( `pip install qiskit-ibm-runtime` )\n", - "- GEM Suite ( `pip install gem-suite` )" + "- Qiskit Runtime v0.22 or later (`pip install qiskit-ibm-runtime`)\n", + "- Qiskit Aer v0.14 or later (`pip install qiskit-aer`)\n", + "- GEM Suite (`pip install gem-suite`)" ] }, { @@ -49,16 +71,18 @@ }, { "cell_type": "code", - "execution_count": 2, + "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", @@ -66,18 +90,28 @@ "from gem_suite.experiments import GemExperiment" ] }, + { + "cell_type": "markdown", + "id": "281ec87e-3f50-44b6-8e6f-a906b92fba74", + "metadata": {}, + "source": [ + "## Small-scale simulator example\n", + "\n", + "In this section, the full workflow is walked through on the noiseless `AerSimulator`. The plaquette lattice is restricted to a single plaquette (12 qubits) so the simulation stays small and fast, while still exercising every part of the GEM protocol: mid-circuit measurement, the $R_{ZZ}$ angle sweep, decoding, and the normalized-variance analysis. The same workflow is later scaled up to multiple plaquettes and the full lattice on real hardware." + ] + }, { "cell_type": "markdown", "id": "39f59f3a-eb2a-4160-9da2-2bb83c58771c", "metadata": {}, "source": [ - "## Step 1: Map classical inputs to a quantum problem\n", + "### Step 1: Map classical inputs to a quantum problem\n", "\n", "The GEM protocol works on a quantum processor with qubit connectivity described by a lattice. Today's IBM quantum processors use the [heavy hex lattice](https://www.ibm.com/quantum/blog/heavy-hex-lattice). The qubits of the processor are grouped into *plaquettes* based on which unit cell of the lattice they occupy. Because a qubit might occur in more than one unit cell, the plaquettes are not disjoint. On the heavy hex lattice, a plaquette contains 12 qubits. The plaquettes themselves also form lattice, where two plaquettes are connected if they share any qubits. On the heavy hex lattice, neighboring plaquettes share 3 qubits.\n", "\n", "In the GEM Suite software package, the fundamental class for implementing the GEM protocol is `PlaquetteLattice`, which represents the lattice of plaquettes (which is distinct from the heavy hex lattice). A `PlaquetteLattice` can be initialized from a qubit coupling map. Currently, only heavy hex coupling maps are supported.\n", "\n", - "The following code cell initializes a plaquette lattice from the coupling map of a IBM quantum processor. The plaquette lattice does not always encompass the entire hardware. For example, `ibm_torino` has 133 total qubits, but the largest plaquette lattice that fits on the device uses only 125 of them, and comprises a total of 18 plaquettes. Similar can be observed for IBM Quantum® devices with different qubit counts as well." + "The following code cell initializes a plaquette lattice from the coupling map of an IBM quantum processor. The plaquette lattice does not always encompass the entire hardware. For example, `ibm_torino` has 133 total qubits but the largest plaquette lattice that fits on the device uses only 125 of them, comprising 18 plaquettes; `ibm_pittsburgh` (156 qubits) similarly fits 144 qubits into 21 plaquettes. The same pattern holds for other heavy-hex IBM Quantum® processors with different qubit counts." ] }, { @@ -90,18 +124,19 @@ "name": "stdout", "output_type": "stream", "text": [ - "Number of qubits in backend: 133\n", - "Number of qubits in plaquette lattice: 125\n", - "Number of plaquettes: 18\n" + "Number of qubits in backend: 156\n", + "Number of qubits in plaquette lattice: 144\n", + "Number of plaquettes: 21\n" ] } ], "source": [ - "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"\", overwrite=True, set_as_default=True)\n", + "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"\", overwrite=True, 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", @@ -121,7 +156,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 3, "id": "625882a4-faeb-4d96-b441-c989f43c4dea", "metadata": {}, "outputs": [ @@ -131,7 +166,7 @@ "\"Output" ] }, - "execution_count": 7, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -150,17 +185,17 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "id": "e412a612-c7d5-4689-840a-2383dd538f06", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "PyPlaquette(index=0, qubits=[0, 1, 2, 3, 4, 15, 16, 19, 20, 21, 22, 23], neighbors=[3, 1])" + "PyPlaquette(index=0, qubits=[3, 4, 5, 6, 7, 16, 17, 23, 24, 25, 26, 27], neighbors=[4, 3, 1])" ] }, - "execution_count": 8, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -182,7 +217,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "id": "a19d63ce-3572-4081-a008-c1332fbbe303", "metadata": {}, "outputs": [ @@ -192,7 +227,7 @@ "\"Output" ] }, - "execution_count": 9, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -211,12 +246,12 @@ "- Each site qubit is labeled either (A) or (B), indicating one of two roles a site qubit can play in the GEM protocol (the roles are explained later).\n", "- Each edge is colored using one of six colors, thus partitioning the edges into six groups. This partitioning determines how two-qubit gates can be parallelized, as well as different scheduling patterns that are likely to incur different amounts of error on a noisy quantum processor. Because edges in a group are disjoint, a layer of two-qubit gates can be applied on those edges simultaneously. In fact, it is possible to partition the six colors into three groups of two colors such that the union of each group of two colors is still disjoint. Therefore, only three layers of two-qubit gates are needed to activate every edge. There are 12 ways to so partition the six colors, and each such partition yields a different 3-layer gate schedule.\n", "\n", - "Now that you have created a plaquette lattice, the next step is to initialize a `GemExperiment` object, passing both the plaquette lattice and the backend that you intend to run the experiment on. The `GemExperiment` class manages the actual implementation of the GEM protocol, including generating circuits, submitting jobs, and analyzing the data. The following code cell initializes the experiment class while restricting the plaquette lattice to only two of the plaquettes (21 qubits), reducing the size of the experiment to ensure that the noise in the hardware doesn't overwhelm the signal." + "Now that you have created a plaquette lattice, the next step is to initialize a `GemExperiment` object, passing both the plaquette lattice and the backend that you intend to run the experiment on. The `GemExperiment` class manages the actual implementation of the GEM protocol, including generating circuits, submitting jobs, and analyzing the data. The following code cell initializes the experiment class while restricting the plaquette lattice to a single plaquette (12 qubits), keeping the simulation small and fast. The full plaquette lattice is used later when scaling up to real hardware." ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 6, "id": "02357c6e-5c83-4ac0-811d-22602d9f33d5", "metadata": {}, "outputs": [ @@ -226,16 +261,19 @@ "\"Output" ] }, - "execution_count": 16, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "gem_exp = GemExperiment(plaquette_lattice.filter([9, 12]), backend=backend)\n", + "# 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, 12]).draw_qubits()" + "plaquette_lattice.filter([9]).draw_qubits()" ] }, { @@ -269,7 +307,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 7, "id": "8e2ade62-9a57-42c3-9a85-3fe2dec3c426", "metadata": {}, "outputs": [ @@ -296,7 +334,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 8, "id": "4f8a2c73-752d-47b9-95d5-83439933fc08", "metadata": {}, "outputs": [ @@ -335,7 +373,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 9, "id": "fd57d483-c70b-4ad5-b309-15750ad38bac", "metadata": {}, "outputs": [ @@ -345,7 +383,7 @@ "\"Output" ] }, - "execution_count": 14, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -364,7 +402,7 @@ "id": "a3aa063b-44cf-49f3-9e12-23b2f6a1c85b", "metadata": {}, "source": [ - "## Step 2: Optimize problem for quantum hardware execution\n", + "### Step 2: Optimize problem for quantum hardware execution\n", "\n", "Transpiling quantum circuits for execution on hardware typically involves a [number of stages](/docs/guides/transpiler-stages). Typically, the stages that incur the most computational overhead are choosing the qubit layout, routing the two-qubit gates to conform to the qubit connectivity of the hardware, and optimizing the circuit to minimize its gate count and depth. In the GEM protocol, the layout and routing stages are unnecessary because the hardware connectivity is already incorporated into the design of the protocol. The circuits already have a qubit layout, and the two-qubit gates are already mapped onto native connections. Furthermore, in order to preserve the structure of the circuit as the $R_{ZZ}$ angle is varied, only very basic circuit optimization should be performed.\n", "\n", @@ -373,7 +411,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 10, "id": "e9b99d48-8d33-46b5-bff5-480ab1c1c1f2", "metadata": {}, "outputs": [ @@ -383,7 +421,7 @@ "\"Output" ] }, - "execution_count": 15, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -394,7 +432,7 @@ " optimization_level=1 # This is the default optimization level\n", ")\n", "pass_manager = generate_preset_pass_manager(\n", - " backend=backend,\n", + " backend=aer_backend,\n", " initial_layout=list(gem_exp.physical_qubits),\n", " **dict(gem_exp.transpile_options),\n", ")\n", @@ -407,14 +445,14 @@ "id": "8d0dcd59-54ef-4af8-9213-0784ef94b838", "metadata": {}, "source": [ - "## Step 3: Execute using Qiskit primitives\n", + "### Step 3: Execute using Qiskit primitives\n", "\n", "To execute the GEM protocol circuits on the hardware, call the `run` method of the `GemExperiment` object. You can specify the number of shots you want to sample from each circuit. The `run` method returns an [ExperimentData](https://qiskit-community.github.io/qiskit-experiments/stubs/qiskit_experiments.framework.ExperimentData.html) object which you should save to a variable. Note that the `run` method only submits jobs without waiting for them to finish, so it is a non-blocking call." ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "id": "6171a383-dd58-4e3f-88aa-bbec7b5870df", "metadata": {}, "outputs": [], @@ -432,23 +470,31 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "id": "ed14a067-35ba-4ffc-8534-4ae5ec6bc4c9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "ExperimentData(GemExperiment, d0d5880a-34c1-4aab-a7b6-c4f58516bc03, job_ids=['cwg12ptmptp00082khhg'], metadata=<5 items>, figure_names=['two_point_correlation.svg', 'normalized_variance.svg', 'plaquette_ops.svg', 'bond_ops.svg'])" + "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": 11, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "exp_data.block_for_results()" + "# 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" ] }, { @@ -456,7 +502,7 @@ "id": "36e0570b-f091-45f2-bb83-143edbc3b433", "metadata": {}, "source": [ - "## Step 4: Post-process and return result in desired classical format\n", + "### Step 4: Post-process and return result in desired classical format\n", "\n", "At an $R_{ZZ}$ angle of $\\frac{\\pi}{2}$, the decoded state would be the GHZ state in the absence of noise. The long-range order of the GHZ state can be visualized by plotting the magnetization of the measured bitstrings. The magnetization $M$ is defined as the sum of the single-qubit Pauli $Z$ operators,\n", "$$\n", @@ -471,7 +517,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "8ead3582-16df-4616-836c-bdce867ad6b8", "metadata": {}, "outputs": [ @@ -481,7 +527,7 @@ "Text(0.5, 1.0, 'Magnetization distribution with and without decoding')" ] }, - "execution_count": 12, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, @@ -556,7 +602,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "id": "4ecb25c8-e572-49af-a879-9943039db131", "metadata": {}, "outputs": [ @@ -566,7 +612,7 @@ "\"Output" ] }, - "execution_count": 13, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -589,7 +635,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "id": "2b351d68-3924-445a-94ef-047b16214e8a", "metadata": {}, "outputs": [ @@ -599,7 +645,7 @@ "\"Output" ] }, - "execution_count": 14, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -613,48 +659,51 @@ "id": "a94e0cbe-8429-487c-b203-50a8b2eacee3", "metadata": {}, "source": [ - "## Scale up the experiment\n", + "## Large-scale hardware example\n", + "\n", + "Having validated the protocol on a simulator, the experiment is now scaled up and run on the real quantum hardware backend selected in the [Setup](#setup) section. Two larger problem sizes are used:\n", "\n", - "The following code cells run the experiment for six plaquettes (49 qubits) and the full 12 plaquettes (125 qubits) and plot the normalized variance. As the experiment is scaled to larger sizes, the greater amount of noise shifts the critical point rightwards." + "- **Six plaquettes (~49 qubits)**: a mid-size run that already shows the rightward shift of the critical point under hardware noise.\n", + "- **The full plaquette lattice**: every plaquette the device's heavy-hex topology supports (for example, 18 plaquettes / 125 qubits on `ibm_torino` or 21 plaquettes / 144 qubits on `ibm_pittsburgh`), entangling qubits across the entire device with constant-depth circuits.\n", + "\n", + "The single code cell below is self-contained: it builds the plaquette lattice from the backend's coupling map and runs both experiments, so this section can be executed after the [Setup](#setup) cells without first running the small-scale section." ] }, { "cell_type": "code", - "execution_count": 15, + "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": [ - "\"Output" + "\"Output" ] }, - "execution_count": 15, "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gem_exp = GemExperiment(\n", - " plaquette_lattice.filter(range(3, 9)), backend=backend\n", - ")\n", - "gem_exp.set_experiment_options(schedule_idx=0)\n", - "exp_data = gem_exp.run(shots=10_000)\n", - "exp_data.block_for_results()\n", - "exp_data.figure(\"normalized_variance\")" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "37e9a4cd-6efb-4ade-ad09-8139db9d58e9", - "metadata": {}, - "outputs": [ + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "\"Output" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/plain": [ - "\"Output" + "\"Output" ] }, "execution_count": 16, @@ -663,11 +712,74 @@ } ], "source": [ - "gem_exp = GemExperiment(plaquette_lattice, backend=backend)\n", - "gem_exp.set_experiment_options(schedule_idx=0)\n", - "exp_data = gem_exp.run(shots=10_000)\n", - "exp_data.block_for_results()\n", - "exp_data.figure(\"normalized_variance\")" + "# -------------------------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": [ + "Note that, depending on the noise level of the backend used, the normalized-variance curves at the larger sizes may not show a clear peak within the swept angle range. In the runs above, the peak has been pushed all the way to $0.5 \\pi$, the right edge of the sweep (the analysis reports `critical_angle = 0.5000` for both the six-plaquette and full-lattice runs). This means hardware noise has shifted the critical point to (or just past) the boundary of the protocol's physically meaningful angle range, so the transition is at the edge of what this sweep can resolve." ] }, { @@ -677,19 +789,35 @@ "source": [ "## Conclusion\n", "\n", - "In this tutorial, you realized a Nishimori phase transition on a quantum processor using the GEM protocol. The metrics that you examined during post-processing, in particular the two-point correlation and the normalized variance, serve as benchmarks of the device's ability to generate long-range entangled states. These benchmarks extend the utility of the GEM protocol beyond probing interesting physics. As part of the protocol, you entangled qubits across the entire device using circuits of only constant depth. This feat is only possible due to the protocol's use of mid-circuit measurements. In this experiment, the entangled state was immediately measured, but an interesting avenue to explore would be to continue using the state in additional quantum processing!" + "In this tutorial, you realized a Nishimori phase transition on a quantum processor using the GEM protocol. The metrics that you examined during post-processing, in particular the two-point correlation and the normalized variance, serve as benchmarks of the device's ability to generate long-range entangled states. These benchmarks extend the utility of the GEM protocol beyond probing interesting physics. As part of the protocol, you entangled qubits across the entire device using circuits of only constant depth. This feat is only possible due to the protocol's use of mid-circuit measurements. In this experiment, the entangled state was immediately measured, but an interesting avenue to explore would be to continue using this state in additional quantum processing!" + ] + }, + { + "cell_type": "markdown", + "id": "717f22c6-4945-4719-b9ba-ae44cde58da8", + "metadata": {}, + "source": [ + "## Next steps\n", + "\n", + "\n", + "\n", + "If you found this work interesting, you might be interested in the following material:\n", + "- [Long-range entanglement with dynamic circuits](/docs/tutorials/long-range-entanglement)\n", + "- [Repetition codes](/docs/tutorials/repetition-codes)\n", + "- [Classical feedforward and control flow](/docs/guides/classical-feedforward-and-control-flow)\n", + "" ] }, { "cell_type": "markdown", - "id": "b9562a76", + "id": "bf0dc8db-004f-4567-8162-f09be453b434", "metadata": {}, "source": [ - "## Tutorial survey\n", + "## References\n", "\n", - "Please take this short survey to provide feedback on this tutorial. Your insights will help us improve our content offerings and user experience.\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. *Realizing the Nishimori transition across the error threshold for constant-depth quantum circuits.* [arXiv:2309.02863](https://arxiv.org/abs/2309.02863) (2023).\n", "\n", - "[Link to survey](https://your.feedback.ibm.com/jfe/form/SV_bsCKQkgzuQUQ7ky)" + "[2] [GEM Suite](https://github.com/qiskit-community/gem-suite) software package." ] } ], diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/02357c6e-5c83-4ac0-811d-22602d9f33d5-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/02357c6e-5c83-4ac0-811d-22602d9f33d5-0.avif index c5e9d643237..ebf483c01b3 100644 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/02357c6e-5c83-4ac0-811d-22602d9f33d5-0.avif and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/02357c6e-5c83-4ac0-811d-22602d9f33d5-0.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-0.avif deleted file mode 100644 index 8dfdca0eff4..00000000000 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-0.avif and /dev/null differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-1.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-1.avif new file mode 100644 index 00000000000..fdf928816ca Binary files /dev/null and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-1.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-2.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-2.avif new file mode 100644 index 00000000000..78d4e8e5c95 Binary files /dev/null and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-2.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-3.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-3.avif new file mode 100644 index 00000000000..060276bb69b Binary files /dev/null and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/08581c09-a6a5-4a56-9fc4-abf22b063c6a-3.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/2b351d68-3924-445a-94ef-047b16214e8a-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/2b351d68-3924-445a-94ef-047b16214e8a-0.avif index b0d50611c94..79e8a6a0f49 100644 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/2b351d68-3924-445a-94ef-047b16214e8a-0.avif and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/2b351d68-3924-445a-94ef-047b16214e8a-0.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/37e9a4cd-6efb-4ade-ad09-8139db9d58e9-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/37e9a4cd-6efb-4ade-ad09-8139db9d58e9-0.avif deleted file mode 100644 index 1f28e2b8938..00000000000 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/37e9a4cd-6efb-4ade-ad09-8139db9d58e9-0.avif and /dev/null differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/4ecb25c8-e572-49af-a879-9943039db131-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/4ecb25c8-e572-49af-a879-9943039db131-0.avif index e1fb4b9d932..58b33e7062c 100644 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/4ecb25c8-e572-49af-a879-9943039db131-0.avif and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/4ecb25c8-e572-49af-a879-9943039db131-0.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/625882a4-faeb-4d96-b441-c989f43c4dea-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/625882a4-faeb-4d96-b441-c989f43c4dea-0.avif index f782b46546a..926ac23b246 100644 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/625882a4-faeb-4d96-b441-c989f43c4dea-0.avif and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/625882a4-faeb-4d96-b441-c989f43c4dea-0.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/8ead3582-16df-4616-836c-bdce867ad6b8-1.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/8ead3582-16df-4616-836c-bdce867ad6b8-1.avif index 2aac7e07909..44683319c8a 100644 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/8ead3582-16df-4616-836c-bdce867ad6b8-1.avif and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/8ead3582-16df-4616-836c-bdce867ad6b8-1.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/a19d63ce-3572-4081-a008-c1332fbbe303-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/a19d63ce-3572-4081-a008-c1332fbbe303-0.avif index ebed715a25d..88949c6c72a 100644 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/a19d63ce-3572-4081-a008-c1332fbbe303-0.avif and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/a19d63ce-3572-4081-a008-c1332fbbe303-0.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/e9b99d48-8d33-46b5-bff5-480ab1c1c1f2-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/e9b99d48-8d33-46b5-bff5-480ab1c1c1f2-0.avif index 1dd1adb81fe..3c3de65d56e 100644 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/e9b99d48-8d33-46b5-bff5-480ab1c1c1f2-0.avif and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/e9b99d48-8d33-46b5-bff5-480ab1c1c1f2-0.avif differ diff --git a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/fd57d483-c70b-4ad5-b309-15750ad38bac-0.avif b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/fd57d483-c70b-4ad5-b309-15750ad38bac-0.avif index f122d140479..a1a7c509d1b 100644 Binary files a/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/fd57d483-c70b-4ad5-b309-15750ad38bac-0.avif and b/public/docs/images/tutorials/nishimori-phase-transition/extracted-outputs/fd57d483-c70b-4ad5-b309-15750ad38bac-0.avif differ