def build_pauli(n): m = 2**n Gx = zeros2(m, n) Gz = zeros2(m, n) for i, idx in enumerate(genidx((2, ) * n)): for j in idx: Gx[i, j] = 1 Gz[i, j] = 1 Hx = zeros2(0, n) Hz = zeros2(0, n) return Gx, Gz, Hx, Hz
def build_compass(li, lj=None): if lj is None: lj = li n = li * lj keys = [(i, j) for i in range(li) for j in range(lj)] coords = {} for i, j in keys: for di in range(-li, li + 1): for dj in range(-lj, lj + 1): coords[i + di, j + dj] = keys.index( ((i + di) % li, (j + dj) % lj)) m = n Gx = zeros2(m, n) Gz = zeros2(m, n) idx = 0 for i in range(li): for j in range(lj): Gx[idx, coords[i, j]] = 1 Gx[idx, coords[i, j + 1]] = 1 Gz[idx, coords[i, j]] = 1 Gz[idx, coords[i + 1, j]] = 1 idx += 1 assert idx == m mx = lj - 1 Hx = zeros2(mx, n) for idx in range(mx): for i in range(li): Hx[idx, coords[i, idx]] = 1 Hx[idx, coords[i, idx + 1]] = 1 mz = li - 1 Hz = zeros2(mz, n) for idx in range(mz): for j in range(lj): Hz[idx, coords[idx, j]] = 1 Hz[idx, coords[idx + 1, j]] = 1 assert dot2(Hx, Hz.transpose()).sum() == 0 return Gx, Gz, Hx, Hz
def build_projective(n, dim=2): import geometry g = geometry.projective(n, dim) P = g.types[0] L = g.types[1] if dim == 3: L = g.types[2] points = g.tplookup[P] lines = g.tplookup[L] #lines = lines[:-4] # throw one out #points = points[:-1] # throw one out n = len(points) m = len(lines) Gx = zeros2(m, n) for i, line in enumerate(lines): for j, point in enumerate(points): if (line, point) in g.incidence: Gx[i, j] = 1 #print shortstr(Gx) Gz = Gx.copy() Hx = None Hz = None return Gx, Gz, Hx, Hz
def build_xy2(li, lj=None): if lj is None: lj = li n = li * lj keys = [(i, j) for i in range(li) for j in range(lj)] coords = {} for i, j in keys: for di in range(-li, li + 1): for dj in range(-lj, lj + 1): coords[i + di, j + dj] = keys.index( ((i + di) % li, (j + dj) % lj)) Gx = [] if argv.open: idxs = range(li - 1) jdxs = range(lj - 1) else: idxs = range(li) jdxs = range(lj) for i in idxs: for j in jdxs: g = zeros2(n) g[coords[i, j]] = 1 g[coords[i, j + 1]] = 1 g[coords[i + 1, j]] = 1 g[coords[i + 1, j + 1]] = 1 Gx.append(g) Gx = array2(Gx) Gz = Gx.copy() return Gx, Gz, None, None
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
def build_ham(self, excite=None, weights=None, Jx=1., Jz=1.): Gx, Gz = self.Gx, self.Gz Rx, Rz = self.Rx, self.Rz Hx, Hz = self.Hx, self.Hz Tx, Tz = self.Tx, self.Tz gz = len(Gz) r = len(Rx) n = self.n if type(excite) is int: _excite = [0] * len(Tx) _excite[excite] = 1 excite = tuple(_excite) if excite is not None: assert len(excite) == len(Tx) t = zeros2(n) for i, ex in enumerate(excite): if ex: t = (t + Tx[i]) % 2 #print "t:", shortstr(t) Gzt = dot2(Gz, t) else: Gzt = 0 if weights is None: weights = [1.] * len(Gx) assert len(weights) == len(Gx), len(weights) H = numpy.zeros((2**r, 2**r)) for i, v in enumerate(genidx((2, ) * r)): v = array2(v) syndrome = (dot2(Gz, Rx.transpose(), v) + Gzt) % 2 value = gz - 2 * syndrome.sum() #print shortstr(dot2(Rx.transpose(), v)), value H[i, i] = Jz * value #U.append(value) Pxt = self.Px.transpose() Qx = Rz.transpose() #print dot2(Rx, Qx) PxtQx = dot2(Pxt, Qx) for i, v in enumerate(genidx((2, ) * r)): v = array2(v) #print shortstr(v), #for g in Gx: for j, g in enumerate(Gx): u = (v + dot2(g, PxtQx)) % 2 k = eval('0b' + shortstr(u, zero='0')) H[i, k] += Jx * weights[j] #A[i, k] = A.get((i, k), 0) + 1 return H
def build_ising(n): assert n >= 2 mx = mz = n if n == 2: mz = 1 Gx = zeros2(mx, n) Gz = zeros2(mz, n) for i in range(mx): Gx[i, i] = 1 # transverse field for i in range(mz): Gz[i, i] = 1 Gz[i, (i + 1) % n] = 1 Hx = zeros2(1, n) Hz = zeros2(0, n) Hx[:] = 1 return Gx, Gz, Hx, Hz
def build_xy(n): m = n Gx = zeros2(m, n) Gz = zeros2(m, n) for i in range(m): Gx[i, i] = 1 Gx[i, (i + 1) % n] = 1 Gz[i, i] = 1 Gz[i, (i + 1) % n] = 1 if n % 2 == 0: Hx = zeros2(1, n) Hz = zeros2(1, n) Hx[:] = 1 Hz[:] = 1 else: Hx = Hz = None return Gx, Gz, Hx, Hz
def build_xy3(li, lj=None, lk=None): if lj is None: lj = li if lk is None: lk = li n = li * lj * lk keys = [(i, j, k) for i in range(li) for j in range(lj) for k in range(lk)] coords = {} for i, j, k in keys: for di in range(-li, li + 1): for dj in range(-lj, lj + 1): for dk in range(-lk, lk + 1): coords[i + di, j + dj, k + dk] = keys.index( ((i + di) % li, (j + dj) % lj, (k + dk) % lk)) Gx = [] if argv.open: idxs = range(li - 1) jdxs = range(lj - 1) kdxs = range(lk - 1) else: idxs = range(li) jdxs = range(lj) kdxs = range(lk) for i in idxs: for j in jdxs: for k in kdxs: g = zeros2(n) g[coords[i, j, k]] = 1 g[coords[i, j + 1, k]] = 1 g[coords[i + 1, j, k]] = 1 g[coords[i + 1, j + 1, k]] = 1 g[coords[i, j, k + 1]] = 1 g[coords[i, j + 1, k + 1]] = 1 g[coords[i + 1, j, k + 1]] = 1 g[coords[i + 1, j + 1, k + 1]] = 1 Gx.append(g) Gx = array2(Gx) Gz = Gx.copy() return Gx, Gz, None, None
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(): 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 print("G =") print(shortstr(G)) GG = dot2(G, G.transpose()) if GG.sum() == 0: print("self-dual code, p=%d mod 4" % (p % 4)) else: print("not a self-dual code, p=%d mod 4" % (p % 4)) m = rank(G) #assert m == N/2 print("F_2 rank =", m) #print("det:", numpy.linalg.det(G)) H = find_kernel(G) H = array2(H) print() print("H =") print(shortstr(H)) # ----------------------------------- print() print("non extended:") print("G =") G1 = G[:-1, :-1] print(shortstr(G1)) #print("det:", numpy.linalg.det(G1.astype(numpy.float))) m = rank(G1) print("rank =", m) #assert m == N/2 H1 = find_kernel(G1) H1 = array2(H1) print() print("H =") print(shortstr(H1)) GG = dot2(G, G.transpose()) if GG.sum() == 0: print("self-dual code") else: print("not a self-dual code") i = iter(nonresidues).__next__() idxs = [(j * i) % p for j in range(p)] assert len(set(idxs)) == p NG1 = G1[:, idxs] print("G~ =") print(shortstr(NG1)) print("G . G~ =") print(dot2(G1, NG1.transpose()).sum()) NH1 = find_kernel(NG1) NH1 = array2(NH1) print() print("NH =") print(shortstr(NH1)) #print(dot2(H1, NH1.transpose())) print("linear_independent(G):") print(shortstr(linear_independent(G1))) print("linear_independent(G~):") print(shortstr(linear_independent(NG1))) # ----------------------------------- # code should be fixed by PSL(2, p). G1 = zeros2(N, N) for u in range(N): for v in range(N): G1[u, v] = G[u, neginv(v)] #print() #print(shortstr(G1)) #print() # still in the codespace: assert dot2(G1, H.transpose()).sum() == 0 # ----------------------------------- # build PSL(2, p) via action on P(F_p) basis = list(range(N)) perm = dict((i, (i + 1) % p) for i in range(p)) perm[p] = p # infty A = Perm(perm, basis) perm = {} for u in range(N): v = neginv(u) perm[u] = v B = Perm(perm, basis) PSL = Group.generate([A, B]) print("|PSL(2,%d)| = %d" % (p, len(PSL))) print(residues) count = 0 for g in PSL: r1 = set(g[r] for r in residues) if r1 == residues: count += 1 print("count =", count) # g = PSL[5] # print(g.orbits()) # for u in span(G): # v = array2([u[A[i]] for i in basis]) # if not eq2(u, v): # continue # v = array2([u[B[i]] for i in basis]) # if not eq2(u, v): # continue # print(u) if p == 23: # Conway & Sloane, p274 cycles = [(p, ), list(range(23))] alpha = Perm.fromcycles(cycles, basis) cycles = [(p, ), (15, 7, 14, 5, 10, 20, 17, 11, 22, 21, 19), (0, ), (3, 6, 12, 1, 2, 4, 8, 16, 9, 18, 13)] beta = Perm.fromcycles(cycles, basis) cycles = [(p, 0), (15, 3), (7, 13), (14, 18), (5, 9), (10, 16), (20, 8), (17, 4), (11, 2), (22, 1), (21, 12), (19, 6)] gamma = Perm.fromcycles(cycles, basis) cycles = [(p, ), (14, 17, 11, 19, 22), (15, ), ( 20, 10, 7, 5, 21, ), (0, ), (18, 4, 2, 6, 1), (3, ), (8, 16, 13, 9, 12)] delta = Perm.fromcycles(cycles, basis) G = Group.generate([alpha, beta, gamma]) # PSL(2,23) assert len(G) == 6072
def mkop(n, ops): A = zeros2(len(ops), n) for i, op in enumerate(ops): for j in op: A[i, j] = 1 return A
def build_compass3(li, lj=None, lk=None): if lj is None: lj = li if lk is None: lk = li n = li * lj * lk keys = [(i, j, k) for i in range(li) for j in range(lj) for k in range(lk)] coords = {} for i, j, k in keys: for di in range(-li, li + 1): for dj in range(-lj, lj + 1): for dk in range(-lk, lk + 1): coords[i + di, j + dj, k + dk] = keys.index( ((i + di) % li, (j + dj) % lj, (k + dk) % lk)) m = 2 * n Gx = zeros2(m, n) Gz = zeros2(m, n) idx = 0 for i in range(li): for j in range(lj): for k in range(lk): Gx[idx, coords[i, j, k]] = 1 Gx[idx, coords[i + 1, j, k]] = 1 Gz[idx, coords[i, j, k]] = 1 Gz[idx, coords[i, j + 1, k]] = 1 idx += 1 Gx[idx, coords[i, j, k]] = 1 Gx[idx, coords[i, j + 1, k]] = 1 Gz[idx, coords[i, j, k]] = 1 Gz[idx, coords[i, j, k + 1]] = 1 idx += 1 assert idx == m # mx = lj-1 # Hx = zeros2(mx, n) # for idx in range(mx): # for i in range(li): # Hx[idx, coords[i, idx]] = 1 # Hx[idx, coords[i, idx+1]] = 1 # # mz = li-1 # Hz = zeros2(mz, n) # for idx in range(mz): # for j in range(lj): # Hz[idx, coords[idx, j]] = 1 # Hz[idx, coords[idx+1, j]] = 1 # # assert dot2(Hx, Hz.transpose()).sum() == 0 Hx = Hz = None return Gx, Gz, Hx, Hz
def sparse_ham_eigs(self, excite=None, weights=None, Jx=1., Jz=1.): key = str((excite, weights, Jx, Jz)) if key in self.cache: return self.cache[key] Gx, Gz = self.Gx, self.Gz Rx, Rz = self.Rx, self.Rz Hx, Hz = self.Hx, self.Hz Tx, Tz = self.Tx, self.Tz Px, Pz = self.Px, self.Pz gz = len(Gz) r = len(Rx) n = self.n if type(excite) is int: _excite = [0] * len(Tx) _excite[excite] = 1 excite = tuple(_excite) if excite is not None: assert len(excite) == len(Tx) t = zeros2(n) for i, ex in enumerate(excite): if ex: t = (t + Tx[i]) % 2 #print "t:", shortstr(t) Gzt = dot2(Gz, t) else: Gzt = 0 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.tostring()] = i verts.append(v) print "span:", len(verts) assert len(lookup) == len(verts) mz = len(Gz) n = len(verts) print "building H", H = {} # 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() syndrome = (dot2(Gz, v) + Gzt) % 2 count = syndrome.sum() #syndrome = (dot2(Gz, Rx.transpose(), v) + Gzt)%2 #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.tostring()] H[i, j] = H.get((i, j), 0) + 1 print "\nnnz:", len(H) for i in range(len(U)): H[i, i] = H.get((i, i), 0) + U[i] N = len(U) del U #H1 = sparse.lil_matrix(N, N) keys = H.keys() keys.sort() data = [] rows = [] cols = [] for idx in keys: #H1[idx] = H[idx] data.append(H[idx]) rows.append(idx[0]) cols.append(idx[1]) del H H1 = sparse.coo_matrix((data, (rows, cols)), (N, N)) H1 = sparse.csr_matrix(H1, dtype=numpy.float64) #print "do_lanczos: eigsh" vals, vecs = sparse.linalg.eigsh(H1, k=min(N - 5, 40), which="LM") vals -= offset self.cache[key] = vals return vals
return model if __name__ == "__main__": Gx, Gz, Hx, Hz = build() model = build_model(Gx, Gz, Hx, Hz) if argv.extend: k = len(model.Lx) n = model.n + k mx = len(model.Hx) mz = len(model.Hz) Hx = zeros2(mx + k, n + k) Hz = zeros2(mz + k, n + k) Hx[:mx, :n] = model.Hx Hz[:mz, :n] = model.Hz Hx[mx:, :n] = model.Lx Hz[mz:, :n] = model.Lz for i in range(k): Hx[mx + i, n + i] = 1 Hz[mz + i, n + i] = 1 model = build_model() # um.... print model