Module 14 Final Exam: Quantum Computation
Introduction
The dynamics of quantum bits, called qubits, are governed by how particles interact at a subatomic level. In some ways, qubits can behave like classical bits and can be treated as a 0 or a 1; these are called the “basis states” of a qubit. Unlike classical bits, however, qubits can exist in a superposition of states that can be expressed as a linear combination of the aforementioned basis states. In this Final Exam Assignment you will use a basic linear algebraic formulation of qubits to understand more about how qubits behave and how they can be used to perform computation.
Skills: conditional statements, control structures, file I/O, functions, classes (OOP), exceptions, NumPy arrays
Qubits as Vectors
It is perhaps simplest to think of a qubit as nothing more than a 2-dimensional vector that lies within the complex vector plane. That is, a qubit in either of the basis states can be represented as a 2x1 vector. Here’s an example of a qubit in the “0” basis state. The qubit, which appears on the left, is called a “ket”. As you can see, a qubit in this state (which can conceptually be thought of as a classical bit with a value of 0), is represented by the 2-dimension column vector shown (with an x-component of 1 and a y-component of 0):
And here’s an example of a qubit in the “1” basis state (which can conceptually be thought of as a classical bit with a value of 1). It has an x-component of 0 and a y-component of 1:
If we plot these on a 2-D plane, we get the result below where the length of each of the 2 basis vectors is 1:
So far our qubits are nothing more than 2-D vectors of unit length and don’t provide any advantages over classical bits in the 0 or 1 state. But, notice the red line in the graph above. This red line represents a superposition of the two basis states and this is one of the advantage quantum bits have over classical bits. Instead of the qubit being only a 0 or 1, the qubit is in a superposition of both 0 and 1 at the same time! We mentioned in the Introduction that in quantum physics we can have qubits in their basis states (the “0” and “1” basis states above) or a superposition of the basis states. This superposition is just a linear combination of the two basis states. So, it might help to think of the superposition to mean the qubit is currently alpha amount in the “0” basis state and beta amount in the “1” basis state. The values alpha and beta, though, are probability amplitudes, so what we’re really saying here is that, if we were to measure the qubit that is in a superposition, there is an alpha2 chance we measure a “0” and a beta2 chance we measure a “1”. A very important thing to keep in mind is that the sum of the squares alpha and beta must equal 1. Here’s an example:
Therefore, there is a 64% chance of measuring a “0” and a 36% chance of measuring a “1”. This makes sense because qubits are probabilistic in nature. If we had a qubit in this state 100 times and performed 100 measurements, we’d expect to receive 64 0’s and 36 1’s from our measurements. For completeness, we can write any arbitrary superposition as the 2-D column vector containing alpha and beta by plugging in the vector representation of |0> and |1>:
Matrices as Logic Gates (Quantum Operators)
Pauli X Gate
To use qubits for computation, we must develop a set of operators (logic gates) that will act upon a (in our case, single) qubit in a similar way to how logic gates act on classical bits. For example, we’ve learned about the NOT operator in Python which negates a Boolean value (it “flips” the value so True becomes False and False becomes True). The quantum analog to the classical NOT gates is the 2x2 matrix called the Pauli X-gate or the “quantum NOT” operator:
Similar to how flipping a classical bit works when applying a NOT gate to a 0, we can apply the X-gate to a qubit (by multiplying the operator (matrix) by the qubit (vector)) in the 0 basis state and we will get a qubit in the 1 basis state:
Similarly, applying an X-gate to a qubit in the 1 basis state will give us a qubit in the 0 basis state:
Hadamard Gate
The Hadamard operator (gate) can be applied to a single qubit to place it into an equally-weighted superposition of the 0 and 1 basis states. This notion does not apply to classical bits which take on only discrete values: 0 or 1. A qubit in a superposition is in both the |0> and the |1> state at the same time! A Hadamard gate can be represented with the following 2x2 matrix:
Here is the Hadamard operator (gate) applied to a qubit in the |0> state. We say the resulting superposition is “equally weighted” because, after squaring the amplitudes, there is a ½ chance measuring the qubit results in a |0> and a ½ chance of measuring a |1>:
Final Exam Programming Assignment Requirements
Outside of the requirements listed below you’re free to implement your solution however you’d like using any of the concepts and libraries we’ve learned during the semester. If you have a question about the use of a particular library we have not covered, please be sure to reach out through Teams or email.
- Your solution must make use of object-oriented programming (custom classes)
- Create a file called main.py that uses name to call a function main() should:
- a. Read in a file called qubits.txt that contains the state of the qubits and sequences of operators that will be applied to the qubit. Each line in the input file will contain a floating point value for alpha, a floating point value for beta, and a number of operators that will be applied to the qubit (only the X and H gates are valid operators) i. Ex: 0.8 0.6 H X (alpha = 0.8, beta = 0.6, apply 1 H gate then 1 X gate)
- b. Raises an InvalidOperator exception that prints “Invalid operator.” if any of the operators in the input file are not X (Pauli X) or H (Hadamard)
- c. Contains a loop that processes each qubit in the input file (applies the list of operators) using the Qubit and SingleQubitOperator classes below.
- d. Prints the initial state of the qubit. (Section 3.e below)
- e. Calls the experiment() method (Section 3.d below)
- f. Prints the final state of the qubit once all operators have been applied. See “Sample Output” and Section 3.e below.
- g. Catches (except’s) any InvalidProbabilityAmplitude exceptions that are raised
- Next, create a Qubit class inside of a module named qubit.py. Your class should:
- a. Extend the ComputingBit abstract class from the computingbit.py module provided on Canvas and implement the 3 abstract methods inside of your Qubit class.
- b. Contain a constructor that uses instance variable(s) to keep track of the state of the qubit, using a 2x1 NumPy column vector, which will be the 0 basis state |0>, the 1 basis state|1>, or an arbitrarily weighted superposition of the two basis states. The constructor should also call validate_amplitudes() (defined in ‘c’ below).
- c. Contain a method named probability_amplitudes that returns the probabilities of receiving a |0> and the probability of receiving a |1> from a measurement (i.e. alpha2 an beta2).
- d. Contains a method called validate_amplitudes that raises an InvalidProbabilityAmplitude exception that prints “Invalid probability amplitude(s).” if illegal values for alpha or beta are provided (the sum of their squares not equal to one).
- e. Contains a method called experiment() that samples from a properly weighted binomial distribution 100 times to demonstrate that a qubit yields a 0 (|0>) with probability alpha2 and yields a 1 (|1>) with probability beta2.
- f. Contains a str method that provides a string representation of a qubit object: i. “X|0> + Y|1>”, where X and Y are the values for alpha and beta respectively
...