Skip to content

Commit

Permalink
Migrate nonlocal games 1596 task2 ghz quantum (#1840)
Browse files Browse the repository at this point in the history
The link to the issue: #1596

This pull request covering
1. GHZ quantum tasks 2.1 (creating entangled triple).
2. GHZ quantum task 2.2 (quantum strategies).
3. Quantum strategy discussion.
4. GHZ quantum task 2.3 (quantum game) is converted to demo.

---------

Co-authored-by: Mariia Mykhailova <[email protected]>
Co-authored-by: César Zaragoza Cortés <[email protected]>
  • Loading branch information
3 people authored Jan 8, 2025
1 parent a88fdbd commit 89e6cfa
Show file tree
Hide file tree
Showing 12 changed files with 407 additions and 1 deletion.
82 changes: 82 additions & 0 deletions katas/content/nonlocal_games/examples/GHZGameDemo.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
namespace Quantum.Kata.GHZGame {
open Microsoft.Quantum.Random;
open Microsoft.Quantum.Convert;

function WinCondition (rst : Bool[], abc : Bool[]) : Bool {
return (rst[0] or rst[1] or rst[2]) == (abc[0] != abc[1] != abc[2]);
}

function AliceClassical (r : Bool) : Bool {
return true;
}

function BobClassical (s : Bool) : Bool {
return true;
}

function CharlieClassical (t : Bool) : Bool {
return true;
}

operation CreateEntangledTriple (qs : Qubit[]) : Unit is Adj {
X(qs[0]);
X(qs[1]);
H(qs[0]);
H(qs[1]);
Controlled Z([qs[0]], qs[1]);
ApplyControlledOnBitString([false, true], X, [qs[0], qs[1]], qs[2]);
ApplyControlledOnBitString([true, false], X, [qs[0], qs[1]], qs[2]);
}

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

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

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

operation getRandomRefereeBits () : Bool[] {
let bits = [[false, false, false],
[true, true, false],
[false, true, true],
[true, false, true]];
return bits[DrawRandomInt(0, 3)];
}

@EntryPoint()
operation GHZ_GameDemo () : Unit {
use (aliceQubit, bobQubit, charlieQubit) = (Qubit(), Qubit(), Qubit());
mutable classicalWins = 0;
mutable quantumWins = 0;
let iterations = 1000;
for _ in 1 .. iterations {
CreateEntangledTriple([aliceQubit, bobQubit, charlieQubit]);
let inputs = getRandomRefereeBits();
let coutputs = [AliceClassical(inputs[0]), BobClassical(inputs[1]), CharlieClassical(inputs[2])];
if WinCondition(inputs, coutputs) {
set classicalWins += 1;
}
let qoutputs = [AliceQuantum(inputs[0], aliceQubit), BobQuantum(inputs[1], bobQubit), CharlieQuantum(inputs[2], charlieQubit)];
if WinCondition(inputs, qoutputs) {
set quantumWins += 1;
}
ResetAll([aliceQubit, bobQubit, charlieQubit]);
}
Message($"Percentage of classical wins is {100.0*IntAsDouble(classicalWins)/IntAsDouble(iterations)}%");
Message($"Percentage of quantum wins is {100.0*IntAsDouble(quantumWins)/IntAsDouble(iterations)}%");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace Kata {
operation CreateEntangledTriple (qs : Qubit[]) : Unit {
// Implement your solution here...
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Kata {
operation CreateEntangledTriple (qs : Qubit[]) : Unit is Adj {
X(qs[0]);
X(qs[1]);
H(qs[0]);
H(qs[1]);
Controlled Z([qs[0]], qs[1]);
ApplyControlledOnBitString([false, true], X, [qs[0], qs[1]], qs[2]);
ApplyControlledOnBitString([true, false], X, [qs[0], qs[1]], qs[2]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Kata.Verification {
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Katas;

operation CreateEntangledTriple_Reference (qs : Qubit[]) : Unit is Adj {
X(qs[0]);
X(qs[1]);
H(qs[0]);
H(qs[1]);
Controlled Z([qs[0]], qs[1]);
ApplyControlledOnBitString([false, true], X, [qs[0], qs[1]], qs[2]);
ApplyControlledOnBitString([true, false], X, [qs[0], qs[1]], qs[2]);
}

@EntryPoint()
operation CheckSolution() : Bool {
CheckOperationsEquivalenceOnZeroStateWithFeedback(Kata.CreateEntangledTriple, CreateEntangledTriple_Reference, 3)
}
}
12 changes: 12 additions & 0 deletions katas/content/nonlocal_games/ghz_create_entangled_triple/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 an entangled triple before the start of the game.

**Input:**
An array of three qubits in the $\ket{000}$ state.

**Goal:**
Create the entangled state $\ket{\Phi} = \frac{1}{2} \big(\ket{000} - \ket{011} - \ket{101} - \ket{110} \big)$ on these qubits.

>This state is equivalent to the three-qubit [GHZ state](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state)
>$$\frac{1}{\sqrt{2}} \big(\ket{000} + \ket{111} \big)$$
>up to local unitary operations. Please refer to the follow-up GHZ Quantum Strategy discussion for details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
1. Apply an X gate to the first and the second qubits to get the $\ket{110}$ state.
2. Appy an H gate to the first and the second qubits to get the following state:
$$\frac12 \big( \ket{000} - \ket{010} - \ket{100} + \ket{110} \big)$$
3. Flip the sign of the last term using a controlled Z gate with the first qubit as control and the second qubit as target (or vice versa):
$$\frac12 \big( \ket{000} - \ket{010} - \ket{100} -{\color{blue}\ket{110}} \big)$$
4. Now we have the right signs for each term, and the first and the last terms match those of the state we're preparing, so we just need to adjust the two middle terms.
To do this, we can use [ControlledOnBitString](https://learn.microsoft.com/qsharp/api/qsharp-lang/microsoft.quantum.canon/applycontrolledonbitstring) operation to flip the state of the last qubit if the first two qubits are in $\ket{01}$ or in $\ket{10}$ states, which gives us:
$$\frac{1}{2} \big(\ket{000} - {\color{blue}\ket{011}} - {\color{blue}\ket{101}} - \ket{110} \big)$$

@[solution]({
"id": "nonlocal_games__ghz_create_entangled_triple_solution",
"codePath": "Solution.qs"
})
19 changes: 19 additions & 0 deletions katas/content/nonlocal_games/ghz_quantum_strategy/Placeholder.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Kata {
operation AliceQuantum (bit : Bool, qubit : Qubit) : Bool {
// Implement your solution here...

return false;
}

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

return false;
}

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

return false;
}
}
23 changes: 23 additions & 0 deletions katas/content/nonlocal_games/ghz_quantum_strategy/Solution.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Kata {
operation AliceQuantum (bit : Bool, qubit : Qubit) : Bool {
if bit {
return MResetX(qubit) == One;
}
return MResetZ(qubit) == One;
}

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

// alternative implementation
operation CharlieQuantum (bit : Bool, qubit : Qubit) : Bool {
if bit {
H(qubit);
}
return M(qubit) == One;
}
}
59 changes: 59 additions & 0 deletions katas/content/nonlocal_games/ghz_quantum_strategy/Verification.qs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
namespace Kata.Verification {

function WinCondition_Reference (rst : Bool[], abc : Bool[]) : Bool {
return (rst[0] or rst[1] or rst[2]) == (abc[0] != abc[1] != abc[2]);
}

function RefereeBits () : Bool[][] {
return [[false, false, false],
[true, true, false],
[false, true, true],
[true, false, true]];
}

operation CreateEntangledTriple_Reference (qs : Qubit[]) : Unit is Adj {
X(qs[0]);
X(qs[1]);
H(qs[0]);
H(qs[1]);
Controlled Z([qs[0]], qs[1]);
ApplyControlledOnBitString([false, true], X, [qs[0], qs[1]], qs[2]);
ApplyControlledOnBitString([true, false], X, [qs[0], qs[1]], qs[2]);
}

operation PlayQuantumGHZ_Reference (strategies : ((Bool, Qubit) => Bool)[], inputs : Bool[], qubits : Qubit[]) : Bool[] {
let r = inputs[0];
let s = inputs[1];
let t = inputs[2];
let a = strategies[0](r, qubits[0]);
let b = strategies[1](s, qubits[1]);
let c = strategies[2](t, qubits[2]);
return [a, b, c];
}

@EntryPoint()
operation CheckSolution () : Bool {
use qs = Qubit[3];
let inputs = RefereeBits();
let strategies = [Kata.AliceQuantum, Kata.BobQuantum, Kata.CharlieQuantum];

let iterations = 1000;
mutable wins = 0;
for _ in 1 .. iterations {
for bits in inputs {
CreateEntangledTriple_Reference(qs);
let abc = PlayQuantumGHZ_Reference(strategies, bits, qs);
if WinCondition_Reference(bits, abc) {
set wins = wins + 1;
}
ResetAll(qs);
}
}
if wins < iterations*Length(inputs) {
Message($"Players' quantum strategies get {wins} wins out of {iterations*Length(inputs)} runs, which is not optimal");
return false;
}
Message("Correct!");
true
}
}
11 changes: 11 additions & 0 deletions katas/content/nonlocal_games/ghz_quantum_strategy/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
In this task, you should implement three functions, one for each player's quantum strategy.
Note that they are covered by one test, so you must implement all of them to pass the test.

**Inputs:**

1. The input bit for one of each of the players (R, S and T respectively),
2. That player's qubit of the entangled triple shared between the players.

**Goal:**
Measure the qubit in the Z basis if the bit is 0 (FALSE), or the X basis if the bit is 1 (TRUE), and return the result.
The state of the qubit after the operation does not matter.
12 changes: 12 additions & 0 deletions katas/content/nonlocal_games/ghz_quantum_strategy/solution.md
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).

Alternatively, you can recall that measuring the qubit in the X basis is equivalent to applying an H gate to it and measuring it in the Z basis.

@[solution]({
"id": "nonlocal_games__ghz_quantum_strategy_solution",
"codePath": "Solution.qs"
})
Loading

0 comments on commit 89e6cfa

Please sign in to comment.