def reed_muller(r, m, puncture=False): "Build Reed-Muller code" assert 0<=r<=m, "r=%s, m=%d"%(r, m) n = 2**m # length one = array2([1]*n) basis = [one] vs = [[] for i in range(m)] for i in range(2**m): for j in range(m): vs[j].append(i%2) i >>= 1 assert i==0 vs = [array2(v) for v in vs] for k in range(r): for items in choose(vs, k+1): v = one #print(items) for u in items: v = v*u basis.append(v) G = numpy.array(basis) code = Code(G, d=2**(m-r), desc="reed_muller(%d, %d)"%(r, m)) if puncture: code = code.puncture(0) return code
def check_toric(): global toric # arff ! import qupy.ldpc.solve import bruhat.solve qupy.ldpc.solve.int_scalar = bruhat.solve.int_scalar from bruhat.solve import shortstr, zeros2, dot2, array2, solve from numpy import alltrue, zeros, dot l = argv.get("l", 2) from qupy.ldpc.toric import Toric2D toric = Toric2D(l) Hx, Hz = toric.Hx, toric.Hz assert alltrue(dot2(Hx, Hz.transpose()) == 0) from qupy.condmat.isomorph import Tanner, search src = Tanner.build2(Hx, Hz) #tgt = Tanner.build2(Hx, Hz) tgt = Tanner.build2(Hz, Hx) # weak duality mx, n = Hx.shape mz, n = Hz.shape fns = [] perms = [] for fn in search(src, tgt): assert len(fn) == mx + mz + n bitmap = [] for i in range(n): bitmap.append(fn[i + mx + mz] - mx - mz) perm = tuple(bitmap) #print(bitmap) fixed = [i for i in range(n) if bitmap[i] == i] print("perm:", perm) print("fixed:", fixed) g = Perm(perm, list(range(n))) assert g.order() == 2 perms.append(perm) for hx in Hx: print(toric.strop(hx)) print("--->") hx = array2([hx[i] for i in perm]) print(toric.strop(hx)) print("--->") hx = array2([hx[i] for i in perm]) print(toric.strop(hx)) print() check_dualities(Hz, Hx.transpose(), perms)
def find_orbits(): n = argv.get("n", 3) m = argv.get("m", 2) rows = list(range(m)) cols = list(range(n)) orbits = {} found = set() for H in numpy.ndindex((2,)*n*m): H = array2(H) H.shape = (m, n) s = H.tostring() if s in orbits: continue if rank(H)<m: continue found.add(s) for rperm in all_perms(rows): for cperm in all_perms(cols): #print(rperm, cperm) J = H[rperm, :] J = J[:, cperm] #print(J) J = J.copy() s = J.tostring() #assert s not in orbits orbits[s] = H for s in found: H = numpy.fromstring(s, dtype=H.dtype) print(H) print(len(found))
def test_triorth(): code = reed_muller(1, 5) code = code.puncture(0) code.dump() print(code.is_triorthogonal()) A = array2(list(span(code.G))) print(is_morthogonal(A, 2)) #print(shortstr(A)) k = len(A) for i in range(k): for j in range(i+1, k): u = A[i] v = A[j] x = (u*v).sum() % 2 if x == 0: continue #print(shortstr(u)) #print(shortstr(v)) #print() for a in range(k): for b in range(a+1, k): for c in range(b+1, k): u = A[a] v = A[b] w = A[c] x = (u*v*w).sum() % 2
def even_rows(G): Gx = [] for u in G: #print(shortstr(u), u.sum()%2) parity = u.sum()%2 if parity==0: Gx.append(u) Gx = array2(Gx) return Gx
def main_fail(): print() print("==" * 70) H = """ 012345678901234 0 YXZZ........... 1 X..X.XX.X...... 2 ZZ..ZZ.......Z. 3 .X..Y....XZ.... 4 .ZX....Y.Z..... 5 .....ZZZ.Z....Z 6 ..Z...ZZ....ZZ. 7 ...Z....Y.XX... 8 ..XX.......ZY.. 9 .........ZXX..Y 10 .....X.....XXXX 11 ....X.X.X.X..X. """ H = syparse(H) print() print(shortstr(H)) m = len(H) n = H.shape[1] // 2 assert n == 15 F = symplectic(n) C = dot2(H, dot2(F, H.transpose())) print(C.shape) for i in range(m): for j in range(i + 1, m): if C[i, j]: print("fail:", i, j) print(rank(H)) H = linear_independent(H) print("H=", H.shape) print(shortstr(H)) HF = dot2(H, F) K = array2(find_kernel(HF)) print("K=", K.shape) print(shortstr(K)) HK = numpy.concatenate((H, K)) L = linear_independent(HK) print() print(shortstr(L))
def gen(): r = argv.get("r", None) # degree m = argv.get("m", None) if r is not None and m is not None: code = reed_muller(r, m) #print(code) #print("d =", code.get_distance()) #code.dump() #code = code.puncture(3) #print(code) code = code.puncture(0) print(code) for g in code.G: print(shortstr(g), g.sum()) print() #code.dump() #print("d =", code.get_distance()) return for m in range(2, 8): for r in range(0, m+1): code = reed_muller(r, m) print(code, end=" ") if code.is_selfdual(): print("is_selfdual", end=" ") if code.is_morthogonal(2): print("is_biorthogonal", end=" ") if code.is_morthogonal(3): print("is_triorthogonal", end=" ") if dot2(code.H, code.H.transpose()).sum()==0: print("***", end=" ") p = code.puncture(0) if p.is_morthogonal(3): print("puncture.is_triorthogonal", end=" ") if p.is_selfdual(): print("puncture.is_selfdual", end=" ") if dot2(p.H, p.H.transpose()).sum()==0: print("***", end=" ") print() if p.is_triorthogonal() and p.k < 20: G = p.G #print(shortstr(G)) A = list(span(G)) A = array2(A) print(is_morthogonal(A, 3))
def __init__(self, G, H=None, d=None, desc="", check=True): assert len(G.shape)==2 self.G = G.copy() self.k, self.n = G.shape self.d = d self.desc = desc if H is None: H = list(find_kernel(G)) H = array2(H) if H.shape == (0,): H.shape = (0, self.n) self.H = H.copy() if check: self.check()
def test_rm(): params = [(r, m) for m in range(2, 8) for r in range(1, m)] r = argv.get("r", None) # degree m = argv.get("m", None) if r is not None and m is not None: params = [(r, m)] for (r, m) in params: #code = reed_muller(r, m) # for code in [ reed_muller(r, m), reed_muller(r, m).puncture(0) ]: for code in [reed_muller(r, m)]: if argv.puncture: print(code, end=" ", flush=True) code = code.puncture(0) code = code.get_even() if argv.puncture==2: code = code.puncture(0) code = code.get_even() G = code.G k, n = G.shape #code = Code(G) #d = code.get_distance() d = "." print("puncture [%d, %d, %s]" % (n, k, d), end=" ", flush=True) else: G = code.G print(code, end=" ", flush=True) i = 1 while i<8: if (is_morthogonal(G, i)): print("(%d)"%i, end="", flush=True) i += 1 else: break if i > code.k: print("*", end="") break print() if argv.show: print(G.shape) print(shortstr(G)) print(dot2(G, G.transpose()).sum()) if len(G) >= 14: continue A = array2(list(span(G))) for i in [1, 2, 3]: assert strong_morthogonal(G, i) == strong_morthogonal(A, i)
def main_torus(): n = 8 # ZZZZZZZZ|XXXXXXXX # 12345678|12345678 H = parse(""" 111..1..|........ 1..1....|1.1..... ........|11.11... .1..1...|.1...1.. ..1...1.|...1..1. ...11.11|........ .....1.1|....1..1 ........|..1..111 """.replace("|", "")) print() print("H=") print(shortstr(H)) F = symplectic(n) C = dot2(H, dot2(F, H.transpose())) for i in range(n): for j in range(i + 1, n): if C[i, j]: print("fail:", i + 1, j + 1) print(rank(H)) H = linear_independent(H) print("H=") print(shortstr(H)) HF = dot2(H, F) K = array2(find_kernel(HF)) print("K=") print(shortstr(K)) HK = numpy.concatenate((H, K)) L = linear_independent(HK) print() print(shortstr(L))
def test(): for idx, H in enumerate(items): H = array2(H) #print(H.shape) print(names[idx]) print(shortstr(H)) assert (dot2(H, H.transpose()).sum()) == 0 # orthogonal code G = H for genus in range(1, 4): print(strong_morthogonal(G, genus), end=" ") print() keys = [0, 4, 8, 12, 16, 20, 24] counts = {0: 0, 4: 0, 8: 0, 12: 0, 16: 0, 20: 0, 24: 0} for v in span(G): counts[v.sum()] += 1 print([counts[k] for k in keys]) print()
def test_tri_rm(): r = argv.get("r", 1) # degree m = argv.get("m", 4) puncture = argv.puncture code = reed_muller(r, m, puncture) G = code.G rows = [row for row in G if row.sum()%2==0] G = array2(rows) k = len(rows) print(G.shape) for i in range(1, 10): # statistical test for m-orthogonality for trials in range(10000): vecs = [rows[randint(0, k-1)] for j in range(i)] v = vecs[0].copy() for w in vecs[1:]: v = v*w if v.sum()%2 != 0: break else: print("(%d)"%i, end=" ", flush=True) continue break print()
def get_all(): directory = path.dirname(__file__) name = path.join(directory, "matrixform.txt") f = open(name) line = f.readline() #items = [] count = 0 dim = None idx = None for line in f: line = line.strip() #print(line) if line in "[ ], ] ];".split(): continue if line.startswith("<"): rows = [] flds = line[1:].split(", ") dim = int(flds[0]) idx = int(flds[1]) count += 1 continue assert line.startswith("["), repr(line) row = line[1:49] assert len(row) == 48 rows.append([ord(c) - 48 for c in row]) if ">" in line: G = array2(rows) #items.append(G) yield (dim, idx, G) rows = None dim = None idx = None
def check_dualities(Hz, Hxt, dualities): from bruhat.solve import shortstr, zeros2, dot2, array2, solve, span from numpy import alltrue, zeros, dot import qupy.ldpc.solve import bruhat.solve qupy.ldpc.solve.int_scalar = bruhat.solve.int_scalar from qupy.ldpc.css import CSSCode Hz = Hz % 2 Hx = Hxt.transpose() % 2 code = CSSCode(Hz=Hz, Hx=Hx) print(code) n = code.n Lx, Lz = code.Lx, code.Lz # check we really do have weak dualities here: for perm in dualities: Hz1 = Hz[:, perm] Hxt1 = Hxt[perm, :] assert solve(Hxt, Hz1.transpose()) is not None assert solve(Hz1.transpose(), Hxt) is not None Lz1 = Lz[:, perm] Lx1 = Lx[:, perm] find_xz = solve(concatenate((Lx, Hx)).transpose(), Lz1.transpose()) is not None find_zx = solve(concatenate((Lz1, Hz1)).transpose(), Lx.transpose()) is not None #print(find_xz, find_zx) assert find_xz assert find_zx # the fixed points live simultaneously in the homology & the cohomology fixed = [i for i in range(n) if perm[i] == i] if len(fixed) == 0: continue v = array2([0] * n) v[fixed] = 1 v.shape = (n, 1) find_xz = solve(concatenate((Lx, Hx)).transpose(), v) is not None find_zx = solve(concatenate((Lz, Hz)).transpose(), v) is not None #print(find_xz, find_zx) assert find_xz assert find_zx from qupy.ldpc.asymplectic import Stim as Clifford s_gates = [] h_gates = [] s_names = [] for idx, swap in enumerate(dualities): fixed = [i for i in range(n) if swap[i] == i] print(idx, fixed) for signs in cross([(-1, 1)] * len(fixed)): # <------- does not scale !!! XXX v = [0] * n for i, sign in enumerate(signs): v[fixed[i]] = sign ux = numpy.dot(Hx, v) uz = numpy.dot(Hz, v) if numpy.alltrue(ux == 0) and numpy.alltrue(uz == 0): #print("*", end=" ") break #else: # assert 0 #print(v) #print() # transversal S/CZ g = Clifford.identity(n) name = [] for i in range(n): j = swap[i] if j < i: continue if j == i: assert v[i] in [1, -1] if v[i] == 1: op = Clifford.s_gate(n, i) name.append("S_%d" % (i, )) else: op = Clifford.s_gate(n, i).inverse() name.append("Si_%d" % (i, )) else: op = Clifford.cz_gate(n, i, j) name.append("CZ_%d_%d" % (i, j)) g = op * g name = "*".join(reversed(name)) s_names.append(name) #print(g) #print() #assert g.is_transversal(code) s_gates.append(g) h = Clifford.identity(n) for i in range(n): h = h * Clifford.h_gate(n, i) for i in range(n): j = swap[i] if j <= i: continue h = h * Clifford.swap_gate(n, i, j) #print(g) #print() #assert h.is_transversal(code) h_gates.append(h) if 0: print() print("CZ:") CZ = Clifford.cz_gate(2, 0, 1) op = (1., [0, 0], [1, 1]) for i in range(4): print(op) op = CZ(*op) return for idx, sop in enumerate(s_gates): print("idx =", idx) #for hx in Hx: perm = dualities[idx] #for hx in span(Hx): for hx in Hx: #print("hx =", hx) #print(s_names[idx]) phase, zop, xop = sop(1., None, hx) assert numpy.alltrue(xop == hx) # fixes x component print(phase, zop, xop, dot2(zop, xop)) for (i, j) in enumerate(perm): if xop[i] and xop[j] and i < j: print("pair", (i, j)) if toric is None: continue print("xop =") print(toric.strop(xop)) print("zop =") print(toric.strop(zop)) print()
def get_even(self): G = self.G rows = [row for row in G if row.sum()%2==0] G = array2(rows) return Code(G)
def is_422_cat_selfdual(Hz, Hx, perm): "concatenate with the [[4,2,2]] code and see if we get a self-dual code" from numpy import alltrue, zeros, dot import qupy.ldpc.solve import bruhat.solve qupy.ldpc.solve.int_scalar = bruhat.solve.int_scalar from bruhat.solve import shortstrx, zeros2, dot2, array2, solve from qupy.ldpc.css import CSSCode Cout = CSSCode(Hz=Hz, Hx=Hx) #print(Cout) #Cin = CSSCode(Hz=array2([[1,1,1,1]]), Hx=array2([[1,1,1,1]])) #print(Cin) pairs = [] singles = [] for i in range(Cout.n): j = perm[i] if j < i: continue if i == j: singles.append(i) else: pairs.append((i, j)) #print(singles, pairs) M = len(singles) + 4 * len(pairs) # encoding matrices enc_z = zeros2(M, Cout.n) enc_x = zeros2(M, Cout.n) row = 0 for col in singles: enc_z[row, col] = 1 enc_x[row, col] = 1 row += 1 H = [] for (i, j) in pairs: enc_z[row, i] = 1 # 1010 enc_z[row + 2, i] = 1 enc_z[row, j] = 1 # 1100 enc_z[row + 1, j] = 1 enc_x[row, i] = 1 # 1100 enc_x[row + 1, i] = 1 enc_x[row, j] = 1 # 1010 enc_x[row + 2, j] = 1 h = array2([0] * M) h[row:row + 4] = 1 H.append(h) row += 4 assert row == M #print(shortstrx(enc_z, enc_x)) Hz = dot2(enc_z, Cout.Hz.transpose()).transpose() Hx = dot2(enc_x, Cout.Hx.transpose()).transpose() assert alltrue(dot2(Hz, Hx.transpose()) == 0) Hz = numpy.concatenate((Hz, H)) Hx = numpy.concatenate((Hx, H)) assert alltrue(dot2(Hz, Hx.transpose()) == 0) C = CSSCode(Hz=Hz, Hx=Hx) assert C.k == Cout.k #print(C) lhs = (solve(Hz.transpose(), Hx.transpose()) is not None) rhs = (solve(Hx.transpose(), Hz.transpose()) is not None) return lhs and rhs
def search(): # Bravyi, Haah, 1209.2426v1 sec IX. # https://arxiv.org/pdf/1209.2426.pdf verbose = argv.get("verbose") m = argv.get("m", 6) # _number of rows k = argv.get("k", None) # _number of odd-weight rows # these are the variables N_x xs = list(cross([(0, 1)]*m)) maxweight = argv.maxweight minweight = argv.get("minweight", 1) xs = [x for x in xs if minweight <= sum(x)] if maxweight: xs = [x for x in xs if sum(x) <= maxweight] N = len(xs) lhs = [] rhs = [] # bi-orthogonality for a in range(m): for b in range(a+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == 1: v[i] = 1 if v.sum(): lhs.append(v) rhs.append(0) # tri-orthogonality for a in range(m): for b in range(a+1, m): for c in range(b+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == x[c] == 1: v[i] = 1 if v.sum(): lhs.append(v) rhs.append(0) # # dissallow columns with weight <= 1 # for i, x in enumerate(xs): # if sum(x)<=1: # v = zeros2(N) # v[i] = 1 # lhs.append(v) # rhs.append(0) if k is not None: # constrain to k _number of odd-weight rows assert 0<=k<m for a in range(m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == 1: v[i] = 1 lhs.append(v) if a<k: rhs.append(1) else: rhs.append(0) A = array2(lhs) rhs = array2(rhs) #print(shortstr(A)) B = pseudo_inverse(A) soln = dot2(B, rhs) if not eq2(dot2(A, soln), rhs): print("no solution") return if verbose: print("soln:") print(shortstr(soln)) soln.shape = (N, 1) rhs.shape = A.shape[0], 1 K = array2(list(find_kernel(A))) #print(K) #print( dot2(A, K.transpose())) #sols = [] #for v in span(K): best = None density = 1.0 size = 99*N trials = argv.get("trials", 1024) count = 0 for trial in range(trials): u = rand2(len(K), 1) v = dot2(K.transpose(), u) #print(v) v = (v+soln)%2 assert eq2(dot2(A, v), rhs) if v.sum() > size: continue size = v.sum() Gt = [] for i, x in enumerate(xs): if v[i]: Gt.append(x) if not Gt: continue Gt = array2(Gt) G = Gt.transpose() assert is_morthogonal(G, 3) if G.shape[1]<m: continue if 0 in G.sum(1): continue if argv.strong_morthogonal and not strong_morthogonal(G, 3): continue #print(shortstr(G)) # for g in G: # print(shortstr(g), g.sum()) # print() _density = float(G.sum()) / (G.shape[0]*G.shape[1]) #if best is None or _density < density: if best is None or G.shape[1] <= size: best = G size = G.shape[1] density = _density if 0: #sols.append(G) Gx = even_rows(G) assert is_morthogonal(Gx, 3) if len(Gx)==0: continue GGx = array2(list(span(Gx))) assert is_morthogonal(GGx, 3) count += 1 print("found %d solutions" % count) if best is None: return G = best #print(shortstr(G)) for g in G: print(shortstr(g), g.sum()) print() print("density:", density) print("shape:", G.shape) G = linear_independent(G) A = list(span(G)) print(strong_morthogonal(A, 1)) print(strong_morthogonal(A, 2)) print(strong_morthogonal(A, 3)) #print(shortstr(dot2(G, G.transpose()))) if 0: B = pseudo_inverse(A) v = dot2(B, rhs) print("B:") print(shortstr(B)) print("v:") print(shortstr(v)) assert eq2(dot2(B, v), rhs)
def search_extend(): # Extend the checks of a random code to make it triorthogonal. # Based on the search function above. verbose = argv.get("verbose") m = argv.get("m", 6) n = argv.get("n", m+2) k = argv.get("k") # odd _numbered rows ( logical operators) code = argv.get("code", "rand") if code == "rand": while 1: G0 = rand2(m, n) counts = G0.sum(0) if min(counts)==2 and rank(G0) == m: cols = set() for i in range(n): cols.add(tuple(G0[:, i])) if len(cols) == n: # no repeated cols break elif code == "toric": G0 = parse(""" 11.11... .111..1. 1...11.1 """) # l=2 toric code X logops + X stabs l = argv.get("l", 3) G0 = build_toric(l) m, n = G0.shape else: return code = Code(G0, check=False) print(shortstr(G0)) print("is_triorthogonal:", code.is_triorthogonal()) # these are the variables N_x xs = list(cross([(0, 1)]*m)) N = len(xs) lookup = {} for i, x in enumerate(xs): lookup[x] = i lhs = [] rhs = [] taken = set() for i in range(n): x = G0[:, i] idx = lookup[tuple(x)] assert idx not in taken taken.add(idx) if verbose: for idx in range(N): print(idx, xs[idx], "*" if idx in taken else "") for idx in taken: v = zeros2(N) v[idx] = 1 lhs.append(v) rhs.append(1) # bi-orthogonality for a in range(m): for b in range(a+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == 1: v[i] += 1 assert v.sum() lhs.append(v) rhs.append(0) # tri-orthogonality for a in range(m): for b in range(a+1, m): for c in range(b+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == x[c] == 1: v[i] += 1 assert v.sum() lhs.append(v) rhs.append(0) # dissallow columns with weight <= 1 for i, x in enumerate(xs): if sum(x)<=1: v = zeros2(N) v[i] = 1 lhs.append(v) rhs.append(0) if k is not None: # constrain to k _number of odd-weight rows assert 0<=k<m for a in range(m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == 1: v[i] = 1 lhs.append(v) if a<k: rhs.append(1) else: rhs.append(0) A = array2(lhs) rhs = array2(rhs) if verbose: print("lhs:") print(shortstr(A)) print("rhs:") print(shortstr(rhs)) B = pseudo_inverse(A) soln = dot2(B, rhs) if not eq2(dot2(A, soln), rhs): print("no solution") return if verbose: print("soln:") print(shortstr(soln)) soln.shape = (N, 1) rhs.shape = A.shape[0], 1 K = array2(list(find_kernel(A))) best = None density = 1.0 size = 9999*n trials = argv.get("trials", 1024) count = 0 for trial in range(trials): u = rand2(len(K), 1) v = dot2(K.transpose(), u) #print(v) assert dot2(A, v).sum()==0 #if v.sum() != n: # continue assert v[0]==0 v = (v+soln)%2 assert eq2(dot2(A, v), rhs) Gt = list(G0.transpose()) for i, x in enumerate(xs): if v[i] and not i in taken: Gt.append(x) if not Gt: continue Gt = array2(Gt) G = Gt.transpose() if verbose: print("G0") print(shortstr(G0)) print("solution:") print(shortstr(G)) assert is_morthogonal(G, 3) if G.shape[1]<m: continue if 0 in G.sum(1): continue #print(shortstr(G)) # for g in G: # print(shortstr(g), g.sum()) # print() _density = float(G.sum()) / (G.shape[0]*G.shape[1]) #if best is None or _density < density: if best is None or G.shape[1] < size: best = G density = _density size = G.shape[1] if 0: #sols.append(G) Gx = even_rows(G) assert is_morthogonal(Gx, 3) if len(Gx)==0: continue GGx = array2(list(span(Gx))) assert is_morthogonal(GGx, 3) count += 1 print("found %d solutions" % count) G = best #print(shortstr(G)) for g in G: print(shortstr(g), g.sum()) print() print("density:", density)
def search_selfdual(): verbose = argv.get("verbose") m = argv.get("m", 6) # _number of rows k = argv.get("k", None) # _number of odd-weight rows maxweight = argv.get("maxweight", m) minweight = argv.get("minweight", 1) # these are the variables N_x print("building xs...") if 0: xs = cross([(0, 1)]*m) xs = [x for x in xs if minweight <= sum(x) <= maxweight] prune = argv.get("prune", 0.5) xs = [x for x in xs if random() < prune] xs = [] N = argv.get("N", m*100) colweight = argv.get("colweight", maxweight) assert colweight <= m for i in range(N): x = [0]*m total = 0 while total < colweight: idx = randint(0, m-1) if x[idx] == 0: x[idx] = 1 total += 1 xs.append(x) N = len(xs) lhs = [] rhs = [] # bi-orthogonality for a in range(m): for b in range(a+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == 1: v[i] = 1 if v.sum(): lhs.append(v) rhs.append(0) k = 0 # all rows must have even weight # constrain to k _number of odd-weight rows assert 0<=k<m for a in range(m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == 1: v[i] = 1 lhs.append(v) if a<k: rhs.append(1) else: rhs.append(0) logops = argv.logops A = array2(lhs) rhs = array2(rhs) #print(shortstr(A)) print("solve...") B = pseudo_inverse(A) soln = dot2(B, rhs) if not eq2(dot2(A, soln), rhs): print("no solution") return if verbose: print("soln:") print(shortstr(soln)) soln.shape = (N, 1) rhs.shape = A.shape[0], 1 K = array2(list(find_kernel(A))) print("kernel:", K.shape) if len(K)==0: return #print(K) #print( dot2(A, K.transpose())) #sols = [] #for v in span(K): best = None density = 1.0 size = 99*N trials = argv.get("trials", 1024) count = 0 print("trials...") for trial in range(trials): u = rand2(len(K), 1) v = dot2(K.transpose(), u) #print(v) v = (v+soln)%2 assert eq2(dot2(A, v), rhs) if v.sum() >= size: continue if v.sum() < m: continue if v.sum(): print(v.sum(), end=" ", flush=True) size = v.sum() if logops is not None and size != 2*m+logops: continue Gt = [] for i, x in enumerate(xs): if v[i]: Gt.append(x) Gt = array2(Gt) G = Gt.transpose() if dot2(G, Gt).sum() != 0: # not self-dual print(shortstr(dot2(G, Gt))) assert 0 return #if G.shape[1]<m: # continue if 0 in G.sum(1): print(".", end="", flush=True) continue #print(shortstr(G)) # for g in G: # print(shortstr(g), g.sum()) # print() _density = float(G.sum()) / (G.shape[0]*G.shape[1]) #if best is None or _density < density: if best is None or G.shape[1] <= size: best = G size = G.shape[1] density = _density if 0: #sols.append(G) Gx = even_rows(G) assert is_morthogonal(Gx, 3) if len(Gx)==0: continue GGx = array2(list(span(Gx))) assert is_morthogonal(GGx, 3) count += 1 print("found %d solutions" % count) if best is None: return G = best #print(shortstr(G)) f = open("selfdual.ldpc", "w") for spec in ["Hx =", "Hz ="]: print(spec, file=f) for g in G: print(shortstr(g), file=f) f.close() print() print("density:", density) print("shape:", G.shape) if 0: B = pseudo_inverse(A) v = dot2(B, rhs) print("B:") print(shortstr(B)) print("v:") print(shortstr(v)) assert eq2(dot2(B, v), rhs)
def triortho(): code = get_code() code.dump() print(code) Gx = [] for u in code.G: print(shortstr(u), u.sum()%2) parity = u.sum()%2 if parity==0: Gx.append(u) Gx = array2(Gx) print("is_triorthogonal:", code.is_triorthogonal()) A = array2(list(span(Gx))) print("span(Gx) is_morthogonal(2):", is_morthogonal(A, 2)) print("span(Gx) is_morthogonal(3):", is_morthogonal(A, 3)) return G = code.G # A = array2(list(span(G))) # poly = {} # for v in A: # w = v.sum() # poly[w] = poly.get(w, 0) + 1 # print(poly) k, n = G.shape if 0: from comm import Poly a = Poly({(1,0):1}) b = Poly({(0,1):1}) poly = Poly.zero(2) for v in span(G): w = v.sum() term = Poly({(n-w,0) : 1}) * Poly({(0,w) : 1}) poly = poly + term print(poly) # print higher genus weight enumerator genus = argv.get("genus", 1) assert 1<=genus<=4 N = 2**genus idxs = list(cross([(0,1)]*genus)) cs = {} # _coefficients : map exponent to coeff for vs in cross([list(span(G)) for _ in range(genus)]): key = [0]*N for i in range(n): ii = tuple(v[i] for v in vs) idx = idxs.index(ii) key[idx] += 1 key = tuple(key) cs[key] = cs.get(key, 0) + 1 #print(cs) keys = list(cs.keys()) keys.sort() print(idxs) for key in keys: print(key, cs[key])
def get(name): assert name in names, "%r not found in %s" % (name, names) idx = names.index(name) H = items[idx] H = array2(H) return H
def projective(n, dim=2): # Take n-dim F_2-vector space # points are subspaces of dimension 1 # lines are subspaces of dimension 2 # etc. def get_key(L): vs = [str(v) for v in span(L) if v.sum()] vs.sort() key = ''.join(vs) return key assert n > 1 points = [] for P in enum2(n): P = array2(P) if P.sum() == 0: continue points.append(P) #print "points:", len(points) lines = [] lookup = {} for L in enum2(2 * n): L = array2(L) L.shape = (2, n) L = row_reduce(L) if len(L) != 2: continue key = get_key(L) if key in lookup: continue lines.append(L) lookup[key] = L #print "lines:", len(lines) spaces = [] if n > 3 and dim > 2: m = 3 lookup = {} for A in enum2(m * n): A.shape = (m, n) A = row_reduce(A) if len(A) != m: continue key = get_key(A) if key in lookup: continue spaces.append(A) lookup[key] = A #print "spaces:", len(spaces) incidence = [] tpmap = {} for point in points: point = str(point) tpmap[point] = 0 #print point for L in lines: line = str(tuple(tuple(row) for row in L)) tpmap[line] = 1 for P in span(L): if P.sum(): incidence.append((str(P), line)) for A in spaces: space = freeze(A) tpmap[space] = 2 for P in span(A): if P.sum() == 0: continue incidence.append((str(P), space)) for L in lines: B = solve(A.transpose(), L.transpose()) if B is not None: line = str(tuple(tuple(row) for row in L)) incidence.append((space, line)) g = Geometry(incidence, tpmap) if dim == 2: assert g.get_diagram() == [(0, 1)] elif dim == 3: assert n > 3 assert g.get_diagram() == [(0, 1), (1, 2)] return g