codedistance 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
codedistance/common.py ADDED
@@ -0,0 +1,566 @@
1
+ import numpy as np
2
+ import itertools as iter
3
+ import sys
4
+ import time
5
+
6
+ #######################################
7
+ ## Sorting and Indexing
8
+ #######################################
9
+
10
+ def argsort(seq,reverse=False):
11
+ '''Argsort but allowing for sorting of tuples'''
12
+ # http://stackoverflow.com/questions/3071415/efficient-method-to-calculate-the-rank-vector-of-a-list-in-python
13
+ return sorted(range(len(seq)), key=seq.__getitem__,reverse=reverse)
14
+
15
+ def argmin(seq,reverse=False):
16
+ '''Argsort but allowing for sorting of tuples'''
17
+ # http://stackoverflow.com/questions/3071415/efficient-method-to-calculate-the-rank-vector-of-a-list-in-python
18
+ compfun = max if reverse else min
19
+ return compfun(range(len(seq)), key=seq.__getitem__)
20
+
21
+ def ixRev(ix):
22
+ ## return indices to restore original column order
23
+ ## input: ix - permutation of [0..n-1]
24
+ ## output: ixR such that ix[ixR] = [0..n-1]
25
+ n = max(ix) + 1
26
+ ixR = ZMatZeros(n)
27
+ ixR[ix] = range(len(ix))
28
+ return ixR
29
+
30
+
31
+
32
+ def nonDecreasing(w):
33
+ '''Check whether vector w is non-decreasing'''
34
+ for i in range(1,len(w)):
35
+ if w[i] < w[i-1]:
36
+ return False
37
+ return True
38
+
39
+ def printObj(params):
40
+ temp = []
41
+ for k,v in vars(params).items():
42
+ temp.append(f'{k}: {v}')
43
+ return "\n".join(temp)
44
+
45
+ #######################################
46
+ ## ZMat - Integer Matrices
47
+ #######################################
48
+
49
+ #######################################
50
+ ## Create ZMat
51
+ #######################################
52
+
53
+
54
+ def Z2MatZeros(s):
55
+ '''Return integer array of zeros of length/shape s'''
56
+ return np.zeros(s,dtype=np.int8)
57
+
58
+
59
+ def Z2Mat(A):
60
+ return ZMat(A,dtype=np.int8)
61
+
62
+ def ZMat(A,n=None,dtype=int):
63
+ '''Create an integer numpy array. If n is set, ensure that the row length is n.'''
64
+ if typeName(A) in ['set','range']:
65
+ A = list(A)
66
+ if typeName(A) != 'ndarray' or A.dtype != dtype:
67
+ A = np.array(A,dtype=dtype)
68
+ if n is not None:
69
+ s = list(A.shape)
70
+ if s[-1] == 0:
71
+ A= np.empty((0,n),dtype=dtype)
72
+ return A
73
+
74
+ def ZMatI(n):
75
+ '''Identity n x n integer matrix'''
76
+ return np.eye(n,dtype=int)
77
+
78
+ def ZMatZeros(s):
79
+ '''Return integer array of zeros of length/shape s'''
80
+ return np.zeros(s,dtype=int)
81
+
82
+ def ZMat2Magma(A,N):
83
+ m,n = A.shape
84
+ temp = [f'C := LinearCode<GF({N}), {n} |']
85
+ for a in A:
86
+ temp.append(f'[{", ".join([str(x) for x in a])}],')
87
+ temp[-1] = temp[-1][:-1] + '>;'
88
+ return ("\n".join(temp))
89
+
90
+
91
+ ###################################################
92
+ ## Calc Linear Combinations of up to t rows
93
+ ###################################################
94
+
95
+ def Orbit2distIter(SX,t=None,return_u=False):
96
+ '''Interator yielding binary rows of form (u SX mod 2) for wt(u) <= t.
97
+ if return_u, yield u as well as the row.'''
98
+ r, n = np.shape(SX)
99
+ if t is None:
100
+ t = r
101
+ t = min(t, r)
102
+ for k in range(t+1):
103
+ for xSupp in iter.combinations(range(r),k):
104
+ vSX = np.mod(np.sum(SX[xSupp,:],axis=0),2)
105
+ if return_u:
106
+ u = set2Bin(r,xSupp)
107
+ yield vSX, u
108
+ else:
109
+ yield vSX
110
+
111
+ # def Orbit2dist(SX,t=None,return_u=False):
112
+ # '''Matrix with binary rows of form (q + u SX mod 2) for wt(u) <= t.
113
+ # if return_u, yield u as well as the row.'''
114
+ # temp = list(Orbit2distIter(SX,t,return_u))
115
+ # # temp = Orbit2dist(SX,t,return_u)
116
+ # print(temp)
117
+ # if return_u:
118
+ # temp = list(zip(*temp))
119
+ # return [ZMat(a) for a in temp]
120
+ # else:
121
+ # return ZMat(temp)
122
+
123
+ def Orbit2dist(SX,t=None,return_u=False):
124
+ r,n = SX.shape
125
+ if t is None:
126
+ t = r
127
+ t = min(t, r)
128
+ if return_u:
129
+ AList = binLinComb(ZMatHstack([SX,ZMatI(r)]),t)
130
+ A = ZMatVstack(AList)
131
+ return [A[:,:n],A[:,n:]]
132
+ AList = binLinComb(SX,t)
133
+ return ZMatVstack(AList)
134
+
135
+ binomCoeff = dict()
136
+
137
+ def binom(n,k):
138
+ # print('binom',n,k)
139
+ if k > n or k < 0 or n < 0:
140
+ return 0
141
+ global binomCoeff
142
+ ix = (n,k)
143
+ if ix not in binomCoeff:
144
+ if k == 0 or n-k == 0:
145
+ binomCoeff[ix] = 1
146
+ elif k == 1 or n-k == 1:
147
+ binomCoeff[ix] = n
148
+ else:
149
+ binomCoeff[ix] = binom(n-1,k-1) + binom(n-1,k)
150
+ return binomCoeff[ix]
151
+
152
+ def binom(n,k,mult=1):
153
+ # print('binom',n,k)
154
+ if k > n or k < 0 or n < 0:
155
+ return 0
156
+ global binomCoeff
157
+ ix = (n,k,mult)
158
+ if ix not in binomCoeff:
159
+ if k == 0 or n-k == 0:
160
+ binomCoeff[ix] = (mult ** k)
161
+ elif k == 1 or n-k == 1:
162
+ binomCoeff[ix] = n * (mult ** k)
163
+ else:
164
+ binomCoeff[ix] = binom(n-1,k-1,mult) * mult + binom(n-1,k,mult)
165
+ return binomCoeff[ix]
166
+
167
+ def binLinComb(A,d):
168
+ '''Linear combinations of up to d rows of A'''
169
+ r,n = A.shape
170
+ ## Allocate space
171
+ AList = [np.empty((binom(r,k),n),dtype=np.int8) for k in range(d+1)]
172
+ ## AList[0] is the all zero vector
173
+ AList[0][:,:] = 0
174
+ ## AList[1] is A
175
+ AList[1] = A
176
+ ## keep track of which parts of AList have been populated
177
+ populated = [n] * 2 + [0] * (d-1)
178
+ for k in range(2,d+1):
179
+ binLinCombRec(r,k,AList,populated)
180
+ return AList
181
+
182
+
183
+ def binLinCombRec(c,d,AList,populated):
184
+ # print(func_name(),c,d)
185
+ '''Recursive step for binLinComb - update lin comb of d of the first c rows of A into AList'''
186
+ ## Can't form lin comb if c < d; if c < 1, nothing to do
187
+ if c < d or c < 1:
188
+ return
189
+ ## Check if we have already populated the relevant part of AList
190
+ if populated[d] < c:
191
+ ## chose d rows from first c-1 rows of A
192
+ if c > d and populated[d] < c-1:
193
+ binLinCombRec(c-1,d,AList,populated)
194
+ ## choose d-1 rows from first c-1 rows of A, then add row A[c-1]
195
+ if d > 1:
196
+ if populated[d-1] < c-1:
197
+ binLinCombRec(c-1,d-1,AList,populated)
198
+ ## update AList
199
+ AList[d][binom(c-1,d): binom(c-1,d)+binom(c-1,d-1) ] = AList[d-1][:binom(c-1,d-1)] ^ AList[1][c-1]
200
+ ## update populated
201
+ populated[d] = c
202
+
203
+ def binLinComb(A,d,mult=1):
204
+ '''Linear combinations of up to d rows of A'''
205
+ r,n = A.shape
206
+ r = r // mult
207
+ ## Allocate space
208
+ AList = [np.empty((binom(r,k,mult),n),dtype=np.int8) for k in range(d+1)]
209
+ ## AList[0] is the all zero vector
210
+ AList[0][:,:] = 0
211
+ ## AList[1] is A
212
+ AList[1] = A
213
+ ## keep track of which parts of AList have been populated
214
+ populated = [n] * 2 + [0] * (d-1)
215
+ for k in range(2,d+1):
216
+ binLinCombRec(r,k,AList,populated,mult)
217
+ return AList
218
+
219
+ def binLinCombRec(c,d,AList,populated,mult=1):
220
+ # print(func_name(),c,d)
221
+ '''Recursive step for binLinComb - update lin comb of d of the first c rows of A into AList'''
222
+ ## Can't form lin comb if c < d; if c < 1, nothing to do
223
+ if c < d or c < 1:
224
+ return
225
+ ## Check if we have already populated the relevant part of AList
226
+ if populated[d] < c:
227
+ ## chose d rows from first c-1 rows of A
228
+ if c > d and populated[d] < c-1:
229
+ binLinCombRec(c-1,d,AList,populated,mult)
230
+ ## choose d-1 rows from first c-1 rows of A, then add row A[c-1]
231
+ if d > 1:
232
+ if populated[d-1] < c-1:
233
+ binLinCombRec(c-1,d-1,AList,populated,mult)
234
+ ## update AList
235
+ Bc1d = binom(c-1,d,mult)
236
+ Bc1d1 = binom(c-1,d-1,mult)
237
+ # print(func_name(),Bc1d + mult * Bc1d1 - len(AList[d]))
238
+ for i in range(mult):
239
+ # print('AList[d-1][:Bc1d1]',AList[d-1][:Bc1d1].shape)
240
+ # print('AList[1][(c-1)*mult+i]',AList[1][(c-1)*mult+i].shape)
241
+ X = AList[d-1][:Bc1d1] ^ AList[1][(c-1)*mult+i]
242
+ # print('X',[x for x in range(len(X)) if np.sum(X[x]) == 0])
243
+ # print('Bc1d1',Bc1d1,X.shape,AList[d].shape,d)
244
+ AList[d][Bc1d + i * Bc1d1: Bc1d + (i+1) * Bc1d1] = X
245
+ ## update populated
246
+ populated[d] = c
247
+
248
+ def getdMax(r,maxLen=1 << 20):
249
+ s = 0
250
+ for i in range(r+1):
251
+ s += binom(r,i)
252
+ if s > maxLen:
253
+ # print(func_name(),s,i-1)
254
+ return i-1
255
+ return r
256
+
257
+ def weightEnumerator(A):
258
+ m,n = A.shape
259
+ temp = ZMatZeros(n+1)
260
+ for s in Orbit2dist(A):
261
+ temp[np.sum(s)] += 1
262
+ return temp
263
+
264
+ ####################################
265
+ ## Conversions to other formats
266
+ ####################################
267
+
268
+ def isIter(A):
269
+ return hasattr(A,'__iter__')
270
+
271
+ def Lolshape(CC):
272
+ if len(CC) == 0 or not isIter(CC[0]):
273
+ return [len(CC)]
274
+ else:
275
+ return [len(CC)] + Lolshape(CC[0])
276
+
277
+ def SL2ZM(CC,ix,A):
278
+ '''recursive step for Sets2ZMat'''
279
+ if len(CC) == 0 or not isIter(CC[0]):
280
+ for i in CC:
281
+ ix2 = (ix + [i])
282
+ A[tuple(ix2)] = 1
283
+ else:
284
+ i = 0
285
+ for c in CC:
286
+ ix2 = ix + [i]
287
+ SL2ZM(c,ix2,A)
288
+ i+=1
289
+
290
+ def Sets2ZMat(n,CC):
291
+ '''Convert a list of lists or sets to a binary matrix with rows of length n
292
+ Fast method - matrix storage is allocated at beginning'''
293
+ ## get shape of final matrix
294
+ s = Lolshape(CC)
295
+ s[-1] = n
296
+ ## intialise to all zeros
297
+ A = np.zeros(s,dtype=np.int8)
298
+ ## recursion
299
+ SL2ZM(CC,[],A)
300
+ return A
301
+
302
+ def ZMat2Sets(A):
303
+ '''Convert a binary matrix to a list of lists of non-zero entries
304
+ recursive method'''
305
+ if len(A.shape) == 1:
306
+ return bin2Set(A)
307
+ else:
308
+ return [ZMat2Sets(B) for B in A]
309
+
310
+ def ZMatVstack(AList):
311
+ '''Faster method for stacking 2xD matrices'''
312
+ if len(AList) == 0:
313
+ return ZMatZeros((0,0))
314
+ A = AList[0]
315
+ r,n = A.shape
316
+ dtype = A.dtype
317
+ ALen = [len(A) for A in AList]
318
+ m = np.sum(ALen)
319
+ B = np.empty((m,n),dtype=dtype)
320
+ c1 = 0
321
+ for i in range(len(AList)):
322
+ c2 = c1 + ALen[i]
323
+ B[c1:c2] = AList[i]
324
+ c1 = c2
325
+ return B
326
+
327
+ def ZMatHstack(AList):
328
+ '''Faster method for stacking 2xD matrices'''
329
+ # return ZMatVstack([A.T for A in AList]).T
330
+ if len(AList) == 0:
331
+ return ZMatZeros((0,0))
332
+ A = AList[0]
333
+ r,n = A.shape
334
+ dtype = A.dtype
335
+ # AList = [ZMat(A) for A in AList]
336
+ ALen = [len(A.T) for A in AList]
337
+ m = np.sum(ALen)
338
+ A = AList[0]
339
+ r,n = A.shape
340
+ B = np.empty((r,m),dtype=dtype)
341
+ c1 = 0
342
+ for i in range(len(AList)):
343
+ c2 = c1 + ALen[i]
344
+ B[:,c1:c2] = AList[i]
345
+ c1 = c2
346
+ return B
347
+
348
+ def Mnt(n,t,mink=1):
349
+ '''Rows are binary strings of length n of weight mink to t'''
350
+ CC = [s for k in range(mink, t+1) for s in iter.combinations(range(n),k)]
351
+ return Sets2ZMat(n,CC)
352
+ A = [set2Bin(n,s) for k in range(mink, t+1) for s in iter.combinations(range(n),k)]
353
+ return ZMat(A)
354
+
355
+ ### multi dimensional versions?
356
+ def set2Bin(n,A,dtype=int):
357
+ '''Convert list of integers t to a binary vector of length n'''
358
+ temp = np.zeros(n,dtype=dtype)
359
+ temp[list(A)] = 1
360
+ return temp
361
+
362
+ def bin2Set(v):
363
+ '''Convert binary vector to a list of indices such that v[i] !=0'''
364
+ v = np.ravel(v)
365
+ return list(map(int,np.nonzero(v)[0]))
366
+
367
+ def ZMat2tuple(A):
368
+ '''Convert rows of A to tuples.'''
369
+ n = np.shape(A)[-1]
370
+ A = np.reshape(A,(-1,n))
371
+ return [tuple(a) for a in A]
372
+
373
+ def set2tuple(c):
374
+ return tuple(sorted(set(c)))
375
+ n = max(c) + 1
376
+ return tuple(inRange(n,c))
377
+
378
+ def invRange(n,S):
379
+ '''return list of elements of range(n) NOT in S'''
380
+ return sorted(set(range(n)) - set(S))
381
+
382
+ def inRange(n,S):
383
+ '''return list of elements of range(n) which ARE in S'''
384
+ return sorted(set(S).intersection(range(n)))
385
+
386
+ def int2bin(x,d,N=2):
387
+ '''convert integer to base N vector'''
388
+ temp = []
389
+ for i in range(d):
390
+ temp.append(x % N)
391
+ x = x // N
392
+ return ZMat(temp)
393
+
394
+ ##############################
395
+ ## ZMat Info
396
+ ##############################
397
+
398
+ def leadingIndex(a):
399
+ '''Return leading index of vector a (ie smallest value for which a[i] !=0)'''
400
+ i = 0
401
+ n = len(a)
402
+ while i < n and a[i]==0:
403
+ i+=1
404
+ return i
405
+
406
+ def isZero(A,N=False):
407
+ '''Check if A modulo N = 0 for all values in A.'''
408
+ if N:
409
+ A = np.mod(A,N)
410
+ return np.all(A == 0)
411
+
412
+
413
+ #######################################
414
+ ## ZMat Analysis
415
+ #######################################
416
+
417
+ def freqTable(wList):
418
+ '''Dict of val:count for val in wList'''
419
+ temp = {w:0 for w in set(wList)}
420
+ for w in wList:
421
+ temp[w] += 1
422
+ return temp
423
+
424
+ def freqTablePrint(wList):
425
+ FT = freqTable(wList)
426
+ temp = [f'{k}:{FT[k]}' for k in sorted(FT.keys())]
427
+ return ",".join(temp)
428
+
429
+ ##########################
430
+ ## Changing Shape of ZMat
431
+ ##########################
432
+
433
+ def ZMatInfo(A):
434
+ return f'{A.dtype} {A.shape}'
435
+
436
+ def ZMat2D(A):
437
+ '''Return a 2-dimensional integer numpy array from A.'''
438
+ s = A.shape
439
+ if len(s) == 2:
440
+ return A
441
+ d = s[-1]
442
+ return np.reshape(A,(-1,d))
443
+
444
+ ##########################
445
+ ## String I/0 for ZMat
446
+ ##########################
447
+
448
+ def row2components(r):
449
+ '''For integer vector r return indices for the non-zero values ix=supp(r) and the non-zero values r[ix].
450
+ Useful for displaying large vectors.'''
451
+ ix = ZMat(np.nonzero(r))
452
+ return ix, r[ix]
453
+
454
+ def row2compStr(r):
455
+ '''Display row r using indices for non-zero values and list of non-zero values
456
+ Useful for displaying large vectors.'''
457
+ ix,vals = row2components(r)
458
+ return f'{ix}:= {vals}'.replace(" ","")
459
+
460
+ def ZMat2compStr(A):
461
+ '''Display 2D integer matrix A using indices for non-zero values and list of non-zero values
462
+ Useful for displaying large vectors.'''
463
+ return "\n".join([row2compStr(r) for r in A])
464
+
465
+ def str2ZMat(mystr):
466
+ '''Convert string of single digit numbers or multi digit numbers split by spaces to an integer array'''
467
+ if mystr.find(" ") > 0:
468
+ mystr = mystr.split()
469
+ return ZMat([int(s) for s in mystr])
470
+
471
+ def str2ZMatdelim(S=''):
472
+ '''Convert string with rows separated by \r, \n "," or ; to 2D integer array.'''
473
+ sep=','
474
+ for s in "\r\n;":
475
+ S = S.replace(s,sep)
476
+ S = S.split(sep)
477
+ return ZMat([str2ZMat(s) for s in S])
478
+
479
+ def bin2ZMat(SX):
480
+ '''Convert multiple types of binary vector input to integer matrix.
481
+ SX is either string or array.'''
482
+ if SX is None:
483
+ return SX
484
+ ## convert string to ZMat
485
+ if isinstance(SX,str):
486
+ return str2ZMatdelim(SX.strip())
487
+ ## convert array to ZMat
488
+ return ZMat(SX)
489
+
490
+ def ZMat2str(A,N=None):
491
+ '''Return string version of integer matrix A.'''
492
+ if np.size(A) == 0:
493
+ return ""
494
+ S = np.char.mod('%d', A)
495
+ sep = ""
496
+ if N is None:
497
+ N = np.amax(A) + 1
498
+ if N > 10:
499
+ Nw= len(str(N-1))
500
+ S = np.char.rjust(S,Nw)
501
+ sep = " "
502
+ return sep.join(S)
503
+ return np.apply_along_axis(func1d=sepjoin,axis=-1,arr=S,sep=sep)
504
+
505
+ def sepjoin(a,sep):
506
+ '''Join text vector a using sep - for display of ZMat.'''
507
+ return sep.join(a)
508
+
509
+ def ZMatPrint(A,N=None,nA=0,tB=1):
510
+ '''Print integer matrix A'''
511
+ temp = []
512
+ A = ZMat2D(A)
513
+ m,n = A.shape
514
+ nB = (n - nA)//tB
515
+ for r in A:
516
+ myRow = [ZMat2str(r[t*nB:(t+1)*nB],N) for t in range(tB)]
517
+ if tB*nB < n:
518
+ myRow.append(ZMat2str(r[tB*nB :],N))
519
+ temp.append("|".join(myRow))
520
+ return "\n".join(temp)
521
+
522
+ #################################################
523
+ ## Debugging Functions
524
+ #################################################
525
+
526
+ def currTime():
527
+ '''Return current time'''
528
+ return time.perf_counter()
529
+ return time.process_time()
530
+
531
+ def startTimer():
532
+ '''Start timer for algorithm and set global variable startTime to be the current time.'''
533
+ global startTime
534
+ startTime = currTime()
535
+ return startTime
536
+
537
+ def elapsedTime():
538
+ '''Return the time elapsed from last startTimer() call.'''
539
+ global startTime
540
+ return -startTime + startTimer()
541
+
542
+ def func_name():
543
+ """Return the name of the current function - for debugging."""
544
+ return sys._getframe(1).f_code.co_name
545
+
546
+ def typeName(val):
547
+ '''Return the name of the type of val in text form.'''
548
+ return type(val).__name__
549
+
550
+
551
+ ##################################
552
+ ## Integer logarithms
553
+ ##################################
554
+
555
+ def logCeil(x,N=2):
556
+ '''Return min(t) where x <= N^t'''
557
+ i = 0
558
+ while x > 0:
559
+ x = x // N
560
+ i = i+1
561
+ return i
562
+
563
+ def log2int(N):
564
+ '''Find t such that N = 2**t or None otherwise'''
565
+ t = logCeil(N-1,2)
566
+ return t if 2 ** t == N else None
@@ -0,0 +1,117 @@
1
+ import numpy as np
2
+ from .common import *
3
+ from .NHow import *
4
+ import json
5
+
6
+ #################################
7
+ # Functions needed to work with complexes
8
+ #################################
9
+
10
+ def complexCheck(AList):
11
+ """Check if AList is a valid complex"""
12
+ for i in range(len(AList) - 1):
13
+ Ai = AList[i]
14
+ mi, ni = np.shape(Ai)
15
+ Aj = AList[i + 1]
16
+ mj, nj = np.shape(Aj)
17
+ ## check dimension of matrices
18
+ if ni != mj:
19
+ print(f"ni={ni} != mj={mj} for i={i},j={i+1}")
20
+ return False
21
+ ## check that successive operators multiply to zero
22
+ AiAj = matMul(Ai, Aj, 2)
23
+ if not np.sum(AiAj) == 0:
24
+ print(f"Ai@Aj != 0 for i={i},j={i+1}")
25
+ return False
26
+ return True
27
+
28
+
29
+ def complexTrim(AList):
30
+ """Remove any all zero matrices from beginning of AList."""
31
+ temp = []
32
+ i = 0
33
+ while np.sum(AList[i]) == 0:
34
+ i += 1
35
+ return AList[i:]
36
+
37
+
38
+ def complexAppendZero(AList):
39
+ """Add zero operator to beginning of AList"""
40
+ m, n = np.shape(AList[0])
41
+ return [ZMatZeros((1, m))] + AList
42
+
43
+
44
+ def complexNew(AList):
45
+ """Make a new complex - make sure there's a zero operator at the end"""
46
+ AList = complexTrim(AList)
47
+ AList = complexAppendZero(AList)
48
+ return AList
49
+
50
+
51
+ def complexDims(AList):
52
+ """Return dimensions of each space acted upon by AList."""
53
+ return [np.shape(A)[1] for A in AList]
54
+
55
+
56
+ def RG2Complex(myrow):
57
+ """convert string format to RG complex boundary operators"""
58
+ boundaryOperators = []
59
+ ## read boundary maps for each level of the complex
60
+ for myLabel in [f"Z{i}" for i in range(4, -1, -1)]:
61
+ if myLabel in myrow:
62
+ ## convert to boundary operators
63
+ boundaryOperators.append(str2ZMatdelim(myrow[myLabel]))
64
+ return complexNew(boundaryOperators)
65
+
66
+
67
+ def importRGList(myfile):
68
+ """Import hyperbolic surface codes stored in myfile.
69
+ Records in myfile are stored in JSON format.
70
+ Parse each record and return list of dict codeList."""
71
+ # mypath = sys.path[0] + "/hyperbolic_codes/"
72
+ # f = open(mypath + myfile, "r")
73
+ f = open(myfile, "r")
74
+ mytext = f.read()
75
+ mytext = mytext.replace("\\\n", "").replace("\n", "")
76
+ mytext = mytext.replace("{", "\n{")
77
+ mytext = mytext.split("\n")
78
+ codeList = []
79
+ for myline in mytext:
80
+ if len(myline) > 0 and myline[0] != "#":
81
+ myrow = json.loads(myline)
82
+ codeList.append([myrow["index"], RG2Complex(myrow)])
83
+ f.close()
84
+ return codeList
85
+
86
+
87
+ def printRGList(codeList, myfile, checkValid=False):
88
+ """Print parameters of the hyperbolic codes stored in list of dict codeList"""
89
+ temp = []
90
+ temp.append(f"Codes in File {myfile}:\n")
91
+ valTxt = "\tValid" if checkValid else ""
92
+ D = len(codeList[0][1])
93
+ myrow = f"i\tindex{valTxt}"
94
+ for i in range(D):
95
+ myrow += f"\t|C{i}|"
96
+ temp.append(myrow)
97
+ for i in range(len(codeList)):
98
+ myrow = codeList[i]
99
+ ix = myrow[0]
100
+ C = myrow[1]
101
+ rowDesc = [i, ix]
102
+ if checkValid:
103
+ rowDesc += [complexCheck(C)]
104
+ rowDesc += complexDims(C)
105
+ temp.append("\t".join([str(a) for a in rowDesc]))
106
+ return "\n".join(temp)
107
+
108
+
109
+ def complexCProduct(C):
110
+ if len(C) == 0:
111
+ return []
112
+ P = C[0]
113
+ temp = [P.T]
114
+ for i in range(1, len(C)):
115
+ P = mod1(P @ C[i])
116
+ temp.append(P.T)
117
+ return temp