Add tutorial on single-qubit gates (#185)

Co-authored-by: Jim Cristofono <jimcristofono@outlook.com>
This commit is contained in:
flockofonions 2019-10-31 17:36:29 -07:00 коммит произвёл Mariia Mykhailova
Родитель 05c6556960
Коммит b85a81c5f8
11 изменённых файлов: 1165 добавлений и 10 удалений

Просмотреть файл

@ -44,3 +44,4 @@ RUN ${HOME}/scripts/prebuild-kata.sh tutorials/DeutschJozsaAlgorithm DeutschJozs
RUN ${HOME}/scripts/prebuild-kata.sh tutorials/ExploringGroversAlgorithm ExploringGroversAlgorithmTutorial.ipynb
RUN ${HOME}/scripts/prebuild-kata.sh tutorials/LinearAlgebra LinearAlgebra.ipynb
RUN ${HOME}/scripts/prebuild-kata.sh tutorials/Qubit Qubit.ipynb
RUN ${HOME}/scripts/prebuild-kata.sh tutorials/SingleQubitGates SingleQubitGates.ipynb

Просмотреть файл

@ -40,6 +40,8 @@ Each kata is a separate project which includes:
which are used to represent quantum states and quantum operations.
* **[The Qubit](./tutorials/Qubit/)**.
This tutorial introduces you to the concept of a qubit.
* **[Single-Qubit Gates](./tutorials/SingleQubitGates/)**.
This tutorial introduces the concept of a quantum gate and walks you through the most common single-qubit gates.
* **[Deutsch–Jozsa algorithm](./tutorials/DeutschJozsaAlgorithm/)**.
This tutorial teaches you to implement classical functions and equivalent quantum oracles,
discusses the classical solution to the Deutsch–Jozsa problem, and introduces the Deutsch and Deutsch–Jozsa algorithms.

Просмотреть файл

@ -17,6 +17,8 @@
" which are used to represent quantum states and quantum operations.\n",
"* **[The Qubit](./tutorials/Qubit/Qubit.ipynb)**.\n",
" This tutorial introduces you to the concept of a qubit.\n",
"* **[Single-Qubit Gates](./tutorials/SingleQubitGates/SingleQubitGates.ipynb)**.\n",
" This tutorial introduces the concept of a quantum gate and walks you through the most common single-qubit gates.\n",
"* **[Deutsch–Jozsa algorithm](./tutorials/DeutschJozsaAlgorithm/DeutschJozsaAlgorithmTutorial.ipynb)**.\n",
" This tutorial teaches you to implement classical functions and equivalent quantum oracles, \n",
" discusses the classical solution to the Deutsch–Jozsa problem and introduces Deutsch and Deutsch–Jozsa algorithms.\n",

Просмотреть файл

@ -962,17 +962,9 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Your function must return a value!\n"
]
}
],
"outputs": [],
"source": [
"@exercise\n",
"def find_eigenvalue(a : Matrix, v : Matrix) -> float:\n",

Просмотреть файл

@ -0,0 +1,58 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
//////////////////////////////////////////////////////////////////////
// This file contains reference solutions to all tasks.
// You should not modify anything in this file.
// We recommend that you try to solve the tasks yourself first,
// but feel free to look up the solution if you get stuck.
//////////////////////////////////////////////////////////////////////
namespace Quantum.Kata.SingleQubitGates {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;
// Exercise 1.
operation ApplyY_Reference (q : Qubit) : Unit is Adj+Ctl {
Y(q);
}
// Exercise 2.
operation GlobalPhaseI_Reference (q : Qubit) : Unit is Adj+Ctl {
X(q);
Z(q);
Y(q);
}
// Exercise 3.
operation SignFlipOnZero_Reference (q : Qubit) : Unit is Adj+Ctl {
X(q);
Z(q);
X(q);
}
// Exercise 4.
operation PrepareMinus_Reference (q : Qubit) : Unit is Adj+Ctl {
X(q);
H(q);
}
// Exercise 5.
operation ThreeQuatersPiPhase_Reference (q : Qubit) : Unit is Adj+Ctl {
S(q);
T(q);
}
// Exercise 6.
operation PrepareRotatedState_Reference (alpha : Double, beta : Double, q : Qubit) : Unit is Adj+Ctl {
let phi = ArcTan2(beta, alpha);
Rx(2.0 * phi, q);
}
// Exercise 7.
operation PrepareArbitraryState_Reference (alpha : Double, beta : Double, theta : Double, q : Qubit) : Unit is Adj+Ctl {
let phi = ArcTan2(beta, alpha);
Ry(2.0 * phi, q);
R1(theta, q);
}
}

Просмотреть файл

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PlatformTarget>x64</PlatformTarget>
<RootNamespace>Quantum.Kata.SingleQubitGates</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Quantum.Standard" Version="0.9.1909.3002" />
<PackageReference Include="Microsoft.Quantum.Development.Kit" Version="0.9.1909.3002" />
<PackageReference Include="Microsoft.Quantum.Xunit" Version="0.9.1909.3002" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,868 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Single-Qubit Gates\n",
"\n",
"This tutorial introduces you to single-qubit gates. Quantum gates are the quantum counterpart to classical logic gates, acting as the building blocks of quantum algorithms. Quantum gates transform qubit states in various ways, and can be applied sequentially to perform complex quantum calculations. Single-qubit gates, as their name implies, act on individual qubits. You can learn more at [Wikipedia](https://en.wikipedia.org/wiki/Quantum_logic_gate).\n",
"\n",
"We recommend to go through the [tutorial that introduces the concept of qubit](../Qubit/Qubit.ipynb) before starting this one.\n",
"\n",
"This tutorial covers the following topics:\n",
"\n",
"* Matrix representation\n",
"* Ket-bra representation\n",
"* The most important single-qubit gates"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To begin, first prepare this notebook for execution (if you skip this step, you'll get \"Syntax does not match any known patterns\" error when you try to execute Q# code in the exercises):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%package Microsoft.Quantum.Katas::0.9.1909.3002"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> The package versions in the output of the cell above should always match. If you are running the Notebooks locally and the versions do not match, please install the IQ# version that matches the version of the `Microsoft.Quantum.Katas` package.\n",
"> <details>\n",
"> <summary><u>How to install the right IQ# version</u></summary>\n",
"> For example, if the version of `Microsoft.Quantum.Katas` package above is 0.1.2.3, the installation steps are as follows:\n",
">\n",
"> 1. Stop the kernel.\n",
"> 2. Uninstall the existing version of IQ#:\n",
"> dotnet tool uninstall microsoft.quantum.iqsharp -g\n",
"> 3. Install the matching version:\n",
"> dotnet tool install microsoft.quantum.iqsharp -g --version 0.1.2.3\n",
"> 4. Reinstall the kernel:\n",
"> dotnet iqsharp install\n",
"> 5. Restart the Notebook.\n",
"> </details>\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# The Basics\n",
"\n",
"There are certain properties common to all quantum gates. This section will introduce those properties, using the $X$ gate as an example."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Matrix Representation\n",
"\n",
"Quantum gates are represented as $2^N \\times 2^N$ [unitary matrices](../LinearAlgebra/LinearAlgebra.ipynb#Unitary-Matrices), where $N$ is the number of qubits the gate operates on. \n",
"As a quick reminder, a unitary matrix is a square matrix whose inverse is its adjoint. \n",
"Single qubit gates are represented by $2 \\times 2$ matrices.\n",
"Our example for this section, the $X$ gate, is represented by the following matrix:\n",
"\n",
"$$\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$$\n",
"\n",
"You may recall that the state of a qubit is represented by a vector of size $2$. You can apply a gate to a qubit by [multiplying](../LinearAlgebra/LinearAlgebra.ipynb#Matrix-Multiplication) the gate's matrix by the qubit's state vector. The result will be another vector, representing the new state of the qubit. For example, applying the $X$ gate to the computational basis states looks like this:\n",
"\n",
"$$X|0\\rangle =\n",
"\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}\n",
"\\begin{bmatrix} 1 \\\\ 0 \\end{bmatrix} =\n",
"\\begin{bmatrix} 0 \\cdot 1 + 1 \\cdot 0 \\\\ 1 \\cdot 1 + 0 \\cdot 0 \\end{bmatrix} =\n",
"\\begin{bmatrix} 0 \\\\ 1 \\end{bmatrix} \\\\\n",
"X|1\\rangle =\n",
"\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}\n",
"\\begin{bmatrix} 0 \\\\ 1 \\end{bmatrix} =\n",
"\\begin{bmatrix} 0 \\cdot 0 + 1 \\cdot 1 \\\\ 1 \\cdot 0 + 0 \\cdot 1 \\end{bmatrix} =\n",
"\\begin{bmatrix} 1 \\\\ 0 \\end{bmatrix}$$\n",
"\n",
"The general case:\n",
"\n",
"$$|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle \\\\\n",
"X|\\psi\\rangle =\n",
"\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}\n",
"\\begin{bmatrix} \\alpha \\\\ \\beta \\end{bmatrix} =\n",
"\\begin{bmatrix} 0 \\cdot \\alpha + 1 \\cdot \\beta \\\\ 1 \\cdot \\alpha + 0 \\cdot \\beta \\end{bmatrix} =\n",
"\\begin{bmatrix} \\beta \\\\ \\alpha \\end{bmatrix}$$\n",
"\n",
"> If you need a reminder of what $|0\\rangle$, $|1\\rangle$, and $|\\psi\\rangle$ mean, you can review the section on [Dirac notation](../Qubit/Qubit.ipynb#Dirac-Notation) in the previous tutorial.\n",
"\n",
"Because this is the most common way to represent quantum gates, the terms \"gate\" and \"gate matrix\" will be used interchangeably in this tutorial.\n",
"\n",
"Applying several quantum gates in sequence is equivalent to performing several of these multiplications. \n",
"For example, if you have gates $A$ and $B$ and a qubit in state $|\\psi\\rangle$, the result of applying $A$ followed by $B$ to that qubit would be $B\\big(A|\\psi\\rangle\\big)$ (the gates closest to the qubit state get applied first). \n",
"Matrix multiplication is associative, so this is equivalent to multiplying the $B$ matrix by the $A$ matrix, producing a compound gate of the two, and then applying that to the qubit: $\\big(BA\\big)|\\psi\\rangle$.\n",
"\n",
"All quantum gates are reversible - there is another gate which will undo any given gate's transformation, returning the qubit to its original state. \n",
"This means that when dealing with quantum gates, information about qubit states is never lost, as opposed to classical logic gates, some of which destroy information. \n",
"Quantum gates are represented by unitary matrices, so the inverse of a gate is its adjoint; these terms are also used interchangeably in quantum computing."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Effects on Basis States (Dirac Notation, Continued)\n",
"\n",
"There is a simple way to find out what a gate does to the two computational basis states ($|0\\rangle$ and $|1\\rangle$) from looking at its matrix that comes in handy when you want to work with states in Dirac notation. Consider an arbitrary gate:\n",
"\n",
"$$A = \\begin{bmatrix} \\epsilon & \\zeta \\\\ \\eta & \\mu \\end{bmatrix}$$\n",
"\n",
"Watch what happens when we apply it to these states:\n",
"\n",
"$$A|0\\rangle =\n",
"\\begin{bmatrix} \\epsilon & \\zeta \\\\ \\eta & \\mu \\end{bmatrix}\n",
"\\begin{bmatrix} 1 \\\\ 0 \\end{bmatrix} =\n",
"\\begin{bmatrix} \\epsilon \\cdot 1 + \\zeta \\cdot 0 \\\\ \\eta \\cdot 1 + \\mu \\cdot 0 \\end{bmatrix} =\n",
"\\begin{bmatrix} \\epsilon \\\\ \\eta \\end{bmatrix} = \\epsilon|0\\rangle + \\eta|1\\rangle \\\\\n",
"A|1\\rangle =\n",
"\\begin{bmatrix} \\epsilon & \\zeta \\\\ \\eta & \\mu \\end{bmatrix}\n",
"\\begin{bmatrix} 0 \\\\ 1 \\end{bmatrix} =\n",
"\\begin{bmatrix} \\epsilon \\cdot 0 + \\zeta \\cdot 1 \\\\ \\eta \\cdot 0 + \\mu \\cdot 1 \\end{bmatrix} =\n",
"\\begin{bmatrix} \\zeta \\\\ \\mu \\end{bmatrix} = \\zeta|0\\rangle + \\mu|1\\rangle$$\n",
"\n",
"Notice that applying the gate to the $|0\\rangle$ state transforms it into the state written as the first column of the gate's matrix. Likewise, applying the gate to the $|1\\rangle$ state transforms it into the state written as the second column. This holds true for any quantum gate, including, of course, the $X$ gate:\n",
"\n",
"$$X = \\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix} \\\\\n",
"X|0\\rangle = \\begin{bmatrix} 0 \\\\ 1 \\end{bmatrix} = |1\\rangle \\\\\n",
"X|1\\rangle = \\begin{bmatrix} 1 \\\\ 0 \\end{bmatrix} = |0\\rangle$$\n",
"\n",
"Once you understand how a gate affects the computational basis states, you can easily find how it affects any state.\n",
"Recall that any qubit state vector can be written as a linear combination of the basis states:\n",
"\n",
"$$|\\psi\\rangle = \\begin{bmatrix} \\alpha \\\\ \\beta \\end{bmatrix} = \\alpha|0\\rangle + \\beta|1\\rangle$$\n",
"\n",
"Because matrix multiplication distributes over addition, once you know how a gate affects those two basis states, you can calculate how it affects any state:\n",
"\n",
"$$X|\\psi\\rangle = X\\big(\\alpha|0\\rangle + \\beta|1\\rangle\\big) = X\\big(\\alpha|0\\rangle\\big) + X\\big(\\beta|1\\rangle\\big) = \\alpha X|0\\rangle + \\beta X|1\\rangle = \\alpha|1\\rangle + \\beta|0\\rangle$$\n",
"\n",
"That is, applying a gate to a qubit in superposition is equivalent to applying that gate to the basis states that make up that superposition and adding the results with appropriate weights."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Ket-bra Representation\n",
"\n",
"There is another way to represent quantum gates, this time using Dirac notation. However, the kets we've been using aren't enough to represent arbitrary matrices. We need to introduce another piece of notation: the **bra** (this is why Dirac notation is sometimes called **bra-ket notation**).\n",
"\n",
"Recall that kets represent column vectors; a bra is a ket's row vector counterpart. For any ket $|\\psi\\rangle$, the corresponding bra is its adjoint (conjugate transpose): $\\langle\\psi| = |\\psi\\rangle^\\dagger$.\n",
"\n",
"> As a quick reminder, the [adjoint](../LinearAlgebra/LinearAlgebra.ipynb#Unary-Operations), also known as the conjugate transpose of a matrix, well, the conjugate of that matrix's transpose.\n",
"\n",
"Some examples:\n",
"\n",
"<table style=\"border:1px solid\">\n",
" <col width=150>\n",
" <col width=150>\n",
" <tr>\n",
" <th style=\"text-align:center; border:1px solid\">Ket</th>\n",
" <th style=\"text-align:center; border:1px solid\">Bra</th>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$|0\\rangle = \\begin{bmatrix} 1 \\\\ 0 \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\langle0| = \\begin{bmatrix} 1 & 0 \\end{bmatrix}$</td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$|1\\rangle = \\begin{bmatrix} 0 \\\\ 1 \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\langle1| = \\begin{bmatrix} 0 & 1 \\end{bmatrix}$</td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$|i\\rangle = \\begin{bmatrix} \\frac{1}{\\sqrt{2}} \\\\ \\frac{i}{\\sqrt{2}} \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\langle i| = \\begin{bmatrix} \\frac{1}{\\sqrt{2}} & -\\frac{i}{\\sqrt{2}} \\end{bmatrix}$</td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$|\\psi\\rangle = \\begin{bmatrix} \\alpha \\\\ \\beta \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\langle\\psi| = \\begin{bmatrix} \\overline{\\alpha} & \\overline{\\beta} \\end{bmatrix}$</td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\langle\\psi| = \\overline{\\alpha}\\langle0| + \\overline{\\beta}\\langle1|$</td>\n",
" </tr>\n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Kets and bras give us a neat way to express [inner](../LinearAlgebra/LinearAlgebra.ipynb#Inner-Product) and [outer](../LinearAlgebra/LinearAlgebra.ipynb#Outer-Product) products. The inner product of $|\\phi\\rangle$ and $|\\psi\\rangle$ is the matrix product of $\\langle\\phi|$ and $|\\psi\\rangle$, denoted as $\\langle\\phi|\\psi\\rangle$, and their outer product is the matrix product of $|\\phi\\rangle$ and $\\langle\\psi|$, denoted as $|\\phi\\rangle\\langle\\psi|$. Notice that the norm of $|\\psi\\rangle$ is $\\sqrt{\\langle\\psi|\\psi\\rangle}$.\n",
"\n",
"This brings us to representing matrices. Recall that the outer product of two vectors of the same size produces a square matrix. We can use a linear combination of several outer products of simple vectors (such as basis vectors) to express any square matrix. For example, the $X$ gate can be expressed as follows:\n",
"\n",
"$$X = |0\\rangle\\langle1| + |1\\rangle\\langle0| \\\\\n",
"|0\\rangle\\langle1| + |1\\rangle\\langle0| =\n",
"\\begin{bmatrix} 1 \\\\ 0 \\end{bmatrix}\\begin{bmatrix} 0 & 1 \\end{bmatrix} +\n",
"\\begin{bmatrix} 0 \\\\ 1 \\end{bmatrix}\\begin{bmatrix} 1 & 0 \\end{bmatrix} =\n",
"\\begin{bmatrix} 0 & 1 \\\\ 0 & 0 \\end{bmatrix} + \\begin{bmatrix} 0 & 0 \\\\ 1 & 0 \\end{bmatrix} =\n",
"\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$$\n",
"\n",
"This representation can be used to carry out calculations in Dirac notation without ever switching back to matrix representation:\n",
"\n",
"$$X|0\\rangle = \\big(|0\\rangle\\langle1| + |1\\rangle\\langle0|\\big)|0\\rangle = |0\\rangle\\langle1|0\\rangle + |1\\rangle\\langle0|0\\rangle = |0\\rangle\\big(\\langle1|0\\rangle\\big) + |1\\rangle\\big(\\langle0|0\\rangle\\big) = |0\\rangle(0) + |1\\rangle(1) = |1\\rangle$$\n",
"\n",
"> That last step may seem a bit confusing. Recall that $|0\\rangle$ and $|1\\rangle$ form an **orthonormal basis**. That is, they are both normalized, and they are orthogonal to each other.\n",
">\n",
"> A vector is normalized if its norm is equal to $1$, which only happens if its inner product with itself is equal to $1$. This means that $\\langle0|0\\rangle = \\langle1|1\\rangle = 1$\n",
">\n",
"> Two vectors are orthogonal to each other if their inner product equals $0$. This means that $\\langle0|1\\rangle = \\langle 1|0\\rangle = 0$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> ## Ket-bra decomposition\n",
">\n",
"> This section deals with finding the ket-bra decompositions of quantum gates. This section is not necessary to start working with quantum gates, so feel free to skip it for now, and come back to it later.\n",
">\n",
"> You can use the properties of [eigenvalues and eigenvectors](../LinearAlgebra/LinearAlgebra.ipynb#Part-III:-Eigenvalues-and-Eigenvectors) to find the ket-bra decomposition of any gate. Given a gate $A$, and its orthogonal eigenvectors $|\\phi\\rangle$ and $|\\psi\\rangle$, if:\n",
">\n",
"> $$A|\\phi\\rangle = x_\\phi|\\phi\\rangle \\\\\n",
"A|\\psi\\rangle = x_\\psi|\\psi\\rangle$$\n",
">\n",
"> Then:\n",
">\n",
"> $$A = x_\\phi|\\phi\\rangle\\langle\\phi| + x_\\psi|\\psi\\rangle\\langle\\psi|$$\n",
">\n",
"> Let's use our $X$ gate as a simple example. The $X$ gate has two eigenvectors: $|+\\rangle = \\frac{1}{\\sqrt{2}}\\big(|0\\rangle + |1\\rangle\\big)$ and $|-\\rangle = \\frac{1}{\\sqrt{2}}\\big(|0\\rangle - |1\\rangle\\big)$. Their eigenvalues are $1$ and $-1$ respectively:\n",
">\n",
"> $$X|+\\rangle = |+\\rangle \\\\\n",
"X|-\\rangle = -|-\\rangle$$\n",
">\n",
"> Here's what the decomposition looks like:\n",
">\n",
"> $$X = |+\\rangle\\langle+| - |-\\rangle\\langle-| = \\\\\n",
"= \\frac{1}{2}\\big[\\big(|0\\rangle + |1\\rangle\\big)\\big(\\langle0| + \\langle1|\\big) - \\big(|0\\rangle - |1\\rangle\\big)\\big(\\langle0| - \\langle1|\\big)\\big] = \\\\\n",
"= \\frac{1}{2}\\big(\\color{red}{|0\\rangle\\langle0|} + |0\\rangle\\langle1| + |1\\rangle\\langle0| + \\color{red}{|1\\rangle\\langle1|} - \\color{red}{|0\\rangle\\langle0|} + |0\\rangle\\langle1| + |1\\rangle\\langle0| - \\color{red}{|1\\rangle\\langle1|}\\big) = \\\\\n",
"= \\frac{1}{2}\\big(2|0\\rangle\\langle1| + 2|1\\rangle\\langle0|\\big) = |0\\rangle\\langle1| + |1\\rangle\\langle0|$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Important Gates\n",
"\n",
"This section introduces some of the common single-qubit gates, including their matrix form, their ket-bra decomposition, and a brief \"cheatsheet\" listing their effect on some common qubit states.\n",
"\n",
"You can use a tool called [Quirk](https://algasert.com/quirk) to visualize how these gates interact with various qubit states.\n",
"\n",
"This section relies on the following notation:\n",
"\n",
"<table>\n",
" <col width=160>\n",
" <col width=160>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$|+\\rangle = \\frac{1}{\\sqrt{2}}\\big(|0\\rangle + |1\\rangle\\big)$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$|-\\rangle = \\frac{1}{\\sqrt{2}}\\big(|0\\rangle - |1\\rangle\\big)$</td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$|i\\rangle = \\frac{1}{\\sqrt{2}}\\big(|0\\rangle + i|1\\rangle\\big)$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$|-i\\rangle = \\frac{1}{\\sqrt{2}}\\big(|0\\rangle - i|1\\rangle\\big)$</td>\n",
" </tr>\n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pauli Gates\n",
"\n",
"The Pauli gates, named after [Wolfgang Pauli](https://en.wikipedia.org/wiki/Wolfgang_Pauli), are based on the so-called **Pauli matrices**. All three Pauli gates are **self-adjoint**, meaning that each one is its own inverse.\n",
"\n",
"<table style=\"border:1px solid\">\n",
" <col width=50>\n",
" <col width=50>\n",
" <col width=150>\n",
" <col width=200>\n",
" <col width=150>\n",
" <col width=50>\n",
" <tr>\n",
" <th style=\"text-align:center; border:1px solid\">Gate</th>\n",
" <th style=\"text-align:center; border:1px solid\">Matrix</th>\n",
" <th style=\"text-align:center; border:1px solid\">Ket-Bra</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to basis states</th>\n",
" <th style=\"text-align:center; border:1px solid\">Q# Documentation</th>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$X$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$|0\\rangle\\langle1| + |1\\rangle\\langle0|$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$X|\\psi\\rangle = \\alpha|1\\rangle + \\beta|0\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$X|0\\rangle = |1\\rangle \\\\\n",
"X|1\\rangle = |0\\rangle \\\\\n",
"X|+\\rangle = |+\\rangle \\\\\n",
"X|-\\rangle = -|-\\rangle \\\\\n",
"X|i\\rangle = i|-i\\rangle \\\\\n",
"X|-i\\rangle = -i|i\\rangle$ </td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.x>X</a></td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$Y$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} 0 & -i \\\\ i & 0 \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$i(|1\\rangle\\langle0| - |0\\rangle\\langle1|)$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$Y|\\psi\\rangle = i\\big(\\alpha|1\\rangle - \\beta|0\\rangle\\big)$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$Y|0\\rangle = i|1\\rangle \\\\\n",
"Y|1\\rangle = -i|0\\rangle \\\\\n",
"Y|+\\rangle = -i|-\\rangle \\\\\n",
"Y|-\\rangle = i|+\\rangle \\\\\n",
"Y|i\\rangle = |i\\rangle \\\\\n",
"Y|-i\\rangle = -|-i\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.y>Y</a></td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$Z$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} 1 & 0 \\\\ 0 & -1 \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$|0\\rangle\\langle0| - |1\\rangle\\langle1|$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$Z|\\psi\\rangle = \\alpha|0\\rangle - \\beta|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$Z|0\\rangle = |0\\rangle \\\\\n",
"Z|1\\rangle = -|1\\rangle \\\\\n",
"Z|+\\rangle = |-\\rangle \\\\\n",
"Z|-\\rangle = |+\\rangle \\\\\n",
"Z|i\\rangle = |-i\\rangle \\\\\n",
"Z|-i\\rangle = |i\\rangle$ </td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.z>Z</a></td>\n",
" </tr>\n",
"</table>\n",
"\n",
"> The $X$ gate is sometimes referred to as the **bit flip** gate, or the **NOT** gate, because it acts like the classical NOT gate on the computational basis.\n",
">\n",
"> The $Z$ gate is sometimes referred to as the **phase flip** gate."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <span style=\"color:blue\">Demo: Pauli Gates</span>\n",
"\n",
"The following cell contains code demonstrating how to apply gates in Q#, using the Pauli $X$ gate as an example. It sets up a series of quantum states, and then shows the result of applying the $X$ gate to each one. To run the demo, run the next cell using `Ctrl+Enter` (`⌘+Enter` on a Mac), then run the cell after it to see the output.\n",
"\n",
"In the previous tutorial we discussed that the qubit state in Q# cannot be directly assigned or accessed. The same logic is extended to the quantum gates: applying a gate to a qubit modifies the internal state of that qubit but doesn't return the resulting state of the qubit. This is why we never assign the output of these gates to any variables in this demo - they don't produce any output.\n",
"\n",
"Applying several gates in a row follows the same principle. In the mathematical notation applying an $X$ gate followed by a $Z$ gate to a state $|\\psi\\rangle$ is denoted as $Z(X(|\\psi\\rangle))$, because the result of applying a gate to a state is another state. In Q#, applying a gate doesn't return anything, so you can't use its output as an input to another gate - something like `Z(X(q))` will not produce expected result. Instead, to apply several gates to the same qubit, you need to call them separately in the order in which they are applied:\n",
"\n",
"```\n",
"X(q);\n",
"Z(q);\n",
"```\n",
"\n",
"All the basic gates we will be covering in this tutorial are part of the [Intrinsic](https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic) namespace. We're also using the function [DumpMachine](https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.diagnostics.dumpmachine) to print the state of the quantum simulator."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"// Run this cell using Ctrl+Enter (⌘+Enter on Mac)\n",
"// Run the next cell to see the output\n",
"\n",
"// To use a namespace, you need to use the `open` keyword to access it\n",
"open Microsoft.Quantum.Diagnostics;\n",
"\n",
"operation PauliGates_Demo () : Unit {\n",
" let divider = \"--------------------------------------------------------------------------------------------------\";\n",
" // This allocates a qubit for us to work with\n",
" using (q = Qubit()) {\n",
" \n",
" // This will put the qubit into an uneven superposition |𝜓❭,\n",
" // where the amplitudes of |0⟩ and |1⟩ have different moduli\n",
" Ry(1.0, q);\n",
"\n",
" Message(\"Qubit in state |𝜓❭:\");\n",
" DumpMachine();\n",
" Message(divider);\n",
" \n",
" // Let's apply the X gate; notice how it swaps the amplitudes of the |0❭ and |1❭ basis states\n",
" X(q);\n",
" Message(\"Qubit in state X|𝜓❭:\");\n",
" DumpMachine();\n",
" Message(divider);\n",
" \n",
" // Applying the Z gate adds -1 relative phase to the |1❭ basis states\n",
" Z(q);\n",
" Message(\"Qubit in state ZX|𝜓❭:\");\n",
" DumpMachine();\n",
" Message(divider);\n",
" \n",
" // Finally, applying the Y gate returns the qubit to its original state |𝜓❭, with an extra global phase of i\n",
" Y(q);\n",
" Message(\"Qubit in state YZX|𝜓❭:\");\n",
" DumpMachine();\n",
" \n",
" // This returns the qubit into state |0❭\n",
" Reset(q);\n",
" }\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"%simulate PauliGates_Demo"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises\n",
"\n",
"The following exercises are designed to test your understanding of the concepts you've learned so far. \n",
"In each exercise your task is to implement an operation that applies a particular transformation to a qubit. \n",
"Unlike the demos you have seen so far, you don't have to allocate the qubit or to put it into a certain initial state - the qubit is already allocated, prepared in some state and provided to you as an input to the operation.\n",
"\n",
"### <span style=\"color:blue\">Exercise 1</span>: The $Y$ gate\n",
"\n",
"**Input:** A qubit in an arbitrary state $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$.\n",
"\n",
"**Goal:** Apply the $Y$ gate to the qubit, i.e., transform the given state into $i\\alpha|1\\rangle - i\\beta|0\\rangle$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%kata T1_ApplyY_Test\n",
"\n",
"operation ApplyY (q : Qubit) : Unit is Adj+Ctl {\n",
" // Fill in your code here, then run the cell to test your work.\n",
" // For this exercise, just apply the Y gate.\n",
" // ...\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <span style=\"color:blue\">Exercise 2</span>: Applying a global phase $i$\n",
"\n",
"**Input:** A qubit in an arbitrary state $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$.\n",
"\n",
"**Goal:** Use several Pauli gates to change the qubit state to $i|\\psi\\rangle = i\\alpha|0\\rangle + i\\beta|1\\rangle$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%kata T2_GlobalPhaseI_Test\n",
"\n",
"operation GlobalPhaseI (q : Qubit) : Unit is Adj+Ctl {\n",
" // ...\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <span style=\"color:blue\">Exercise 3</span>*: Applying a $-1$ phase to $|0\\rangle$ state\n",
"\n",
"**Input:** A qubit in an arbitrary state $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$.\n",
"\n",
"**Goal:** Use several Pauli gates to change the qubit state to $- \\alpha|0\\rangle + \\beta|1\\rangle$, i.e., apply the transformation represented by the following matrix::\n",
"\n",
"$$\\begin{bmatrix} -1 & 0 \\\\ 0 & 1 \\end{bmatrix}$$\n",
"\n",
"<br/>\n",
"<details>\n",
" <summary><strong>Need a hint? Click here</strong></summary>\n",
" Experiment with different sequences of Pauli gates and observe their effect on the state.\n",
"</details>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%kata T3_SignFlipOnZero_Test\n",
"\n",
"operation SignFlipOnZero (q : Qubit) : Unit is Adj+Ctl {\n",
" // ...\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Identity\n",
"\n",
"The identity gate is mostly here for completeness, at least for now. It will come in handy when dealing with multi-qubit systems and multi-qubit gates. It is represented by the identity matrix, and does not affect the state of the qubit.\n",
"\n",
"<table style=\"border:1px solid\">\n",
" <col width=50>\n",
" <col width=50>\n",
" <col width=150>\n",
" <col width=200>\n",
" <col width=50>\n",
" <tr>\n",
" <th style=\"text-align:center; border:1px solid\">Gate</th>\n",
" <th style=\"text-align:center; border:1px solid\">Matrix</th>\n",
" <th style=\"text-align:center; border:1px solid\">Ket-Bra</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$</th>\n",
" <th style=\"text-align:center; border:1px solid\">Q# Documentation</th>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$I$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} 1 & 0 \\\\ 0 & 1 \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$|0\\rangle\\langle0| + |1\\rangle\\langle1|$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$I|\\psi\\rangle = |\\psi\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.i>I</a></td>\n",
" </tr>\n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Hadamard\n",
"\n",
"The **Hadamard** gate is an extremely important quantum gate. Unlike the previous gates, applying the Hadamard gate to a qubit in a computational basis state puts that qubit into a superposition.\n",
"Like the Pauli gates, the Hadamard gate is self-adjoint.\n",
"\n",
"<table style=\"border:1px solid\">\n",
" <col width=50>\n",
" <col width=200>\n",
" <col width=150>\n",
" <col width=260>\n",
" <col width=150>\n",
" <col width=50>\n",
" <tr>\n",
" <th style=\"text-align:center; border:1px solid\">Gate</th>\n",
" <th style=\"text-align:center; border:1px solid\">Matrix</th>\n",
" <th style=\"text-align:center; border:1px solid\">Ket-Bra</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to basis states</th>\n",
" <th style=\"text-align:center; border:1px solid\">Q# Documentation</th>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$H$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} \\frac{1}{\\sqrt{2}} & \\frac{1}{\\sqrt{2}} \\\\ \\frac{1}{\\sqrt{2}} & -\\frac{1}{\\sqrt{2}} \\end{bmatrix} = \\frac{1}{\\sqrt{2}}\\begin{bmatrix} 1 & 1 \\\\ 1 & -1 \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$|0\\rangle\\langle+| + |1\\rangle\\langle-|$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$H|\\psi\\rangle = \\alpha|+\\rangle + \\beta|-\\rangle = \\frac{\\alpha + \\beta}{\\sqrt{2}}|0\\rangle + \\frac{\\alpha - \\beta}{\\sqrt{2}}|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$H|0\\rangle = |+\\rangle \\\\\n",
"H|1\\rangle = |-\\rangle \\\\\n",
"H|+\\rangle = |0\\rangle \\\\\n",
"H|-\\rangle = |1\\rangle \\\\\n",
"H|i\\rangle = e^{i\\pi/4}|-i\\rangle \\\\\n",
"H|-i\\rangle = e^{-i\\pi/4}|i\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.h>H</a></td>\n",
" </tr>\n",
"</table>\n",
"\n",
"> As a reminder, $e^{i\\pi/4} = \\frac{1}{\\sqrt2} (1 + i)$ and $e^{-i\\pi/4} = \\frac{1}{\\sqrt2} (1 - i)$. \n",
"> If you need a refresher on calculating expressions like $e^{i\\theta}$, you should review the section on [complex exponentiation](../ComplexArithmetic/ComplexArithmetic.ipynb#Imaginary-Exponents)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <span style=\"color:blue\">Exercise 4</span>: Preparing a $|-\\rangle$ state\n",
"\n",
"**Input:** A qubit in state $|0\\rangle$.\n",
"\n",
"**Goal:** Transform the qubit into state $|-\\rangle$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%kata T4_PrepareMinus_Test\n",
"\n",
"operation PrepareMinus (q : Qubit) : Unit is Adj+Ctl {\n",
" // ...\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Phase Shift Gates\n",
"\n",
"The next two gates are known as phase shift gates. They apply a phase to the $|1\\rangle$ state, and leave the $|0\\rangle$ state unchanged.\n",
"\n",
"<table style=\"border:1px solid\">\n",
" <col width=50>\n",
" <col width=50>\n",
" <col width=150>\n",
" <col width=200>\n",
" <col width=150>\n",
" <col width=50>\n",
" <tr>\n",
" <th style=\"text-align:center; border:1px solid\">Gate</th>\n",
" <th style=\"text-align:center; border:1px solid\">Matrix</th>\n",
" <th style=\"text-align:center; border:1px solid\">Ket-Bra</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to basis states</th>\n",
" <th style=\"text-align:center; border:1px solid\">Q# Documentation</th>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$S$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} 1 & 0 \\\\ 0 & i \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$|0\\rangle\\langle0| + i|1\\rangle\\langle1|$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$S|\\psi\\rangle = \\alpha|0\\rangle + i\\beta|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$S|0\\rangle = |0\\rangle \\\\\n",
"S|1\\rangle = i|1\\rangle \\\\\n",
"S|+\\rangle = |i\\rangle \\\\\n",
"S|-\\rangle = |-i\\rangle \\\\\n",
"S|i\\rangle = |-\\rangle \\\\\n",
"S|-i\\rangle = |+\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.s>S</a></td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$T$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} 1 & 0 \\\\ 0 & e^{i\\pi/4} \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$|0\\rangle\\langle0| + e^{i\\pi/4}|1\\rangle$$\\langle1|$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$T|\\psi\\rangle = \\alpha|0\\rangle + e^{i\\pi/4} \\beta |1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$T|0\\rangle = |0\\rangle \\\\\n",
"T|1\\rangle = e^{i\\pi/4}|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.t>T</a></td>\n",
" </tr>\n",
"</table>\n",
"\n",
"> Notice that applying the $T$ gate twice is equivalent to applying the $S$ gate, and applying the $S$ gate twice is equivalent to applying the $Z$ gate: \n",
"$$T^2 = S, S^2 = Z$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <span style=\"color:blue\">Exercise 5</span>: Three-fourths phase\n",
"\n",
"**Input:** A qubit in an arbitrary state $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$.\n",
"\n",
"**Goal:** Use several phase shift gates to apply the transformation represented by the following matrix to the given qubit:\n",
"\n",
"$$\\begin{bmatrix} 1 & 0 \\\\ 0 & e^{3i\\pi/4} \\end{bmatrix}$$\n",
"\n",
"<br/>\n",
"<details>\n",
" <summary><strong>Need a hint? Click here</strong></summary>\n",
" As a reminder, $i = e^{i\\pi/2}$.\n",
"</details> "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%kata T5_ThreeQuatersPiPhase_Test\n",
"\n",
"operation ThreeQuatersPiPhase (q : Qubit) : Unit is Adj+Ctl {\n",
" // ...\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Rotation Gates\n",
"\n",
"The next few gates are parametrized: their exact behavior depends on a numeric parameter - an angle $\\theta$, given in radians. \n",
"These gates are the $X$ rotation gate $R_x(\\theta)$, $Y$ rotation gate $R_y(\\theta)$, $Z$ rotation gate $R_z(\\theta)$, and the arbitrary phase gate $R_1(\\theta)$. \n",
"Note that for the first three gates the parameter $\\theta$ is multiplied by $\\frac{1}{2}$ within the gate's matrix.\n",
"\n",
"> These gates are known as rotation gates, because they represent rotations around various axes on the Bloch sphere. The Bloch sphere is a way of representing the qubit states visually, mapping them onto the surface of a sphere. \n",
"> Unfortunately, this visualization isn't very useful beyond single-qubit states, which is why we have opted not to go into details in this tutorial series. \n",
"> If you are curious about it, you can learn more in [this slide deck](http://www.vcpc.univie.ac.at/~ian/hotlist/qc/talks/bloch-sphere.pdf) or in [Wikipedia article](https://en.wikipedia.org/wiki/Bloch_sphere).\n",
"\n",
"<table style=\"border:1px solid\">\n",
" <col width=50>\n",
" <col width=100>\n",
" <col width=400>\n",
" <col width=250>\n",
" <col width=50>\n",
" <tr>\n",
" <th style=\"text-align:center; border:1px solid\">Gate</th>\n",
" <th style=\"text-align:center; border:1px solid\">Matrix</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$</th>\n",
" <th style=\"text-align:center; border:1px solid\">Applying to basis states</th>\n",
" <th style=\"text-align:center; border:1px solid\">Q# Documentation</th>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$R_x(\\theta)$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} \\cos\\frac{\\theta}{2} & -i\\sin\\frac{\\theta}{2} \\\\ -i\\sin\\frac{\\theta}{2} & \\cos\\frac{\\theta}{2} \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$R_x(\\theta)|\\psi\\rangle = (\\alpha\\cos\\frac{\\theta}{2} - i\\beta\\sin\\frac{\\theta}{2})|0\\rangle + (\\beta\\cos\\frac{\\theta}{2} - i\\alpha\\sin\\frac{\\theta}{2})|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$R_x(\\theta)|0\\rangle = \\cos\\frac{\\theta}{2}|0\\rangle - i\\sin\\frac{\\theta}{2}|1\\rangle \\\\\n",
"R_x(\\theta)|1\\rangle = \\cos\\frac{\\theta}{2}|1\\rangle - i\\sin\\frac{\\theta}{2}|0\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.rx>Rx</a></td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$R_y(\\theta)$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} \\cos\\frac{\\theta}{2} & -\\sin\\frac{\\theta}{2} \\\\ \\sin\\frac{\\theta}{2} & \\cos\\frac{\\theta}{2} \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$R_y(\\theta)|\\psi\\rangle = (\\alpha\\cos\\frac{\\theta}{2} - \\beta\\sin\\frac{\\theta}{2})|0\\rangle + (\\beta\\cos\\frac{\\theta}{2} + \\alpha\\sin\\frac{\\theta}{2})|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$R_y(\\theta)|0\\rangle = \\cos\\frac{\\theta}{2}|0\\rangle + \\sin\\frac{\\theta}{2}|1\\rangle \\\\\n",
"R_y(\\theta)|1\\rangle = \\cos\\frac{\\theta}{2}|1\\rangle - \\sin\\frac{\\theta}{2}|0\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.ry>Ry</a></td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$R_z(\\theta)$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} e^{-i\\theta/2} & 0 \\\\ 0 & e^{i\\theta/2} \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$R_z(\\theta)|\\psi\\rangle = \\alpha e^{-i\\theta/2}|0\\rangle + \\beta e^{i\\theta/2}|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$R_z(\\theta)|0\\rangle = e^{-i\\theta/2}|0\\rangle \\\\\n",
"R_z(\\theta)|1\\rangle = e^{i\\theta/2}|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.rz>Rz</a></td>\n",
" </tr>\n",
" <tr>\n",
" <td style=\"text-align:center; border:1px solid\">$R_1(\\theta)$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$\\begin{bmatrix} 1 & 0 \\\\ 0 & e^{i\\theta} \\end{bmatrix}$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$R_1(\\theta)|\\psi\\rangle = \\alpha|0\\rangle + \\beta e^{i\\theta}|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\">$R_1(\\theta)|0\\rangle = |0\\rangle \\\\\n",
"R_1(\\theta)|1\\rangle = e^{i\\theta}|1\\rangle$</td>\n",
" <td style=\"text-align:center; border:1px solid\"><a href=https://docs.microsoft.com/qsharp/api/qsharp/microsoft.quantum.intrinsic.r1>R1</a></td>\n",
" </tr>\n",
"</table>\n",
"\n",
"You have already encountered some special cases of the $R_1$ gate: \n",
"\n",
"$$T = R_1(\\frac{\\pi}{4}), S = R_1(\\frac{\\pi}{2}), Z = R_1(\\pi)$$\n",
"\n",
"In addition, this gate is closely related to the $R_z$ gate: applying $R_1$ gate is equivalent to applying the $R_z$ gate, and then applying a global phase: \n",
"\n",
"$$R_1(\\theta) = e^{i\\theta/2}R_z(\\theta)$$\n",
"\n",
"In addition, the rotation gates are very closely related to their respective Pauli gates: \n",
"\n",
"$$X = iR_x(\\pi), Y = iR_y(\\pi), Z = iR_z(\\pi)$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <span style=\"color:blue\">Exercise 6</span>: Preparing a rotated state\n",
"\n",
"**Inputs:**\n",
"\n",
"1. Real numbers $\\alpha$ and $\\beta$ such that $\\alpha^2 + \\beta^2 = 1$.\n",
"3. A qubit in state $|0\\rangle$.\n",
"\n",
"**Goal:** Use a rotation gate to transform the qubit into state $\\alpha|0\\rangle -i\\beta|1\\rangle$\n",
"\n",
"> You will probably need functions from the [Math](https://docs.microsoft.com/en-us/qsharp/api/qsharp/microsoft.quantum.math?view=qsharp-preview) namespace, specifically [ArcTan2](https://docs.microsoft.com/en-us/qsharp/api/qsharp/microsoft.quantum.math.arctan2?view=qsharp-preview).\n",
"> \n",
"> You can assign variables in Q# by using the `let` keyword: `let num = 3;` or `let result = Function(input);`\n",
"\n",
"<details>\n",
" <summary><strong>Need a hint? Click here</strong></summary>\n",
" Don't forget, you can tell what a matrix does to the basis states by looking at its matrix: the first column of the matrix is the state into which it will transform the $|0\\rangle$ state.\n",
"</details> "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%kata T6_PrepareRotatedState_Test\n",
"\n",
"open Microsoft.Quantum.Math;\n",
"\n",
"operation PrepareRotatedState (alpha : Double, beta : Double, q : Qubit) : Unit is Adj+Ctl {\n",
" // ...\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### <span style=\"color:blue\">Exercise 7</span>**: Preparing an arbitrary state\n",
"\n",
"**Inputs:**\n",
"\n",
"1. A non-negative real number $\\alpha$.\n",
"2. A non-negative real number $\\beta = \\sqrt{1 - \\alpha^2}$.\n",
"3. A real number $\\theta$.\n",
"4. A qubit in state $|0\\rangle$.\n",
"\n",
"**Goal:** Transform the qubit into state $\\alpha|0\\rangle + e^{i\\theta}\\beta|1\\rangle$.\n",
"\n",
"> Since only the relative amplitudes and relative phase have any physical meaning, this allows us to prepare any single-qubit quantum state we want to."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%kata T7_PrepareArbitraryState_Test\n",
"\n",
"open Microsoft.Quantum.Math;\n",
"\n",
"operation PrepareArbitraryState (alpha : Double, beta : Double, theta : Double, q : Qubit) : Unit is Adj+Ctl {\n",
" // ...\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Conclusion\n",
"\n",
"Congratulations! You have learned enough to try solving the first part of the [Basic Gates kata](../../BasicGates/BasicGates.ipynb). \n",
"When you are done with that, proceed to learn about the multi-qubit systems and the multi-qubit gates."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Q#",
"language": "qsharp",
"name": "iqsharp"
},
"language_info": {
"file_extension": ".qs",
"mimetype": "text/x-qsharp",
"name": "qsharp",
"version": "0.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

Просмотреть файл

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29306.81
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SingleQubitGates", "SingleQubitGates.csproj", "{D00121A5-6A8E-474B-A0CA-BC01C4488F43}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D00121A5-6A8E-474B-A0CA-BC01C4488F43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D00121A5-6A8E-474B-A0CA-BC01C4488F43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D00121A5-6A8E-474B-A0CA-BC01C4488F43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D00121A5-6A8E-474B-A0CA-BC01C4488F43}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E500D02C-E57E-4624-A303-D368FB4A259F}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
//////////////////////////////////////////////////////////////////
// This file is a back end for the tasks in Basic Gates tutorial.
// We strongly recommend to use the Notebook version of the tutorial
// to enjoy the full experience.
//////////////////////////////////////////////////////////////////
namespace Quantum.Kata.SingleQubitGates {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;
// Exercise 1.
operation ApplyY (q : Qubit) : Unit is Adj+Ctl {
// ...
}
// Exercise 2.
operation GlobalPhaseI (q : Qubit) : Unit is Adj+Ctl {
// ...
}
// Exercise 3.
operation SignFlipOnZero (q : Qubit) : Unit is Adj+Ctl {
// ...
}
// Exercise 4.
operation PrepareMinus (q : Qubit) : Unit is Adj+Ctl {
// ...
}
// Exercise 5.
operation ThreeQuatersPiPhase (q : Qubit) : Unit is Adj+Ctl {
// ...
}
// Exercise 5.
operation PrepareRotatedState (alpha : Double, beta : Double, q : Qubit) : Unit is Adj+Ctl {
// ...
}
// Exercise 7.
operation PrepareArbitraryState (alpha : Double, beta : Double, theta : Double, q : Qubit) : Unit is Adj+Ctl {
// ...
}
}

Просмотреть файл

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
//////////////////////////////////////////////////////////////////////
// This file contains parts of the testing harness.
// You should not modify anything in this file.
// The tasks themselves can be found in Tasks.qs file.
//////////////////////////////////////////////////////////////////////
using System.Diagnostics;
using Microsoft.Quantum.Simulation.XUnit;
using Microsoft.Quantum.Simulation.Simulators;
using Xunit.Abstractions;
namespace Quantum.Kata.SingleQubitGates
{
public class TestSuiteRunner
{
private readonly ITestOutputHelper output;
public TestSuiteRunner(ITestOutputHelper output)
{
this.output = output;
}
/// <summary>
/// This driver will run all Q# tests (operations named "...Test")
/// that belong to namespace Quantum.Kata.SingleQubitGates.
/// </summary>
[OperationDriver(TestNamespace = "Quantum.Kata.SingleQubitGates")]
public void TestTarget(TestOperation op)
{
using (var sim = new QuantumSimulator())
{
// OnLog defines action(s) performed when Q# test calls function Message
sim.OnLog += (msg) => { output.WriteLine(msg); };
sim.OnLog += (msg) => { Debug.WriteLine(msg); };
op.TestOperationRunner(sim);
}
}
}
}

Просмотреть файл

@ -0,0 +1,91 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
//////////////////////////////////////////////////////////////////////
// This file contains testing harness for all tasks.
// You should not modify anything in this file.
//////////////////////////////////////////////////////////////////////
namespace Quantum.Kata.SingleQubitGates {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Convert;
// The tests are written to test controlled versions of operations instead of plain ones.
// This is done to verify that the tasks don't add a global phase to the implementations.
// Global phase is not relevant physically, but it can be very confusing for a beginner to consider R1 vs Rz,
// so the tests use controlled version of the operations which converts the global phase into a relative phase
// and makes it possible to detect.
// ------------------------------------------------------
// Helper wrapper to represent controlled variant of operation on one qubit
// as an operation on an array of two qubits
operation ControlledArrayWrapperOperation (op : (Qubit => Unit is Adj+Ctl), qs : Qubit[]) : Unit is Adj+Ctl {
Controlled op([qs[0]], qs[1]);
}
// ------------------------------------------------------
operation AssertEqualOnZeroState (testImpl : (Qubit => Unit is Ctl), refImpl : (Qubit => Unit is Adj+Ctl)) : Unit {
using (qs = Qubit[2]) {
within {
H(qs[0]);
}
apply {
// apply operation that needs to be tested
Controlled testImpl([qs[0]], qs[1]);
// apply adjoint reference operation
Adjoint Controlled refImpl([qs[0]], qs[1]);
}
// assert that all qubits end up in |0⟩ state
AssertAllZero(qs);
}
}
// Exercise 1.
operation T1_ApplyY_Test () : Unit {
AssertOperationsEqualReferenced(2, ControlledArrayWrapperOperation(ApplyY, _), ControlledArrayWrapperOperation(Y, _));
}
// Exercise 2.
operation T2_GlobalPhaseI_Test () : Unit {
AssertOperationsEqualReferenced(2, ControlledArrayWrapperOperation(GlobalPhaseI, _), ControlledArrayWrapperOperation(GlobalPhaseI_Reference, _));
}
// Exercise 3.
operation T3_SignFlipOnZero_Test () : Unit {
AssertOperationsEqualReferenced(2, ControlledArrayWrapperOperation(SignFlipOnZero, _), ControlledArrayWrapperOperation(SignFlipOnZero_Reference, _));
}
// Exercise 4.
operation T4_PrepareMinus_Test () : Unit {
AssertEqualOnZeroState(PrepareMinus, PrepareMinus_Reference);
}
// Exercise 5.
operation T5_ThreeQuatersPiPhase_Test () : Unit {
AssertOperationsEqualReferenced(2, ControlledArrayWrapperOperation(ThreeQuatersPiPhase, _), ControlledArrayWrapperOperation(ThreeQuatersPiPhase_Reference, _));
}
// Exercise 6.
operation T6_PrepareRotatedState_Test () : Unit {
for (i in 0 .. 10) {
AssertEqualOnZeroState(PrepareRotatedState(Cos(IntAsDouble(i)), Sin(IntAsDouble(i)), _),
PrepareRotatedState_Reference(Cos(IntAsDouble(i)), Sin(IntAsDouble(i)), _));
}
}
// Exercise 7.
operation T7_PrepareArbitraryState_Test () : Unit {
for (i in 0 .. 10) {
for (j in 0 .. 10) {
AssertEqualOnZeroState(PrepareArbitraryState(Cos(IntAsDouble(i)), Sin(IntAsDouble(i)), IntAsDouble(j), _),
PrepareArbitraryState_Reference(Cos(IntAsDouble(i)), Sin(IntAsDouble(i)), IntAsDouble(j), _));
}
}
}
}