-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathUserDemo.py
301 lines (252 loc) · 9.62 KB
/
UserDemo.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
"""
This module serves as a demonstration for the multiple tasks our implementation constists of. It includes Benchmarks between using SparseMatrices, LazyMatrices and
numpy arrays. It allows the user through prompts to navigate through our programs.
"""
from QuantumCircuit import *
import Presentation
from Circuit import *
import numpy as np
import matplotlib.pyplot as plt
import time
import Sparse
def timeBenchmarks():
"""
Runs Benchmarks for Grover's algorithm for both the Circuit-Builder implementation and the Pre-defined Circuit implementation.
It also plots a graph for comparison.
"""
max_qbits = 8 # the limit of sparse matrices
qbits = np.arange(2,max_qbits +1,1)
times = np.zeros((3,len(qbits)))
for q in qbits:
t1 = time.time()
Presentation.Grover_Circuit(q, [3], plot_results=False)
t2 = time.time()
times[0,q-2] = t2-t1
t1 = time.time()
Presentation.LazyGroverDemo(q, [3], plot_results=False)
t2 = time.time()
times[1,q-2] = t2-t1
t1 = time.time()
g = Grover()
g.run_circuit(q,1,'m')
t2 = time.time()
times[2,q-2] = t2-t1
plt.plot(qbits, times[0], label='Sparse')
plt.plot(qbits, times[1], label='Lazy')
plt.plot(qbits, times[2], label='Numpy')
plt.title("Runtime of Grover's Algorithm over Number of Qubits in the system")
plt.xlabel("Number of Qubits")
plt.ylabel("Runtime (s)")
plt.yscale("log")
plt.legend()
plt.show()
def tensorTest():
"""
Checks the runtime of computing the Tensorproduct in three different ways. First using our own Lazy Matrix Implementation, second
using Numpy Tensor Product of Gates and third using Numpy Tensor Product of individual qubits.
"""
# Change this depending on memory on computer used to run this.
max_qubits = 14
qbits = np.arange(2,max_qubits + 1,1)
times = np.zeros((3,len(qbits)))
had = Sparse.ColMatrix(2)
had[0,0] = 1/np.sqrt(2)
had[0,1] = 1/np.sqrt(2)
had[1,0] = 1/np.sqrt(2)
had[1,1] = -1/np.sqrt(2)
for q in qbits:
print(f"\nChecking the time it takes for each of the two implementations\nto do a tensor product of {q} items:")
qbit_zero = Qubit(1,0)
reg = []
for i in range(q):
reg.append(qbit_zero)
state = Tensor(reg)
state = state.to_state()
test_vector = np.copy(state.vector)
t1 = time.time()
for i in range(q):
gate = Sparse.Gate(2**q, had, [i])
test_vector = gate.apply(test_vector) # apply the hadamards to register?
t2 = time.time()
print(f"\nResult 1 :\n {test_vector} ")
print(f"Time taken : {t2-t1} ")
times[0,q-2] = t2-t1
t1 = time.time()
reg = []
h_gate = Gate("Hadamard")
for i in range(q):
reg.append(h_gate)
register = Tensor(reg)
big_gate = register.to_gate("Biggie") # basically what creates the Memory error
state.apply_gate(big_gate)
t2 = time.time()
print(f"\nResult 2 :\n {state.vector.T} ")
print(f"Time taken : {t2-t1} ")
times[1,q-2] = t2-t1
t1 = time.time()
qbit_zero = Qubit(1,0)
reg = []
h_gate = Gate("Hadamard")
qbit_zero.apply_gate(h_gate)
for i in range(q):
reg.append(qbit_zero) # doing it this way is much faster and gives the same result
register = Tensor(reg)
state = register.to_state()
t2 = time.time()
print(f"\nResult 3 :\n {state.vector.T} ")
print(f"Time taken : {t2-t1} ")
times[2,q-2] = t2-t1
plt.plot(qbits, times[0], label='Lazy')
plt.plot(qbits, times[1], label='Numpy (Tensor Product of Gates)')
plt.plot(qbits, times[2], label='Numpy (Tensor Product of Qubits)')
plt.title("Runtime of Tensor product over Number of Qubits in the system")
plt.xlabel("Number of Qubits")
plt.ylabel("Runtime (s)")
plt.yscale("log")
plt.xticks(qbits)
plt.legend()
plt.show()
def compareProbabilities():
"""
Compares the two implementations to make sure that they give the same states for Grover's algorithm search.
"""
lazy_max_measures = []
numpy_max_measures = []
# 2-9 qubits
measured_bits = 1
for n_qubits in range(2,8):
lazy_max_measures.append([])
grover_circuit = QuantumCircuit('Grover', n_qubits)
repetitions = int(np.pi/4*np.sqrt(2**n_qubits)) - 1
grover_circuit.addGate('h', [i for i in range(n_qubits)])
grover_circuit.addmeasure()
# calculate oracle
oracle = Sparse.ColMatrix(2**n_qubits)
for i in range(2**n_qubits):
if i in [measured_bits]:
oracle[i,i] = -1
else: oracle[i,i] = 1
#Add Oracle
grover_circuit.addCustom(0, n_qubits-1, oracle, 'oracle')
#Add diffuser
Presentation.diffuser(grover_circuit)
grover_circuit.addmeasure()
# Repeat if necessary
for i in range(repetitions):
# Add Oracle
grover_circuit.addCustom(0, n_qubits-1, oracle, 'oracle')
#Add diffuser
Presentation.diffuser(grover_circuit)
grover_circuit.addmeasure()
#show results
final_statevec, measurements = grover_circuit.lazysim()
for m in measurements[1]:
lazy_max_measures[n_qubits-2].append(max(m*m.conj()))
g = Grover()
iter, success, desired_amps = g.run_circuit(n_qubits, 1,'testing')
numpy_max_measures.append(desired_amps)
print("Checking if the two implementations produce the same results:")
print(f"\nResult 1 :")
print(np.array(lazy_max_measures, dtype=object))
print(f"\nResult 2 :")
print(np.array(numpy_max_measures, dtype=object))
def BorD_prompt():
"""
A function to prompt for benchmark or demonstration.
"""
BorD = input("\nPlease type 'd' for Demonstrations or 'b' for Benchmarks: ")
if(BorD=='b'):
BorD = "benchmarks"
print("Benchmarks")
elif(BorD=='d'):
BorD = "demo"
print("Demonstration")
else:
print("Invalid entry. Please try again.")
BorD = BorD_prompt()
return BorD
def builder_prompt():
"""
A function to prompt for circuit-builder or pre-built circuits.
"""
build = input("\nPlease type 'p' for pre-built circuits or 'b' for circuit-builder: ")
if(build=='p'):
print("Pre-built circuits")
build = circuit_prompt()
elif(build=='b'):
build = 'builder'
print("Circuit builder")
else:
print("Invalid entry. Please try again.")
build = builder_prompt()
return build
def circuit_prompt():
"""
A function to prompt for specific pre-built circuits.
"""
circ = input("\nPlease type 'b' for Bell States circuit, 'g' for Grover circuit,\nor 't' for Teleportation circuit:")
while(circ!='b' and circ!='g' and circ!='t'):
print("Invalid entry. Please try again.")
circ = circuit_prompt()
if circ=='b':
circ = "Bell States"
elif circ=='g':
circ = "Grover"
elif circ=='t':
circ = "Teleportation"
return circ
def custom_builder_prompt():
"""
Function to determine which circuit to build for the user.
"""
circ = input("\nWhich circuit would you like to build?\nType 'g' for Grover's circuit or 'BV' for a Bernstein-Vazirani circuit.\n")
if circ=='g':
return circ
if circ=='BV':
return circ
else:
print('Invalid entry')
return custom_builder_prompt()
def actual_builder(algorithm):
"""
Function which builds the circuit as prompted by the user.
"""
if algorithm=='g':
size = int(input("\nPlease enter the size of the desired circuit\n"))
state = int(input("\nPlease enter the desired state\n"))
if state<2**size:
Presentation.LazyGroverDemo(size, [state])
else:
print("\nSomething went wrong. \nThe desired state might be out of bounds")
actual_builder('grover')
elif algorithm=='BV':
mystery_string = str(input("\nPlease enter a mystery bitstring (i.e. a bunch of 1s and 0s)"))
Presentation.Ber_Vaz(mystery_string)
print("Your mystery string was:", mystery_string)
print("Does it match the qubits in the register?")
if __name__ == '__main__':
BorD = BorD_prompt()
if(BorD=='benchmarks'):
tensorTest()
input("\nPress any key for the next test...")
compareProbabilities()
input("\nPress any key for the next test...")
timeBenchmarks()
elif(BorD=='demo'):
build = builder_prompt()
stop = False
while(not stop):
if(build!= 'builder'):
circ = Circuit(build)
circ.run_circuit()
esc = input("\nPress any key for another circuit or 's' to stop... ")
if esc=="s":
stop = True
else:
build = circuit_prompt()
else:
toBuild = custom_builder_prompt()
actual_builder(toBuild)
esc = input("\nPress any key for another circuit or 's' to stop... ")
if esc=="s":
stop = True