# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
from collections import Counter
import numpy as np
from braket.circuits import Circuit, Qubit
from braket.devices import Device
from braket.experimental.algorithms.bells_inequality.bells_inequality import (
bell_singlet_rotated_basis,
)
from braket.tasks import QuantumTask
[docs]
def create_chsh_inequality_circuits(
qubit0: Qubit = 0,
qubit1: Qubit = 1,
*,
a1: float = np.pi / 2,
a2: float = 0,
b1: float = np.pi / 4,
b2: float = 3 * np.pi / 4,
) -> list[Circuit]:
"""Create the four circuits for CHSH inequality. Default angles will give maximum violation of
the inequality.
Args:
qubit0 (Qubit): First qubit.
qubit1 (Qubit): Second qubit.
a1 (float): First basis rotation angle for first qubit.
a2 (float): Second basis rotation angle for first qubit.
b1 (float): First basis rotation angle for second qubit.
b2 (float): Second basis rotation angle for second qubit.
Returns:
List[Circuit]: List of quantum circuits.
"""
circ_a1b1 = bell_singlet_rotated_basis(qubit0, qubit1, a1, b1)
circ_a1b2 = bell_singlet_rotated_basis(qubit0, qubit1, a1, b2)
circ_a2b1 = bell_singlet_rotated_basis(qubit0, qubit1, a2, b1)
circ_a2b2 = bell_singlet_rotated_basis(qubit0, qubit1, a2, b2)
return [circ_a1b1, circ_a1b2, circ_a2b1, circ_a2b2]
[docs]
def run_chsh_inequality(
circuits: list[Circuit],
device: Device,
shots: int = 1_000,
) -> list[QuantumTask]:
"""Submit four CHSH circuits to a device.
Args:
circuits (List[Circuit]): Four CHSH inequality circuits to run.
device (Device): Quantum device or simulator.
shots (int): Number of shots. Defaults to 1_000.
Returns:
List[QuantumTask]: List of quantum tasks.
"""
tasks = [device.run(circ, shots=shots) for circ in circuits]
return tasks
[docs]
def get_chsh_results(
tasks: list[QuantumTask], verbose: bool = True
) -> tuple[float, list[Counter], float, float, float]:
"""Return CHSH task results after post-processing.
Args:
tasks (List[QuantumTask]): List of quantum tasks.
verbose (bool): Controls printing of the inequality result. Defaults to True.
Returns:
Tuple[float, List[Counter], float, float, float]: The chsh_value, list of results,
and the four probabilities: E_a1b1, E_a1b2, E_a2b1, E_a2b2.
"""
results = [task.result().result_types[0].value for task in tasks]
prob_same = np.array([d[0] + d[3] for d in results]) # 00 and 11 states
prob_different = np.array([d[1] + d[2] for d in results]) # 01 and 10 states
E_a1b1, E_a1b2, E_a2b1, E_a2b2 = np.array(prob_same) - np.array(prob_different)
chsh_value = E_a1b1 + E_a1b2 + E_a2b1 - E_a2b2
if verbose:
print(f"E_a1b1 = {E_a1b1}, E_a1b2 = {E_a1b2}, E_a2b1 = {E_a2b1}, E_a2b2 = {E_a2b2}")
print(f"\nCHSH inequality: {np.abs(chsh_value)} ≤ 2")
if np.abs(chsh_value) > 2:
print("CHSH inequality is violated!")
print(
"Notice that the quantity may not be exactly as predicted by Quantum theory. "
"This is may be due to finite shots or the effects of noise on the QPU."
)
else:
print("CHSH inequality is not violated.")
return chsh_value, results, E_a1b1, E_a1b2, E_a2b1, E_a2b2