def make_random_modular(): ngens = 4 a, ai, b, bi = range(ngens) rels = [ (ai, a), (bi, b), (a, ) * 2, ( a, b, ) * 3, ] # modular group rels += [ (b, ) * 7, ] # 2,3,7 triangle group for _ in range(10000): graph = Schreier(ngens, rels) hgens = [] for i in range(2): gen = tuple(randint(0, ngens - 1) for k in range(20)) hgens.append(gen) if graph.build(hgens, maxsize=2000): if len(graph) < 3: continue #print("hgens:", hgens) gens = graph.get_gens() G = mulclose(gens, maxsize=10000) if len(G) < 10000: print(len(graph), end=" ", flush=True) print(len(G))
def build_gates(ring, i4, root2, i8): qubit = Space(2, ring) hom = Hom(qubit, qubit) I = Map.from_array([[1, 0], [0, 1]], hom) X = Map.from_array([[0, 1], [1, 0]], hom) Z = Map.from_array([[1, 0], [0, -1]], hom) H = (1/root2)*(X+Z) assert H*H == I S = Map.from_array([[1, 0], [0, i4]], hom) assert S*S == Z T = Map.from_array([[1, 0], [0, i8]], hom) assert S*S == Z #gen = [X, Z, S] # generates 32 elements gen = [X, Z, S, H] # generates 192 elements #gen = [X, Z, S, H, T] if argv.gap: print("G := Group(") ms = [] for g in gen: m = gapstr(g) ms.append(m) print(",\n".join(ms)+");;") if ring.p <= 41: G = mulclose(gen) print("|G| =", len(G))
def build(): if argv.steane: zops = "1111111 1001011 0101101 0010111".split() xops = "1001011 0101101 0010111".split() elif argv.toric: zops = "111..1.. 1.11...1 .1..111.".split() #xops = "1.1..... .1...1.. 11.11... .111..1. 1...11.1".split() xops = "11.11... .111..1. 1...11.1".split() else: return stab = [] for s in xops: s = s.replace("0", "I") s = s.replace(".", "I") gx = s.replace("1", "X") stab.append(Op("".join(gx))) for s in zops: s = s.replace("0", "I") s = s.replace(".", "I") gz = s.replace("1", "Z") stab.append(Op("".join(gz))) for g in stab: for h in stab: assert g*h == h*g G = mulclose(stab) print("|G| =", len(G)) return G
def __init__(self, perms=None, gen=None): if perms is None: assert gen is not None perms = list(mulclose(gen)) else: perms = list(perms) #perms.sort() assert perms canonical = list(perms) canonical.sort() self.canonical = canonical #gen = list(gen) self.gens = list(gen or perms) self.perms = perms self.n = len(self.perms) self.rank = perms[0].rank self.lookup = dict( (perm, idx) for (idx, perm) in enumerate(self.perms)) self.identity = Perm(list(range(self.rank))) self._str = str(self.canonical) self._hash = hash(self._str) self._subgroups = None # cache assert len(self.lookup) == self.n if debug: self.do_check()
def test_hom(): ring = element.Q n = argv.get("n", 3) V = Space(ring, n) # build action of symmetric group on the space V items = list(range(n)) gen1 = [] gen2 = [] for i in range(n - 1): perm = dict((item, item) for item in items) perm[items[i]] = items[i + 1] perm[items[i + 1]] = items[i] g = Perm(perm, items) gen1.append(g) A = elim.zeros(ring, n, n) for k, v in perm.items(): A[v, k] = ring.one lin = Lin(V, V, A) gen2.append(lin) perms = mulclose(gen1) G = Group(perms, items) #print(G) action = mulclose_hom(gen1, gen2) for g in G: for h in G: assert action[g * h] == action[g] * action[h] # check it's a group hom
def main(): # ---------------------------------- # binary tetrahedral group ... maybe? field = CyclotomicField(4) i = field.x print(i) M = Linear(2, field) gen = [ M.get([[(-1 + i) / 2, (-1 + i) / 2], [(1 + i) / 2, (-1 - i) / 2]]), M.get([[0, i], [-i, 0]]) ] G = mulclose(gen) assert len(G) == 48 # ??? # ---------------------------------- # binary octahedral group field = CyclotomicField(8) x = field.x a = x - x**3 #sqrt(2) i = x**2 print((1 + i) / a) # FAIL M = Linear(2, field) gen = [ M.get([[(-1 + i) / 2, (-1 + i) / 2], [(1 + i) / 2, (-1 - i) / 2]]), M.get([[(1 + i) / a, 0], [0, (1 - i) / a]]) ] print(gen[0]) print(gen[1]) return G = mulclose(gen) print(len(G))
def main(): desc = argv.next() assert desc print("constructing %s" % desc) assert "_" in desc, repr(desc) name, idx = desc.split("_") idx = int(idx) attr = getattr(Weyl, "build_%s" % name) G = attr(idx) print(G) e = G.identity gen = G.gen roots = G.roots els = G.generate() G = Group(els, roots) print("order:", len(els)) ring = element.Z value = zero = Poly({}, ring) q = Poly("q", ring) for g in els: #print(g.word) value = value + q**(len(g.word)) print(value.qstr()) n = len(gen) Hs = [] for idxs in all_subsets(n): print(idxs, end=" ") gen1 = [gen[i] for i in idxs] or [e] H = Group(mulclose(gen1), roots) Hs.append(H) gHs = G.left_cosets(H) value = zero for gH in gHs: items = list(gH) items.sort(key=lambda g: len(g.word)) #for g in items: # print(g.word, end=" ") #print() g = items[0] value = value + q**len(g.word) #print(len(gH)) print(value.qstr()) G = Group(els, roots) burnside(G, Hs)
def make_random_55(): #seed(4) ngens = 6 a, ai, b, bi, c, ci = range(ngens) i_rels = [ (ai, a), (bi, b), (ci, c), (a, ) * 2, (b, ) * 2, (c, ) * 2, (a, b) * 5, (b, c) * 5, (a, c) * 2, ] a1 = (b, a) b1 = (a, c) rel1 = (3 * a1 + b1) * 3 # Bring's curve for _ in range(10000): rels = list(i_rels) for i in range(1): #gen = tuple([a, b, c][randint(0, 2)] for k in range(30)) gen = () for k in range(50): gen += choice([(a, b), (a, c), (b, c)]) #gen = rel1 rels.append(gen) graph = Schreier(ngens, rels) if graph.build(maxsize=1040000): print(".", flush=True, end="") n = len(graph) if n <= 1320: continue #print("rels:", rels) #graph.show() print(len(graph.neighbors)) try: gens = graph.get_gens() except AssertionError: print("XXX") continue G = mulclose(gens, maxsize=10000) if len(G) < 10000: print(gen) print(len(graph), end=" ", flush=True) print(len(G)) print()
def subgroups(self, verbose=False): if self._subgroups is not None: #return list(self._subgroups) for H in self._subgroups: yield H return I = self.identity trivial = Group([I]) cyclic = self.cyclic_subgroups() #if verbose: # print "Group.subgroups: cyclic:", len(cyclic) n = len(self) # order items = set(cyclic) items.add(trivial) items.add(self) for H in items: yield H bdy = set(G for G in cyclic if len(G) < n) while bdy: _bdy = set() # consider each group in bdy for G in bdy: # enlarge by a cyclic subgroup for H in cyclic: perms = set(G.perms + H.perms) k = len(perms) if k == n or k == len(G) or k == len(H): continue #perms = mulclose(perms) perms = mulclose(perms) K = Group(perms) if K not in items: yield K _bdy.add(K) items.add(K) if verbose: print('.', flush=True, end="") #else: # print('/') bdy = _bdy #if verbose: # print "items:", len(items) # print "bdy:", len(bdy) if verbose: print() items = list(items) #items.sort(key = len) self._subgroups = items
def specht(n, space): assert n >= 2 d = len(space) ring = space.ring items = list(range(n)) gen1 = [] for i in range(n - 1): perm = dict((item, item) for item in items) perm[items[i]] = items[i + 1] perm[items[i + 1]] = items[i] perm = Perm(perm, items) gen1.append(perm) perms = mulclose(gen1) G = Group(perms, items) #I = space.ident # tensor power of the space tensor = lambda x, y: x @ y tspace = reduce(tensor, [space] * n) # build action of symmetric group on the tensor power thom = Hom(tspace, tspace) gen2 = [] for g in gen1: items = [] for idxs in tspace.gen: jdxs = tuple(idxs[g[i]] for i in range(len(idxs))) items.append(((idxs, jdxs), ring.one)) #print(idxs, "->", jdxs) #print() swap = Map(items, thom) gen2.append(swap) action = mulclose_hom(gen1, gen2) for g in G: for h in G: assert action[g * h] == action[g] * action[h] # check it's a group hom tp = Cat(G, ring) rep = Rep(action, tspace, tp) return rep
def test_render(): x = Leaf() t = ((x*x)*x)*x s = ((x*x)*(x*x)) #cvs = s.render(h=-1) #cvs.writePDFfile("tree.pdf") #return A = Assoc( (x*x)*x, x*(x*x) ) B = Assoc( x*((x*x)*x), x*(x*(x*x)) ) G = mulclose([A, B, ~A, ~B], maxsize=60) seed(2) question = Canvas().text(0, 0, "?", [Scale(7.)]+st_center) cvs = Canvas() x, y = 0, 0 for i in range(4): f = choice(G) g = choice(G) row = [f.render(), r"$\times$", g.render(), r"$=$", (f*g).render()] #if i==0: # row[-1] = question row = make_eq(row) cvs.insert(x, y, row) y += 1.1*row.get_bound_box().height bb = cvs.get_bound_box() bg = Canvas() m = 0.1 bg.fill(path.rect(bb.llx-m, bb.lly-m, bb.width+2*m, bb.height+2*m), [white]) cvs = bg.append(cvs) if 0: cvs.writePDFfile("tree-puzzle.pdf") cvs.writePNGfile("tree-puzzle.png") else: cvs.writePDFfile("tree-soln.pdf") cvs.writePNGfile("tree-soln.png")
def __init__(self, n, space): assert n >= 2 d = len(space) ring = space.ring items = list(range(n)) gen1 = [] for i in range(n - 1): perm = dict((item, item) for item in items) perm[items[i]] = items[i + 1] perm[items[i + 1]] = items[i] perm = Perm(perm, items) gen1.append(perm) perms = mulclose(gen1) G = Group(perms, items) #I = space.ident # tensor power of the space tensor = lambda x, y: x @ y tspace = reduce(tensor, [space] * n) # build action of symmetric group on the tensor power thom = Hom(tspace, tspace) gen2 = [] for g in gen1: items = [] for idxs in tspace.gen: jdxs = tuple(idxs[g[i]] for i in range(len(idxs))) items.append(((idxs, jdxs), ring.one)) #print(idxs, "->", jdxs) #print() swap = Map(items, thom) gen2.append(swap) action = mulclose_hom(gen1, gen2) for g in G: for h in G: assert action[ g * h] == action[g] * action[h] # check it's a group hom # Build the young symmetrizers projs = [] parts = [] for part in partitions(n): if len(part) > d: continue parts.append(part) t = Young(G, part) rowG = t.get_rowperms() colG = t.get_colperms() horiz = None for g in rowG: P = action[g] horiz = P if horiz is None else (horiz + P) vert = None for g in colG: P = action[g] s = g.sign() P = s * P vert = P if vert is None else (vert + P) A = vert * horiz + horiz * vert #A = horiz * vert assert vert * vert == len(colG) * vert assert horiz * horiz == len(rowG) * horiz #A = A.transpose() projs.append(A) #print(part) #print(t) #print(A) self.projs = projs self.parts = parts
def main(): #ring = element.Z ring = element.Q qubit = Space(2, ring) q2 = qubit @ qubit hom = Hom(qubit, qubit) I = Map.from_array([[1, 0], [0, 1]], hom) X = Map.from_array([[0, 1], [1, 0]], hom) Z = Map.from_array([[1, 0], [0, -1]], hom) H = X + Z E = Map.from_array([[0, 1], [0, 0]], hom) # raising F = Map.from_array([[0, 0], [1, 0]], hom) # lowering II = I @ I XI = X @ I IX = I @ X XX = X @ X assert XI * IX == XX CNOT = Map.from_array( [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], hom @ hom) SWAP = Map.from_array( [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], hom @ hom) assert SWAP * SWAP == II assert CNOT * CNOT == II G = mulclose([XI, IX, CNOT]) # order 8 G = mulclose([XI, IX, CNOT, SWAP]) # order 24.. must be S_4 G = mulclose([CNOT, SWAP]) # print(len(G)) # for g in G: # print(g) A = SWAP @ I B = I @ SWAP S_3 = list(mulclose([A, B])) assert len(S_3) == 6 # for g in G: # print(g) # print(g.hom) hom = A.hom space = hom.src N = 2**3 basis = space.get_basis() orbits = set() for v in basis: v1 = space.zero_vector() for g in S_3: u = g * v v1 = v1 + u orbits.add(v1) orbits = list(orbits) # for v in orbits: # print(v) HHH = H @ H @ H v = basis[7] #print(v) #print(HHH * v) # ---------------------------------------------------------- specht = Specht(4, qubit) for i, A in enumerate(specht.projs): print("part:", specht.parts[i]) print("proj:") im = A.image() #im = A src, tgt = im.hom for i in src: for j in tgt: v = im[j, i] if v != ring.zero: print("%s*%s" % (v, j), end=" ") print() return # ---------------------------------------------------------- items = [0, 1, 2, 3] g1 = Perm({0: 1, 1: 0, 2: 2, 3: 3}, items) g2 = Perm({0: 0, 1: 2, 2: 1, 3: 3}, items) g3 = Perm({0: 0, 1: 1, 2: 3, 3: 2}, items) gen1 = [g1, g2, g3] s1 = SWAP @ I @ I s2 = I @ SWAP @ I s3 = I @ I @ SWAP gen2 = [s1, s2, s3] G = mulclose(gen1) hom = mulclose_hom(gen1, gen2) for g in G: for h in G: assert hom[g * h] == hom[g] * hom[h] # check it's a group hom projs = [] for part in [(4, ), (3, 1), (2, 2)]: t = Young(part) rowG = t.get_rowperms() colG = t.get_colperms() horiz = None for g in rowG: P = hom[g] horiz = P if horiz is None else (horiz + P) vert = None for g in colG: P = hom[g] s = g.sign() P = s * P vert = P if vert is None else (vert + P) A = vert * horiz #A = horiz * vert assert vert * vert == len(colG) * vert assert horiz * horiz == len(rowG) * horiz #print(t) #print(A) projs.append(A) for A in projs: for B in projs: assert A * B == B * A # print() # for A in projs: # for g in G: # P = hom[g] # if P*A != A*P: # print(P*A) # print(A*P) # return for A in projs: print("proj:") im = A.image() #im = A src, tgt = im.hom for i in src: for j in tgt: v = im[j, i] if v != ring.zero: print("%s*%s" % (v, j), end=" ") print()
def main(): # ---------------------------- # Gaussian integers R = NumberRing((-1, 0)) one = R.one i = R.i assert i * i == -one assert i**3 == -i assert (1 + i)**2 == 2 * i assert (2 + i) * (2 - i) == 5 assert (3 + 2 * i) * (3 - 2 * i) == 13 items = [] i = R.i_find() while len(items) < 20: items.append(i.__next__()) items.sort() #print(' '.join(str(x) for x in items)) # reflection group i = R.i I = Mobius(R) a = Mobius(R, 1, 0, 0, 1, True) b = Mobius(R, i, 0, 0, 1, True) c = Mobius(R, -1, 0, 1, 1, True) d = Mobius(R, 0, 1, 1, 0, True) gens = [a, b, c, d] if 0: # yes, works... G = mulclose(gens, maxsize=100) for f in G: for g in G: for h in G: assert f * (g * h) == (f * g) * h return # Coxeter reflection group: a--4--b--4--c--3--d for g in gens: assert g.order() == 2 assert (a * b).order() == 4 assert (a * c).order() == 2 assert (a * d).order() == 2 assert (b * c).order() == 4 assert (b * d).order() == 2 assert (c * d).order() == 3 # rotation group a = Mobius(R, -i, 0, 0, 1) b = Mobius(R, -i, 0, i, 1) c = Mobius(R, 1, 1, -1, 0) assert a.order() == 4 assert b.order() == 4 assert c.order() == 3 # ---------------------------- # Eisenstein integers R = NumberRing((-1, -1)) one = R.one i = R.i assert i**3 == 1 assert 1 + i + i**2 == 0 # ---------------------------- # Kleinian integers R = NumberRing((-2, -1)) one = R.one i = R.i assert i * (-1 - i) == 2 assert i * (1 + i) == -2 # ---------------------------- # Golden (Fibonacci) integers R = NumberRing((1, 1)) one = R.one i = R.i assert i**2 == i + 1 assert i**3 == 2 * i + 1 assert i**4 == 3 * i + 2 # ---------------------------- R = NumberRing((-1, 0)) I = Ideal(R, 2 - R.i) S = R / I zero, one, i = S.zero, S.one, S.i assert 1 + i != 0 assert 2 - i == 0 assert 2 + i != 0 assert 1 - i == 2 + i V = Space(S, 2) SL = S.get_sl(V) GL = S.get_gl(V) def lin(a, b, c, d): a = S.promote(a) b = S.promote(b) c = S.promote(c) d = S.promote(d) return Lin(V, V, [[a, b], [c, d]]) # generators for SL gen = lin(0, 1, -1, 0), lin(1, 0, 1, 1), lin(1, 0, i, 1) G = mulclose(gen) assert len(G) == 120 i = S.i I = Mobius(S) if 0: # This just does not work over S a = Mobius(S, 1, 0, 0, 1, True) b = Mobius(S, i, 0, 0, 1, True) c = Mobius(S, -1, 0, 1, 1, True) d = Mobius(S, 0, 1, 1, 0, True) gens = [a, b, c, d] G = mulclose(gens) inv = {} for g in G: for h in G: if g * h == I: inv[g] = h inv[h] = g assert (g == h) == (hash(g) == hash(h)) for f in G: print(g) print(h) print(f) assert (g * h) * f == g * (h * f) print() assert len(G) == 240 return G, hom = cayley(G) assert len(G) == 240 G.do_check() return # rotation group gens = [a * b, b * c, c * d]
def main(): d = argv.get("d", 3) assert d>=2 double = argv.double if d==2: ring = CyclotomicRing(4) #ring = element.Z gamma = ring.x w = gamma**2 assert w == -1 double = True else: ring = CyclotomicRing(d**2) gamma = ring.x w = gamma**d I = numpy.zeros((d, d), dtype=object) wI = numpy.zeros((d, d), dtype=object) X = numpy.zeros((d, d), dtype=object) Z = numpy.zeros((d, d), dtype=object) Zdag = numpy.zeros((d, d), dtype=object) S = numpy.zeros((d, d), dtype=object) Sdag = numpy.zeros((d, d), dtype=object) T = numpy.zeros((d, d), dtype=object) Tdag = numpy.zeros((d, d), dtype=object) for j in range(d): I[j, j] = 1 wI[j, j] = w X[j, (j+1)%d] = 1 Z[j, j] = w**j Zdag[j, j] = w**(d-j) if d==2: val = gamma**(j**2) ival = gamma**(d**2 - (j**2)%(d**2)) else: val = w**(j**2) ival = w**(d - (j**2)%d) assert val*ival == 1 S[j, j] = val Sdag[j, j] = ival if d in [2, 3, 6]: val = gamma**(j**3) ival = gamma**(d**2 - (j**3)%(d**2)) else: val = w**(j**3) ival = w**(d - (j**3)%d) assert val*ival == 1 T[j, j] = val Tdag[j, j] = ival qu = Space(d, ring) hom = Hom(qu, qu) I = Map.from_array(I, hom) wI = Map.from_array(wI, hom) Xdag = Map.from_array(X.transpose(), hom) X = Xs = Map.from_array(X, hom) Z = Map.from_array(Z, hom) Zdag = Map.from_array(Zdag, hom) S = Map.from_array(S, hom) Sdag = Map.from_array(Sdag, hom) T = Map.from_array(T, hom) Tdag = Map.from_array(Tdag, hom) if d==2: Y = gamma*X*Z # ? else: Y = w*X*Z # ? assert S*Sdag == I assert Z*Zdag == I assert X*Xdag == I if d>2: for j in range(1, d+1): assert (j==d) == (X**j==I) assert (j==d) == (Z**j==I) else: assert X != I assert Z != I assert X*X == I assert Z*Z == I assert Z*X == (w**(d-1))*X*Z if double: pauli = mulclose([X, Z, gamma*I]) names = mulclose_names([X, Z, gamma*I], "X Z i".split()) else: pauli = mulclose([X, Z]) names = mulclose_names([X, Z, Xdag, Zdag, -I], "X Z Xi Zi -I".split()) pauli = set(pauli) print("pauli:", len(pauli)) assert Zdag in pauli assert Xdag in pauli if d<6: # slow.. lhs = atpow(X, d) rhs = atpow(Z, d) assert lhs * rhs == rhs * lhs lhs = X@X rhs = Z@Zdag assert lhs * rhs == rhs * lhs lhs = X@(X**(d-1)) rhs = Z@Z assert lhs * rhs == rhs * lhs if 0: n = 5 ops = [X, Xdag] lhs = [] for op in cross([ops]*n): op = reduce(matmul, op) lhs.append(op) ops = [Z, Zdag] rhs = [] for op in cross([ops]*n): op = reduce(matmul, op) rhs.append(op) for l in lhs: for r in rhs: if l*r == r*l: print("/", end=" ", flush=True) else: print(".", end=" ", flush=True) print() print("S =") print(S) print("XSX =") print(X*S*X) print("XSXS =") print(X*S*X*S) #print("Y =") #print(Y) #print("S*X*Sdag =") #print(S*X*Sdag) assert Y == S*X*Sdag def get_orbit(g, gi, v): orbit = [v] while 1: u = g*orbit[-1]*gi if u == orbit[0]: break orbit.append(u) return orbit print("S orbit:") for A in [X, Z]: print('\t', [''.join(names[op]) for op in get_orbit(S, Sdag, A)]) U = X*S Ui = Sdag * Xdag assert U*Ui == I print("XS orbit:") for A in [X, Z]: print('\t', [''.join(names[op]) for op in get_orbit(U, Ui, A)]) U = X*X*S Ui = Sdag * Xdag * Xdag assert U*Ui == I print("XXS orbit:") for A in [X, Z]: print('\t', [''.join(names[op]) for op in get_orbit(U, Ui, A)]) return inverse = {} for g in pauli: for h in pauli: if g*h == I: inverse[g] = h inverse[h] = g def is_cliff(A, Ai): assert A*Ai == I for g in pauli: h = A*g*Ai if h not in pauli: return False return True print("S =") print(S) print("S**2 =") print(S**2) print("Sdag =") print(Sdag) assert is_cliff(S, Sdag) #print("is_cliff:", (S in pauli), is_cliff(S, Sdag)) def is_third_level(A, Ai): assert A*Ai == I for g in pauli: gi = inverse[g] h = A*g*Ai*gi hi = g*A*gi*Ai if not is_cliff(h, hi): return False return True print("is_pauli(S)", S in pauli) print("is_cliff(S)", is_cliff(S, Sdag)) #print("is_third_level(S)", is_third_level(S, Tdag)) print("is_pauli(T)", T in pauli) print("is_cliff(T)", is_cliff(T, Tdag)) print("is_third_level(T)", is_third_level(T, Tdag)) print("OK")
def make_random_homogeneous_refl(): seed(1) ngens = 6 a, ai, b, bi, c, ci = range(ngens) i_rels = [ (ai, a), (bi, b), (ci, c), (a, ) * 2, (b, ) * 2, (c, ) * 2, (a, b) * 5, (b, c) * 5, (a, c) * 2, ] while 1: rels = [] for i in range(4): gen = () for k in range(20): gen += choice([(a, b), (a, c), (b, c)]) rels.append(gen) # G/H = 720/24 = 30, N(H)=24 _rels = [(0, 2, 2, 4, 0, 4, 2, 4, 2, 4, 0, 4, 0, 4, 2, 4, 0, 2, 0, 4, 2, 4, 0, 4, 2, 4, 0, 2, 0, 2, 0, 2, 2, 4, 2, 4, 2, 4, 2, 4), (0, 2, 2, 4, 0, 4, 2, 4, 0, 2, 0, 4, 0, 2, 0, 4, 0, 4, 0, 2, 0, 2, 0, 2, 0, 4, 0, 4, 2, 4, 0, 4, 0, 2, 0, 2, 2, 4, 0, 2), (0, 2, 2, 4, 2, 4, 2, 4, 2, 4, 0, 2, 0, 4, 0, 4, 0, 4, 0, 4, 0, 2, 0, 2, 0, 4, 0, 2, 0, 2, 2, 4, 0, 4, 0, 2, 0, 4, 0, 2), (0, 2, 0, 4, 0, 4, 2, 4, 0, 4, 0, 2, 0, 2, 2, 4, 0, 4, 0, 4, 0, 2, 0, 4, 0, 2, 0, 2, 2, 4, 0, 2, 2, 4, 2, 4, 0, 4, 0, 2)] # G/H = 9720/324 = 30, N(H)=1944 _rels = [(0, 4, 0, 2, 0, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 0, 4, 0, 2, 0, 2, 0, 4, 2, 4, 0, 2, 0, 2, 0, 2, 2, 4, 0, 2, 0, 4, 0, 4), (0, 4, 2, 4, 0, 2, 0, 2, 0, 2, 2, 4, 0, 2, 0, 2, 2, 4, 2, 4, 0, 4, 2, 4, 0, 4, 2, 4, 0, 4, 0, 2, 2, 4, 0, 2, 2, 4, 0, 2), (0, 4, 0, 4, 0, 4, 0, 2, 0, 4, 0, 4, 2, 4, 0, 4, 0, 2, 0, 2, 0, 4, 0, 2, 0, 2, 0, 2, 0, 4, 0, 4, 0, 4, 2, 4, 0, 2, 2, 4), (2, 4, 2, 4, 0, 4, 2, 4, 0, 2, 0, 4, 0, 4, 2, 4, 2, 4, 2, 4, 2, 4, 2, 4, 0, 4, 0, 4, 2, 4, 2, 4, 2, 4, 0, 4, 0, 2, 2, 4)] graph = Schreier(ngens, i_rels) if not graph.build(rels, maxsize=10400): print(choice("/\\"), end="", flush=True) continue n = len(graph) if n <= 24: continue print("\n[%d]" % n) #, flush=True, end="") print(len(graph.neighbors) ) # how big did the graph get? compare with maxsize above try: gens = graph.get_gens() except AssertionError: print("** FAIL **") continue N = 10000 perms = mulclose(gens, maxsize=N) if len(perms) >= N: print("|G| = ?") continue print(rels) items = list(range(n)) G = Group(perms, items) G.gens = gens print("|G| =", len(G)) print() break rels = [reduce(mul, [gens[i] for i in rel]) for rel in rels] H = Coset(mulclose(rels), items) print(len(H)) print(len(G) / len(H)) N = [] for g in G: lhs = g * H rhs = H * g if lhs == rhs: N.append(g) print(len(N))
def clifford(): p = argv.get("p", 17) field = FiniteField(p) #ring = PolynomialRing(field) #x = ring.x for fgen in range(1, p): items = set() j = fgen while j not in items: items.add(j) j = (j*fgen)%p if len(items) == p-1: break else: assert 0 finv = {} for i in range(1, p): for j in range(1, p): if (i*j)%p == 1: finv[i] = j finv[j] = i assert len(finv) == p-1 #print("fgen:", fgen) items = [field.promote(i) for i in range(p)] has_imag = [i for i in items if i*i == -1] #print(p, has_imag) if not has_imag: assert 0 i4 = has_imag[0] assert -i4 == has_imag[1] has_root2 = [i for i in items if i*i == 2] if not has_root2: assert 0 r2 = has_root2[0] assert -r2 == has_root2[1] has_i8 = [i for i in items if i*i == i4] if not has_i8: assert 0 i8 = has_i8[0] assert -i8 == has_i8[1] print("p =", p) #print(i4, r2, i8) #print(has_imag, has_root2, has_i8) for i in items: if i*i8 == 1: i8_dag = i #print(i8_dag) # try to take a daggar... doesn't really work tho. assert p==17 dag = { 0:0, 1:1, 2:9, 3:3, 4:13, 5:12, 6:6, 7:7, 8:15, 9:2, 10:10, 11:11, 12:5, 13:4, 14:14, 15:8, 16:16, } for (k, v) in list(dag.items()): dag[k] = field.promote(v) dag[field.promote(k)] = field.promote(v) assert dag[i4] == -i4 qubit = Space(2, field) hom = Hom(qubit, qubit) def getdag(A): items = [((j, i), dag[v]) for ((i, j), v) in A.items] return Map(items, hom) I = Map.from_array([[1, 0], [0, 1]], hom) X = Map.from_array([[0, 1], [1, 0]], hom) Z = Map.from_array([[1, 0], [0, -1]], hom) H = (1/r2)*(X+Z) assert H*H == I S = Map.from_array([[1, 0], [0, i4]], hom) Sdag = Map.from_array([[1, 0], [0, dag[i4]]], hom) assert S*S == Z assert S*Sdag == I assert getdag(S) == Sdag T = Map.from_array([[1, 0], [0, i8]], hom) assert S*S == Z C1 = mulclose([X, Z]) assert len(C1) == 8 # C1 is Pauli group + phases #P = fgen*I # phase P = i4*I C1 = mulclose([X, Z, P]) # add phases # assert len(C1) == 64, len(C1) assert len(C1) == 32, len(C1) C1_lookup = set(C1) #gen = [X, Z, S, H] #C2 = mulclose(gen) #assert len(C2) == 192 G = [] for a in range(p): for b in range(p): for c in range(p): for d in range(p): if (a*d - b*c)%p: G.append(Map.from_array([[a, b], [c, d]], hom)) G_lookup = set(G) print("|GL(%d, 2)|=%d" % (p, len(G))) U = [] for g in G: if g*getdag(g) == I: U.append(g) print("|U|=", len(U)) gen = [X, Z, S, H, P] # Clifford group + phases C2 = mulclose(gen) # assert len(C2) == 384, len(C2) assert len(C2) == 192, len(C2) C2_lookup = set(C2) print("|C2| =", len(C2)) print(C2_lookup == set(U)) for g in C2: assert g in G_lookup #assert g*getdag(g) == I, str(g) # FAIL # inv = {I:I} # for a in G: # if a in inv: # continue # for b in G: # ab = a*b # ci = inv.get(ab) # if ci is None: # continue # inv[a] = b*ci # inv[b] = ci*a # print(len(inv), end=" ", flush=True) # print() inv = {I:I} remain = set(G) remain.remove(I) while remain: a = iter(remain).__next__() assert a not in inv for b in G: ab = a*b ci = inv.get(ab) if ci is None: continue if a not in inv: inv[a] = b*ci remain.remove(a) if b not in inv: inv[b] = ci*a remain.remove(b) print(len(inv), end=" ", flush=True) print() assert len(inv) == len(G) if 0: for g2 in C2: for g in C1: assert g2 * g * inv[g2] in C1 C2 = [] for g2 in G: for g in C1: if g2*g*inv[g2] not in C1_lookup: break else: C2.append(g2) assert len(C2) == 384 # same as above C2_lookup = set(C2) C3 = [] for g3 in G: for g in C1: if g3*g*inv[g3] not in C2_lookup: break else: C3.append(g3) print("|C3| =", len(C3)) C3_lookup = set(C3) shuffle(C3) # count = 0 # for a in C3: # for b in C3: # if a*b in C3_lookup: # count += 1 # print(count) def src(a): return set([b for b in C3 if a*b in C3_lookup]) def tgt(a): return set([b for b in C3 if b*a in C3_lookup]) if 0: items = iter(C3) a = items.__next__() src_a = src(a) print("|src_a| =", len(src_a)) srcs = [] for b in C3: src_b = src(b) if src_b not in srcs: print("|src_b| = ", len(src_b)) srcs.append(src_b) if len(srcs)==4: # there is only 4 of these to be found break obs = list(srcs) tgts = [] for b in C3: tgt_b = tgt(b) if tgt_b not in obs: obs.append(tgt_b) if tgt_b not in tgts: print("|tgt_b| = ", len(tgt_b)) tgts.append(tgt_b) if len(tgts)==4: # there is only 4 of these to be found break done = False while not done: done = True #print("obs:", len(obs)) obs.sort(key = len, reverse=True) obs1 = list(obs) for s in obs: for t in obs: st = s.intersection(t) a = ' ' if st not in obs1: a = '*' obs1.append(st) done = False #print("%4d"%(len(st)), end=a) #print() obs = obs1 obs.sort(key = len, reverse=True) print("obs:", len(obs), [len(ob) for ob in obs]) for ob in obs: #print(len(ob), end=" ") iob = [inv[a] for a in ob if inv[a] in ob] print((len(ob), len(iob)), end=" ") print()
def test_gaussian(): # ---------------------------- from bruhat.action import mulclose R = NumberRing((-1, 0)) z = 2 + 3 * R.i # |G| = 2184 z = 3 * R.one # |G| = 720 z = 2 + 1 * R.i # |G| = 120 #z = -1+R.i # fail I = Ideal(R, z) S = R / I zero, one, i = S.zero, S.one, S.i a = Mobius(S, -i, 0, 0, 1) b = Mobius(S, -i, 0, i, 1) c = Mobius(S, 1, 1, -1, 0) gens = [a, b, c] assert a.order() == 4 assert b.order() == 4 assert c.order() == 3 #print((a*b).order()) # == 2 #print((b*a).order()) # == 2 G = mulclose(gens) #assert len(G) == 120, len(G) print(len(G)) #a, b, c = G[:3] #assert a.order() == 4 #assert b.order() == 4 #assert c.order() == 3 G, hom = cayley(G) a, b, c = hom[a], hom[b], hom[c] assert a.order() == 4 assert b.order() == 4 assert c.order() == 3 def make_cayley(a, b): H = Group.generate([a, b]) print(len(H), len(G) // len(H)) import string names = dict(zip(H, string.ascii_lowercase[:len(H)])) f = open("cayley_graph.dot", "w") print("digraph\n{\n", file=f) for g in H: print(" %s -> %s [color=red];" % (names[g], names[a * g]), file=f) print(" %s -> %s [color=green];" % (names[g], names[b * g]), file=f) print("}", file=f) f.close() if argv.cayley_graph: #make_cayley(a, b) make_cayley(c, b) if 0: H = Group.generate([b, c]) gset = G.action_subgroup(H) print(gset.get_orbits()) #H = Group.generate([c]) #o_edges = G.left_cosets(H) #print(len(o_edges)) if argv.burnside: burnside(G) for H in G.subgroups(): if len(H) == 60: assert H.is_simple() break
def test_hw(): # Heisenberg-Weyl group # copied from dev/qudit.py d = argv.get("d", 3) # qudit dimension assert d >= 2 assert is_prime(d) if d == 2: ring = CyclotomicRing(4) #ring = element.Z gamma = ring.x w = gamma**2 assert w == -1 argv.double = True elif 1: ring = CyclotomicRing(d**2) gamma = ring.x w = gamma**d else: ring = CyclotomicRing(d) w = ring.x I = Matrix(ring, d) wI = Matrix(ring, d) X = Matrix(ring, d) Z = Matrix(ring, d) Zdag = Matrix(ring, d) S = Matrix(ring, d) Sdag = Matrix(ring, d) T = Matrix(ring, d) Tdag = Matrix(ring, d) for j in range(d): I[j, j] = 1 wI[j, j] = w X[j, (j + 1) % d] = 1 Z[j, j] = w**j Zdag[j, j] = w**(d - j) if d == 2: val = gamma**(j**2) ival = gamma**(d**2 - (j**2) % (d**2)) else: val = w**(j**2) ival = w**(d - (j**2) % d) assert val * ival == 1 S[j, j] = val Sdag[j, j] = ival if d in [2, 3, 6]: val = gamma**(j**3) ival = gamma**(d**2 - (j**3) % (d**2)) else: val = w**(j**3) ival = w**(d - (j**3) % d) assert val * ival == 1 T[j, j] = val Tdag[j, j] = ival Y = w * X * Z # ? Xdag = X.transpose() assert S * Sdag == I assert Z * Zdag == I assert X * Xdag == I if d > 2: for j in range(1, d + 1): assert (j == d) == (X**j == I) assert (j == d) == (Z**j == I) else: assert X != I assert Z != I assert X * X == I assert Z * Z == I assert Z * X == (w**(d - 1)) * X * Z if argv.double: pauli = mulclose([X, Z, gamma * I]) else: pauli = mulclose([X, Z]) print("pauli:", len(pauli)) if d == 2: phases = mulclose([gamma * I]) else: phases = mulclose([w * I]) print("phases:", len(phases)) assert Zdag in pauli assert Xdag in pauli if d <= 3: # slow.. lhs = atpow(X, d) rhs = atpow(Z, d) assert lhs * rhs == rhs * lhs equ = {e: {g * e for g in phases} for e in pauli} G = [] for i in range(d): for j in range(d): m = (X**i) * (Z**j) G.append(m) print(len(G)) for g in G: for h in G: i = int(g * h == h * g) print(i or '.', end=" ") print()
def test(n): G = Weyl.build_A(n) # print "%d roots" % len(G.roots) # print G.roots # for g in G.gen: # print [g(root) for root in G.roots] gen = G.gen for i in range(n): for j in range(n): gi = gen[i] gj = gen[j] if i == j: assert gi * gj == G.identity elif abs(i - j) == 1: assert gi * gj != G.identity assert (gi * gj)**2 != G.identity assert (gi * gj)**3 == G.identity else: assert gi * gj != G.identity assert (gi * gj)**2 == G.identity if n < 5: assert len(mulclose(G.gen)) == factorial(n + 1) # --------------------------------------------------------- G = Weyl.build_B(n) gen = G.gen for g in gen: assert g * g == G.identity for i in range(n - 1): for j in range(i + 1, n - 1): gi = gen[i] gj = gen[j] if abs(i - j) == 1: assert gi * gj != G.identity assert (gi * gj)**2 != G.identity assert (gi * gj)**3 == G.identity else: assert gi * gj != G.identity assert (gi * gj)**2 == G.identity if i < n - 1: gj = gen[n - 1] assert gi * gj != G.identity assert (gi * gj)**2 == G.identity if n > 2: gi = gen[n - 2] gj = gen[n - 1] assert (gi * gj) != G.identity assert (gi * gj)**2 != G.identity assert (gi * gj)**3 != G.identity assert (gi * gj)**4 == G.identity if n < 5: assert len(mulclose(G.gen)) == (2**n) * factorial(n) # --------------------------------------------------------- G = Weyl.build_C(n) # --------------------------------------------------------- if n < 3: return # <---------------------- return G = Weyl.build_D(n) gen = G.gen for i in range(n - 1): gi = gen[i] for j in range(i + 1, n - 1): gj = gen[j] if abs(i - j) == 1: assert gi * gj != G.identity assert (gi * gj)**2 != G.identity assert (gi * gj)**3 == G.identity else: assert gi * gj != G.identity assert (gi * gj)**2 == G.identity gj = gen[n - 1] if i < n - 3 or i == n - 2: assert gi * gj != G.identity assert (gi * gj)**2 == G.identity elif i == n - 3: assert gi * gj != G.identity assert (gi * gj)**2 != G.identity assert (gi * gj)**3 == G.identity if n < 5: assert len(mulclose(G.gen)) == (2**(n - 1)) * factorial(n)
def test_young0(): ring = element.Q n = argv.get("n", 3) part = argv.get("part", (1, 1, 1)) assert sum(part) == n V = Space(ring, n) # build action of symmetric group on the space V items = list(range(n)) gen1 = [] gen2 = [] for i in range(n - 1): perm = dict((item, item) for item in items) perm[items[i]] = items[i + 1] perm[items[i + 1]] = items[i] g = Perm(perm, items) gen1.append(g) A = elim.zeros(ring, n, n) for k, v in perm.items(): A[v, k] = ring.one lin = Lin(V, V, A) gen2.append(lin) perms = mulclose(gen1) G = Group(perms, items) #print(G) action = mulclose_hom(gen1, gen2) for g in G: for h in G: assert action[g * h] == action[g] * action[h] # check it's a group hom young = Young(G, part) rowG = young.get_rowperms() print("rowG", len(rowG)) colG = young.get_colperms() print("colG", len(colG)) horiz = None for g in rowG: P = action[g] horiz = P if horiz is None else (horiz + P) vert = None for g in colG: P = action[g] s = g.sign() P = ring.promote(s) * P vert = P if vert is None else (vert + P) A = horiz * vert assert vert * vert == len(colG) * vert assert horiz * horiz == len(rowG) * horiz print("part:", part) print(young) print("rank:", A.rank()) print("is_zero:", A.is_zero()) print(A) #if not A.is_zero(): # print(A) print()
def test_young(): # code ripped from qu.py d = argv.get("d", 2) n = argv.get("n", 3) p = argv.get("p") if p is None: ring = element.Q else: ring = element.FiniteField(p) print("ring:", ring) space = Space(ring, d) # tensor power of the space tspace = reduce(matmul, [space] * n) # build action of symmetric group on the tensor power items = list(range(n)) gen1 = [] gen2 = [] for i in range(n - 1): perm = dict((item, item) for item in items) perm[items[i]] = items[i + 1] perm[items[i + 1]] = items[i] g = Perm(perm, items) gen1.append(g) lin = tspace.get_swap([g[i] for i in items]) #print(lin.hom) gen2.append(lin) perms = mulclose(gen1) G = Group(perms, items) #print(G) action = mulclose_hom(gen1, gen2) for g in G: for h in G: assert action[g * h] == action[g] * action[h] # check it's a group hom # Build the young symmetrizers projs = [] part = argv.get("part") parts = list(partitions(n)) if part is None else [part] for part in parts: assert sum(part) == n t = Young(G, part) rowG = t.get_rowperms() colG = t.get_colperms() horiz = None for g in rowG: P = action[g] horiz = P if horiz is None else (horiz + P) vert = None for g in colG: P = action[g] s = g.sign() P = ring.promote(s) * P vert = P if vert is None else (vert + P) A = horiz * vert assert vert * vert == len(colG) * vert assert horiz * horiz == len(rowG) * horiz #A = A.transpose() projs.append(A) print("part:", part) print(t) print("rank:", A.rank()) print("is_zero:", A.is_zero()) #if not A.is_zero(): # print(A) print()
def make_random_homogeneous(): # use rotation group #seed(1) ngens = 6 a, ai, b, bi, c, ci = range(ngens) i_rels = [ (ai, a), (bi, b), (ci, c), (a, ) * 5, (b, ) * 2, (c, ) * 4, (a, b, c), ] while 1: rels = [] for i in range(argv.get("nwords", 2)): gen = tuple( choice([a, b, c]) for k in range(argv.get("wordlen", 100))) rels.append(gen) gen = (ci, ) + gen + (c, ) rels.append(gen) gen = (ci, ) + gen + (c, ) rels.append(gen) rels = [reduce_word(i_rels, rel) for rel in rels] graph = Schreier(ngens, i_rels) if not graph.build(rels, maxsize=10400): print(choice("/\\"), end="", flush=True) continue n = len(graph) if n <= argv.get("minsize", 12): print('.', end="", flush=True) continue print("[%d]" % n, flush=True, end="") # how big did the graph get? compare with maxsize above print("(%d) " % len(graph.neighbors), flush=True, end="") try: gens = graph.get_gens() except AssertionError: print("** FAIL **") continue items = list(range(n)) print() break N = argv.get("N", 10000) perms = mulclose(gens, maxsize=N) if len(perms) >= N: #print("|G| = ?") continue print() print(rels) G = Group(perms, items) G.gens = gens print("|G| =", len(G)) rels = [reduce(mul, [gens[i] for i in rel]) for rel in rels] H = Coset(mulclose(rels), items) print("|H| =", len(H)) assert len(G) % len(H) == 0 print("[H:G] = ", len(G) // len(H)) N = [] for g in G: lhs = g * H rhs = H * g if lhs == rhs: N.append(g) assert len(N) % len(H) == 0 print("[H:N(H)] =", len(N) // len(H)) print(rels) a, ai, b, bi, c, ci = gens assert (a**5).is_identity() assert (b**2).is_identity() assert (c**4).is_identity() assert (a * b * c).is_identity() print(a.fixed()) print(b.fixed()) print(c.fixed()) print(a.orbits()) print(b.orbits()) print(c.orbits())
def make_homogeneous(): # use rotation group ngens = 6 a, ai, b, bi, c, ci = range(ngens) i_rels = [ (ai, a), (bi, b), (ci, c), (a, ) * 5, (b, ) * 2, (c, ) * 4, (a, b, c), ] _rels = [(2, 4, 0, 4, 0, 0, 4, 0, 4, 4, 4, 2, 2, 2, 2, 2, 0, 4, 2, 0, 4, 4, 2, 4, 0, 4, 0, 4, 4, 0, 2, 0, 4, 2, 4, 0, 2, 0, 4, 4), (0, 0, 0, 2, 2, 4, 2, 0, 4, 2, 0, 4, 0, 4, 4, 0, 0, 0, 4, 4, 2, 4, 4, 4, 4, 4, 0, 2, 2, 2, 0, 4, 4, 0, 4, 0, 2, 4, 0, 4), (2, 0, 4, 4, 0, 2, 4, 4, 2, 0, 0, 2, 0, 2, 2, 2, 2, 2, 0, 4, 2, 2, 0, 0, 2, 4, 0, 4, 4, 2, 2, 4, 2, 4, 0, 0, 2, 0, 0, 0)] # no fixed points, F,E,V = 12,30,16 rels = [ (2, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 0, 4, 2, 0, 4, 2, 0, 0, 4, 4, 0, 4, 2, 0, 4, 4, 2, 0, 2, 0, 4, 4, 4), (5, 2, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 0, 4, 2, 0, 4, 2, 0, 0, 4, 4, 0, 4, 2, 0, 4, 4, 2, 0, 2, 0), (5, 5, 2, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 0, 4, 2, 0, 4, 2, 0, 0, 4, 4, 0, 4, 2, 0, 4, 4, 2, 0, 2, 0, 4), (0, 0, 4, 0, 0, 4, 0, 4, 4, 4, 0, 0, 4, 0, 4, 2, 0, 0, 0, 0, 4, 0, 4, 0, 4, 4, 0, 4, 4, 2, 4, 4, 4, 2, 0, 4, 2, 4, 2, 4, 4, 0, 4, 4, 4), (5, 0, 0, 4, 0, 0, 4, 0, 4, 4, 4, 0, 0, 4, 0, 4, 2, 0, 0, 0, 0, 4, 0, 4, 0, 4, 4, 0, 4, 4, 2, 4, 4, 4, 2, 0, 4, 2, 4, 2, 4, 4, 0), (5, 5, 0, 0, 4, 0, 0, 4, 0, 4, 4, 4, 0, 0, 4, 0, 4, 2, 0, 0, 0, 0, 4, 0, 4, 0, 4, 4, 0, 4, 4, 2, 4, 4, 4, 2, 0, 4, 2, 4, 2, 4, 4, 0, 4) ] rels = [reduce_word(i_rels, word) for word in rels] print(rels) graph = Schreier(ngens, i_rels) if not graph.build(rels, maxsize=10400): assert 0 words = graph.get_words() for w in words: assert reduce_word(conj_rels(i_rels + rels), w) == w # print(w) print("words:", len(words)) gens = graph.get_gens() N = argv.get("N", 10000) perms = mulclose(gens, maxsize=N) if len(perms) >= N: print("|G| = ?") else: print("|G| = ", len(perms)) a, ai, b, bi, c, ci = gens assert (a**5).is_identity() assert (b**2).is_identity() assert (c**4).is_identity() assert (a * b * c).is_identity() print(a.fixed()) print(b.fixed()) print(c.fixed()) print("faces:", len(a.orbits())) print("edges:", len(b.orbits())) print("vertices:", len(c.orbits())) from bruhat.disc import render_group rels = conj_rels(rels) render_group(5, 2, 4, words, rels) return # edges = set() # for tile in items: # for g in [a, ai, c, ci]: # edge = (tile, g(tile)) # edges.append(edge) def intersect(lhs, rhs): return bool(set(lhs).intersection(rhs)) def eq(lhs, rhs): for i in lhs: if i not in rhs: return False for i in rhs: if i not in lhs: return False assert len(lhs) == len(rhs) return True def search(tiles, tiless): for rhs in tiless: if eq(tiles, rhs): return True faces = [tuple(face) for face in a.orbits()] print("faces:", faces) assert intersect(faces[0], faces[0]) assert not intersect(faces[0], faces[1]) flookup = {} for face in faces: for i in face: flookup[i] = face for face in faces: print(faces.index(face), ":", end=" ") for i in face: print(faces.index(flookup[c(i)]), end=" ") print()
def main(): n = argv.n if n: test(n) elif argv.test: for n in range(2, 6): test(n) test_longest_element() if argv.test_longest_element: test_longest_element() G = None if argv.E_8: G = Weyl.build_E8() assert G.matrix() == { (0, 1): 3, (1, 2): 3, (2, 3): 3, (3, 4): 3, (4, 5): 3, (4, 6): 3, (6, 7): 3 } if argv.E_7: G = Weyl.build_E7() assert G.matrix() == { (0, 6): 3, (1, 2): 3, (2, 3): 3, (3, 4): 3, (3, 5): 3, (5, 6): 3 } if argv.E_6: G = Weyl.build_E6() assert G.matrix() == { (0, 1): 3, (1, 2): 3, (2, 3): 3, (2, 4): 3, (4, 5): 3 } #items = mulclose(G.gen, verbose=True) #print("|E6|=", len(items)) if argv.F_4: G = Weyl.build_F4() assert G.matrix() == {(0, 1): 3, (1, 2): 4, (2, 3): 3} #items = mulclose(G.gen, verbose=True) #print("|F4|=", len(items)) # == 1152 if argv.G_2: G = Weyl.build_G2() assert G.matrix() == {(0, 1): 6} assert len(mulclose(G.gen)) == 12 # dihedral group D_6 for arg in argv: if len(arg) < 3 or arg[1] != "_": continue try: n = int(arg[2:]) except: continue print("constructing %s" % arg) if arg.startswith("A"): G = Weyl.build_A(n) if arg.startswith("B"): G = Weyl.build_B(n) if arg.startswith("C"): G = Weyl.build_C(n) if arg.startswith("D"): G = Weyl.build_D(n) if G is None: return print("roots:", len(G.roots)) for root in G.roots: print("\t", root) print(len(G.build_group())) if argv.show_qpoly: show_qpoly(G) if argv.show: for g in G.gen: print(g) if argv.longest_element: g = G.longest_element() print(g) if argv.monoid: test_monoid(G) if argv.representation: representation(G) if argv.find_negi: find_negi(G) if argv.orders: G = G.build_group() orders = [g.order() for g in G] orders.sort() print(orders) if argv.orbiplex: G = G.build_group() action.orbiplex(G)
def test_tree(): x = Leaf() lhs = x*(x*x) rhs = (x*x)*x #print(lhs, rhs) #for key in lhs.keys(): # print(key, lhs[key]) #print(lhs.sup(rhs)) lhs, rhs = x*((x*x)*x), (x*x)*x #print(lhs.sup(rhs)) lhs, rhs = x*((x*x)*x), (x*x)*x ks = lhs.keys() assert ks == [(0,), (1, 0, 0), (1, 0, 1), (1, 0), (1, 1), (1,), ()] assert lhs.find_carets() == {3: (1,0)} s = ((x*x)*x)*x t = (x*x)*(x*x) assert t.find_carets() == {2: (0,), 4: (1,)} assert s.find_carets() == {2: (0, 0)} t, s = cancel_carets(t, s) assert t == x*(x*x), t assert s == (x*x)*x, s assert s.reassoc((0,)) == t assert t.reassoc((1,)) == s tree = s*s assert list(tree.internal_nodes()) == [(0, 0), (0,), (1, 0), (1,)] catalan = [1, 1, 2, 5, 14, 42, 132] for i in range(7): n = i+1 trees = list(all_trees(n)) assert len(trees) == catalan[i] for tree in trees: assert tree.nleaves() == n keys = list(tree.internal_nodes()) assert len(keys) == max(0, n-2), (n, len(keys)) for k in keys: other = tree.reassoc(k) assert other != tree assert other in trees I = Assoc( x, x ) assert I == I assert I*I == I F = Assoc( (x*x)*x, (x*x)*x ) assert F == I A = Assoc( (x*x)*x, x*(x*x) ) B = Assoc( x*((x*x)*x), x*(x*(x*x)) ) #print(A, B) assert A*A == Assoc( (((x*x)*x)*x), (x*(x*(x*x))) ) assert I*A == A assert A*I == A assert A*~A == I assert ~A*A == I lhs = bracket( A*~B, ~A*B*A ) rhs = bracket( A*~B, (~A)*(~A)*B*A*A ) assert lhs == rhs G = mulclose([A, B, ~A, ~B], maxsize=100) assert len(G) >= 100 #for g in G: # print(g.diamond_str()) for n in range(1, 6): trees = list(all_trees(n)) found = [] for src in trees: for k in src.internal_nodes(): tgt = src.reassoc(k) f = Assoc(tgt, src) found.append(f) uniq = set(found) #print(len(trees), len(found), len(set(found))) assert len(uniq) == max(0, 2**(n-1) - 2) # woah ! uniq = list(uniq) uniq.sort(key = str) for f in uniq: assert ~f in uniq
def make_dicyclic(n, debug=False): # Binary dihedral group # https://people.maths.bris.ac.uk/~matyd/GroupNames/dicyclic.html p = cyclotomic(PolynomialRing(Z), 4 * n) ring = PolynomialRing(Z) / p rzeta = ring.x zeta = rzeta**2 izeta = zeta**(2 * n - 1) # inverse for k in range(1, 6 * n): if zeta**k == 1: break assert k == 2 * n if n == 3: assert zeta - 1 == zeta**2 i = rzeta**n assert i != 1 assert i**2 == -1 assert i**3 == -i assert i**4 == 1 assert zeta**(2 * n) == 1 assert izeta != 1 assert zeta * izeta == 1 def is_real(v): # this is a total hack assert ring.promote(v) is v x = exp(2.j * pi / (4 * n)) s = str(v) v = eval(s, locals()) return abs(v.imag) < EPSILON for k in range(1, 6 * n): assert is_real(rzeta**k) == (k % (2 * n) == 0) assert is_real(zeta + izeta) # we use the natural 2-dim representation GL = Linear(2, ring) e = GL.get([[1, 0], [0, 1]]) r = GL.get([[zeta, 0], [0, izeta]]) s = GL.get([[0, -1], [1, 0]]) Di = mulclose([r, s]) Di = list(Di) assert len(Di) == 4 * n eidx = Di.index(e) ridx = Di.index(r) sidx = Di.index(s) G = cayley(Di) e = G[eidx] r = G[ridx] s = G[sidx] assert r**(2 * n) == e assert s**2 == r**n assert r * s * r == s # complex characters ---------------------------------------------------- # build the transpose of the character table. cols = [] elems = [] # group elements with order the cols cgy = [] # element of each cgy class kidxs = range(2, n) desc = [] # class: e, size 1 elems.append(e) cgy.append(e) desc.append("e") cols.append([1, 1, 1, 1, 2] + [2 for k in kidxs]) # class: s^2, size 1 cols.append([1, 1, (-1)**n, (-1)**n, -2] + [((-1)**k) * 2 for k in kidxs]) elems.append(s * s) cgy.append(s * s) desc.append("s^2") for idx in range(1, n): # class: r**idx, size 2 col = [1, 1, (-1)**idx, (-1)**idx, zeta**idx + izeta**idx ] + [zeta**(idx * k) + izeta**(idx * k) for k in kidxs] cols.append(col) cols.append(col) elems.append(r**idx) cgy.append(r**idx) desc.append("r^%d" % idx) elems.append(r**(2 * n - idx)) for idx in range(n): # class: s, size n cols.append([1, -1, i**n, -i**n, 0] + [0 for k in kidxs]) elems.append(s * (r**(2 * idx))) cgy.append(s) desc.append("s") for idx in range(n): # class: s*r, size n cols.append([1, -1, -i**n, i**n, 0] + [0 for k in kidxs]) elems.append(s * (r**(2 * idx + 1))) cgy.append(s * r) desc.append("sr") #print(i, -i, i**n, -i**n) assert len(set(elems)) == len(elems) == len(G) assert set(elems) == set(G) for col in cols: assert len(col) == n + 3, len(col) if debug: print() for s in desc: s = "%10s" % s print(s, end=" ") print() c_chars = [] for k in range(n + 3): chi = dict((elems[i], cols[i][k]) for i in range(4 * n)) f = CFunc(G, chi) for g in cgy: s = "%10s" % (f[g]) print(s, end=" ") print() c_chars.append(f) print() for f in c_chars: for g in c_chars: val = f.dot(g, normalize=False) #assert (f == g) == (val == 1) print(val, end=" ") print() else: c_chars = [] for k in range(n + 3): chi = dict((elems[i], cols[i][k]) for i in range(4 * n)) f = CFunc(G, chi) c_chars.append(f) for f in c_chars: for g in c_chars: val = f.dot(g) assert (f == g) == (val == 1) G.c_chars = c_chars # complex reps ---------------------------------------------------- c_reps = [] e = G[eidx] r = G[ridx] s = G[sidx] tp = Cat(G, ring) def mk_rep(gen, reps): assert reps f = reps[0] V = f.hom.src send_perms = mulclose_hom(gen, reps) rep = Rep(send_perms, V, tp) return rep # 1-dim irreps V = Space(1, ring) hom = Hom(V, V) f_1 = Map.from_array([[1]], hom) f_n1 = Map.from_array([[-1]], hom) c_reps.append(mk_rep([r, s], [f_1, f_1])) # Triv c_reps.append(mk_rep([r, s], [f_1, f_n1])) # 1A f_r = Map.from_array([[-1]], hom) f_s = Map.from_array([[i**n]], hom) c_reps.append(mk_rep([r, s], [f_r, f_s])) # 1B f_s = Map.from_array([[-i**n]], hom) c_reps.append(mk_rep([r, s], [f_r, f_s])) # 1C # 2-dim irreps V = Space(2, ring) hom = Hom(V, V) for k in range(1, n): rho_r = Map.from_array([[zeta**k, 0], [0, izeta**k]], hom) rho_s = Map.from_array([[0, 1], [(-1)**k, 0]], hom) c_reps.append(mk_rep([r, s], [rho_r, rho_s])) # rho_k for idx, rep in enumerate(c_reps): rep.check() char = c_chars[idx] tr = rep.trace() tr = CFunc(G, tr) # print(tr, end=" ") # val = tr.frobenius_schur() # if val == -1: # print("quaternionic") # elif val == 0: # print("complex") # elif val == 1: # print("real") # else: # assert 0, val for g in G: lhs, rhs = tr[g], char[g] assert lhs == rhs, "%d: %s != %s" % (idx, lhs, rhs) assert len(c_reps) == n + 3 G.c_reps = c_reps # real characters ---------------------------------------------------- r_chars = [] r_chars.append(c_chars[0]) # Triv r_chars.append(c_chars[1]) # 1A if n % 2 == 0: assert c_chars[2].frobenius_schur() == 1 # real assert c_chars[3].frobenius_schur() == 1 # real r_chars.append(c_chars[2]) # 1B r_chars.append(c_chars[3]) # 1C else: assert c_chars[2].frobenius_schur() == 0 # complex assert c_chars[3].frobenius_schur() == 0 # complex r_chars.append(c_chars[2] + c_chars[3]) # 1B+1C for idx, rep in enumerate(c_reps): if idx < 4: continue char = c_chars[idx] val = char.frobenius_schur() if val == 1: r_chars.append(char) elif val == -1: r_chars.append(2 * char) else: assert 0 G.r_chars = r_chars return G
def main(): Z = element.Z ring = element.CyclotomicRing(8) x = ring.x r2 = x + x**7 assert r2**2 == 2 qubit = Space(2, ring) q2 = qubit @ qubit hom = Hom(qubit, qubit) I = Map.from_array([[1, 0], [0, 1]], hom) X = Map.from_array([[0, 1], [1, 0]], hom) Z = Map.from_array([[1, 0], [0, -1]], hom) Y = Map.from_array([[0, x**6], [x**2, 0]], hom) assert Y * Y == I assert Y == (x**2) * X * Z II = I @ I XI = X @ I IX = I @ X XX = X @ X ZI = Z @ I IZ = I @ Z assert XI * IX == XX T = Map.from_array([[1, 0], [0, x]], hom) Td = Map.from_array([[1, 0], [0, x**7]], hom) S = T * T Sd = Td * Td assert Z == S * S assert T * Td == I assert S * Sd == I assert S * Z == Z * S assert T * Z == Z * T assert (Z * X * Z) == -X assert ((Z @ Z) * (X @ X) * (Z @ Z)) == X @ X assert ((S @ S) * (X @ X) * (Sd @ Sd)) == atpow((S * X * Sd), 2) SXSd = S * X * Sd TXTd = T * X * Td lhs = r2 * TXTd i = x**2 assert (lhs == X + i * X * Z) if 0: names = mulclose_names([X, Z, x * I], "X Z xI".split()) #print("SXSd:", "*".join(names[SXSd])) names = mulclose_names([XI, IX, ZI, IZ], "XI IX ZI IZ".split()) g = atpow(SXSd, 2) #print("*".join(names[g])) gen = [ X @ I @ I @ I, I @ X @ I @ I, I @ I @ X @ I, I @ I @ I @ X, Z @ I @ I @ I, I @ Z @ I @ I, I @ I @ Z @ I, I @ I @ I @ Z, x * (I @ I @ I @ I) ] names = "XIII IXII IIXI IIIX ZIII IZII IIZI IIIZ wIIII".split() names = mulclose_names(gen, names) g = atpow(SXSd, 4) #print("*".join(names[g])) g = atpow(TXTd, 4) assert g not in names I8, X8, Z8 = atpow(I, 8), atpow(X, 8), atpow(Z, 8) T8 = atpow(T, 8) #print(T8.str(hide_zero=True, sep="")) Td8 = atpow(Td, 8) G = mulclose([X8, Z8]) P = I8 + X8 + Z8 + X8 * Z8 assert P * P == 4 * P lhs = P rhs = T8 * P * Td8 assert (rhs * rhs == 4 * rhs) #T1 = reduce(matmul, [T, Td]*4) #T2 = reduce(matmul, [Td, T]*4) #print(T1*P*T2) #return Q = P @ P RM14 = """ 1111111111111111 .1.1.1.1.1.1.1.1 ..11..11..11..11 ....1111....1111 ........11111111 """.strip().split() RM14.pop(0) def interp(row, op): ops = [op if s == "1" else I for s in row] A = reduce(matmul, ops) return A RM14 = [row[1:] for row in RM14] # puncture n = len(RM14[0]) Sx = [interp(row, X) for row in RM14] Sz = [interp(row, Z) for row in RM14] if 0: print("mulclose...") G = mulclose(Sx + Sz, maxsize=2**len(Sx + Sz)) # too slow :-( print(len(G)) P = reduce(add, G) assert P * P == len(G) * P Tn = atpow(T, n) Tdn = atpow(Td, n) print(P == Tn * P * Tdn) #print(lhs.str(hide_zero=True, sep="")) #print() #print() #print() #print(rhs.str(hide_zero=True, sep="")) gen = [ X @ I @ I @ I @ I @ I @ I @ I, I @ X @ I @ I @ I @ I @ I @ I, I @ I @ X @ I @ I @ I @ I @ I, I @ I @ I @ X @ I @ I @ I @ I, I @ I @ I @ I @ X @ I @ I @ I, I @ I @ I @ I @ I @ X @ I @ I, I @ I @ I @ I @ I @ I @ X @ I, I @ I @ I @ I @ I @ I @ I @ X, Z @ I @ I @ I @ I @ I @ I @ I, I @ Z @ I @ I @ I @ I @ I @ I, I @ I @ Z @ I @ I @ I @ I @ I, I @ I @ I @ Z @ I @ I @ I @ I, I @ I @ I @ I @ Z @ I @ I @ I, I @ I @ I @ I @ I @ Z @ I @ I, I @ I @ I @ I @ I @ I @ Z @ I, I @ I @ I @ I @ I @ I @ I @ Z, x * (I @ I @ I @ I @ I @ I @ I @ I) ] names = """ XIIIIIII IXIIIIII IIXIIIII IIIXIIII IIIIXIII IIIIIXII IIIIIIXI IIIIIIIX ZIIIIIII IZIIIIII IIZIIIII IIIZIIII IIIIZIII IIIIIZII IIIIIIZI IIIIIIIZ wIIIIIIII """.strip().split() gen.pop(-1) names.pop(-1) if 0: g = atpow(TXTd, 8) for i in range(8): print(g == (x**i) * atpow(X * Z, 8)) return if 0: names = mulclose_names(gen, names) g = atpow(TXTd, 8) for i in range(8): print(names.get((x**i) * g, "?")) #for i in [1, 2, 4]: # print(atpow(TXTd, i)) if 0: #print(Td*X*T) X4 = X @ X @ X @ X T4 = T @ T @ T @ T Td4 = Td @ Td @ Td @ Td print(Td4 * X4 * T4) H = X + Z E = Map.from_array([[0, 1], [0, 0]], hom) # raising F = Map.from_array([[0, 0], [1, 0]], hom) # lowering CNOT = Map.from_array( [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], hom @ hom) SWAP = Map.from_array( [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], hom @ hom) assert SWAP * SWAP == II assert CNOT * CNOT == II G = mulclose([XI, IX, CNOT]) # order 8 G = mulclose([XI, IX, CNOT, SWAP]) # order 24.. must be S_4 G = mulclose([CNOT, SWAP]) # print(len(G)) # for g in G: # print(g) A = SWAP @ I B = I @ SWAP S_3 = list(mulclose([A, B])) assert len(S_3) == 6 # for g in G: # print(g) # print(g.hom) hom = A.hom space = hom.src N = 2**3 basis = space.get_basis() orbits = set() for v in basis: v1 = space.zero_vector() for g in S_3: u = g * v v1 = v1 + u orbits.add(v1) orbits = list(orbits) # for v in orbits: # print(v) HHH = H @ H @ H v = basis[7] #print(v) #print(HHH * v) print("OK")
def main(): d = 2 ring = CyclotomicRing(8) #ring = element.Z e = ring.x gamma = e**2 w = gamma**2 assert w == -1 I = numpy.zeros((d, d), dtype=object) wI = numpy.zeros((d, d), dtype=object) X = numpy.zeros((d, d), dtype=object) Z = numpy.zeros((d, d), dtype=object) Zdag = numpy.zeros((d, d), dtype=object) S = numpy.zeros((d, d), dtype=object) Sdag = numpy.zeros((d, d), dtype=object) T = numpy.zeros((d, d), dtype=object) Tdag = numpy.zeros((d, d), dtype=object) for j in range(d): I[j, j] = 1 wI[j, j] = w X[j, (j + 1) % d] = 1 Z[j, j] = w**j Zdag[j, j] = w**(d - j) val = [1, gamma][j] ival = [1, -gamma][j] assert val * ival == 1 S[j, j] = val Sdag[j, j] = ival val = [1, e][j] ival = [1, e**7][j] assert val * ival == 1 T[j, j] = val Tdag[j, j] = ival qu = Space(d, ring) hom = Hom(qu, qu) I = Map.from_array(I, hom) wI = Map.from_array(wI, hom) Xdag = Map.from_array(X.transpose(), hom) X = Xs = Map.from_array(X, hom) Z = Map.from_array(Z, hom) Zdag = Map.from_array(Zdag, hom) S = Map.from_array(S, hom) Sdag = Map.from_array(Sdag, hom) T = Map.from_array(T, hom) Tdag = Map.from_array(Tdag, hom) Y = w * X * Z # ? assert S * Sdag == I assert S * S == Z assert T * T == S assert Z * Zdag == I assert X * Xdag == I if d > 2: for j in range(1, d + 1): assert (j == d) == (X**j == I) assert (j == d) == (Z**j == I) else: assert X != I assert Z != I assert X * X == I assert Z * Z == I assert Z * X == (w**(d - 1)) * X * Z pauli = mulclose([X, Z, gamma * I]) pauli = set(pauli) print("pauli:", len(pauli)) assert Zdag in pauli assert Xdag in pauli if d < 6: # slow.. lhs = atpow(X, d) rhs = atpow(Z, d) assert lhs * rhs == rhs * lhs lhs = X @ X rhs = Z @ Zdag assert lhs * rhs == rhs * lhs lhs = X @ (X**(d - 1)) rhs = Z @ Z assert lhs * rhs == rhs * lhs if 0: n = 5 ops = [X, Xdag] lhs = [] for op in cross([ops] * n): op = reduce(matmul, op) lhs.append(op) ops = [Z, Zdag] rhs = [] for op in cross([ops] * n): op = reduce(matmul, op) rhs.append(op) for l in lhs: for r in rhs: if l * r == r * l: print("/", end=" ", flush=True) else: print(".", end=" ", flush=True) print() #print(Z@Z@Z) #print(Y) #print(S*X*Sdag) #print(Y == S*X*Sdag) if d == 3: assert (Y == S * X * Sdag) inverse = {} for g in pauli: for h in pauli: if g * h == I: inverse[g] = h inverse[h] = g def is_cliff(A, Ai): assert A * Ai == I for g in pauli: h = A * g * Ai if h not in pauli: return False return True print(S) print(Sdag) assert is_cliff(S, Sdag) #print("is_cliff:", (S in pauli), is_cliff(S, Sdag)) def is_third_level(A, Ai): assert A * Ai == I for g in pauli: gi = inverse[g] h = A * g * Ai * gi hi = g * A * gi * Ai if not is_cliff(h, hi): return False return True print("is_pauli(S)", S in pauli) print("is_cliff(S)", is_cliff(S, Sdag)) #print("is_third_level(S)", is_third_level(S, Tdag)) print("is_pauli(T)", T in pauli) print("is_cliff(T)", is_cliff(T, Tdag)) print("is_third_level(T)", is_third_level(T, Tdag)) #C2 = mulclose([X, T, H]) print("OK")
def test(): f = FiniteField(5) one = f.one zero = f.zero assert one==1 assert str(one) == "1" a = zero for i in range(1000): a = one + a if a==zero: break assert i==4, i # ------------------------- one = Z.one two = one + one assert one/one == one assert two/two == one assert two/(-one) == -two ring = PolynomialRing(Z) one = ring.one assert ring.x == Polynomial({1:1}, ring) x = ring.x assert (x+one)**5 == x**5+5*x**4+10*x**3+10*x**2+5*x+1 assert str((x+one)**3) == "x**3+3*x**2+3*x+1" assert ring.content(10*x + 2) == 2 assert ring.content(5*x**2 + 10*x + 2) == 1 for (a, b) in [ (4, 10), (4, 10*x), (2*x+1, 3*x), (x**3 + x + 1, x**6), ]: a = ring.promote(a) b = ring.promote(b) div, rem = a.reduce(b) assert a*div + rem == b #print("(%s) * (%s) + %s = %s" % (a, div, rem, b)) c = ring.gcd(a, b) #print("gcd(%s, %s) == %s"%(a, b, c)) #return # ------------------------- field = FiniteField(5) ring = PolynomialRing(field) one = ring.one x = ring.x assert (x+one)**5 == x**5+1 assert x**0 == one # ------------------------- # check we can build galois field GF(8) field = FiniteField(2) ring = PolynomialRing(field) one = ring.one x = ring.x f = x**3 - x - 1 assert f == x**3+x+1 assert f(0) != 0 assert f(1) != 0 b = x**5 div, rem = f.reduce(b) assert f*div + rem == b group = [] for i in range(2): for j in range(2): for k in range(2): a = i + j*x + k*x**2 if a != 0: group.append(a) div = {} for a in group: for b in group: c = f.reduce(a*b)[1] div[c, a] = b div[c, b] = a # all non-zero pairs elements of GF(8) should be divisable: assert len(div) == 49 # -------------------------------------------------- # GF(4) x = ring.x GF = GaloisField(ring, (x**2 + x + 1)) x = GF.x one = GF.one a, b = x, x+one assert a*a == b assert a*b == b*a assert a*b == one assert b*b == a assert one/x == one+x frobenius = lambda a : a**2 assert frobenius(one) == one assert frobenius(one+one) == one+one assert frobenius(x) == x+1 assert frobenius(x+1) == x # -------------------------------------------------- # GF(8) x = ring.x GF = GaloisField(ring, (x**3 + x + 1)) one = GF.one x = GF.x assert one/x == x**2+1 # -------------------------------------------------- # GF(64) x = ring.x GF = GaloisField(ring, (x**6 + x + 1)) one = GF.one x = GF.x assert len(GF.elements) == 64 # ------------------------- p = 7 field = FiniteField(p) ring = PolynomialRing(field) x = ring.x if p % 4 == 3: r = p-1 else: assert 0 GF = GaloisField(ring, x**2 - r) one = GF.one x = GF.x for a in GF.elements: b = a**(p+1) assert b.deg <= 0, repr(b) # ------------------------- Z2 = FiniteField(2) for GL in [Linear(1, Z), Linear(2, Z), Linear(2, Z2)]: one = GL.one zero = GL.zero assert one-one == zero assert zero+one == one assert one+one != one assert one*one == one assert zero*one == zero assert one+one == 2*one if GL.base == Z2: assert one+one == zero GL2 = Linear(2, Z) A = GL2.get([[1, 1], [0, 1]]) # ------------------------- # field = FiniteField(2) GL = Linear(3, field) gen = [ [[1, 1, 0], [0, 1, 0], [0, 0, 1]], [[1, 0, 0], [0, 1, 1], [0, 0, 1]], [[1, 0, 0], [1, 1, 0], [0, 0, 1]], [[1, 0, 0], [0, 1, 0], [0, 1, 1]], ] gen = [GL.get(g) for g in gen] GL3_2 = mulclose(gen) assert len(GL3_2) == 168 if argv.GL3_2: burnside(cayley(GL3_2)) # high memory usage # ------------------------- # ring = Z GL = Linear(3, ring) gen = [ [[0, 0, -1], [0, 1, 0], [1, 0, 0]], [[1, 0, 0], [0, 0, 1], [0, -1, 0]], ] gen = [GL.get(g) for g in gen] B_3 = mulclose(gen) assert len(B_3) == 24 if argv.B_3: B_3 = cayley(B_3) burnside(B_3) # ------------------------- field = FiniteField(3) GL = Linear(2, field) A = GL.get([[1, 1], [0, 1]]) B = GL.get([[1, 0], [1, 1]]) # AKA. binary tetrahedral group SL2_3 = mulclose([A, B]) assert len(SL2_3) == 24 if argv.SL2_3: burnside(cayley(SL2_3)) # ------------------------- # https://people.maths.bris.ac.uk/~matyd/GroupNames/1/GL(2,3).html C = GL.get([[2, 0], [0, 1]]) D = GL.get([[1, 0], [0, 2]]) GL2_3 = mulclose([A, B, C, D]) assert len(GL2_3) == 48 if argv.GL2_3: burnside(cayley(GL2_3)) # ------------------------- # https://people.maths.bris.ac.uk/~matyd/GroupNames/1/Q8.html # quaternion group, Q_8 A = GL.get([[2, 2], [2, 1]]) B = GL.get([[0, 2], [1, 0]]) Q8 = mulclose([A, B]) assert(len(Q8)) == 8 if argv.Q8 or argv.Q_8: burnside(cayley(Q8)) # ------------------------- # https://people.maths.bris.ac.uk/~matyd/GroupNames/97/SL(2,5).html # aka binary icosahedral group field = FiniteField(5) GL = Linear(2, field) A = GL.get([[4, 2], [4, 1]]) B = GL.get([[3, 3], [4, 1]]) SL2_5 = mulclose([A, B]) assert len(SL2_5) == 120 if argv.SL2_5: burnside(cayley(SL2_5)) # ------------------------- field = FiniteField(7) GL = Linear(2, field) A = GL.get([[1, 1], [0, 1]]) B = GL.get([[1, 0], [1, 1]]) SL2_7 = mulclose([GL.one, A, B]) assert len(SL2_7) == 336 == 168*2 # https://people.maths.bris.ac.uk/~matyd/GroupNames/1/CSU(2,3).html # aka binary octahedral group A = GL.get([[2, 1], [2, 5]]) B = GL.get([[1, 2], [6, 6]]) C = GL.get([[4, 0], [2, 2]]) D = GL.get([[2, 5], [6, 5]]) BO = mulclose([A, B, C, D]) assert len(BO) == 48 if argv.BO: burnside(cayley(BO)) # ------------------------- ring = PolynomialRing(Z) x = ring.x assert cyclotomic(ring, 1) == x-1 assert cyclotomic(ring, 2) == x+1 assert cyclotomic(ring, 3) == x**2+x+1 assert cyclotomic(ring, 4) == x**2+1 assert cyclotomic(ring, 5) == x**4+x**3+x**2+x+1 assert cyclotomic(ring, 6) == x**2-x+1 assert cyclotomic(ring, 7) == x**6+x**5+x**4+x**3+x**2+x+1 assert cyclotomic(ring, 8) == x**4+1 assert cyclotomic(ring, 9) == x**6+x**3+1 assert cyclotomic(ring, 10) == x**4-x**3+x**2-x+1 assert cyclotomic(ring, 24) == x**8-x**4+1 # ------------------------- for n in range(2, 20): p = cyclotomic(PolynomialRing(Z), 2*n) ring = PolynomialRing(Z) / p x = ring.x assert x*1 == x x1 = x**(2*n-1) # inverse assert x**(2*n) == 1 assert x1 != 1 # ---------------------------- # Binary dihedral group # https://people.maths.bris.ac.uk/~matyd/GroupNames/dicyclic.html GL = Linear(2, ring) A = GL.get([[x, 0], [0, x1]]) B = GL.get([[0, -1], [1, 0]]) Di = mulclose([A, B]) assert len(Di) == 4*n if argv.Dic and n==argv.get("n"): print("order =", len(Di)) burnside(cayley(Di)) return # ------------------------- one = Q.one two = one+one assert two*one == two half = one/two assert 2*half == 1 assert 4*one/4 == one assert str(18*one/4) == "9/2" # ------------------------- ring = PolynomialRing(Z) field = FieldOfFractions(ring) one = field.one two = one+one assert two*one == two half = one/two assert 2*half == 1 assert 4*one/4 == one # ------------------------- # Gaussian integers # http://math.ucr.edu/home/baez/week216.html ring = PolynomialRing(Z) x = ring.x gints = ring / (x**2 + 1) one = gints.one i = gints.x assert i*i == -one assert i**3 == -i assert (1+i)**2 == 2*i assert (2+i)*(2-i) == 5 assert (3+2*i)*(3-2*i) == 13 # ------------------------- # Eisenstein integers ring = PolynomialRing(Z) x = ring.x ints = ring / cyclotomic(ring, 3) one = ints.one i = ints.x assert i**3 == 1 # ------------------------- # Kleinian integers ring = PolynomialRing(Z) x = ring.x ints = ring / (x**2 + x + 2) one = ints.one i = ints.x assert i * (-1-i) == 2 assert i * (1+i) == -2 # ------------------------- # ring = PolynomialRing(Z) p = cyclotomic(PolynomialRing(Z), 8) ring = ring / p field = FieldOfFractions(ring) x = field.promote(ring.x) one = field.one r2 = x + x**7 assert r2**2 == 2 # sqrt(2) i = x**2 assert i**2 == -one # sqrt(-1) GL = Linear(2, field) I = GL.get([[1, 0], [0, 1]]) J = GL.get([[1, 0], [0, i]]) M = (r2/2) * GL.get([[1, 1], [1, -1]]) # Hadamard assert J**4 == I assert M**2 == I G = mulclose([J, M]) assert len(G) == 192 assert M in G def get_order(A): count = 1 B = A while B!=I: B = A*B count += 1 return count #for g in G: # if get_order(g)==4: # print(g) assert get_order(M)==2 # Metaplectic Hadamard M1 = GL.get([[1, -i], [-i, 1]]) r = x / r2 M1 = r*M1 assert get_order(M1)==4 # #G = cayley(G) # #orders = [g.order() for g in G] # orders = [get_order(A) for A in G] # orders.sort() # print(orders) i_actually_know_what_im_doing = False if i_actually_know_what_im_doing: # ------------------------- # Q[i] ring = PolynomialRing(Q) x = ring.x gints = ring / (x**2 + 1) one = gints.one i = gints.x assert i*i == -one assert i**3 == -i assert (1+i)**2/i == 2 assert (2+i)*(2-i)/5 == 1 assert (3+2*i)*(3-2*i)/13 == 1