498 lines
18 KiB
Plaintext
498 lines
18 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "30734ce9",
|
||
"metadata": {},
|
||
"source": [
|
||
"# CHSH inequality"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "6b41d6b3",
|
||
"metadata": {},
|
||
"source": [
|
||
"*Usage estimate: 4 minutes on IBM Kyiv (NOTE: This is an estimate only. Your runtime may vary.)*"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "93ae1484",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Background\n",
|
||
"\n",
|
||
"In this tutorial, you will run an experiment on a quantum computer to demonstrate the violation of the CHSH inequality with the Estimator primitive.\n",
|
||
"\n",
|
||
"The CHSH inequality, named after the authors Clauser, Horne, Shimony, and Holt, is used to experimentally prove Bell's theorem (1969). This theorem asserts that local hidden variable theories cannot account for some consequences of entanglement in quantum mechanics. The violation of the CHSH inequality is used to show that quantum mechanics is incompatible with local hidden-variable theories. This is an important experiment for understanding the foundation of quantum mechanics.\n",
|
||
"\n",
|
||
"The 2022 Nobel Prize for Physics was awarded to Alain Aspect, John Clauser and Anton Zeilinger in part for their pioneering work in quantum information science, and in particular, for their experiments with entangled photons demonstrating violation of Bell’s inequalities."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "6f5d9398-5aaa-4596-a554-61c923f0c2d2",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Requirements\n",
|
||
"\n",
|
||
"Before starting this tutorial, ensure that you have the following installed:\n",
|
||
"\n",
|
||
"* Qiskit SDK 1.0 or later\n",
|
||
"* Qiskit Runtime (`pip install qiskit-ibm-runtime`) 0.22 or later\n",
|
||
"* Visualization support (`'qiskit[visualization]'`)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "b5df762e",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Setup"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"id": "3938d4a6",
|
||
"metadata": {},
|
||
"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",
|
||
"# Plotting routines\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"import matplotlib.ticker as tck"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "66d5e2e2",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Step 1: Map classical inputs to a quantum problem"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "36669708",
|
||
"metadata": {},
|
||
"source": [
|
||
"For this experiment, we will create an entangled pair on which we measure each qubit on two different bases. We will label the bases for the first qubit $A$ and $a$ and the bases for the second qubit $B$ and $b$. This allows us to compute the CHSH quantity $S_1$:\n",
|
||
"\n",
|
||
"$$\n",
|
||
"S_1 = A(B-b) + a(B+b).\n",
|
||
"$$\n",
|
||
"\n",
|
||
"Each observable is either $+1$ or $-1$. Clearly, one of the terms $B\\pm b$ must be $0$, and the other must be $\\pm 2$. Therefore, $S_1 = \\pm 2$. The average value of $S_1$ must satisfy the inequality:\n",
|
||
"\n",
|
||
"$$\n",
|
||
"|\\langle S_1 \\rangle|\\leq 2.\n",
|
||
"$$\n",
|
||
"\n",
|
||
"Expanding $S_1$ in terms of $A$, $a$, $B$, and $b$ results in:\n",
|
||
"\n",
|
||
"$$\n",
|
||
"|\\langle S_1 \\rangle| = |\\langle AB \\rangle - \\langle Ab \\rangle + \\langle aB \\rangle + \\langle ab \\rangle| \\leq 2\n",
|
||
"$$\n",
|
||
"\n",
|
||
"You can define another CHSH quantity $S_2$:\n",
|
||
"\n",
|
||
"$$\n",
|
||
"S_2 = A(B+b) - a(B-b),\n",
|
||
"$$\n",
|
||
"\n",
|
||
"This leads to another inequality:\n",
|
||
"\n",
|
||
"$$\n",
|
||
"|\\langle S_2 \\rangle| = |\\langle AB \\rangle + \\langle Ab \\rangle - \\langle aB \\rangle + \\langle ab \\rangle| \\leq 2\n",
|
||
"$$\n",
|
||
"\n",
|
||
"If quantum mechanics can be described by local hidden variable theories, the previous inequalities must hold true. However, as is demonstrated in this notebook, these inequalities can be violated in a quantum computer. Therefore, quantum mechanics is not compatible with local hidden variable theories."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "2033cfcd",
|
||
"metadata": {},
|
||
"source": [
|
||
"If you want to learn more theory, explore [Entanglement in Action](https://learning.quantum-computing.ibm.com/course/basics-of-quantum-information/entanglement-in-action#the-chsh-game) with John Watrous.\n",
|
||
"\n",
|
||
"<ImageLink\n",
|
||
" title=\"Entanglement in Action | Understanding Quantum Information & Computation - Lesson 04\"\n",
|
||
" alt=\"Video thumbnail: John Watrous stands against a blue background.\"\n",
|
||
" href=\"https://youtube.com/watch?v=GSsElSQgMbU&t=2426\"\n",
|
||
" src=\"/docs/images/tutorials/chsh-inequality/youtube-thumbnail.avif\"\n",
|
||
"/>"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "d4cec8d8",
|
||
"metadata": {},
|
||
"source": [
|
||
"You will create an entangled pair between two qubits in a quantum computer by creating the Bell state $|\\Phi^+\\rangle = \\frac{|00\\rangle + |11\\rangle}{\\sqrt{2}}$. Using the Estimator primitive, you can directly obtain the expectation values needed ($\\langle AB \\rangle, \\langle Ab \\rangle, \\langle aB \\rangle$, and $\\langle ab \\rangle$) to calculate the expectation values of the two CHSH quantities $\\langle S_1\\rangle$ and $\\langle S_2\\rangle$. Before the introduction of the Estimator primitive, you would have to construct the expectation values from the measurement outcomes.\n",
|
||
"\n",
|
||
"You will measure the second qubit in the $Z$ and $X$ bases. The first qubit will be measured also in orthogonal bases, but with an angle with respect to the second qubit, which we are going to sweep between $0$ and $2\\pi$. As you will see, the Estimator primitive makes running parameterized circuits very easy. Rather than creating a series of CHSH circuits, you only need to create *one* CHSH circuit with a parameter specifying the measurement angle and a series of phase values for the parameter.\n",
|
||
"\n",
|
||
"Finally, you will analyze the results and plot them against the measurement angle. You will see that for certain range of measurement angles, the expectation values of CHSH quantities $|\\langle S_1\\rangle| > 2$ or $|\\langle S_2\\rangle| > 2$, which demonstrates the violation of the CHSH inequality."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"id": "16f323fb",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'ibm_torino'"
|
||
]
|
||
},
|
||
"execution_count": 3,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"# To run on hardware, select the backend with the fewest number of jobs in the queue\n",
|
||
"service = QiskitRuntimeService()\n",
|
||
"backend = service.least_busy(\n",
|
||
" operational=True, simulator=False, min_num_qubits=127\n",
|
||
")\n",
|
||
"backend.name"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "1ab329f2",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Create a parameterized CHSH circuit\n",
|
||
"\n",
|
||
"First, we write the circuit with the parameter $\\theta$, which we call `theta`. The [`Estimator` primitive](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.EstimatorV2) can enormously simplify circuit building and output analysis by directly providing expectation values of observables. Many problems of interest, especially for near-term applications on noisy systems, can be formulated in terms of expectation values. `Estimator` (V2) primitive can automatically change measurement basis based on the supplied observable."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"id": "6c77e40a",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/6c77e40a-0.svg\" alt=\"Output of the previous code cell\" />"
|
||
]
|
||
},
|
||
"execution_count": 3,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"theta = Parameter(\"$\\\\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": "de760250",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Create a list of phase values to be assigned later\n",
|
||
"\n",
|
||
"After creating the parameterized CHSH circuit, you will create a list of phase values to be assigned to the circuit in the next step. You can use the following code to create a list of 21 phase values range from $0$ to $2 \\pi$ with equal spacing, that is, $0$, $0.1 \\pi$, $0.2 \\pi$, ..., $1.9 \\pi$, $2 \\pi$."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"id": "bcb3b32b",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"number_of_phases = 21\n",
|
||
"phases = np.linspace(0, 2 * np.pi, number_of_phases)\n",
|
||
"# Phases need to be expressed as list of lists in order to work\n",
|
||
"individual_phases = [[ph] for ph in phases]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "6e559aed",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Observables\n",
|
||
"\n",
|
||
"Now we need observables from which to compute the expectation values. In our case we are looking at orthogonal bases for each qubit, letting the parameterized $Y-$ rotation for the first qubit sweep the measurement basis nearly continuously with respect to the second qubit basis. We will therefore choose the observables $ZZ$, $ZX$, $XZ$, and $XX$."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"id": "940fc1dc-89c5-4137-bea7-5e892dd7f36e",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# <CHSH1> = <AB> - <Ab> + <aB> + <ab> -> <ZZ> - <ZX> + <XZ> + <XX>\n",
|
||
"observable1 = SparsePauliOp.from_list(\n",
|
||
" [(\"ZZ\", 1), (\"ZX\", -1), (\"XZ\", 1), (\"XX\", 1)]\n",
|
||
")\n",
|
||
"\n",
|
||
"# <CHSH2> = <AB> + <Ab> - <aB> + <ab> -> <ZZ> + <ZX> - <XZ> + <XX>\n",
|
||
"observable2 = SparsePauliOp.from_list(\n",
|
||
" [(\"ZZ\", 1), (\"ZX\", 1), (\"XZ\", -1), (\"XX\", 1)]\n",
|
||
")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "efabedc4",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Step 2: Optimize problem for quantum hardware execution"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "4b2b4637-a2d4-41d6-a9c5-98fe3b8a2cd2",
|
||
"metadata": {},
|
||
"source": [
|
||
"To reduce the total job execution time, V2 primitives only accept circuits and observables that conforms to the instructions and connectivity supported by the target system (referred to as instruction set architecture (ISA) circuits and observables)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "5dcd3fea-3754-4c75-b11e-9216570336b7",
|
||
"metadata": {},
|
||
"source": [
|
||
"### ISA Circuit"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "9a5561eb",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/9a5561eb-0.svg\" alt=\"Output of the previous code cell\" />"
|
||
]
|
||
},
|
||
"execution_count": 6,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"target = backend.target\n",
|
||
"pm = generate_preset_pass_manager(target=target, optimization_level=3)\n",
|
||
"\n",
|
||
"chsh_isa_circuit = pm.run(chsh_circuit)\n",
|
||
"chsh_isa_circuit.draw(output=\"mpl\", idle_wires=False, style=\"iqp\")"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "718759d4-f1d8-45c3-9142-c8404059a892",
|
||
"metadata": {},
|
||
"source": [
|
||
"### ISA Observables"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "76b721cc-7f45-4195-ae61-53d29e2bf8d4",
|
||
"metadata": {},
|
||
"source": [
|
||
"Similarly, we need to transform the observables to make it backend compatible before running jobs with [`Runtime Estimator V2`](/docs/api/qiskit-ibm-runtime/estimator-v2#run). We can perform the transformation using the `apply_layout` the method of `SparsePauliOp` object."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"id": "a787d6f9-5df4-4e0b-b2f0-07948b882a94",
|
||
"metadata": {},
|
||
"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": "b7194399",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Step 3: Execute using Qiskit primitives\n",
|
||
"\n",
|
||
"In order to execute the entire experiment in one call to the [`Estimator`](https://docs.quantum-computing.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.EstimatorV2)."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "2d8ad9e1",
|
||
"metadata": {},
|
||
"source": [
|
||
"We can create a [Qiskit Runtime `Estimator`](/docs/api/qiskit-ibm-runtime/estimator-v2) primitive to compute our expectation values. The `EstimatorV2.run()` method takes an iterable of `primitive unified blocs (PUBs)`. Each PUB is an iterable in the format `(circuit, observables, parameter_values: Optional, precision: Optional)`."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"id": "e73db51f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# To run on a local simulator:\n",
|
||
"# Use the StatevectorEstimator from qiskit.primitives instead.\n",
|
||
"\n",
|
||
"estimator = Estimator(mode=backend)\n",
|
||
"\n",
|
||
"pub = (\n",
|
||
" chsh_isa_circuit, # ISA circuit\n",
|
||
" [[isa_observable1], [isa_observable2]], # ISA Observables\n",
|
||
" individual_phases, # Parameter values\n",
|
||
")\n",
|
||
"\n",
|
||
"job_result = estimator.run(pubs=[pub]).result()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "ace7dc90",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Step 4: Post-process and return result in desired classical format\n",
|
||
"\n",
|
||
"The estimator returns expectation values for both of the observables, $\\langle ZZ \\rangle - \\langle ZX \\rangle + \\langle XZ \\rangle + \\langle XX \\rangle$ and $\\langle ZZ \\rangle + \\langle ZX \\rangle - \\langle XZ \\rangle + \\langle XX \\rangle$."
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 9,
|
||
"id": "947fc660-073b-4dee-b347-358fd3e52ea2",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"chsh1_est = job_result[0].data.evs[0]\n",
|
||
"chsh2_est = job_result[0].data.evs[1]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 10,
|
||
"id": "f6267448",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/f6267448-0.svg\" alt=\"Output of the previous code cell\" />"
|
||
]
|
||
},
|
||
"metadata": {},
|
||
"output_type": "display_data"
|
||
}
|
||
],
|
||
"source": [
|
||
"fig, ax = plt.subplots(figsize=(10, 6))\n",
|
||
"\n",
|
||
"# results from hardware\n",
|
||
"ax.plot(phases / np.pi, chsh1_est, \"o-\", label=\"CHSH1\", zorder=3)\n",
|
||
"ax.plot(phases / np.pi, chsh2_est, \"o-\", label=\"CHSH2\", zorder=3)\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√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(phases / np.pi, -2, -2 * np.sqrt(2), color=\"0.6\", alpha=0.7)\n",
|
||
"\n",
|
||
"# set x tick labels to the unit of pi\n",
|
||
"ax.xaxis.set_major_formatter(tck.FormatStrFormatter(\"%g $\\\\pi$\"))\n",
|
||
"ax.xaxis.set_major_locator(tck.MultipleLocator(base=0.5))\n",
|
||
"\n",
|
||
"# set labels, and legend\n",
|
||
"plt.xlabel(\"Theta\")\n",
|
||
"plt.ylabel(\"CHSH witness\")\n",
|
||
"plt.legend()\n",
|
||
"plt.show()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "63e63853",
|
||
"metadata": {},
|
||
"source": [
|
||
"In the figure, the lines and gray areas delimit the bounds; the outer-most (dash-dotted) lines delimit the quantum-bounds ($\\pm 2$), whereas the inner (dashed) lines delimit the classical bounds ($\\pm 2\\sqrt{2}$). You can see that there are regions where the CHSH witness quantities exceeds the classical bounds. Congratulations! You have successfully demonstrated the violation of CHSH inequality in a real quantum system!"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "24942533",
|
||
"metadata": {},
|
||
"source": [
|
||
"## Tutorial survey\n",
|
||
"\n",
|
||
"Please take one minute to provide feedback on this tutorial. Your insights will help us improve our content offerings and user experience.\n",
|
||
"\n",
|
||
"[Link to survey](https://your.feedback.ibm.com/jfe/form/SV_3xxAgm1SF1wGp9k)"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"description": "Run an experiment on a quantum computer to demonstrate the violation of the CHSH inequality with the Estimator primitive.",
|
||
"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"
|
||
},
|
||
"platform": "cloud",
|
||
"title": "CHSH inequality",
|
||
"vscode": {
|
||
"interpreter": {
|
||
"hash": "1910f834ba40d1043b9ae723a4d216fb6c2faf55822807adca52e5ece8e3f1c8"
|
||
}
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|