From 1342756391a947eb7aae3236e08dc37645cba7ff Mon Sep 17 00:00:00 2001 From: JPark1023 Date: Wed, 5 Jun 2024 21:01:36 -0500 Subject: [PATCH 1/3] update --- .../zero_plus_inc/Placeholder.qs | 6 ++ .../zero_plus_inc/Solution.qs | 21 +++++ .../zero_plus_inc/Verification.qs | 91 +++++++++++++++++++ .../zero_plus_inc/index.md | 18 ++++ .../zero_plus_inc/solution.md | 25 +++++ 5 files changed, 161 insertions(+) create mode 100644 katas/content/distinguishing_states/zero_plus_inc/Placeholder.qs create mode 100644 katas/content/distinguishing_states/zero_plus_inc/Solution.qs create mode 100644 katas/content/distinguishing_states/zero_plus_inc/Verification.qs create mode 100644 katas/content/distinguishing_states/zero_plus_inc/index.md create mode 100644 katas/content/distinguishing_states/zero_plus_inc/solution.md diff --git a/katas/content/distinguishing_states/zero_plus_inc/Placeholder.qs b/katas/content/distinguishing_states/zero_plus_inc/Placeholder.qs new file mode 100644 index 0000000000..d4cc2d94cc --- /dev/null +++ b/katas/content/distinguishing_states/zero_plus_inc/Placeholder.qs @@ -0,0 +1,6 @@ +namespace Kata { + operation IsQubitZeroOrPlusOrInconclusive (q : Qubit) : Int { + // Implement your solution here... + return -2; + } +} diff --git a/katas/content/distinguishing_states/zero_plus_inc/Solution.qs b/katas/content/distinguishing_states/zero_plus_inc/Solution.qs new file mode 100644 index 0000000000..2d7541660b --- /dev/null +++ b/katas/content/distinguishing_states/zero_plus_inc/Solution.qs @@ -0,0 +1,21 @@ +namespace Kata { + operation IsQubitZeroOrPlusOrInconclusive (q : Qubit) : Int { + let basis = DrawRandomInt(0, 1); + + // randomize over std and had + if basis == 0 { + + // use standard basis + let result = M(q); + // result is One only if the state was |+⟩ + return result == One ? 1 | -1; + } + else { + // use Hadamard basis + H(q); + let result = M(q); + // result is One only if the state was |0⟩ + return result == One ? 0 | -1; + } + } +} diff --git a/katas/content/distinguishing_states/zero_plus_inc/Verification.qs b/katas/content/distinguishing_states/zero_plus_inc/Verification.qs new file mode 100644 index 0000000000..5b62735a96 --- /dev/null +++ b/katas/content/distinguishing_states/zero_plus_inc/Verification.qs @@ -0,0 +1,91 @@ +namespace Kata.Verification { + open Microsoft.Quantum.Katas; + + operation SetQubitZeroOrPlus (q : Qubit, state : Int) : Unit { + if state != 0 { + H(q); + } + } + + @EntryPoint() + operation CheckSolution() : Bool { + USD_DistinguishStates_MultiQubit_Threshold(1, 2, 0.8, 0.1, StatePrep_IsQubitZeroOrPlus, IsQubitPlusZeroOrInconclusiveSimpleUSD); + + let nTotal = 10000; + let thresholdInconcl = 0.8; + let thresholdConcl = 0.1; + mutable isCorrect = true; + + // counts total inconclusive answers + mutable nInconc = 0; + + // counts total conclusive |0⟩ state identifications + mutable nConclOne = 0; + + // counts total conclusive |+> state identifications + mutable nConclPlus = 0; + + use qs = Qubit[1]; + for i in 1 .. nTotal { + + // get a random integer to define the state of the qubits + let state = DrawRandomInt(0, Nstate - 1); + + // do state prep: convert |0⟩ to outcome with return equal to state + SetQubitZeroOrPlus(qs[0], state); + + // get the solution's answer and verify that it's a match + let ans = IsQubitZeroOrPlusOrInconclusive(qs[0]); + + // check that the answer is actually in allowed range + if (ans < -1 or ans > 1) { + Message($"state {state} led to invalid response {ans}."); + } + + // keep track of the number of inconclusive answers given + if ans == -1 { + set nInconc += 1; + } + + if (ans == 0 and state == 0) { + set nConclOne += 1; + } + + if (ans == 1 and state == 1) { + set nConclPlus += 1; + } + + // check if upon conclusive result the answer is actually correct + if (ans == 0 and state == 1 or ans == 1 and state == 0) { + fail $"state {state} led to incorrect conclusive response {ans}."; + } + + // we're not checking the state of the qubit after the operation + ResetAll(qs); + } + + if IntAsDouble(nInconc) > thresholdInconcl * IntAsDouble(nTotal) { + Message($"{nInconc} test runs out of {nTotal} returned inconclusive which does not meet the required threshold of at most {thresholdInconcl * 100.0}%."); + isCorrect = false; + } + + if IntAsDouble(nConclOne) < thresholdConcl * IntAsDouble(nTotal) { + Message($"Only {nConclOne} test runs out of {nTotal} returned conclusive |0⟩ which does not meet the required threshold of at least {thresholdConcl * 100.0}%."); + isCorrect = false; + } + + if IntAsDouble(nConclPlus) < thresholdConcl * IntAsDouble(nTotal) { + Message($"Only {nConclPlus} test runs out of {nTotal} returned conclusive |+> which does not meet the required threshold of at least {thresholdConcl * 100.0}%."); + isCorrect = false; + } + + if (isCorrect) { + Message("Correct!"); + return true; + } else { + Message("Incorrect"); + return false; + } + } + +} diff --git a/katas/content/distinguishing_states/zero_plus_inc/index.md b/katas/content/distinguishing_states/zero_plus_inc/index.md new file mode 100644 index 0000000000..afd047f188 --- /dev/null +++ b/katas/content/distinguishing_states/zero_plus_inc/index.md @@ -0,0 +1,18 @@ +**Input:** A qubit which is guaranteed to be in either the $\ket{0}$ or the $\ket{+}$ state. + +**Output:** +* 0 if the qubit was in the $\ket{0}$ state, +* 1 if it was in the $\ket{+}$ state, +* -1 if you can't decide, i.e., an "inconclusive" result. + +Your solution: + +* should never give 0 or 1 answer incorrectly (i.e., identify $\ket{0}$ as 1 or $\ket{+}$ as 0), +* will be called multiple times, with one of the states picked with equal probability every time, +* may give an inconclusive (-1) answer in at most 80% of all the cases, +* must correctly identify the $\ket{0}$ state as 0 in at least 10% of all the cases, +* must correctly identify the $\ket{1}$ state as 1 in at least 10% of all the cases. + +The state of the qubit at the end of the operation does not matter. + +> This task is an example of unambiguous state discrimination.\n \ No newline at end of file diff --git a/katas/content/distinguishing_states/zero_plus_inc/solution.md b/katas/content/distinguishing_states/zero_plus_inc/solution.md new file mode 100644 index 0000000000..5c41128b0b --- /dev/null +++ b/katas/content/distinguishing_states/zero_plus_inc/solution.md @@ -0,0 +1,25 @@ +### Solution + +A simple strategy that gives an inconclusive result with probability 0.75 and never errs in case it yields a conclusive result can be obtained from randomizing the choice of measurement basis between the computational basis (std) and the Hadamard basis (had). + +Notice that when measured in the standard basis, the state $\ket{0}$ will always lead to the outcome "0", and the state $\ket{+}$ will lead to outcomes "0" and "1" with probability $\frac12$ each. This means that if we measure "1", we can with certainty conclude that the state was $\ket{+}$. + +A similar argument applies to the scenario where we measure in the Hadamard basis, where $\ket{0}$ can lead to both "+" and "-" outcomes, and $\ket{+}$ always leads to "+". Then if we measured "-", we can with certainty conclude that the state was $\ket{0}$. + +This leads to the following scenarios (shown are the conditional probabilities + of the resulting answers in each of the above scenarios). + + + State | Basis | P(0) | P(1) | P(-1) +-------------|-------|-----------|-----------|---------- + $\ket{0}$ | std | $0$ | $0$ | $1$ + $\ket{+}$ | std | $0$ | $\frac12$ | $\frac12$ + $\ket{0}$ | had | $\frac12$ | $0$ | $\frac12$ + $\ket{+}$ | had | $0$ | $0$ | $1$ + +> The easiest way to implement the measurement in the Hadamard basis in Q# is to apply an H gate followed by a regular measurement in computational basis. + +@[solution]({ + "id": "distinguishing_states__zero_one_solution", + "codePath": "Solution.qs" +}) From f2f17b67e39e5272dd907189c4fd718a535684c2 Mon Sep 17 00:00:00 2001 From: JPark1023 Date: Thu, 6 Jun 2024 07:51:30 -0500 Subject: [PATCH 2/3] added peres_wooter and zero_plus_inconclusive --- katas/content/distinguishing_states/Common.qs | 40 -------- katas/content/distinguishing_states/index.md | 21 ++++- .../peres_wooters_game/Placeholder.qs | 6 ++ .../peres_wooters_game/Solution.qs | 38 ++++++++ .../peres_wooters_game/Verification.qs | 69 ++++++++++++++ .../peres_wooters_game/index.md | 17 ++++ .../peres_wooters_game/solution.md | 91 +++++++++++++++++++ .../zero_plus/Verification.qs | 35 ++++++- .../zero_plus_inc/Solution.qs | 1 + .../zero_plus_inc/Verification.qs | 29 ++---- .../zero_plus_inc/index.md | 2 +- .../zero_plus_inc/solution.md | 50 ++++++++-- 12 files changed, 325 insertions(+), 74 deletions(-) delete mode 100644 katas/content/distinguishing_states/Common.qs create mode 100644 katas/content/distinguishing_states/peres_wooters_game/Placeholder.qs create mode 100644 katas/content/distinguishing_states/peres_wooters_game/Solution.qs create mode 100644 katas/content/distinguishing_states/peres_wooters_game/Verification.qs create mode 100644 katas/content/distinguishing_states/peres_wooters_game/index.md create mode 100644 katas/content/distinguishing_states/peres_wooters_game/solution.md diff --git a/katas/content/distinguishing_states/Common.qs b/katas/content/distinguishing_states/Common.qs deleted file mode 100644 index 151919f5a9..0000000000 --- a/katas/content/distinguishing_states/Common.qs +++ /dev/null @@ -1,40 +0,0 @@ -namespace Kata.Verification { - open Microsoft.Quantum.Convert; - open Microsoft.Quantum.Random; - - operation DistinguishStates_MultiQubit_Threshold (nQubit : Int, - nState : Int, - threshold : Double, - statePrep : ((Qubit, Int) => Unit), - testImpl : (Qubit => Bool)) : Bool { - let nTotal = 1000; - mutable nOk = 0; - - use qs = Qubit[nQubit]; - for i in 1 .. nTotal { - // get a random integer to define the state of the qubits - let state = DrawRandomInt(0, nState - 1); - - // do state prep: convert |0⟩ to outcome with return equal to state - statePrep(qs[0], state); - - // get the solution's answer and verify that it's a match - let ans = testImpl(qs[0]); - if ans == (state == 0) { - set nOk += 1; - } - - // we're not checking the state of the qubit after the operation - ResetAll(qs); - } - - if IntAsDouble(nOk) < threshold * IntAsDouble(nTotal) { - Message($"{nTotal - nOk} test runs out of {nTotal} returned incorrect state, which does not meet the required threshold of at least {threshold * 100.0}%."); - Message("Incorrect."); - return false; - } else { - Message("Correct!"); - return true; - } - } -} diff --git a/katas/content/distinguishing_states/index.md b/katas/content/distinguishing_states/index.md index d7dcabc1f3..74f8441bcf 100644 --- a/katas/content/distinguishing_states/index.md +++ b/katas/content/distinguishing_states/index.md @@ -51,8 +51,25 @@ This kata is designed to get you familiar with the concept of measurements and u "title": "|0〉 or |+〉?", "path": "./zero_plus/", "qsDependencies": [ - "../KatasLibrary.qs", - "./Common.qs" + "../KatasLibrary.qs" + ] +}) + +@[exercise]({ + "id": "distinguishing_states__zero_plus_inc", + "title": "|0〉 or |+〉 or Inconclusive?", + "path": "./zero_plus_inc/", + "qsDependencies": [ + "../KatasLibrary.qs" + ] +}) + +@[exercise]({ + "id": "distinguishing_states__peres_wooters_game", + "title": "Peres/Wooters game", + "path": "./peres_wooters_game/", + "qsDependencies": [ + "../KatasLibrary.qs" ] }) diff --git a/katas/content/distinguishing_states/peres_wooters_game/Placeholder.qs b/katas/content/distinguishing_states/peres_wooters_game/Placeholder.qs new file mode 100644 index 0000000000..5643e339a5 --- /dev/null +++ b/katas/content/distinguishing_states/peres_wooters_game/Placeholder.qs @@ -0,0 +1,6 @@ +namespace Kata { + operation IsQubitNotInABC (q : Qubit) : Int { + // Implement your solution here... + return -1; + } +} \ No newline at end of file diff --git a/katas/content/distinguishing_states/peres_wooters_game/Solution.qs b/katas/content/distinguishing_states/peres_wooters_game/Solution.qs new file mode 100644 index 0000000000..fce626f409 --- /dev/null +++ b/katas/content/distinguishing_states/peres_wooters_game/Solution.qs @@ -0,0 +1,38 @@ +namespace Kata { + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Canon; + operation IsQubitNotInABC (q : Qubit) : Int { + let alpha = ArcCos(Sqrt(2.0 / 3.0)); + + use a = Qubit(); + Z(q); + CNOT(a, q); + Controlled H([q], a); + S(a); + X(q); + + ApplyControlledOnInt(0, Ry, [a], (-2.0 * alpha, q)); + CNOT(a, q); + Controlled H([q], a); + CNOT(a, q); + + // finally, measure in the standard basis + let res0 = MResetZ(a); + let res1 = M(q); + + // dispatch on the cases + if (res0 == Zero and res1 == Zero) { + return 0; + } + elif (res0 == One and res1 == Zero) { + return 1; + } + elif (res0 == Zero and res1 == One) { + return 2; + } + else { + // this should never occur + return 3; + } + } +} \ No newline at end of file diff --git a/katas/content/distinguishing_states/peres_wooters_game/Verification.qs b/katas/content/distinguishing_states/peres_wooters_game/Verification.qs new file mode 100644 index 0000000000..9cbf5c1556 --- /dev/null +++ b/katas/content/distinguishing_states/peres_wooters_game/Verification.qs @@ -0,0 +1,69 @@ +namespace Kata.Verification { + open Microsoft.Quantum.Katas; + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Random; + open Microsoft.Quantum.Math; + + operation StatePrep_IsQubitNotInABC (q : Qubit, state : Int) : Unit { + let alpha = (2.0 * PI()) / 3.0; + H(q); + + if state == 0 { + // convert |0⟩ to 1/sqrt(2) (|0⟩ + |1⟩) + } + elif state == 1 { + // convert |0⟩ to 1/sqrt(2) (|0⟩ + ω |1⟩), where ω = exp(2iπ/3) + R1(alpha, q); + } + else { + // convert |0⟩ to 1/sqrt(2) (|0⟩ + ω² |1⟩), where ω = exp(2iπ/3) + R1(2.0 * alpha, q); + } + } + + + @EntryPoint() + operation CheckSolution () : Bool { + let nTotal = 1000; + mutable bad_value = 0; + mutable wrong_state = 0; + + use qs = Qubit[1]; + + for i in 1 .. nTotal { + // get a random integer to define the state of the qubits + let state = DrawRandomInt(0, 2); + + // do state prep: convert |0⟩ to outcome with return equal to state + StatePrep_IsQubitNotInABC(qs[0], state); + + // get the solution's answer and verify that it's a match + let ans = Kata.IsQubitNotInABC(qs[0]); + + // check that the value of ans is 0, 1 or 2 + if (ans < 0 or ans > 2) { + // Message("You can not return any value other than 0, 1 or 2."); + set bad_value += 1; + } + + // check if upon conclusive result the answer is actually correct + if ans == state { + // Message($"State {state} led to incorrect conclusive response {ans}."); + set wrong_state += 1; + } + + // we're not checking the state of the qubit after the operation + ResetAll(qs); + } + + if bad_value == 0 and wrong_state == 0 { + Message("Correct!"); + return true; + } else { + Message($"Returned values other than 0, 1 or 2 {bad_value} times."); + Message($"State led to incorrect conclusive response {wrong_state} times"); + Message("Incorrect."); + return false; + } + } +} \ No newline at end of file diff --git a/katas/content/distinguishing_states/peres_wooters_game/index.md b/katas/content/distinguishing_states/peres_wooters_game/index.md new file mode 100644 index 0000000000..7d0495138c --- /dev/null +++ b/katas/content/distinguishing_states/peres_wooters_game/index.md @@ -0,0 +1,17 @@ +**Input:** A qubit which is guaranteed to be in one of the three states: + +* $\ket{A} = \frac{1}{\sqrt{2}} \big( \ket{0} + \ket{1} \big)$, +* $\ket{B} = \frac{1}{\sqrt{2}} \big( \ket{0} + \omega \ket{1} \big)$, +* $\ket{C}= \frac{1}{\sqrt{2}} \big( \ket{0} + \omega^2 \ket{1} \big)$, + +Here $\omega = e^{2i \pi/ 3}$. + +**Output:** + +* 1 or 2 if the qubit was in the $\ket{A}$ state, +* 0 or 2 if the qubit was in the $\ket{B}$ state, +* 0 or 1 if the qubit was in the $\ket{C}$ state. + +You are never allowed to give an incorrect answer. Your solution will be called multiple times, with one of the states picked with equal probability every time. + +The state of the qubit at the end of the operation does not matter. \ No newline at end of file diff --git a/katas/content/distinguishing_states/peres_wooters_game/solution.md b/katas/content/distinguishing_states/peres_wooters_game/solution.md new file mode 100644 index 0000000000..7a14b7eaa6 --- /dev/null +++ b/katas/content/distinguishing_states/peres_wooters_game/solution.md @@ -0,0 +1,91 @@ +### Solution + +> The task is a simple game inspired by a quantum detection problem due to Holevo ("Information-theoretical aspects of quantum measurement", A. Holevo) and Peres/Wootters ("Optimal detection of quantum information", A. Peres and W. K. Wootters). In the game, player A thinks of a number (0,1 or 2) and the opponent, player B, tries to guess any number but the one chosen by player A. +> +> Classically, if you just made a guess, you'd have to ask two questions to be right $100\%$ of the time. If instead, player A prepares a qubit with 0, 1, or 2 encoded into three single qubit states that are at an angle of 120 degrees with respect to each other and then hands the state to the opponent, then player B can apply a Positive Operator Valued Measure (POVM) consisting of 3 states that are perpendicular to the states chosen by player A. +> It can be shown that this allows B to be right $100\%$ of the time with only 1 measurement, which is something that is not achievable with a von Neumann measurement on 1 qubit. +See also ("Quantum Theory: Concepts and Methods", A. Peres) for a nice description of the optimal POVM. + +Next, we address how we can implement the mentioned POVM by way of a von Neumann measurement, and then how to implement said von Neumann measurement in Q\#. First, we note that the POVM elements are given by the columns of the following matrix: + +$$M = \frac{1}{\sqrt{2}}\left(\begin{array}{rrr} +1 & 1 & 1 \\ +1 & \omega & \omega^2 +\end{array} +\right)$$ + +where $\omega = e^{2 \pi i/3}$ denotes a primitive 3rd root of unity. Our task will be to implement the rank 1 POVM given by the columns of $M$ via a von Neumann measurement. This can be done by \"embedding\" $M$ into a larger unitary matrix (taking complex conjugates and transposed): + +$$M' = \frac{1}{\sqrt{3}}\left(\begin{array}{cccc} +1 & -1 & 1 & 0 \\ +1 & -\omega^2 & \omega & 0 \\ +1 & -\omega & \omega^2 & 0 \\ +0 & 0 & 0 & -i\sqrt{3} +\end{array} +\right)$$ + +Notice that applying $M'$ to input states given by column $i$ of $M$ (padded with two zeros to make it a vector of length $4$), where $i=0, 1, 2$ will never return the label $i$ as the corresponding vectors are perpendicular. + +We are therefore left with the problem of implementing $M'$ as a sequence of elementary quantum gates. Notice that + +$$M' \cdot {\rm diag}(1,-1,1,-1) = M' \cdot (\mathbf{1}_2 \otimes Z) = +\frac{1}{\sqrt{3}}\left(\begin{array}{cccc} +1 & 1 & 1 & 0 \\ +1 & \omega^2 & \omega & 0 \\ +1 & \omega & \omega^2 & 0 \\ +0 & 0 & 0 & i\sqrt{3} +\end{array} +\right)$$ + +Using a technique used in the Rader (also sometimes called Rader-Winograd) decomposition of the discrete Fourier transform ("Discrete Fourier transforms when the number of data samples is prime", C. M. Rader), which reduces it to a cyclic convolution, we apply a $2\times 2$ Fourier transform on the indices $i,j=1,2$ of this matrix (i.e. a block matrix which consists of a direct sum of blocks $\mathbf{1}_1$, $H$, and $\mathbf{1}_1$ which we abbreviate in short as ${\rm diag}(1,H,1)$). + +> To implement this in Q#, we can use the following sequence of gates, applied to a 2-qubit array: +> +> ``` +> CNOT(qs[1], qs[0]); +> Controlled H([qs[0]], qs[1]); +> CNOT(qs[1], qs[0]); +> ``` + +This yields + +$${\rm diag}(1, H, 1) \cdot M' \cdot (\mathbf{1}_2 \otimes Z) \cdot {\rm diag}(1, H, 1) = +\left(\begin{array}{rrrr} +\frac{1}{\sqrt3} & \sqrt{\frac23} & 0 & 0 \\ +\sqrt{\frac23} & -\frac{1}{\sqrt3} & 0 & 0 \\ +0 & 0 & i & 0 \\ +0 & 0 & 0 & i +\end{array} +\right)$$ + +This implies that after multiplication with the diagonal operator $(S^\dagger \otimes \mathbf{1}_2)$, we are left with + +$${\rm diag}(1, H, 1) \cdot M' \cdot (\mathbf{1}_2 \otimes Z) \cdot {\rm diag}(1, H, 1)\cdot (S^\dagger \otimes \mathbf{1}_2) = +\left(\begin{array}{rrrr} +\frac{1}{\sqrt3} & \sqrt{\frac23} & 0 & 0 \\ +\sqrt{\frac23} & -\frac{1}{\sqrt3} & 0 & 0 \\ +0 & 0 & 1 & 0 \\ +0 & 0 & 0 & 1 +\end{array} +\right)$$ + +which is a zero-controlled rotation $R$ around the $Y$-axis by an angle given by $\arccos \sqrt{\frac23}$ (plus reordering of rows and columns). + +> In Q#, we can implement this matrix as the following sequence of gates, applied to a 2-qubit array: +> ``` +> CNOT(qs[1], qs[0]); +> X(qs[0]); +> let alpha = ArcCos(Sqrt(2.0 / 3.0)); +> (ControlledOnInt(0, Ry))([qs[1]], (-2.0 * alpha, qs[0])); +> ``` + +Putting everything together, we can implement the matrix $M'$ by applying the inverses of gates: + +$$M' = {\rm diag}(1,H,1) \cdot R \cdot (S \otimes \mathbf{1}_2) \cdot {\rm diag}(1,H,1) \cdot (\mathbf{1}_2 \otimes Z)$$ + +Noting finally, that to apply this sequence of unitaries to a column vector, we have to apply it in reverse when writing it as a program (as actions on vectors are left-associative). + +@[solution]({ + "id": "distinguishing_states__peres_wooters_game_solution", + "codePath": "Solution.qs" +}) \ No newline at end of file diff --git a/katas/content/distinguishing_states/zero_plus/Verification.qs b/katas/content/distinguishing_states/zero_plus/Verification.qs index a2c68bc2e6..18f9237d59 100644 --- a/katas/content/distinguishing_states/zero_plus/Verification.qs +++ b/katas/content/distinguishing_states/zero_plus/Verification.qs @@ -1,5 +1,8 @@ namespace Kata.Verification { open Microsoft.Quantum.Katas; + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Random; + operation SetQubitZeroOrPlus (q : Qubit, state : Int) : Unit { if state != 0 { @@ -9,6 +12,36 @@ namespace Kata.Verification { @EntryPoint() operation CheckSolution () : Bool { - return DistinguishStates_MultiQubit_Threshold(1, 2, 0.8, SetQubitZeroOrPlus, Kata.IsQubitZeroOrPlus); + // return DistinguishStates_MultiQubit_Threshold(1, 2, 0.8, SetQubitZeroOrPlus, Kata.IsQubitZeroOrPlus); + let nTotal = 1000; + mutable nOk = 0; + let threshold = 0.8; + + use qs = Qubit[1]; + for i in 1 .. nTotal { + // get a random integer to define the state of the qubits + let state = DrawRandomInt(0, 1); + + // do state prep: convert |0⟩ to outcome with return equal to state + SetQubitZeroOrPlus(qs[0], state); + + // get the solution's answer and verify that it's a match + let ans = Kata.IsQubitZeroOrPlus(qs[0]); + if ans == (state == 0) { + set nOk += 1; + } + + // we're not checking the state of the qubit after the operation + ResetAll(qs); + } + + if IntAsDouble(nOk) < threshold * IntAsDouble(nTotal) { + Message($"{nTotal - nOk} test runs out of {nTotal} returned incorrect state, which does not meet the required threshold of at least {threshold * 100.0}%."); + Message("Incorrect."); + return false; + } else { + Message("Correct!"); + return true; + } } } diff --git a/katas/content/distinguishing_states/zero_plus_inc/Solution.qs b/katas/content/distinguishing_states/zero_plus_inc/Solution.qs index 2d7541660b..998ed83670 100644 --- a/katas/content/distinguishing_states/zero_plus_inc/Solution.qs +++ b/katas/content/distinguishing_states/zero_plus_inc/Solution.qs @@ -1,4 +1,5 @@ namespace Kata { + open Microsoft.Quantum.Random; operation IsQubitZeroOrPlusOrInconclusive (q : Qubit) : Int { let basis = DrawRandomInt(0, 1); diff --git a/katas/content/distinguishing_states/zero_plus_inc/Verification.qs b/katas/content/distinguishing_states/zero_plus_inc/Verification.qs index 5b62735a96..cd2b58c18a 100644 --- a/katas/content/distinguishing_states/zero_plus_inc/Verification.qs +++ b/katas/content/distinguishing_states/zero_plus_inc/Verification.qs @@ -1,5 +1,7 @@ namespace Kata.Verification { open Microsoft.Quantum.Katas; + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Random; operation SetQubitZeroOrPlus (q : Qubit, state : Int) : Unit { if state != 0 { @@ -9,8 +11,6 @@ namespace Kata.Verification { @EntryPoint() operation CheckSolution() : Bool { - USD_DistinguishStates_MultiQubit_Threshold(1, 2, 0.8, 0.1, StatePrep_IsQubitZeroOrPlus, IsQubitPlusZeroOrInconclusiveSimpleUSD); - let nTotal = 10000; let thresholdInconcl = 0.8; let thresholdConcl = 0.1; @@ -29,18 +29,13 @@ namespace Kata.Verification { for i in 1 .. nTotal { // get a random integer to define the state of the qubits - let state = DrawRandomInt(0, Nstate - 1); + let state = DrawRandomInt(0, 1); // do state prep: convert |0⟩ to outcome with return equal to state SetQubitZeroOrPlus(qs[0], state); // get the solution's answer and verify that it's a match - let ans = IsQubitZeroOrPlusOrInconclusive(qs[0]); - - // check that the answer is actually in allowed range - if (ans < -1 or ans > 1) { - Message($"state {state} led to invalid response {ans}."); - } + let ans = Kata.IsQubitZeroOrPlusOrInconclusive(qs[0]); // keep track of the number of inconclusive answers given if ans == -1 { @@ -55,28 +50,22 @@ namespace Kata.Verification { set nConclPlus += 1; } - // check if upon conclusive result the answer is actually correct - if (ans == 0 and state == 1 or ans == 1 and state == 0) { - fail $"state {state} led to incorrect conclusive response {ans}."; - } - - // we're not checking the state of the qubit after the operation ResetAll(qs); } if IntAsDouble(nInconc) > thresholdInconcl * IntAsDouble(nTotal) { Message($"{nInconc} test runs out of {nTotal} returned inconclusive which does not meet the required threshold of at most {thresholdInconcl * 100.0}%."); - isCorrect = false; + set isCorrect = false; } if IntAsDouble(nConclOne) < thresholdConcl * IntAsDouble(nTotal) { - Message($"Only {nConclOne} test runs out of {nTotal} returned conclusive |0⟩ which does not meet the required threshold of at least {thresholdConcl * 100.0}%."); - isCorrect = false; + Message($"{nConclOne} test runs out of {nTotal} returned conclusive |0⟩ which does not meet the required threshold of at least {thresholdConcl * 100.0}%."); + set isCorrect = false; } if IntAsDouble(nConclPlus) < thresholdConcl * IntAsDouble(nTotal) { - Message($"Only {nConclPlus} test runs out of {nTotal} returned conclusive |+> which does not meet the required threshold of at least {thresholdConcl * 100.0}%."); - isCorrect = false; + Message($"{nConclPlus} test runs out of {nTotal} returned conclusive |+> which does not meet the required threshold of at least {thresholdConcl * 100.0}%."); + set isCorrect = false; } if (isCorrect) { diff --git a/katas/content/distinguishing_states/zero_plus_inc/index.md b/katas/content/distinguishing_states/zero_plus_inc/index.md index afd047f188..26a3f168bd 100644 --- a/katas/content/distinguishing_states/zero_plus_inc/index.md +++ b/katas/content/distinguishing_states/zero_plus_inc/index.md @@ -15,4 +15,4 @@ Your solution: The state of the qubit at the end of the operation does not matter. -> This task is an example of unambiguous state discrimination.\n \ No newline at end of file +> This task is an example of unambiguous state discrimination. \ No newline at end of file diff --git a/katas/content/distinguishing_states/zero_plus_inc/solution.md b/katas/content/distinguishing_states/zero_plus_inc/solution.md index 5c41128b0b..2ecabbe184 100644 --- a/katas/content/distinguishing_states/zero_plus_inc/solution.md +++ b/katas/content/distinguishing_states/zero_plus_inc/solution.md @@ -8,18 +8,48 @@ A similar argument applies to the scenario where we measure in the Hadamard basi This leads to the following scenarios (shown are the conditional probabilities of the resulting answers in each of the above scenarios). - - - State | Basis | P(0) | P(1) | P(-1) --------------|-------|-----------|-----------|---------- - $\ket{0}$ | std | $0$ | $0$ | $1$ - $\ket{+}$ | std | $0$ | $\frac12$ | $\frac12$ - $\ket{0}$ | had | $\frac12$ | $0$ | $\frac12$ - $\ket{+}$ | had | $0$ | $0$ | $1$ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StateBasisP(0)P(1)P(-1)
$\ket{0}$std$0$$0$$1$
$\ket{+}$std$0$$\frac12$$\frac12$
$\ket{0}$had$\frac12$$0$$\frac12$
$\ket{+}$had$0$$0$$1$
+ > The easiest way to implement the measurement in the Hadamard basis in Q# is to apply an H gate followed by a regular measurement in computational basis. @[solution]({ - "id": "distinguishing_states__zero_one_solution", + "id": "distinguishing_states__zero_plus_inc_solution", "codePath": "Solution.qs" }) From ba181adfb6f5c27a53f29f02fe52466dd257255c Mon Sep 17 00:00:00 2001 From: Mariia Mykhailova Date: Thu, 6 Jun 2024 14:11:16 -0700 Subject: [PATCH 3/3] Apply suggestions from code review --- katas/content/distinguishing_states/index.md | 2 +- .../peres_wooters_game/Placeholder.qs | 2 +- .../peres_wooters_game/Solution.qs | 3 --- .../peres_wooters_game/Verification.qs | 10 ++++++---- .../peres_wooters_game/solution.md | 6 ++---- .../zero_plus/Verification.qs | 7 +++---- .../zero_plus_inc/Placeholder.qs | 2 +- .../zero_plus_inc/Solution.qs | 6 ++---- .../zero_plus_inc/Verification.qs | 6 +++--- .../zero_plus_inc/solution.md | 14 +++++++------- 10 files changed, 26 insertions(+), 32 deletions(-) diff --git a/katas/content/distinguishing_states/index.md b/katas/content/distinguishing_states/index.md index 74f8441bcf..62ae5a0a00 100644 --- a/katas/content/distinguishing_states/index.md +++ b/katas/content/distinguishing_states/index.md @@ -57,7 +57,7 @@ This kata is designed to get you familiar with the concept of measurements and u @[exercise]({ "id": "distinguishing_states__zero_plus_inc", - "title": "|0〉 or |+〉 or Inconclusive?", + "title": "|0〉, |+〉 or Inconclusive?", "path": "./zero_plus_inc/", "qsDependencies": [ "../KatasLibrary.qs" diff --git a/katas/content/distinguishing_states/peres_wooters_game/Placeholder.qs b/katas/content/distinguishing_states/peres_wooters_game/Placeholder.qs index 5643e339a5..a6102e85db 100644 --- a/katas/content/distinguishing_states/peres_wooters_game/Placeholder.qs +++ b/katas/content/distinguishing_states/peres_wooters_game/Placeholder.qs @@ -1,5 +1,5 @@ namespace Kata { - operation IsQubitNotInABC (q : Qubit) : Int { + operation IsQubitNotInABC(q : Qubit) : Int { // Implement your solution here... return -1; } diff --git a/katas/content/distinguishing_states/peres_wooters_game/Solution.qs b/katas/content/distinguishing_states/peres_wooters_game/Solution.qs index fce626f409..002cf9fbb5 100644 --- a/katas/content/distinguishing_states/peres_wooters_game/Solution.qs +++ b/katas/content/distinguishing_states/peres_wooters_game/Solution.qs @@ -1,6 +1,5 @@ namespace Kata { open Microsoft.Quantum.Math; - open Microsoft.Quantum.Canon; operation IsQubitNotInABC (q : Qubit) : Int { let alpha = ArcCos(Sqrt(2.0 / 3.0)); @@ -16,11 +15,9 @@ namespace Kata { Controlled H([q], a); CNOT(a, q); - // finally, measure in the standard basis let res0 = MResetZ(a); let res1 = M(q); - // dispatch on the cases if (res0 == Zero and res1 == Zero) { return 0; } diff --git a/katas/content/distinguishing_states/peres_wooters_game/Verification.qs b/katas/content/distinguishing_states/peres_wooters_game/Verification.qs index 9cbf5c1556..8bf13708b1 100644 --- a/katas/content/distinguishing_states/peres_wooters_game/Verification.qs +++ b/katas/content/distinguishing_states/peres_wooters_game/Verification.qs @@ -42,13 +42,11 @@ namespace Kata.Verification { // check that the value of ans is 0, 1 or 2 if (ans < 0 or ans > 2) { - // Message("You can not return any value other than 0, 1 or 2."); set bad_value += 1; } // check if upon conclusive result the answer is actually correct if ans == state { - // Message($"State {state} led to incorrect conclusive response {ans}."); set wrong_state += 1; } @@ -60,8 +58,12 @@ namespace Kata.Verification { Message("Correct!"); return true; } else { - Message($"Returned values other than 0, 1 or 2 {bad_value} times."); - Message($"State led to incorrect conclusive response {wrong_state} times"); + if bad_value > 0 { + Message($"Solution returned values other than 0, 1 or 2 {bad_value} times."); + } + if wrong_state > 0 { + Message($"Solution gave incorrect response {wrong_state} times"); + } Message("Incorrect."); return false; } diff --git a/katas/content/distinguishing_states/peres_wooters_game/solution.md b/katas/content/distinguishing_states/peres_wooters_game/solution.md index 7a14b7eaa6..cbdd243f4a 100644 --- a/katas/content/distinguishing_states/peres_wooters_game/solution.md +++ b/katas/content/distinguishing_states/peres_wooters_game/solution.md @@ -1,6 +1,4 @@ -### Solution - -> The task is a simple game inspired by a quantum detection problem due to Holevo ("Information-theoretical aspects of quantum measurement", A. Holevo) and Peres/Wootters ("Optimal detection of quantum information", A. Peres and W. K. Wootters). In the game, player A thinks of a number (0,1 or 2) and the opponent, player B, tries to guess any number but the one chosen by player A. +> The task is a game inspired by a quantum detection problem due to Holevo ("Information-theoretical aspects of quantum measurement", A. Holevo) and Peres/Wootters ("Optimal detection of quantum information", A. Peres and W. K. Wootters). In the game, player A thinks of a number (0, 1 or 2) and the opponent, player B, tries to guess any number but the one chosen by player A. > > Classically, if you just made a guess, you'd have to ask two questions to be right $100\%$ of the time. If instead, player A prepares a qubit with 0, 1, or 2 encoded into three single qubit states that are at an angle of 120 degrees with respect to each other and then hands the state to the opponent, then player B can apply a Positive Operator Valued Measure (POVM) consisting of 3 states that are perpendicular to the states chosen by player A. > It can be shown that this allows B to be right $100\%$ of the time with only 1 measurement, which is something that is not achievable with a von Neumann measurement on 1 qubit. @@ -14,7 +12,7 @@ $$M = \frac{1}{\sqrt{2}}\left(\begin{array}{rrr} \end{array} \right)$$ -where $\omega = e^{2 \pi i/3}$ denotes a primitive 3rd root of unity. Our task will be to implement the rank 1 POVM given by the columns of $M$ via a von Neumann measurement. This can be done by \"embedding\" $M$ into a larger unitary matrix (taking complex conjugates and transposed): +where $\omega = e^{2 \pi i/3}$ denotes a primitive third root of unity. Our task will be to implement the rank 1 POVM given by the columns of $M$ via a von Neumann measurement. This can be done by \"embedding\" $M$ into a larger unitary matrix (taking complex conjugate and transpose): $$M' = \frac{1}{\sqrt{3}}\left(\begin{array}{cccc} 1 & -1 & 1 & 0 \\ diff --git a/katas/content/distinguishing_states/zero_plus/Verification.qs b/katas/content/distinguishing_states/zero_plus/Verification.qs index 18f9237d59..59db1ee2bf 100644 --- a/katas/content/distinguishing_states/zero_plus/Verification.qs +++ b/katas/content/distinguishing_states/zero_plus/Verification.qs @@ -12,10 +12,9 @@ namespace Kata.Verification { @EntryPoint() operation CheckSolution () : Bool { - // return DistinguishStates_MultiQubit_Threshold(1, 2, 0.8, SetQubitZeroOrPlus, Kata.IsQubitZeroOrPlus); - let nTotal = 1000; - mutable nOk = 0; - let threshold = 0.8; + let nTotal = 1000; + mutable nOk = 0; + let threshold = 0.8; use qs = Qubit[1]; for i in 1 .. nTotal { diff --git a/katas/content/distinguishing_states/zero_plus_inc/Placeholder.qs b/katas/content/distinguishing_states/zero_plus_inc/Placeholder.qs index d4cc2d94cc..0a522d9dce 100644 --- a/katas/content/distinguishing_states/zero_plus_inc/Placeholder.qs +++ b/katas/content/distinguishing_states/zero_plus_inc/Placeholder.qs @@ -1,5 +1,5 @@ namespace Kata { - operation IsQubitZeroOrPlusOrInconclusive (q : Qubit) : Int { + operation IsQubitZeroPlusOrInconclusive(q : Qubit) : Int { // Implement your solution here... return -2; } diff --git a/katas/content/distinguishing_states/zero_plus_inc/Solution.qs b/katas/content/distinguishing_states/zero_plus_inc/Solution.qs index 998ed83670..a6a6060f4d 100644 --- a/katas/content/distinguishing_states/zero_plus_inc/Solution.qs +++ b/katas/content/distinguishing_states/zero_plus_inc/Solution.qs @@ -1,11 +1,9 @@ namespace Kata { open Microsoft.Quantum.Random; - operation IsQubitZeroOrPlusOrInconclusive (q : Qubit) : Int { + operation IsQubitZeroPlusOrInconclusive(q : Qubit) : Int { + // Pick a random basis let basis = DrawRandomInt(0, 1); - - // randomize over std and had if basis == 0 { - // use standard basis let result = M(q); // result is One only if the state was |+⟩ diff --git a/katas/content/distinguishing_states/zero_plus_inc/Verification.qs b/katas/content/distinguishing_states/zero_plus_inc/Verification.qs index cd2b58c18a..5b9191684e 100644 --- a/katas/content/distinguishing_states/zero_plus_inc/Verification.qs +++ b/katas/content/distinguishing_states/zero_plus_inc/Verification.qs @@ -34,8 +34,8 @@ namespace Kata.Verification { // do state prep: convert |0⟩ to outcome with return equal to state SetQubitZeroOrPlus(qs[0], state); - // get the solution's answer and verify that it's a match - let ans = Kata.IsQubitZeroOrPlusOrInconclusive(qs[0]); + // get the solution's answer and analyze it + let ans = Kata.IsQubitZeroPlusOrInconclusive(qs[0]); // keep track of the number of inconclusive answers given if ans == -1 { @@ -64,7 +64,7 @@ namespace Kata.Verification { } if IntAsDouble(nConclPlus) < thresholdConcl * IntAsDouble(nTotal) { - Message($"{nConclPlus} test runs out of {nTotal} returned conclusive |+> which does not meet the required threshold of at least {thresholdConcl * 100.0}%."); + Message($"{nConclPlus} test runs out of {nTotal} returned conclusive |+⟩ which does not meet the required threshold of at least {thresholdConcl * 100.0}%."); set isCorrect = false; } diff --git a/katas/content/distinguishing_states/zero_plus_inc/solution.md b/katas/content/distinguishing_states/zero_plus_inc/solution.md index 2ecabbe184..bc2fa25700 100644 --- a/katas/content/distinguishing_states/zero_plus_inc/solution.md +++ b/katas/content/distinguishing_states/zero_plus_inc/solution.md @@ -1,6 +1,4 @@ -### Solution - -A simple strategy that gives an inconclusive result with probability 0.75 and never errs in case it yields a conclusive result can be obtained from randomizing the choice of measurement basis between the computational basis (std) and the Hadamard basis (had). +A simple strategy that gives an inconclusive result with probability 0.75 and never errs in case it yields a conclusive result can be obtained from randomizing the choice of measurement basis between the computational basis and the Hadamard basis. Notice that when measured in the standard basis, the state $\ket{0}$ will always lead to the outcome "0", and the state $\ket{+}$ will lead to outcomes "0" and "1" with probability $\frac12$ each. This means that if we measure "1", we can with certainty conclude that the state was $\ket{+}$. @@ -19,34 +17,36 @@ This leads to the following scenarios (shown are the conditional probabilities $\ket{0}$ - std + Computational $0$ $0$ $1$ $\ket{+}$ - std + Computational $0$ $\frac12$ $\frac12$ $\ket{0}$ - had + Hadamard $\frac12$ $0$ $\frac12$ $\ket{+}$ - had + Hadamard $0$ $0$ $1$ +Since each of the four scenarios occurs with probability 25%, overall this strategy ends up correctly identifying $\ket{0}$ and $\ket{+}$ states with 12.5% probability each and giving inconclusive result with 75% probability. + > The easiest way to implement the measurement in the Hadamard basis in Q# is to apply an H gate followed by a regular measurement in computational basis. @[solution]({