def glue_morth(): m = argv.get("m", 4) n = argv.get("n", m + m + 1) genus = argv.get("genus", 2) if 0: H = make_morthogonal(m, n, genus) elif 0: H = reed_muller.build(1, 4).G print(shortstrx(H)) else: H = find_triorth(m, 1) assert dot2(H, H.transpose()).sum() == 0 Hx = Hz = H if 0: print(classical_distance(Hx)) print(classical_distance(Hz)) i0 = 0 i1 = Hx.shape[1] Hx = direct_sum(Hx, Hx) Hz = direct_sum(Hz, Hz) print(shortstrx(Hx, Hz)) print(strong_morthogonal(Hx, genus)) print(strong_morthogonal(Hz, genus)) print() code = CSSCode(Hx=Hx, Hz=Hz) print(code) if 0: Hz = glue_self_classical(Hz, [(i0, i1), (i0, i1 + 1)]) print(shortstrx(Hz)) print(strong_morthogonal(Hz, genus)) print() return Hx, Hz = glue_self(Hx, Hz, [(i0, i1), (i0, i1 + 1)]) #Hx, Hz = glue_self(Hx, Hz, [(i0, i1)]) print(shortstrx(Hx, Hz)) print(strong_morthogonal(Hx, genus)) print(strong_morthogonal(Hz, genus)) print() code = CSSCode(Hx=Hx, Hz=Hz) # Hx, Hz = glue_self(Hx, Hz, [(0, n)]) # print(shortstrx(Hx, Hz)) # print(strong_morthogonal(Hx, genus)) # print(strong_morthogonal(Hz, genus)) # print() code = CSSCode(Hx=Hx, Hz=Hz) print(code)
def get_code(self, **kw): from qupy.ldpc.css import CSSCode Lx, Lz, Hx, Tz, Hz, Tx = (self.Lx, self.Lz, self.Hx, self.Tz, self.Hz, self.Tx) code = CSSCode(Lx=Lx, Lz=Lz, Hx=Hx, Tz=Tz, Hz=Hz, Tx=Tx, **kw) code.__dict__.update(self.__dict__) return code
def build_code(self, build=False, check=False): qubits = self.qubits guage = self.guage n = len(qubits) m = len(guage) Gx, Gz = self.Gx, self.Gz #Hx, Hz, Lx, Lz = build_stab(Gx, Gz) Hx, Hz = self.Hx, self.Hz if build: Lx = find_logops(Gz, Hx) Lz = find_logops(Gx, Hz) else: Lx = Lz = None code = CSSCode(Lx, Lz, Hx, None, Hz, None, Gx, Gz, build=build, check=check) return code
def get_code(self, **kw): from qupy.ldpc.css import CSSCode #Lx, Lz, Hx, Tz, Hz, Tx = ( # self.Lx, self.Lz, self.Hx, # self.Tz, self.Hz, self.Tx) code = CSSCode(Hx=self.Hx, Hz=self.Hz, **kw) code.__dict__.update(self.__dict__) return code
def test(): Hx = parse("1.11. .11.1") Hz = parse("111.. ..111") code = CSSCode(Hx=Hx, Hz=Hz) print(code) z_weld(code, code, [(3, 0), (4, 1)])
def glue_logops(): m = argv.get("m", 4) n = argv.get("n", m + m + 1) dist = argv.get("dist", 3) N = argv.get("N", 2) M = argv.get("M", N) p = argv.get("p", 0.03) weight = argv.weight codes = [] code = None for i in range(N): Hx, Hz = make_quantum(n, m, dist, weight) #Hx, Hz = make_surface() print("Hx, Hz:") print(shortstrx(Hx, Hz)) c = CSSCode(Hx=Hx, Hz=Hz) codes.append(c) code = c if code is None else code + c A, B = codes code = A + B print(code) print("Lx, Lz:") print(shortstrx(code.Lx, code.Lz)) print("Hx, Hz:") print(shortstrx(code.Hx, code.Hz)) print() #Hx = cat((code.Lx, code.Hx)) Hx = code.Hx Hz = cat((code.Lz, code.Hz)) idxs = list(range(2 * n)) idxs.sort(key=lambda i: (-code.Lz[:, i].sum(), )) Hx = Hx[:, idxs] Hz = Hz[:, idxs] print(shortstrx(Hx, Hz)) i0 = argv.get("i0") i1 = argv.get("i1") if i0 is None: return # code = code.glue(0, n) # print(code) # print(shortstrx(code.Hx, code.Hz)) Hx, Hz = glue1_quantum(Hx, Hz, i0, i1) print("Hx, Hz:") print(shortstrx(Hx, Hz))
def test_quantum(): m = argv.get("m", 4) n = argv.get("n", m + m + 1) dist = argv.get("dist", 3) N = argv.get("N", 2) M = argv.get("M", N) p = argv.get("p", 0.03) weight = argv.weight codes = [] code = None for i in range(N): Hx, Hz = make_quantum(n, m, dist, weight) #Hx, Hz = make_surface() print("Hx, Hz:") print(shortstrx(Hx, Hz)) c = CSSCode(Hx=Hx, Hz=Hz) codes.append(c) code = c if code is None else code + c for _ in range(2 * M): print(code) #code.save("glue.ldpc") counts, err = score(code, p) print("err = %.4f" % err) i0 = numpy.argmin(counts) i1 = numpy.argmax(counts) assert i0 != i1 print(counts, i0, i1) code = code.glue(i0, i1) code = code.dual() print(shortstrx(code.Hx, code.Hz)) return code = CSSCode(Hx=Hx, Hz=Hz) print(code) code = code + code print(shortstrx(code.Hx, code.Hz)) #Hx, Hz = glue1_quantum(code.Hx, code.Hz, 0, 1) #code = CSSCode(Hx=Hx, Hz=Hz) code = code.glue(0, n) print(code) print(shortstrx(code.Hx, code.Hz)) return k = argv.get("k", 1) pairs = [(i, i) for i in range(k)] H1x, H1z = glue_quantum(Hx, Hz, Hx, Hz, pairs) assert dot2(H1x, H1z.transpose()).sum() == 0 code = CSSCode(Hx=H1x, Hz=H1z) print(code) print(shortstrx(code.Hx, code.Hz))
def find_logops(): Hz = parse(""" 11111......................... 1....1111..................... .1.......1111................. ..1..1.......111.............. ...1..1..1......11............ ....1.....1..1....11.......... ...........1....1...111....... ............1.....1.1..11..... ..............1....1...1.11... .......1.......1.........1.11. ........1........1...1.....1.1 ......................1.1.1.11 """) Hx = parse(""" 11......1..1.........1........ .....11..11..1................ ...11...........1.1.1......... .........1..1....1......1....1 ....................11.1.1.1.. ..........11.......1..1...1... .............1.1..1.....1...1. ..11...........1.1.........1.. .....1..1.....1...........1..1 .11.........1.1........1...... 1...1..1...........1.....1.... ......11........1.....1.....1. """) Hz = remove_dependent(Hz) Hx = remove_dependent(Hx) mx, n = Hx.shape mz, n = Hz.shape print(n, mx, mz) Hz = parse("1.111... .111.1.. 1...1.11") Hx = parse("111...1. 11.1...1 ..1.111.") from qupy.ldpc.css import CSSCode code = CSSCode(Hx=Hx, Hz=Hz) print("Lx:") print(shortstr(code.Lx)) print("Lz:") print(shortstr(code.Lz))
def test_flow(): seed(3) m, n = argv.get("m", 3), argv.get("n", 3) cx = Complex() if argv.disc: cx.build_surface((0, 0), (m, n)) k = 0 elif argv.surface: cx.build_surface((0, 0), (m, n), open_top=True, open_bot=True) k = 0 elif argv.torus: cx.build_torus(m, n) k = 2 else: cx.build_torus(m, n) k = 2 #print(cx) for trial in range(10): flow = Flow(cx) flow.build() if argv.render: flow.render(name="output") break chain = flow.morse_homology(1) A, B = chain BA = B * A for key, v in BA.elements.items(): assert v % 2 == 0 #print(BA.todense()) Hzt = A.todense() % 2 Hz = Hzt.transpose() Hx = B.todense() % 2 assert dot2(Hx, Hzt).sum() == 0 code = CSSCode(Hx=Hx, Hz=Hz) #print("k =", code.k) assert code.k == k, (code.k, k)
def find_homology_2(g, f, *dims): print("find_homology") print(dims[2], "--f-->", dims[1], "--g-->", dims[0]) F = numpy.zeros((dims[1], dims[2])) for row, col in list(f.keys()): v = f[row, col] F[row, col] = v % 2 #print shortstr(F.transpose()) #print G = numpy.zeros((dims[0], dims[1])) for row, col in list(g.keys()): v = g[row, col] G[row, col] = v % 2 #print shortstr(G) if argv.ldpc: from qupy.ldpc.css import CSSCode code = CSSCode(Hx=F.transpose(), Hz=G) code.build() code = code.prune_deadbits() print(code) name = argv.get("name") if name.endswith(".ldpc"): print("saving", name) code.save(name) if argv.logops: L = find_logops(G, F.transpose()) w = min([v.sum() for v in L]) print("logops weight:", w) L = find_logops(F, G.transpose()) w = min([v.sum() for v in L]) print("logops weight:", w) GF = numpy.dot(G, F) % 2 #print shortstr(GF) assert numpy.abs(GF).sum() == 0 F = F.astype(numpy.int32) G = G.astype(numpy.int32) print("rank(f)=%d, rank(g)=%d" % (rank(F), rank(G))) if g: kerg = find_kernel(G) print("ker(g):", len(kerg))
def __call__(self, other): assert isinstance(other, CSSCode) assert other.n * 2 == self.n Lx, Lz, Hx, Tz, Hz, Tx, Gx, Gz = (other.Lx, other.Lz, other.Hx, other.Tz, other.Hz, other.Tx, other.Gx, other.Gz) assert Gx is None assert Gz is None A = self.A.transpose() LxLz = dot2(cat((Lx, Lz), axis=1), A) HxTz = dot2(cat((Hx, Tz), axis=1), A) TxHz = dot2(cat((Tx, Hz), axis=1), A) n = self.n // 2 Lx, Lz = LxLz[:, :n], LxLz[:, n:] Hx, Tz = HxTz[:, :n], HxTz[:, n:] Tx, Hz = TxHz[:, :n], TxHz[:, n:] code = CSSCode(Lx=Lx, Lz=Lz, Hx=Hx, Tz=Tz, Hz=Hz, Tx=Tx) return code
def get_code(self): self.check() keys = self.keys keymap = self.keymap x_ops, z_ops = self.get_stabs() n = len(keys) mx = len(x_ops) mz = len(z_ops) Hx = zeros2(mx, n) Hz = zeros2(mz, n) for idx, stab in enumerate(x_ops): for key in stab: Hx[idx, keymap[key]] = 1 for idx, stab in enumerate(z_ops): for key in stab: Hz[idx, keymap[key]] = 1 code = CSSCode(Hx=Hx, Hz=Hz) return code
def test_hyperbicycle(): name = sys.argv[1] from qupy.ldpc.css import CSSCode code = CSSCode.load(name) X = Chain([code.Hx, code.Hz.transpose()]) X.check() # 0 -> 1 -> 2 -> 3 -> 4 #XX = X.tensor(X, 1) # very big :-( XX = X.tensor(X) #XX.dumpcodes() code = XX.get_code(1) print(code) code.save("hyper_%d_%d.ldpc" % (code.n, len(code.Lx)))
def get_code(self, idx=0, build=True, check=True): #print "get_code" Hs = self.Hs Hx = Hs[idx] write("li:") Hx = solve.linear_independent(Hx) Hz = Hs[idx + 1].transpose() write("li:") Hz = solve.linear_independent(Hz) #print(Hx.shape, Hz.shape) if self.Ls: Lz = self.Ls[idx] #print "get_code:", Lz.shape else: Lz = None #print shortstr(dot(Hx, Hz.transpose())) #print "Hz:" #print shortstr(Hz) #print "Hx:" #print shortstr(Hx) from qupy.ldpc.css import CSSCode code = CSSCode(Hx=Hx, Hz=Hz, Lz=Lz, build=build, check=check) return code
def get_code(self, **kw): from qupy.ldpc.css import CSSCode code = CSSCode(Hx=self.Hx, Hz=self.Hz, **kw) code.__dict__.update(self.__dict__) return code
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_code(Hxi, Hzi, Hx, Lx, Lz, Lx0, Lx1, LxiHx, **kw): code = CSSCode(Hx=Hxi, Hz=Hzi) print(code) assert rank(intersect(Lx, code.Lx)) == code.k assert rank(intersect(Lz, code.Lz)) == code.k verbose = argv.verbose decoder = get_decoder(argv, argv.decode, code) if decoder is None: return p = argv.get("p", 0.01) N = argv.get("N", 0) distance = code.n count = 0 failcount = 0 nonuniq = 0 logops = [] for i in range(N): err_op = ra.binomial(1, p, (code.n, )) err_op = err_op.astype(numpy.int32) op = decoder.decode(p, err_op, verbose=verbose, argv=argv) c = 'F' success = False if op is not None: op = (op + err_op) % 2 # Should be a codeword of Hz (kernel of Hz) assert dot2(code.Hz, op).sum() == 0 write("%d:" % op.sum()) # Are we in the image of Hx ? If so, then success. success = dot2(code.Lz, op).sum() == 0 if success and op.sum(): nonuniq += 1 c = '.' if success else 'x' if op.sum() and not success: distance = min(distance, op.sum()) write("L") logops.append(op.copy()) else: failcount += 1 write(c + ' ') count += success if N: print() print(argv) print("error rate = %.8f" % (1. - 1. * count / (i + 1))) print("fail rate = %.8f" % (1. * failcount / (i + 1))) print("nonuniq = %d" % nonuniq) print("distance <= %d" % distance) mx0, mx1 = len(Lx0), len(Lx1) LxHx = numpy.concatenate((Lx0, Lx1, Hx)) for op in logops: print(op.sum()) #print(shortstr(op)) #print(op.shape) #print(op) K = solve(LxHx.transpose(), op) K.shape = (1, len(K)) print(shortstrx(K[:, :mx0], K[:, mx0:mx0 + mx1], K[:, mx0 + mx1:]))
def test_symplectic(): n = 3 I = Matrix.identity(n) for idx in range(n): for jdx in range(n): if idx == jdx: continue CN_01 = Matrix.cnot(n, idx, jdx) CN_10 = Matrix.cnot(n, jdx, idx) assert CN_01 * CN_01 == I assert CN_10 * CN_10 == I lhs = CN_10 * CN_01 * CN_10 rhs = Matrix.swap(n, idx, jdx) assert lhs == rhs lhs = CN_01 * CN_10 * CN_01 assert lhs == rhs #print(Matrix.cnot(3, 0, 2)) #if 0: cnot = Matrix.cnot hadamard = Matrix.hadamard n = 2 gen = [cnot(n, 0, 1), cnot(n, 1, 0), hadamard(n, 0), hadamard(n, 1)] for A in gen: assert A.is_symplectic() Cliff2 = mulclose_fast(gen) assert len(Cliff2) == 72 # index 10 in Sp(2, 4) CZ = array2([[1, 0, 0, 0], [0, 1, 0, 0], [0, 1, 1, 0], [1, 0, 0, 1]]) CZ = Matrix(CZ) assert CZ.is_symplectic() assert CZ in Cliff2 n = 3 gen = [ cnot(n, 0, 1), cnot(n, 1, 0), cnot(n, 0, 2), cnot(n, 2, 0), cnot(n, 1, 2), cnot(n, 2, 1), hadamard(n, 0), hadamard(n, 1), hadamard(n, 2), ] for A in gen: assert A.is_symplectic() assert len(mulclose_fast(gen)) == 40320 # index 36 in Sp(2,4) if 0: # cnot's generate GL(2, n) n = 4 gen = [] for i in range(n): for j in range(n): if i != j: gen.append(cnot(n, i, j)) assert len(mulclose_fast(gen)) == 20160 if 0: n = 2 count = 0 for A in enum2(4 * n * n): A.shape = (2 * n, 2 * n) A = Matrix(A) try: assert A.is_symplectic() count += 1 except: pass print(count) # 720 = |Sp(2, 4)| return for n in [1, 2]: gen = [] for x in enum2(2 * n): A = Matrix.transvect(x) assert A.is_symplectic() gen.append(A) G = mulclose_fast(gen) assert len(G) == [6, 720][n - 1] n = 2 Sp = G #print(len(Sp)) found = set() for g in Sp: A = g.A.copy() A[:n, n:] = 0 A[n:, :n] = 0 found.add(str(A)) #print(len(A)) #return n = 4 I = Matrix.identity(n) H = Matrix.hadamard(n, 0) assert H * H == I CN_01 = Matrix.cnot(n, 0, 1) assert CN_01 * CN_01 == I n = 3 trivial = CSSCode(Lx=parse("1.."), Lz=parse("1.."), Hx=zeros2(0, n), Hz=parse(".1. ..1")) assert trivial.row_equal(CSSCode.get_trivial(3, 0)) repitition = CSSCode(Lx=parse("111"), Lz=parse("1.."), Hx=zeros2(0, n), Hz=parse("11. .11")) assert not trivial.row_equal(repitition) CN_01 = Matrix.cnot(n, 0, 1) CN_12 = Matrix.cnot(n, 1, 2) CN_21 = Matrix.cnot(n, 2, 1) CN_10 = Matrix.cnot(n, 1, 0) encode = CN_12 * CN_01 code = CN_01(trivial) assert not code.row_equal(repitition) code = CN_12(code) assert code.row_equal(repitition) A = get_encoder(trivial, repitition) gen, names = get_gen(3) word = mulclose_find(gen, names, A) if 1: assert type(word) is tuple #print("word:") #print(repr(word)) items = [gen[names.index(op)] for op in word] op = reduce(mul, items) #print(op) #assert op*(src) == (tgt) #print(op(trivial).longstr()) assert op(trivial).row_equal(repitition)
def even_code(): p = argv.get("p", 7) #assert (p%8) in [1, 7] # equivalent to "2 (binary!) is a quadratic _residue mod p" # eg. 7 17 23 31 41 47 71 73 79 89 97 def neginv(i): if i == 0: return p if i == p: return 0 for j in range(1, p): if (i * j) % p == 1: break else: assert 0 return (-j) % p nonresidues = set(range(1, p)) residues = set() for i in range(1, p): j = (i * i) % p if j not in residues: residues.add(j) nonresidues.remove(j) print("residues:", residues) print("non-residues:", nonresidues) # extended binary quadratic _residue code N = p + 1 G = zeros2(N, N) G[p, :] = 1 for u in range(p): G[u, p] = 0 if (p - 1) % 8 == 0 else 1 for v in range(p): if u == v: i = 0 elif (v - u) % p in residues: i = 1 else: i = 0 G[u, v] = i G = linear_independent(G) print("G =") print(shortstr(G)) from qupy.ldpc.css import CSSCode from qupy.ldpc.gallagher import classical_distance G = G.astype(numpy.int32) code = CSSCode(Hx=G, Hz=G) print(code) from bruhat.codes import strong_morthogonal for genus in range(1, 4): print("genus:", genus, "strong_morthogonal:", strong_morthogonal(G, genus)) def double(G): M, N = G.shape DG = zeros2(M + 1, 2 * N) DG[1:, 0:N] = G DG[1:, N:2 * N] = G DG[0, 0:N] = 1 DG = DG.astype(numpy.int32) return DG DG = G DG = DG.astype(numpy.int32) print("distance:", classical_distance(DG)) for _ in range(2): DG = double(DG) DG = linear_independent(DG) print(shortstr(DG)) for genus in range(1, 5): print("genus:", genus, "strong_morthogonal:", strong_morthogonal(DG, genus)) code = CSSCode(Hx=DG, Hz=DG) print(code)
def main(): n = 5 Tx = parse(""" 1.... 1.1.. 1.1.1 """) Tz = parse(""" .1... ...1. """) code = CSSCode(Hx=Tx, Hz=Tz) #print(code) #print(code.longstr()) S = parse(""" 1.1..1 11.1.. .11.1. ...111 """) I = parse(""" 1... .1.. ..1. ...1 """) A = parse(""" 1... 11.. ..1. ...1 """) B = parse(""" 1... .1.. .11. ...1 """) C = parse(""" 1... .1.. ..1. ..11 """) #print(I) #print(dot2(A)) #print(dot2(B, A)) L = dot2(C, B, A) #print(dot2(L, S)) # row reduced S L = L[:3, :3] S = S[:3, :] print("S =") print(S) print("LS =") print(dot2(L, S)) J = parse(""" 1.. 11. ... ... 111 ... """) U = parse(""" 1.. .11 ..1 """) print(dot2(U, L, S))
def main(): l = argv.get('l', 8) li = argv.get('li', l) lj = argv.get('lj', l) si = argv.get('si', 0) sj = argv.get('sj', 0) toric = Toric2D(li, lj, si, sj) Hx, Hz = toric.Hx, toric.Hz strop = toric.strop #print("Hx:") #print(shortstr(Hx)) #print("Lx:") #print(shortstr(toric.Lx)) code = CSSCode(Hx=Hx, Hz=Hz, Lx=toric.Lx, Lz=toric.Lz) print(code) print(code.Lx) decoder = ClusterCSSDecoder(2, code.Hx, code.Hz) N = argv.get("N", 0) p = argv.get("p", 0.05) verbose = argv.verbose distance = code.n count = 0 failcount = 0 nonuniq = 0 total = numpy.array([0.] * code.k) for trial in range(N): err_op = ra.binomial(1, p, (code.n, )) err_op = err_op.astype(numpy.int32) write(str(err_op.sum())) #print err_op.shape s = dot2(code.Hz, err_op) write(":s%d:" % s.sum()) op = decoder.decode(p, err_op, verbose=verbose, argv=argv) c = 'F' success = False result = numpy.array([1] * code.k) if op is not None: op = (op + err_op) % 2 # Should be a codeword of Hz (kernel of Hz) if dot2(code.Hz, op).sum() != 0: print(dot2(code.Hz, op)) print("\n!!!!! BUGBUG !!!!!", sparsestr(err_op)) continue write("%d:" % op.sum()) # Are we in the image of Hx ? If so, then success. result = dot2(code.Lz, op) success = result.sum() == 0 #print(result, end=" ") if success and op.sum(): nonuniq += 1 # print "\n", shortstr(err_op) # return c = '.' if success else 'x' if op.sum() and not success: distance = min(distance, op.sum()) else: failcount += 1 if failures: print(shortstr(err_op), file=failures) failures.flush() total += result write(c + ' ') count += success if N: print() print(datestr) print(argv) print("error rate = %.8f" % (1. - 1. * count / (trial + 1))) print("fail rate = %.8f" % (1. * failcount / (trial + 1))) print("nonuniq = %d" % nonuniq) print("distance <= %d" % distance) total = total / (trial + 1) print("logop errors = [%s]" % ', '.join(str(x) for x in total))
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 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 main(): m = argv.get('m', 6) # constraints (rows) n = argv.get('n', 16) # bits (cols) j = argv.get('j', 3) # column weight (left degree) k = argv.get('k', 8) # row weight (constraint weight; right degree) #assert 2*m<=n, "um?" max_iter = argv.get('max_iter', 200) verbose = argv.verbose check = argv.get('check', False) strop = shortstr Lx = None Lz = None Hx = None Tz = None Hz = None Tx = None build = argv.get('build', False) logops_only = argv.get("logops_only", True) code = None if argv.code == 'ldpc': H = ldpc(m, n, j, k) code = CSSCode(Hz=H, Hx=zeros2(0, n)) elif argv.code == 'cycle': #n = argv.get('n', 20) #m = argv.get('m', 18) row = str(argv.get('H', '1101')) H = [] for i in range(n): h = [0] * n for j, c in enumerate(row): h[(i + j) % n] = int(c) H.append(h) delta = n - m for i in range(delta): H.pop(i * n // delta - i) # while len(H) > m: # idx = randint(0, len(H)-1) # H.pop(idx) Hz = array2(H) print(shortstr(Hz)) #print shortstr(solve.row_reduce(Hz)) # code = CSSCode(Hz=Hz) # print # print code # print code.weightstr() # # decoder = StarDynamicDistance(code) # L = decoder.find(verbose=verbose) # print shortstr(L) # print "distance:", L.sum() # return elif argv.code == "opticycle": code = opticycle(m, n) H = Hz = code.Hz #return elif argv.code == 'tree': k = argv.get('k', 5) n = 2**k + 1 code = build_tree(45) print(code) # graph = Graph() # for i in range(H.shape[0]): # edge = list(numpy.where(H[i])[0]) # #print edge, # for i0 in edge: # for i1 in edge: # if i0!=i1: # graph.add_edge(i0, i1) # # leaves = [idx for idx in range(n) if H[:, idx].sum()<=1] # print leaves # # # k = len(leaves)//2 # print graph.metric(leaves[1], leaves[k]) # return # for i in range(k-1): # #i0 = poprand(leaves) # #i1 = poprand(leaves) # u = zeros2(1, n) # u[0, leaves[i]] = 1 # u[0, leaves[i+k]] = 1 # # what about picking three leaves? # print (leaves[i], leaves[i+k]), # H = append2(H, u) # print # # # if we take all the leaves we get degenerate... # leaves = [idx for idx in range(n) if H[:, idx].sum()<=1] # print "leaves:", leaves # # #print shortstr(H) # #print # #print shortstr(solve.row_reduce(H)) # code = CSSCode(Hz=H) # print code # print code.weightstr() # print numpy.where(code.Lx[3]) # # return elif argv.code == 'bicycle': from qupy.ldpc.bicycle import Bicycle_LDPC print("Bicycle_LDPC(%s, %s, %s, %s)" % (m, n, j, k)) b = Bicycle_LDPC(m, n, j, k) Hx = Hz = b.H elif argv.code == 'toric': from qupy.ldpc.toric import Toric2D l = argv.get('l', 8) li = argv.get('li', l) lj = argv.get('lj', l) si = argv.get('si', 0) sj = argv.get('sj', 0) toric = Toric2D(li, lj, si, sj) Hx, Hz = toric.Hx, toric.Hz strop = toric.strop #print("Hx:") #print(shortstr(Hx)) #print("Lx:") #print(shortstr(toric.Lx)) code = CSSCode(Hx=Hx, Hz=Hz, Lx=toric.Lx, Lz=toric.Lz) elif argv.code == 'cylinder': from qupy.ldpc.toric import Cylinder l = argv.get('l', 8) li = argv.get('li', l) lj = argv.get('lj', l) si = argv.get('si', 0) sj = argv.get('sj', 0) assert si == 0 surface = Cylinder(li, lj, sj) Hx, Hz = surface.Hx, surface.Hz strop = surface.strop #print("Hx:") #print(shortstr(Hx)) #print("Lx:") #print(shortstr(surface.Lx)) code = CSSCode(Hx=Hx, Hz=Hz) elif argv.code == 'torichie': from qupy.ldpc.toric import Toric2DHie l = argv.get('l', 8) toric = Toric2DHie(l) Hx, Hz = toric.Hx, toric.Hz elif argv.code == 'surface': from qupy.ldpc.toric import Surface l = argv.get('l', 8) si = argv.get('si', 0) # todo sj = argv.get('sj', 0) surface = Surface(l) #Hx, Hz = surface.Hx, surface.Hz #strop = surface.strop #print shortstr(Hx) code = surface.get_code() elif argv.code == 'toric3': from qupy.ldpc.toric import Toric3D l = argv.get('l', 8) toric = Toric3D(l) Hx, Hz = toric.Hx, toric.Hz strop = toric.strop #print shortstr(Hx) elif argv.code == 'gcolor': from qupy.ldpc.gcolor import Lattice l = argv.get('l', 1) lattice = Lattice(l) #code = lattice.build_code() G = lattice.Hx print(shortstr(G)) m, n = G.shape G1 = zeros2(m + 1, n + 1) G1[1:, 1:] = G G1[0, :] = 1 print() print(shortstr(G1)) for genus in range(1, 5): print(genus, strong_morthogonal(G1, genus)) code = CSSCode(Hx=G1, Hz=G1) elif argv.code == 'self_ldpc': from qupy.ldpc.search import SelfContainingLDPC_Code ldpc_code = SelfContainingLDPC_Code(m, n, j, k) ldpc_code.search(max_step=argv.get('max_step', None), verbose=verbose) #print ldpc_code H = ldpc_code.H print("H:") print(shortstr(H)) H = solve.linear_independent(H) Hx = Hz = H code = CSSCode(Hx=Hx, Hz=Hz) elif argv.code == 'cssldpc': from qupy.ldpc.search import CSS_LDPC_Code ldpc_code = CSS_LDPC_Code(m, n, j, k) ldpc_code.search(max_step=argv.get('max_step', None), verbose=verbose) #print ldpc_code Hx, Hz = ldpc_code.Hx, ldpc_code.Hz #print "Hx:" #print shortstr(Hx) Hx = solve.linear_independent(Hx) Hz = solve.linear_independent(Hz) #Hx = Hz = H code = CSSCode(Hx=Hx, Hz=Hz) elif argv.code == "hpack": code = hpack(n, j=j, k=k, check=check, verbose=verbose) elif argv.code == 'randldpc': mz = argv.get('mz', n // 3) rw = argv.get('rw', 12) # row weight code = randldpc(n, mz, rw, check=check, verbose=verbose) elif argv.code == 'randcss': mx = argv.get('mx', n // 3) mz = argv.get('mz', n // 3) distance = argv.get("code_distance") code = randcss(n, mx, mz, distance=distance, check=check, verbose=verbose) elif argv.code == 'sparsecss': mx = argv.get('mx', n // 3) mz = argv.get('mz', n // 3) weight = argv.get('weight', 4) code = sparsecss(n, mx, mz, weight, check=check, verbose=verbose) elif argv.code == 'ensemble': mx = argv.get('mx', n // 3) mz = argv.get('mz', mx) rw = argv.get('rw', 12) # row weight maxw = argv.get('maxw', 4 * rw) C = argv.get("C", 100) code = ensemble.build(n, mx, mz, rw, maxw, C, check=check, verbose=verbose) elif argv.code == "rm" or argv.code == "reed_muller": from qupy.ldpc import reed_muller r = argv.get("r", 1) m = argv.get("m", 4) puncture = argv.puncture cl_code = reed_muller.build(r, m, puncture) G = cl_code.G G = array2([row for row in G if row.sum() % 2 == 0]) code = CSSCode(Hx=G, Hz=G) elif argv.code == "qrm": from qupy.ldpc.gallagher import get_code, hypergraph_product from qupy.ldpc import reed_muller r = argv.get("r", 1) m = argv.get("m", 4) puncture = argv.puncture cl_code = reed_muller.build(r, m, puncture) H = cl_code.G H = array2([row for row in H if row.sum() % 2 == 0]) print(shortstr(H)) m, n = 4, 4 J = zeros2(m, n) for i in range(m): J[i, i] = 1 J[i, (i + 1) % n] = 1 print() print(shortstr(J)) Hx, Hz, Lx, Lz = hypergraph_product(J, H) code = CSSCode(Hx=Hx, Hz=Hz, Lx=Lx, Lz=Lz) #print(code.weightstr()) #print("Hz:") #print(shortstr(code.Hz)) #print("Hx:") #print(shortstr(code.Hx)) elif argv.code == "qgall": from qupy.ldpc.gallagher import make_gallagher, hypergraph_product 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 dist = argv.get("dist", 4) # distance H = make_gallagher(r, n, l, m, dist) #print(H) rm = argv.get("rm", dist) J = zeros2(rm, rm) for i in range(rm): J[i, i] = 1 J[i, (i + 1) % rm] = 1 #print(J) Hx, Hz, Lx, Lz = hypergraph_product(J, H) code = CSSCode(Hx=Hx, Hz=Hz, Lx=Lx, Lz=Lz) #print(code.weightstr()) #print("Hz:") #print(shortstr(code.Hz)) #print("Hx:") #print(shortstr(code.Hx)) elif argv.code == "qr7": H = parse(""" ...1111 .11..11 1.1.1.1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "golay" or argv.code == "qr23": H = parse(""" 1.1..1..11111.......... 1111.11.1....1......... .1111.11.1....1........ ..1111.11.1....1....... ...1111.11.1....1...... 1.1.1.111..1.....1..... 1111...1..11......1.... 11.111...11........1... .11.111...11........1.. 1..1..11111..........1. .1..1..11111..........1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "dgolay": # double golay code (tri-orthogonal) H = parse(""" 111111111111111111111111........................ .1111.1.11..11..1.1....1.1111.1.11..11..1.1....1 ..1111.1.11..11..1.1...1..1111.1.11..11..1.1...1 ...1111.1.11..11..1.1..1...1111.1.11..11..1.1..1 ....1111.1.11..11..1.1.1....1111.1.11..11..1.1.1 .....1111.1.11..11..1.11.....1111.1.11..11..1.11 1.....1111.1.11..11..1.11.....1111.1.11..11..1.1 .1.....1111.1.11..11..11.1.....1111.1.11..11..11 1.1.....1111.1.11..11..11.1.....1111.1.11..11..1 .1.1.....1111.1.11..11.1.1.1.....1111.1.11..11.1 ..1.1.....1111.1.11..111..1.1.....1111.1.11..111 1..1.1.....1111.1.11..111..1.1.....1111.1.11..11 11..1.1.....1111.1.11..111..1.1.....1111.1.11..1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "dham": # double hamming code (tri-orthogonal) H = parse(""" 11111111........ .11.1..1.11.1..1 ..11.1.1..11.1.1 ...11.11...11.11 1...11.11...11.1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "ddham": # double double hamming code H = parse(""" 1111111111111111................ 11111111........11111111........ .11.1..1.11.1..1.11.1..1.11.1..1 ..11.1.1..11.1.1..11.1.1..11.1.1 ...11.11...11.11...11.11...11.11 1...11.11...11.11...11.11...11.1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "qr31": H = parse(""" 1..1..1.1...11.11.............. 11.11.1111..1.11.1............. 11111111.11.1.....1............ .11111111.11.1.....1........... ..11111111.11.1.....1.......... ...11111111.11.1.....1......... 1..111.1.1111.11......1........ 11.111....11...........1....... .11.111....11...........1...... ..11.111....11...........1..... ...11.111....11...........1.... ....11.111....11...........1... 1..1.1...11.11..............1.. .1..1.1...11.11..............1. ..1..1.1...11.11..............1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "qr17": # not self-dual Hz = parse(""" .11.1...11...1.11 1.11.1...11...1.1 11.11.1...11...1. .11.11.1...11...1 1.11.11.1...11... .1.11.11.1...11.. ..1.11.11.1...11. ...1.11.11.1...11 1...1.11.11.1...1 11...1.11.11.1... .11...1.11.11.1.. ..11...1.11.11.1. ...11...1.11.11.1 1...11...1.11.11. .1...11...1.11.11 1.1...11...1.11.1 11.1...11...1.11. """) Hx = parse(""" ...1.111..111.1.. 11.1.....1.111..1 111..111.1.....1. ....1.111..111.1. 111.1.....1.111.. .111..111.1.....1 .....1.111..111.1 .111.1.....1.111. 1.111..111.1..... 1.....1.111..111. ..111.1.....1.111 .1.111..111.1.... .1.....1.111..111 1..111.1.....1.11 ..1.111..111.1... 1.1.....1.111..11 11..111.1.....1.1 """) Hz = solve.linear_independent(Hz) Hx = solve.linear_independent(Hx) code = CSSCode(Hx=Hx, Hz=Hz) elif argv.code == "qr41": # not self-dual Hz = parse(""" .11.11..111.....1.1.11.1.1.....111..11.11 1.11.11..111.....1.1.11.1.1.....111..11.1 11.11.11..111.....1.1.11.1.1.....111..11. .11.11.11..111.....1.1.11.1.1.....111..11 1.11.11.11..111.....1.1.11.1.1.....111..1 11.11.11.11..111.....1.1.11.1.1.....111.. .11.11.11.11..111.....1.1.11.1.1.....111. ..11.11.11.11..111.....1.1.11.1.1.....111 1..11.11.11.11..111.....1.1.11.1.1.....11 11..11.11.11.11..111.....1.1.11.1.1.....1 111..11.11.11.11..111.....1.1.11.1.1..... .111..11.11.11.11..111.....1.1.11.1.1.... ..111..11.11.11.11..111.....1.1.11.1.1... ...111..11.11.11.11..111.....1.1.11.1.1.. ....111..11.11.11.11..111.....1.1.11.1.1. .....111..11.11.11.11..111.....1.1.11.1.1 1.....111..11.11.11.11..111.....1.1.11.1. .1.....111..11.11.11.11..111.....1.1.11.1 1.1.....111..11.11.11.11..111.....1.1.11. .1.1.....111..11.11.11.11..111.....1.1.11 """) Hx = parse(""" ...1..11...11111.1.1..1.1.11111...11..1.. 1111...11..1.....1..11...11111.1.1..1.1.1 111.1.1..1.1.11111...11..1.....1..11...11 ....1..11...11111.1.1..1.1.11111...11..1. 11111...11..1.....1..11...11111.1.1..1.1. 1111.1.1..1.1.11111...11..1.....1..11...1 .....1..11...11111.1.1..1.1.11111...11..1 .11111...11..1.....1..11...11111.1.1..1.1 11111.1.1..1.1.11111...11..1.....1..11... 1.....1..11...11111.1.1..1.1.11111...11.. 1.11111...11..1.....1..11...11111.1.1..1. .11111.1.1..1.1.11111...11..1.....1..11.. .1.....1..11...11111.1.1..1.1.11111...11. .1.11111...11..1.....1..11...11111.1.1..1 ..11111.1.1..1.1.11111...11..1.....1..11. ..1.....1..11...11111.1.1..1.1.11111...11 1.1.11111...11..1.....1..11...11111.1.1.. ...11111.1.1..1.1.11111...11..1.....1..11 1..1.....1..11...11111.1.1..1.1.11111...1 .1.1.11111...11..1.....1..11...11111.1.1. """) code = CSSCode(Hz=Hz, Hx=Hx) elif argv.code == "qr47": H = parse(""" 1...11..11.11..1..1.1..11...................... 11..1.1.1.11.1.11.1111.1.1..................... 111.1..11.....111111.111..1.................... 11111......11...11.1..1....1................... .11111......11...11.1..1....1.................. 1.11..1.11.11111...111.1.....1................. 11.1.1.11.11.11.1.1..111......1................ 111..11.......1..1111.1........1............... .111..11.......1..1111.1........1.............. 1.11.1.1.1.11..11.11.111.........1............. 11.1.11..111.1.11111..1...........1............ .11.1.11..111.1.11111..1...........1........... 1.111..1.1...1...1.1.1.1............1.......... 11.1.....1111.11......11.............1......... 111..1..111..1..1.1.1.................1........ .111..1..111..1..1.1.1.................1....... ..111..1..111..1..1.1.1.................1...... ...111..1..111..1..1.1.1.................1..... 1.....1.1..1.111.11...11..................1.... 11..11.11..1..1.1..11......................1... .11..11.11..1..1.1..11......................1.. ..11..11.11..1..1.1..11......................1. ...11..11.11..1..1.1..11......................1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "qr71": H = parse(""" 1.1.1.11.1...11..11.....1....1...1111.................................. 1111111.111..1.1.1.1....11...11..1...1................................. .1111111.111..1.1.1.1....11...11..1...1................................ ..1111111.111..1.1.1.1....11...11..1...1............................... 1.11.1..1..11.1.11..1.1.1..111..1.11....1.............................. 1111...1....1.11.....1.111..1.1...1......1............................. .1111...1....1.11.....1.111..1.1...1......1............................ 1..1.111.....1..1.1....11111.11.1111.......1........................... 111.....11...1....11.....1111111............1.......................... .111.....11...1....11.....1111111............1......................... ..111.....11...1....11.....1111111............1........................ ...111.....11...1....11.....1111111............1....................... ....111.....11...1....11.....1111111............1...................... 1.1.11...1.......1.....1.....1111................1..................... .1.1.11...1.......1.....1.....1111................1.................... ..1.1.11...1.......1.....1.....1111................1................... ...1.1.11...1.......1.....1.....1111................1.................. 1.1....11.....1..11..1..1..1.1.......................1................. .1.1....11.....1..11..1..1..1.1.......................1................ ..1.1....11.....1..11..1..1..1.1.......................1............... ...1.1....11.....1..11..1..1..1.1.......................1.............. ....1.1....11.....1..11..1..1..1.1.......................1............. .....1.1....11.....1..11..1..1..1.1.......................1............ ......1.1....11.....1..11..1..1..1.1.......................1........... 1.1.1.1......1.1.11..1...1..11.1.1.1........................1.......... 1111111..1...1..11.1..1.1.1...1.11.1.........................1......... 11.1.1...11..1......1..111.1.1.1...1..........................1........ 11.....1.111.1...11..1...11.111.1111...........................1....... 11..1.11111111...1.1..1.1.11..11................................1...... .11..1.11111111...1.1..1.1.11..11................................1..... ..11..1.11111111...1.1..1.1.11..11................................1.... ...11..1.11111111...1.1..1.1.11..11................................1... ....11..1.11111111...1.1..1.1.11..11................................1.. 1.1.11.1...11..11.....1....1...1111..................................1. .1.1.11.1...11..11.....1....1...1111..................................1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "rm_2_5_p": H = parse(""" ...11111111.................... .11..1111..11.................. 1.1.1.11.1.1.1................. 11.1..1.11.1..1................ ...1111........1111............ .11..11........11..11.......... 1.1.1.1........1.1.1.1......... 11.1..1.........11.1..1........ .11111111......11......11...... 1.111111.1.....1.1.....1.1..... 11.1111.11......11.....1..1.... 111.1111...1...1...1...1...1... 1111.11.1..1....1..1...1....1.. 11111.1..1.1.....1.1...1.....1. 111111.111.1...111.1...1......1 """) code = CSSCode(Hx=H, Hz=H) elif argv.code == "to_16_6": # triorthogonal H = parse(""" ........11111111 ....1111....1111 11111111........ ..11..11..11..11 .1.1.1.1.1.1.1.1 1..1.11..11.1..1 """) # distance = 4 code = CSSCode(Hx=H, Hz=H) elif argv.code == "B11": # Pless 1971, punctured B12 H = parse(""" .1111...... ...1111.... .....1111.. .......1111 1.1.1.1.1.1 """) from qupy.ldpc.gallagher import classical_distance print(classical_distance(H)) code = CSSCode(Hx=H, Hz=H) elif argv.code == "glue_classical_self": from qupy.ldpc.glue import glue_classical, glue_classical_self H = glue_classical_self() H = H.copy() code = CSSCode(Hx=H, Hz=H) #if argv.classical_distance: # from qupy.ldpc.gallagher import classical_distance # print("distance:", classical_distance(H)) elif argv.code == "randselfdual": m = argv.get("m", 4) n = argv.get("n", 8) rw = argv.get("rw", 4) code = randselfdual(m, n, rw) else: from qupy.ldpc.gallagher import get_code code = get_code(argv.code) if argv.truncate: idx = argv.truncate Hx = Hx[:idx] Hz = Hz[:idx] for arg in argv: if arg.endswith('.ldpc'): code = CSSCode.load(arg, build=build, check=check, rebuild=argv.rebuild) if argv.rebuild: code.save(arg) break if code is None: code = CSSCode(Lx, Lz, Hx, Tz, Hz, Tx, build=build, check=check, verbose=verbose, logops_only=logops_only) if argv.dual: print("dual code...") code = code.dual(build=build) # take several copies of the code.. mul = argv.get("mul", 1) code = mul * code if argv.classical_product: H1 = code.Hx H2 = H1.transpose() Hx, Hz = hypergraph_product(H1, H2) code = CSSCode(Hx=Hx, Hz=Hz) if argv.product: codes = code.product(code.dual()) for _code in codes: print(_code) if _code.k: _code.save(stem="prod") if argv.verbose != 0: print(code) #print code.longstr() #print code.weightstr() print(code.weightsummary()) if argv.shorten: code.shorten() print(code) print(code.weightsummary()) if argv.prune: print("pruning:", argv.prune) code.prune_xlogops(argv.prune) print(code) print(code.weightsummary()) if argv.split: for i in range(4): code = x_split(code, build=False) print(code) print(code.weightsummary()) code = code.dual() code = x_split(code, build=False) code = code.dual() print(code) print(code.weightsummary()) code.save(stem="split") if argv.save: code.save(argv.save) if argv.symplectic: i = randint(0, code.mz - 1) j = randint(0, code.k - 1) code.Lz[j] += code.Hz[i] code.Lz[j] %= 2 code.Tx[i] -= code.Lx[j] code.Tx[i] %= 2 code.do_check() return if argv.showcode: print(code.longstr()) if argv.todot: todot(code.Hz) return if argv.tanner: Hx = code.Hx graph = Tanner(Hx) #graph.add_dependent() depth = 3 graphs = [graph] for i in range(depth): _graphs = [] for g in graphs: left, right = g.split() _graphs.append(left) _graphs.append(right) graphs = _graphs print("split", graphs) k = code.Lx.shape[0] op = code.Lx[1] #op = (op + code.Tx[20])%2 print(strop(op), op.sum()) print() for i in range(Hx.shape[0]): if random() <= 0.5: op = (op + Hx[i]) % 2 #print shortstr(op), op.sum() print(strop(op), op.sum()) print() #for graph in [left, right]: for graph in graphs * 2: #op = graph.minimize(op, verbose=True) op = graph.localmin(op, verbose=True) print(strop(op), op.sum()) print() #op = graph.localmin(op) #print strop(op), op.sum() #print #print shortstr(op), op.sum() return if argv.distance == 'star': decoder = StarDynamicDistance(code) L = decoder.find(verbose=verbose) print(shortstr(L)) print("distance <=", L.sum()) elif argv.distance == 'stab': d = random_distance_stab(code) print("distance <=", d) elif argv.distance == 'pair': d = pair_distance(code) print("distance <=", d) elif argv.distance == 'free': d = free_distance(code) print("distance <=", d) elif argv.distance == 'lookup': d = lookup_distance(code) if d <= 4: print("distance =", d) else: print("distance <=", d) if type(argv.distance) == str: return if argv.get('exec'): exec(argv.get('exec')) N = argv.get('N', 0) p = argv.get('p', 0.01) weight = argv.weight #assert code.Tx is not None, "use code.build ?" decoder = get_decoder(argv, argv.decode, code) if decoder is None: return if argv.whack: whack(code, decoder, p, N, argv.get("C0", 10), argv.get("error_rate", 0.05), argv.get("mC", 1.2), verbose, argv) return if argv.noerr: print("redirecting stderr to stderr.out") fd = os.open("stderr.out", os.O_CREAT | os.O_WRONLY) os.dup2(fd, 2) decoder.strop = strop print("decoder:", decoder.__class__.__name__) n_ranks = numpy.zeros((code.n, ), dtype=numpy.float64) n_record = [] k_ranks = numpy.zeros((code.k, ), dtype=numpy.float64) k_record = [] failures = open(argv.savefail, 'w') if argv.savefail else None if argv.loadfail: loadfail = open(argv.loadfail) errs = loadfail.readlines() N = len(errs) newHx = [] newHz = [] distance = code.n count = 0 failcount = 0 nonuniq = 0 if argv.weight1: # run through all weight=1 errors N = code.n if argv.weight2: # run through all weight=1 errors N = code.n**2 for i in range(N): # We use Hz to look at X type errors (bitflip errors) if argv.loadfail: err_op = parse(errs[i]) err_op.shape = (code.n, ) elif argv.weight1: err_op = zeros2(code.n) err_op[i % code.n] = 1 elif argv.weight2: err_op = zeros2(code.n) ai = i % code.n bi = (i // code.n) err_op[ai] = 1 err_op[bi] = 1 elif weight is not None: err_op = zeros2(code.n) r = 0 while r < weight: idx = randint(0, code.n - 1) if err_op[idx] == 0: err_op[idx] = 1 r += 1 #print err_op else: err_op = ra.binomial(1, p, (code.n, )) err_op = err_op.astype(numpy.int32) # err_op = parse("..............................") # err_op.shape = (err_op.shape[1],) write(str(err_op.sum())) #print err_op.shape s = dot2(code.Hz, err_op) write(":s%d:" % s.sum()) op = decoder.decode(p, err_op, verbose=verbose, argv=argv) c = 'F' success = False if op is not None: op = (op + err_op) % 2 # Should be a codeword of Hz (kernel of Hz) if dot2(code.Hz, op).sum() != 0: print(dot2(code.Hz, op)) print("\n!!!!! BUGBUG !!!!!", sparsestr(err_op)) continue write("%d:" % op.sum()) #print "is_stab:" #print strop(op) # Are we in the image of Hx ? If so, then success. #success = code.is_stab(op) success = dot2(code.Lz, op).sum() == 0 if success and op.sum(): nonuniq += 1 # print "\n", shortstr(err_op) # return c = '.' if success else 'x' if argv.k_rank: # XX this does not work very well... a = dot2(code.Lz, op) assert (a.sum() == 0) == success if not success: #r = -1. // (a.sum()**0.5) # sqrt ?? r = -1. / a.sum() k_ranks += r * a else: #r = 1. / (code.k**0.5) r = 1. / code.k k_ranks += r * a k_record.append((a, success)) if op.sum() and not success: distance = min(distance, op.sum()) #if op.sum() == 2: # print() # print("main:") # print(shortstr(op)) # print() # print(strop(op)) if argv.minop and argv.minop >= op.sum(): a = dot2(code.Lz, op) print() print(sparsestr(a)) if not success and argv.addstabs and op.sum() <= argv.addstabs: #write("%d"%op.sum()) print((sparsestr(op))) newHx.append(op) A = numpy.concatenate((code.Lx, code.Hx)) c = solve.solve(A.transpose(), op.transpose()).transpose() cL = c[:code.k] zstab = dot2(cL, code.Lz) print(shortstr(zstab)) graph = Tanner(code.Hz) zstab = graph.minimize(zstab, target=8, verbose=True) print(shortstr(zstab)) newHz.append(zstab) break # Hz, Hx = code.Hz, append2(code.Hx, op) # #if len(Hz) < len(Hx): # # Hx, Hz = Hz, Hx # print Hx.shape, Hz.shape # code = CSSCode(Hx=Hx, Hz=Hz) # if len(Hz) < len(Hx): # code = code.dual() # decoder = get_decoder(argv, argv.decode, code) # print # print code # print code.weightsummary() # code.save("addstabs_%d_%d_%d.ldpc"%(code.n, code.k, code.distance)) if not success and argv.showfail: print() print("FAIL:") print(shortstr(err_op)) else: failcount += 1 if failures: print(shortstr(err_op), file=failures) failures.flush() if argv.n_rank: r = 2. * int(success) - 1 #print "r =", r if err_op.sum(): r /= err_op.sum() #print r #print r*err_op n_ranks += r * err_op n_record.append((err_op, success)) write(c + ' ') count += success if hasattr(decoder, 'fini'): decoder.fini() if N: print() print(datestr) print(argv) print("error rate = %.8f" % (1. - 1. * count / (i + 1))) print("fail rate = %.8f" % (1. * failcount / (i + 1))) print("nonuniq = %d" % nonuniq) print("distance <= %d" % distance) if argv.n_rank: #n_ranks //= N n_ranks = list(enumerate(n_ranks)) n_ranks.sort(key=lambda item: -item[1]) #print [r[0] for r in n_ranks] print(' '.join('%d:%.2f' % r for r in n_ranks)) #print min(r[1] for r in n_ranks) #print max(r[1] for r in n_ranks) A = numpy.array([rec[0] for rec in n_record]) b = numpy.array([rec[1] for rec in n_record]) print(A.shape, b.shape) sol = lstsq(A, b) x, res, rk, s = sol #print x for i, val in enumerate(x): if val < 0: print(i, end=' ') print() if argv.k_rank: #k_ranks //= N k_ranks = list(enumerate(k_ranks)) k_ranks.sort(key=lambda item: -item[1]) #print [r[0] for r in k_ranks] print(' '.join('%d:%.2f' % r for r in k_ranks)) #print ' '.join(str(r) for r in k_ranks) #print min(r[1] for r in k_ranks) #print max(r[1] for r in k_ranks) A = numpy.array([rec[0] for rec in k_record]) b = numpy.array([rec[1] for rec in k_record]) #print A.shape, b.shape sol = lstsq(A, b) x, res, rk, s = sol #print x xs = list(enumerate(x)) xs.sort(key=lambda item: item[1]) print(' '.join('%d:%.2f' % item for item in xs)) if argv.addstabs and newHz: Hz = append2(code.Hz, newHz[0]) code = CSSCode(Hx=code.Hx, Hz=Hz) code.save(stem="addstabs") print(code) print(code.weightsummary()) elif argv.addstabs and newHx: # and newHx.shape[0]>code.Hx.shape[0]: newHx = array2(newHx) newHx = numpy.concatenate((code.Hx, newHx)) #print shortstr(newHx) #print Hx = solve.linear_independent(newHx) #print shortstr(Hx) #print code = CSSCode(Hx=Hx, Hz=code.Hz) code.save(stem="addstabs") print(code) print(code.weightsummary())
def get_code(self, grade=1): Hz, Hx = self.get_parity_checks(grade) code = CSSCode(Hx=Hx, Hz=Hz) return code
def make_surface_54_oriented(G0): " find integer chain complex " from bruhat.solve import shortstr, zeros2, dot2 from numpy import alltrue, zeros, dot print() print("|G0| =", len(G0)) a, ai, b, bi, c, ci, d, di = G0.gens # 5,5 coxeter subgroup G_55 = Group.generate([a, b, c]) assert G0.is_subgroup(G_55) # orientation subgroup L = Group.generate([a * b, a * d]) #assert len(L) == 60, len(L) print("L:", len(L)) orients = G0.left_cosets(L) assert len(orients) == 2 orients = list(orients) H = Group.generate([a, b]) faces = G_55.left_cosets(H) fold_faces = G0.left_cosets(H) print("faces:", len(faces)) print("fold_faces:", len(fold_faces)) #hom = G.left_action(faces) o_faces = [face.intersect(orients[0]) for face in faces] # oriented faces r_faces = [face.intersect(orients[1]) for face in faces] # reverse oriented faces K = Group.generate([b, c]) vertices = G_55.left_cosets(K) #assert len(vertices) == 12 # unoriented vertices o_vertices = [vertex.intersect(orients[0]) for vertex in vertices] # oriented vertices print("o_vertices:", len(o_vertices)) J0 = Group.generate([a, d]) assert len(J0) == 8 assert G0.is_subgroup(J0) act_edges = G0.action_subgroup(J0) act_fold_faces = G0.action_subgroup(H) #print("stab:", len(act_edges.get_stabilizer())) print("|G0| =", len(G0)) print("edges:", len(G0) // len(J0)) edges = G0.left_cosets(J0) #for e in edges: # k = choice(e.perms) # e1 = e.left_mul(~k) # assert set(e1.perms) == set(J0.perms) fold_perms = [] for i, g in enumerate(G0): assert g in G0 #h_edge = act_edges.tgt[act_edges.send_perms[i]] #h_fold_faces = act_fold_faces.tgt[act_fold_faces.send_perms[i]] h_edge = act_edges[g] h_fold_faces = act_fold_faces[g] n_edge = len(h_edge.fixed()) n_fold_faces = len(h_fold_faces.fixed()) count = 0 #perms = [] # extract action on the fixed edges #for e0 in edges: # #e1 = e0.left_mul(g) # e1 = g*e0 # if e0 != e1: # continue # perm = e0.left_mul_perm(g) # #print(perm, end=" ") # perms.append(perm) # count += 1 #assert count == n_edge if g.order() == 2 and g not in G_55 and g not in L: fold_perms.append(g) else: continue #print([p.order() for p in perms] or '', end="") print( "[|g|=%s,%s.%s.%s.%s]" % ( g.order(), n_edge or ' ', # num fixed edges n_fold_faces or ' ', # num fixed faces+vertexes [" ", "pres" ][int(g in G_55)], # preserves face/vertex distinction ["refl", "rot "][int(g in L)], # oriented or un-oriented ), end=" ", flush=True) print() print() J = Group.generate([a, c]) u_edges = G_55.left_cosets(J) print("u_edges:", len(u_edges)) J = Group.generate([c]) edges = G_55.left_cosets(J) print("edges:", len(edges)) # Here we choose an orientation on each edge: pairs = {} for e in u_edges: pairs[e] = [] for e1 in edges: if e.intersect(e1): pairs[e].append(e1) assert len(pairs[e]) == 2, len(pairs[e]) def shortstr(A): s = str(A) s = s.replace("0", '.') return s Hz = zeros((len(o_faces), len(u_edges)), dtype=int) for i, l in enumerate(o_faces): for j, e in enumerate(u_edges): le = l.intersect(e) if not le: continue e1, e2 = pairs[e] if e1.intersect(le): Hz[i, j] = 1 elif e2.intersect(le): Hz[i, j] = -1 else: assert 0 Hxt = zeros((len(u_edges), len(o_vertices)), dtype=int) for i, e in enumerate(u_edges): for j, v in enumerate(o_vertices): ev = e.intersect(v) if not ev: continue e1, e2 = pairs[e] if e1.intersect(ev): Hxt[i, j] = 1 elif e2.intersect(ev): Hxt[i, j] = -1 else: assert 0 #print(shortstr(Hz)) #print() #print(shortstr(Hxt)) #print() assert alltrue(dot(Hz, Hxt) == 0) for perm in fold_perms: pass 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)