Skip to content

Entanglement Testing (CHSH)

We test the entanglement of two qubits by whether the the bell state violates CHSH inequality and by how much.

Initially, we prepare a shared bell state for Alice and Bob \frac{1}{\sqrt{2}}(|00\rangle + |11\rangle).

# Importing standard Qiskit libraries and configuring account
from qiskit import QuantumCircuit, execute, IBMQ
from qiskit.tools.monitor import *
from qiskit.providers.ibmq.managed import IBMQJobManager

# Loading your IBM Q account(s)
import qiskit
from qiskit import IBMQ

provider = IBMQ.load_account()

import matplotlib.pyplot as plt
import numpy as np

import context
from device_independent_test import entanglement

def initial_state():
    return entanglement.create_bell_state()

initial_state().draw()
     ┌───┐     
q_0: ┤ H ├──■──
     └───┘┌─┴─┐
q_1: ─────┤ X ├
          └───┘

Then, Alice measures with observables \{X, Z\}, and Bob measures with observables \{H, H'\}, where X, Z are Pauli operator and H is a Hardamard operator, and H' = \begin{pmatrix} -1 & 1 \\ 1 & 1 \end{pmatrix}.

Measuring in Z basis is a default measurement, and we get the following equivalent circuit. Note that H = (X+Z)/2 and H' = (-X+Z)/2.

  • measure in X = H + measure in Z
  • measure in H = SHTH + measure in Z
  • measure in H' = SHT^\dagger H + measure in Z
# Alice measures with observable Z and Bob measures with observable H
measure_ZH = initial_state()
measure_ZH.s(1)
measure_ZH.h(1)
measure_ZH.t(1)
measure_ZH.h(1)
measure_ZH.measure_all()
measure_ZH.draw()
        ┌───┐                          ░ ┌─┐   
   q_0: ┤ H ├──■───────────────────────░─┤M├───
        └───┘┌─┴─┐┌───┐┌───┐┌───┐┌───┐ ░ └╥┘┌─┐
   q_1: ─────┤ X ├┤ S ├┤ H ├┤ T ├┤ H ├─░──╫─┤M├
             └───┘└───┘└───┘└───┘└───┘ ░  ║ └╥┘
meas_0: ══════════════════════════════════╩══╬═
                                             ║ 
meas_1: ═════════════════════════════════════╩═
                                               
# Alice measures with observable X and Bob measures with observable H
measure_XH = initial_state()
measure_XH.h(0)
measure_XH.s(1)
measure_XH.h(1)
measure_XH.t(1)
measure_XH.h(1)
measure_XH.measure_all()
measure_XH.draw()
        ┌───┐     ┌───┐                ░ ┌─┐   
   q_0: ┤ H ├──■──┤ H ├────────────────░─┤M├───
        └───┘┌─┴─┐├───┤┌───┐┌───┐┌───┐ ░ └╥┘┌─┐
   q_1: ─────┤ X ├┤ S ├┤ H ├┤ T ├┤ H ├─░──╫─┤M├
             └───┘└───┘└───┘└───┘└───┘ ░  ║ └╥┘
meas_0: ══════════════════════════════════╩══╬═
                                             ║ 
meas_1: ═════════════════════════════════════╩═
                                               
# Alice measures with observable Z and Bob measures with observable H'
measure_ZHp = initial_state()
measure_ZHp.s(1)
measure_ZHp.h(1)
measure_ZHp.tdg(1)
measure_ZHp.h(1)
measure_ZHp.measure_all()
measure_ZHp.draw()
        ┌───┐                            ░ ┌─┐   
   q_0: ┤ H ├──■─────────────────────────░─┤M├───
        └───┘┌─┴─┐┌───┐┌───┐┌─────┐┌───┐ ░ └╥┘┌─┐
   q_1: ─────┤ X ├┤ S ├┤ H ├┤ TDG ├┤ H ├─░──╫─┤M├
             └───┘└───┘└───┘└─────┘└───┘ ░  ║ └╥┘
meas_0: ════════════════════════════════════╩══╬═
                                               ║ 
meas_1: ═══════════════════════════════════════╩═
                                                 
# Alice measures with observable X and Bob measures with observable H'
measure_XHp = initial_state()
measure_XHp.h(0)
measure_XHp.s(1)
measure_XHp.h(1)
measure_XHp.tdg(1)
measure_XHp.h(1)
measure_XHp.measure_all()
measure_XHp.draw()
        ┌───┐     ┌───┐                  ░ ┌─┐   
   q_0: ┤ H ├──■──┤ H ├──────────────────░─┤M├───
        └───┘┌─┴─┐├───┤┌───┐┌─────┐┌───┐ ░ └╥┘┌─┐
   q_1: ─────┤ X ├┤ S ├┤ H ├┤ TDG ├┤ H ├─░──╫─┤M├
             └───┘└───┘└───┘└─────┘└───┘ ░  ║ └╥┘
meas_0: ════════════════════════════════════╩══╬═
                                               ║ 
meas_1: ═══════════════════════════════════════╩═
                                                 
def run_job(circuit, shots):
    job = execute(circuit, backend=provider.get_backend('ibmq_qasm_simulator'), shots=shots)
    job_monitor(job)
    return job
shots = 1000
ZH_counts = run_job(measure_ZH, shots).result().get_counts()
XH_counts = run_job(measure_XH, shots).result().get_counts()
ZHp_counts = run_job(measure_ZHp, shots).result().get_counts()
XHp_counts = run_job(measure_XHp, shots).result().get_counts()
Job Status: job has successfully run
Job Status: job has successfully run
Job Status: job has successfully run
Job Status: job has successfully run

To calculate the left-hand side of the CHSH inequality given by $$ \mid \langle ZH \rangle + \langle XH \rangle + \langle ZH' \rangle - \langle XH' \rangle \mid \leq 2 $$ we compute the correlated expectation given by $$ \langle AB \rangle = Pr(00|AB) + Pr(11|AB) - Pr(01|AB) - Pr(10|AB). $$

exp_ZH = entanglement.compute_expectation_for_CHSH(ZH_counts, shots)
exp_XH = entanglement.compute_expectation_for_CHSH(XH_counts, shots)
exp_ZHp = entanglement.compute_expectation_for_CHSH(ZHp_counts, shots)
exp_XHp = entanglement.compute_expectation_for_CHSH(XHp_counts, shots)

CHSH = exp_ZH + exp_XH + exp_ZHp - exp_XHp
print(CHSH)
2.778

This shows the test violates CHSH inequality, and the initial state is indeed an entangled state. We know that bell state violates this inequality with the value 2\sqrt{2} \approx 2.828, and the value we get is pretty close to this value.

This entanglement test can be done using the HandShake suite.

from device_independent_test.handshake import HandShake
from device_independent_test.quantum_communicator import LocalDispatcher

dispatcher = LocalDispatcher([provider.get_backend('ibmq_qasm_simulator')])
handshake = HandShake(dispatcher)

tolerance = 0.1
shots = 1000
handshake.entanglement(tolerance, shots)
Passed Entanglement with value:  2.87





(True, 2.87)

We can run it on the actual quantum machine by instantiating the dispatcher with actual machine.

from qiskit.providers.ibmq import least_busy

backend = least_busy(provider.backends())
dispatcher = LocalDispatcher([backend])
handshake = HandShake(dispatcher)

tolerance = 0.7
shots = 2000
handshake.entanglement(tolerance, shots, 0)
Passed Entanglement with value:  2.582





(True, 2.582)

The quantum computers can have quite a large error. They typically violate the CHSH inequality, however, a wide tolerance has to be used to ensure a pass. The allowed tolerance is decided by the computation task at hand.