-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherrors.py
More file actions
185 lines (160 loc) · 6.99 KB
/
errors.py
File metadata and controls
185 lines (160 loc) · 6.99 KB
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
"""
Load a error model for the specified parameters.
The error model must be in the folder data/ following the name format
stablished by decomposition/tools/names.py.
author: Eduardo Villasenor
created-on: 21/08/17
"""
import numpy as np
import pickle
from os.path import dirname, realpath
import decomposition.tools.names as names
# Pauli errors on stabilizer representation
I, X, Y, Z = [1, 1], [1, -1], [-1, -1], [-1, 1]
class Generator:
def __init__(self, surface, ps, pm, pg, eta, a0, a1, theta, protocol):
"""Init function.
Parameters
----------
surface : (string) planar or toric code
ps : (scalar) single qubit gate error rate.
pm : (scalar) measurement error rate.
pg : (scalar) two qubit gate error rate.
eta : (scalar) detection efficiency.
a0 : (scalar) extra environmental error when electron spin is being operated.
a1 : (scalar) default environmental error.
theta : (scalar) determines how the states are initialized when generating remote
entanglement.
protocol : (string) name of the protocol used in generating the states
"""
chi_star = self._load_model(ps, pm, pg, eta, a0, a1, theta,
4, "X", protocol)
chi_plaq = self._load_model(ps, pm, pg, eta, a0, a1, theta,
4, "Z", protocol)
self.chi = [chi_star, chi_plaq]
self.chi_keys = [np.array(list(chi_star.keys())),
np.array(list(chi_plaq.keys()))]
self.chi_vals = [np.array(list(chi_star.values())),
np.array(list(chi_plaq.values()))]
self.errors = [self._symbol_to_error_list(self.chi_keys[0]),
self._symbol_to_error_list(self.chi_keys[1])]
self.indexes = range(len(self.chi_keys[0]))
if surface == "planar":
chi_star_border = self._load_model(ps, pm, pg, eta, a0, a1, theta,
3, "X", protocol)
chi_plaq_border = self._load_model(ps, pm, pg, eta, a0, a1, theta,
3, "Z", protocol)
self.chi_border = [chi_star_border, chi_plaq_border]
self.chi_keys_border = [np.array(list(chi_star_border.keys())),
np.array(list(chi_plaq_border.keys()))]
self.chi_vals_border = [np.array(list(chi_star_border.values())),
np.array(list(chi_plaq_border.values()))]
self.errors_border = [self._symbol_to_error_list(self.chi_keys_border[0], True),
self._symbol_to_error_list(self.chi_keys_border[1], True)]
self.indexes_border = range(len(self.chi_keys_border[0]))
# self.n_NOK = 0
# self.n_E = 0
def _generate_name(self, ps, pm, pg, eta, a0, a1, theta, stab_size, parity, protocol):
"""Name for CHI matrix file."""
file_name = names.chi(ps, pm, pg, eta, a0, a1, theta,
stab_size, parity, protocol)
return file_name
def _load_model(self, ps, pm, pg, eta, a0, a1, theta, stab_size, parity, protocol):
# Load a file with a error model in a dictionary
file_name = self._generate_name(ps, pm, pg, eta, a0, a1, theta,
stab_size, parity, protocol)
# try:
pickle_in = open(file_name, "rb")
return pickle.load(pickle_in)
# except:
# raise NameError("Model file not found: " + file_name)
def get_errors(self, num_errors, stabilizer, border=False):
"""
Get a list of errors corresponding to the loaded error model.
Paramaters
-----------
num_errors : (int) number of stabilizers measured on which errors are
applied
stabilizer : (string) plaq or star, type of the stabilizer measured
border : (bool) if the stabilizer measured is in the border of the
planar code
"""
if stabilizer == "star":
c = 0
elif stabilizer == "plaq":
c = 1
if border:
i = self.indexes_border
v = self.chi_vals_border[c]
e = self.errors_border[c]
else:
i = self.indexes
v = self.chi_vals[c]
e = self.errors[c]
e_index = np.array(np.random.choice(i, num_errors, p=v))
m_errors = e[0][e_index]
q_errors = e[1][:, :, e_index]
# Debug stuff
# kk = self.chi_keys[c][e_index].tolist()
# self.n_NOK += kk.count('IIII_NOK')
# self.n_E += num_errors - kk.count('IIII_NOK') - kk.count('IIII_OK')
# print("Errors -------------------------> NOK: ", kk.count('IIII_NOK'), "E: ", num_errors - kk.count('IIII_NOK') - kk.count('IIII_OK'))
# print(kk)
# Shuffle qubit errors to restore the lost permutations
# NOTE: shuffle works on the list pointers
for x in q_errors.transpose((2, 0, 1)):
np.random.shuffle(x)
# Change axes to make it manageable
q_errors = q_errors.transpose((1, 0, 2))
# Qubit errors format:
# array([[[ 1., -1.],
# [ 1., -1.]],
#
# [[ 1., 1.],
# [ 1., 1.]], All 4 data qubits for each stabilizer
# q_errors[0] gives the error for all qubits
# [[ 1., -1.], on top of the stabilizer.
# [ 1., 1.]], q_errors[1] for the bottom and so on.
#
# [[ 1., 1.],
# [ 1., 1.]]])
return m_errors, q_errors
def _symbol_to_error_list(self, symbol_list, border=False):
# Transform the symbols in the error dictionary to lists with the
# corresponding errors
N = len(symbol_list)
if border:
d_qubits = 3
else:
d_qubits = 4
# Create lists to save the errors
qubit_errs = np.ones((d_qubits, 2, N))
measurement_errs = np.ones(N)
# Iterate through the error filling the lists with the corresponding
# values
for i in range(N):
m, q = self._symbol_to_error(symbol_list[i])
measurement_errs[i] *= m
qubit_errs[:, :, i] *= q
return [measurement_errs, qubit_errs]
def _symbol_to_error(self, symbol):
# Tansform a errror symbol into a list representation
if "N" in symbol:
measurement = -1
symbol = symbol.replace("_NOK", "")
else:
measurement = 1
symbol = symbol.replace("_OK", "")
l_symbol = list(symbol)
errors = [self._pauli_error(s) for s in l_symbol]
return measurement, errors
def _pauli_error(self, s):
# Individual string to list representation
if s == "I":
return I
elif s == "X":
return X
elif s == "Y":
return Y
elif s == "Z":
return Z