def test_1(): assert S*S == Z i = 1.j phase = numpy.exp(i*pi/8) C1 = mulclose([X, Z, phase*I]) # Pauli group C2 = mulclose([H, S, phase*I]) # Clifford group assert len(C1) == 64, len(C1) assert len(C2) == 384, len(C2) r = numpy.exp(-pi*i/8)/sqrt(2) v = r*numpy.array([[1., i], [i, 1.]]) M = Qu((2, 2), 'ud', v) for g in C2: ginv = inv(g) assert g*ginv == I for g2 in C2: g2inv = inv(g2) assert g2*g2inv == I for g in C1: k = g2 * g * g2inv assert find(k, C1) print(M) print(find(M, C2)) for g in C1: k = M * g * inv(M) assert find(k, C1)
def build_octa(idx=0): " binary _octahedral group " x = cyclotomic(8) r2 = x - x**3 # sqrt(2) i = x**2 gen = [ [[[(-1 + i) / 2, (-1 + i) / 2], [(1 + i) / 2, (-1 - i) / 2]], [[(1 + i) / r2, 0], [0, (1 - i) / r2]]], [ # 2A [[(1. + i) / r2, 0.], [0., (1 - i) / r2]], [[1. / r2, -i / r2], [-i / r2, 1. / r2]], ], [ # 2B [[(-1. - i) / r2, 0.], [0., (-1. + i) / r2]], [[-1. / r2, i / r2], [i / r2, -1. / r2]], ], # [ # 2C # [[1., 0.], [-1., -1.]], # [[0., 1.], [1., 0.]], # ], ][idx] gen = [Qu((2, 2), 'ud', v) for v in gen] octa_gen = gen #a, b = gen #print((a**3*b).trace()) Octa = mulclose(gen) assert len(Octa) == 48, len(Octa) #print("Octa:", Octa.words.values()) return gen, Octa
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
def uniq_codes(pauli, n): I = pauli.I X = pauli.X Y = pauli.Y Z = pauli.Z In = reduce(matmul, [I] * n) count = 0 ops = {} for gen in all_codes_3(pauli, n): G = mulclose(gen) if len(G) != 8: continue if -In in G: continue count += 1 P = reduce(add, G) s = str(P) if s not in ops: ops[s] = P yield P print("codes:", count) print("uniq:", len(ops))
def build(self): if "G" in self.__dict__: return stabs = self.stabs G = mulclose(stabs) assert len(G) == 2**len(stabs) P = reduce(add, G) assert (P * P == 2**len(stabs) * P) self.G = G self.P = P
def build_tetra(idx=0): " binary _tetrahedral group " i = cyclotomic(4) r2 = sqrt(2) r3 = sqrt(3) r6 = sqrt(6) gen = [ [ # same as Natural repr ? [[(-1 + i) / 2, (-1 + i) / 2], [(1 + i) / 2, (-1 - i) / 2]], # order 3 [[-1 / 2 - 1 / 2 * i, -1 / 2 - 1 / 2 * i], [1 / 2 - 1 / 2 * i, -1 / 2 + 1 / 2 * i]] # order 3 ], [ # Natural repr [[(1 + i * r3) / 2, 0], [0, (1 - i * r3) / 2]], [[(r3 - i) / (2 * r3), (-i * 2 * r2) / (2 * r3)], [(-i * 2 * r2) / (2 * r3), (r3 + i) / (2 * r3)]], ], [ # 2A [[(-2) / 2., 0], [0, (1 + i * r3) / 2.]], [[(2 * i) / (2 * r3), (r6 + i * r2) / (2 * r3)], [(r6 + i * r2) / (2 * r3), (i - r3) / (2 * r3)]], ], [ # 2B [[(1 - i * r3) / 2., 0], [0, (-2) / 2.]], [[(-r3 - i) / (2 * r3), (-r6 + i * r2) / (2 * r3)], [(-r6 + i * r2) / (2 * r3), (-2 * i) / (2 * r3)]], ], ][idx] gen = [Qu((2, 2), 'ud', v) for v in gen] a, b = gen #print( len(mulclose([b], maxsize=32))) assert len(mulclose([a], maxsize=32)) in (3, 6) assert len(mulclose([b], maxsize=32)) in (3, 6) Tetra = mulclose(gen, maxsize=32) assert len(Tetra) == 24 return gen, Tetra
def build_pauli(*args): X = Qu((2, 2), 'ud', [[0., 1], [1., 0.]]) Z = Qu((2, 2), 'ud', [[1., 0], [0., -1.]]) gen = [X, Z] G = mulclose(gen) assert len(G) == 8 return gen, G
def build_icosa(idx=0): " binary _icosahedral group " i = cyclotomic(4) v = cyclotomic(10) z = v**2 r5 = 2 * z**3 + 2 * z**2 + 1 #sqrt(5) gen = [ [ # Same as Nat ? [[z**3, 0], [0, z**2]], [[(z**4 - z) / r5, (z**2 - z**3) / r5], [(z**2 - z**3) / r5, -(z**4 - z) / r5]] ], [ # Nat [[v, 0], [0, v**9]], [[(5 * (v - v**4) - r5 * (v + v**4)) / 10., (-2 * r5 * (v + v**4)) / 10.], [(-2 * r5 * (v + v**4)) / 10., (5 * (v - v**4) + r5 * (v + v**4)) / 10.]] ], [ [[0, i], [i, (1 - r5) / 2]], [[-i, i], [-(1 - r5) / 2., (1 - r5) / 2 + i]], ] ][idx] gen = [Qu((2, 2), 'ud', v) for v in gen] #a, b = gen #H = mulclose([b], maxsize=100) #print(len(H)) X = Qu((2, 2), 'ud', [[0., 1], [1., 0.]]) Z = Qu((2, 2), 'ud', [[1., 0], [0., -1.]]) G = mulclose(gen, maxsize=256) assert len(G) == 120 if idx in (0, 1): assert X * Z in G assert X not in G assert Z not in G return gen, G
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 test_clifford(): # Clifford group: # https://www.mathstat.dal.ca/~selinger/papers/clifford.pdf i = 1.j phase = numpy.exp(i*pi/4) phase = -1. II = I@I XI = X@I IX = I@X ZI = Z@I IZ = I@Z gen = [XI, IX, ZI, IZ, phase*II] C1 = mulclose(gen) assert len(C1) == 32, len(C1) assert (H*H) == I gen = gen + [H@I, I@H, CZ]
def get_projector(self): G = mulclose(self.ops) # build projector onto codespace P = (1./len(G))*reduce(add, G) return P
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)
def main(): t = argv.get("t", 0.02) T = build(""" XZZXI IXZZX XIXZZ ZXIXZ XXXXX """) n = 5 stabs = [ X@Z@Z@X@I, I@X@Z@Z@X, X@I@X@Z@Z, Z@X@I@X@Z] Lx = X@X@X@X@X #Lz = Z@Z@Z@Z@Z Lz = T[n-1] ops = stabs + [Lx] for i in range(n): for j in range(n): c = (T[i]*ops[j] == ops[j]*T[i]) assert c == (i!=j) a = (T[i]*ops[j] == -ops[j]*T[i]) assert a == (i==j) G = mulclose(stabs) assert len(G) == 16 N = len(G) P = (1./N) * sumops(G) assert P*P == P for op in stabs: assert Lx*op == op*Lx assert Lz*op == op*Lz trials = argv.get("trials", 100) for trial in range(trials): if 1: # noise on one qubit U = errop(t) U = U@I@I@I@I else: # noise on all qubits Us = [] for i in range(n): Us.append(errop(t)) U = reduce(matmul, Us) v = Qu.random((2,)*n, "u"*n) v = P*v v.normalize() #print(v.flatstr()) u = U*v u.normalize() for i, op in enumerate(stabs): val, u = measure(op, u) print(fstr(val), end=" ") if val < 0: #print("*") u = T[i]*u #print() #for i, op in enumerate(stabs): #val, v = measure(op, v) #print(fstr(val), end=" ") #print() assert P*u == u assert P*v == v phase = None for uu in [u, Lx*u, Lz*u, Lx*Lz*u]: r = ~uu * v if abs(1. - abs(r)) < EPSILON: #write("+") phase = r #else: #write(".") #write("\n") if phase is not None: print(phase) else: print()
def test_2(): "two qubits" i = 1.j phase = numpy.exp(i*pi/8) II = I@I XI = X@I IX = I@X ZI = Z@I IZ = I@Z gen = [XI, IX, ZI, IZ, phase*II] gen = [op.flat() for op in gen] C1 = mulclose(gen) assert len(C1) == 256, len(C1) # CZ = Z.control() # op = CZ.flat() # print(op) # print(op.valence) r = numpy.exp(-pi*i/8) v = r*numpy.array([ [1., 0., 0., 0.], [0., 1.j, 0., 0.], [0., 0., 1.j, 0.], [0., 0., 0., 1.]]) CZ = Qu((4, 4), 'ud', v) II = II.flat() assert (CZ*~CZ) == II assert not find(CZ, C1) for g in C1: k = CZ * g * ~CZ assert find(k, C1) r = numpy.exp(pi*i/8)/sqrt(2) v = r*numpy.array([[1., i], [i, 1.]]) H = Qu((2, 2), 'ud', v) plus = 1./sqrt(2) * (bitvec(0) + bitvec(1)) #print(plus) #print(H*plus) # proportional to plus state IH = (I@H).flat() HI = (H@I).flat() HH = (H@H).flat() assert IH * CZ * IH == CZ * IH * CZ # Reidemeister III move g = CZ * HH * CZ assert g*g == II assert g != SWAP.flat() A = (CZ @ I).flat() B = (I @ CZ).flat() III = (II@I).flat() assert A*B == B*A ABA = A*B*A BAB = B*A*B r = numpy.exp(pi*i/8) print((ABA/r).shortstr()) print((BAB/r).shortstr()) #assert A*B*A == B*A*B op = III for i in range(1, 100): op = ABA * op if op == III: break else: assert 0 print(i) assert ABA ** 16 == III assert BAB ** 16 == III