# Quantum Phase Estimation implementation

I tried implementing quantum phase estimation in qiskit, however, I'm not getting the expected results.

I choose a controlled $$U1$$ gate.

First of, I implemented inverse QFT operation (basically a rewrite of the textbook version in a way that I understand better) :

def qft_dagger(circ, q, n):
"""n-qubit inverse QFT on q in circ."""
for i in range(n-1,-1,-1):
for m in range(n-i,1,-1):
circ.cu1(-2*math.pi/2**m, q[i+m-1], q[i])
circ.h(q[i])
circ.barrier()


Then, the n-qubit hadamard operation :

def n_hadamard(circ, q, n):
"apply n qubits hadamard in circ on q"
for i in range(n):
circ.h(q[i])


Then a function to initiate state vector :

def build_state_vector(circ, inp, s):
"build state vector in circ from inp a binary string"
for i, e in enumerate(inp):
if e == '1':
circ.x(s[i])


Then, the code of my experiment goes as follow :

nancilla = 3
theta = 0.78
q = QuantumRegister(nancilla, 'q')
s = QuantumRegister(1, 's')
c = ClassicalRegister(nancilla, 'c')

qpe = QuantumCircuit(q, s, c)

build_state_vector(qpe, '1', s)

for i in range(nancilla):
#Applying U^(2^(n-j)) on qubit j
qpe.cu1(2*math.pi*theta*2**(nancilla-i-1), q[i], s[0])

# Applying inverse QFT
qft_dagger(qpe, q, nancilla)

for i in range(nancilla):
qpe.measure(q[i],c[i])

backend = BasicAer.get_backend('qasm_simulator')
shots = 2**17
results = execute(qpe, backend=backend, shots=shots).result()


For instance, here, I get as a result 0.25 when I should get 0.75. When increasing the number of ancilla qubits, the result don't get better.

I feel like there is something wrong in my implementation, but I have looked at every part separately and I can't tell what is wrong.

• What output string result do you get? You say you get a result 0.25 (I assume this means 25% of the time) but you don't say what output you received and what output you were expecting. – Matthew Stypulkoski Dec 18 '19 at 20:06
• No, what I mean is that given the input state $\Psi = |1\rangle = 1$ I expect to get $x = 2^n \theta$ where $\theta = 0.75$ (because my angle is $0.78$) and what I get is $\theta = 0.25$ i.e. $x = 2^n 0.25 = 2 = 010$. – servabat Dec 18 '19 at 20:31
• Oh ok. so the output you expect with this $\theta$ = 0.75 would be 6 (110), right? – Matthew Stypulkoski Dec 18 '19 at 20:49
• Yes, that's right – servabat Dec 18 '19 at 20:58
• When I use the qft_dagger implementation directly from the textbook with the rest of your code it looks like it returns the expected result. So there may be something inconsistent in your qft_dagger function – Matthew Stypulkoski Dec 18 '19 at 21:04

3 things I see from your implementation of inverse QFT:

1. SWAP gates are missing prior to applying Hadamard gates and cu1 gates.
2. The Hadamard gate should come first before cu1 gates.
3. The angles of cu1 gates, how I understand inverse QFT, should be different.

Here is inverse QFT that worked for me with not touching other parts of the code:

def qft_dagger(circ, q, n):
"""n-qubit inverse QFT on q in circ."""
# SWAP gates
for i in range(n//2):
circ.swap(q[i], q[n - i - 1])

for i in reversed(range(n)):
circ.h(q[i])
for m in reversed(range(i)):
circ.cu1(-2*np.pi/2**(i - m + 1), q[i], q[m])
circ.barrier()


For 0.75 I obtained: 011, 0.875: 111, 0.5: 001, 0.25: 010.

For more info see Figure 5.1. from the M.A. Nielsen and I.L. Chuang's book.

It shows the circuit for QFT without SWAP gates. From the book "Not shown are swap gates at the end of the circuit which reverse the order of the qubits".

The inverse QFT should be the same gates but in reversed order with their daggered versions. Note that $$H^{\dagger} = H$$, $$u1^{\dagger} (\lambda) = u1(-\lambda)$$ and $$R_k$$ in the book corresponds to $$R_k = u1(2 \pi / 2^{k})$$.

• Indeed, your qft function resolve the problems, and it works as expected. However, I fail to understand why. As you say, the inverse QFT should be the same gates in reversed order, which mean that the $H$ gates should appear after the $R_z$ gates. Moreover, from what I understand, the swap gates should only be there to correct the endianess, which mean that by reversing the order in which the $C-U^{2^k}$ gates are applied, it should solve the problem. – servabat Jan 5 '20 at 21:49
• Exactly!! If you want you can reverse the order of controlled unitaries and delete the swap gates and you will obtain the same result. BTW I like this solution more because you don't use extra/useless/error-prone swap gates. In this case, you will not use inverse QFT. You can still call it inverse QFT, but it is not :) – Davit Khachatryan Jan 5 '20 at 22:49
• in QFT last gate (not including swaps) is $H$, so the first for inverse QFT should be also $H$. – Davit Khachatryan Jan 5 '20 at 22:54
• In the code, the inverse QFT is not exactly the reversed version of QFT...in the reversed version one should apply $H[j_n]$, $CR_z[j_n, j_{n-1}]$, $H[j_n-1]$.... while in the code we have $H[j_n]$, $CR_z[j_n, j_{n-1}]$, $CR_z[j_n, j_{n-2}]$...$CR_z[j_n, j_{0}]$, $H[j_n-1]$ .... Don't know why, but I feel that they do the same thing :). Need to think more why it works :) – Davit Khachatryan Jan 5 '20 at 23:02
• I think I understand why it works :) because one can change the order of any $CR_z[i, j]$ and $H[k]$, where $i \ne j \ne k$. You can check it with writing an arbitrary 3 qubit state $a_0 |000> + a_1|001> + a_2 |010> + ...$ and try apply $H[1]$, then $CR_z(0,2)$ and $CR_z(0,2)$, then $H[1]$. You will see that they do the same job. So, you can reorder gates in inverse QFT and see that it can be implemented in the gate order that is presented in the code. – Davit Khachatryan Jan 5 '20 at 23:30