A single quantum bit - The Bloch sphere

To understand the quantum computing, you must understand quantum bits, or q-bits. Good news: the surface is very simple. The bad news: the core is not. In this post, we will deal with a simplest, visual representation, the Bloch sphere.

According to Wikipedia, the Bloch sphere can represent a simple, two-level quantum system. Well... This is true if you know what is a two-level quantum system and how can it be simple.

Now we will think about the Bloch spare as a unit length vector which can point to the surface of a unit radius sphere. (And without any connection to the quantum mechanics or physics. This is just a simple, geometrical object.)

Here is a simple visual representation of it:

If you want to see it for yourself, the following Python code can generate it:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations
from matplotlib.patches import FancyArrowPatch
from mpl_toolkits.mplot3d import proj3d

class Arrow3D(FancyArrowPatch):

    def __init__(self, x0, y0, z0, alpha, beta, *args, **kwargs):
        FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
        x = np.cos(alpha)*np.sin(beta)
        y = np.sin(alpha)*np.sin(beta)
        z = np.cos(beta)
        print("(x={}, y={}, z={})".format(x, y, z))
        self._verts3d = [x0, x], [y0, y], [z0, z]

    def draw(self, renderer):
        xs3d, ys3d, zs3d = self._verts3d
        xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
        self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
        FancyArrowPatch.draw(self, renderer)

class QuantumBit:
    def __init__(self, alpha, beta):
        self.alpha = alpha
        self.beta = beta

    def draw(self):
        fig = plt.figure()
        ax = fig.gca(projection='3d')
        ax.set_aspect("auto")

        # draw sphere
        u, v = np.mgrid[0:2*np.pi:10j, 0:np.pi:10j]
        x = np.cos(u)*np.sin(v)
        y = np.sin(u)*np.sin(v)
        z = np.cos(v)
        ax.plot_wireframe(x, y, z, color="gray")

        # draw a point
        ax.scatter([0], [0], [0], color="g", s=100)

        a = Arrow3D(0, 0, 0, self.alpha, self.beta, mutation_scale=20,
                    lw=1, arrowstyle="-|>", color="k")

        ax.add_artist(a)
        ax.plot([0, 1], [0, 0], zs=[0, 0], color="r")
        ax.plot([0, 0], [0, 1], zs=[0, 0], color="b")
        ax.plot([0, 0], [0, 0], zs=[0, 1], color="g")
        
        plt.grid(False)
        plt.axis('off')

        plt.show()

ratio = np.pi/180

quantumBit = QuantumBit(ratio*45, ratio*45)
quantumBit.draw()

Cool... What can we do with this Bloch sphere? Well... Two things:
  • Set the arrow to any point of the surface
  • Make a measure
Setting the arrow to any point of the surface is very straighforward. You just modify alpha and beta in the constructor call of QuantumBit. You can set the tip of the arrow to any point of the surface.

Measuring is a little bit more messy. First, we have to define our coordinate system.
  • The green dot in the center of the sphere is our origo.
  • The (alpha = 0, beta = 0) direction is the positive Z axis. (Marked by the green line.).
  • The (alpha = 0;, beta = 90°) direction is the positive X axis. (Marked by the red line.).
  • The (alpha = 90°, beta = 90°) direction is the positive Y axis. (Marked by the blue line.).
Measuring the qbit is not like measuring a distance or a temperature. Firstly, you will get only one bit of information with a measurement. Secondly, the measure will modify the state of the system. Maybe calling it measurement is very misleading, but we will stick to the official wording.
So... Measuring will
  • set Alpha to 0°;
  • set Beta to 0° or 180° randomly (not neceserly 50%-50%, we will define the propabilities later);
  • return 0 if Beta == 0° and return 1 if Beta == 180°.
As you can see, the measurement not just measures the state of the object, it also destroys the current direction (state) and sets the qbit into Z+ or Z- directions. These directions (or states) are very important, they are called the measurement states. To make our life easier, lets name these states of the qbit. The Z+ direction (or state) will be called |0> and the Z- will be called |1>.
Important: |0> and |1> are NOT numbers. We mark them only with 0 and 1, because measuring the qbit in |0> state will be 0 and measuring it in |1> state will be 1. We could use Greek letters or anything else, but using |0> and |1> are convinient.
Before we can implement the measure member function, we have to define the propabilities of the two results.
We can start by enumerating some intuitive rules we except:
  • P(measurement == 0) + P(measurement == 1) = 1
    • This only means that the result of the measurement is 0 or 1.
  • If the qbit is in state |0>, P(measurement == 0) = 1
    • The same is true for |1>
  • If the state (the direction of the arrow) is closer to |0> than to |1>, then P(measurement == 0) > P(measurement == 1)
    • This "closer" concept is the same as in everyday life. For example, Berlin is closer to the north pole than Sydney
    • The value of Alpha does not metter during measurment. It only rotates the vector around Z axis, it doesn't change the distance from the |1> or |0>. (It has some indirect effect, but we will deal with it later.)

Ok, now we should write some equations to define P(measurement == |1>) and P(measurement == |0>). We have many options:
  • We can project the vector to the Z axis (get the Z coordinate, which is Vz) and measure (calculate) the distance between this point and the two endpoints (which are Z = -1 for |0> and Z = 1 for |1>). In this case
    • P(measurement == 0) := (Vz-(-1))/((Vz-(-1)) + (1-Vz)) = (Vz+1)/2
    • P(measurement == 1) := (1-Vz)/2
  • We can measure (calculate) the distance between the arrow and the poles. In this case:
    • The distance from the Z axis: r := sqrt(x^2+y^2);
    • The distance from the |0> (0, 0, 1): d0 := sqrt((Vz-(-1))^2 + r^2); d1 := sqrt((Vz-1)^2 + r^2);
    • The distance from the |1> (0, 0, -1): d1 := sqrt((Vz-1)^2 + r^2); d1 := sqrt((Vz-1)^2 + r^2);
    • P(measurement == 0) := d0/(d0+d1)
    • P(measurement == 1) := d1/(d0+d1)
  • We can calculate the distance from the poles measuring on the sufrace of the sphere. I won't fully deduct this one, but the formulas will be something like this:
    • ArcV-|0> is the length of the arc between the vector and the (0, 0, -1)
    • ArcV-|1> is the length of the arc between the vector and the (0, 0, 1)
    • TotalArc := ArcV-|0> + ArcV-|1>
    • P(measurement == 0) := ArcV-|0>/TotalArc
    • P(measurement == 1) := ArcV-|1>/TotalArc
These propabilities are all valid, they all satisfy our intuitive expectations. If you are familiar with different norms, you can define infinitly more and if you are not, you can still see the general form. (P(a) = a/(a+b), P(b) = b/(a+b)).
We can't choose between these formulas only with logical arguments, they are both valid. We need the measurements of the quantum physicists. I don't want to dive into the details (especially because I don't understand them), but the physically usable formulas will be:

P(measurement == 0) := cos2(Beta/2)
P(measurement == 1) := sin2(Beta/2)

These formulas meet our expectations:
  • P(measurement == 0) + P(measurement == 1) = cos2(Beta/2) + sin2(Beta/2) = 1. (Trigonometric identity)
  • If the qbit is in state |0>, P(measurement == 0) = cos2(0/2) = 1
  • If the qbit is in state |1>, P(measurement == 1) = sin2(180/2) = 1
  • If the qbit is closer to state |0>, Beta < 90 and cos(0..45-) > sin(0..45-)
  • If the qbit is closer to state |1>, Beta > 90 and cos(45+..90) < sin(45+..90)

With this knowledge, we can add the measurement function to our qbit:

class QuantumBit:
    ....
    
    def measure(self) -> bool:
        p0 = np.power(np.cos(self.beta/2), 2)
        measuredStateIs0 = random.random() < p0
        
        self.alpha = 0
        if measuredStateIs0:
            self.beta = 0
            return False
        else:
            self.beta = np.pi
            return True


Now, you see the quantum bit as a purely mathematical object, like a Matrix, Tensor or the Hilbert Space. It can be described as an one-unit lenght vector. You saw that
  • the math behind the quantum bit is just basic propability and trigonometry;
    • for now...
  • the quantum bit has two continous state variables (Alpha and Beta), altough Alpha looks like it is unnecessary;
    • for now...
  • measurements can be done on a qbit, but these measurements are propabilistic and they destroy/reset the inner state of the qbit;
    • this is the so called "collapsing";
  • the qbit has two highlighted states, the Beta == 0, and Beta == 180;
    • these states are so frquently used, that we named them |0> and |1>;
  • these states are special because
    • the measurement is deterministic if the qbit is in one of these states;
    • the new state after a measurement is |0> or |1>;

In the next blog post, I will write about an other, more frequently used representation of a quantum bit.

Comments

Popular posts from this blog

Introduction