forked from microsoft/qsharp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start migration of Phase Estimation kata (microsoft#1824)
* First two exercises match the last two exercises from classic Linear Algebra kata, and follow a similar approach for migrating it to Q#, replacing Python code with a hardcoded exercise * Third exercise is 1.3 from classic PhaseEstimation kata, rewritten to work with Boolean checks rather than assertions. Part 2 will include exercises 2.1 and 1.4 from classic PhaseEstimation kata and new (to katas) QPE algorithm theory and demo of its success probability --------- Co-authored-by: Scott Carda <[email protected]>
- Loading branch information
1 parent
d64d3a8
commit a8b00c8
Showing
16 changed files
with
337 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Kata { | ||
open Microsoft.Quantum.Math; | ||
|
||
function EigenvaluesS() : Complex[] { | ||
// Replace the return value with correct answer. | ||
return [Complex(0.0, 0.0), | ||
Complex(0.0, 0.0)]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Kata { | ||
open Microsoft.Quantum.Math; | ||
|
||
function EigenvaluesS() : Complex[] { | ||
return [Complex(1.0, 0.0), | ||
Complex(0.0, 1.0)]; | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
katas/content/phase_estimation/eigenvalues_s/Verification.qs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
namespace Kata.Verification { | ||
open Microsoft.Quantum.Math; | ||
|
||
function ComplexEqual(x : Complex, y : Complex) : Bool { | ||
// Tests two complex numbers for equality. | ||
AbsD(x::Real - y::Real) <= 0.001 and AbsD(x::Imag - y::Imag) <= 0.001 | ||
} | ||
|
||
|
||
@EntryPoint() | ||
operation CheckSolution() : Bool { | ||
let actual = Kata.EigenvaluesS(); | ||
let expected = [Complex(1.0, 0.0), Complex(0.0, 1.0)]; | ||
if Length(actual) != 2 { | ||
Message("The array of eigenvalues should have exactly two elements."); | ||
return false; | ||
} | ||
if ComplexEqual(actual[0], expected[0]) and ComplexEqual(actual[1], expected[1]) or | ||
ComplexEqual(actual[0], expected[1]) and ComplexEqual(actual[1], expected[0]) { | ||
Message("Correct!"); | ||
return true; | ||
} | ||
Message("Incorrect value for one of the eigenvalues."); | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
**Input:** None. | ||
|
||
**Output:** Return an array of two eigenvalues of the $S$ gate. | ||
|
||
$$S = \begin{bmatrix} 1 & 0 \\ 0 & i \end{bmatrix}$$ | ||
|
||
Sort the eigenvalues in decreasing order of their real parts. | ||
|
||
> In this task, the eigenvalues are represented as complex numbers of Q# `Complex` type. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Since the $S$ gate is diagonal, it's easy to realize that its eigenvectors are the basis vectors $\ket{0}$ and $\ket{1}$. | ||
|
||
To find the corresponding eigenvalues, you need to solve the two equations: | ||
- $S\ket{0} = \lambda \ket{0}$, which gives you $\lambda = 1$. | ||
- $S\ket{1} = \lambda \ket{1}$, which gives you $\lambda = i$. | ||
|
||
@[solution]({ | ||
"id": "phase_estimation__eigenvalues_s_solution", | ||
"codePath": "Solution.qs" | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Kata { | ||
open Microsoft.Quantum.Math; | ||
|
||
function EigenvectorsX() : Double[][] { | ||
// Replace the return value with correct answer. | ||
return [[0.0, 0.0], | ||
[0.0, 0.0]]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Kata { | ||
open Microsoft.Quantum.Math; | ||
|
||
function EigenvectorsX() : Double[][] { | ||
return [[1.0, 1.0], | ||
[1.0, -1.0]]; | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
katas/content/phase_estimation/eigenvectors_x/Verification.qs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
namespace Kata.Verification { | ||
open Microsoft.Quantum.Math; | ||
|
||
@EntryPoint() | ||
operation CheckSolution() : Bool { | ||
let actual = Kata.EigenvectorsX(); | ||
if Length(actual) != 2 { | ||
Message("The array of eigenvectors should have exactly two elements."); | ||
return false; | ||
} | ||
for i in 0 .. 1 { | ||
if Length(actual[i]) != 2 { | ||
Message("Each eigenvector should have exactly two elements."); | ||
return false; | ||
} | ||
if AbsD(actual[i][0]) + AbsD(actual[i][1]) < 1E-9 { | ||
Message("Each eigenvector should be non-zero."); | ||
return false; | ||
} | ||
} | ||
|
||
// One eigenvector has to have equal components, the other one - opposite ones | ||
if AbsD(actual[0][0] - actual[0][1]) < 1e-9 and AbsD(actual[1][0] + actual[1][1]) < 1e-9 or | ||
AbsD(actual[0][0] + actual[0][1]) < 1e-9 and AbsD(actual[1][0] - actual[1][1]) < 1e-9 { | ||
Message("Correct!"); | ||
return true; | ||
} | ||
|
||
Message("Incorrect value for one of the eigenvectors."); | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
**Input:** None. | ||
|
||
**Output:** Return an array of two eigenvectors of the $X$ gate that correspond to different eigenvalues. | ||
|
||
$$X = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}$$ | ||
|
||
The eigenvectors don't have to be normalized, that is, they don't have to describe valid quantum states. | ||
Both eigenvectors have to be non-zero. | ||
|
||
> In this task, the eigenvectors are represented as arrays of Q# `Double` type of length $2$. Your return should be an array of two such arrays. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
Since the $X$ gate is self-adjoint, you know that its eigenvalues can only be $+1$ and $-1$. | ||
Now, you need to find the eigenvectors that correspond to these eigenvalues. | ||
To do this, you need to solve the two equations: | ||
- $X \begin{bmatrix} v_0 \\ v_1 \end{bmatrix} = \begin{bmatrix} v_0 \\ v_1 \end{bmatrix}$, which gives you $v_0 = v_1$. | ||
- $X \begin{bmatrix} v_0 \\ v_1 \end{bmatrix} = -\begin{bmatrix} v_0 \\ v_1 \end{bmatrix}$, which gives you $v_0 = -v_1$. | ||
|
||
One of the eigenvectors should consist of two equal elements, and the other - of two elements with equal absolute values but opposite signs. | ||
|
||
@[solution]({ | ||
"id": "phase_estimation__eigenvectors_x_solution", | ||
"codePath": "Solution.qs" | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# Phase Estimation | ||
|
||
@[section]({ | ||
"id": "phase_estimation__overview", | ||
"title": "Overview" | ||
}) | ||
|
||
This kata introduces you to the phase estimation algorithm - an important building block in more advanced quantum algorithms such as integer factoring. | ||
|
||
**This kata covers the following topics:** | ||
|
||
- The definition of eigenvalues and eigenvectors | ||
- The phase estimation problem | ||
- The quantum phase estimation algorithm based on quantum Fourier transform | ||
|
||
**What you should know to start working on this kata:** | ||
|
||
- Basic quantum gates and measurements. | ||
- Quantum Fourier transform. | ||
|
||
@[section]({ | ||
"id": "phase_estimation__eigen", | ||
"title": "Eigenvectors, Eigenvalues, and Eigenphases" | ||
}) | ||
|
||
An *eigenvector* of a matrix $A$ is a non-zero vector that, when multiplied by that matrix, changes by a scalar factor: | ||
|
||
$$A \ket{v} = \lambda \ket{v}$$ | ||
|
||
The number $\lambda$ is called an *eigenvalue* that corresponds to this eigenvector. In general, eigenvalues of matrices can be complex numbers. | ||
|
||
Recall that all quantum gates are unitary matrices, for which their inverse equals their adjoint ($U^{-1} = U^\dagger$). This means that the eigenvalues of their eigenvectors have the property that their modulus equals $1$: | ||
|
||
$$|\lambda| = 1$$ | ||
|
||
Thus, they can be written in the following form: | ||
$$\lambda = e^{i\theta}$$ | ||
|
||
The value $\theta$ is called an *eigenphase* that corresponds to this eigenvector. | ||
|
||
> How can you prove that the modulus of an eigenvalue of a unitary matrix equals $1$? | ||
> | ||
> On one hand, by definition of an eigenvalue, | ||
> $$U \ket{v} = \lambda \ket{v}$$ | ||
> $$|U \ket{v}| = |\lambda| \cdot |\ket{v}|$$ | ||
> On the other hand, using the properties of the unitary matrix, you can write the following equation: | ||
> $$|U \ket{v}|^2 = \bra{v} U^\dagger U \ket{v} = \bra{v} U^{-1} U \ket{v} = \bra{v} I \ket{v} = \braket{v|v} = |\ket{v}|^2$$ | ||
> | ||
> From these two equations, you get the following equality: | ||
> $$(|\lambda| \cdot |\ket{v}|)^2 = |\ket{v}|^2$$ | ||
> And then, finally: | ||
> $$|\lambda| = 1$$ | ||
If the quantum gate is self-adjoint, that is, its matrix equals its inverse $U^{-1} = U$, the eigenvalues of this matrix can only be $+1$ and $-1$, with eigenphases $0$ and $\pi$, respectively. | ||
|
||
> You can prove this in a similar manner, using the defintion of an eigenvalue: | ||
> $$U^2 \ket{v} = U(U \ket{v}) = U(\lambda \ket{v}) = \lambda U \ket{v} = \lambda^2 \ket{v}$$ | ||
> At the same time, | ||
> $$U^2 \ket{v} = UU \ket{v} = U^{-1}U \ket{v} = I \ket{v} = \ket{v}$$ | ||
> So you can conclude that $\lambda^2 = 1$. | ||
For example, the $Z$ gate has two eigenvctors: | ||
- $\ket{0}$, with eigenvalue $1$ | ||
- $\ket{1}$, with eigenvalue $-1$ | ||
|
||
|
||
@[exercise]({ | ||
"id": "phase_estimation__eigenvalues_s", | ||
"title": "Find Eigenvalues of the S Gate", | ||
"path": "./eigenvalues_s/" | ||
}) | ||
|
||
@[exercise]({ | ||
"id": "phase_estimation__eigenvectors_x", | ||
"title": "Find Eigenvectors of the X Gate", | ||
"path": "./eigenvectors_x/" | ||
}) | ||
|
||
@[exercise]({ | ||
"id": "phase_estimation__state_eigenvector", | ||
"title": "Is Given State an Eigenvector of the Gate?", | ||
"path": "./state_eigenvector/" | ||
}) | ||
|
||
|
||
@[section]({ | ||
"id": "phase_estimation__problem", | ||
"title": "Phase Estimation Problem" | ||
}) | ||
|
||
The phase estimation problem is formulated as follows. | ||
|
||
You are given a unitary operator $U$ and its eigenvector $\ket{\psi}$. The eigenvector is given as a unitary operator $P$ that, when applied to $\ket{0}$, results in the state $\ket{\psi}$. | ||
|
||
Your goal is to find the eigenvalue $\lambda$ associated with this eigenvector, or, in a more common formulation, the corresponding eigenphase $\theta$: | ||
|
||
$$U\ket{\psi} = e^{2 \pi i \theta} \ket{\psi}, \theta = ?$$ | ||
|
||
The value of $\theta$ is defined to be between $0$ and $1$, since any value outside of this range has an equivalent value within it. Instead of representing $\theta$ as a decimal, sometimes it is represented as a binary fraction with $n$ digits: | ||
|
||
$$\theta = 0.\theta_1 \theta_2... \theta_n = \frac{\theta_1}{2^1}+ \frac{\theta_2}{2^2}+...\frac{\theta_n}{2^n}$$ | ||
|
||
Let's consider a simplified variant of the phase estimation problem, in which you are guaranteed that the phase $\theta$ has exactly one binary digit, that is, it's either $0$ or $\frac12$. | ||
|
||
- exercise: solve for one bit eigenphase | ||
|
||
|
||
@[section]({ | ||
"id": "phase_estimation__qpe", | ||
"title": "Quantum Phase Estimation Algorithm" | ||
}) | ||
|
||
- theory | ||
- exercise: task 1.4 to implement QPE | ||
- demo of end-to-end probabilistic behavior in case of lower precision (use R1 gate) | ||
|
||
|
||
@[section]({ | ||
"id": "phase_estimation__conclusion", | ||
"title": "Conclusion" | ||
}) | ||
|
||
Congratulations! In this kata you learned about the phase estimation problem and its solution using the quantum phase estimation algorithm. |
7 changes: 7 additions & 0 deletions
7
katas/content/phase_estimation/state_eigenvector/Placeholder.qs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Kata { | ||
operation IsEigenvector(U : Qubit => Unit, P : Qubit => Unit is Adj) : Bool { | ||
// Implement your solution here... | ||
|
||
return false; | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
katas/content/phase_estimation/state_eigenvector/Solution.qs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Kata { | ||
import Microsoft.Quantum.Diagnostics.CheckZero; | ||
operation IsEigenvector(U : Qubit => Unit, P : Qubit => Unit is Adj) : Bool { | ||
use q = Qubit(); | ||
P(q); | ||
U(q); | ||
Adjoint P(q); | ||
let ret = CheckZero(q); | ||
Reset(q); | ||
return ret; | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
katas/content/phase_estimation/state_eigenvector/Verification.qs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
namespace Kata.Verification { | ||
open Microsoft.Quantum.Unstable.StatePreparation; | ||
|
||
@EntryPoint() | ||
operation CheckSolution() : Bool { | ||
let eigenvectors = [ | ||
(Z, I, "Z, |0⟩"), | ||
(Z, X, "Z, |1⟩"), | ||
(S, I, "S, |0⟩"), | ||
(S, X, "S, |1⟩"), | ||
(X, H, "X, |+⟩"), | ||
(X, q => PreparePureStateD([1., -1.], [q]), "X, |-⟩")]; | ||
for (U, P, msg) in eigenvectors { | ||
if not Kata.IsEigenvector(U, P) { | ||
Message($"Incorrect for (U, P) = ({msg}): expected true"); | ||
return false; | ||
} | ||
} | ||
|
||
let notEigenvectors = [ | ||
(Z, H, "Z, |+⟩"), | ||
(X, X, "X, |1⟩"), | ||
(X, Z, "X, |0⟩"), | ||
(Y, H, "Y, |+⟩"), | ||
(Y, X, "Y, |1⟩")]; | ||
for (U, P, msg) in notEigenvectors { | ||
if Kata.IsEigenvector(U, P) { | ||
Message($"Incorrect for (U, |ψ⟩) = ({msg}): expected false"); | ||
return false; | ||
} | ||
} | ||
|
||
Message("Correct!"); | ||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
**Inputs:** | ||
|
||
1. A single-qubit unitary $U$. | ||
2. A single-qubit state $\ket{\psi}$, given as a unitary $P$ that prepares it from the $\ket{0}$ state. In other words, the result of applying the unitary $P$ to the state $\ket{0}$ is the $\ket{\psi}$ state: | ||
$$P\ket{0} = \ket{\psi}$$ | ||
|
||
**Output:** Return true if the given state is an eigenstate of the given unitary, and false otherwise. | ||
|
||
<details> | ||
<summary><b>Need a hint?</b></summary> | ||
|
||
The library operation <code>CheckZero</code> allows you to check whether the state of the given qubit is $\ket{0}$. | ||
|
||
</details> |
12 changes: 12 additions & 0 deletions
12
katas/content/phase_estimation/state_eigenvector/solution.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
A quantum state is an eigenstate of a quantum gate if applying that gate to that state doesn't change it, other than multiply it by a global phase. This means that your solution should probably start by preparing the state $\ket{\psi}$ and applying the unitary $U$ to it. How can you check that the state after that is still $\ket{\psi}$ (up to a global phase)? | ||
|
||
Let's consider what happens if you apply the adjoint of $P$ to the state $\ket{\psi}$: | ||
|
||
$$P^\dagger \ket{\psi} = P^\dagger P\ket{0} = I\ket{0} = \ket{0}$$ | ||
|
||
You can use this to finish the solution: apply `Adjoint P` to the state you obtained after applying $U$ and check whether the result is $\ket{0}$ using the library operation `CheckZero`. | ||
|
||
@[solution]({ | ||
"id": "phase_estimation__state_eigenvector_solution", | ||
"codePath": "Solution.qs" | ||
}) |