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 homology(self, i): "kern of Hs[i] mod image Hs[i+1]" H0, H1 = self[i], self[i + 1] #print "homology", i #print H0.shape, H1.shape L = solve.find_logops(H0, H1.transpose()) return L
def main(): import models assert not argv.orbiham, "it's called orbigraph now" if argv.find_ideals: find_ideals() return Gx, Gz, Hx, Hz = models.build() if argv.chainmap: do_chainmap(Gx, Gz) if argv.symmetry: do_symmetry(Gx, Gz, Hx, Hz) return #print shortstrx(Gx, Gz) if argv.report: print("Hz:") for i, h in enumerate(Hz): print(i, shortstr(h), h.sum()) #print shortstr(find_stabilizers(Gx, Gz)) Lz = find_logops(Gx, Hz) Lx = find_logops(Gz, Hx) #print "Lz:", shortstr(Lz) if Lz.shape[0]*Lz.shape[1]: print(Lz.shape, Gx.shape) check_commute(Lz, Gx) check_commute(Lz, Hx) Px = get_reductor(Hx) # projector onto complement of rowspan of Hx Pz = get_reductor(Hz) Rz = [dot2(Pz, g) for g in Gz] Rz = array2(Rz) Rz = row_reduce(Rz, truncate=True) rz = len(Rz) n = Gx.shape[1] print("n =", n) if len(Lx): print("Lx Lz:") print(shortstrx(Lx, Lz)) print("Hx:", len(Hx), "Hz:", len(Hz)) print("Gx:", len(Gx), "Gz:", len(Gz)) Rx = [dot2(Px, g) for g in Gx] Rx = array2(Rx) Rx = row_reduce(Rx, truncate=True) rx = len(Rx) print("Rx:", rx, "Rz:", rz) if argv.show: print(shortstrx(Rx, Rz)) Qx = u_inverse(Rx) Pxt = Px.transpose() assert eq2(dot2(Rx, Qx), identity2(rx)) assert eq2(dot2(Rx, Pxt), Rx) #print shortstr(dot2(Pxt, Qx)) PxtQx = dot2(Pxt, Qx) lines = [shortstr(dot2(g, PxtQx)) for g in Gx] lines.sort() #print "PxtQx:" #for s in lines: # print s #print "RzRxt" #print shortstr(dot2(Rz, Rx.transpose())) offset = argv.offset if len(Hz): Tx = find_errors(Hz, Lz, Rz) else: Tx = zeros2(0, n) if argv.dense: dense(**locals()) return if argv.dense_full: dense_full(**locals()) return if argv.show_delta: show_delta(**locals()) return if argv.slepc: slepc(**locals()) return # if argv.orbigraph: # from linear import orbigraph # orbigraph(**locals()) # return v0 = None # excite = argv.excite # if excite is not None: # v0 = zeros2(n) # v0[excite] = 1 verts = [] lookup = {} for i, v in enumerate(span(Rx)): # XXX does not scale well if v0 is not None: v = (v+v0)%2 v = dot2(Px, v) lookup[v.tobytes()] = i verts.append(v) print("span:", len(verts)) assert len(lookup) == len(verts) mz = len(Gz) n = len(verts) if argv.lie: U = [] for i, v in enumerate(verts): count = dot2(Gz, v).sum() Pxv = dot2(Px, v) assert count == dot2(Gz, Pxv).sum() U.append(mz - 2*count) uniq = list(set(U)) uniq.sort(reverse=True) s = ', '.join("%d(%d)"%(val, U.count(val)) for val in uniq) print(s) print("sum:", sum(U)) return if n <= 1024 and argv.solve: H = numpy.zeros((n, n)) syndromes = [] for i, v in enumerate(verts): syndromes.append(dot2(Gz, v)) count = dot2(Gz, v).sum() Pxv = dot2(Px, v) assert count == dot2(Gz, Pxv).sum() H[i, i] = mz - 2*count for g in Gx: v1 = (g+v)%2 v1 = dot2(Px, v1) j = lookup[v1.tobytes()] H[i, j] += 1 if argv.showham: s = lstr2(H, 0).replace(', ', ' ') s = s.replace(' 0', ' .') s = s.replace(', -', '-') print(s) vals, vecs = numpy.linalg.eigh(H) show_eigs(vals) if argv.show_partition: beta = argv.get("beta", 1.0) show_partition(vals, beta) if argv.orbigraph: if argv.symplectic: H1 = build_orbigraph(H, syndromes) else: H1 = build_orbigraph(H) print("orbigraph:") print(H1) vals, vecs = numpy.linalg.eig(H1) show_eigs(vals) elif argv.sparse: print("building H", end=' ') A = {} # adjacency U = [] # potential if offset is None: offset = mz + 1 # make H positive definite for i, v in enumerate(verts): if i%1000==0: write('.') count = dot2(Gz, v).sum() #H[i, i] = mz - 2*count U.append(offset + mz - 2*count) for g in Gx: v1 = (g+v)%2 v1 = dot2(Px, v1) j = lookup[v1.tobytes()] A[i, j] = A.get((i, j), 0) + 1 print("\nnnz:", len(A)) if argv.lanczos: vals, vecs = do_lanczos(A, U) elif argv.orbigraph: vals, vecs = do_orbigraph(A, U) else: return vals -= offset # offset doesn't change vecs show_eigs(vals) elif argv.orbigraph: assert n<=1024 H = numpy.zeros((n, n)) syndromes = [] for i, v in enumerate(verts): syndromes.append(dot2(Gz, v)) count = dot2(Gz, v).sum() Pxv = dot2(Px, v) assert count == dot2(Gz, Pxv).sum() H[i, i] = mz - 2*count for g in Gx: v1 = (g+v)%2 v1 = dot2(Px, v1) j = lookup[v1.tobytes()] H[i, j] += 1 if argv.showham: s = lstr2(H, 0).replace(', ', ' ') s = s.replace(' 0', ' .') s = s.replace(', -', '-') print(s) if argv.symplectic: H1 = build_orbigraph(H, syndromes) else: H1 = build_orbigraph(H)
def build_gcolor2(): n = 39 m = 10 delta = 19 top = n - 1 # top qubit # bottom faces: points must be adjacent in each face bfaces = [[0, 1, 2, 3], [1, 4, 5, 6, 7, 2], [3, 2, 7, 8], [4, 9, 10, 5], [8, 7, 6, 11, 12, 13], [9, 14, 15, 10], [5, 10, 15, 16, 11, 6], [11, 16, 17, 12], [13, 12, 17, 18]] faces = list(bfaces) + [[i + delta for i in face] for face in bfaces] def check_faces(): items = [list(face) for face in faces] for face in items: assert len(face) % 2 == 0, face face.sort() assert len(set([tuple(face) for face in items])) == len(items) check_faces() # bottom edges bedges = [] for face in bfaces: f = len(face) for i in range(f): bedges.append([face[i], face[(i + 1) % f]]) # edges are not yet unique.. for edge in bedges: edge.sort() bedges = list(set([tuple(e) for e in bedges])) # extrude bottom edges to make a face for edge in bedges: edge = list(edge) a, b = edge face = edge + [a + delta, b + delta] faces.append(face) check_faces() stabs = [] for face in bfaces: stabs.append(face + [i + delta for i in face]) # top faces for face in [[0, 1, 4, 9, 14], [0, 3, 8, 13, 18], [14, 15, 16, 17, 18]]: face = [i + delta for i in face] + [top] faces.append(face) check_faces() stabs.append([i + delta for i in range(19)] + [top]) g = len(faces) #print "faces:", g for stab in stabs: assert len(stab) % 2 == 0, stab #faces.sort() #for face in faces: # print face Gx = mkop(n, faces) Gz = Gx.copy() rows = [shortstr(g) for g in Gx] #rows.sort() #for i, row in enumerate(rows): # print row, faces[i] assert len(set(rows)) == len(rows) Hz = mkop(n, stabs) Hx = Hz.copy() # bottom face Lx = mkop(n, [list(range(19))]) Lz = Lx.copy() check_commute(Hx, Hz) check_commute(Hx, Gz) check_commute(Hz, Gx) check_commute(Gx, Lz) check_commute(Gz, Lx) check_commute(Hx, Lz) check_commute(Hz, Lx) #code = CSSCode(Hx=Hx, Gx=Gx, Hz=Hz, Gz=Gz, build=False) Lx = find_logops(Gz, Hx) #print "Lx:", shortstr(Lx) return Gx, Gz, Hx
def build_model(Gx=None, Gz=None, Hx=None, Hz=None): if Gx is None: Gx, Gz, Hx, Hz = build() n = Gx.shape[1] if Hx is None: Hx = find_stabilizers(Gz, Gx) if Hz is None: Hz = find_stabilizers(Gx, Gz) check_commute(Hx, Hz) check_commute(Gx, Hz) check_commute(Hx, Gz) #Px = get_reductor(concatenate((Lx, Hx))) #Pz = get_reductor(concatenate((Lz, Hz))) Px = get_reductor(Hx) Pz = get_reductor(Hz) # Lz = find_logops( Hx , Hz ) # find_logops( ............. , ............. ) # ( commutes with , orthogonal to ) # ( ............. , ............. ) Lz = find_logops(Gx, Hz) assert Lz.shape[1] == n if 0: PGz = get_reductor(Gz) Lz = dot2(Lz, PGz.transpose()) Lz = row_reduce(Lz) print(shortstrx(Lz, Gz, Hz)) if len(Lz): #print Lz.shape, Hz.shape assert len(row_reduce(concatenate((Lz, Hz)))) == len(Lz) + len(Hz) assert len(row_reduce(concatenate( (Lz, Gz)))) == len(Lz) + len(row_reduce(Gz)) # Tz = find_errors( Hx , Lx ) # find_errors( ............. , ............. ) # ( conjugate to , commutes with ) # ( ............. , ............. ) Lx = find_errors(Lz, Gz) # invert Lz, commuting with Gz check_commute(Lx, Gz) check_commute(Lx, Hz) check_conjugate(Lx, Lz) check_commute(Lz, Gx) check_commute(Lz, Hx) # Lx | Lz # Hx | ? # ? | Hz # ? | ? #Rz = find_logops(concatenate((Lx, Hx)), Hz) Rz = dot2(Gz, Pz.transpose()) Rz = row_reduce(Rz) check_commute(Rz, Lx) check_commute(Rz, Hx) Rx = dot2(Gx, Px.transpose()) Rx = row_reduce(Rx) check_commute(Rx, Lz) check_commute(Rx, Hz) # Lx | Lz # Hx | ? # ? | Hz # Rx'| Rz' Tz = find_errors(Hx, concatenate((Lx, Rx))) Tx = find_errors(Hz, concatenate((Lz, Rz, Tz))) assert len((concatenate((Lx, Hx, Tx, Rx)))) == n assert len((concatenate((Lz, Hz, Tz, Rz)))) == n assert len(row_reduce(concatenate((Lx, Hx, Tx, Rx)))) == n assert len(row_reduce(concatenate((Lz, Hz, Tz, Rz)))) == n check_commute(Rz, Tx) Rx = find_errors(Rz, concatenate((Lz, Hz, Tz))) check_conjugate(Rx, Rz) check_commute(Rx, Hz) check_commute(Rx, Tz) check_commute(Rx, Lz) Rxt = Rx.transpose() Rzt = Rz.transpose() Pxt = Px.transpose() Pzt = Pz.transpose() check_sy(Lx, Hx, Tx, Rx, Lz, Hz, Tz, Rz) assert eq2(dot2(Gz, Rxt), dot2(Gz, Pzt, Rxt)) assert eq2(dot2(Gx, Rzt), dot2(Gx, Pxt, Rzt)) # print shortstrx(dot2(Rx, Pz), Rx) assert eq2(dot2(Rx, Pz), Rx) assert eq2(dot2(Rz, Px), Rz) assert len(find_kernel(dot2(Gz, Rx.transpose()))) == 0 model = Model(locals()) if argv.dual: model = model.get_dual() argv.dual = False # HACK !! return model
def main(l): lattice = Lattice(l) n = len(lattice.qubits) print(lattice) code = lattice.build_code(check=False) #Ex = lattice.Ex Gx, Gz = code.Gx, code.Gz Hx, Hz = code.Hx, code.Hz Lx = find_logops(Gz, Hx) #print Lx #print dot2(Lx, Gz.transpose()) print(code) print("Gx:") print(shortstrx(Gx)) print("Hx:") print(shortstrx(Hx)) print("Lx:") print(shortstrx(Lx)) print("0-simplices (bodies):", len(lattice.simplices[0])) print("1-simplices (faces):", len(lattice.simplices[1])) print("2-simplices (edges):", len(lattice.simplices[2])) corners = [] edges = [] faces = [] internal = [] for i in range(n): gw = Gx[:, i].sum() hw = Hx[:, i].sum() assert gw >= 3 assert hw in [1, 2, 3, 4] assert gw in [3, 5, 6] if gw == 3: corners.append(i) assert hw == 1 elif gw == 5: edges.append(i) assert hw == 2 elif gw == 6: if hw == 3: faces.append(i) else: assert hw == 4 internal.append(i) assert len(corners) + len(edges) + len(faces) + len(internal) == n #return # op = zeros2(n) # for i in corners: # op[i] = 1 # assert solve(Gx.transpose(), op) if 0: # ops spanned by gauge operators are all even weight for trial in range(100): m = len(Gx) op = zeros2(n) for i in range(m // 2): op += Gx[randint(0, m - 1)] op %= 2 w = op.sum() % 2 assert w % 2 == 0 print(op) #return desc = "stabs gauge strings qubits".split() for d in range(4): counts = {} print("%d:" % d, desc[d]) for p in lattice.simplices[d]: #print '\t', p #if not p.is_internal(): # continue cs = [colorof(v) for v in p.vs] cs.sort() cs = tuple(cs) + (len(lattice.get_qubits(p)), ) counts[cs] = counts.get(cs, 0) + 1 print(counts) R = [] for p in lattice.simplices[1]: a = lattice.make_op(p) a.shape = 1, n R.append(a) find_skip(Hx, Lx, R) return A = Hx[:, :] r = rank(A) source = [] for p in lattice.simplices[1]: if not p.is_internal(): continue vs = p.vs v0, v1 = vs key = (v1 - v0), p source.append(key) source.sort(key=lambda k_p: (k_p[0].color, k_p[0]), reverse=True) source = [(None, p) for p in lattice.simplices[1]] gauges = {} for key, p in source: if p.is_internal(): vs = p.vs v0, v1 = vs #write(str(v1-v0)) a = lattice.make_op(p) a.shape = 1, n A1 = numpy.concatenate((A, a)) if rank(A1) == r: #write("\n") continue #write(" OK\n") r = r + 1 A = A1 key = [colorof(v) for v in p.vs] key.sort() key = tuple(key) # + (len(lattice.get_qubits(p)),) gauges.setdefault(key, []).append(p) #print for key, value in list(gauges.items()): print(key, len(value)) print("rank:", r) print(rank(A)) #print shortstrx(A) return key = list(gauges.keys())[0] A = [] for op in gauges[key]: a = zeros2(n) for qubit in lattice.get_qubits(op): a[qubit.i] = 1 A.append(a) A = array2(A) #print shortstrx(A) print(A.shape) print(rank(A)) A = numpy.concatenate((Hx, A)) print(A.shape) print(rank(A)) #code.build_from_gauge() #A = dot2(code.Gx, code.Gz.transpose()) #print shortstrx(code.Gxr, code.Gzr) #print shortstr(A) assert rank(Hx) == Hx.shape[0] # L.I. #Hx = linear_independant(Hx) #Hz = linear_independant(Hz) n = code.n m = Hx.shape[0] + Hz.shape[0] r = n - m - 1 assert r % 2 == 0 return Rx = [] Rz = [] for gx, gz in pairs: Rx.append(gx) Rz.append(gz) Rx.append(gz) Rz.append(gx) Rx = array2(Rx) Rz = array2(Rz) print(shortstrx(Rx, Rz)) assert Rx.shape[0] == r assert rank(Rx) == r assert rank(numpy.concatenate((Rx, Hx))) == r + m // 2 A = dot2(Rx, Rz.transpose()) print(shortstrx(A)) return Rx = slow_remove(Gx, Hx) Rz = slow_remove(Gz, Hz) r = rank(Rx) assert r + m + 1 == n print("r =", r)
def build(self, logops_only=False, check=True, verbose=False): Hx, Hz = self.Hx, self.Hz Lx, Lz = self.Lx, self.Lz Tx, Tz = self.Tx, self.Tz if verbose: _write = write else: _write = lambda *args : None _write('li:') self.Hx = Hx = solve.linear_independent(Hx) self.Hz = Hz = solve.linear_independent(Hz) mz, n = Hz.shape mx, nx = Hx.shape assert n==nx assert mz+mx<=n, (mz, mx, n) _write('build:') if check: # check kernel of Hx contains image of Hz^t check_commute(Hx, Hz) if Lz is None: _write('find_logops(Lz):') Lz = solve.find_logops(Hx, Hz, verbose=verbose) #print shortstr(Lz) #_write(len(Lz)) k = len(Lz) assert n-mz-mx==k, "_should be %d logops, found %d. Is Hx/z degenerate?"%( n-mx-mz, k) _write("n=%d, mx=%d, mz=%d, k=%d\n" % (n, mx, mz, k)) # Find Lx -------------------------- if Lx is None: _write('find_logops(Lx):') Lx = solve.find_logops(Hz, Hx, verbose=verbose) assert len(Lx)==k if check: check_commute(Lx, Hz) check_commute(Lz, Hx) U = dot2(Lz, Lx.transpose()) I = identity2(k) A = solve.solve(U, I) assert A is not None, "problem with logops: %s"%(U,) #assert eq2(dot2(U, A), I) #assert eq2(dot2(Lz, Lx.transpose(), A), I) Lx = dot2(A.transpose(), Lx) if check: check_conjugate(Lz, Lx) if not logops_only: # Find Tz -------------------------- _write('Find(Tz):') U = zeros2(mx+k, n) U[:mx] = Hx U[mx:] = Lx B = zeros2(mx+k, mx) B[:mx] = identity2(mx) Tz_t = solve.solve(U, B) Tz = Tz_t.transpose() assert len(Tz) == mx check_conjugate(Hx, Tz) check_commute(Lx, Tz) # Find Tx -------------------------- _write('Find(Tx):') U = zeros2(n, n) U[:mz] = Hz U[mz:mz+k] = Lz U[mz+k:] = Tz B = zeros2(n, mz) B[:mz] = identity2(mz) Tx_t = solve.solve(U, B) Tx = Tx_t.transpose() _write('\n') if check: check_conjugate(Hz, Tx) check_commute(Lz, Tx) check_commute(Tz, Tx) self.k = k self.Lx = Lx self.Lz = Lz self.Tz = Tz self.Tx = Tx
def build_from_gauge(self, check=True, verbose=False): write("build_from_gauge:") Gx, Gz = self.Gx, self.Gz Hx, Hz = self.Hx, self.Hz Lx, Lz = self.Lx, self.Lz #print "build_stab" #print shortstr(Gx) #vs = solve.find_kernel(Gx) #vs = list(vs) #print "kernel Gx:", len(vs) n = Gx.shape[1] if Hz is None: A = dot2(Gx, Gz.transpose()) vs = solve.find_kernel(A) vs = list(vs) #print "kernel GxGz^T:", len(vs) Hz = zeros2(len(vs), n) for i, v in enumerate(vs): Hz[i] = dot2(v.transpose(), Gz) Hz = solve.linear_independent(Hz) if Hx is None: A = dot2(Gz, Gx.transpose()) vs = solve.find_kernel(A) vs = list(vs) Hx = zeros2(len(vs), n) for i, v in enumerate(vs): Hx[i] = dot2(v.transpose(), Gx) Hx = solve.linear_independent(Hx) if check: check_commute(Hz, Hx) check_commute(Hz, Gx) check_commute(Hx, Gz) #Gxr = numpy.concatenate((Hx, Gx)) #Gxr = solve.linear_independent(Gxr) #print(Hx.shape) #assert rank(Hx) == len(Hx) #assert eq2(Gxr[:len(Hx)], Hx) #Gxr = Gxr[len(Hx):] Px = solve.get_reductor(Hx).transpose() Gxr = dot2(Gx, Px) Gxr = solve.linear_independent(Gxr) #Gzr = numpy.concatenate((Hz, Gz)) #Gzr = solve.linear_independent(Gzr) #assert eq2(Gzr[:len(Hz)], Hz) #Gzr = Gzr[len(Hz):] Pz = solve.get_reductor(Hz).transpose() Gzr = dot2(Gz, Pz) Gzr = solve.linear_independent(Gzr) if Lx is None: Lx = solve.find_logops(Gz, Hx) if Lz is None: Lz = solve.find_logops(Gx, Hz) write('\n') print("Gxr", Gxr.shape) print("Gzr", Gzr.shape) assert len(Gxr)==len(Gzr) kr = len(Gxr) V = dot2(Gxr, Gzr.transpose()) U = solve.solve(V, identity2(kr)) assert U is not None Gzr = dot2(U.transpose(), Gzr) if check: check_conjugate(Gxr, Gzr) check_commute(Hz, Gxr) check_commute(Hx, Gzr) check_commute(Lz, Gxr) check_commute(Lx, Gzr) assert len(Lx)+len(Hx)+len(Hz)+len(Gxr)==n self.Lx, self.Lz = Lx, Lz self.Hx, self.Hz = Hx, Hz self.Gxr, self.Gzr = Gxr, Gzr