This subsection provides an algorithm for simulating quantum measurement in Python. First, we consider the steps needed to simulate quantum measurement on a classic computer. These are as follows:
- To implement an algorithm for quantum measurement, we will also choose a basis. In this example, I chose the |"0"> and |"1"> basis.
- Next, we need to figure out how many qubits the state represents. For a state of n qubits, we need 2n numbers to represent it. Essentially, each of these numbers helps codify the probability of each of the 2n possibilities of an n qubit state. So, given a state, we can compute how many numbers it contains then take the logarithm, base 2, to recover n, the number of qubits the state represents.
- To compute the probability of each of the 2n possibilities of an n qubit state, we will take the number that represents it in the state and square it to get the probability. Because the number is complex, we multiply the number by its complex conjugate to get the value of the number squared.
- We simulate the randomness of the outcome by picking a random number.
- For n qubits, there are 2n different possible measurements, one for each possible binary value. For example, for 3 qubits, there are 23=8 possibilities for a measurement: 000, 001, 010, 011, 111, 101, 110, 100. We go through each of these 2n possibilities.
- The sum of the probabilities of all states will add to one. To find the state "measured" in our simulation, we check each state in order. If the first state for which the random number chosen is less than the sum of the probabilities of the states we have checked so far, we return a string representing that state.
The following algorithm implements what we have described:
from math import log
from random import random
import itertools
def measure_in_01_basis(state): #1.
n_qubits=int(log(state.shape[0],2)) # 2.
probabilities=[(coeff*coeff.conjugate())
.real for coeff in state.flat] # 3.
rand=random() #4.
for idx,state_desc in enumerate([''.join(map(str,state_desc))
for state_desc in itertools.product(
[0, 1], repeat=n_qubits)]): #5.
if rand < sum(probabilities[0:(idx+1)]): # 6.
return '|"%s">' % state_desc #7.
Now, let's try it out on a few states. measure_in_01_basis(create_quantum_state([one_qubit,zero_qubit,zero_qubit,one_qubit,one_qubit])) will always return the string |"10011">, as we have constructed a state of basis states where the probability of each qubit returning that basis state is 100%.
Measurement gets more interesting when we deal with multiple qubits that are entangled. Let's try the measurement out on the following state, which we'll call bell_state_phi_plus:
![](assets/133ab023-80b1-4297-b5eb-28892906e056.png)
After writing some Python code to prepare this same state 10 times in a row, and then measure it, we have the following:
for i in range(10):
bell_state_phi_plus=(create_quantum_state([zero_qubit,zero_qubit])+create_quantum_state([one_qubit,one_qubit]))/np.sqrt(2)
print(measure_in_01_basis(bell_state_phi_plus))
When we ran the preceding code, we got the following output:
|"11"> |"00"> |"00"> |"00"> |"11"> |"00"> |"11"> |"00"> |"00"> |"11">
However, each time you run the code, there are new random numbers chosen as part of the measurement, so it will print different results. My results matched our expectations, which were that we would get |"00"> 50% of the time and |"11"> 50% of the time. What are your results?
Now, this code is missing one piece inherent to quantum mechanics: after we measure a state once, we need to guarantee that every subsequent measurement produces the same results. For this, we imagine a new function, measure_in_01_basis_collapse, which could be written to ensure that property.
The function measure_in_01_basis_collapse, which you will have the chance to implement in the chapter exercises, would need to ensure that the following code would always print |"00"> twice in a row, or |"11"> twice in a row:
bell_state_phi_plus=(create_quantum_state([zero_qubit,zero_qubit])+create_quantum_state([one_qubit,one_qubit]))/np.sqrt(2)
print(measure_in_01_basis_collapse(bell_state_phi_plus))
print(measure_in_01_basis_collapse(bell_state_phi_plus))
Our current function doesn't guarantee that, but the sixth question at the end of this chapter will give you a chance to implement a function that does.
Note that if we prepare multiple bell_state_phi_plus then the measurements of one do not affect the other. So the following code:
bell_state_phi_plus=(create_quantum_state([zero_qubit,zero_qubit])
+create_quantum_state(
[one_qubit,one_qubit]))/np.sqrt(2)
print(measure_in_01_basis_collapse(bell_state_phi_plus))
print(measure_in_01_basis_collapse(bell_state_phi_plus))
bell_state_phi_plus=(create_quantum_state([zero_qubit,zero_qubit])
+create_quantum_state(
[one_qubit,one_qubit]))/np.sqrt(2)
print(measure_in_01_basis_collapse(bell_state_phi_plus))
print(measure_in_01_basis_collapse(bell_state_phi_plus))
This produces the following, for example:
|"00">
|"00">
|"11">
|"11">