-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathqft.py
130 lines (108 loc) · 3.76 KB
/
qft.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
'''
Quantum Implementations of:
1. Fourier Transform
2. Inverse Fourier Transform
'''
import numpy as np
import math
from typing import Tuple, List
from pyquil import Program
from pyquil.gates import *
from pyquil.quilatom import QubitPlaceholder
from pyquil.api import WavefunctionSimulator
from pyquil.quil import address_qubits, DefGate
########################################
# For Reference
########################################
def classical_qft(j, d):
k_vec = lambda k : np.array([0 if i != k else 1 for i in range(d)])
omega = 2.0 * np.pi * 1j / d
return (1.0 / np.sqrt(d)) * np.sum([omega ** (k * j) * k_vec(k) for k in range(d)])
def classical_iqft(j, d):
k_vec = lambda k : np.array([0 if i != k else 1 for i in range(d)])
omega = 2.0 * np.pi * 1j / d
return (1.0 / np.sqrt(d)) * np.sum([omega ** (-k * j) * k_vec(k) for k in range(d)])
########################################
# Helper PyQuil Wrappers
########################################
# Reference: http://www-bcf.usc.edu/~tbrun/Course/lecture13.pdf (Page 10)
def Rk_mat(k):
return np.array([[1, 0], [0, (2*np.pi*1j) / (2**k)]])
def RK_gate(k):
# Get the Quil definition for the new gate
Rk_definition = DefGate("Rk", Rk_mat(k))
# Get the gate constructor
RK = Rk_definition.get_constructor()
return RK, Rk_definition
# Reference: https://courses.edx.org/c4x/BerkeleyX/CS191x/asset/chap5.pdf (Page 2)
def QFT_mat(n):
omega = np.exp(2.0 * np.pi * 1j / n)
mat = np.ones((n, n), dtype=complex)
for i in range(1, n):
for j in range(1, n):
mat[i, j] = omega ** (i * j)
mat /= math.sqrt(float(n))
return mat
def QFT_gate(n):
# Get the Quil definition for the new gate
QFT_definition = DefGate("QFT{}".format(n), QFT_mat(2 ** n))
# Get the gate constructor
QFT = QFT_definition.get_constructor()
return QFT, QFT_definition
def IQFT_mat(n):
omega = np.exp(2.0 * np.pi * 1j / n)
mat = np.ones((n, n), dtype=complex)
for i in range(1, n):
for j in range(1, n):
mat[i, j] = omega ** (-i * j)
mat /= math.sqrt(float(n))
#print(mat.shape)
return mat
def IQFT_gate(n):
# Get the Quil definition for the new gate
IQFT_definition = DefGate("IQFT{}".format(n), IQFT_mat(2 ** n))
# Get the gate constructor
IQFT = IQFT_definition.get_constructor()
return IQFT, IQFT_definition
########################################
# Quantum Implemenations
########################################
# Fourier Transform
def qft(phi, n):
pq = Program()
QFT, QFT_definition = QFT_gate(n)
pq += QFT_definition
if isinstance(phi, List):
pq += QFT(*phi) #Program("QFT({}) {}".format(n, *phi)) #QFT(*phi)
else:
pq += QFT(phi) #Program("QFT({}) {}".format(n, phi)) #QFT(phi)
return pq
# Inverse Fourier Transform
def iqft(phi, n):
pq = Program()
IQFT, IQFT_definition = IQFT_gate(n)
pq += IQFT_definition
if isinstance(phi, List):
pq += IQFT(*phi) #Program("IQFT({}) {}".format(n, *phi)) #IQFT(*phi)
else:
pq += IQFT(phi) #Program("IQFT({}) {}".format(n, phi)) #IQFT(phi)
return pq
########################################
# Tests
########################################
def init_pure(p: List[QubitPlaceholder]) -> Program:
pq = Program()
for i in range(len(p)):
pq += X(p[i])
return pq
def qft_tests(n=4):
phi = [QubitPlaceholder() for i in range(n)]
tests = [
init_pure(phi) + H(phi[0]) + qft(phi, n) + iqft(phi, n), # Should be H(0)
init_pure(phi) + iqft(phi, n) + qft(phi, n), # Should be pure |1>'s
]
wf_sim = WavefunctionSimulator()
for test in tests:
print(wf_sim.wavefunction(address_qubits(test)))
if __name__ == "__main__":
qft_tests()