Skip to content

Commit

Permalink
Migrate nonlocal games 1596 task1 - quantum (#1745)
Browse files Browse the repository at this point in the history
The link to the issue: #1596

This pull request is covering
1. CHSH quantum tasks (2.2, 2.4; 2.5 is converted to a demo)
2. CHSH discussion
3. Few changes in CHSH classical

---------

Co-authored-by: Mariia Mykhailova <[email protected]>
  • Loading branch information
ggridin and tcNickolas authored Aug 1, 2024
1 parent 76bbdb7 commit 2e6ffa1
Show file tree
Hide file tree
Showing 14 changed files with 394 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ namespace Kata.Verification {
operation CheckSolution() : Bool {
mutable wins = 0;
for i in 1..1000 {
let x = DrawRandomInt(0, 1) == 1 ? true | false;
let y = DrawRandomInt(0, 1) == 1 ? true | false;
let x = DrawRandomBool(0.5);
let y = DrawRandomBool(0.5);
let (a, b) = (Kata.AliceClassical(x), Kata.BobClassical(y));
if ((x and y) == (a != b)) {
set wins = wins + 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
**Input:**
* Alice and Bob's starting bits (X and Y).
* Alice and Bob's output bits (A and B).

- Alice and Bob's starting bits (X and Y).
- 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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Kata {
operation AliceQuantum (bit : Bool, qubit : Qubit) : Bool {
// Implement your solution here...

return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Kata {
operation AliceQuantum (bit : Bool, qubit : Qubit) : Bool {
if bit {
let q = MResetX(qubit);
return q == One;
}
else {
let q = MResetZ(qubit);
return q == One;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
namespace Kata.Verification {
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Random;

@EntryPoint()
operation CheckSolution() : Bool {
use q = Qubit();
for _ in 1 .. 4 {
// repeat 4 times since we are testing a measurement and wrong basis still might get
// the correct answer, reduces probability of false positives
let result = Kata.AliceQuantum(false, q);
Reset(q);
if (result != false) {
Message("Measuring |0⟩ in the Z basis returned incorrect value; expected false");
return false;
}

// apply the Pauli X gate
X(q);
let result = Kata.AliceQuantum(false, q);
Reset(q);
if (result != true) {
Message("Measuring |1⟩ in the Z basis returned incorrect value; expected true");
return false;
}

// apply the Hadamard gate
H(q);
let result = Kata.AliceQuantum(true, q);
Reset(q);
if (result != false) {
Message("Measuring |+⟩ in the X basis returned incorrect value; expected false");
return false;
}

// apply the Pauli X and then the Hadamard gate
X(q);
H(q);
let result = Kata.AliceQuantum(true, q);
Reset(q);
if (result != true) {
Message("Measuring |-⟩ in the X basis returned incorrect value; expected true");
return false;
}
}
Message("Correct!");
true
}
}
12 changes: 12 additions & 0 deletions katas/content/nonlocal_games/chsh_quantum_alice_strategy/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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.

**Inputs:**

- Alice's starting bit (X).
- 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 measurement result as Boolean value: map `Zero` to false and `One` to true.
The state of the qubit after the operation does not matter.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
In Q#, you can perform measurements in a specific basis using either the
[Measure operation](https://learn.microsoft.com/qsharp/api/qsharp-lang/microsoft.quantum.intrinsic/measure)
or convenient shorthands for measure-and-reset-to-$\ket{0}$ sequence of operations
[MResetZ](https://learn.microsoft.com/qsharp/api/qsharp-lang/microsoft.quantum.measurement/mresetz) and
[MResetX](https://learn.microsoft.com/qsharp/api/qsharp-lang/microsoft.quantum.measurement/mresetx).

(See the the lesson below for details on why Alice should follow this strategy.)

@[solution]({
"id": "nonlocal_games__chsh_quantum_alice_strategy_solution",
"codePath": "Solution.qs"
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Kata {
open Microsoft.Quantum.Math;

operation BobQuantum (bit : Bool, qubit : Qubit) : Bool {
// Implement your solution here...

return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Kata {
open Microsoft.Quantum.Math;

operation BobQuantum (bit : Bool, qubit : Qubit) : Bool {
let angle = 2.0 * PI() / 8.0;
Ry(not bit ? -angle | angle, qubit);
return M(qubit) == One;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
namespace Kata.Verification {
open Microsoft.Quantum.Math;

operation RotateBobQubit (clockwise : Bool, qubit : Qubit) : Unit {
if (clockwise) {
Ry(-PI()/4.0, qubit);
} else {
Ry(PI()/4.0, qubit);
}
}

@EntryPoint()
operation CheckSolution() : Bool {
for _ in 1 .. 4 {
// repeat 4 times since we are testing a measurement and wrong basis still might get
// the correct answer, reduces probability of false positives
use q = Qubit();
RotateBobQubit(false, q);
let result = Kata.BobQuantum(false, q);
Reset(q);
if (result != false) {
Message("π/8 from |0⟩ not measured as false");
return false;
}

X(q);
RotateBobQubit(false, q);
let result = Kata.BobQuantum(false, q);
Reset(q);
if (result != true) {
Message("π/8 from |1⟩ not measured as true");
return false;
}

RotateBobQubit(true, q);
let result = Kata.BobQuantum(true, q);
Reset(q);
if (result != false) {
Message("-π/8 from |0⟩ not measured as false");
return false;
}

X(q);
RotateBobQubit(true, q);
let result = Kata.BobQuantum(true, q);
Reset(q);
if (result != true) {
Message("-π/8 from |1⟩ not measured as true");
return false;
}
}
Message("Correct!");
true
}
}
11 changes: 11 additions & 0 deletions katas/content/nonlocal_games/chsh_quantum_bob_strategy/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
**Inputs:**

- Bob's starting bit (Y).
- 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 measurement result as a Boolean value: map `Zero` to false and `One` to true.
The state of the qubit after the operation does not matter.

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.
11 changes: 11 additions & 0 deletions katas/content/nonlocal_games/chsh_quantum_bob_strategy/solution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
A suitable $R_y$ rotation can be used to go from the computational basis $\{ \ket{0}, \ket{1} \}$ to the $\{ \ket{\psi_+}, \ket{\psi_-} \}$ basis and vice versa.

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 $R_y$ gate (note the negation of the Boolean parameter we need to do).

(See the lesson below for details on why Bob should follow this strategy.)

@[solution]({
"id": "nonlocal_games__chsh_quantum_bob_strategy_solution",
"codePath": "Solution.qs"
})
52 changes: 52 additions & 0 deletions katas/content/nonlocal_games/examples/CHSHGameDemo.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
namespace Quantum.Kata.CHSHGame {
open Microsoft.Quantum.Random;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Convert;

function WinCondition (x : Bool, y : Bool, a : Bool, b : Bool) : Bool {
return (x and y) == (a != b);
}

function AliceClassical (x : Bool) : Bool {
return false;
}

function BobClassical (y : Bool) : Bool {
return false;
}

operation AliceQuantum (bit : Bool, qubit : Qubit) : Bool {
if bit {
return MResetX(qubit) == One;
}
return MResetZ(qubit) == One;
}

operation BobQuantum (bit : Bool, qubit : Qubit) : Bool {
let angle = 2.0 * PI() / 8.0;
Ry(not bit ? -angle | angle, qubit);
return M(qubit) == One;
}

@EntryPoint()
operation CHSH_GameDemo() : Unit {
use (aliceQubit, bobQubit) = (Qubit(), Qubit());
mutable classicalWins = 0;
mutable quantumWins = 0;
let iterations = 1000;
for _ in 1 .. iterations {
H(aliceQubit);
CNOT(aliceQubit, bobQubit);
let (x, y) = (DrawRandomBool(0.5), DrawRandomBool(0.5));
if WinCondition(x, y, AliceClassical(x), BobClassical(y)) {
set classicalWins += 1;
}
if WinCondition(x, y, AliceQuantum(x, aliceQubit), BobQuantum(y, bobQubit)) {
set quantumWins += 1;
}
ResetAll([aliceQubit, bobQubit]);
}
Message($"Percentage of classical wins is {100.0*IntAsDouble(classicalWins)/IntAsDouble(iterations)}%");
Message($"Percentage of quantum wins is {100.0*IntAsDouble(quantumWins)/IntAsDouble(iterations)}%");
}
}
Loading

0 comments on commit 2e6ffa1

Please sign in to comment.