-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Includes 6 tasks from classic QFT kata (except register reverse and inverse QFT) and a new section that discusses equivalence of two QFT notations used in the definition and the implementation. --------- Co-authored-by: César Zaragoza Cortés <[email protected]>
- Loading branch information
1 parent
5655f6c
commit 76bbdb7
Showing
32 changed files
with
611 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,6 @@ | ||
namespace Kata { | ||
operation BinaryFractionClassical(q : Qubit, j : Bool[]) : Unit is Adj + Ctl { | ||
// Implement your solution here... | ||
|
||
} | ||
} |
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 { | ||
operation BinaryFractionClassical(q : Qubit, j : Bool[]) : Unit is Adj + Ctl { | ||
for ind in 0 .. Length(j) - 1 { | ||
if j[ind] { | ||
R1Frac(2, ind + 1, q); | ||
} | ||
} | ||
} | ||
} |
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,11 @@ | ||
namespace Kata { | ||
open Microsoft.Quantum.Arrays; | ||
open Microsoft.Quantum.Convert; | ||
open Microsoft.Quantum.Math; | ||
|
||
operation BinaryFractionClassical(q : Qubit, j : Bool[]) : Unit is Adj + Ctl { | ||
let n = Length(j); | ||
let jIntBE = BoolArrayAsInt(Reversed(j)); | ||
R1(2.0 * PI() * IntAsDouble(jIntBE) / IntAsDouble(1 <<< n), q); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
katas/content/qft/binary_fraction_classical/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.Arrays; | ||
open Microsoft.Quantum.Convert; | ||
open Microsoft.Quantum.Katas; | ||
open Microsoft.Quantum.Math; | ||
|
||
operation BinaryFractionClassical_Alternative (q : Qubit, j : Bool[]) : Unit is Adj+Ctl { | ||
// Convert the number to an integer and apply a single R1 rotation | ||
R1(2.0 * PI() * IntAsDouble(BoolArrayAsInt(Reversed(j))) / IntAsDouble(1 <<< Length(j)), q); | ||
} | ||
|
||
@EntryPoint() | ||
operation CheckSolution() : Bool { | ||
for n in 1 .. 5 { | ||
for exp in 0 .. (1 <<< n) - 1 { | ||
let j = Reversed(IntAsBoolArray(exp, n)); | ||
let solution = qs => Kata.BinaryFractionClassical(qs[0], j); | ||
let reference = qs => BinaryFractionClassical_Alternative(qs[0], j); | ||
if not CheckOperationsAreEqualStrict(1, solution, reference) { | ||
Message($"Incorrect for j = {j}."); | ||
Message("Hint: examine the effect your solution has on the state 0.6|0〉 + 0.8|1〉 and compare it with the effect it " + | ||
"is expected to have."); | ||
ShowQuantumStateComparison(1, qs => Ry(ArcTan2(0.8, 0.6) * 2.0, qs[0]), solution, reference); | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
Message("Correct!"); | ||
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,9 @@ | ||
**Inputs**: | ||
|
||
1. A qubit in state $\ket{\psi} = \alpha \ket{0} + \beta \ket{1}$. | ||
2. An array of $n$ bits $[j_1, j_2, ..., j_n]$, stored as `Bool[]`. | ||
|
||
**Goal**: | ||
Change the state of the qubit to $\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1 j_2 ... j_n} \ket{1}$, where $0.j_1 j_2 ... j_n$ is a binary fraction in big endian notation, similar to decimal fractions: | ||
|
||
$$0.j_1 j_2 ... j_n = j_1 \cdot \frac{1}{2^1} + j_2 \cdot \frac{1}{2^2} + ... + j_n \cdot \frac{1}{2^n}$$ |
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,56 @@ | ||
Since you can express the exponent of a sum as a product of exponents ($e^{a+b} = e^a \cdot e^b$), you can implement the required transformation as a sequence of rotation gates from the previous task with increasing $k$. | ||
|
||
Each of the individual rotations will use the bit $j_k$ to decide whether to apply the rotation (you only want to apply the rotation if $j_k$ is true), and the index of that bit $k$ to define the rotation angle. | ||
The gate applied for each $k$ will be: | ||
|
||
$$U_k = \begin{cases} | ||
I, j_k=0 \\ | ||
\textrm{R1Frac}(2, k), j_k=1 | ||
\end{cases}$$ | ||
|
||
Recall that | ||
|
||
$$ \textrm{R1Frac}(2, k)( \alpha \ket{0} + \beta \ket{1}) = \alpha \ket{0} + \beta \cdot e^{2\pi i/2^{k}} \ket{1} = \alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0. \underset{k-1}{\underbrace{0\dots0}} 1} \ket{1}$$ | ||
|
||
This means that the overall effect of the gate $U_k$ for each $k$ is: | ||
|
||
$$U_k (\alpha \ket{0} + \beta \ket{1}) = \alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0. \underset{k-1}{\underbrace{0\dots0}} j_k} \ket{1}$$ | ||
|
||
As you iterate over $k$, the resulting state will get closer and closer to the required one: | ||
|
||
<table> | ||
<tr> | ||
<th>$k$</th> | ||
<th>State after step $k$</th> | ||
</tr> | ||
<tr> | ||
<td>$1$</td> | ||
<td>$$\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1} \ket{1}$$</td> | ||
</tr> | ||
<tr> | ||
<td>$2$</td> | ||
<td>$$\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1j_2} \ket{1}$$</td> | ||
</tr> | ||
<tr> | ||
<td>...</td> | ||
<td>...</td> | ||
</tr> | ||
<tr> | ||
<td>$n$</td> | ||
<td>$$\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1j_2 \dots j_n}\ket{1}$$</td> | ||
</tr> | ||
</table> | ||
|
||
@[solution]({ | ||
"id": "qft__binary_fraction_classical_solution_a", | ||
"codePath": "./SolutionA.qs" | ||
}) | ||
|
||
Alternatively, you can do this in a single rotation using the $R1$ gate if you convert the array $j$ into a rotation angle. You'll need the angle $2\pi \cdot 0.j_1j_2 \dots j_n$, and this fraction can be calculated by converting the bit string into an integer $j$ (using big endian notation) and dividing it by $2^n$. | ||
|
||
This solution is better when considered on its own, since it involves doing only a single rotation rather than a series of them. However, it will not be as helpful as the first one once you get to the next task! | ||
|
||
@[solution]({ | ||
"id": "qft__binary_fraction_classical_solution_b", | ||
"codePath": "./SolutionB.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,6 @@ | ||
namespace Kata { | ||
operation BinaryFractionQuantumInPlace(j : Qubit[]) : Unit is Adj + Ctl { | ||
// Implement your solution here... | ||
|
||
} | ||
} |
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 { | ||
operation BinaryFractionQuantumInPlace(j : Qubit[]) : Unit is Adj + Ctl { | ||
H(j[0]); | ||
for ind in 1 .. Length(j) - 1 { | ||
Controlled R1Frac([j[ind]], (2, ind + 1, j[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,26 @@ | ||
namespace Kata.Verification { | ||
open Microsoft.Quantum.Arrays; | ||
open Microsoft.Quantum.Convert; | ||
open Microsoft.Quantum.Katas; | ||
open Microsoft.Quantum.Math; | ||
|
||
operation BinaryFractionQuantumInPlace_Reference(j : Qubit[]) : Unit is Adj + Ctl { | ||
H(j[0]); | ||
for ind in 1 .. Length(j) - 1 { | ||
Controlled R1Frac([j[ind]], (2, ind + 1, j[0])); | ||
} | ||
} | ||
|
||
@EntryPoint() | ||
operation CheckSolution() : Bool { | ||
for n in 1 .. 5 { | ||
if not CheckOperationsAreEqualStrict(n, Kata.BinaryFractionQuantumInPlace, BinaryFractionQuantumInPlace_Reference) { | ||
Message($"Incorrect for n = {n}."); | ||
return false; | ||
} | ||
} | ||
|
||
Message("Correct!"); | ||
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,11 @@ | ||
**Input**: | ||
A register of $n$ qubits in state $\ket{j_1 j_2 ... j_n}$. | ||
|
||
**Goal**: | ||
Change the state of the register from $\ket{j_1} \otimes \ket{j_2 ... j_n}$ to $\frac1{\sqrt2}(\ket{0} + e^{2\pi i \cdot 0.j_1 j_2 ... j_n} \ket{1}) \otimes \ket{j_2 ... j_n}$. | ||
|
||
<details> | ||
<summary><b>Need a hint?</b></summary> | ||
|
||
This task is very similar to the previous task, but the digit $j_1$ has to be encoded in-place. You can do this using the first task of the kata, "Single-Qubit QFT". | ||
</details> |
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 @@ | ||
First, let's recall the first task of the kata: a Hadamard gate applied to a single qubit, $H\ket{j_1}$, will give either | ||
$\frac1{\sqrt2}(\ket{0} + \ket{1})$ or $\frac{1}{\sqrt{2}}(\ket{0} - \ket{1})$ depending on the state of $\ket{j_1}$. This operation can also be written as | ||
$$H\ket{j_1} = \frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot \frac{j_1}{2}}\ket{1} \big)= \frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_1}\ket{1} \big)$$ | ||
|
||
So, if the starting register state is $\ket{j_1 j_2 ... j_n}$, applying a Hadamard gate to the first qubit will result in: | ||
|
||
$$\big(H_1\otimes I_{n-1} \big) \big(\ket{j_1} \otimes \ket{j_2 ... j_n} \big)= \frac1{\sqrt2} \big(\ket{0} + e^{2\pi i \cdot 0.j_1}\ket{1} \big) \otimes \ket{j_2 ... j_n} $$ | ||
|
||
After this, we can repeat the loop we used in the previous task for qubits $\ket{j_2 ... j_n}$ with the first qubit as the target to adjust the remaining phase terms via the controlled $\textrm{R1Frac}$ gate. | ||
|
||
@[solution]({ | ||
"id": "qft__binary_fraction_inplace_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,6 @@ | ||
namespace Kata { | ||
operation BinaryFractionQuantum(q : Qubit, j : Qubit[]) : Unit is Adj + Ctl { | ||
// Implement your solution here... | ||
|
||
} | ||
} |
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 BinaryFractionQuantum(q : Qubit, j : Qubit[]) : Unit is Adj + Ctl { | ||
for ind in 0 .. Length(j) - 1 { | ||
Controlled R1Frac([j[ind]], (2, ind + 1, q)); | ||
} | ||
} | ||
} |
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,27 @@ | ||
namespace Kata.Verification { | ||
open Microsoft.Quantum.Arrays; | ||
open Microsoft.Quantum.Convert; | ||
open Microsoft.Quantum.Katas; | ||
open Microsoft.Quantum.Math; | ||
|
||
operation BinaryFractionQuantum_Reference(q : Qubit, j : Qubit[]) : Unit is Adj + Ctl { | ||
for ind in 0 .. Length(j) - 1 { | ||
Controlled R1Frac([j[ind]], (2, ind + 1, q)); | ||
} | ||
} | ||
|
||
@EntryPoint() | ||
operation CheckSolution() : Bool { | ||
for n in 1 .. 5 { | ||
let solution = qs => Kata.BinaryFractionQuantum(qs[0], qs[1 ...]); | ||
let reference = qs => BinaryFractionQuantum_Reference(qs[0], qs[1 ...]); | ||
if not CheckOperationsAreEqualStrict(n + 1, solution, reference) { | ||
Message($"Incorrect for n = {n}."); | ||
return false; | ||
} | ||
} | ||
|
||
Message("Correct!"); | ||
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,10 @@ | ||
**Inputs**: | ||
|
||
1. A qubit in state $\ket{\psi} = \alpha \ket{0} + \beta \ket{1}$. | ||
2. An array of $n$ qubits $j$ in state $\ket{j_1 j_2 ... j_n}$. | ||
|
||
**Goal**: | ||
Change the state of the input qubits from $(\alpha \ket{0} + \beta \ket{1}) \otimes \ket{j_1 j_2 ... j_n}$ to $(\alpha \ket{0} + \beta \cdot e^{2\pi i \cdot 0.j_1 j_2 ... j_n} \ket{1}) \otimes \ket{j_1 j_2 ... j_n}$, where $0.j_1 j_2 ... j_n$ is a binary fraction corresponding to the basis state $j_1 j_2 ... j_n$ of the qubit array $j$. | ||
|
||
> The qubit array can be in superposition as well; | ||
the behavior of the transformation in this case is defined by its behavior on the basis states and the linearity of unitary transformations. |
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 @@ | ||
From the goal of the exercise, you can see that the register $j$ has to remain unchanged, while the first input qubit should acquire a phase that depends on the value of the qubits in the register $j$. | ||
|
||
Since $j$ is a quantum register and can be in a superposition of basis states, you cannot just measure the register and then apply the operation from the previous task using measurement results as the second argument. Instead, you have to convert the solution to the previous task from using $\textrm{R1Frac}$ gates with classical conditions to using them as controlled operations, with the qubits of the register $j$ as quantum conditions. You can do this using the `Controlled` functor. | ||
|
||
@[solution]({ | ||
"id": "qft__binary_fraction_quantum_solution", | ||
"codePath": "./Solution.qs" | ||
}) |
Oops, something went wrong.