I have tried to implement Grover's algorithm for three qubits in python/numpy and the first two iterations work like a charm but the third one starts to diverge. Is this expected, or is there a bug in the code? I expected the inversion around the mean to blow up the coefficient of the marked state in each iteration. The code follows Nielsen closely, with a silly Oracle that hard-codes the negation of the basis state. The Python code requires a little bit of set-up but the essential idea is:
- Define a phase shift operator of -1 on all basis states except zero.
- Define a reflection around the mean operator as Hadamard ⊗ Phase Shift ⊗ Hadamard.
- Define the full Grover step as the Oracle followed by the reflection.
- Start with an equally balanced state.
- Repeatedly apply the Grover step.
Source code:
import numpy as np
def dagger(m):
return np.transpose(np.conjugate(m))
def proj(m):
return m * dagger(m)
# identity matrix for 3 qubits = 8x8 matrix
id3 = np.identity(2**3)
# hadamard matrix for 1, 2 and 3 qubits
H1 = np.matrix([[1.0, 1.0], [1.0, -1.0]], dtype=np.complex256) / np.sqrt(2)
H2 = np.kron(H1, H1)
H3 = np.kron(H2, H1)
# 3 qubit zero vector |000>
zero3 = np.array([[1],[0],[0],[0],[0],[0],[0],[0]], dtype=np.complex256)
# phase shift operator 2*|0><0| - I for 3 qubits
PS3 = 2 * proj(zero3) - id3
# reflection around the mean
R = H3 * PS3 * H3
# 3 qbit oracle, marking/negating state |101> = column vector (0 0 0 0 0 1 0 0)
O = id3
O[5,5] = -1
# grover operator
G = R * O
# start state |000>
x0 = H3 * zero3
# apply grover step three times
x1 = G * x0
print x1
x2 = G * x1
print x2
x3 = G * x2
print x3
The output of the program is shown below. The coefficient (driving the probability) for the state to search for is 0.88 after one iteration, then 0.97 but then falls back to 0.57. Am I missing any essential step in the algorithm?
[[ 0.1767767+0.0j]
[ 0.1767767+0.0j]
[ 0.1767767+0.0j]
[ 0.1767767+0.0j]
[ 0.1767767+0.0j]
[ 0.88388348+0.0j]
[ 0.1767767+0.0j]
[ 0.1767767+0.0j]]
[[-0.088388348+0.0j]
[-0.088388348+0.0j]
[-0.088388348+0.0j]
[-0.088388348+0.0j]
[-0.088388348+0.0j]
[ 0.97227182+0.0j]
[-0.088388348+0.0j]
[-0.088388348+0.0j]]
[[-0.30935922+0.0j]
[-0.30935922+0.0j]
[-0.30935922+0.0j]
[-0.30935922+0.0j]
[-0.30935922+0.0j]
[ 0.57452426+0.0j]
[-0.30935922+0.0j]
[-0.30935922+0.0j]]