def test_puncture(H): print("\ntest_puncture --------") n = H.shape[1] G = find_kernel(H) k = len(G) print("n = %d, k = %d" % (n, k)) print("G =") print(shortstr(G)) R = row_reduce(H) print("R =") print(shortstr(R)) pivots = get_pivots(R) rows = [i for (i, j) in pivots] cols = [j for (i, j) in pivots] print("pivots:", pivots) A = cols[:k] remain = [j for j in range(n) if j not in A] S = R[:, remain] print("S =") print(shortstr(S)) G1 = find_kernel(S) print("G1 =") G1 = row_reduce(G1) print(G1) S = row_reduce(S) print("S: rank = ", rank(S)) print(shortstr(S))
def build_reduced(): Gx, Gz, Hx, Hz = build() Px = get_reductor(Hx) # projector onto complement of rowspan of Hx Pz = get_reductor(Hz) Rz = [dot2(Pz, g) for g in Gz] Rz = array2(Rz) Rz = row_reduce(Rz, truncate=True) Rx = [dot2(Px, g) for g in Gx] Rx = array2(Rx) Rx = row_reduce(Rx, truncate=True) return Rx, Rz
def __init__(self, U): U = row_reduce(U) m, n = U.shape self.m = m self.n = n self.U = U self._key = (m, n, U.tostring())
def in_support(H, keep_idxs): # find span of H contained within idxs support n = H.shape[1] remove_idxs = [i for i in range(n) if i not in keep_idxs] A = identity2(n) A = A[remove_idxs] #print("in_support", remove_idxs) P = get_reductor(A) PH = dot2(H, P.transpose()) PH = row_reduce(PH) #print(shortstr(PH)) return PH
def z_weld(acode, bcode, pairs): for c in [acode, bcode]: print("Lx:") print(c.Lx) print("Lz:") print(c.Lz) print("Hx:") print(c.Hx) print("Hz:") print(c.Hz) print("-------------------") mx = acode.mx + bcode.mx #for (i, j) in pairs: assert len(set(pairs)) == len(pairs) # uniq n = acode.n + bcode.n - len(pairs) # Hx = zeros2(mx, n) # Hx[:acode.mx, :acode.n] = acode.Hx # Hx[acode.mx:, acode.n-len(pairs):] = bcode.Hx # # az = acode.mz + bcode.mz + acode.k + bcode.k # Az = zeros2(az, n) # r0, r1 = 0, acode.mz # Az[r0:r1, :acode.n] = acode.Hx; r0, r1 = r1, r1+len(acode.Hx) # Az[r0:r1, acode.n-len(pairs):] = bcode.Hx; r0, r1 = r1, r1+len(bcode.Hx) ## Az[r0:r1, :acode.n] = acode.Lz; r0, r1 = r1, r1+len(acode.Lz) ## #assert r1 == len(Az), (r1, len(Az)) ## Az[r0:r1, acode.n-len(pairs):] = bcode.Lz; r0, r1 = r1, r1+len(bcode.Lz) # # print("Az:") # print(Az) #print(Az) Hz = [] for z in span(Az): #print(z) #print( dot2(Hx, z.transpose())) if dot2(Hx, z.transpose()).sum() == 0: Hz.append(z) Hz = array2(Hz) Hz = row_reduce(Hz) print("Hx:") print(Hx) print("Hz:") print(Hz)
def test(n, k, dist=2, verbose=False): assert n > k if argv.rand: while 1: G = rand2(k, n) if rank(G) < k: continue dG = min_weight(G) if dG < dist: continue H = find_kernel(G) dH = min_weight(H) if dH < dist: continue break else: G = zeros2(k, n) jdx = 0 for idx in range(k): for kdx in range(dist): G[idx,jdx+kdx] = 1 jdx += dist-1 dG = min_weight(G) if n < 20 else None assert dG is None or dG == dist H = find_kernel(G) #print(".", flush=True, end="") H = row_reduce(H) search(G, H) if verbose: print("G =") print(shortstr(G)) print("weight =", dG) print() print("H =") print(shortstr(H)) print()
def opticycle(m, n): best_d = 0 for trial in range(4000): #row = '1101' row = [0] * n for i in range(18): row[randint(0, n-1)] = 1 print(shortstr(row)) Hz = build_cycle(m, n, row) Hz = solve.row_reduce(Hz, truncate=True) #print shortstr(Hz) code = CSSCode(Hz=Hz, build=True, check=True) Lx = code.Lx k = Lx.shape[0] ws = [Lx[i].sum() for i in range(k)] d = min(ws) print("\nd =", d) if d > best_d: d = code.find_distance(stopat=best_d) print("\n*d =", d) if d > best_d: best_d = d best = code print("distance <=", best_d) code = best print() print(code) #print code.weightstr() print(code.weightsummary()) print("distance <=", best_d) return code
def normal_form(self): A = self.A #print("normal_form") #print(A) A = row_reduce(A) #print(A) m, n = A.shape j = 0 for i in range(m): while A[i, j] == 0: j += 1 i0 = i - 1 while i0 >= 0: r = A[i0, j] if r != 0: A[i0, :] += A[i, :] A %= 2 i0 -= 1 j += 1 #print(A) A = Matrix(A) return A
def dependent_rows(H): "find dependent rows of H, first to last" idxs = set(range(len(H))) #print(H) K = find_kernel(H.transpose()) #print("K:") #print(K) K = row_reduce(K, truncate=True) #print("K:") #print(K) assert dot2(K, H).sum() == 0 deps = [] for row in K: #print(row) idx = numpy.where(row != 0)[0][0] deps.append(idx) idxs.remove(idx) assert len(set(deps)) == len(K) idxs = list(idxs) idxs.sort() deps.sort() return idxs, deps
def build_model(Gx=None, Gz=None, Hx=None, Hz=None): if Gx is None: Gx, Gz, Hx, Hz = build() n = Gx.shape[1] if Hx is None: Hx = find_stabilizers(Gz, Gx) if Hz is None: Hz = find_stabilizers(Gx, Gz) check_commute(Hx, Hz) check_commute(Gx, Hz) check_commute(Hx, Gz) #Px = get_reductor(concatenate((Lx, Hx))) #Pz = get_reductor(concatenate((Lz, Hz))) Px = get_reductor(Hx) Pz = get_reductor(Hz) # Lz = find_logops( Hx , Hz ) # find_logops( ............. , ............. ) # ( commutes with , orthogonal to ) # ( ............. , ............. ) Lz = find_logops(Gx, Hz) assert Lz.shape[1] == n if 0: PGz = get_reductor(Gz) Lz = dot2(Lz, PGz.transpose()) Lz = row_reduce(Lz) print(shortstrx(Lz, Gz, Hz)) if len(Lz): #print Lz.shape, Hz.shape assert len(row_reduce(concatenate((Lz, Hz)))) == len(Lz) + len(Hz) assert len(row_reduce(concatenate( (Lz, Gz)))) == len(Lz) + len(row_reduce(Gz)) # Tz = find_errors( Hx , Lx ) # find_errors( ............. , ............. ) # ( conjugate to , commutes with ) # ( ............. , ............. ) Lx = find_errors(Lz, Gz) # invert Lz, commuting with Gz check_commute(Lx, Gz) check_commute(Lx, Hz) check_conjugate(Lx, Lz) check_commute(Lz, Gx) check_commute(Lz, Hx) # Lx | Lz # Hx | ? # ? | Hz # ? | ? #Rz = find_logops(concatenate((Lx, Hx)), Hz) Rz = dot2(Gz, Pz.transpose()) Rz = row_reduce(Rz) check_commute(Rz, Lx) check_commute(Rz, Hx) Rx = dot2(Gx, Px.transpose()) Rx = row_reduce(Rx) check_commute(Rx, Lz) check_commute(Rx, Hz) # Lx | Lz # Hx | ? # ? | Hz # Rx'| Rz' Tz = find_errors(Hx, concatenate((Lx, Rx))) Tx = find_errors(Hz, concatenate((Lz, Rz, Tz))) assert len((concatenate((Lx, Hx, Tx, Rx)))) == n assert len((concatenate((Lz, Hz, Tz, Rz)))) == n assert len(row_reduce(concatenate((Lx, Hx, Tx, Rx)))) == n assert len(row_reduce(concatenate((Lz, Hz, Tz, Rz)))) == n check_commute(Rz, Tx) Rx = find_errors(Rz, concatenate((Lz, Hz, Tz))) check_conjugate(Rx, Rz) check_commute(Rx, Hz) check_commute(Rx, Tz) check_commute(Rx, Lz) Rxt = Rx.transpose() Rzt = Rz.transpose() Pxt = Px.transpose() Pzt = Pz.transpose() check_sy(Lx, Hx, Tx, Rx, Lz, Hz, Tz, Rz) assert eq2(dot2(Gz, Rxt), dot2(Gz, Pzt, Rxt)) assert eq2(dot2(Gx, Rzt), dot2(Gx, Pxt, Rzt)) # print shortstrx(dot2(Rx, Pz), Rx) assert eq2(dot2(Rx, Pz), Rx) assert eq2(dot2(Rz, Px), Rz) assert len(find_kernel(dot2(Gz, Rx.transpose()))) == 0 model = Model(locals()) if argv.dual: model = model.get_dual() argv.dual = False # HACK !! return model
def main(): if argv.ldpc: # LDPC l = argv.get("l", 3) # column weight m = argv.get("m", 4) # row weight n = argv.get("n", 8) # cols r = argv.get("r", n * l // m) # rows d = argv.get("d", 1) # distance print("make_gallagher%s" % ((r, n, l, m, d), )) C = make_gallagher(r, n, l, m, d) print(shortstr(C)) print() print(shortstr(C)) print("rank(C) = ", rank(C), "kernel(C) = ", len(find_kernel(C))) if argv.same: D = C else: D = make_gallagher(r, n, l, m, d) assert rank(C) == len(C) assert rank(D) == len(D) print("rank(D)", rank(D), "kernel(D)", len(find_kernel(D))) elif argv.hrand: #C = random_code(16, 8, 0, 3) C = random_code(8, 4, 0, 3) D = random_code(8, 4, 1, 3) elif argv.hvrand: #C = random_code(16, 8, 8, 3) C = random_code(8, 4, 4, 3) D = random_code(8, 4, 4, 3) elif argv.hvrandsmall: #C = random_code(16, 8, 8, 3) C = random_code(7, 1, 1, 2) # n, k, kt, d D = random_code(7, 1, 1, 2) elif argv.samerand: C = random_code(12, 6, 0, 4) D = C elif argv.smallrand: # make some vertical logops from rank degenerate parity check matrices C = random_code(8, 4, 0, 3) D = random_code(6, 3, 0, 2) elif argv.cookup: # [12,6,4] example that has no k-bipuncture C = parse(""" .1..1111.... 111.11111111 11.111...11. 1..11...1.11 .11...1...11 ..11.11.111. """) D = C R = row_reduce(C) print(shortstr(R)) elif argv.cookup2: # [12,6,4] example that has no k-bipuncture C = parse(""" .11..1.11..1 11...1111... 1....1.11111 ..1.1111..1. 111....1.11. 1111.11...11 .1.1.1....1. 1111111.1111 ....1..111.. .1..1.111.11 11.11......1 11..1111.1.. """) D = C elif argv.pair: #C = make_gallagher(9, 12, 3, 4, 4) # big C = make_gallagher(15, 20, 3, 4, 4) # big D = make_gallagher(6, 8, 3, 4, 1) # small elif argv.torus: # Torus C = parse(""" 11.. .11. ..11 1..1 """) D = C elif argv.hamming: C = parse(""" ...1111 .11..11 1.1.1.1 111.... """) D = C elif argv.surf or argv.surface: # Surface C = parse(""" 11.... .11... ..11.. ...11. ....11 """) D = parse(""" 11.. .11. ..11 """) elif argv.small: C = parse("""1111""") D = parse("""1111""") else: print("please specify a code") return print("C: shape=%s, rank=%d, dist=%d" % (C.shape, rank(C), classical_distance(C))) print("C.t: dist=%d" % (classical_distance(C.transpose()), )) print(shortstr(C)) print("D: shape=%s, rank=%d, dist=%d" % (D.shape, rank(D), classical_distance(D))) print("D.t: dist=%d" % (classical_distance(D.transpose()), )) print(shortstr(D)) Ct = C.transpose() Dt = D.transpose() if argv.dual: C, Ct = Ct, C D, Dt = Dt, D if argv.test_puncture: test_puncture(C) return # <--------- return if argv.test_indep: kw = hypergraph_product(C, Dt) test_indep(**kw) return # <--------- return if argv.test_code: kw = hypergraph_product(C, Dt) test_code(**kw) return # <--------- return if argv.test_overlap: #while 1: kw = hypergraph_product(C, Dt) success = test_overlap(**kw) print("success:", success) if argv.success: assert success #if success: # break #else: # sys.exit(0) C = shuff22(C) if argv.same: D = C Dt = D.transpose() else: Dt = shuff22(Dt)
def hypergraph_product(C, D, check=False): print("hypergraph_product: C=%s, D=%s" % (C.shape, D.shape)) c0, c1 = C.shape d0, d1 = D.shape Ic0 = identity2(c0) Id0 = identity2(d0) Ic1 = identity2(c1) Id1 = identity2(d1) Hz0 = kron(Ic1, D.transpose()), kron(C.transpose(), Id1) Hz = numpy.concatenate(Hz0, axis=1) # horizontal concatenate Hx0 = kron(C, Id0), kron(Ic0, D) #print("Hx0:", Hx0[0].shape, Hx0[1].shape) Hx = numpy.concatenate(Hx0, axis=1) # horizontal concatenate assert dot2(Hx, Hz.transpose()).sum() == 0 n = Hz.shape[1] assert Hx.shape[1] == n # --------------------------------------------------- # Build Lz KerC = find_kernel(C) #KerC = min_span(KerC) # does not seem to matter... ?? KerC = rand_span(KerC) # ?? KerC = row_reduce(KerC) assert KerC.shape[1] == c1 K = KerC.transpose() #K = min_span(K) #K = rand_span(K) #E = identity2(d0) #print("c0,c1,d0,d1=", c0, c1, d0, d1) Lzt0 = kron(K, Id0), zeros2(c0 * d1, K.shape[1] * d0) Lzt0 = numpy.concatenate(Lzt0, axis=0) assert dot2(Hx, Lzt0).sum() == 0 KerD = find_kernel(D) K = KerD.transpose() assert K.shape[0] == d1 Lzt1 = zeros2(c1 * d0, K.shape[1] * c0), kron(Ic0, K) Lzt1 = numpy.concatenate(Lzt1, axis=0) assert dot2(Hx, Lzt1).sum() == 0 Lzt = numpy.concatenate((Lzt0, Lzt1), axis=1) # horizontal concatenate Lz = Lzt.transpose() assert dot2(Hx, Lzt).sum() == 0 # These are linearly independent among themselves, but # once we add stabilixers it will be reduced: assert rank(Lz) == len(Lz) # --------------------------------------------------- # Build Lx counit = lambda n: unit2(n).transpose() CokerD = find_cokernel(D) # matrix of row vectors #CokerD = min_span(CokerD) CokerD = rand_span(CokerD) Lx0 = kron(Ic1, CokerD), zeros2(CokerD.shape[0] * c1, c0 * d1) Lx0 = numpy.concatenate(Lx0, axis=1) # horizontal concatenate assert dot2(Lx0, Hz.transpose()).sum() == 0 CokerC = find_cokernel(C) Lx1 = zeros2(CokerC.shape[0] * d1, c1 * d0), kron(CokerC, Id1) Lx1 = numpy.concatenate(Lx1, axis=1) # horizontal concatenate Lx = numpy.concatenate((Lx0, Lx1), axis=0) assert dot2(Lx, Hz.transpose()).sum() == 0 # --------------------------------------------------- # overlap = 0 for lz in Lz: for lx in Lx: w = (lz * lx).sum() overlap = max(overlap, w) assert overlap <= 1, overlap #print("max overlap:", overlap) if 0: # here we assume that Hz/Hx are full rank Hzi = Hz Hxi = Hx assert rank(Hz) == len(Hz) assert rank(Hx) == len(Hx) mz = len(Hz) mx = len(Hx) else: Hzi = remove_dependent(Hz) Hxi = remove_dependent(Hx) mz = rank(Hz) mx = rank(Hx) assert len(Hzi) == mz assert len(Hxi) == mx # --------------------------------------------------- # Lz0, Lz1 = Lzt0.transpose(), Lzt1.transpose() Lzi = independent_logops(Lz, Hzi) Lxi = independent_logops(Lx, Hxi) print("Lzi:", len(Lzi)) print("Lxi:", len(Lxi)) k = len(Lzi) assert len(Lxi) == k assert mz + mx + k == n LziHz = numpy.concatenate((Lzi, Hzi)) assert rank(LziHz) == k + mz LxiHx = numpy.concatenate((Lxi, Hxi)) assert rank(LxiHx) == k + mx return locals()
def process(G, H): m, n = G.shape row = 0 while row < m: col = 0 while G[row, col] == 0: col += 1 assert col >= row swap_col(G, row, col) swap_col(H, row, col) echelon(G, row, row) row += 1 col = row row = 0 m, n = H.shape while row < m: j = col while H[row, j] == 0: j += 1 swap_col(G, col, j) swap_col(H, col, j) echelon(H, row, col) row += 1 col += 1 k = n-m print("G =") print(shortstr(G)) print("H =") print(shortstr(H)) print() A = G[:, k:] B = H[:, :k] assert eq2(A.transpose(), B) if 0: for size in range(2, k): result = search(G, H, size=size, verbose=True) print("search(size=%d): %s"%(size, result)) wd = weight_dist(H) print("H:", wd, sum(wd)) wd = weight_dist(G) print("G:", wd, sum(wd)) r = rank(A) print("rank deficit:", k-r) if r == k: idxs = list(range(k)) jdxs = list(range(k, 2*k)) C = cokernel(B)[0] C = row_reduce(C) rows, cols = C.shape assert rows == n-2*k assert cols == n-k jdxs = list(range(m)) pivots = [] for i in range(rows): for j in range(i, cols): if C[i, j] != 0: pivots.append(j) jdxs.remove(j) break print("C:", pivots) print(shortstr(C)) assert len(jdxs) == k jdxs = [k+i for i in jdxs] assert len( in_support(G, idxs) ) == 0 assert len( in_support(G, jdxs) ) == 0 assert len( in_support(H, idxs) ) == 0 for row in in_support(H, jdxs): print("in_support:", row) assert len( in_support(H, jdxs) ) == 0 print("OK")
def bruhat(): n = argv.get("n", 4) assert n % 2 == 0, repr(n) m = argv.get("m", 2) q = argv.get("q", 2) # symplectic form A = mk_form(n, q) # all non-zero vectors vals = list(range(q)) vecs = list(cross((vals, ) * n)) assert sum(vecs[0]) == 0 vecs.pop(0) # find unique spaces spaces = set() for U in cross_upper(vecs, m): U = numpy.array(U) U.shape = m, n B = numpy.dot(U, numpy.dot(A, U.transpose())) % q if B.max(): continue space = Space(U, q) if space.m != m: continue spaces.add(space) if 0: #space = [str(v) for v in span(U)] # SLOW space = [v.tostring() for v in span(U)] # q==2 only if len(space) != q**m: continue space.sort() #space = ''.join(space) #print(space) space = tuple(space) spaces.add(space) N = len(spaces) print("points:", N) if argv.verbose: for X in spaces: print(X) B = list(borel_sp(n, q)) print("borel:", len(B)) assert len(B) spaces = list(spaces) lookup = dict((space, i) for (i, space) in enumerate(spaces)) orbits = list(set([space]) for space in spaces) perms = [] for g in B: perm = [] for i, space in enumerate(spaces): U = numpy.dot(space.U, g) % q t = Space(U, q) #if t not in lookup: # print(space) # print(t) perm.append(lookup[t]) perms.append(perm) print(".", end=" ", flush=True) print() remain = set(range(N)) orbits = [] while remain: i = iter(remain).__next__() remain.remove(i) orbit = [i] for perm in perms: j = perm[i] if j in remain: remain.remove(j) orbit.append(j) orbits.append(orbit) orbits.sort(key=len) print("%d orbits:" % len(orbits)) for orbit in orbits: print("size =", len(orbit)) for idx in orbit: space = spaces[idx] U = space.U if q == 2: U = row_reduce(U)
def hypergraph_product(C, D, check=False): print("hypergraph_product:", C.shape, D.shape) print("distance:", classical_distance(C)) c0, c1 = C.shape d0, d1 = D.shape E1 = identity2(c0) E2 = identity2(d0) M1 = identity2(c1) M2 = identity2(d1) Hx0 = kron(M1, D.transpose()), kron(C.transpose(), M2) Hx = numpy.concatenate(Hx0, axis=1) # horizontal concatenate Hz0 = kron(C, E2), kron(E1, D) #print("Hz0:", Hz0[0].shape, Hz0[1].shape) Hz = numpy.concatenate(Hz0, axis=1) # horizontal concatenate assert dot2(Hz, Hx.transpose()).sum() == 0 n = Hx.shape[1] assert Hz.shape[1] == n # --------------------------------------------------- # Build Lx KerC = find_kernel(C) #KerC = min_span(KerC) # does not seem to matter... ?? assert KerC.shape[1] == c1 K = KerC.transpose() E = identity2(d0) print(shortstr(KerC)) print() Lxt0 = kron(K, E), zeros2(c0 * d1, K.shape[1] * d0) Lxt0 = numpy.concatenate(Lxt0, axis=0) assert dot2(Hz, Lxt0).sum() == 0 K = find_kernel(D).transpose() assert K.shape[0] == d1 E = identity2(c0) Lxt1 = zeros2(c1 * d0, K.shape[1] * c0), kron(E, K) Lxt1 = numpy.concatenate(Lxt1, axis=0) assert dot2(Hz, Lxt1).sum() == 0 Lxt = numpy.concatenate((Lxt0, Lxt1), axis=1) # horizontal concatenate Lx = Lxt.transpose() assert dot2(Hz, Lxt).sum() == 0 # These are linearly dependent, but # once we add stabilizers it will be reduced: assert rank(Lx) == len(Lx) if 0: # --------------------------------------------------- print(shortstr(Lx)) k = get_k(Lx, Hx) print("k =", k) left, right = [], [] draw = Draw(c0, c1, d0, d1) cols = [] for j in range(d0): # col col = [] for i in range(len(KerC)): # logical op = Lx[i * d0 + j] col.append(op) if j == i: draw.mark_xop(op) if j < d0 / 2: left.append(op) else: right.append(op) cols.append(col) draw.save("output.2") left = array2(left) right = array2(right) print(get_k(left, Hx)) print(get_k(right, Hx)) return # --------------------------------------------------- # Build Lz counit = lambda n: unit2(n).transpose() K = find_cokernel(D) # matrix of row vectors #E = counit(c1) E = identity2(c1) Lz0 = kron(E, K), zeros2(K.shape[0] * c1, c0 * d1) Lz0 = numpy.concatenate(Lz0, axis=1) # horizontal concatenate assert dot2(Lz0, Hx.transpose()).sum() == 0 K = find_cokernel(C) #E = counit(d1) E = identity2(d1) Lz1 = zeros2(K.shape[0] * d1, c1 * d0), kron(K, E) Lz1 = numpy.concatenate(Lz1, axis=1) # horizontal concatenate Lz = numpy.concatenate((Lz0, Lz1), axis=0) assert dot2(Lz, Hx.transpose()).sum() == 0 overlap = 0 for lx in Lx: for lz in Lz: w = (lx * lz).sum() overlap = max(overlap, w) assert overlap <= 1, overlap #print("max overlap:", overlap) assert rank(Hx) == len(Hx) assert rank(Hz) == len(Hz) mx = len(Hx) mz = len(Hz) # --------------------------------------------------- Lxs = [] for op in Lx: op = (op + Hx) % 2 Lxs.append(op) LxHx = numpy.concatenate(Lxs) LxHx = row_reduce(LxHx) print("LxHx:", len(LxHx)) assert LxHx.shape[1] == n print(len(intersect(LxHx, Hx)), mx) assert len(intersect(LxHx, Hx)) == mx Lzs = [] for op in Lz: op = (op + Hz) % 2 Lzs.append(op) LzHz = numpy.concatenate(Lzs) LzHz = row_reduce(LzHz) print("LzHz:", len(LzHz)) assert LzHz.shape[1] == n # --------------------------------------------------- # Remove excess logops. # print("remove_dependent") # # # -------- Lx # # Lx, Lx1 = mk_disjoint_logops(Lx, Hx) # # # -------- Lz # # Lz, Lz1 = mk_disjoint_logops(Lz, Hz) # -------------------------------- # independent_logops for Lx k = get_k(Lx, Hx) idxs0, idxs1 = [], [] for j in range(d0): # col for i in range(c1): idx = j + i * d0 if j < d0 // 2: idxs0.append(idx) else: idxs1.append(idx) Lx0 = in_support(LxHx, idxs0) Lx0 = independent_logops(Lx0, Hx) k0 = (len(Lx0)) Lx1 = in_support(LxHx, idxs1) Lx1 = independent_logops(Lx1, Hx) k1 = (len(Lx1)) assert k0 == k1 == k, (k0, k1, k) # -------------------------------- # independent_logops for Lz idxs0, idxs1 = [], [] for j in range(d0): # col for i in range(c1): idx = j + i * d0 if i < c1 // 2: idxs0.append(idx) else: idxs1.append(idx) Lz0 = in_support(LzHz, idxs0) Lz0 = independent_logops(Lz0, Hz) k0 = (len(Lz0)) Lz1 = in_support(LzHz, idxs1) Lz1 = independent_logops(Lz1, Hz) k1 = (len(Lz1)) assert k0 == k1 == k, (k0, k1, k) # --------------------------------------------------- # #assert eq2(dot2(Lz, Lxt), identity2(k)) assert mx + mz + k == n print("mx = %d, mz = %d, k = %d : n = %d" % (mx, mz, k, n)) # --------------------------------------------------- # # if Lx1 is None: # return # # if Lz1 is None: # return # --------------------------------------------------- # op = zeros2(n) for lx in Lx0: for lz in Lz0: lxz = lx * lz #print(lxz) #print(op.shape, lxz.shape) op += lxz for lx in Lx1: for lz in Lz1: lxz = lx * lz #print(lxz) #print(op.shape, lxz.shape) op += lxz idxs = numpy.where(op)[0] print("correctable region size = %d" % len(idxs)) #print(op) #print(idxs) Lx, Lz = Lx0, Lz0 Lxs = [] for op in Lx: op = (op + Hx) % 2 Lxs.append(op) LxHx = numpy.concatenate(Lxs) LxHx = row_reduce(LxHx) assert LxHx.shape[1] == n Lzs = [] for op in Lz: op = (op + Hz) % 2 Lzs.append(op) LzHz = numpy.concatenate(Lzs) LzHz = row_reduce(LzHz) assert LzHz.shape[1] == n if argv.draw: do_draw(**locals()) good = is_correctable(n, idxs, LxHx, LzHz) assert good print("good") # --------------------------------------------------- # if argv.code: print("code = CSSCode()") code = CSSCode(Hx=Hx, Hz=Hz, Lx=Lx, Lz=Lz, check=True, verbose=False, build=True) print(code) #print(code.weightstr()) if check: U = solve(Lx.transpose(), code.Lx.transpose()) assert U is not None #print(U.shape) assert eq2(dot2(U.transpose(), Lx), code.Lx) #print(shortstr(U)) if 0: Lx, Lz = code.Lx, code.Lz print("Lx:", Lx.shape) print(shortstr(Lx)) print("Lz:", Lz.shape) print(shortstr(Lz))
def main(): import models assert not argv.orbiham, "it's called orbigraph now" if argv.find_ideals: find_ideals() return Gx, Gz, Hx, Hz = models.build() if argv.chainmap: do_chainmap(Gx, Gz) if argv.symmetry: do_symmetry(Gx, Gz, Hx, Hz) return #print shortstrx(Gx, Gz) if argv.report: print("Hz:") for i, h in enumerate(Hz): print(i, shortstr(h), h.sum()) #print shortstr(find_stabilizers(Gx, Gz)) Lz = find_logops(Gx, Hz) Lx = find_logops(Gz, Hx) #print "Lz:", shortstr(Lz) if Lz.shape[0]*Lz.shape[1]: print(Lz.shape, Gx.shape) check_commute(Lz, Gx) check_commute(Lz, Hx) Px = get_reductor(Hx) # projector onto complement of rowspan of Hx Pz = get_reductor(Hz) Rz = [dot2(Pz, g) for g in Gz] Rz = array2(Rz) Rz = row_reduce(Rz, truncate=True) rz = len(Rz) n = Gx.shape[1] print("n =", n) if len(Lx): print("Lx Lz:") print(shortstrx(Lx, Lz)) print("Hx:", len(Hx), "Hz:", len(Hz)) print("Gx:", len(Gx), "Gz:", len(Gz)) Rx = [dot2(Px, g) for g in Gx] Rx = array2(Rx) Rx = row_reduce(Rx, truncate=True) rx = len(Rx) print("Rx:", rx, "Rz:", rz) if argv.show: print(shortstrx(Rx, Rz)) Qx = u_inverse(Rx) Pxt = Px.transpose() assert eq2(dot2(Rx, Qx), identity2(rx)) assert eq2(dot2(Rx, Pxt), Rx) #print shortstr(dot2(Pxt, Qx)) PxtQx = dot2(Pxt, Qx) lines = [shortstr(dot2(g, PxtQx)) for g in Gx] lines.sort() #print "PxtQx:" #for s in lines: # print s #print "RzRxt" #print shortstr(dot2(Rz, Rx.transpose())) offset = argv.offset if len(Hz): Tx = find_errors(Hz, Lz, Rz) else: Tx = zeros2(0, n) if argv.dense: dense(**locals()) return if argv.dense_full: dense_full(**locals()) return if argv.show_delta: show_delta(**locals()) return if argv.slepc: slepc(**locals()) return # if argv.orbigraph: # from linear import orbigraph # orbigraph(**locals()) # return v0 = None # excite = argv.excite # if excite is not None: # v0 = zeros2(n) # v0[excite] = 1 verts = [] lookup = {} for i, v in enumerate(span(Rx)): # XXX does not scale well if v0 is not None: v = (v+v0)%2 v = dot2(Px, v) lookup[v.tobytes()] = i verts.append(v) print("span:", len(verts)) assert len(lookup) == len(verts) mz = len(Gz) n = len(verts) if argv.lie: U = [] for i, v in enumerate(verts): count = dot2(Gz, v).sum() Pxv = dot2(Px, v) assert count == dot2(Gz, Pxv).sum() U.append(mz - 2*count) uniq = list(set(U)) uniq.sort(reverse=True) s = ', '.join("%d(%d)"%(val, U.count(val)) for val in uniq) print(s) print("sum:", sum(U)) return if n <= 1024 and argv.solve: H = numpy.zeros((n, n)) syndromes = [] for i, v in enumerate(verts): syndromes.append(dot2(Gz, v)) count = dot2(Gz, v).sum() Pxv = dot2(Px, v) assert count == dot2(Gz, Pxv).sum() H[i, i] = mz - 2*count for g in Gx: v1 = (g+v)%2 v1 = dot2(Px, v1) j = lookup[v1.tobytes()] H[i, j] += 1 if argv.showham: s = lstr2(H, 0).replace(', ', ' ') s = s.replace(' 0', ' .') s = s.replace(', -', '-') print(s) vals, vecs = numpy.linalg.eigh(H) show_eigs(vals) if argv.show_partition: beta = argv.get("beta", 1.0) show_partition(vals, beta) if argv.orbigraph: if argv.symplectic: H1 = build_orbigraph(H, syndromes) else: H1 = build_orbigraph(H) print("orbigraph:") print(H1) vals, vecs = numpy.linalg.eig(H1) show_eigs(vals) elif argv.sparse: print("building H", end=' ') A = {} # adjacency U = [] # potential if offset is None: offset = mz + 1 # make H positive definite for i, v in enumerate(verts): if i%1000==0: write('.') count = dot2(Gz, v).sum() #H[i, i] = mz - 2*count U.append(offset + mz - 2*count) for g in Gx: v1 = (g+v)%2 v1 = dot2(Px, v1) j = lookup[v1.tobytes()] A[i, j] = A.get((i, j), 0) + 1 print("\nnnz:", len(A)) if argv.lanczos: vals, vecs = do_lanczos(A, U) elif argv.orbigraph: vals, vecs = do_orbigraph(A, U) else: return vals -= offset # offset doesn't change vecs show_eigs(vals) elif argv.orbigraph: assert n<=1024 H = numpy.zeros((n, n)) syndromes = [] for i, v in enumerate(verts): syndromes.append(dot2(Gz, v)) count = dot2(Gz, v).sum() Pxv = dot2(Px, v) assert count == dot2(Gz, Pxv).sum() H[i, i] = mz - 2*count for g in Gx: v1 = (g+v)%2 v1 = dot2(Px, v1) j = lookup[v1.tobytes()] H[i, j] += 1 if argv.showham: s = lstr2(H, 0).replace(', ', ' ') s = s.replace(' 0', ' .') s = s.replace(', -', '-') print(s) if argv.symplectic: H1 = build_orbigraph(H, syndromes) else: H1 = build_orbigraph(H)
def dense_full(Gx, Gz, Hx, Hz, Rx, Pxt, Qx, Pz, Tx, **kw): " find orbigraph for hamiltonian component Gamma " gz, n = Gz.shape if argv.excite: excites = [argv.excite] else: excites = genidx((2,)*len(Tx)) for excite in excites: print("excite:", excite) assert len(excite)==len(Tx) t = zeros2(n) for i, ex in enumerate(excite): if ex: t = (t + Tx[i])%2 #print "t:", shortstr(t) Gzt = dot2(Gz, t) #print "Gzt:", shortstr(Gzt) # This is our basis Bx = array2([v+t for v in Rx] + [v+t for v in Hx]) Bx %= 2 r = len(Bx) N = 2**r Bx = row_reduce(Bx, truncate=True) assert len(Bx)==r # linearly independent rows Cx = u_inverse(Bx) if N<=1024: H = numpy.zeros((N, N)) else: H = None A = {} U = [] #for i in range(N): pos = neg = 0 for i, v in enumerate(genidx((2,)*r)): v = array2(v) syndrome = dot2(Gz, Bx.transpose(), v) value = gz - 2*syndrome.sum() #print shortstr(dot2(Rx.transpose(), v)), value if H is not None: H[i, i] = value U.append(value) for i, v in enumerate(genidx((2,)*r)): v = array2(v) u0 = dot2(Bx.transpose(), v) #print shortstr(v), for g in Gx: u1 = (u0 + g) % 2 v1 = dot2(Cx.transpose(), u1) assert v1.shape == v.shape j = eval('0b'+shortstr(v1, zero='0')) if H is not None: H[i, j] += 1 A[i, j] = A.get((i, j), 0) + 1 #print H if argv.orbistab: hx = Hx[0] do_orbistab(Bx, Cx, H, hx) if argv.orbigraph: vals, vecs = do_orbigraph(A, U) show_eigs(vals) if argv.solve: assert N <= 1024 assert numpy.allclose(H, H.transpose()) vals, vecs = numpy.linalg.eigh(H) if argv.show_eigs: show_eigs(vals) #print vals vals = list(vals) vals.sort() val0 = vals[-1] # top one is last vec0 = vecs[:,-1] if vec0[0] < 0: vec0 = -vec0 assert vals[-2] < val0 - 1e-4 print("excite:", excite, end=' ') print("eigval:", val0)
def hypergraph_product(A, B, check=False): #print("hypergraph_product: A=%s, B=%s"%(A.shape, B.shape)) ma, na = A.shape mb, nb = B.shape Ima = identity2(ma) Imb = identity2(mb) Ina = identity2(na) Inb = identity2(nb) Hz0 = kron(Ina, B.transpose()), kron(A.transpose(), Inb) Hz = numpy.concatenate(Hz0, axis=1) # horizontal concatenate Hx0 = kron(A, Imb), kron(Ima, B) #print("Hx0:", Hx0[0].shape, Hx0[1].shape) Hx = numpy.concatenate(Hx0, axis=1) # horizontal concatenate assert dot2(Hx, Hz.transpose()).sum() == 0 n = Hz.shape[1] assert Hx.shape[1] == n # --------------------------------------------------- # Build Lz KerA = find_kernel(A) #KerA = rand_rowspan(KerA) # ?? KerA = row_reduce(KerA) ka = len(KerA) assert KerA.shape[1] == na K = KerA.transpose() #K = rand_rowspan(K) #E = identity2(mb) #print("ma,na,mb,nb=", ma, na, mb, nb) Lzt0 = kron(K, Imb), zeros2(ma*nb, K.shape[1]*mb) Lzt0 = numpy.concatenate(Lzt0, axis=0) assert dot2(Hx, Lzt0).sum() == 0 KerB = find_kernel(B) KerB = row_reduce(KerB) kb = len(KerB) K = KerB.transpose() assert K.shape[0] == nb Lzt1 = zeros2(na*mb, K.shape[1]*ma), kron(Ima, K) Lzt1 = numpy.concatenate(Lzt1, axis=0) assert dot2(Hx, Lzt1).sum() == 0 Lzt = numpy.concatenate((Lzt0, Lzt1), axis=1) # horizontal concatenate Lz = Lzt.transpose() assert dot2(Hx, Lzt).sum() == 0 # These are linearly independent among themselves, but # once we add stabilizers it will be reduced: assert rank(Lz) == len(Lz) # --------------------------------------------------- # Build Lx counit = lambda n : unit2(n).transpose() CokerB = find_cokernel(B) # matrix of row vectors #CokerB = rand_rowspan(CokerB) assert rank(CokerB)==len(CokerB) kbt = len(CokerB) Lx0 = kron(Ina, CokerB), zeros2(CokerB.shape[0]*na, ma*nb) Lx0 = numpy.concatenate(Lx0, axis=1) # horizontal concatenate assert dot2(Lx0, Hz.transpose()).sum() == 0 CokerA = find_cokernel(A) assert rank(CokerA)==len(CokerA) kat = len(CokerA) Lx1 = zeros2(CokerA.shape[0]*nb, na*mb), kron(CokerA, Inb) Lx1 = numpy.concatenate(Lx1, axis=1) # horizontal concatenate Lx = numpy.concatenate((Lx0, Lx1), axis=0) assert dot2(Lx, Hz.transpose()).sum() == 0 #print(ka, kat, kb, kbt) # --------------------------------------------------- # overlap = 0 for lz in Lz: for lx in Lx: w = (lz*lx).sum() overlap = max(overlap, w) assert overlap <= 1, overlap #print("max overlap:", overlap) if 0: # here we assume that Hz/Hx are full rank Hzi = Hz Hxi = Hx assert rank(Hz) == len(Hz) assert rank(Hx) == len(Hx) mz = len(Hz) mx = len(Hx) else: Hzi = remove_dependent(Hz) Hxi = remove_dependent(Hx) mz = rank(Hz) mx = rank(Hx) assert len(Hzi) == mz assert len(Hxi) == mx # --------------------------------------------------- # Lz0, Lz1 = Lzt0.transpose(), Lzt1.transpose() Lzi = independent_logops(Lz, Hzi) Lxi = independent_logops(Lx, Hxi) #print("Lzi:", len(Lzi)) #print("Lxi:", len(Lxi)) k = len(Lzi) assert len(Lxi) == k assert mz + mx + k == n LziHz = numpy.concatenate((Lzi, Hzi)) assert rank(LziHz) == k+mz LxiHx = numpy.concatenate((Lxi, Hxi)) assert rank(LxiHx) == k+mx return locals()