Iterative Phase Estimation Algorithm

The latest version of this notebook is available on https://github.com/qiskit/qiskit-tutorial.

For more information about how to use the IBM Q Experience (QX), consult the tutorials, or check out the community.


Contributors

Antonio Córcoles, Jay Gambetta, Rudy Raymond

Quantum Phase Estimation (QPE)

The Quantum Phase Estimation (QPE) algorithm solves the problem of finding unknown eigenvalues of a unitary operator. The attractiveness of the QPE algorithm is due to the fact that it is a key ingredient of some other very powerful algorithms, like order-finding and Shor's.

In a standard textbook, such as Nielsen & Chuang Quantum Computation and Quantum Information, in the QPE, each bit of the phase is encoded in a different qubit on a register using the phase kickback property of controlled-unitary operations. This is followed by an inverse Quantum Fourier Transform operation, which yields an n-bit approximation to the phase by reading the n-qubit register.

Iterative Phase Estimation Algorithm (IPEA)

The QPE algorithm can, however, be realized in a much smaller qubit system, by iterating the steps on a system of just two qubits. This is called the Iterative Phase Estimation Algorithm (IPEA).

Consider the problem of finding $\varphi$ given $|\Psi\rangle$ and $U$ in $U |\Psi\rangle = e^{i \phi} | \Psi \rangle$, with $\phi = 2 \pi \varphi$. Let's assume for now that $\varphi$ can be written as $\varphi = \varphi_1/2 + \varphi_2/4 + ... + \varphi_m/2^m = 0.\varphi_1 \varphi_2 ... \varphi_m$, where we have defined the notation $0.\varphi_1 \varphi_2 ... \varphi_m$. Now, if we have two qubits, $q_0$ and $q_1$, and we initialize them as $q_0 \rightarrow |+\rangle$ and $q_1 \rightarrow |\Psi \rangle$, then, after applying a control-U between $q_0$ and $q_1$ $2^t$ times, the state of $q_0$ can be written as $|0\rangle + e^{i 2 \pi 2^{t} \varphi} | 1 \rangle$. That is, the phase of $U$ has been kicked back into $q_0$ as many times as the control operation has been performed.

For $t=0$, we have a total phase in $q_0$ of $e^{i 2 \pi 2^{0} \varphi} = e^{i 2 \pi \varphi} = e^{i 2 \pi 0.\varphi_1 \varphi_2 ... \varphi_m}$

For $t=1$, the phase would be $e^{i 2 \pi 2^{1} \varphi} = e^{i 2 \pi \varphi_1} e^{i 2 \pi 0.\varphi_2 \varphi_3 ... \varphi_m}$

For $t=2$, $e^{i 2 \pi 2^{2} \varphi} = e^{i 2 \pi 2 \varphi_1} e^{i 2 \pi \varphi_2} e^{i 2 \pi 0.\varphi_3 \varphi_4 ... \varphi_m}$

And for $t=m-1$, $e^{i 2 \pi 2^{m-1} \varphi} = e^{i 2 \pi 2^{m-2} \varphi_1} e^{i 2 \pi 2^{m-3} \varphi_2} ... e^{i 2 \pi 2^{-1} \varphi_m} = e^{i 2 \pi 0.\varphi_m}$. Note that if we perform a Hadamard operation on the state $|0\rangle + e^{i 2 \pi 0.\varphi_m}|1\rangle$ and perform a measurement in the standard basis, we obtain $|0\rangle$ if $\varphi_m = 0$ and $|1\rangle$ if $\varphi_m = 1$.

In the first step of the IPEA, we directly measure the least significant bit of the phase $\varphi$, $\varphi_m$, by initializing the 2-qubit register as described above, performing $2^{m-1}$ control-$U$ operations between the qubits, and measuring $q_0$ in the diagonal basis.

For the second step, we initialize the register in the same way and apply $2^{m-2}$ control-$U$ operations. The phase in $q_0$ after these operations is now $e^{i 2 \pi 0.\varphi_{m-1}\varphi_{m}}= e^{i 2 \pi 0.\varphi_{m-1}} e^{i 2 \pi \varphi_m/4}$. We see that prior to extracting the phase bit $\varphi_{m-1}$, we must perform a phase correction of $\varphi_m /2$. This is equivalent to a rotation around the $Z-$axis of angle $-\varphi_m /4$.

Therefore, the $k$th step of the IPEA, giving $\varphi_{m-k+1}$, consists of the register initialization ($q_0$ in $|+\rangle$, $q_1$ in $|\Psi\rangle$), the application of control-$U$ $2^{m-k}$ times, a rotation around $Z$ of angle $\omega_k = -2 \pi 0.0\varphi_{k+1} ... \varphi_m$, a Hadamard transform to $q_0$, and a measurement of $q_0$ in the standard basis. Note that $q_1$ remains in the state $|\Psi\rangle$ throughout the algorithm.

IPEA circuit

Let's first initialize the API and import the necessary packages


In [1]:
from math import pi
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
%matplotlib inline

# importing Qiskit
from qiskit import Aer, IBMQ
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
from qiskit import execute
from qiskit.tools.visualization import plot_histogram
from qiskit.wrapper.jupyter import *

In [2]:
# Load saved IBMQ accounts
IBMQ.load_accounts()

Now you can try the following circuit in the quantum simulator for a phase of $-5\pi/8 = 2 \pi \varphi$ and $m=4$. Note that the IPEA cannot be run in the real device in this form, due to the current lack of feedback capability.


In [3]:
# We first define controlled gates used in the IPEA
def cu1fixed(qProg, c, t, a):
    qProg.u1(-a, t)
    qProg.cx(c, t)
    qProg.u1(a, t)
    qProg.cx(c, t)

def cu5pi8(qProg, c, t):
    cu1fixed(qProg, c, t, -5.0*pi/8.0)

# We then prepare quantum and classical registers and the circuit
qr = QuantumRegister(2)
cr = ClassicalRegister(4)
circuitName="IPEAonSimulator"
ipeaCircuit = QuantumCircuit(qr, cr)

# Apply IPEA
ipeaCircuit.h(qr[0])
for i in range(8):
    cu5pi8(ipeaCircuit, qr[0], qr[1])
ipeaCircuit.h(qr[0])
ipeaCircuit.measure(qr[0], cr[0])

ipeaCircuit.reset(qr[0])

ipeaCircuit.h(qr[0])
for i in range(4):
    cu5pi8(ipeaCircuit, qr[0], qr[1])
ipeaCircuit.u1(-pi/2, qr[0]).c_if(cr, 1)
ipeaCircuit.h(qr[0])
ipeaCircuit.measure(qr[0], cr[1])

ipeaCircuit.reset(qr[0])

ipeaCircuit.h(qr[0])
for i in range(2):
    cu5pi8(ipeaCircuit, qr[0], qr[1])
ipeaCircuit.u1(-pi/4, qr[0]).c_if(cr, 1)
ipeaCircuit.u1(-pi/2, qr[0]).c_if(cr, 2)
ipeaCircuit.u1(-3*pi/4, qr[0]).c_if(cr, 3)
ipeaCircuit.h(qr[0])
ipeaCircuit.measure(qr[0], cr[2])

ipeaCircuit.reset(qr[0])

ipeaCircuit.h(qr[0])
cu5pi8(ipeaCircuit, qr[0], qr[1])
ipeaCircuit.u1(-pi/8, qr[0]).c_if(cr, 1)
ipeaCircuit.u1(-2*pi/8, qr[0]).c_if(cr, 2)
ipeaCircuit.u1(-3*pi/8, qr[0]).c_if(cr, 3)
ipeaCircuit.u1(-4*pi/8, qr[0]).c_if(cr, 4)
ipeaCircuit.u1(-5*pi/8, qr[0]).c_if(cr, 5)
ipeaCircuit.u1(-6*pi/8, qr[0]).c_if(cr, 6)
ipeaCircuit.u1(-7*pi/8, qr[0]).c_if(cr, 7)
ipeaCircuit.h(qr[0])
ipeaCircuit.measure(qr[0], cr[3])

backend = Aer.get_backend('qasm_simulator')
shots = 1000

results = execute(ipeaCircuit, backend=backend, shots=shots).result()
plot_histogram(results.get_counts())


The results are given in terms of $\varphi = 0.\varphi_1 \varphi_2 \varphi_3 \varphi_4$, with the least significant digit ($\varphi_4$) as the leftmost bit in the classical register. The result is $\varphi = 11/16$, from which $\phi = 2\pi \varphi = 11 \pi/8 = 2 \pi - 5\pi/8$, as encoded in the circuit.

IPEA in the real device

As we have mentioned before, we currently lack the ability to use measurement feedback or feedforward, along with qubit resetting, on the real device in the Quantum Experience. However, we still can implement a segmentized version of the IPEA by extracting the information about the phase one bit at a time.

Try the following four circuits in the real device. They estimate the same phase as in the previous example (-5$\pi/8$), one bit at a time, from least ($\varphi_4$) to most ($\varphi_1$) significant bit.


In [4]:
%%qiskit_job_status
# We then prepare quantum and classical registers and the circuit
qr = QuantumRegister(5)
cr = ClassicalRegister(5)
realStep1Circuit = QuantumCircuit(qr, cr)

# Apply IPEA
realStep1Circuit.h(qr[0])
for i in range(8):
    cu5pi8(realStep1Circuit, qr[0], qr[1])
realStep1Circuit.h(qr[0])
realStep1Circuit.measure(qr[0], cr[0])

#connect to remote API to be able to use remote simulators and real devices
print("Available backends:", [Aer.backends(), IBMQ.backends()])


backend = IBMQ.get_backend("ibmq_5_tenerife")
shots = 1000
   
job_exp1 = execute(realStep1Circuit, backend=backend, shots=shots)


Available backends: [[<QasmSimulator('qasm_simulator') from Aer()>, <QasmSimulatorPy('qasm_simulator_py') from Aer()>, <StatevectorSimulator('statevector_simulator') from Aer()>, <StatevectorSimulatorPy('statevector_simulator_py') from Aer()>, <UnitarySimulator('unitary_simulator') from Aer()>, <CliffordSimulator('clifford_simulator') from Aer()>], [<IBMQBackend('ibmqx4') from IBMQ()>, <IBMQBackend('ibmqx5') from IBMQ()>, <IBMQBackend('ibmqx2') from IBMQ()>, <IBMQBackend('ibmq_16_melbourne') from IBMQ()>, <IBMQBackend('ibmq_qasm_simulator') from IBMQ()>]]

In [8]:
results1 = job_exp1.result()
plot_histogram(results1.get_counts())


In the first step of IPEA as above, we obtain the bit "1" with probability close to one. We then proceed to the second step of IPEA, assuming that we have identified the result of the first step correctly, as below.


In [5]:
%%qiskit_job_status
realStep2Circuit = QuantumCircuit(qr, cr)

# Apply IPEA
realStep2Circuit.h(qr[0])
for i in range(4):
    cu5pi8(realStep2Circuit, qr[0], qr[1])
realStep2Circuit.u1(-pi/2, qr[0]) # Assuming the value of the measurement on Step 1
realStep2Circuit.h(qr[0])
realStep2Circuit.measure(qr[0], cr[0])

job_exp2 = execute(realStep2Circuit, backend=backend, shots=shots)



In [9]:
results2 = job_exp2.result()
plot_histogram(results2.get_counts())


In the second step of IPEA as above, we obtain the bit "1" with probability close to one. We then proceed to the third step of IPEA, assuming that we have identified the result of the first and second steps correctly, as below.


In [6]:
%%qiskit_job_status
realStep3Circuit = QuantumCircuit(qr, cr)

# Apply IPEA
realStep3Circuit.h(qr[0])
for i in range(2):
    cu5pi8(realStep3Circuit, qr[0], qr[1])
realStep3Circuit.u1(-3*pi/4, qr[0]) # Assuming the value of the measurement on Step 1 and Step 2
realStep3Circuit.h(qr[0])
realStep3Circuit.measure(qr[0], cr[0])

job_exp3 = execute(realStep3Circuit, backend=backend, shots=shots)



In [10]:
results3 = job_exp3.result()
plot_histogram(results3.get_counts())


In the third step of IPEA as above, we obtain the bit "0" with probability close to one. We then proceed to the fourth step of IPEA, assuming that we have identified the result of the first, second, and third steps correctly, as below.


In [7]:
%%qiskit_job_status
realStep4Circuit = QuantumCircuit(qr, cr)

# Apply IPEA
realStep4Circuit.h(qr[0])
cu5pi8(realStep4Circuit, qr[0], qr[1])
realStep4Circuit.u1(-3*pi/8, qr[0]) # Assuming the value of the measurement on Step 1, 2, and 3
realStep4Circuit.h(qr[0])
realStep4Circuit.measure(qr[0], cr[0])
 
job_exp4 = execute(realStep4Circuit, backend=backend, shots=shots)



In [11]:
results4 = job_exp4.result()
plot_histogram(results4.get_counts())


In the fourt step of the IPEA, we identify the bit "1" with high probability. In summary, we can conclude with high probability that the binary string of the phase is "1011"; that is, eleven in the decimal.

We have left aside the case when $\varphi$ does not accept a decomposition of the form $\varphi = \varphi_1/2 + \varphi_2/4 + ... + \varphi_m/2^m$. In that case, it can be shown that we can still use the IPEA to obtain $\varphi$ to an accuracy of $2^{-m}$ with greater than a constant probability independent of $m$ (around $81\%$ [1]).

References

[1] M. Dobsicek et al. Phys. Rev. A 76, 030306 (2007)