-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdiff_cycle_visibility.py
More file actions
327 lines (236 loc) · 10.5 KB
/
diff_cycle_visibility.py
File metadata and controls
327 lines (236 loc) · 10.5 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
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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
import random
import numpy as np
from graph import TannerGraph
from tanner import VariableTannerGraph
from Hmatrixbaby import ParityCheckMatrix
import row_echleon as r
from scipy.linalg import null_space
import sympy as sympy
from itertools import combinations
from pstats import Stats
import re
from cProfile import Profile
from tqdm import tqdm
import matplotlib.pyplot as plt
from protograph_interface import get_Harr_sc_ldpc, get_dv_dc
import sys
from load_saved_codes import get_saved_code
cycle_visibilities = [
0.6003421116458378,
0.5110994804498513,
0.3667743212019863,
0.2716979205228691,
0.22870418831458952,
0.21462399632357634,
0.1748981962546434,
0.10786729131827871
]
def choose_symbols(n_motifs, picks):
""" Returns Symbol Dictionary given the motifs and the number of picks """
# Reference Motif Address starts from 1 not 0
return [list(i) for i in (combinations(np.arange(1, n_motifs+1), picks))]
def coupon_collector_channel(symbol, R, visibility=1):
reads = []
for i in range(R):
if random.random() < visibility:
reads.append(random.choice(symbol))
return reads
def get_symbol_index(symbols, symbol):
for i in symbols:
if set(i) == set(symbol):
return symbols.index(i)
def get_possible_symbols(reads, symbols, motifs, n_picks):
reads = [set(i) for i in reads]
symbol_possibilities = []
for i in reads:
# Will only work for the Coupon Collector Channel
motifs_encountered = i
motifs_not_encountered = set(motifs) - set(motifs_encountered)
read_symbol_possibilities = []
# For the case of distraction
if len(motifs_encountered) > n_picks:
return symbols
if len(motifs_encountered) == n_picks:
read_symbol_possibilities = [get_symbol_index(symbols, motifs_encountered)]
else:
# The symbol possibilites are the motifs that are encountered in combination with the motifs that are not encountered
remaining_motif_combinations = [set(i) for i in combinations(motifs_not_encountered, n_picks - len(motifs_encountered))]
for i in remaining_motif_combinations:
possibe_motifs = motifs_encountered.union(i)
symbols = [set(i) for i in symbols]
if possibe_motifs in symbols:
read_symbol_possibilities.append(get_symbol_index(symbols, motifs_encountered.union(i)))
symbol_possibilities.append(read_symbol_possibilities)
return symbol_possibilities
def simulate_reads(C, read_length, symbols):
""" Simulates the reads from the coupon collector channel """
reads = []
# Simulate one read
cycle_counter = 0
for i in C:
if cycle_counter == 8:
cycle_counter = 0
read = coupon_collector_channel(symbols[i], read_length, cycle_visibilities[cycle_counter])
reads.append(read)
cycle_counter += 1
# Make reads a set
return reads
def read_symbols(C, read_length, symbols, motifs, picks):
reads = simulate_reads(C, read_length, symbols)
return get_possible_symbols(reads, symbols, motifs, picks)
def display_parameters(n_motifs, n_picks, dv, dc, k, n, motifs, symbols, Harr, H, G, C, ffdim):
print("The number of motifs are {}".format(n_motifs))
print("The number of picks are {}".format(n_picks))
print("The dv is {}".format(dv))
print("The dc is {}".format(dc))
print("The k is {}".format(k))
print("The n is {}".format(n))
print("GF{}".format(ffdim))
print("The Motifs are \n{}\n".format(motifs))
print("The Symbols are \n{}\n".format(symbols))
print("The Harr is \n{}\n".format(Harr))
print("The Parity Matrice is \n{}\n".format(H))
print("The Generator Matrix is \n{}\n".format(G))
print("The Codeword is \n{}\n".format(C))
return
def get_parameters(n_motifs, n_picks, dv, dc, k, n, ffdim, display=True, Harr=None, H=None, G=None):
""" Returns the parameters for the simulation """
# Starting adresses from 1
motifs = np.arange(1, n_motifs+1)
symbols = choose_symbols(n_motifs, n_picks)
symbols.pop(-1)
symbols.pop(-2)
symbols.pop(-3)
symbol_keys = np.arange(0, ffdim)
graph = TannerGraph(dv, dc, k, n, ffdim=ffdim)
if Harr is None:
Harr = r.get_H_arr(dc, dv, k, n)
H = r.get_H_Matrix(dc, dv, k, n, Harr)
G = r.parity_to_generator(H, ffdim=ffdim)
graph.establish_connections(Harr)
if np.any(np.dot(G, H.T) % ffdim != 0):
print("Matrices are not valid, aborting simulation")
exit()
input_arr = [random.choice(symbol_keys) for i in range(k)]
# Encode the input array
C = np.dot(input_arr, G) % ffdim
# Check if codeword is valid
if np.any(np.dot(C, H.T) % ffdim != 0):
print("Codeword is not valid, aborting simulation")
exit()
if display:
display_parameters(n_motifs, n_picks, dv, dc, k, n, motifs, symbols, Harr, H, G, C, ffdim)
return graph, C, symbols, motifs
def get_parameters_sc_ldpc(n_motifs, n_picks, dv, dc, k, n, ffdim, display=True, Harr=None, H=None, G=None):
""" Returns the parameters for the simulation """
# Starting adresses from 1
motifs = np.arange(1, n_motifs+1)
symbols = choose_symbols(n_motifs, n_picks)
symbols.pop(-1)
symbols.pop(-2)
symbols.pop(-3)
symbol_keys = np.arange(0, ffdim)
if Harr is None:
Harr, dv, dc, k, n = get_Harr_sc_ldpc(dv, dc, k, n)
else:
dv, dc = get_dv_dc(dv, dc, k, n, Harr)
graph = VariableTannerGraph(dv, dc, k, n, ffdim=ffdim)
graph.establish_connections(Harr)
if H is None and G is None:
H = r.get_H_matrix_sclpdc(dc, dv, k, n, Harr)
G = r.parity_to_generator(H, ffdim=ffdim)
if np.any(np.dot(G, H.T) % ffdim != 0):
print("Matrices are not valid, aborting simulation")
exit()
input_arr = [random.choice(symbol_keys) for i in range(k)]
# Encode the input array
C = np.dot(input_arr, G) % ffdim
# Check if codeword is valid
if np.any(np.dot(C, H.T) % ffdim != 0):
print("Codeword is not valid, aborting simulation")
exit()
if display:
display_parameters(n_motifs, n_picks, dv, dc, k, n, motifs, symbols, Harr, H, G, C)
return graph, C, symbols, motifs
def run_singular_decoding(graph, C, read_length, symbols, motifs, n_picks):
reads = simulate_reads(C, read_length, symbols)
# Convert to possible symbols
possible_symbols = read_symbols(C, read_length, symbols, motifs, n_picks)
#possible_symbols = get_possible_symbols(reads, symbol_arr)
# Assigning values to Variable Nodes
graph.assign_values(possible_symbols)
decoded_values = graph.coupon_collector_decoding()
# Check if it is a homogenous array - if not then decoding is unsuccessful
if sum([len(i) for i in decoded_values]) == len(decoded_values):
if np.all(np.array(decoded_values).T[0] == C):
print("Decoding successful")
return np.array(decoded_values).T[0]
else:
print("Decoding unsuccessful")
return None
def frame_error_rate(k, n, dv, dc, graph, C, symbols, motifs, n_picks, iterations=50, uncoded=False, bec_decode=False, label=None, code_class=""):
""" Returns the frame error rate curve - for same H, same G, same C"""
starting_read, ending_read = 16, 28
read_lengths = np.arange(starting_read, ending_read)
frame_error_rate = []
for i in tqdm(read_lengths):
counter = 0
for j in tqdm(range(iterations)):
# Assigning values to Variable Nodes after generating erasures in zero array
symbols_read = read_symbols(C, i, symbols, motifs, n_picks)
if not uncoded:
graph.assign_values(read_symbols(C, i, symbols, motifs, n_picks))
if bec_decode:
decoded_values = graph.coupon_collector_erasure_decoder()
else:
decoded_values = graph.coupon_collector_decoding()
else:
decoded_values = symbols_read
# Getting the average error rates for iteration runs
if sum([len(i) for i in decoded_values]) == len(decoded_values):
if np.all(np.array(decoded_values).T[0] == C):
counter += 1
error_rate = (iterations - counter)/iterations
frame_error_rate.append(error_rate)
plt.plot(read_lengths, frame_error_rate, 'o')
plt.plot(read_lengths, frame_error_rate, label=label)
plt.title("Frame Error Rate for CC for {}{}-{} {}-{} for 8C4 Symbols".format(code_class, k, n, dv, dc))
plt.ylabel("Frame Error Rate")
plt.xlabel("Read Length")
# Displaying final figure
plt.xlim(starting_read, ending_read)
plt.ylim(0,1)
plt.xticks(np.arange(starting_read, ending_read, 1))
plt.grid()
plt.legend()
return frame_error_rate
def run_fer(n_motifs, n_picks, dv, dc, k, n, L, M, ffdim, code_class="", iterations=10, bec_decoder=False, uncoded=False, saved_code=False, singular_decoding=True):
Harr, H, G = None, None, None
if saved_code:
Harr, H, G = get_saved_code(dv, dc, k, n, L, M, code_class=code_class)
if code_class == "sc_":
graph, C, symbols, motifs = get_parameters_sc_ldpc(n_motifs, n_picks, dv, dc, k, n, ffdim, display=False, Harr=Harr, H=H, G=G)
else:
graph, C, symbols, motifs = get_parameters(n_motifs, n_picks, dv, dc, k, n, ffdim, display=False, Harr =Harr, H=H, G=G)
if singular_decoding:
run_singular_decoding(graph, C, 8, symbols, motifs, n_picks)
print(frame_error_rate(k, n, dv, dc, graph, C, symbols, motifs, n_picks, iterations=iterations, label=f'CC Decoder', code_class=code_class))
if bec_decoder:
print(frame_error_rate(graph, C, symbols, motifs, n_picks, iterations=100, bec_decode=True, label='BEC Decoder'))
if uncoded:
print(frame_error_rate(graph, C, symbols, motifs, n_picks, iterations=100, uncoded=True, label='Uncoded'))
plt.show()
if __name__ == "__main__":
with Profile() as prof:
n_motifs, n_picks = 8, 4
dv, dc, ffdim = 3, 9, 67
k, n = 612, 1020
L, M = 10, 102
read_length = 6
run_fer(n_motifs, n_picks, dv, dc, k, n, L, M, ffdim, code_class="sc_", saved_code=True, singular_decoding=False, iterations=50)
(
Stats(prof)
.strip_dirs()
.sort_stats("cumtime")
.print_stats(10)
)