Quantum Phase Estimation in Qiskit

Interested in learning how to program quantum computers? Then check out our Qiskit textbook Introduction to Quantum Computing with Qiskit.

Introduction

In this tutorial we will explore Quantum Phase Estimation and how to implement in Qiskit for IBM’s Quantum devices.

What is Quantum Phase Estimation?

Quantum Phase Estimation is a quantum algorithm that estimates the phase of a unitary operator. Phase estimation plays a very important role in a number of quantum algorithms such as Shor’s algorithm.

See our tutorial on Shor’s algorithm here: https://quantumcomputinguk.org/tutorials/shors-algorithm-with-code

How does it work?

Quantum Phase estimation is essentially a quantum circuit consisting of two sets of qubits. The first set consists of counting qubits that are used to control unitary operations and the second set whom the unitary operations are applied to.

The steps in Phase Estimation are as follows:

Step 1: Put the counting qubits in to Superposition

The counting qubits are put in to superposition using Hadamard gates.

Step 2: Apply unitary operations to the second set

The main part of the circuit is to apply unitary operations on the second set.

These unitary operations are essentially just controlled phase rotations of a specific angle. This angle is the phase that we wish to estimate. The first counting qubit will do 1 rotation while the second will do 2 rotations and the third will do 4 rotations and so on.

For example lets say we have 4 qubits Q0 to Q3. The first 3 are the counting qubits and the 4th qubit is the qubit we wish to apply phase rotations to.

The phase we wish to encode is pi/2. The first 3 qubits are put in to superposition. Next Q0 will control 1 phase rotation on Q3. Then Q1 will do 2 phase rotations on Q3 and Q2 will do 4 phase rotations on Q3. Note that each rotation will rotate Q3’s phase by pi/2.

Step 3: Apply an Inverse QFT

After these rotations an inverse QFT is applied to the counting qubits and they are measured.

A QFT or Quantum Fourier Transform is a circuit that transforms the state of the qubit from the computational basis to the Fourier basis. However in phase estimation we use the inverse QFT which puts the state in the Fourier basis in to the computational basis so we can measure it.

For more information on the Quantum Fourier Transform see our tutorial here: https://quantumcomputinguk.org/tutorials/quantum-fourier-transform-in-qiskit

Step 4: Measure the counting qubits

After we have applied the inverse QFT we measure the qubits. If we have encoded a phase of pi/2 in to Q3 then we should get the binary value ‘010’ which is 2.

To estimate the phase we use the following formula:

CodeCogsEqn (1).gif

Where θ is the estimated phase, M is the measured value, and n is the number of counting qubits. As such from the measurement above:

CodeCogsEqn (3).gif


Which is correct since pi/2 corresponds to a quarter rotation or 0.25.

Implementation

Next we will see how to implement quantum phase estimation in Qiskit so we can run it on real quantum devices!

For the implementation our circuit will consist of 4 qubits. The first 3 will be the counting qubits and the 4th will be qubit that we encode the unitary operations on.

For this example we will encode a phase of 2(pi/3). This will correspond to a phase rotation of 1/3.

Circuit diagram of the phase estimation circuit.

Circuit diagram of the phase estimation circuit.

Step 1: Initialise the quantum and classical registers

This is done using the following code:

q = QuantumRegister(4,'q')
c = ClassicalRegister(3,'c')

circuit = QuantumCircuit(q,c)

Note that the quantum register consists of 4 qubits but the classical register consists of only 3 bits. This is because we only want to measure the 3 counting qubits whose values will be mapped to the classical register.

Step 2: Put the counting qubits in to Superposition

This is done by applying Hadamard gates with the following code:

circuit.h(q[0])
circuit.h(q[1])
circuit.h(q[2])
circuit.x(q[3]) # Flips Q[3] to 1

Step 3: Apply unitary operations

Now we can apply unitary operations with the specified phase angle (2*pi/3):

angle = 2*pi/3 #The phase angle we wish to encode
actual_phase = angle/(2*pi) # This is the actual phase rotation ie 0.5 would be half a rotation. Our expected rotation will be 0.33.  

circuit.cu1(angle, q[0], q[3]);#where angle is the rotation amount, q[0] is the control qubit and q[3] is the target qubit

circuit.cu1(angle, q[1], q[3]); 
circuit.cu1(angle, q[1], q[3]);

circuit.cu1(angle, q[2], q[3]);
circuit.cu1(angle, q[2], q[3]);
circuit.cu1(angle, q[2], q[3]);
circuit.cu1(angle, q[2], q[3]);

circuit.barrier()

Note: cu1 is a rotational gate in qiskit which only rotates the phase of the qubit.

Step 4: Apply an inverse QFT

circuit.swap(q[0],q[2])
circuit.h(q[0])
circuit.cu1(-pi/2, q[0], q[1]);
circuit.h(q[1])
circuit.cu1(-pi/4, q[0], q[2]);
circuit.cu1(-pi/2, q[1], q[2]);
circuit.h(q[2])

circuit.barrier()

Step 5: Measure the qubits

#### Measuring counting qubits ####
circuit.measure(q[0],0)
circuit.measure(q[1],1)
circuit.measure(q[2],2)

Step 6: Run the circuit and obtain the results

Next we run the circuit by executing the job. Then we use the job monitor to monitor its progress and finally we obtain the counts.

job = execute(circuit, backend, shots=8192)
job_monitor(job)

counts = job.result().get_counts()

Step 7: Estimate the Phase

When we obtain the counts we can use them to estimate the phase with the formula showing earlier.

print("Phase estimation output")
print("-----------------------\n")

a = counts.most_frequent()

print('Most frequent measurement: ',a,'\n')

bin_a = int(a,2) # Converts the binary value to an integer
phase = bin_a/(2**3) # The calculation used to estimate the phase

print('Actual phase is: ',actual_phase)
print('Estimated phase is: ',phase)
input()

How to run the program

  1. Copy and paste the code below in to a python file

  2. Enter your API token in the IBMQ.enable_account('Insert API token here') part

  3. Save and run

In order to get an API key you will have to register to the IBM quantum experience: https://quantum-computing.ibm.com

Code

from qiskit import QuantumRegister, ClassicalRegister
from qiskit import QuantumCircuit, execute,IBMQ
from qiskit.tools.monitor import job_monitor
from qiskit.circuit.library import QFT
import numpy as np

IBMQ.enable_account('ENTER API KEY HERE')
provider = IBMQ.get_provider(hub='ibm-q')

backend = provider.get_backend('ibmq_qasm_simulator')

q = QuantumRegister(4,'q')
c = ClassicalRegister(3,'c')

circuit = QuantumCircuit(q,c)

pi = np.pi

angle = 2*(pi/3)

actual_phase = angle/(2*pi)


#### Controlled unitary operations ####
circuit.h(q[0])
circuit.h(q[1])
circuit.h(q[2])
circuit.x(q[3])

circuit.cu1(angle, q[0], q[3]);

circuit.cu1(angle, q[1], q[3]);
circuit.cu1(angle, q[1], q[3]);

circuit.cu1(angle, q[2], q[3]);
circuit.cu1(angle, q[2], q[3]);
circuit.cu1(angle, q[2], q[3]);
circuit.cu1(angle, q[2], q[3]);

circuit.barrier()

#### Inverse QFT ####
circuit.swap(q[0],q[2])
circuit.h(q[0])
circuit.cu1(-pi/2, q[0], q[1]);
circuit.h(q[1])
circuit.cu1(-pi/4, q[0], q[2]);
circuit.cu1(-pi/2, q[1], q[2]);
circuit.h(q[2])

circuit.barrier()

#### Measuring counting qubits ####
circuit.measure(q[0],0)
circuit.measure(q[1],1)
circuit.measure(q[2],2)


print(circuit)

job = execute(circuit, backend, shots=8192)

job_monitor(job)

counts = job.result().get_counts()

print('\n')
print("Phase estimation output")
print("-----------------------\n")

a = counts.most_frequent()

print('Most frequent measurement: ',a,'\n')

bin_a = int(a,2) # Converts the binary value to an integer
phase = bin_a/(2**3)# The calculation used to estimate the phase


print('Actual phase is: ',actual_phase)
print('Estimated phase is: ',phase)
input()

Output

Output showing the circuit and the measurement and estimated phase.

Output showing the circuit and the measurement and estimated phase.