Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quantum-kittens
GitHub Repository: quantum-kittens/platypus
Path: blob/main/notebooks/intro/entangled-states.ipynb
3855 views
Kernel: Python 3

Entangled states

Product and entangled states

In previous sections we've already seen how to express multi-qubit states as vectors. For example, here is the state vector for two qubits,

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{_ket-psi}{|\ps…

What we haven't looked at so far is the structure of these superpositions, and how that affects their behavior and what they can be used for. For example, consider the following two states.

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{_ket-plus-0}{|…

At a glance they may seem pretty similar. Both are an equally weighted superposition of two different bit strings. However, let's take a closer look.

In particular, let us look at the ∣+0⟩|{+}{0} \rangle state. This is made up of the two terms:

  • ∣00⟩|00\rangle: Both qubits are in the state ∣0⟩|0\rangle;

  • ∣10⟩|10\rangle: The qubit states are ∣1⟩|1\rangle (on the left) and ∣0⟩|0\rangle (on the right).

Both these terms tell the same story for the qubit on the right: It is in the ∣0⟩|0\rangle state. With this in mind, we see that all the superposition in this state belongs to the other qubit. Specifically, the qubit on the left can be described by the single qubit ParseError: KaTeX parse error: Undefined control sequence: \class at position 1: \̲c̲l̲a̲s̲s̲{ket-plus}{|+\r… state.

So the ∣+0⟩|{+}0\rangle state is a two qubit state vector that actually describes a pair of single qubit states: ParseError: KaTeX parse error: Undefined control sequence: \class at position 1: \̲c̲l̲a̲s̲s̲{ket-plus}{|+\r… and ∣0⟩|0\rangle.

image showing how two single qubit states become one two qubit state

Reminder

Qubit ordering In Qiskit code, qubits and bits are indexed from 0 and numbered from right to left. So for a four qubit state like ∣1000⟩|1000\rangle, the four qubits are numbered 0, 1, 2, and 3. It is qubit 3 that is in state ∣1⟩|1\rangle, while the rest are in state ∣0⟩|0\rangle. This is by design, so that the qubit's index is also the power of 2 it represents.

Quick quiz

Suppose you had two qubits, with qubit 0 in state ParseError: KaTeX parse error: Undefined control sequence: \class at position 1: \̲c̲l̲a̲s̲s̲{ket-plus}{|+\r…, qubit 1 in state ParseError: KaTeX parse error: Undefined control sequence: \class at position 1: \̲c̲l̲a̲s̲s̲{ket-minus}{|-\…. What two qubit state would represent this?

  1. ∣+−⟩|{+}{-}\rangle

  1. ∣−+⟩|{-}{+}\rangle

  1. ∣0⟩|0\rangle

Product states

The ∣+0⟩|{+}0 \rangle is an example of a kind of multi-qubit state known as a 'product state'. These represent cases that could alternatively be written as a sequence of single qubit states.

For a general form of two-qubit product states, we need to start with two general single qubit states,

ParseError: KaTeX parse error: Undefined control sequence: \class at position 1: \̲c̲l̲a̲s̲s̲{_ket-vague}{|a…

We'll use ∣ba⟩|b a\rangle to refer to product combined state of these, where ∣a⟩|a\rangle represents the qubit on the right and ∣b⟩|b\rangle is the one on the left. We can write this as:

∣b a⟩=[b0a0b0a1b1a0b1a1].|b \, a\rangle = \begin{bmatrix} b_0 a_0 \\ b_0 a_1 \\ b_1 a_0 \\ b_1 a_1 \end{bmatrix}.

Again, these rules follow from standard probability rules: If we want to find the probability of two unrelated events occurring, we multiply their probabilities together. To extend this rule to quantum mechanics, we just switch out probabilities with amplitudes. So the amplitude of the state ∣00⟩|00\rangle is the amplitude of qubit aa being ∣0⟩|0\rangle, multiplied by the amplitude of qubit bb being ∣0⟩|0\rangle.

Let's check this works: Suppose both qubits are measured, what is the probability that the qubit on the right comes out 0? This will be the sum of the probabilities for the two outcomes which have a 0 on the right, namely 00 and 10,

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{_pa0}{p_{|a\ra…

Now we can substitute in the calculations for these states given above and do simple algebra

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 45: …(|0\rangle) &= \̲c̲s̲s̲I̲d̲{_p00}{(b_0 a_0…

This gives us exactly what we would get with just the single qubit calculation. Using this method, you'd also find p∣b⟩(∣0⟩)=b02p_{|b\rangle}(|0\rangle) = b_0^2.

Entangled states

Now let's look again at the state ∣Φ+⟩|\Phi^+ \rangle,

∣Φ+⟩=12[1001]=12(∣00⟩+∣11⟩).|\Phi^+ \rangle = \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\ 0 \\ 0 \\ 1 \end{bmatrix} = \frac{1}{\sqrt{2}}(|00\rangle+|11\rangle).

There are no pairs of single qubit states ∣a⟩|a \rangle and ∣b⟩|b\rangle whose product state would look like this. Try it for yourself by trying to find b0b_0, b1b_1, c0c_0 and c1c_1 values that would correspond to ∣Φ+⟩|\Phi^{+} \rangle. You'll find that it's impossible!

This represents a different kind of two-qubit state, distinct from the product states, which cannot be described as combination of simple single qubit states. These are known as entangled states.

Quick quiz

Which of these product states does the following state correspond to?

12[1−1−11]\frac{1}{2} \begin{bmatrix} 1 \\ -1 \\ -1 \\ 1 \end{bmatrix}
  1. ∣+−⟩|{+}{-}\rangle

  1. ∣−−⟩|{-}{-}\rangle

  1. ∣−+⟩|{-}{+}\rangle

Quick quiz

Which of the following states is entangled?

  1. 12[1−1−11] \frac{1}{2} \begin{bmatrix} 1 \\\\ -1 \\\\ -1 \\\\ 1 \end{bmatrix}

  1. 12[1100] \frac{1}{\sqrt{2}} \begin{bmatrix} 1 \\\\ 1 \\\\ 0 \\\\ 0 \end{bmatrix}

  1. 12[0110] \frac{1}{\sqrt{2}} \begin{bmatrix} 0 \\\\ 1 \\\\ 1 \\\\ 0 \end{bmatrix}

Entangling gates

Quantum computations typically start in a product state. Specifically, they start in the simplest product state of all, where all qubits are in the state ∣0⟩|0\rangle.

If we then apply only single qubit gates, we will manipulate these individual single qubit states. Some might be rotated to ∣+⟩|+\rangle by a Hadamard, or a more complex superposition by a more general rotation. But nevertheless, they will remain in a product state.

To create entanglement, we need to apply multi-qubit gates. The most prominent of these are controlled gates, with the cx and cz gates being the simplest examples.

The cx gate

To see the cx in action, let's begin with the two qubit ∣00⟩|00\rangle state.

from qiskit import QuantumCircuit from qiskit.quantum_info import Statevector qc = QuantumCircuit(2) # This calculates what the state vector of our qubits would be # after passing through the circuit 'qc' ket = Statevector(qc) # The code below writes down the state vector. # Since it's the last line in the cell, the cell will display it as output ket.draw()
∣00⟩|00\rangle
# "... let's begin with the two qubit |00⟩ state." assert ket == Statevector.from_label('00')

(In the cell output above, the state vectors are drawn horizontally instead of vertically as we usually draw them, but they mean the same thing here).

The cx acts on two qubits, which are known as the 'control' and the 'target'. Let's first try using qubit 0 as control and qubit 1 as target and see what happens.

qc.cx(0,1) ket = Statevector(qc) ket.draw()
∣00⟩|00\rangle
# "The state remains |00⟩." assert ket == Statevector.from_label('00')

This cx had no effect. The state remains ∣00⟩|00\rangle.

Now let's try it with the control and target reversed.

qc.cx(1,0) ket = Statevector(qc) ket.draw()
∣00⟩|00\rangle
# "Again, no effect!" assert ket == Statevector.from_label('00')

Again, no effect!

This underwhelming performance from the cx is actually to be expected. We can interpret its action as being conditional on the state of the control qubit: if the control is in state ∣0⟩|0\rangle, the cx does nothing. If the control is in state ∣1⟩|1\rangle, the cx performs an x on the target qubit.

depiction of the effect of a CX gate

So if we want to see the cx do something, we need to flip the control qubit to the ∣1⟩|1\rangle state.

qc.x(1) ket = Statevector(qc) ket.draw()
∣10⟩|10\rangle
# "...we need to flip the control qubit to the |1⟩ state." #Leftmost qubit is control assert ket == Statevector.from_label('10')

Now when we perform a cx, it will flip the target qubit as well.

qc.cx(1,0) ket = Statevector(qc) ket.draw()
∣11⟩|11\rangle
# "...it will flip the target qubit as well." # Both qubits should be |1⟩ assert ket == Statevector.from_label('11')

So far, we have not yet seen any entanglement. That comes when the control qubit is not just a simple ∣0⟩|0\rangle or ∣1⟩|1\rangle, but a superposition of the two. For example, suppose we have the ∣+0⟩|{+}{0}\rangle state from before.

# Let's create a fresh quantum circuit qc = QuantumCircuit(2) qc.h(1) ket = Statevector(qc) ket.draw()
22∣00⟩+22∣10⟩\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |10\rangle
# "...suppose we have the |+0⟩ state from before." assert ket == Statevector.from_label('+0')

Now if we apply the cx, it will act in parallel on the two states. It will leave the ∣00⟩|00\rangle state unchanged, since the control qubit there is in state ∣0⟩|0\rangle. But ∣10⟩|10\rangle has the control in state ∣1⟩|1\rangle, so the target is flipped to make the ∣11⟩|11\rangle state.

qc.cx(1,0) ket = Statevector(qc) ket.draw()
22∣00⟩+22∣11⟩\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle

The result is our favorite entangled state: ∣Φ+⟩|\Phi^+ \rangle. The cx gate has created entanglement!

The cz gate

The cz is a gate whose effect is rather similar to the cx. It also acts on two qubits: the target and control. It also does nothing when the control qubit is in state ∣0⟩|0\rangle. But for the control state ∣1⟩|1\rangle, it performs a z to the target.

Or at least, that is the standard interpretation of this gate. But if we think about it a little more, we can see that another interpretation is also possible.

The z gate applied to a single qubit has the effect of doing nothing to ∣0⟩|0\rangle, and giving a phase of −1-1 to the state ∣1⟩|1\rangle. So for the cz gate, it only has any effect at all when both qubits are in state ∣1⟩|1\rangle. It doesn't matter which we decided to label 'control' and 'target', the effect is the same. We could equally have defined it as the gate which does nothing when the target state is ∣0⟩|0\rangle, and otherwise performs a z on the control.

The fact that the same gate can be interpreted in two seemingly contradictory ways is just one expression of the interesting effects that we will see with entangled states.

The cx gate revisited

The cx gate is also known as the controlled-X or controlled-NOT, due to its effect of flipping the target bit based on the state of the control. However, just as we saw with the cx gate, other interpretations are also possible.

For example, let's start with the case where both qubits are in the ∣+⟩|+ \rangle state.

qc = QuantumCircuit(2) qc.h(0) qc.h(1) ket = Statevector(qc) ket.draw()
12∣00⟩+12∣01⟩+12∣10⟩+12∣11⟩\frac{1}{2} |00\rangle+\frac{1}{2} |01\rangle+\frac{1}{2} |10\rangle+\frac{1}{2} |11\rangle
# "...both qubits are in the |+⟩ state." assert ket == Statevector.from_label('++')

Here we will also find that the cx has no effect, no matter which way around we do it.

qc.cx(1,0) ket = Statevector(qc) ket.draw()
12∣00⟩+12∣01⟩+12∣10⟩+12∣11⟩\frac{1}{2} |00\rangle+\frac{1}{2} |01\rangle+\frac{1}{2} |10\rangle+\frac{1}{2} |11\rangle
# "...the cx has no effect..." assert Out[14].data == Out[16].data

However, let's now flip the target qubit from ∣+⟩|+\rangle to ∣−⟩|-\rangle using the single qubit z gate.

qc.z(0) ket = Statevector(qc) ket.draw()
12∣00⟩−12∣01⟩+12∣10⟩−12∣11⟩\frac{1}{2} |00\rangle- \frac{1}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{1}{2} |11\rangle
# "...let's now flip the target qubit from |+⟩ to |−⟩..." # Rightmost is target assert ket == Statevector.from_label('+-')

If we do the cx now, we will see an effect. It flips the control qubit to ∣−⟩|-\rangle as well.

qc.cx(1,0) ket = Statevector(qc) ket.draw()
12∣00⟩−12∣01⟩−12∣10⟩+12∣11⟩\frac{1}{2} |00\rangle- \frac{1}{2} |01\rangle- \frac{1}{2} |10\rangle+\frac{1}{2} |11\rangle
# "It flips the control qubit to |−⟩ as well." assert ket == Statevector.from_label('--')

This effect is sometimes known as 'phase kickback': When there is a superposition on both the control and target qubits, some features of the target superposition can feed back into the control.

This effect can also motivate us to make an alternative interpretation of the cx. We can think of it as applying a z to the control if the target is in state ∣−⟩|-\rangle, and do nothing if it is in state ∣+⟩|+\rangle.

The power of entanglement

Entanglement is a key ingredient of many aspects of quantum computing. It powers the algorithms and methods that we use, and it is a necessary part of any quantum advantage. To get some idea of why this is, we'll take a few specific examples of entanglement in action.

Entangled states and simulation

To fully describe the state of nn qubits, we may need to keep track of up to 2n2^n amplitudes. Since these vectors grow exponentially with the number of qubits, quantum computers with large numbers of qubits become very difficult to simulate. A modern laptop can easily handle 2202^{20} amplitudes (the maximum needed for 20 qubits), but processing 21002^{100} amplitudes (the maximum needed for 100 qubits) is too difficult for even the largest supercomputers.

But sometimes there’s a smarter way. For example, suppose we begin in a product state. This means that each qubit can be independently described by a single qubit state with two amplitudes.

Now suppose we perform a circuit with only single qubit gates. These manipulations can be easily described by modifying the single qubit states, which means making changes to the specific pairs of amplitudes affected. Then, when each qubit is measured, the probability of the outcome 0 or 1 for each qubit are determined by their respective amplitudes.

During this process, the states remained product states. As such there was never truly an nn-qubit computation, but rather nn separate single qubit computations. This makes it possible to keep track of everything with a very manageable 2n2 n amplitudes, rather than the full 2n2^n. For such situations, simulating thousands of qubits would be easy even for your phone.

Useful quantum algorithms need to be able to do things that classical computers cannot simulate, so they must work in a way that prevents tricks like this from being found. They must involve more complex manipulations of the qubits, creating states for which there are no easy shortcuts. This means that they must use states for which the full 2n2^n amplitude description is needed, and so will need to involve more than just product states. And since anything that is not a product state is an entangled state, we find that entanglement is a necessary ingredient of any quantum advantage.

Qubits working together: Superdense coding

We'll now look at an example of entanglement in action using a protocol for quantum communication. Like quantum computation, this is based on manipulating qubits with quantum gates. But it also incorporates the idea of qubits being transmitted between different parties, and explores applications based on sending information rather than processing it.

For classical communication there is a fundamental limit on how much information we can send with a given number of bits. By definition, we can send no more than nn bits of information when we send nn bits. For quantum information, much the same rule applies: no more than nn bits of information can be reliably encoded and retrieved from nn qubits. However, there are ways that we can push the boundaries to do things that are not possible classically, and for that we require entanglement. Here we will look at one such example, in which transferring one qubit can allow a two bit message to be sent.

Suppose we have two people: Alice and Bob. Alice wishes to send a two bit message to Bob - 00, 01, 10 or 11 - and wants to do it by sending qubits.

The simplest way to do this is with two qubits. Alice can simply use the qubits to encode the bit values, applying an x to flip them for a 1 state.

# The message MESSAGE = '00' # Alice encodes the message qc_alice = QuantumCircuit(2, 2) if MESSAGE[-1]=='1': qc_alice.x(0) if MESSAGE[-2]=='1': qc_alice.x(1)

After Alice sends the qubits to Bob, all he needs to do is measure them.

from qiskit import Aer backend = Aer.get_backend('aer_simulator') # Bob measures qc_bob = QuantumCircuit(2,2) qc_bob.measure([0,1],[0,1]) backend.run(qc_alice.compose(qc_bob)).result().get_counts()
{'00': 1024}
# "The result Bob gets out will be exactly what Alice put in.." # Check only result is MESSAGE assert list(_.keys()) == [MESSAGE]

The result Bob gets out will be exactly what Alice put in.

This protocol did not involve any entanglement. One way to insert it would be for Alice to add h and cx gates after encoding the information. Let's look at the states that are created by these gates.

MESSAGE = '00' qc_alice = QuantumCircuit(2,2) # Alice encodes the message if MESSAGE[-1]=='1': qc_alice.x(0) if MESSAGE[-2]=='1': qc_alice.x(1) # then she creates entangled states qc_alice.h(1) qc_alice.cx(1,0) ket = Statevector(qc_alice) ket.draw()
22∣00⟩+22∣11⟩\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle
# "For a message 00, the state created by these gates is |Φ+⟩." from numpy import sqrt as _sqrt assert MESSAGE == '00' assert ket == Statevector([1/_sqrt(2), 0, 0, 1/_sqrt(2)])

For a message 00, the state created by these gates is ∣Φ+⟩|\Phi^+ \rangle. For the other messages we get other entangled states, know as ∣Φ−⟩|\Phi^- \rangle, ∣Ψ+⟩|\Psi^+ \rangle and ∣Ψ−⟩|\Psi^- \rangle.

00→∣Φ+⟩=12(∣00⟩+∣11⟩)01→∣Ψ+⟩=12(∣01⟩+∣10⟩)10→∣Φ−⟩=12(∣00⟩−∣11⟩)11→∣Ψ−⟩=12(∣01⟩−∣10⟩)\mathtt{00} \rightarrow |\Phi^+ \rangle = \frac{1}{\sqrt{2}}(|00\rangle+|11\rangle) \\ \mathtt{01} \rightarrow |\Psi^+ \rangle = \frac{1}{\sqrt{2}}(|01\rangle+|10\rangle) \\ \mathtt{10} \rightarrow |\Phi^- \rangle = \frac{1}{\sqrt{2}}(|00\rangle-|11\rangle) \\ \mathtt{11} \rightarrow |\Psi^- \rangle = \frac{1}{\sqrt{2}}(|01\rangle-|10\rangle)

When Bob receives these states he needs to disentangle them, by undoing the h and cx. Then he can measure and retrieve the message as before.

qc_bob = QuantumCircuit(2,2) # Bob disentangles qc_bob.cx(1,0) qc_bob.h(1) # Then measures qc_bob.measure([0,1],[0,1]) qc_bob.draw()
Image in a Jupyter notebook

So here we used entangled states, but they didn't give us any advantages. For that we need to look at the relationship between these four entangled states.

For example, the state ∣Φ+⟩|\Phi^+ \rangle is a superposition of ∣00⟩|00\rangle and ∣11⟩|11\rangle, whereas ∣Ψ+⟩|\Psi^+ \rangle is a superposition of ∣01⟩|01\rangle and ∣10⟩|10\rangle. So a simple x gate on either qubit is sufficient to rotate a ∣Φ+⟩|\Phi^+ \rangle into ∣Ψ+⟩|\Psi^+ \rangle and vice-versa. The same is true for rotating between ∣Φ−⟩|\Phi^- \rangle into ∣Ψ−⟩|\Psi^- \rangle. Similarly the difference between ∣Φ+⟩|\Phi^+ \rangle and ∣Φ−⟩|\Phi^- \rangle is simply the relative phase, which can be changed by a z on either qubit, and the same with ∣Ψ+⟩|\Psi^+ \rangle and ∣Ψ−⟩|\Psi^- \rangle. So Alice could send her message by creating an entangled state first, and then changing it using x and z gates to encode the correct message.

MESSAGE = '00' qc_alice = QuantumCircuit(2,2) qc_alice.h(1) qc_alice.cx(1,0) if MESSAGE[-2]=='1': qc_alice.z(1) if MESSAGE[-1]=='1': qc_alice.x(1) ket = Statevector(qc_alice) ket.draw()
22∣00⟩+22∣11⟩\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle

Since Bob is receiving the same states as before, he doesn't need to change his circuit at all.

backend.run(qc_alice.compose(qc_bob)).result().get_counts()
{'00': 1024}
# "...[Bob] doesn't need to change his circuit at all." # This implies Bob should still only measure MESSAGE assert list(_.keys()) == [MESSAGE]

The important thing to note here is that the x and z gates can be applied to just a single qubit (qubit 1 in this case). This means that Alice could send qubit 0 to Bob as soon as she has created the entangled pair. In fact, she could send it before she even knows what message she wants to send!

This gets even more surprising if you imagine a third party, whose job is just to create ∣Φ+⟩|\Phi^+ \rangle states and send the qubits out.

qc_charlie = QuantumCircuit(2,2) qc_charlie.h(1) qc_charlie.cx(1,0) qc_charlie.draw()
Image in a Jupyter notebook

This third party can directly send one qubit to Bob, and then the other to Alice. Alice can encode her two qubit message by manipulating just this single qubit, and send only this one qubit to Bob.

MESSAGE = '01' qc_alice = QuantumCircuit(2,2) if MESSAGE[-2]=='1': qc_alice.z(1) if MESSAGE[-1]=='1': qc_alice.x(1)

Now Bob can apply the same process as before and extract the message from his two qubits.

complete_qc = qc_charlie.compose(qc_alice.compose(qc_bob)) backend.run(complete_qc).result().get_counts()
{'01': 1024}
# "Now Bob can apply the same process as before and extract # the message from his two qubits." assert list(_.keys()) == [MESSAGE]

The end result of all this is that Alice sent two bits of information to Bob, and only had to send one qubit to do it. This was made possible by the fact that the qubit was part of an entangled pair. As such, while Alice was just applying gates to one qubit, she was manipulating the larger set of four possible states this entangled pair can be in.

This serves as a simple example of how qubits can allow us to do things that normal bits cannot, and how entanglement is a crucial resource for this.

Try it

Create a function that takes a QuantumCircuit and two-bit string as input, and applies the gates that encode the string onto the entangled state so Bob can decode it. Verify it works on all inputs.

Try in IBM Quantum Lab

Unique correlations: The Hardy paradox

A blue cube and a grey 3d-triangle thing

Some classical correlations

Now let's consider another situation with our friends Alice, Bob, and Charlie. First, we'll consider a completely classical case.

Suppose Charlie packages up a pair of colored shapes every day, sending one out to Alice and the other to Bob. Every day, Alice & Bob look at their shape and compare what they have received. For each shape they look at one of two properties: whether it was a cube or not, and whether it was blue or not.

After many days, and many choices of whether to look at the shape or color, they make two observations

  1. They are never both a cube.

  2. If one is not blue, the other will be a cube.

Clearly Charlie is not just sending out random shapes. There is some degree of correlation between the objects that Charlie chooses to send.

With these observations in mind, Alice and Bob imagine the case that they both look at the color, and they both find that their shape is not blue. Bob would then be able to apply observation 2 and infer that Alice's shape is certainly a cube. Alice could do the same and infer that Bob's shape is a cube. However, from observation 1 they know that this is impossible. So they conclude that one of their shapes will always be blue.

This is a rather artificial scenario, but it shows that there are limits on the kind of correlations possible with classical systems (like colored shapes). The color and shape of each object are both simultaneously well-defined. This means we can apply chains of logic such as those above, which use the results of one to deduce things about the other.

For qubits, however, the results of a measurement are not well-defined before the measurement is made. So can we find different kinds of behaviour?

Measuring a qubit

In the scenario above we looked at two different properties of a classical object: shape and color. For a quantum counterpart we'll need to do the same for qubits.

The only information we extract from a qubit is through measurement: We apply the measure operation and get back a 0 or a 1. The way that this is physically implemented in a quantum computer depends on the details of how your qubit is built. For some types of qubit, it's possible to rotate the measurement device to do different kinds of measurement, and see different behavior from the results.

For other kinds of qubit, rotating your measurement device will just break it. Nevertheless, there is a simple way to get the same effect: just rotate the qubit instead! By performing single qubit gates before making a standard measurement, we reproduce the effects of these alternative forms of measurement.

The most common example of this is to simply perform an h gate immediately before measurement. This gives us what is known as an x measurement.

meas_x = QuantumCircuit(1,1) meas_x.h(0) meas_x.measure(0,0) meas_x.draw()
Image in a Jupyter notebook

The standard form of measurement, which is done with just a measure gate, is known as a z measurement in this context.

meas_z = QuantumCircuit(1,1) meas_z.measure(0,0) meas_z.draw()
Image in a Jupyter notebook

As you might be able to guess from the names, there is also something called a y measurement, but we won't need to use that here.

Now let's look at what happens to certain states when we do these measurements. We'll start with the simple ∣0⟩|0\rangle state.

qc = QuantumCircuit(1,1) qc.draw()
Image in a Jupyter notebook

For the standard measurement, as we know, this is certain to output 0.

z_meas_counts = backend.run(qc.compose(meas_z)).result().get_counts() print('Results from z measurement:', z_meas_counts)
Results from z measurement: {'0': 1024}
# "...this is certain to output 0." assert list(z_meas_counts.keys()) == ['0']

For an x measurement, however, we'll get completely random results.

x_meas_counts = backend.run(qc.compose(meas_x)).result().get_counts() print('Results from x measurement:', x_meas_counts)
Results from x measurement: {'1': 524, '0': 500}
# "...we'll get completely random results." assert x_meas_counts['0'] > x_meas_counts['1']*0.9 assert x_meas_counts['0'] < x_meas_counts['1']*1.1

A similar situation occurs for the ∣1⟩|1\rangle state.

qc = QuantumCircuit(1,1) qc.x(0) qc.draw()
Image in a Jupyter notebook

The z measurement outputs the expected result with certainty, but the x measurement gives random results.

for basis,circ in [('z', meas_z), ('x', meas_x)]: print('Results from ' + basis + ' measurement:', backend.run(qc.compose(circ)).result().get_counts())
Results from z measurement: {'1': 1024} Results from x measurement: {'0': 522, '1': 502}

The tables are turned for the ∣+⟩|+\rangle state.

qc = QuantumCircuit(1,1) qc.h(0) qc.draw()
Image in a Jupyter notebook

Though the results are random for a z measurement, they produce 0 with certainty for an x measurement.

for basis,circ in [('z', meas_z), ('x', meas_x)]: print('Results from ' + basis + ' measurement:', backend.run(qc.compose(circ)).result().get_counts())
Results from z measurement: {'0': 528, '1': 496} Results from x measurement: {'0': 1024}

Quick quiz

What would be the results for a ∣−⟩|-\rangle state?

  1. Random for both z and x measurements.

  1. Random for a z measurement, 0 for an x measurement.

  1. Random for a z measurement, 1 for an x measurement.

  1. 0 for a z measurement, 1 for an x measurement.

For other states we can find a compromise between the two. For example, we can try out different angles for ry rotations.

from math import pi qc = QuantumCircuit(1, 1) qc.ry(-pi/4, 0) qc.draw()
Image in a Jupyter notebook

For the angle −π/4-\pi/4, we see both results are partly random, but not completely.

for basis,circ in [('z', meas_z), ('x', meas_x)]: print('Results from ' + basis + ' measurement:', backend.run(qc.compose(circ)).result().get_counts())
Results from z measurement: {'1': 153, '0': 871} Results from x measurement: {'0': 161, '1': 863}

The uncertainty principle

All these results are the consequence of the uncertainty principle discovered by Werner Heisenberg, which is one of the most important aspects of quantum mechanics. It states that for certain pairs of attributes of a quantum system, it is impossible to know both with certainty.

This is not true of the color and shape of an object, as in our example before. As we know from everyday experience, knowing exactly what shape something is does not cause its color to become random.

It is true, however, for the outcomes of z and x measurements. These are two different ways that we could choose to encode a bit of information in a qubit. We can do it the normal way, using the ∣0⟩|0\rangle and ∣1⟩|1\rangle states to encode the bit values 0 and 1 and using the z measurement to read it out. Or we could do it an alternative way, using the ∣+⟩|+\rangle and ∣−⟩|-\rangle states to encode the bit values and the x measurement for read out. But the uncertainty principle makes sure that we can't do both at once.

Specifically, for the z measurements we can define a quantity

ParseError: KaTeX parse error: Undefined control sequence: \class at position 1: \̲c̲l̲a̲s̲s̲{expectation-va…

where pz(0)p_z(0) is the probability of the outcome 0, and pz(1)p_z(1) is the probability of 1. This quantity reaches its maximum value of 11 for a state that is certain to output 0, and its minimum value of −1-1 for a state certain to output 1. Note that in both of these cases where the output is certain, ⟨Z⟩2=1\langle Z \rangle^2 = 1. For a completely random result, however, we would find ⟨Z⟩=⟨Z⟩2=0\langle Z \rangle = \langle Z \rangle^2 = 0.

We can similarly define the quantity ParseError: KaTeX parse error: Undefined control sequence: \class at position 1: \̲c̲l̲a̲s̲s̲{_expectation-v… for the outcomes of x measurements. For these we can find that, for any valid state vector

⟨Z⟩2+⟨X⟩2≤1.\langle Z \rangle^2 + \langle X \rangle^2 \leq 1.

This is the uncertainty principle for a qubit, specifically how much certainty can be shared between these kinds of measurement.

Unique quantum correlations

With the notions of these different measurement bases, we can start to look at unique correlations that are possible for qubits.

For example, let's again consider our friends Alice, Bob, and Charlie. Charlie creates a particular entangled state and sends one qubit to Alice and the other to Bob. They make measurements and compare the results. Then Charlie sends another, identically prepared state. This repeats many times, so Alice and Bob can build up statistics on all the different measurement results.

Let's consider the case where Charlie sends out the following entangled state.

qc_charlie = QuantumCircuit(2,2) qc_charlie.ry(1.911,1) qc_charlie.cx(1,0) qc_charlie.ry(0.785,0) qc_charlie.cx(1,0) qc_charlie.ry(2.356,0) qc_charlie.draw()
Image in a Jupyter notebook

First Alice and Bob try making z measurements of their qubits.

meas_zz = QuantumCircuit(2,2) meas_zz.measure([0,1],[0,1])
<qiskit.circuit.instructionset.InstructionSet at 0x1367007c0>

From many samples, they find the following results.

from qiskit.visualization import plot_histogram print('Results for z measurements:') counts = backend.run(qc_charlie.compose(meas_zz)).result().get_counts() plot_histogram(counts)
Results for z measurements:
Image in a Jupyter notebook
# "...the qubits never both output 0..." assert '00' not in counts.keys()

From this they make the observation that the qubits never both output 0 for z measurements.

Next, let's see the results of an when Bob performs an x measurement and Alice performs a z measurement.

meas_zx = QuantumCircuit(2,2) meas_zx.h(0) meas_zx.measure([0,1],[0,1]) print('Results for a z and an x measurement:') counts = backend.run(qc_charlie.compose(meas_zx)).result().get_counts() plot_histogram(counts)
Results for a z and an x measurement:
Image in a Jupyter notebook
# "...the qubits never both output 1..." assert '11' not in counts.keys()

In this case we find that the qubits never both output 1. The same is true when Bob makes the z measurement and Alice does the x.

meas_xz = QuantumCircuit(2,2) meas_xz.h(1) meas_xz.measure([0,1],[0,1]) print('Results for an x and a z measurement:') counts = backend.run(qc_charlie.compose(meas_xz)).result().get_counts() plot_histogram(counts)
Results for an x and a z measurement:
Image in a Jupyter notebook
# "...the qubits never both output 1. The same is true when..." assert '11' not in counts.keys()

With this information, Alice and Bob can begin to speculate about what would happen if they both performed an x measurement.

They can summarize their results so far in the following two observations:

  1. If z measurements are made on both qubits, they never both output 0;

  2. If an x measurement of one qubit outputs 1, a z measurement of the other will output 0 (because the 11 result never occurs in these cases).

These correspond exactly to the observations made for the colored shapes in the classical scenario. If we apply the same logic as we did in that case, we can analyse the case where both Alice and Bob make an x measurement, and they both get the result 1. Bob would then be able to apply observation 2 and infer that Alice would certainly have gotten a 0 if she had instead done a z measurement. Alice can do the same, inferring that Bob would have gotten a 1 if he'd have made a z measurement. So together they conclude that, if they had both made z measurements, they would both have gotten the output 0. Since observation 1 shows us that such a result would be impossible, Alice and Bob could predict that the 11 result will never occur.

So let's see if they would be right.

meas_xx = QuantumCircuit(2,2) meas_xx.h([0,1]) meas_xx.measure([0,1],[0,1]) print('Results for an x and an x measurement:') counts = backend.run(qc_charlie.compose(meas_xx)).result().get_counts() plot_histogram(counts)
Results for an x and an x measurement:
Image in a Jupyter notebook
# "The 11 result is not likely, but it is certainly not impossible." assert '11' in counts.keys()

They would not! The 11 result is not likely, but it is certainly not impossible.

The results of qubits are not well-defined before measurement. Though this might seem like it means that qubits are more random that classical variables, it is not always a negative quality. It also means that restrictions applied to classical variables do not always apply to qubits, and that quantum correlations can have properties that would be impossible classically. These unique correlations are one of the signature properties of entangled states.

# pylint: disable=unused-import import qiskit.tools.jupyter %qiskit_version_table