From 7c48b35cb5666763742516d0d93a08d209f874f3 Mon Sep 17 00:00:00 2001 From: Devika Mehra Date: Fri, 31 May 2024 06:42:22 +0530 Subject: [PATCH] Teleportation Task 1.2-1.4 added (#1556) Teleportation Task 1.2-1.4 added --------- Co-authored-by: Mariia Mykhailova --- katas/content/teleportation/Common.qs | 118 ++++++++++++++++++ katas/content/teleportation/index.md | 30 +++++ .../reconstruct_message/Placeholder.qs | 5 + .../reconstruct_message/Solution.qs | 10 ++ .../reconstruct_message/Verification.qs | 10 ++ .../reconstruct_message/index.md | 8 ++ .../reconstruct_message/solution.md | 10 ++ .../teleportation/send_message/Placeholder.qs | 6 + .../teleportation/send_message/Solution.qs | 7 ++ .../send_message/Verification.qs | 10 ++ .../teleportation/send_message/index.md | 8 ++ .../teleportation/send_message/solution.md | 9 ++ .../Placeholder.qs | 26 ++++ .../Solution.qs | 27 ++++ .../Verification.qs | 10 ++ .../standard_teleportation_protocol/index.md | 8 ++ .../solution.md | 10 ++ 17 files changed, 312 insertions(+) create mode 100644 katas/content/teleportation/reconstruct_message/Placeholder.qs create mode 100644 katas/content/teleportation/reconstruct_message/Solution.qs create mode 100644 katas/content/teleportation/reconstruct_message/Verification.qs create mode 100644 katas/content/teleportation/reconstruct_message/index.md create mode 100644 katas/content/teleportation/reconstruct_message/solution.md create mode 100644 katas/content/teleportation/send_message/Placeholder.qs create mode 100644 katas/content/teleportation/send_message/Solution.qs create mode 100644 katas/content/teleportation/send_message/Verification.qs create mode 100644 katas/content/teleportation/send_message/index.md create mode 100644 katas/content/teleportation/send_message/solution.md create mode 100644 katas/content/teleportation/standard_teleportation_protocol/Placeholder.qs create mode 100644 katas/content/teleportation/standard_teleportation_protocol/Solution.qs create mode 100644 katas/content/teleportation/standard_teleportation_protocol/Verification.qs create mode 100644 katas/content/teleportation/standard_teleportation_protocol/index.md create mode 100644 katas/content/teleportation/standard_teleportation_protocol/solution.md diff --git a/katas/content/teleportation/Common.qs b/katas/content/teleportation/Common.qs index f923380035..a10d2aae37 100644 --- a/katas/content/teleportation/Common.qs +++ b/katas/content/teleportation/Common.qs @@ -1,7 +1,125 @@ namespace Kata.Verification { + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Math; + operation EntangleWrapper_Reference(qs : Qubit[]) : Unit is Adj + Ctl { let (qAlice, qBob) = (qs[0], qs[1]); H(qAlice); CNOT(qAlice, qBob); } + + // ------------------------------------------------------ + // Helper which prepares proper Bell state on two qubits + // 0 - |Φ⁺⟩ = (|00⟩ + |11⟩) / sqrt(2) + // 1 - |Φ⁻⟩ = (|00⟩ - |11⟩) / sqrt(2) + // 2 - |Ψ⁺⟩ = (|01⟩ + |10⟩) / sqrt(2) + // 3 - |Ψ⁻⟩ = (|01⟩ - |10⟩) / sqrt(2) + operation StatePrep_BellState(q1 : Qubit, q2 : Qubit, state : Int) : Unit { + H(q1); + CNOT(q1, q2); + + // now we have |00⟩ + |11⟩ - modify it based on state arg + if state % 2 == 1 { + // negative phase + Z(q2); + } + + if state / 2 == 1 { + X(q2); + } + } + + // ------------------------------------------------------ + // Helper operation that run teleportation using the given operations to prepare the message qubit + // and the entangled pair, and to run sender and receiver parts of the protocol. + operation ComposeTeleportation( + bellPrepOp : ((Qubit, Qubit) => Unit), + getDescriptionOp : ((Qubit, Qubit) => (Bool, Bool)), + reconstructOp : ((Qubit, (Bool, Bool)) => Unit), + qAlice : Qubit, + qBob : Qubit, + qMessage : Qubit) : Unit { + + bellPrepOp(qAlice, qBob); + let classicalBits = getDescriptionOp(qAlice, qMessage); + + // Alice sends the classical bits to Bob. + // Bob uses these bits to transform his part of the entangled pair into the message. + reconstructOp(qBob, classicalBits); + } + + operation SendMessage_Reference(qAlice: Qubit, qMessage: Qubit) : (Bool, Bool) { + CNOT(qMessage, qAlice); + H(qMessage); + return (M(qMessage) == One, M(qAlice) == One); + } + + operation ReconstructMessage_Reference(qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit { + if b1 { + Z(qBob); + } + if b2 { + X(qBob); + } + } + + // ------------------------------------------------------ + // Helper operation that runs a teleportation operation (specified by teleportOp). + // The state to teleport is set up using an operation (specified by setupPsiOp). + // + // Specifying the state to teleport through an operation allows to get the inverse + // which makes testing easier. + operation TeleportTestHelper( + teleportOp : ((Qubit, Qubit, Qubit) => Unit), + setupPsiOp : (Qubit => Unit is Adj), + psiName: String) : Bool { + + use (qMessage, qAlice, qBob) = (Qubit(), Qubit(), Qubit()); + setupPsiOp(qMessage); + + // This should modify qBob to be identical to the state + // of qMessage before the function call. + teleportOp(qAlice, qBob, qMessage); + + // Applying the inverse of the setup operation to qBob + // should make it Zero. + Adjoint setupPsiOp(qBob); + if not CheckZero(qBob) { + Message($"Incorrect. The state {psiName} was teleported incorrectly."); + setupPsiOp(qBob); + Message("The state of the qubits [qMessage, qAlice, qBob] after teleportation:"); + DumpMachine(); + ResetAll([qMessage, qAlice, qBob]); + return false; + } + ResetAll([qMessage, qAlice, qBob]); + return true; + } + + // ------------------------------------------------------ + // Run teleportation for a number of different states. + // After each teleportation success is asserted. + // Also repeats for each state several times as + // code is expected to take different paths each time because + // measurements done by Alice are not deterministic. + operation TeleportTestLoop(teleportOp : ((Qubit, Qubit, Qubit) => Unit)) : Bool { + // Define setup operations for the message qubit + // on which to test teleportation: |0⟩, |1⟩, |0⟩ + |1⟩, unequal superposition. + let setupPsiOps = [(I, "|0⟩"), (X, "|1⟩"), (H, "|+⟩"), (Ry(ArcCos(0.6) * 2.0, _), "0.6|0⟩ + 0.8|1⟩")]; + + // As part of teleportation Alice runs some measurements + // with nondeterministic outcome. + // Depending on the outcomes different paths are taken on Bob's side. + // We repeat each test run several times to ensure that all paths are checked. + let numRepetitions = 100; + for (psiOp, psiName) in setupPsiOps { + for j in 1 .. numRepetitions { + if not TeleportTestHelper(teleportOp, psiOp, psiName) { + return false; + } + } + } + Message("Correct."); + return true; + } } \ No newline at end of file diff --git a/katas/content/teleportation/index.md b/katas/content/teleportation/index.md index ae331c6694..16d34ea7e0 100644 --- a/katas/content/teleportation/index.md +++ b/katas/content/teleportation/index.md @@ -33,3 +33,33 @@ We split the teleportation protocol into several steps: "./Common.qs" ] }) + +@[exercise]({ + "id": "teleportation__send_message", + "title": "Send Message (Alice's Task)", + "path": "./send_message/", + "qsDependencies": [ + "../KatasLibrary.qs", + "./Common.qs" + ] +}) + +@[exercise]({ + "id": "teleportation__reconstruct_message", + "title": "Reconstruct Message (Bob's Task)", + "path": "./reconstruct_message/", + "qsDependencies": [ + "../KatasLibrary.qs", + "./Common.qs" + ] +}) + +@[exercise]({ + "id": "teleportation__standard_teleportation_protocol", + "title": "Standard Teleportation Protocol", + "path": "./standard_teleportation_protocol/", + "qsDependencies": [ + "../KatasLibrary.qs", + "./Common.qs" + ] +}) \ No newline at end of file diff --git a/katas/content/teleportation/reconstruct_message/Placeholder.qs b/katas/content/teleportation/reconstruct_message/Placeholder.qs new file mode 100644 index 0000000000..82efeae1b2 --- /dev/null +++ b/katas/content/teleportation/reconstruct_message/Placeholder.qs @@ -0,0 +1,5 @@ +namespace Kata { + operation ReconstructMessage(qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit { + // Implement your solution here... + } +} \ No newline at end of file diff --git a/katas/content/teleportation/reconstruct_message/Solution.qs b/katas/content/teleportation/reconstruct_message/Solution.qs new file mode 100644 index 0000000000..76f52dfbdc --- /dev/null +++ b/katas/content/teleportation/reconstruct_message/Solution.qs @@ -0,0 +1,10 @@ +namespace Kata { + operation ReconstructMessage(qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit { + if b1 { + Z(qBob); + } + if b2 { + X(qBob); + } + } +} \ No newline at end of file diff --git a/katas/content/teleportation/reconstruct_message/Verification.qs b/katas/content/teleportation/reconstruct_message/Verification.qs new file mode 100644 index 0000000000..4296ee87e0 --- /dev/null +++ b/katas/content/teleportation/reconstruct_message/Verification.qs @@ -0,0 +1,10 @@ +namespace Kata.Verification { + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Katas; + + @EntryPoint() + operation CheckSolution() : Bool { + let teleport = ComposeTeleportation(StatePrep_BellState(_, _, 0), SendMessage_Reference, Kata.ReconstructMessage, _, _, _); + return TeleportTestLoop(teleport); + } +} \ No newline at end of file diff --git a/katas/content/teleportation/reconstruct_message/index.md b/katas/content/teleportation/reconstruct_message/index.md new file mode 100644 index 0000000000..159811df09 --- /dev/null +++ b/katas/content/teleportation/reconstruct_message/index.md @@ -0,0 +1,8 @@ +Transform Bob's qubit into the required state using the two classical bits received from Alice. + +**Inputs:** +1. Bob's part of the entangled pair of qubits `qBob`. +2. The tuple of classical bits received from Alice, in the format used in previous exercise. + +**Goal:** +Transform Bob's qubit `qBob` into the state in which the message qubit had been originally. \ No newline at end of file diff --git a/katas/content/teleportation/reconstruct_message/solution.md b/katas/content/teleportation/reconstruct_message/solution.md new file mode 100644 index 0000000000..3034838672 --- /dev/null +++ b/katas/content/teleportation/reconstruct_message/solution.md @@ -0,0 +1,10 @@ +Bob's qubit now contains the information about the amplitudes of the teleported state, but it needs correction based on the classical message received for his qubit to match the teleported state precisely: +- For 00, no change is required. +- For 01, only Z correction is required. +- For 10, only X correction is required. +- For 11, both Z and X correction is requried. + +@[solution]({ + "id": "teleportation__reconstruct_the_message_solution", + "codePath": "./Solution.qs" +}) \ No newline at end of file diff --git a/katas/content/teleportation/send_message/Placeholder.qs b/katas/content/teleportation/send_message/Placeholder.qs new file mode 100644 index 0000000000..32beb50d84 --- /dev/null +++ b/katas/content/teleportation/send_message/Placeholder.qs @@ -0,0 +1,6 @@ +namespace Kata { + operation SendMessage(qAlice : Qubit, qMessage : Qubit) : (Bool, Bool) { + // Implement your solution here... + return (false, false); + } +} \ No newline at end of file diff --git a/katas/content/teleportation/send_message/Solution.qs b/katas/content/teleportation/send_message/Solution.qs new file mode 100644 index 0000000000..7abb1d02ba --- /dev/null +++ b/katas/content/teleportation/send_message/Solution.qs @@ -0,0 +1,7 @@ +namespace Kata { + operation SendMessage(qAlice : Qubit, qMessage : Qubit) : (Bool, Bool) { + CNOT(qMessage, qAlice); + H(qMessage); + return (M(qMessage) == One, M(qAlice) == One); + } +} \ No newline at end of file diff --git a/katas/content/teleportation/send_message/Verification.qs b/katas/content/teleportation/send_message/Verification.qs new file mode 100644 index 0000000000..e60a8f0bbb --- /dev/null +++ b/katas/content/teleportation/send_message/Verification.qs @@ -0,0 +1,10 @@ +namespace Kata.Verification { + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Katas; + + @EntryPoint() + operation CheckSolution() : Bool { + let teleport = ComposeTeleportation(StatePrep_BellState(_, _, 0), Kata.SendMessage, ReconstructMessage_Reference, _, _, _); + return TeleportTestLoop(teleport); + } +} \ No newline at end of file diff --git a/katas/content/teleportation/send_message/index.md b/katas/content/teleportation/send_message/index.md new file mode 100644 index 0000000000..3d855453be --- /dev/null +++ b/katas/content/teleportation/send_message/index.md @@ -0,0 +1,8 @@ +Entangle the message qubit with Alice's qubit and extract two classical bits to be sent to Bob. + +**Inputs:** +1. Alice's part of the entangled pair of qubits `qAlice`. +2. The message qubit `qMessage`. + +**Output:** +Two classical bits Alice will send to Bob via classical channel as a tuple of Boolean values. The first bit in the tuple should hold the result of measurement of the message qubit, the second bit - the result of measurement of Alice's qubit. Represent measurement result `One` as `true` and `Zero` as `false`. The state of the qubits in the end of the operation doesn't matter. \ No newline at end of file diff --git a/katas/content/teleportation/send_message/solution.md b/katas/content/teleportation/send_message/solution.md new file mode 100644 index 0000000000..ba7d94e4f7 --- /dev/null +++ b/katas/content/teleportation/send_message/solution.md @@ -0,0 +1,9 @@ +Requirement is to perform measurement in bell state: +- Apply $CNOT$ with $qMessage$ as control qubit +- Apply Hadamard on $qMessage$ qubit +- Measure both the qubits and report in boolean format + +@[solution]({ + "id": "teleportation__send_the_message_solution", + "codePath": "./Solution.qs" +}) \ No newline at end of file diff --git a/katas/content/teleportation/standard_teleportation_protocol/Placeholder.qs b/katas/content/teleportation/standard_teleportation_protocol/Placeholder.qs new file mode 100644 index 0000000000..679117fe1b --- /dev/null +++ b/katas/content/teleportation/standard_teleportation_protocol/Placeholder.qs @@ -0,0 +1,26 @@ +namespace Kata { + operation StandardTeleport(qAlice : Qubit, qBob : Qubit, qMessage : Qubit) : Unit { + // Implement your solution here... + } + + // You might find these helper operations from earlier tasks useful. + operation Entangle(qAlice : Qubit, qBob : Qubit) : Unit is Adj + Ctl { + H(qAlice); + CNOT(qAlice, qBob); + } + + operation SendMessage(qAlice: Qubit, qMessage: Qubit) : (Bool, Bool) { + CNOT(qMessage, qAlice); + H(qMessage); + return (M(qMessage) == One, M(qAlice) == One); + } + + operation ReconstructMessage(qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit { + if b1 { + Z(qBob); + } + if b2 { + X(qBob); + } + } +} \ No newline at end of file diff --git a/katas/content/teleportation/standard_teleportation_protocol/Solution.qs b/katas/content/teleportation/standard_teleportation_protocol/Solution.qs new file mode 100644 index 0000000000..62ea0848d4 --- /dev/null +++ b/katas/content/teleportation/standard_teleportation_protocol/Solution.qs @@ -0,0 +1,27 @@ +namespace Kata { + operation StandardTeleport(qAlice : Qubit, qBob : Qubit, qMessage : Qubit) : Unit { + Entangle(qAlice, qBob); + let classicalBits = SendMessage(qAlice, qMessage); + ReconstructMessage(qBob, classicalBits); + } + + operation Entangle(qAlice : Qubit, qBob : Qubit) : Unit is Adj + Ctl { + H(qAlice); + CNOT(qAlice, qBob); + } + + operation SendMessage(qAlice: Qubit, qMessage: Qubit) : (Bool, Bool) { + CNOT(qMessage, qAlice); + H(qMessage); + return (M(qMessage) == One, M(qAlice) == One); + } + + operation ReconstructMessage(qBob : Qubit, (b1 : Bool, b2 : Bool)) : Unit { + if b1 { + Z(qBob); + } + if b2 { + X(qBob); + } + } +} \ No newline at end of file diff --git a/katas/content/teleportation/standard_teleportation_protocol/Verification.qs b/katas/content/teleportation/standard_teleportation_protocol/Verification.qs new file mode 100644 index 0000000000..bae6a02ecb --- /dev/null +++ b/katas/content/teleportation/standard_teleportation_protocol/Verification.qs @@ -0,0 +1,10 @@ +namespace Kata.Verification { + open Microsoft.Quantum.Katas; + + @EntryPoint() + operation CheckSolution() : Bool { + let teleport = Kata.StandardTeleport; + return TeleportTestLoop(teleport); + } + +} \ No newline at end of file diff --git a/katas/content/teleportation/standard_teleportation_protocol/index.md b/katas/content/teleportation/standard_teleportation_protocol/index.md new file mode 100644 index 0000000000..e05aeb11ae --- /dev/null +++ b/katas/content/teleportation/standard_teleportation_protocol/index.md @@ -0,0 +1,8 @@ +Put together the steps implemented in previous three exercises to implement the full teleportation protocol. + +**Inputs:** +1. The two qubits `qAlice` and `qBob` in $\ket{0}$ state. +2. The message qubit `qMessage` in the state $\ket{\psi}$ to be teleported. + +**Goal:** +Transform Bob's qubit `qBob` into the state $\ket{\psi}$. The state of the qubits `qAlice` and `qMessage` in the end of the operation doesn't matter. \ No newline at end of file diff --git a/katas/content/teleportation/standard_teleportation_protocol/solution.md b/katas/content/teleportation/standard_teleportation_protocol/solution.md new file mode 100644 index 0000000000..240258e055 --- /dev/null +++ b/katas/content/teleportation/standard_teleportation_protocol/solution.md @@ -0,0 +1,10 @@ +Combine solutions of all three exercises in the correct order + +- Entangle qubits of Alice and Bob +- Send the message using Alice's qubit and message qubit +- Based on the message qubit, reconstruct the state of Bob's qubit + +@[solution]({ + "id": "teleportation__standard_teleportation_protocol_solution", + "codePath": "./Solution.qs" +}) \ No newline at end of file