def get_adj(left, right): A = zeros2((len(left), len(right))) for i, l in enumerate(left): for j, r in enumerate(right): lr = l.intersect(r) A[i, j] = len(lr) return A
def rel(self, a, b): incidence = self.incidence A = zeros2(len(a), len(b)) for i, aa in enumerate(a): for j, bb in enumerate(b): A[i, j] = (aa, bb) in incidence return A
def syparse(decl): for c in '0123456789': decl = decl.replace(c, ' ') decl = decl.strip().split() n = len(decl[0]) m = len(decl) H = zeros2(m, 2 * n) for i, row in enumerate(decl): for j, c in enumerate(row): if c == 'X' or c == 'Y': H[i, j] = 1 if c == 'Z' or c == 'Y': H[i, n + j] = 1 return H
def symplectic(n): F = zeros2(2 * n, 2 * n) for i in range(n): F[i, n + i] = 1 F[n + i, i] = 1 return F
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 search(): # Bravyi, Haah, 1209.2426v1 sec IX. # https://arxiv.org/pdf/1209.2426.pdf verbose = argv.get("verbose") m = argv.get("m", 6) # _number of rows k = argv.get("k", None) # _number of odd-weight rows # these are the variables N_x xs = list(cross([(0, 1)]*m)) maxweight = argv.maxweight minweight = argv.get("minweight", 1) xs = [x for x in xs if minweight <= sum(x)] if maxweight: xs = [x for x in xs if sum(x) <= maxweight] N = len(xs) lhs = [] rhs = [] # bi-orthogonality for a in range(m): for b in range(a+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == 1: v[i] = 1 if v.sum(): lhs.append(v) rhs.append(0) # tri-orthogonality for a in range(m): for b in range(a+1, m): for c in range(b+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == x[c] == 1: v[i] = 1 if v.sum(): lhs.append(v) rhs.append(0) # # dissallow columns with weight <= 1 # for i, x in enumerate(xs): # if sum(x)<=1: # v = zeros2(N) # v[i] = 1 # lhs.append(v) # rhs.append(0) if k is not None: # constrain to k _number of odd-weight rows assert 0<=k<m for a in range(m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == 1: v[i] = 1 lhs.append(v) if a<k: rhs.append(1) else: rhs.append(0) A = array2(lhs) rhs = array2(rhs) #print(shortstr(A)) B = pseudo_inverse(A) soln = dot2(B, rhs) if not eq2(dot2(A, soln), rhs): print("no solution") return if verbose: print("soln:") print(shortstr(soln)) soln.shape = (N, 1) rhs.shape = A.shape[0], 1 K = array2(list(find_kernel(A))) #print(K) #print( dot2(A, K.transpose())) #sols = [] #for v in span(K): best = None density = 1.0 size = 99*N trials = argv.get("trials", 1024) count = 0 for trial in range(trials): u = rand2(len(K), 1) v = dot2(K.transpose(), u) #print(v) v = (v+soln)%2 assert eq2(dot2(A, v), rhs) if v.sum() > size: continue size = v.sum() Gt = [] for i, x in enumerate(xs): if v[i]: Gt.append(x) if not Gt: continue Gt = array2(Gt) G = Gt.transpose() assert is_morthogonal(G, 3) if G.shape[1]<m: continue if 0 in G.sum(1): continue if argv.strong_morthogonal and not strong_morthogonal(G, 3): continue #print(shortstr(G)) # for g in G: # print(shortstr(g), g.sum()) # print() _density = float(G.sum()) / (G.shape[0]*G.shape[1]) #if best is None or _density < density: if best is None or G.shape[1] <= size: best = G size = G.shape[1] density = _density if 0: #sols.append(G) Gx = even_rows(G) assert is_morthogonal(Gx, 3) if len(Gx)==0: continue GGx = array2(list(span(Gx))) assert is_morthogonal(GGx, 3) count += 1 print("found %d solutions" % count) if best is None: return G = best #print(shortstr(G)) for g in G: print(shortstr(g), g.sum()) print() print("density:", density) print("shape:", G.shape) G = linear_independent(G) A = list(span(G)) print(strong_morthogonal(A, 1)) print(strong_morthogonal(A, 2)) print(strong_morthogonal(A, 3)) #print(shortstr(dot2(G, G.transpose()))) if 0: B = pseudo_inverse(A) v = dot2(B, rhs) print("B:") print(shortstr(B)) print("v:") print(shortstr(v)) assert eq2(dot2(B, v), rhs)
def search_selfdual(): verbose = argv.get("verbose") m = argv.get("m", 6) # _number of rows k = argv.get("k", None) # _number of odd-weight rows maxweight = argv.get("maxweight", m) minweight = argv.get("minweight", 1) # these are the variables N_x print("building xs...") if 0: xs = cross([(0, 1)]*m) xs = [x for x in xs if minweight <= sum(x) <= maxweight] prune = argv.get("prune", 0.5) xs = [x for x in xs if random() < prune] xs = [] N = argv.get("N", m*100) colweight = argv.get("colweight", maxweight) assert colweight <= m for i in range(N): x = [0]*m total = 0 while total < colweight: idx = randint(0, m-1) if x[idx] == 0: x[idx] = 1 total += 1 xs.append(x) N = len(xs) lhs = [] rhs = [] # bi-orthogonality for a in range(m): for b in range(a+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == 1: v[i] = 1 if v.sum(): lhs.append(v) rhs.append(0) k = 0 # all rows must have even weight # constrain to k _number of odd-weight rows assert 0<=k<m for a in range(m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == 1: v[i] = 1 lhs.append(v) if a<k: rhs.append(1) else: rhs.append(0) logops = argv.logops A = array2(lhs) rhs = array2(rhs) #print(shortstr(A)) print("solve...") B = pseudo_inverse(A) soln = dot2(B, rhs) if not eq2(dot2(A, soln), rhs): print("no solution") return if verbose: print("soln:") print(shortstr(soln)) soln.shape = (N, 1) rhs.shape = A.shape[0], 1 K = array2(list(find_kernel(A))) print("kernel:", K.shape) if len(K)==0: return #print(K) #print( dot2(A, K.transpose())) #sols = [] #for v in span(K): best = None density = 1.0 size = 99*N trials = argv.get("trials", 1024) count = 0 print("trials...") for trial in range(trials): u = rand2(len(K), 1) v = dot2(K.transpose(), u) #print(v) v = (v+soln)%2 assert eq2(dot2(A, v), rhs) if v.sum() >= size: continue if v.sum() < m: continue if v.sum(): print(v.sum(), end=" ", flush=True) size = v.sum() if logops is not None and size != 2*m+logops: continue Gt = [] for i, x in enumerate(xs): if v[i]: Gt.append(x) Gt = array2(Gt) G = Gt.transpose() if dot2(G, Gt).sum() != 0: # not self-dual print(shortstr(dot2(G, Gt))) assert 0 return #if G.shape[1]<m: # continue if 0 in G.sum(1): print(".", end="", flush=True) continue #print(shortstr(G)) # for g in G: # print(shortstr(g), g.sum()) # print() _density = float(G.sum()) / (G.shape[0]*G.shape[1]) #if best is None or _density < density: if best is None or G.shape[1] <= size: best = G size = G.shape[1] density = _density if 0: #sols.append(G) Gx = even_rows(G) assert is_morthogonal(Gx, 3) if len(Gx)==0: continue GGx = array2(list(span(Gx))) assert is_morthogonal(GGx, 3) count += 1 print("found %d solutions" % count) if best is None: return G = best #print(shortstr(G)) f = open("selfdual.ldpc", "w") for spec in ["Hx =", "Hz ="]: print(spec, file=f) for g in G: print(shortstr(g), file=f) f.close() print() print("density:", density) print("shape:", G.shape) if 0: B = pseudo_inverse(A) v = dot2(B, rhs) print("B:") print(shortstr(B)) print("v:") print(shortstr(v)) assert eq2(dot2(B, v), rhs)
def search_extend(): # Extend the checks of a random code to make it triorthogonal. # Based on the search function above. verbose = argv.get("verbose") m = argv.get("m", 6) n = argv.get("n", m+2) k = argv.get("k") # odd _numbered rows ( logical operators) code = argv.get("code", "rand") if code == "rand": while 1: G0 = rand2(m, n) counts = G0.sum(0) if min(counts)==2 and rank(G0) == m: cols = set() for i in range(n): cols.add(tuple(G0[:, i])) if len(cols) == n: # no repeated cols break elif code == "toric": G0 = parse(""" 11.11... .111..1. 1...11.1 """) # l=2 toric code X logops + X stabs l = argv.get("l", 3) G0 = build_toric(l) m, n = G0.shape else: return code = Code(G0, check=False) print(shortstr(G0)) print("is_triorthogonal:", code.is_triorthogonal()) # these are the variables N_x xs = list(cross([(0, 1)]*m)) N = len(xs) lookup = {} for i, x in enumerate(xs): lookup[x] = i lhs = [] rhs = [] taken = set() for i in range(n): x = G0[:, i] idx = lookup[tuple(x)] assert idx not in taken taken.add(idx) if verbose: for idx in range(N): print(idx, xs[idx], "*" if idx in taken else "") for idx in taken: v = zeros2(N) v[idx] = 1 lhs.append(v) rhs.append(1) # bi-orthogonality for a in range(m): for b in range(a+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == 1: v[i] += 1 assert v.sum() lhs.append(v) rhs.append(0) # tri-orthogonality for a in range(m): for b in range(a+1, m): for c in range(b+1, m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == x[b] == x[c] == 1: v[i] += 1 assert v.sum() lhs.append(v) rhs.append(0) # dissallow columns with weight <= 1 for i, x in enumerate(xs): if sum(x)<=1: v = zeros2(N) v[i] = 1 lhs.append(v) rhs.append(0) if k is not None: # constrain to k _number of odd-weight rows assert 0<=k<m for a in range(m): v = zeros2(N) for i, x in enumerate(xs): if x[a] == 1: v[i] = 1 lhs.append(v) if a<k: rhs.append(1) else: rhs.append(0) A = array2(lhs) rhs = array2(rhs) if verbose: print("lhs:") print(shortstr(A)) print("rhs:") print(shortstr(rhs)) B = pseudo_inverse(A) soln = dot2(B, rhs) if not eq2(dot2(A, soln), rhs): print("no solution") return if verbose: print("soln:") print(shortstr(soln)) soln.shape = (N, 1) rhs.shape = A.shape[0], 1 K = array2(list(find_kernel(A))) best = None density = 1.0 size = 9999*n trials = argv.get("trials", 1024) count = 0 for trial in range(trials): u = rand2(len(K), 1) v = dot2(K.transpose(), u) #print(v) assert dot2(A, v).sum()==0 #if v.sum() != n: # continue assert v[0]==0 v = (v+soln)%2 assert eq2(dot2(A, v), rhs) Gt = list(G0.transpose()) for i, x in enumerate(xs): if v[i] and not i in taken: Gt.append(x) if not Gt: continue Gt = array2(Gt) G = Gt.transpose() if verbose: print("G0") print(shortstr(G0)) print("solution:") print(shortstr(G)) assert is_morthogonal(G, 3) if G.shape[1]<m: continue if 0 in G.sum(1): continue #print(shortstr(G)) # for g in G: # print(shortstr(g), g.sum()) # print() _density = float(G.sum()) / (G.shape[0]*G.shape[1]) #if best is None or _density < density: if best is None or G.shape[1] < size: best = G density = _density size = G.shape[1] if 0: #sols.append(G) Gx = even_rows(G) assert is_morthogonal(Gx, 3) if len(Gx)==0: continue GGx = array2(list(span(Gx))) assert is_morthogonal(GGx, 3) count += 1 print("found %d solutions" % count) G = best #print(shortstr(G)) for g in G: print(shortstr(g), g.sum()) print() print("density:", density)
def build_toric(l=3, allgen=True): keys = [] keymap = {} for i in range(l): for j in range(l): for k in (0, 1): m = len(keys) keys.append((i, j, k)) for di in (-l, 0, l): for dj in (-l, 0, l): keymap[i+di, j+dj, k] = m if l>2: assert keys[keymap[2, 1, 0]] == (2, 1, 0) if allgen: m = l**2 # rows (constraints) else: m = l**2-1 # rows (constraints) n = len(keys) # cols (bits) assert n == 2*(l**2) Lx = zeros2(2, n) Lz = zeros2(2, n) Hx = zeros2(m, n) Tz = zeros2(m, n) Hz = zeros2(m, n) Tx = zeros2(m, n) for i in range(l): Lx[0, keymap[i, l-1, 1]] = 1 Lx[1, keymap[l-1, i, 0]] = 1 Lz[0, keymap[0, i, 1]] = 1 Lz[1, keymap[i, 0, 0]] = 1 row = 0 xmap = {} for i in range(l): for j in range(l): if (i, j)==(0, 0) and not allgen: continue Hx[row, keymap[i, j, 0]] = 1 Hx[row, keymap[i, j, 1]] = 1 Hx[row, keymap[i-1, j, 0]] = 1 Hx[row, keymap[i, j-1, 1]] = 1 xmap[i, j] = row i1 = i while i1>0: Tz[row, keymap[i1-1, j, 0]] = 1 i1 -= 1 j1 = j while j1>0: Tz[row, keymap[i1, j1-1, 1]] = 1 j1 -= 1 row += 1 row = 0 zmap = {} for i in range(l): for j in range(l): if i==l-1 and j==l-1 and not allgen: continue Hz[row, keymap[i, j, 0]] = 1 Hz[row, keymap[i, j, 1]] = 1 Hz[row, keymap[i+1, j, 1]] = 1 Hz[row, keymap[i, j+1, 0]] = 1 zmap[i, j] = row i1 = i while i1<l-1: Tx[row, keymap[i1+1, j, 1]] = 1 i1 += 1 j1 = j while j1<l-1: Tx[row, keymap[i1, j1+1, 0]] = 1 j1 += 1 row += 1 return Hx
def hecke(self): bag0 = self.get_bag() bag1 = self.get_bag() points = [p for p in bag0 if p.desc == '0'] lines = [p for p in bag0 if p.desc == '1'] print(points) print(lines) flags = [] for p in points: ls = [l for l in p.nbd if l != p] print(p, ls) for l in ls: flags.append((p, l)) print("flags:", len(flags)) # for point in bag0: # print point, repr(point.desc) #items = [(point.idx, line.idx) for point in points for line in lines] #items = [(a.idx, b.idx) for a in points for b in points] items = [(a, b) for a in flags for b in flags] # fixing two points gives the Klein four group, Z_2 x Z_2: #for f in isomorph.search(bag0, bag1): # if f[0]==0 and f[1]==1: # print f perms = [] for f in isomorph.search(bag0, bag1): #print f g = dict((bag0[idx], bag0[f[idx]]) for idx in list(f.keys())) perm = {} for a, b in items: a1 = (g[a[0]], g[a[1]]) b1 = (g[b[0]], g[b[1]]) assert (a1, b1) in items perm[a, b] = a1, b1 perm = Perm(perm, items) perms.append(perm) write('.') print() g = Group(perms, items) print("group:", len(g)) orbits = g.orbits() #print orbits print("orbits:", len(orbits)) eq = numpy.allclose dot = numpy.dot n = len(flags) basis = [] gen = [] I = identity2(n) for orbit in orbits: A = zeros2(n, n) #print orbits for a, b in orbit: A[flags.index(a), flags.index(b)] = 1 print(shortstr(A)) print(A.sum()) #print basis.append(A) if A.sum() == 42: gen.append(A) assert len(gen) == 2 L = gen[0] P = gen[1] q = 2 assert eq(dot(L, L), L + q * I) assert eq(dot(P, P), P + q * I) assert eq(dot(L, dot(P, L)), dot(P, dot(L, P)))