Gates for any Unitary#

Warning

This page below here is not yet finished/polished.

We have built our simulator with some universal quantum gates: \(P(\theta)\), H, and CNOT.

These gates have the property that:

  • You can build any unitary using these gates.

  • They aren’t especially bad. What we mean by this is that there isn’t another set of reasonable gates that are much better. One way to see this is that we can build other reasonable gate sets from this set without too much trouble.

  • They aren’t cheating. A couple special 1 and 2 qubit gates are reasonable atomic constructs that experimentalists can build. There are lots of other choices but we will see (later) that with different choices you can quickly build up this set (and then can build anything).

We will focus on showing the first two bullet points in this section. We will first show how to reasonably efficiently build any one and two qubit gates. This will tell us that there isn’t much penalty for using the set we’ve chosen. Then we will also see how to build any arbitrary unitary from these gates.

To accomplish this, what we will need to do is figure out how to take an arbitrary unitary and break it up into H, P, and CNOT.

As our first step we are going to figure out how to build arbitrary 1 bit unitaries.

Next, we will generate arbitrary control-unitaries (first one bit, and then otherwise)

Finally, we will put it all together to generate an arbitrary unitary. It is important to note that this algorithm will eat an arbitrary unitary and give you a circuit but there’s no reason to think that the circuit you get out will be the most efficient way of doing things.

Gates for Shor’s Algorithm

If you’re goal is just to make it through Shor’s algorithm, then you only need to implement a small subset of these gates. To get through Shor you are going to need

Control-Phase: To make this gate do, NOT -> Rz -> Control-Rz -> Control-Phase

Control-Classical Function: This will be done on a separate page.

Swap: Figure out how to build a swap using three CNOT

Long-range CNOT: (possibly already implemented in your simulator but you can also do long-range CNOT by swapping up and then CNOT and then swapping down)


Universal Single Qubit Gates#

We are going to spend a bit of time building circuits for more sophistcated gates. We are going to start by building 1-wire circuits. When you just have 1-wire (and therefore 1-qubit) we can visualize that qubit on a bloch sphere (see here). This is sensible because a single qubit has three parameters that specify it (two complex numbers and on constraints). In our language, \(|0\rangle\) points in the \(\hat{z}\) direction, and \(|1\rangle\) points in the \(-\hat{z}\) direction. \(|0\rangle + |1\rangle\) is in the \(\hat{x}\) direction.

We can graph a single qubit in python using the following:

import qutip

def graph(vec):
    b=qutip.Bloch()
    up=qutip.basis(2,0)
    down=qutip.basis(2,1)
    b.add_states(vec[0]*up+vec[1]*down)
    b.show()

graph(myOneWireState)

Go ahead and graph a couple vectors and see what it does. Also, try to figure out what the Hadamard gate does.

Pauli Gates#

The three pauli gates are

\[\begin{split} Z= \begin{bmatrix} 1 & 0 \\ 0 & -1 \\ \end{bmatrix} \end{split}\]
\[\begin{split} X= \begin{bmatrix} 0 & 1 \\ 1 & 0 \\ \end{bmatrix} \end{split}\]
\[\begin{split} Y= \begin{bmatrix} 0 & -i \\ i & 0 \\ \end{bmatrix} \end{split}\]

Figure out how to build these circuits from Hadamard and phase gates. Think about what this does on the Bloch sphere (or just graph it on some vectors before and after) Notice that X=NOT.

Rotation matrices#

Often we want to take a qubit and do a rotation around these axis.

\[R_x(\theta)=e^{-i \frac{\theta}{2} X}\]
\[R_y(\theta)=e^{-i \frac{\theta}{2} Y}\]
\[R_z(\theta)=e^{-i \frac{\theta}{2} Z}\]

Build a python code which eats \(\theta\) and produces circuits for these three gates.

Any one-qubit unitary#

Here we will consider how to generate arbitrary one-wire unitaries given our univesal gate sets. Notice that a one-wire unitary essentially is a rotation of the Bloch sphere and so we expect to be able to write it as rotations.

A unitary matrix has the property that \(UU^\dagger=I\). It then follows that \(\det(UU^\dagger)=1\) which implies \(\det(U)\det(U^\dagger)=aa^*=1\). Therefore the determinant of a unitary matrix, \(\det(U)=e^{i\phi}\).

We will find it convenient to write unitaries as $\( U= \begin{bmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{bmatrix} = e^{i\phi/2} \begin{bmatrix} u_{11} & u_{12} \\ u_{21} & u_{22} \\ \end{bmatrix} =e^{i\phi/2} \begin{bmatrix} e^{i\phi_1}\cos(\theta) & e^{i\phi_2} \sin(\theta) \\ -e^{-i\phi_2}\sin(\theta) & e^{-i\phi_1} \cos(\theta) \\ \end{bmatrix} \)$

with certain constraints on these values.

If we then let $\(\alpha = arg(u_{11})-arg(u_{21})\)\( \)\(\beta = arg(u_{11})+arg(u_{21})\)\( \)\(\theta = \arctan(|u_{21}|/|u_{11}|)\)$

we can write $\(U = e^{i\phi/2} R_z(-\alpha)R_y(2 \theta)R_z(-\beta)\)$ (At the moment you don’t have to worry about the global phase out front because it just gives a global phase to the entire system. - You should understand this! We will eventually need to deal with the phase though if, for example, we are controlling it)

Convince yourself that this gives you the right matrix. This also checks that my formulas don’t have missing factors of two or minus signs somewhere (one way to convince yourself is to write three lines of code to take a random unitary, split it up like this and multiply out the matrices to check ).

Build a python code which eats the unitary matrix and produces a one-wire circuit for \(U\).

For testing you probably want to generate random unitaries and see if it does the correct thing. To get a random unitary, generate a random matrix, make it Hermitian, multiply it by \(i\) and then exponentiate it using scipy.linalg.expm.

Verify that when you run your one-wire circuit through your simulator that you get the correct results.

An aside about simulating one-qubit circuits#

Edification

This section is just for your edification and one doesn’t need to understand it for anything else in this project.

Here we are going to start learning a bit about the power and the limitations of quantum computing. First let’s think about simulations where you only have one-qubit gates.

Do the following test. Choose some random unitary matrices with determinant 1. Run your circuit and get the quantum state as output.

3
U 0 u11 u12 u21 u22
U 1 v11 v12 v21 v22
U 2 w11 w12 w21 w22

Now, run three simulations

1
U 0 u11 u12 u21 u22

and

1
U 0 v11 v12 v21 v22

and

1
U 0 w11 w12 w21 w22

get your output and tensor product your outputs. Compare it to the output you got when you had three wires? What do you notice? Why is this?

Now, suppose that these four circuit descriptions have

Measure

at the end. Can you figure out the relationship of the probabilities of the first circuit description compares to the last three? In other words, can you write some python code that takes a circuit description with only single qubit gates and simulates it exponentially faster then your general quantum simulator. You don’t have to do this for a grade but it’s a nice illustrative project if you’re ahead.

An aside about controlling one-qubit unitaries#

Edification

This section is just for your edification and one doesn’t need to understand it for anything else in this project.

Control-U (one wire) We’ve seen that we can generate any 1-qubit unitary matrix. Now we’d like to see how we can generate ctrl-U for one-wire U. Figure out how to do a ctrl-U. Here you have to pay attention to the phase \(e^{i\phi}\) since if it’s controlled it only applies to some of the binary numbers.

You might want to use the fact that

\(A=R_z(\alpha)R_y(-\theta)\) \(B=R_y(\theta)R_z(-\frac{\beta+\alpha}{2})\) \(C=R_z(\frac{\beta-\alpha}{2})\)

and that \(ABC=I\) and \(AXBXC=U\) (and that X=NOT) (check this to feret out any factors of 2 I have wrong).

Add this to your preprocessor using the syntax

CU 0 1 u11 u12 u21 u22

where the first number is the control and the second number is the wire the unitary is on.

Warning

This page below here is not yet finished/polished.

Two qubit gates#

At this point you have successfully generated any one-qubit unitaries. The next step is to be able to generate an arbitrary two-qubit unitary (assuming you have access to one-qubit unitaries). Work out how to get arbitrary two-qubit unitaries uses one-qubit unitaries and a CNOT.

Arbitrary Unitaries#

Finally, you know need to figure out how to take an arbitrary unitary written as a big matrix and write code which generates the circuit description for this unitary. Effectively what you wnat to do here is use circuit descriptions to decompose it into two-qubit unitaries.

A note about Discrete Universal Gate Sets#

In our work so far, we’ve been using a universal gate set that has a continuous set of gates (because our phase gate can be any angle). There are also universal gate sets that are discrete. In this case, we have to get the continuous phase to be pretty close from a discrete set of gates. Consider this.