{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Bell and CHSH inequalities\n", "$\\newcommand{\\bra}[1]{\\left\\langle{#1}\\right|}$\n", "$\\newcommand{\\ket}[1]{\\left|{#1}\\right\\rangle}$\n", "\n", "The purpose of this notebook is to simulate the CHSH experiment\n", "described in the IBM Quantum Experience tutorial in the section\n", "entitled \n", "\n", ">Multiple Qubits, Gates, and Entangled States/Entanglement and Bell Tests" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First change your working directory to the qubiter directory in your computer, and add its path to the path environment variable." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/home/rrtucci/PycharmProjects/qubiter/qubiter/jupyter_notebooks\n", "/home/rrtucci/PycharmProjects/qubiter\n" ] } ], "source": [ "import os\n", "import sys\n", "print(os.getcwd())\n", "os.chdir('../../')\n", "print(os.getcwd())\n", "sys.path.insert(0,os.getcwd())" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "loaded OneQubitGate, WITHOUT autograd.numpy\n" ] } ], "source": [ "from qubiter.SEO_writer import *\n", "from qubiter.SEO_simulator import *\n", "from qubiter.StateVec import *\n", "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, we define matrices $S, T, H, \\sigma_X, \\sigma_Y, \\sigma_Z, I_2$.\n", "We will denote the Pauli matrices by $\\sigma_X, \\sigma_Y, \\sigma_Z$\n", "\n", "Recal that\n", "\n", "$S = diag(1, i) = e^{i \\frac{\\pi}{4}} e^{-i \\frac{\\pi}{4} \\sigma_Z}$\n", "\n", "$T = diag(1, e^{i \\frac{\\pi}{4}}) = e^{i \\frac{\\pi}{8}} e^{-i \\frac{\\pi}{8} \\sigma_Z}$\n", "\n", "$H = \\frac{1}{\\sqrt{2}}(\\sigma_Z + \\sigma_X)$\n", "\n", "$H^2 = 1$\n", "\n", "$H\\sigma_X H = \\sigma_Z$\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "smat = np.matrix([[1, 0], [0, 1j]])\n", "tmat = np.matrix([[1, 0], [0, np.exp(1j*np.pi/4)]])\n", "had = np.matrix([[1, 1], [1, -1]])/np.sqrt(2)\n", "sigx = np.matrix([[0, 1], [1, 0]])\n", "sigy = np.matrix([[0, -1j], [1j, 0]])\n", "sigz = np.matrix([[1, 0], [0, -1]])\n", "id2 = np.matrix([[1, 0], [0, 1]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define $\\sigma_{n} = \\hat{n}\\cdot\\vec{\\sigma}$\n", "for any 3dim unit vector $\\hat{n}$.\n", "\n", "Recall that \n", "\n", "$\\sigma_Z\\ket{0_Z} = \\ket{0_Z}$\n", "\n", "$\\sigma_Z\\ket{1_Z} = -\\ket{1_Z}$,\n", "\n", "or, more succinctly, \n", "\n", "$\\sigma_Z\\ket{b_Z} = (-1)^b\\ket{b_Z}$\n", "\n", "for $b=0,1$.\n", "\n", "Likewise,\n", "\n", "$\\sigma_n\\ket{b_n} = (-1)^b\\ket{b_n}$\n", "\n", "for any 3dim unit vector $\\hat{n}$ and $b=0, 1$.\n", "\n", "One can show by Taylor expansion that\n", "\n", "$e^{i\\theta \\sigma_n} = \\cos(\\theta) + i\\sigma_n \\sin(\\theta)$" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def exp_mat2(theta, vec4):\n", " # vec4 is 4 dimensional np.array. Zero component not used.\n", " unit_vec = np.array([0, vec4[1], vec4[2], vec4[3]])\n", " unit_vec = unit_vec/np.linalg.norm(unit_vec)\n", "\n", " mat = unit_vec[1]*sigx + unit_vec[2]*sigy + unit_vec[3]*sigz\n", " return np.cos(theta)*id2 + 1j*mat*np.sin(theta)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define\n", "\n", "$roty = e^{i \\frac{\\pi}{8}\\sigma_Y}$\n", "\n", "$\\hat{w} = \\frac{1}{\\sqrt{2}}(\\hat{x} + \\hat{z})$\n", "\n", "$\\hat{v} = \\frac{1}{\\sqrt{2}}(-\\hat{x} + \\hat{z})$\n", "\n", "$sigw = \\sigma_W = \\frac{1}{\\sqrt{2}}(\\sigma_X + \\sigma_Z)$\n", "\n", "$sigv = \\sigma_V = \\frac{1}{\\sqrt{2}}(-\\sigma_X + \\sigma_Z)$\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "roty = exp_mat2(np.pi/8, np.array([0, 0, 1, 0]))\n", "sigw = (sigx + sigz)/np.sqrt(2)\n", "sigv = (-sigx + sigz)/np.sqrt(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check that\n", "\n", "$\\sigma_W = e^{-i \\frac{\\pi}{8}\\sigma_Y}\\sigma_Z e^{i \\frac{\\pi}{8}\\sigma_Y}$\n", "\n", "$\\sigma_V = e^{i \\frac{\\pi}{8}\\sigma_Y}\\sigma_Z e^{-i \\frac{\\pi}{8}\\sigma_Y}$" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.5700924586837752e-16\n", "1.5700924586837752e-16\n" ] } ], "source": [ "print(np.linalg.norm(sigw - roty.getH()*sigz*roty))\n", "print(np.linalg.norm(sigv - roty*sigz*roty.getH()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check that\n", "\n", "$ e^{i \\frac{\\pi}{8}\\sigma_Y} = e^{-i \\frac{\\pi}{8}} S^\\dagger H T H S$" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.9641608582688534e-16\n" ] } ], "source": [ "roty1 = np.exp(-1j*np.pi/8)*smat.getH()*had*tmat*had*smat\n", "print(np.linalg.norm(roty - roty1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Therefore, (Note that $S$ and $\\sigma_Z$ are both diagonal so they commute)\n", "\n", "$\\sigma_W = (S^\\dagger H T^\\dagger H S) \\sigma_Z (S^\\dagger H T H S)=\n", "(S^\\dagger H T^\\dagger H ) \\sigma_Z ( H T H S)$\n", "\n", "$\\sigma_V =\n", "(S^\\dagger H T H ) \\sigma_Z ( H T^\\dagger H S)$\n", "\n", "Note that \n", "\n", "$\\sigma_Z =\\ket{0_Z}\\bra{0_Z} - \\ket{1_Z}\\bra{1_Z} $\n", "\n", "so the same is true if we replace the $Z$ by $W$ or $V$ or any 3dim unit vector.\n", "\n", "Therefore,\n", "a W measurement $\\bra{b_W}$ is related to a Z measurment $\\bra{ b_Z}$ by\n", "\n", "$\\bra{ b_W} = \\bra{ b_Z} H T H S$\n", "\n", "Likewise, \n", "\n", "$\\bra{ b_V} = \\bra{ b_Z} H T^\\dagger H S$\n", "\n", "for $b= 0, 1$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that\n", "\n", "$\\bra{\\psi} \\sigma_A(0) \\sigma_B(1)\\ket{\\psi}\n", "=\\bra{\\psi}\n", "\\begin{array}{c}\n", "(\\ket{0_A}\\bra{0_A} - \\ket{1_A}\\bra{1_A} )(0)\n", "\\\\\n", "(\\ket{0_B}\\bra{0_B} - \\ket{1_B}\\bra{1_B})(1)\n", "\\end{array}\n", "\\ket{\\psi}$\n", "\n", "so \n", "\n", "$\\bra{\\psi} \\sigma_A(0) \\sigma_B(1)\\ket{\\psi}\n", "= Prob(0, 0) + Prob(1, 1) - Prob(0, 1) - Prob(1, 0)$" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def write_bell_plus(file_prefix, bell_only=True, extra_had=False, t_herm=False):\n", " num_qbits = 2\n", " z_axis = 3\n", " emb = CktEmbedder(num_qbits, num_qbits)\n", " print('-------------------', file_prefix)\n", " wr = SEO_writer(file_prefix, emb)\n", " wr.write_one_qbit_gate(0, OneQubitGate.had2)\n", "\n", " control_pos = 0\n", " target_pos = 1\n", " trols = Controls.new_single_trol(num_qbits, control_pos, kind=True)\n", " wr.write_controlled_one_qbit_gate(\n", " target_pos, trols, OneQubitGate.sigx)\n", "\n", " if not bell_only:\n", " if extra_had:\n", " wr.write_one_qbit_gate(0, OneQubitGate.had2) # H(0)\n", "\n", " wr.write_one_qbit_gate(1, OneQubitGate.rot_ax, [-np.pi/4, z_axis]) # S(1)\n", " wr.write_one_qbit_gate(1, OneQubitGate.had2) # H(1)\n", " if t_herm:\n", " pm_one = -1\n", " else:\n", " pm_one = 1\n", " wr.write_one_qbit_gate(1, OneQubitGate.rot_ax,\n", " [-pm_one*np.pi/8, z_axis]) # T(1) if pm_one=1\n", " wr.write_one_qbit_gate(1, OneQubitGate.had2) # H(1)\n", " wr.close_files()\n", " wr.print_pic_file(jup=True)\n", " init_st_vec = StateVec.get_standard_basis_st_vec([0, 0])\n", " sim = SEO_simulator(file_prefix, num_qbits, init_st_vec)\n", " StateVec.describe_st_vec_dict(sim.cur_st_vec_dict, print_st_vec=True, do_pp=True,\n", " omit_zero_amps=True, show_pp_probs=True)\n", " fin_st_vec = sim.cur_st_vec_dict[\"pure\"]\n", " print('Prob(bit0=j, bit1=k) for j,k=0,1:')\n", " prob_arr = np.abs(fin_st_vec.arr)**2\n", " print(prob_arr)\n", " mean = prob_arr[0, 0] \\\n", " + prob_arr[1, 1] \\\n", " - prob_arr[0, 1] \\\n", " - prob_arr[1, 0]\n", " print('mean=', mean)\n", " return mean\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "------------------- bell_zz_meas\n" ] }, { "data": { "text/html": [ "
1
|   H
2
X---@
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "*********branch= pure\n", "state vector:\n", "ZL convention (Zero bit Last in state tuple)\n", "(00)ZL ( 0.707107 + 0.000000j)\t prob=0.500000\n", "(11)ZL ( 0.707107 + 0.000000j)\t prob=0.500000\n", "total probability of state vector (=one if no measurements)= 1.000000\n", "dictionary with key=qubit, value=(Prob(0), Prob(1))\n", "{0: (0.5, 0.5), 1: (0.5, 0.5)}\n", "Prob(bit0=j, bit1=k) for j,k=0,1:\n", "[[0.5 0. ]\n", " [0. 0.5]]\n", "mean= 0.9999999999999998\n" ] } ], "source": [ "# sigz(0)sigz(1) measurement\n", "file_prefix = 'bell_zz_meas'\n", "mean_zz = write_bell_plus(file_prefix, bell_only=True)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "------------------- bell_zw_meas\n" ] }, { "data": { "text/html": [ "
1
|   H
2
X---@
3
Rz  |
4
H   |
5
Rz  |
6
H   |
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "*********branch= pure\n", "state vector:\n", "ZL convention (Zero bit Last in state tuple)\n", "(00)ZL ( 0.461940 - 0.461940j)\t prob=0.426777\n", "(10)ZL (-0.191342 - 0.191342j)\t prob=0.073223\n", "(01)ZL ( 0.191342 - 0.191342j)\t prob=0.073223\n", "(11)ZL ( 0.461940 + 0.461940j)\t prob=0.426777\n", "total probability of state vector (=one if no measurements)= 1.000000\n", "dictionary with key=qubit, value=(Prob(0), Prob(1))\n", "{0: (0.5, 0.5), 1: (0.5, 0.5)}\n", "Prob(bit0=j, bit1=k) for j,k=0,1:\n", "[[0.4267767 0.0732233]\n", " [0.0732233 0.4267767]]\n", "mean= 0.7071067811865472\n" ] } ], "source": [ "# sigz(0)sigw(1) measurement\n", "file_prefix = 'bell_zw_meas'\n", "mean_zw = write_bell_plus(file_prefix, bell_only=False, extra_had=False, t_herm=False)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "------------------- bell_zv_meas\n" ] }, { "data": { "text/html": [ "
1
|   H
2
X---@
3
Rz  |
4
H   |
5
Rz  |
6
H   |
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "*********branch= pure\n", "state vector:\n", "ZL convention (Zero bit Last in state tuple)\n", "(00)ZL ( 0.461940 - 0.461940j)\t prob=0.426777\n", "(10)ZL ( 0.191342 + 0.191342j)\t prob=0.073223\n", "(01)ZL (-0.191342 + 0.191342j)\t prob=0.073223\n", "(11)ZL ( 0.461940 + 0.461940j)\t prob=0.426777\n", "total probability of state vector (=one if no measurements)= 1.000000\n", "dictionary with key=qubit, value=(Prob(0), Prob(1))\n", "{0: (0.5, 0.5), 1: (0.5, 0.5)}\n", "Prob(bit0=j, bit1=k) for j,k=0,1:\n", "[[0.4267767 0.0732233]\n", " [0.0732233 0.4267767]]\n", "mean= 0.7071067811865472\n" ] } ], "source": [ "# sigz(0)sigv(1) measurement\n", "file_prefix = 'bell_zv_meas'\n", "mean_zv = write_bell_plus(file_prefix, bell_only=False, extra_had=False, t_herm=True)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "------------------- bell_xw_meas\n" ] }, { "data": { "text/html": [ "
1
|   H
2
X---@
3
|   H
4
Rz  |
5
H   |
6
Rz  |
7
H   |
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "*********branch= pure\n", "state vector:\n", "ZL convention (Zero bit Last in state tuple)\n", "(00)ZL ( 0.461940 - 0.461940j)\t prob=0.426777\n", "(10)ZL ( 0.191342 + 0.191342j)\t prob=0.073223\n", "(01)ZL ( 0.191342 - 0.191342j)\t prob=0.073223\n", "(11)ZL (-0.461940 - 0.461940j)\t prob=0.426777\n", "total probability of state vector (=one if no measurements)= 1.000000\n", "dictionary with key=qubit, value=(Prob(0), Prob(1))\n", "{0: (0.5, 0.5), 1: (0.5, 0.5)}\n", "Prob(bit0=j, bit1=k) for j,k=0,1:\n", "[[0.4267767 0.0732233]\n", " [0.0732233 0.4267767]]\n", "mean= 0.7071067811865469\n" ] } ], "source": [ "# sigx(0)sigw(1) measurement\n", "file_prefix = 'bell_xw_meas'\n", "mean_xw = write_bell_plus(file_prefix, bell_only=False, extra_had=True, t_herm=False)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "------------------- bell_xv_meas\n" ] }, { "data": { "text/html": [ "
1
|   H
2
X---@
3
|   H
4
Rz  |
5
H   |
6
Rz  |
7
H   |
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "*********branch= pure\n", "state vector:\n", "ZL convention (Zero bit Last in state tuple)\n", "(00)ZL ( 0.191342 - 0.191342j)\t prob=0.073223\n", "(10)ZL ( 0.461940 + 0.461940j)\t prob=0.426777\n", "(01)ZL ( 0.461940 - 0.461940j)\t prob=0.426777\n", "(11)ZL (-0.191342 - 0.191342j)\t prob=0.073223\n", "total probability of state vector (=one if no measurements)= 1.000000\n", "dictionary with key=qubit, value=(Prob(0), Prob(1))\n", "{0: (0.5, 0.5), 1: (0.5, 0.5)}\n", "Prob(bit0=j, bit1=k) for j,k=0,1:\n", "[[0.0732233 0.4267767]\n", " [0.4267767 0.0732233]]\n", "mean= -0.7071067811865468\n" ] } ], "source": [ "# sigx(0)sigv(1) measurement\n", "file_prefix = 'bell_xv_meas'\n", "mean_xv = write_bell_plus(file_prefix, bell_only=False, extra_had=True, t_herm=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let\n", "\n", "$mean\\_ab = \\bra{\\psi} \\sigma_A(0) \\sigma_B(1)\\ket{\\psi}$\n", "\n", "where\n", "\n", "$\\ket{\\psi} = \\frac{1}{\\sqrt{2}}(\\ket{00}+ \\ket{11})$\n", "\n", "Ckeck that \n", "\n", "$C = mean\\_zw + mean\\_zv + mean\\_xw - mean\\_xv = 2\\sqrt{2}$\n", "\n", "The classical analogue of $C$ satisfies $|C| \\leq 2$" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-----------------------\n", "mean_zw + mean_zv + mean_xw - mean_xv - 2*np.sqrt(2)= -2.220446049250313e-15\n" ] } ], "source": [ "print('-----------------------')\n", "print('mean_zw + mean_zv + mean_xw - mean_xv - 2*np.sqrt(2)=',\n", " mean_zw + mean_zv + mean_xw - mean_xv - 2*np.sqrt(2))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.9" }, "toc": { "colors": { "hover_highlight": "#DAA520", "running_highlight": "#FF0000", "selected_highlight": "#FFD700" }, "moveMenuLeft": true, "nav_menu": { "height": "30px", "width": "252px" }, "navigate_menu": true, "number_sections": true, "sideBar": true, "threshold": 4, "toc_cell": false, "toc_section_display": "block", "toc_window_display": false, "widenNotebook": false } }, "nbformat": 4, "nbformat_minor": 4 }