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 test_glue(): m = argv.get("m", 9) n = argv.get("n", 10) d = argv.get("d", 0) p = argv.get("p", 0.5) weight = argv.weight H1 = rand2(m, n, p, weight) G1 = find_kernel(H1) G1t = G1.transpose() H1t = H1.transpose() A1 = Chain([G1, H1t]) k1 = len(G1) print("H1") print(fstr(H1)) print() print(fstr(G1)) w = wenum(H1) print("wenum:", [len(wi) for wi in w]) H2 = rand2(m, n, p, weight) H2t = H2.transpose() G2 = find_kernel(H2) G2t = G2.transpose() A2 = Chain([G2, H2t]) k2 = len(G2) print("H2") print(fstr(H2)) print() print(fstr(G2)) w = wenum(H2) print("wenum:", [len(wi) for wi in w]) if k1 != k2: return k = k1 I = identity2(k) B = Chain([I, zeros2(k, 0)]) a = zeros2(n, k) for i in range(k): a[i, i] = 1 f1 = Morphism(B, A1, [dot2(G1, a), a, zeros2(m, 0)]) f2 = Morphism(B, A2, [dot2(G2, a), a, zeros2(m, 0)]) a, b, C, _ = chain.pushout(f1, f2) H = C[1].transpose() print("H:") print(fstr(H)) w = wenum(H) print("wenum:", [len(wi) for wi in w])
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 C = make_gallagher(r, n, l, m, d) 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.torus: # Torus C = parse(""" 11.. .11. ..11 1..1 """) D = C elif argv.hamming: C = parse(""" ...1111 .11..11 1.1.1.1 """) D = C elif argv.surf or argv.surface: # Surface C = parse(""" 11.. .11. ..11 """) D = C else: return Ct = C.transpose() Dt = D.transpose() hypergraph_product(C, Dt)
def solve(self, H, minimize=True, verbose=True): m, n = H.shape # rows, cols u1 = self.u1 assert u1.shape == (m, ) rows = [i for i in range(m) if u1[i]] #print rows H = H[rows, :] u0 = self.u0[rows] v = self.v cols = [i for i in range(n) if v[i]] #print cols H = H[:, cols] assert cols, self.u0 #print shortstr(H) #print "u0:", shortstr(u0) if verbose: print("Cluster.solve:", H.shape) v = solve.solve(H, u0) if v is None: return if minimize: kern = solve.find_kernel(H) if kern: kern = array2(kern) write("[w=%d, kern=%d, " % (v.sum(), len(list(kern)))) graph = dynamic.Tanner(kern) #v = graph.minimize(v, target=30, verbose=True) v = graph.localmin(v, verbose=True) write("w=%d]" % v.sum()) #u = dot(H, v) #assert numpy.abs(u-u0).sum() == 0 v0 = numpy.zeros((n, ), dtype=numpy.int32) v0[cols] = v #print "v0:", shortstr(v0) #write("[%d]"%v0.sum()) return v0
def show_stabx(self, sx): gxs = [] for gx in self.Gx: if eq2(gx * sx, gx): gxs.append(gx) Gx = array2(gxs) #print "Gx:", Gx.shape #print shortstr(Gx) print("sx.sum() =", sx.sum(), end=' ') Gxt = Gx.transpose() K = find_kernel(Gxt) #print "kernel:", K K = array2(K) #print "kernel:", len(K) #print shortstr(K) #print best = None ubest = None u = solve(Gxt, sx) for w in enum2(len(K)): u2 = (u + dot2(w, K)) % 2 if best is None or u2.sum() < best: best = u2.sum() ubest = u2 print("u.sum() =", u2.sum(), end=' ') print()
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 shorten(G, i): print(shortstrx(G)) H = array2(list(find_kernel(G))) m, n = H.shape H1 = zeros2(m + 1, n) H1[:m, :] = H H1[m, i] = 1 print() print(shortstrx(H1)) print() G1 = array2(list(find_kernel(H1))) m, n = G1.shape G2 = zeros2(m, n - 1) G2[:, :i] = G1[:, :i] G2[:, i:] = G1[:, i + 1:] print() print(shortstrx(G2)) print(strong_morthogonal(G2, 2)) H2 = array2(list(find_kernel(G2))) print(classical_distance(H2))
def wenum(H): m, n = H.shape K = find_kernel(H) #print(H) #print(K) w = dict((i, []) for i in range(n + 1)) for v in image(K.transpose()): assert dot2(H, v).sum() == 0 w[v.sum()].append(v) w = [w[i] for i in range(n + 1)] return w
def sparsecss_FAIL(n, mx, mz, weight=3, **kw): print("sparsecss", n, mx, mz) k = n-mx-mz assert k>=0 Hz = rand2(mz, n, weight=weight) #print shortstrx(Hx) kern = numpy.array(solve.find_kernel(Hz)) mkern = kern.shape[0] print("kern:") print(shortstr(kern)) print() kern1 = zeros2(mkern, n) for i in range(mkern): v = rand2(1, mkern) kern1[i] = dot2(v, kern) print("kern1:") print(shortstr(kern1)) print() kern = kern1 Hx = [] for i in range(mx): j = randint(0, mkern-1) v = kern[j].copy() count = 0 while 1: v += kern[randint(0, mkern-1)] v %= 2 w = v.sum() if w==weight and count > 100: break count += 1 Hx.append(v) Hx = array2(Hx) print(shortstrx(Hx)) C = CSSCode(Hx=Hx, Hz=Hz, **kw) return C
def classical_distance(H, max_dist=0): if max_dist == 0: return max_dist n = H.shape[1] dist = n K = find_kernel(H) K = numpy.array(K) Kt = K.transpose() for u in numpy.ndindex((2, ) * K.shape[0]): v = dot2(Kt, u) if 0 < v.sum() < dist: dist = v.sum() #if dist<=max_dist: # break return dist
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 main(): # test that robustness is equiv. to full-rank property #n, k, kt, d = 8, 4, 0, 1 cw = argv.get("cw", 3) # column weight rw = argv.get("rw", 4) # row weight n = argv.get("n", 8) # cols m = argv.get("m", n * cw // rw) # rows d = argv.get("d", 1) # distance rank = argv.get("rank", 0) print("m =", m) trials = argv.get("trials", 1000) while 1: #H = random_code(n, k, kt, d) H = make_gallagher(m, n, cw, rw, d) if len(H) < rank: continue G = find_kernel(H) print() print("__" * 20) print("G:%sH:" % (' ' * (n - 1), )) print(shortstrx(G, H)) print(G.shape, H.shape) result = get_bipuncture(G, H, trials) print("get_bipuncture:", result) robust = result is not None if robust: idxs, jdxs = result build_echelon(G, H, idxs, jdxs) rhs = has_property(G, trials) assert robust == rhs, (robust, rhs) #assert not rhs or robust # rhs ==> robust #print(robust) print() if argv.robust: assert robust
def get_bipuncture(H, G=None, verbose=True): n = H.shape[1] if G is None: G = find_kernel(H) k = len(G) if verbose: print(shortstrx(G, H)) while 1: # copied from classical.py idxs = set() while len(idxs) < k: idx = randint(0, n - 1) idxs.add(idx) idxs = list(idxs) idxs.sort() G1 = in_support(G, idxs) if len(G1): continue jdxs = set() while len(jdxs) < k: jdx = randint(0, n - 1) if jdx not in idxs: jdxs.add(jdx) jdxs = list(jdxs) jdxs.sort() G2 = in_support(G, jdxs) if len(G2) == 0: break if 0: v = zeros2(1, n) v[:, idxs] = 1 print(shortstr(v)) v = zeros2(1, n) v[:, jdxs] = 1 print(shortstr(v)) if verbose: print("in_support(H):", in_support(H, idxs), in_support(H, jdxs)) return idxs, jdxs
def main(): n = argv.get("n", 8) k = argv.get("k", 4) kt = argv.get("kt", 4) d = argv.get("d", 1) # distance na = argv.get("na", n) nb = argv.get("nb", n) ka = argv.get("ka", k) kat = argv.get("kat", kt) kb = argv.get("kb", k) kbt = argv.get("kbt", kt) A = random_code(na, ka, kat, d) B = random_code(nb, kb, kbt, d) #assert A.shape == (na-ka, na), (A.shape,) #assert B.shape == (nb-kb, nb), (B.shape,) print("A, B:") print(shortstrx(A, B)) if 1: # A tensor B kw = hypergraph_product(A, B) test_puncture(**kw) else: # -------------------------------------- #B, Bt = Bt, B KerA = find_kernel(A).transpose() ma = na-ka mb = nb-kb print("KerA:") print(shortstrx(KerA)) print() # print(shortstrx(kron(KerA, identity2(mb)))) print(shortstrx( kron(identity2(mb), KerA), kron(B, identity2(na))))
def randcss(n, mx, mz, distance=None, **kw): """ http://arxiv.org/abs/quant-ph/9512032 Quantum error-correcting codes exist with asymptotic rate: k/n = 1 - 2H(2t/n) where H(p) = -p log p - (1-p) log (1-p) and t = floor((d-1)/2). """ while 1: k = n-mx-mz assert k>=0 #print "rate:", 1.*k//n #H = lambda p: -p*log(p) - (1-p)*log(1-p) #d = 56 #print 1-2*H(1.*d//n) # works! Hz = rand2(mz, n) #print shortstrx(Hx) kern = numpy.array(solve.find_kernel(Hz)) Hx = zeros2(mx, n) for i in range(mx): v = rand2(1, n-mx) Hx[i] = dot2(v, kern) C = CSSCode(Hx=Hx, Hz=Hz, **kw) if distance is None: break d = lookup_distance(C) if d < distance: continue d = lookup_distance(C.dual()) if d < distance: continue break return C
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 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 main(): n = argv.get("n", 8) k = argv.get("k", 4) assert 2*k<=n m = n-k dist = argv.get("dist", 2) Hdist = argv.get("Hdist", dist) max_tries = argv.get("max_tries", 1000) verbose = argv.verbose trials = argv.get("trials", 100000) count = 0 fails = 0 if argv.all_codes: gen = all_codes(m, n) elif argv.get_codes: gen = get_codes(m, n) elif argv.gallagher: cw = argv.get("cw", 3) # column weight rw = argv.get("rw", 4) # row weight m = argv.get("m", n*cw//rw) # rows n = argv.get("n", 12) # cols def gen(trials=1000, m=m, n=n, cw=cw, rw=rw, dist=dist): for _ in range(trials): H = make_gallagher(m, n, cw, rw, dist) yield H gen = gen(trials) elif argv.wedge: H = zeros2(m, n) H[0, :k+1] = 1 H[:, k-1] = 1 for i in range(m): H[i, i+k] = 1 gen = [H] #print(shortstr(H)) #print() elif argv.cookup: # fail gen = [parse(""" 1111........ ..1.1....... ..1..1...... ..1...1..... ..1....1.... ..1.....1... ..1......1.. ..1.......1. ..1........1 """)] gen = [parse(""" ....11...... ....1.1..... ....1..1.... ....1...1... 1.111....1.. .111......1. 11.11......1 """)] else: gen = rand_codes(m, n, trials) #assert Hdist == 2 for H in gen: m, n = H.shape assert rank(H) == m k = n-m dH = min_weight(H) if dH < Hdist: #print("[dH=%d]"%dH, end="", flush=True) continue G = find_kernel(H) #print(shortstr(G)) dG = min_weight(G) if dG < dist: #print("[dG=%d]"%dG, end="", flush=True) continue print("") result = search(G, H, max_tries) count += 1 print("result =", result) process(G, H) if result: if not argv.silent: print(".", end="", flush=True) continue if not argv.silent: print("|") if not result: if not argv.noassert: assert 0, "FAIL" fails += 1 print() print("codes found: %d, fails %d"%(count, fails))
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 build_from_gauge(self, check=True, verbose=False): write("build_from_gauge:") Gx, Gz = self.Gx, self.Gz Hx, Hz = self.Hx, self.Hz Lx, Lz = self.Lx, self.Lz #print "build_stab" #print shortstr(Gx) #vs = solve.find_kernel(Gx) #vs = list(vs) #print "kernel Gx:", len(vs) n = Gx.shape[1] if Hz is None: A = dot2(Gx, Gz.transpose()) vs = solve.find_kernel(A) vs = list(vs) #print "kernel GxGz^T:", len(vs) Hz = zeros2(len(vs), n) for i, v in enumerate(vs): Hz[i] = dot2(v.transpose(), Gz) Hz = solve.linear_independent(Hz) if Hx is None: A = dot2(Gz, Gx.transpose()) vs = solve.find_kernel(A) vs = list(vs) Hx = zeros2(len(vs), n) for i, v in enumerate(vs): Hx[i] = dot2(v.transpose(), Gx) Hx = solve.linear_independent(Hx) if check: check_commute(Hz, Hx) check_commute(Hz, Gx) check_commute(Hx, Gz) #Gxr = numpy.concatenate((Hx, Gx)) #Gxr = solve.linear_independent(Gxr) #print(Hx.shape) #assert rank(Hx) == len(Hx) #assert eq2(Gxr[:len(Hx)], Hx) #Gxr = Gxr[len(Hx):] Px = solve.get_reductor(Hx).transpose() Gxr = dot2(Gx, Px) Gxr = solve.linear_independent(Gxr) #Gzr = numpy.concatenate((Hz, Gz)) #Gzr = solve.linear_independent(Gzr) #assert eq2(Gzr[:len(Hz)], Hz) #Gzr = Gzr[len(Hz):] Pz = solve.get_reductor(Hz).transpose() Gzr = dot2(Gz, Pz) Gzr = solve.linear_independent(Gzr) if Lx is None: Lx = solve.find_logops(Gz, Hx) if Lz is None: Lz = solve.find_logops(Gx, Hz) write('\n') print("Gxr", Gxr.shape) print("Gzr", Gzr.shape) assert len(Gxr)==len(Gzr) kr = len(Gxr) V = dot2(Gxr, Gzr.transpose()) U = solve.solve(V, identity2(kr)) assert U is not None Gzr = dot2(U.transpose(), Gzr) if check: check_conjugate(Gxr, Gzr) check_commute(Hz, Gxr) check_commute(Hx, Gzr) check_commute(Lz, Gxr) check_commute(Lx, Gzr) assert len(Lx)+len(Hx)+len(Hz)+len(Gxr)==n self.Lx, self.Lz = Lx, Lz self.Hx, self.Hz = Hx, Hz self.Gxr, self.Gzr = Gxr, Gzr
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 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()
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 test_puncture(A, B, ma, na, mb, nb, Ina, Ima, Inb, Imb, ka, kb, kat, kbt, k, KerA, KerB, CokerA, CokerB, Lzi, Lxi, Hzi, Hxi, **kw): I = identity2 assert ka - na + ma -kat == 0 assert kb - nb + mb -kbt == 0 #print("ka=%s, kat=%s, kb=%s, kbt=%s"%(ka, kat, kb, kbt)) assert k == ka*kbt + kat*kb == len(Lzi) == len(Lxi) kernel = lambda X : find_kernel(X).transpose() # use convention in paper KerA = KerA.transpose() # use convention in paper KerB = KerB.transpose() # use convention in paper #CokerA = CokerA.transpose() # use convention in paper #CokerB = CokerB.transpose() # use convention in paper assert CokerA.shape == (kat, ma) assert CokerB.shape == (kbt, mb) blocks = [ [kron(KerA, Imb), zeros2(na*mb, ma*kb), kron(Ina, B)], [zeros2(ma*nb, ka*mb), kron(Ima, KerB), kron(A,Inb)], ] print("blocks:", [[X.shape for X in row] for row in blocks]) #print(shortstrx(*blocks[0])) #print() #print(shortstrx(*blocks[1])) Mv = cat((blocks[0][0], blocks[0][2]), axis=1) Mh = cat((blocks[1][0], blocks[1][2]), axis=1) M = cat((Mv, Mh), axis=0) KM = kernel(M) Mv = cat(blocks[0], axis=1) Mh = cat(blocks[1], axis=1) M = cat((Mv, Mh), axis=0) x = kron(I(ka), B) dot2(blocks[0][0], x) y = zeros2(blocks[0][1].shape[1], x.shape[1]) dot2(blocks[0][1], y) z = kron(KerA, I(nb)) dot2(blocks[0][2], z) #print(shortstr(x)+'\n') #print(shortstr(y)+'\n') #print(shortstr(z)+'\n') xz = cat((x, z), axis=0) xyz = cat((x, y, z), axis=0) assert dot2(M, xyz).sum() == 0 #print(shortstr(xyz)) print("xyz:", xyz.shape) assert len(find_kernel(xyz))==0 assert rowspan_eq(KM.transpose(), xz.transpose()) print("kernel(M):", kernel(M).shape) Hzt = cat((blocks[0][2], blocks[1][2]), axis=0) #print("kernel(Hzt):", kernel(Hzt).shape) KHzt = kernel(Hzt) #assert KHzt.shape[1] == 0, (KHzt.shape,) print("kernel(Hzt):", KHzt.shape) Hx = cat((kron(A, I(mb)), kron(I(ma), B)), axis=1) #print("CokerB") #print(shortstr(CokerB)) #R = CokerB #R = rand2(CokerB.shape[0], CokerB.shape[1]) #R = rand2(mb, 1) #R = CokerB[:, 0:1] if argv.puncture and 1: idxs = get_puncture(B.transpose(), kbt) print("get_puncture:", idxs) R = zeros2(mb, len(idxs)) for i, idx in enumerate(idxs): R[idx, i] = 1 elif argv.puncture: idxs = get_puncture(B.transpose(), kbt) R = zeros2(mb, 1) R[idxs] = 1 elif argv.identity2: R = I(mb) else: R = B[:, :1] #R = rand2(mb, 100) print("R:") print(shortstrx(R)) lzt = cat((kron(KerA, R), zeros2(ma*nb, KerA.shape[1]*R.shape[1])), axis=0) print("lzt:", lzt.shape) print(shortstrx(lzt)) print("Hzt:", Hzt.shape) print(shortstrx(Hzt)) assert dot2(Hx, lzt).sum()==0 lz = lzt.transpose() Hz = Hzt.transpose() print(rank(lz), rank(Hz), rank(intersect(lz, Hz))) result = rowspan_le(lzt.transpose(), Hzt.transpose()) print("lzt <= Hzt:", result) if argv.puncture: assert not result assert not rank(intersect(lz, Hz)) print("OK")
def test(A, B, ma, na, mb, nb, Ina, Ima, Inb, Imb, ka, kb, kat, kbt, k, KerA, KerB, CokerA, CokerB, Lzi, Lxi, Hzi, Hxi, **kw): #print("ka=%s, kat=%s, kb=%s, kbt=%s"%(ka, kat, kb, kbt)) assert k == ka*kbt + kat*kb == len(Lzi) == len(Lxi) KerA = KerA.transpose() # use convention in paper KerB = KerB.transpose() # use convention in paper CokerA = CokerA.transpose() # use convention in paper CokerB = CokerB.transpose() # use convention in paper blocks = [ [kron(KerA, Imb), zeros2(na*mb, ma*kb), kron(Ina, B)], [zeros2(ma*nb, ka*mb), kron(Ima, KerB), kron(A,Inb)], ] print("blocks:", [[X.shape for X in row] for row in blocks]) #print(shortstrx(*blocks[0])) #print() #print(shortstrx(*blocks[1])) Hzt = cat((blocks[0][2], blocks[1][2]), axis=0) K = find_kernel(Hzt) assert len(K) == ka*kb # see proof of Lemma 3 Lzv = cat((blocks[0][0], blocks[1][0])).transpose() Lzh = cat((blocks[0][1], blocks[1][1])).transpose() assert dot2(Hxi, Lzv.transpose()).sum() == 0 # Hz = Hzt.transpose() # Hzi = linear_independent(Hz) # Lzhi = independent_logops(Lzh, Hzi, verbose=True) # print("Lzhi:", Lzhi.shape) # -------------------------------------------------------- # basis for all logops, including stabilizers lz = find_kernel(Hxi) # returns transpose of kernel #lz = rand_rowspan(lz) #print("lz:", lz.shape) assert len(lz) == k+len(Hzi) # vertical qubits Iv = cat((identity2(na*mb), zeros2(ma*nb, na*mb)), axis=0).transpose() # horizontal qubits Ih = cat((zeros2(na*mb, ma*nb), identity2(ma*nb)), axis=0).transpose() assert len(intersect(Iv, Ih))==0 # sanity check # now restrict these logops to vertical qubits #print("Iv:", Iv.shape) lzv = intersect(Iv, lz) #print("lzv:", lzv.shape) J = intersect(lzv, Lzv) assert len(J) == len(lzv) # -------------------------------------------------------- # now we manually build _lz supported on vertical qubits x = rand2(ka*mb, ka*nb) y = kron(KerA, Inb) assert eq2(dot2(blocks[0][2], y), kron(KerA, B)) v = (dot2(blocks[0][0], x) + dot2(blocks[0][2], y)) % 2 h = zeros2(ma*nb, v.shape[1]) _lzt = cat((v, h)) assert dot2(Hxi, _lzt).sum() == 0 #print(shortstr(_lzt)) _lz = _lzt.transpose() _lz = linear_independent(_lz) #print("*"*(na*mb)) #print(shortstr(_lz)) assert len(intersect(_lz, Ih)) == 0 assert len(intersect(_lz, Iv)) == len(_lz) J = intersect(_lz, lz) assert len(J) == len(_lz) J = intersect(_lz, Lzv) #print(J.shape, _lz.shape, Lzv.shape) assert len(J) == len(_lz) if 0: V = cat(blocks[0][:2], axis=1) H = cat(blocks[1][:2], axis=1) X = cat((V, H), axis=0) K = find_kernel(X) print(K.shape) V = cat(blocks[0], axis=1) H = cat(blocks[1], axis=1) X = cat((V, H), axis=0) K = find_kernel(X) print(K.shape) #print("-"*(ka*mb+ma*kb)) I = cat((identity2(ka*mb+ma*kb), zeros2(ka*mb+ma*kb, na*nb)), axis=1) J = intersect(K, I) print("J:", J.shape)
def find_ideals(): import networkx as nx from models import build_model model = build_model() if argv.verbose: print(model) print() #print(shortstrx(Hx, Hz)) Gx, Gz = model.Gx, model.Gz Hx, Hz = model.Hx, model.Hz #print shortstrx(Gx, Gz) Rx, Rz = model.Rx, model.Rz Rxt = Rx.transpose() Rzt = Rz.transpose() Px, Pz = model.Px, model.Pz Pxt = Px.transpose() Pzt = Pz.transpose() r, n = Rx.shape assert eq2(dot2(Rx, Pxt), Rx) # print shortstrx(Gx, Gz) # print PGx = dot2(Gx, Pxt) PGz = dot2(Gz, Pzt) # print shortstrx(PGx, PGz) # print if 0: ng = len(PGx) graph = nx.Graph() for i in range(ng): graph.add_node(i) for i, gi in enumerate(PGx): for j, gj in enumerate(PGz): if (gi*gj).sum()%2: graph.add_edge(i, j) mx = len(Gx) mz = len(Gz) graph = nx.Graph() for i in range(mx+mz): graph.add_node(i) for ix in range(mx): for iz in range(mz): if (Gx[ix]*Gz[iz]).sum()%2: graph.add_edge(ix, mx+iz) # excite = argv.excite # if type(excite) is int: # _excite = [0]*len(model.Tx) # _excite[excite] = 1 # excite = tuple(_excite) # #elif excite is None: # print("excite:", excite) equs = nx.connected_components(graph) equs = list(equs) print(model) print(("find_ideals:", len(equs))) models = [] for equ in equs: equ = list(equ) equ.sort() #print(equ) gxs = [] gzs = [] for i in equ: if i<mx: gxs.append(Gx[i]) else: gzs.append(Gz[i-mx]) _model = build_model(array2(gxs), array2(gzs)) print(_model) #print(shortstrx(_model.Gx)) basis = find_kernel(_model.Gx.transpose()) print(("kernel:", len(basis), [v.sum() for v in basis])) models.append(_model) idx = argv.dumpc if idx is not None: model = models[idx] #model = model.get_sector(compress=True) print(model) #print(shortstrx(model.Gx)) basis = find_kernel(model.Gx.transpose()) print(("kernel:", len(basis), [v.sum() for v in basis])) models.append(_model) model.dumpc() return if not argv.solve: return if argv.excite or argv.exciteall or argv.minweightall: if argv.minweightall: excites = minweightall(Hz) #print("excite", excite) elif argv.exciteall: excites = list(enum2(len(Hz)))[1:] else: assert len(Hz), Hz excites = [] for i in range(len(Hz)): excite = array2([0]*len(Hz)) excite[i] = 1 excites.append(excite) print(("excites", len(excites))) else: excites = [None] if eq2(model.Hx, model.Hz): print("self dual stabilizers") _excite = None top = None for excite in excites: #if excite is not None: # print "excite:", (excite) # g = dot2(model.Hx.transpose(), excite) # model.show_stabx(g) if excite is not None: tx = dot2(excite, model.Tx) total = 0. gaps = [] for _model in models: #print(_model) if excite is not None: _tx = dot2(tx, _model.Hz.transpose(), _model.Tx) _excite = dot2(_tx, _model.Hz.transpose()) #print(shortstrx(_excite)) #print _excite r = len(_model.Rx) if r <= 12 and not argv.slepc and not argv.sparse: H = _model.build_ham(_excite) #weights=weights1) if argv.orbigraph: H1 = build_orbigraph(H) vals, vecs = numpy.linalg.eigh(H) elif argv.sparse and r <= 19: vals = _model.sparse_ham_eigs(_excite) #weights=weights1) elif r <= 27: #for i in range(len(_excite)): # _excite[i] = 1 #print("excite:", tuple(_excite)) #vals = slepc(excite=tuple(_excite), **_model.__dict__) if _excite is not None: _excite = tuple(_excite) #vals = slepc(excite=_excite, **_model.__dict__) vals = _model.do_slepc(excite=_excite) #vals = [0, 0] else: assert 0, "r=%d too big"%r vals = list(vals) vals.sort(reverse=True) print(("total +=", vals[0])) total += vals[0] gaps.append(vals[0]-vals[1]) if top is None or total > top: top = total print(("eval_1:", total)) print(("eval_2:", total-min(gaps))) print(("top:", top))
def find_triorth(m, k): # 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) if 0: A = list(span(G)) print(strong_morthogonal(A, 1)) print(strong_morthogonal(A, 2)) print(strong_morthogonal(A, 3)) G = [row for row in G if row.sum() % 2 == 0] return array2(G) #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)