This tutorial introduces you to multi-qubit systems - their representation in mathematical notation and in Q# code, and the concept of entanglement.
If you are not familiar with the single-qubit systems, we recommend that you complete that tutorial first.
This tutorial covers the following topics:
In the previous tutorial we discussed the concept of a qubit - the basic building block of a quantum computer. A multi-qubit system is a collection of multiple qubits, treated as a single system.
Let's start by examining a system of two classical bits. Each bit can be in two states: $0$ and $1$. Therefore, a system of two bits can be in four different states: $00$, $01$, $10$, and $11$. Generally, a system of $N$ classical bits can be in any of the $2^N$ states.
A system of $N$ qubits can also be in any of the $2^N$ classical states, but, unlike the classical bits, it can also be in a superposition of all these states.
Similarly to single-qubit systems, a state of an $N$-qubit system can be represented as a complex vector of size $2^N$: $$\begin{bmatrix} x_0 \\ x_1 \\ \vdots \\ x_{2^N-1}\end{bmatrix}$$
Similarly to single-qubit systems, multi-qubit systems have their own sets of basis states. The computational basis for an $N$-qubit system is a set of $2^N$ vectors, in each of which with one element equals $1$, and the other elements equal $0$.
For example, this is the computational basis for a two-qubit system:
$$\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}\text{, } \begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \end{bmatrix}\text{, } \begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix}\text{, } \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix}$$It is easy to see that these vectors form an orthonormal basis. Note that each of these basis states can be represented as a tensor product of some combination of single-qubit basis states:
$\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix}$ | $\begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \end{bmatrix} = \begin{bmatrix} 1 \\ 0 \end{bmatrix} \otimes \begin{bmatrix} 0 \\ 1 \end{bmatrix}$ | $\begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix}$ | $\begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 0 \\ 1 \end{bmatrix} \otimes \begin{bmatrix} 0 \\ 1 \end{bmatrix}$ |
Any two-qubit system can be expressed as some linear combination of those tensor products of single-qubit basis states.
Similar logic applies to systems of more than two qubits. In general case,
$$\begin{bmatrix} x_0 \\ x_1 \\ \vdots \\ x_{2^N-1} \end{bmatrix} = x_0 \begin{bmatrix} 1 \\ 0 \\ \vdots \\ 0 \end{bmatrix} + x_1 \begin{bmatrix} 0 \\ 1 \\ \vdots \\ 0 \end{bmatrix} + \dotsb + x_{2^N-1} \begin{bmatrix} 0 \\ 0 \\ \vdots \\ 1 \end{bmatrix}$$The coefficients of the basis vectors define how "close" is the system state to the corresponding basis vector.
Just like with single-qubit systems, there exist other orthonormal bases states for multi-qubit systems. An example for a two-qubit system is the Bell basis:
$$\frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\ 0 \\ 0 \\ 1 \end{bmatrix}\text{, }
\frac{1}{\sqrt{2}}\begin{bmatrix} 1 \\ 0 \\ 0 \\ -1 \end{bmatrix}\text{, } \frac{1}{\sqrt{2}}\begin{bmatrix} 0 \\ 1 \\ 1 \\ 0 \end{bmatrix}\text{, } \frac{1}{\sqrt{2}}\begin{bmatrix} 0 \\ 1 \\ -1 \\ 0 \end{bmatrix}$$
You can check that these vectors are normalized, and orthogonal to each other, and that any two-qubit state can be expressed as a linear combination of these vectors. The vectors of Bell basis, however, can not be represented as tensor products of single-qubit basis states.
Sometimes the state of a multi-qubit system can be separated into the states of individual qubits or smaller subsystems. To do this, you would express the vector state of the system as a tensor product of the vectors representing each individual qubit/subsystem. Here is an example for two qubits:
$$\begin{bmatrix} \frac{1}{\sqrt{2}} \\ 0 \\ \frac{1}{\sqrt{2}} \\ 0 \end{bmatrix} = \begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix} \otimes \begin{bmatrix} 1 \\ 0 \end{bmatrix}$$The states that allow such representation are known as separable states.
Can't come up with a solution? See the explained solution in the Multi-Qubit Systems Workbook.
Note that finding such representation is not always possible, as you will see in the next exercise.
Can't come up with a solution? See the explained solution in the Multi-Qubit Systems Workbook.
As we've just seen, some quantum states are impossible to factor into individual qubit states or even into states of larger subsystems. The states of these qubits are inseparable from one another and must always be considered as part of a larger system - they are entangled.
For example, every state in the Bell basis we saw earlier is an entangled state.
Entanglement is a huge part of what makes quantum computing so powerful. It allows us to link the qubits so that they stop behaving like individuals and start behaving like a large, more complex system. In entangled systems, measuring one of the qubits modifies the state of the other qubits, and tells us something about their state. In the example above, when one of the qubits is measured, we know that the second qubit will end up in the same state. This property is used extensively in many quantum algorithms.
Just like with single qubits, Dirac notation provides a useful shorthand for writing down states of multi-qubit systems.
As we've seen earlier, multi-qubit systems have their own canonical bases, and the basis states can be represented as tensor products of single-qubit basis states. Any multi-qubit system can be represented as a linear combination of these basis states:
$$\begin{bmatrix} x_0 \\ x_1 \\ x_2 \\ x_3 \end{bmatrix} = x_0\begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix} + x_1\begin{bmatrix} 0 \\ 1 \\ 0 \\ 0 \end{bmatrix} + x_2\begin{bmatrix} 0 \\ 0 \\ 1 \\ 0 \end{bmatrix} + x_3\begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix} = x_0|0\rangle \otimes |0\rangle + x_1|0\rangle \otimes |1\rangle + x_2|1\rangle \otimes |0\rangle + x_3|1\rangle \otimes |1\rangle$$To simplify this, tensor products of basis states have their own notation:
$$|0\rangle \otimes |0\rangle = |00\rangle$$$$|0\rangle \otimes |1\rangle = |01\rangle$$$$|1\rangle \otimes |0\rangle = |10\rangle$$$$|1\rangle \otimes |1\rangle = |11\rangle$$$$|0\rangle \otimes |0\rangle \otimes |0\rangle = |000\rangle$$And so on.
Or, more generally:
$$|i_0\rangle \otimes |i_1\rangle \otimes \dotsb \otimes |i_n\rangle = |i_0i_1...i_n\rangle$$Using this notation simplifies our example:
$$\begin{bmatrix} x_0 \\ x_1 \\ x_2 \\ x_3 \end{bmatrix} = x_0|00\rangle + x_1|01\rangle + x_2|10\rangle + x_3|11\rangle$$Just like with single qubits, we can put arbitrary symbols within the kets the same way variables are used in algebra. Whether a ket represents a single qubit or an entire system depends on the context. Some ket symbols have a commonly accepted usage, such as the symbols for the Bell basis:
$|\Phi^+\rangle = \frac{1}{\sqrt{2}}\big(|00\rangle + |11\rangle\big) \\ |\Phi^-\rangle = \frac{1}{\sqrt{2}}\big(|00\rangle - |11\rangle\big)$ | $|\Psi^+\rangle = \frac{1}{\sqrt{2}}\big(|01\rangle + |10\rangle\big) \\ |\Psi^-\rangle = \frac{1}{\sqrt{2}}\big(|01\rangle - |10\rangle\big)$ |
Endianness¶
In classical computing, endianness refers to the order of bits (or bytes) when representing numbers in binary. You're probably familiar with the typical way of writing numbers in binary: $0 = 0_2$, $1 = 1_2$, $2 = 10_2$, $3 = 11_2$, $4 = 100_2$, $5 = 101_2$, $6 = 110_2$, etc. This is known as big-endian format. In big-endian format, the most significant bits come first. For example: $110_2 = 1 \cdot 4 + 1 \cdot 2 + 0 \cdot 1 = 4 + 2 = 6$.
There is an alternate way of writing binary numbers - little-endian format. In little-endian format, the least significant bits come first. For example, $2$ would be written as $01$, $4$ as $001$, and $6$ as $011$. To put it another way, in little endian format, the number is written backwards compared to the big-endian format.
In Dirac notation for multi-qubit systems, it's common to see integer numbers within the kets instead of bit sequences. What those numbers mean depends on the context - whether the notation used is big-endian or little-endian.
Examples with a 3 qubit system:
Integer Ket $|0\rangle$ $|1\rangle$ $|2\rangle$ $|3\rangle$ $|4\rangle$ $|5\rangle$ $|6\rangle$ $|7\rangle$ Big-endian $|000\rangle$ $|001\rangle$ $|010\rangle$ $|011\rangle$ $|100\rangle$ $|101\rangle$ $|110\rangle$ $|111\rangle$ Little-endian $|000\rangle$ $|100\rangle$ $|010\rangle$ $|110\rangle$ $|001\rangle$ $|101\rangle$ $|011\rangle$ $|111\rangle$ Multi-qubit quantum systems that store superpositions of numbers are often referred to as quantum registers.
This demo shows you how to allocate multiple qubits in Q# and examine their joint state. It uses single-qubit gates for manipulating the individual qubit states - if you need a refresher on them, please see the corresponding tutorial.
These demos use the function DumpMachine
to print the state of the quantum simulator.
If you aren't familiar with the output of this function for single qubits, you should revisit the tutorial on the concept of a qubit.
When printing the state of multi-qubit systems, this function outputs the same information for each multi-qubit basis state.
This tutorial explains how DumpMachine
works for multiple qubits in more detail.
// Run this cell using Ctrl+Enter (⌘+Enter on Mac)
// Then run the next cell to see the output
open Microsoft.Quantum.Diagnostics;
operation MultiQubitSystemsDemo () : Unit {
// This allocates an array of 2 qubits, each of them in state |0⟩.
// The overall state of the system is |00⟩
use qs = Qubit[2];
// X gate changes the first qubit into state |1⟩
// The entire system is now in state |10⟩
X(qs[0]);
Message("System in state |10⟩:");
DumpMachine();
// This changes the second qubit into state |+⟩ = (1/sqrt(2))(|0⟩ + |1⟩).
// The entire system is now in state (1/sqrt(2))(|10⟩ + |11⟩)
H(qs[1]);
Message("System in state (1/sqrt(2))(|10⟩ + |11⟩):");
DumpMachine();
// This changes the first qubit into state |-⟩ = (1/sqrt(2))(|0⟩ - |1⟩)
// The entire system is now in state 0.5(|00⟩ + |01⟩ - |10⟩ - |11⟩)
H(qs[0]);
Message("System in state 0.5(|00⟩ + |01⟩ - |10⟩ - |11⟩):");
DumpMachine();
// You can use DumpRegister to examine the state of specific qubits rather than the entire simulator.
// This prints the state of the first qubit
Message("First qubit (in state |-⟩ = (1/sqrt(2))(|0⟩ - |1⟩):");
DumpRegister((), [qs[0]]);
// The next lines entangle the qubits.
// Don't worry about what exactly they do for now
H(qs[1]);
CNOT(qs[0], qs[1]);
Message("Entangled state (1/sqrt(2))(|00⟩ - |11⟩):");
DumpMachine();
// Since the states of entangled qubits are inseparable,
// it makes no sense to examine only one of them
Message("Let's try to examine one of two entangled qubits on its own...");
DumpRegister((), [qs[0]]);
// This returns the system into state |00⟩
ResetAll(qs);
}
%simulate MultiQubitSystemsDemo
You might have noticed that we've been "resetting" the qubits at the end of our demos, i.e., returning them to $|0\rangle$ state. Q# requires you to return your qubits into the $|0\rangle$ state before releasing them at the end of the
use
block. The reason for this is entanglement.Consider running a program on a quantum computer: the number of qubits is very limited, and you want to reuse the released qubits in other parts of the program.
If they are not in zero state by that time, they can potentially be still entangled with the qubits which are not yet released, thus operations you perform on them can affect the state of other parts of the program, causing erroneous and hard to debug behavior.
Resetting the qubits to zero state automatically when they go outside the scope of their
use
block is dangerous as well: if they were entangled with others, measuring them to reset them can affect the state of the unreleased qubits, and thus change the results of the program - without the developer noticing this.The requirement that the qubits should be in zero state before they can be released aims to remind the developer to double-check that all necessary information has been properly extracted from the qubits, and that they are not entangled with unreleased qubits any more.
(An alternative way to break entanglement is to measure qubits; in this case Q# allows to release them regardless of the measurement result. You can learn more about measurements in this tutorial.)
In the following exercises you will learn to prepare separable quantum states by manipulating individual qubits. You will only need single-qubit gates for that.
In each exercise, you'll be given an array of qubits to manipulate; you can access $i$-th element of the array
qs
asqs[i]
.
Array elements are indexed starting with 0, the first array element corresponds to the leftmost qubit in Dirac notation.
Input: A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}$.
Goal: Transform the system into the basis state $|11\rangle = \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \end{bmatrix}$.
%kata T1_PrepareState1
operation PrepareState1 (qs : Qubit[]) : Unit is Adj+Ctl {
// ...
}
Can't come up with a solution? See the explained solution in the Multi-Qubit Systems Workbook.
Input: A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}$.
Goal: Transform the system into the state $\frac{1}{\sqrt2}\big(|00\rangle - |01\rangle\big) = \frac{1}{\sqrt2}\begin{bmatrix} 1 \\ -1 \\ 0 \\ 0 \end{bmatrix}$.
%kata T2_PrepareState2
operation PrepareState2 (qs : Qubit[]) : Unit is Adj+Ctl {
// ...
}
Can't come up with a solution? See the explained solution in the Multi-Qubit Systems Workbook.
Input: A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}$.
Goal: Transform the system into the state $\frac{1}{2}\big(|00\rangle - |01\rangle + |10\rangle - |11\rangle\big) = \frac{1}{2}\begin{bmatrix} 1 \\ -1 \\ 1 \\ -1 \end{bmatrix}$.
%kata T3_PrepareState3
operation PrepareState3 (qs : Qubit[]) : Unit is Adj+Ctl {
// ...
}
Can't come up with a solution? See the explained solution in the Multi-Qubit Systems Workbook.
Input: A two-qubit system in the basis state $|00\rangle = \begin{bmatrix} 1 \\ 0 \\ 0 \\ 0 \end{bmatrix}$.
Goal: Transform the system into the state $\frac{1}{2}\big(|00\rangle + e^{i\pi/4}|01\rangle + e^{i\pi/2}|10\rangle + e^{3i\pi/4}|11\rangle\big) = \frac{1}{2}\begin{bmatrix} 1 \\ e^{i\pi/4} \\ e^{i\pi/2} \\ e^{3i\pi/4} \end{bmatrix}$.
%kata T4_PrepareState4
operation PrepareState4 (qs : Qubit[]) : Unit is Adj+Ctl {
// ...
}
Can't come up with a solution? See the explained solution in the Multi-Qubit Systems Workbook.
As you've seen in the exercises, you can prepare separable multi-qubit states using only single-qubit gates. However, to prepare and manipulate entangled states you'll need more powerful tools. In the next tutorial you will learn about multi-qubit gates which give you access to all states of multi-qubit systems.