# -*- coding: utf-8 -*-
# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Q#
#     language: qsharp
#     name: iqsharp
# ---

# # CHSH Game Workbook
#
# **What is this workbook?**
# A workbook is a collection of problems, accompanied by solutions to them. 
# The explanations focus on the logical steps required to solve a problem; they illustrate the concepts that need to be applied to come up with a solution to the problem, explaining the mathematical steps required. 
#
# Note that a workbook should not be the primary source of knowledge on the subject matter; it assumes that you've already read a tutorial or a textbook and that you are now seeking to improve your problem-solving skills. You should attempt solving the tasks of the respective kata first, and turn to the workbook only if stuck. While a textbook emphasizes knowledge acquisition, a workbook emphasizes skill acquisition.
#
# This workbook describes the solutions to the problems offered in the [CHSH Game kata](./CHSHGame.ipynb). 
# Since the tasks are offered as programming problems, the explanations also cover some elements of Q# that might be non-obvious for a first-time user.

# ## Part I. Classical CHSH
#

# ### Task 1.1. Win Condition
# **Input:** 
#
#   1. Alice and Bob's starting bits (X and Y),
#
#   2. Alice and Bob's output bits (A and B).
#
# **Output:** 
# True if Alice and Bob won the CHSH game, that is, if X ∧ Y = A ⊕ B, and false otherwise.

# ### Solution
#
# There are four input pairs (X, Y) possible, (0,0), (0,1), (1,0), and (1,1), each with 25% probability.
# In order to win, Alice and Bob have to output different bits if the input is (1,1), and same bits otherwise.
#
# To check whether the win condition holds, you need to compute $x \wedge y$ and $a \oplus b$ and to compare these values: if they are equal, Alice and Bob won. [`Microsoft.Quantum.Logical`](https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.logical) library offers you logical functions `And` and `Xor` which you can use for this computation. Alternatively, you can compute these values using built-in operators: $x \wedge y$ as `x and y` and $a \oplus b$ as `a != b`.

# +
%kata T11_WinCondition_Test 

open Microsoft.Quantum.Logical;

function WinCondition (x : Bool, y : Bool, a : Bool, b : Bool) : Bool {
    let p = And(x, y);
    let u = Xor(a, b);
    return (p == u);
}
# -

# [Return to task 1.1 of the CHSH Game kata.](./CHSHGame.ipynb#Task-1.1.-Win-Condition)

# ### Task 1.2. Alice and Bob's classical strategy
#
# In this task you have to implement two functions, one for Alice's classical strategy and one for Bob's.
# Note that they are covered by one test, so you have to implement both to pass the test. Once you implement one of the strategies, execute its cell - it will fail with the error message indicating that the other strategy is not implemented yet. Once you implement the second strategy, execute its cell to get the test result.
#
# **Input:** Alice's OR Bob's starting bit (X or Y, respectively).
#
# **Output:** The bit that Alice OR Bob should output (A or B, respectively) to maximize their chance of winning.

# ### Solution
#
# If Alice and Bob always return TRUE, they will have a 75% win rate,
# since TRUE ⊕ TRUE = FALSE, and the AND operation on their input bits will be false with 75% probability.
#
# Alternatively, Alice and Bob could agree to always return FALSE to achieve the same 75% win probability.
# A classical strategy cannot achieve a higher success probability.

# +
%kata T12_ClassicalStrategy_Test 

operation AliceClassical (x : Bool) : Bool {
    return true;
}

# +
%kata T12_ClassicalStrategy_Test 

operation BobClassical (y : Bool) : Bool {
    // Alternatively, Alice and Bob could agree to always return FALSE to achieve the same 75% win chances.
    return true;
}
# -

# [Return to task 1.2 of the CHSH Game kata.](./CHSHGame.ipynb#Task-1.2.-Alice-and-Bob's-classical-strategy)

# ## Part II. Quantum CHSH
#
# In the quantum version of the game, the players still can not
# communicate during the game, but they are allowed to share 
# qubits from a Bell pair before the start of the game.
#

# ### Task 2.1. Entangled pair
#
# **Input:** An array of two qubits in the $|00\rangle$ state.
#
# **Goal:** Create a Bell state $|\Phi^{+}\rangle = \frac{1}{\sqrt{2}} \big( |00\rangle + |11\rangle \big)$ on these qubits.

# ### Solution
#
# You can find a detailed explanation of the solution to this task in the [Superposition kata workbook](../Superposition/Workbook_Superposition.ipynb#bell-state).

# +
%kata T21_CreateEntangledPair_Test 

operation CreateEntangledPair (qs : Qubit[]) : Unit {
    H(qs[0]);
    // This performs a Hadamard transform on the first qubit
    // which produces the intermediate state (|00> + |10>) / sqrt(2).
    
    CX(qs[0], qs[1]);
    // CX (Controlled X, Controlled NOT, CNOT) operates on two qubits, putting the second qubit through a NOT gate
    // if and only if the first qubit is '1'.
    
    // The 4x4 operator matrix for CX is:
    // [1  0  0  0]
    // [0  1  0  0]
    // [0  0  0  1]
    // [0  0  1  0]
    
    // The original state |00> corresponds to the two-qubit amplitude vector [1, 0, 0, 0].
    
    // The state after the Hadamard transform is given by the column vector [1/sqrt(2), 0, 1/sqrt(2), 0].
    
    // The CX operator changes this vector to [1/sqrt(2), 0, 0, 1/sqrt(2)], which is the desired Bell state.
}
# -

# [Return to task 2.1 of the CHSH Game kata.](./CHSHGame.ipynb#Task-2.1.-Entangled-pair)

# ### Task 2.2. Alice's quantum strategy
#
# **Inputs:**
#
#   1. Alice's starting bit (X),
#
#   2. Alice's half of Bell pair she shares with Bob.
#
# **Goal:** Measure Alice's qubit in the Z basis if her bit is 0 (false), or the X basis if her bit is 1 (true), and return the result.
# The state of the qubit after the operation does not matter.

# ### Solution
#
# In Q#, you can perform measurements in a specific basis using either the 
# [Measure operation](https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.measure) 
# or convenient shorthands for measure-and-reset-to-$|0\rangle$ sequence of operations 
# [MResetZ](https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.measurement.mresetz) and 
# [MResetX](https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.measurement.mresetx).
#
# (See the [discussion](#discussion) below for details on why Alice should follow this strategy.)

# +
%kata T22_AliceQuantum_Test 

open Microsoft.Quantum.Measurement;

operation AliceQuantum (bit : Bool, qubit : Qubit) : Bool {
    if (bit) {
        let q = MResetX(qubit);
        return (q == One);
    }
    else {
        let q = MResetZ(qubit);
        return (q == One);
    }
}
# -

# [Return to task 2.2 of the CHSH Game kata.](./CHSHGame.ipynb#Task-2.2.-Alice's-quantum-strategy)

# ### Task 2.3. Rotate Bob's qubit
#
# **Inputs:**
#
#   1. The direction to rotate: true for clockwise, false for counterclockwise,
#
#   2. Bob's qubit.
#
# **Goal:** Rotate the qubit $\frac{\pi}{8}$ radians around the Y axis in the given direction.

# ### Solution
#
# In Q#, you can perform rotations around a specific axis using one of the rotation gates. 
# In our case the axis is Y, and the corresponding rotation gate is [Ry](https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.ry).
#
# Note that in the $R_y(\theta)$ matrix entries, the trigonometric functions are actually performed on $\frac{\theta}{2}$, so the angle input into the function has to be doubled.
#
# (See the [discussion](#discussion) below for details on why Bob should rotate the qubit.)

# +
%kata T23_RotateBobQubit_Test 

open Microsoft.Quantum.Math;

operation RotateBobQubit (clockwise : Bool, qubit : Qubit) : Unit {
    mutable dir = PI() / 8.0;
    if (clockwise) {
        set dir = dir * -1.0;
    }
    Ry(2.0 * dir, qubit);
}
# -

# [Return to task 2.3 of the CHSH Game kata.](./CHSHGame.ipynb#Task-2.3.-Rotate-Bob's-qubit)

# ### Task 2.4. Bob's quantum strategy
#
# **Inputs:**
#
#   1. Bob's starting bit (Y),
#
#   2. Bob's half of Bell pair he shares with Alice.
#
# **Goal:** Measure Bob's qubit in the $\frac{\pi}{8}$ basis if his bit is 0 (false), or the $-\frac{\pi}{8}$ basis if his bit is 1 (true), and return the result.
# The state of the qubit after the operation does not matter.

# ### Solution
#
# Measuring a qubit in the $\theta$ basis is the same as rotating the qubit by $\theta$, clockwise, and then making a standard measurement in the Z basis.
#
# To implement the described transformation in Q#, we need to rotate the qubit by $\frac{\pi}{8}$ clockwise if `bit = false` or counterclockwise if `bit = true` and then perform a measurement. 
# We can do the rotation using the previous task (note the negation of the boolean parameter we need to do).
#
# (See the [discussion](#discussion) below for details on why Bob should follow this strategy.)

# +
%kata T24_BobQuantum_Test 

open Microsoft.Quantum.Measurement;

operation BobQuantum (bit : Bool, qubit : Qubit) : Bool {
    RotateBobQubit(not bit, qubit);
    return M(qubit) == One;
}
# -

# [Return to task 2.4 of the CHSH Game kata.](./CHSHGame.ipynb#Task-2.4.-Bob's-quantum-strategy)

# ### Task 2.5. Play the CHSH game using the quantum strategy
#
# **Input:**
# Operations that return Alice and Bob's output bits (A and B) based on their quantum
# strategies and given their respective qubits from the Bell pair.
# Alice and Bob have already been told what their starting bits X and Y are.
#
# **Goal:** Return Alice and Bob's output bits (A, B).
# Note that this task uses strategies `AliceQuantum` and `BobQuantum`, which you've implemented in tasks 2.2 and 2.4, respectively.

# ### Solution
#
# Putting together the building blocks we've implemented into a strategy is very simple:
#
# 1. Allocate two qubits and prepare a Bell state on them (using `CreateEntangledPair` from task 2.1).
# 2. Send one of the qubits to Alice and another to Bob (this step is "virtual", not directly reflected in Q# code, other than making sure that Alice and Bob each act on their qubit only).
# 3. Have Alice and Bob perform their measurements on their respective qubits using `askAlice` and `askBob` operations.
# 4. Return their measurement results.

# +
%kata T25_PlayQuantumCHSH_Test 

operation PlayQuantumCHSH (askAlice : (Qubit => Bool), askBob : (Qubit => Bool)): (Bool, Bool) {
    using (bell = Qubit[2]) {
        CreateEntangledPair(bell);
        
        let A = askAlice(bell[0]);
        let B = askBob(bell[1]);
        
        return (A, B);
    }
}
# -

# [Return to task 2.5 of the CHSH Game kata.](./CHSHGame.ipynb#Task-2.5.-Play-the-CHSH-game-using-the-quantum-strategy)

# ### <a name="discussion"></a>Discussion: probability of victory for quantum strategy
#
# The above quantum strategy adopted by Alice and Bob offers a win rate of $\frac{2 + \sqrt{2}}{4}$, or about 85.36%. Let's see why this is the case.
#
# First, consider the outcome if Alice and Bob simply measure their qubits in the Z basis without manipulating them at all.  Because of the entanglement inherent to the Bell state they hold, their measurements will always agree (i.e., both true or both false).  
# This will suffice for victory in the three scenarios (0,0), (0,1) and (1,0) and fail for (1,1), so their win probability is 75%, the same as that for the straightforward classical strategies of invariably returning both true or both false.
#
# Now let's analyze the optimal quantum strategy.
#
# > As a reminder, probability "wavefunction" for a two-qubit state is given by the following length-4 vector of amplitudes:
# > 
# > $$
# \begin{bmatrix}
# \psi_{00}\\
# \psi_{01}\\
# \psi_{10}\\
# \psi_{11}
# \end{bmatrix}
# $$
# >
# > $|\psi_{ij}|^2$ gives the probability of observing the corresponding basis state $|ij\rangle$ upon measuring the qubit pair.
#
# The initial state $|00\rangle$ has $\psi_{00} = 1$ and $\psi_{01} = \psi_{10} = \psi_{11} = 0$.  
# The Bell state we prepare as the first step of the game has an amplitude vector as follows (we'll use decimal approximations for matrix elements):
#
# $$
# \begin{bmatrix}
# 1/\sqrt{2}\\
# 0\\
# 0\\
# 1/\sqrt{2}
# \end{bmatrix} = 
# \begin{bmatrix}
# 0.7071\\
# 0\\
# 0\\
# 0.7071
# \end{bmatrix}
# $$
#
# Let's analyze the probabilities of outcomes in case of different bits received by players.
#
# #### Case 1: Alice holds bit 0
#
# In this case Alice simply measures in the Z basis as above.  
#
# * When Bob's bit is 0, he rotates his qubit clockwise by $\pi/8$, which corresponds to the operator
#
#   $$
# \begin{bmatrix}
# 0.9239 & 0.3827 & 0 & 0\\
# -0.3827 & 0.9239 & 0 & 0\\
# 0 & 0 & 0.9239 & 0.3827\\
# 0 & 0 & -0.3827 & 0.9239
# \end{bmatrix}
# $$
#
#   This performs the $R_y$ rotation by $\pi/8$ radians clockwise on Bob's qubit while leaving Alice's qubit unchanged.
#
# * If Bob's bit were 1, he would rotate his qubit counterclockwise by $\pi/8$, applying a very similar operator
#
#  $$
# \begin{bmatrix}
# 0.9239 & -0.3827 & 0 & 0\\
# 0.3827 & 0.9239 & 0 & 0\\
# 0 & 0 & 0.9239 & -0.3827\\
# 0 & 0 & 0.3827 & 0.9239
# \end{bmatrix}
# $$
#
# Therefore, when Alice has bit 0, the application of the rotation operator to the Bell state gives
#
# $$
# \begin{bmatrix}
# 0.6533 \\
# -0.2706 \\
# 0.2706 \\
# 0.6533 
# \end{bmatrix} \text{ or }
# \begin{bmatrix}
# 0.6533\\
# 0.2706\\
# -0.2706\\
# 0.6533
# \end{bmatrix}
# $$
#
# depending on whether Bob holds 0 (left-hand case) or 1 (right-hand case).  
#
# The result of AND on their input bits will always be 0; thus they win when their outputs agree.  These two cases correspond to the top and bottom elements of the vectors above, with a combined probability of $(0.6533)^2 + (0.6533)^2 = 0.4268 + 0.4268 = 0.8536$, so they have an 85.36% win chance.
#
# #### Case 2: Alice holds bit 1
#
# When Alice holds bit 1, she measures in basis X (or, equivalently, Hadamard-transforms her qubit, leaving Bob's be, before making her Z-basis measurement).  This corresponds to applying the operator
#
# $$
# \begin{bmatrix}
# 0.7071 & 0 & 0.7071 & 0\\
# 0 & 0.7071 & 0 & 0.7071\\
# 0.7071 & 0 & -0.7071 & 0\\
# 0 & 0.7071 & 0 & -0.7071
# \end{bmatrix}
# $$
#
# to the Bell state, resulting in a vector of:
#
# $$
# \begin{bmatrix}
# 0.5\\
# 0.5\\
# 0.5\\
# -0.5
# \end{bmatrix}
# $$
#
# Now, one of the two rotation operators is applied depending on what bit Bob holds, transforming this vector into:
#
# $$
# \begin{bmatrix}
# 0.6533 \\
# 0.2706 \\
# 0.2706 \\
# -0.6533
# \end{bmatrix} \text{ or }
# \begin{bmatrix}
# 0.2706\\
# 0.6533\\
# 0.6533\\
# -0.2706
# \end{bmatrix}
# $$
#
# When Bob holds 0, they still want to return the same parity, which they again do with 85.36% probability (left-hand vector above). 
# But when Bob holds 1, the AND condition is now true and the players want to answer in opposite parity.  This corresponds to the second and third elements of the right-hand vector above. 
# Thanks to the "magic" of the combination of the counterclockwise rotation and Hadamard transform, they now do this with probability $(0.6533)^2 + (0.6533)^2 = 0.8536$ and thus 85.36% becomes their win odds once more.
#
# #### Side notes
#
# * If Bob never rotated his qubit, their entangled state would remain the Bell state if Alice held bit 0 and the state corresponding to $\frac12 \big(|00\rangle + |01\rangle + |10\rangle - |11\rangle\big)$ if Alice held bit 1.  
# While she and Bob would have a 100% success probability against Alice's 0 bit, they would have only a 50% chance of success if she held bit 1, and thus their win chance would revert to the 75% of the classical strategy again.
#
# * It can be proven that Alice and Bob cannot surpass an overall win probability of 85.36% in the CHSH game.  This entails a higher-level discussion of quantum observable theory, for instance see [Tsirelson's bound](https://en.wikipedia.org/wiki/Tsirelson's_bound).

StarcoderdataJupyterScriptsDedupFiltered