{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Multi-Qubit Gates\n",
"\n",
"This tutorial continues the introduction to quantum gates started in [this tutorial](../SingleQubitGates/SingleQubitGates.ipynb), focusing on applying quantum gates to multi-qubit systems. \n",
"\n",
"If you need a refresher on the representation of multi-qubit systems, we recommend you to review the [relevant tutorial](../MultiQubitSystems/MultiQubitSystems.ipynb).\n",
"\n",
"This tutorial covers the following topics:\n",
"\n",
"- Applying quantum gates to a part of the system\n",
"- $\\text{CNOT}$ and $\\text{SWAP}$ gates\n",
"- Controlled gates"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Basics\n",
"\n",
"As a reminder, single-qubit gates are represented by $2\\times2$ [unitary matrices](../LinearAlgebra/LinearAlgebra.ipynb#Unitary-Matrices). \n",
"The effect of a gate applied to a qubit can be calculated by multiplying the corresponding matrix by the state vector of the qubit to get the resulting state vector. \n",
"\n",
"Multi-qubit gates are represented by $2^N\\times2^N$ matrices, where $N$ is the number of qubits the gate operates on. To apply this gate, you multiply the matrix by the state vector of the $N$-qubit quantum system.\n",
"\n",
"> In Q# you can use the `DumpOperation` command to see the matrix that an operation implements. You can find more info and a demo in [this tutorial](../VisualizationTools/VisualizationTools.ipynb#Display-the-matrix-implemented-by-the-operation)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Applying Gates to a Part of the System\n",
"\n",
"The simplest thing we can do with multi-qubit systems is to apply gates to only a subset of qubits in the system. \n",
"Similar to how it is sometimes possible to represent the state of a multi-qubit systems as a tensor product of single-qubit states, \n",
"you can construct gates that modify the state of a multi-qubit system as tensor products of gates that affect parts of the system. \n",
"\n",
"Let's consider an example of applying single-qubit gates to one of the qubits of a two-qubit system.\n",
"If you want to apply an $X$ gate to the first qubit of the system and do nothing to the second qubit,\n",
"the resulting gate will be represented as a tensor product of an $X$ gate and the identity gate $I$ which corresponds to doing nothing:\n",
"\n",
"$$X \\otimes I =\n",
"\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix} \\otimes \\begin{bmatrix} 1 & 0 \\\\ 0 & 1 \\end{bmatrix} =\n",
"\\begin{bmatrix}\n",
" 0 & 0 & 1 & 0 \\\\\n",
" 0 & 0 & 0 & 1 \\\\\n",
" 1 & 0 & 0 & 0 \\\\\n",
" 0 & 1 & 0 & 0\n",
"\\end{bmatrix}$$\n",
"\n",
"You can use the same approach when applying several gates to independent parts of the system at the same time.\n",
"For example, applying the $X$ gate to the first qubit and the $H$ gate to the second qubit would be represented as follows:\n",
"\n",
"$$X \\otimes H =\n",
"\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix} \\otimes \\frac{1}{\\sqrt{2}}\\begin{bmatrix} 1 & 1 \\\\ 1 & -1 \\end{bmatrix} =\n",
"\\frac{1}{\\sqrt{2}}\\begin{bmatrix}\n",
" 0 & 0 & 1 & 1 \\\\\n",
" 0 & 0 & 1 & -1 \\\\\n",
" 1 & 1 & 0 & 0 \\\\\n",
" 1 & -1 & 0 & 0\n",
"\\end{bmatrix}$$\n",
"\n",
"> Note that we can use [mixed-multiplication property of tensor product](../LinearAlgebra/LinearAlgebra.ipynb#Tensor-Product) to see that this is equivalent to applying $X$ gate to the first qubit and applying $H$ gate to the second qubit, in either order:\n",
">\n",
"> $$X \\otimes H = (I X) \\otimes (H I) = (I \\otimes H) (X \\otimes I)$$\n",
"> $$X \\otimes H = (X I) \\otimes (I H) = (X \\otimes I) (I \\otimes H)$$\n",
"\n",
"This approach can be generalized to larger systems and gates that act on multiple qubits as well. \n",
"It can be less straightforward if a multi-qubit gate is applied to a subset of qubits that are not \"adjacent\" to each other in the tensor product; we'll see an example later in this tutorial."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercise 1: Compound Gate\n",
"\n",
"**Inputs:** $3$ qubits in an arbitrary superposition state $|\\psi\\rangle$, stored in an array of length 3.\n",
"\n",
"**Goal:** Apply the following matrix to the system. This matrix can be represented as applying $3$ single-qubit gates.\n",
"\n",
"$$Q = \\begin{bmatrix}\n",
" 0 & -i & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n",
" i & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n",
" 0 & 0 & 0 & -i & 0 & 0 & 0 & 0 \\\\\n",
" 0 & 0 & i & 0 & 0 & 0 & 0 & 0 \\\\\n",
" 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n",
" 0 & 0 & 0 & 0 & -1 & 0 & 0 & 0 \\\\\n",
" 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\\\n",
" 0 & 0 & 0 & 0 & 0 & 0 & -1 & 0\n",
"\\end{bmatrix}$$\n",
"\n",
"> We recommend to keep a list of common quantum gates on hand, such as [this tutorial](../SingleQubitGates/SingleQubitGates.ipynb).\n",
"\n",
"Need a hint? Click here
\n",
"Start by noticing that the top right and bottom left quadrants of the matrix are filled with $0$s, and the bottom right quadrant equals to the top left one, multiplied by $i$. Does this look like a tensor product of a 1-qubit and 2-qubit matrices? Which ones?\n",
"
Gate | \n", "Matrix | \n", "Applying to $|\\psi\\rangle = \\alpha|00\\rangle + \\beta|01\\rangle + \\gamma|10\\rangle + \\delta|11\\rangle$ | \n", "Applying to basis states | \n", "Q# Documentation | \n", "
---|---|---|---|---|
$\\text{CNOT}$ | \n", "$\\begin{bmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\end{bmatrix}$ | \n", "$\\text{CNOT}|\\psi\\rangle = \\alpha|00\\rangle + \\beta|01\\rangle + {\\color{red}\\delta}|10\\rangle + {\\color{red}\\gamma}|11\\rangle$ | \n", "$\\text{CNOT}|00\\rangle = |00\\rangle$ \n", " $\\text{CNOT}|01\\rangle = |01\\rangle$ \n", " $\\text{CNOT}|10\\rangle = |11\\rangle$ \n", " $\\text{CNOT}|11\\rangle = |10\\rangle$ | \n",
" CNOT | \n", "
Gate | \n", "Matrix | \n", "Applying to $|\\psi\\rangle = \\alpha|00\\rangle + \\beta|01\\rangle + \\gamma|10\\rangle + \\delta|11\\rangle$ | \n", "Applying to basis states | \n", "Q# Documentation | \n", "
---|---|---|---|---|
$\\text{SWAP}$ | \n", "$\\begin{bmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\end{bmatrix}$ | \n", "$\\text{SWAP}|\\psi\\rangle = \\alpha|00\\rangle + {\\color{red}\\gamma}|01\\rangle + {\\color{red}\\beta}|10\\rangle + \\delta|11\\rangle$ | \n", "$\\text{SWAP}|00\\rangle = |00\\rangle$ \n", " $\\text{SWAP}|01\\rangle = |10\\rangle$ \n", " $\\text{SWAP}|10\\rangle = |01\\rangle$ \n", " $\\text{SWAP}|11\\rangle = |11\\rangle$ | \n",
" SWAP | \n", "
Gate | \n", "Matrix | \n", "Q# Documentation | \n", "
---|---|---|
$\\text{Controlled U}$ | \n", "$\\begin{bmatrix}\n", " 1 & 0 & 0 & 0 \\\\\n", " 0 & 1 & 0 & 0 \\\\\n", " 0 & 0 & \\alpha & \\beta \\\\\n", " 0 & 0 & \\gamma & \\delta\n", " \\end{bmatrix}$ | \n", "Controlled functor | \n", "
Input state | \n", "Output state | \n", "
---|---|
$|00\\rangle$ | \n", "$|01\\rangle$ | \n", "
$|01\\rangle$ | \n", "$|00\\rangle$ | \n", "
$|10\\rangle$ | \n", "$|10\\rangle$ | \n", "
$|11\\rangle$ | \n", "$|11\\rangle$ | \n", "