-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfresh-qc-sim.py
230 lines (211 loc) · 8.1 KB
/
fresh-qc-sim.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
import numpy as np
import random
import math
import cmath #so eval can work w/ complex #s
from datetime import datetime #for output file
import os #for directory stuff
#file input vs. cli interface handling -> edit so it can accomodate noise
input_mode = input('file input or cli input? ')
if input_mode == 'file':
file_contents = []
file_name = input('file name: ')
with open(file_name, 'r') as file:
for i in file:#make sure i is each new line
file_contents.append(i.strip('\n'))
file_commands = file_contents[3:]
qnum = int(file_contents[0])
simulation_type = file_contents[1]
z_or_o = file_contents[2]
else:
qnum = int(input("How many qubits: "))
simulation_type = input("ideal or nonideal simulation: ")
z_or_o = input('would you like to start in the 0 or 1 state: ')
zero_state = np.matrix([[1],[0]])
one_state = np.matrix([[0],[1]])
iterate = 1
while iterate <= qnum:
if iterate == 1:
if z_or_o == '0':
x = zero_state
elif z_or_o == '1':
x = one_state
if iterate == qnum:
qstat = x
print(qstat)
else:
x = np.kron(x,zero_state)
iterate+=1
basis_states = []
for i in range(0, 2**qnum):
basis_states.append(bin(i)[2:].zfill(qnum))
done = 'n'
things_done = []
gates = {}
def record(name):
things_done.append(name)
#for 'j' write '1j'
def custom_gate(dimension):
value_hold = []
for y in range(dimension):
for x in range(dimension):
element = input('What value for position ({}, {}): '.format(y+1, x+1))
element = element.strip("\"\'\\\/") #sanitizes input
value_hold.append(eval(element))
matrix = np.matrix(np.resize(value_hold, (dimension, dimension)))
if np.allclose(np.dot(matrix, matrix.conj().T), np.eye(dimension)):
try:
save = input("Would you like to save this gate? y or n: ")
if save == 'y':
save_gate(matrix)
else:
matrix_name = input("Please input matrix name: ")
gates[matrix_name] = matrix
record(matrix_name)
return np.dot(matrix, qstat)
except ValueError:
print("not same size as vector, not applying")
return qstat
else:
print("Invalid gate (not unitary), not applying")
return qstat
def save_gate(matrix):
matrix_name = input('please input a name for your matrix: ')
record(matrix_name)
gates[matrix_name] = matrix#add folder stuff
np.savetxt(matrix_name+'.txt', matrix, delimiter=',')
def apply(matrix, qstat):
try:
return np.dot(matrix, qstat)
except ValueError:
print("not same size as vector, not applying")
return qstat
def norm(qstat):
return math.sqrt(sum(float(i)**2 for i in qstat))
def normalize(qstat):
norm_result = norm(qstat)
return np.dot(1/(norm_result),qstat)
def projection(acceptable_stats):
#create qnum*qnum diagonal matrix
diag_gen = []
for i in range(0, qnum**2):
diag_gen.append(1)
diagonal_matrix = np.diag(diag_gen)
#list of indexes of allowed states
position_nums = []
for i in acceptable_stats:
position_nums.append(basis_states.index(i))
#modify diagonal matrix to comply with list
for i in range(0, qnum**2):
if i not in position_nums:
for k in range(0, qnum**2):
diagonal_matrix[i][k] = 0
return diagonal_matrix
def probability(qstat, qnum_index):
amplitude = np.array(qstat)[qnum_index][0]
prob = abs(amplitude)**2
return prob
#measurement in different bases?
def measurement(qstat, qnum_meas="all"):
if qnum_meas != "all":
qnum_meas = int(qnum_meas)
zero_prob = 1 - probability(qstat, qnum_meas-1)
rand = random.random()
acceptable_stats = []
if rand < zero_prob:
#zero
print(qnum_meas,' qubit measured as zero')
record(str(qnum_meas)+' qubit measured as zero')
for i in basis_states:
if i[qnum_meas-1] == '0':
acceptable_stats.append(i)
else:
#one
print(qnum_meas,' qubit measured as one')
record(str(qnum_meas)+' qubit measured as one')
for i in basis_states:
if i[qnum_meas-1] == '1':
acceptable_stats.append(i)
projection_result = projection(acceptable_stats)
return normalize(np.dot(projection_result, qstat))
else:
probabilities = []
for i in qstat:
probabilities.append(probability(qstat, np.where(qstat==i)[0][0]))
rand_int = random.random()
zero_vector = np.zeros((qnum**2, 1))
counter = 0
for i in probabilities:
if rand_int < sum(probabilities[:counter+1]):
zero_vector[counter][0] = 1
return zero_vector
counter+=1
#actual running...add 'if' for file/cli input
if input_mode == 'cli':
if simulation_type == 'ideal':
while done == 'n':
next_item = input("custom gate or measurement or import or prev used: ")
if next_item == 'measurement':
measure_num = input('input all or which qubit num you would like measured: ')
qstat = measurement(qstat, measure_num)
record('measurement: '+measure_num)
print(qstat)
elif next_item == 'import':
file_read = input("input file name you would like to read: ")
try:#add folder stuff
matrix_load = np.loadtxt(file_read, delimiter=',')
gates[file_read[:file_read.index('.')]] = matrix_load
print(gates)
try:
matrix = input("which gate from your file would you like to use: ")
qstat = apply(gates[matrix], qstat)
record(matrix)
except KeyError:
print('this gate does not seem to have been saved in the past. try custom gate')
print(qstat)
except FileNotFoundError:
print("file not found, check your spelling")
elif next_item == 'prev used':
print('list of gates: ',gates)
matrix = input("please input the matrix name: ")
try:
qstat = apply(gates[matrix],qstat)
print(qstat)
record(matrix)
except KeyError:
print("this gate does not seem to have been saved in the past. try custom gate")
else:
dimension = int(input("Please give the size of your gate: "))
qstat = custom_gate(dimension)
print(qstat)
done = input("Done with your qubits? y or n: ")
#consider having user import decoherence times they wish, but own noise function
#nothing special has to be done for error correction?
#how do decohered qubits affect other decohered qubits?
else:
print('this is not done yet; sorry!')#maybe turn this into a flag instead
#of an else statement so it works w/ file run too
else:
#file input run
for i in file_commands:
if 'measure' in i:
if any(k.isdigit() for k in i):
num = i.strip('measurement\n ')
qstat = measurement(qstat, num)
else:
qstat = measurement(qstat, 'all')
else:
matrix_load = np.loadtxt(i, delimiter=',')#add folder stuff
qstat = apply(matrix_load, qstat)
record(i)
#provides output
print("end state: ", qstat)
record("end state: "+str(qstat))
for i in basis_states:
print('probability of |'+i+'> on measurement: ', probability(qstat, basis_states.index(i)))
record('probability of |'+i+'> on measurement: '+str(probability(qstat, basis_states.index(i))))
#create text file from record list
filename = str(datetime.now())+'-qc-sim-run.txt'
with open(filename, 'w') as file:#add folder stuff??
file.write(str(datetime.now())+'\n')
for i in things_done:
file.write(i+'\n')