def decode(self, p, err_op, **kw): decode0 = self.decode0 decode1 = self.decode1 op = decode0.decode(p, err_op, **kw) if op is None: write("F") op = decode1.decode(p, err_op, **kw) return op
def build_spin_chain(G): I = G.get_ident() In = G.get_ident(degree) nt_ops = [op for op in G if op != I and op.phase == 1] while 1: while 1: A = [I] * degree B = [I] * degree for i in range(weight): a = choice(nt_ops) A[i] = a B[(i + 1) % degree] = a A = reduce(matmul, A) B = reduce(matmul, B) if A * B == B * A: break gen = [A, B] for i in range(2, degree): idxs = [A.idxs[(-i + j) % degree] for j in range(degree)] op = Tensor(G, idxs, A.phase) gen.append(op) print("gen:") for op in gen: print(" ", op) S = mulclose(gen) print("|S| =", len(S)) #ops = [G.get_dense(op) for op in S] #P = reduce(add, ops) P = G.get_dense(S[0]) for op in S[1:]: P = P + G.get_dense(op) r = P.norm() if abs(r) > EPSILON: break write(".") show_spec(P) find_errors(G, P, degree) return
def __init__(self, code, weight=4, maxsize=256 * 1024): lookup = {} n = code.n Hz = code.Hz Lz = code.Lz err = zeros2(n) write("LookupDecoder: building...") w = 0 #for w in range(0, weight+1): count = 0 remove = set() while w < weight + 1 or len(lookup) < maxsize: for idxs in choose(list(range(n)), w): err[:] = 0 err[idxs] = 1 syn = dot2(Hz, err) key = syn.tostring() other = lookup.get(key) if other is None: lookup[key] = idxs elif len(other) == w: for idx in other: err[idx] = (err[idx] + 1) % 2 assert dot2(Hz, err).sum() == 0 #assert dot2(Lz, err).sum()==0, "not an exact decoder." if dot2(Lz, err).sum(): remove.add(key) if len(lookup) == count: break count = len(lookup) w += 1 write("\n") for key in remove: del lookup[key] print("lookup size:", len(lookup)) self.lookup = lookup self.code = code
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 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 whack(code, decoder, p, N, C0, error_rate, mC, verbose, argv): """keep decoding until we get below error_rate""" errors = [] succeeds = [] # put error ops here when we decode them fails = [] # if the decoder is wrong for i in range(N): err_op = ra.binomial(1, p, (code.n, )) err_op = err_op.astype(numpy.int32) errors.append(err_op) target_succeed = (1. - error_rate) * N i = 0 C = C0 while len(succeeds) < target_succeed and len(succeeds) + len( errors) >= target_succeed: err_op = errors[i] # We use Hz to look at X type errors (bitflip errors) write(str(err_op.sum())) s = dot2(code.Hz, err_op) write(":s%d:" % s.sum()) op = decoder.decode(p, err_op, C=C, verbose=verbose, argv=argv) c = 'F' success = False if op is None: print(i, "TRY AGAIN") i = i + 1 else: 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()) success = code.is_stab(op) c = '.' if success else 'x' errors.pop(i) if success: print(i, "GOOD") succeeds.append(err_op) else: print(i, "BAD") fails.append(err_op) if i == len(errors): i = 0 C = int(ceil(C * mC)) print(("C = ", C)) write(c + ' ') print("errors = ", len(errors), "succeeds =", len(succeeds), "fails =", len(fails)) if len(succeeds) >= target_succeed: print("SUCCESS") else: assert len(succeeds) + len(errors) < target_succeed print("FAIL") print() print(datestr) print(argv) print("error rate = %.8f" % (1. * (len(errors) + len(fails)) / N)) print("fail rate = %.8f" % (1. * len(fails) / N))
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 main(): name = argv.get("G", "icosa") G = groups.build(name) def get_reflects(G, I): reflects = [] count = 0 for ops in cross((G, ) * degree): op = reduce(matmul, ops) if op * op == I: count += 1 reflects.append(op) reflects.remove(I) reflects.remove(nI) return reflects def rand_reflect(G, I, degree, weight=None): if weight is None: weight = degree while 1: #ops = [choice(G) for i in range(degree)] idxs = list(range(degree)) ops = [G.get_ident() for i in idxs] for j in range(weight): idx = choice(idxs) idxs.remove(idx) ops[idx] = choice(G.non_central) op = reduce(matmul, ops) if op * op == I and op != I and op.phase == 1: return op def mk_stab(reflects): # build commutative subgroup from these size = 0 for trials in range(100): remain = list(reflects) gen = [] S = [] while remain: idx = randint(0, len(remain) - 1) a = remain.pop(idx) for b in gen: if a * b != b * a: break else: if a not in S: S1 = mulclose(gen + [a]) if nI not in S1: S = S1 gen.append(a) if len(S) > size: #print("|S| =", len(S)) size = len(S) for op in S: assert op * op == I return gen, S print("|G| =", len(G)) print("building...", end="", flush=True) G = Group(G) print("done") degree = argv.get("degree", 2) weight = argv.get("weight", degree) def build_spin_chain(G): I = G.get_ident() In = G.get_ident(degree) nt_ops = [op for op in G if op != I and op.phase == 1] while 1: while 1: A = [I] * degree B = [I] * degree for i in range(weight): a = choice(nt_ops) A[i] = a B[(i + 1) % degree] = a A = reduce(matmul, A) B = reduce(matmul, B) if A * B == B * A: break gen = [A, B] for i in range(2, degree): idxs = [A.idxs[(-i + j) % degree] for j in range(degree)] op = Tensor(G, idxs, A.phase) gen.append(op) print("gen:") for op in gen: print(" ", op) S = mulclose(gen) print("|S| =", len(S)) #ops = [G.get_dense(op) for op in S] #P = reduce(add, ops) P = G.get_dense(S[0]) for op in S[1:]: P = P + G.get_dense(op) r = P.norm() if abs(r) > EPSILON: break write(".") show_spec(P) find_errors(G, P, degree) return I = G.get_ident(degree) nI = -I n_reflects = argv.get("reflects", 4) reflects = [] while 1: reflects += [ rand_reflect(G, I, degree, weight) for i in range(n_reflects) ] if 0: #print("reflects:") idxs = set() for op in reflects: for idx in op.idxs: idxs.add(idx) idxs = list(idxs) idxs.sort() ops = [G[idx] for idx in idxs] H = mulclose(ops) print("reflects:", idxs) print("|H|:", len(H)) gen, S = mk_stab(reflects) write("%s," % len(S)) if len(S) >= 2**degree: break print() print("gen:") for op in gen: print(" ", op) gen.pop(0) S = mulclose(gen) # build projector onto codespace ops = [G.get_dense(op) for op in S] P = reduce(add, ops) show_spec(P) find_errors(G, P, degree)