Implementing a controlled rotation gate, Rk, in Python

Recall the Pauli gates: X, Y, and Z, which rotate a qubit about the x, y, or z axis respectively by 180°, and the phase gate, S, which rotates about the z axis by 90°. For the QFT, we will want a gate that rotates about the z axis by the number of degrees of our choice. To get some insight into how to do this, recall the definition of the S gate:

The S gate rotates around the z axis, about the x-y plane by 90° (π/2 radians). 

In Python, recall that this is the following:

S=np.matrix([[1,0],[0,np.e**(i_*np.pi/2.)]])

We see that pi/2 in the preceding equation determines the number of radians by which S will perform its rotation. So, for an arbitrary number of radians, we would want to make that a function of some parameter, for example, let's define a function, called simple_rotation, which performs a rotation by a specified parameter, lambda:

def simple_rotation(lambda):
np.matrix([[1,0],[0,np.e**(i_*lambda)]])

That will then rotate around the z axis by lambda (the symbol for lambda is λ) degrees. With the QFT we will be performing a transform on n qubits, and each rotation will be controlled by another qubit. Recall the CNOT gate that performed an operation on a target qubit only if the control qubit is |"1">. For the QFT we will not only want to rotation gate the be controlled by a control qubit, but at index k, we will also want to change the amount of the rotation based on the qubit that is the control qubit. The formula we will use to do so is as follows, in radians:

  

The preceding formula can be written in degrees as follows:

To this end, we define a rotation gate, Rk, that is a function of k:

def Rk(k):
return np.matrix([[1,0][0,np.e**(2*np.pi*1j/2**k)]])

This rotates around the axis by a certain amount that changes depending on the value of kFor k = 0 this rotation is 0° (0 radians); for k = 1 this rotation is 180° (π radians); for k = 2 this rotation is 90° (π/2 radians); for k = 4 this rotation is 45° (π/4 radians); for k = 4 this rotation is 22.5° (π/8 radians); and for k = 5 this rotation is 11.25° (π/16 radians), for example. Notice that the k = 0 case is identical to the I gate; the k = 1 case is identical to the Z gate; k = 2 case is identical to the S gate; and the k = 3 case is identical to the T gate. For k = 4 and above, we do not have a primitive gate that we have studied thus far in IBM QX, which is the equivalent, so we will expect to need a type of gate we haven't yet studied in order to implement this in IBM QX. This gate, called the U1 gate, will be introduced in the IBM QX implementation section of this chapter.

What is left then is to make Rk a controlled gate. To do this, let's look to the CNOT gate as inspiration. Recall that the CNOT gate was defined as the following:

CNOT=np.matrix('1 0 0 0; 0 1 0 0; 0 0 0 1; 0 0 1 0')

The first two columns of the first two rows of the CNOT gate, separated by semi-colons in the Python syntax, correspond to what amounts to the identity gate, meaning to leave the output unchanged if the control qubit is zero. The second two columns of the second two rows correspond to the X gate, that is, the NOT gate, meaning to flip the output if the control qubit is one. In this case, to define our controlled rotation gate, we will want to leave the first two rows the same as the CNOT gate, but change the second two rows to incorporate the Rk gate. Thus, we have the following:

def CRk(k):
return np.matrix([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,np.e**(2*np.pi*1j/2**k)]])