def __init__(self, G_0): a, ai, b, bi, c, ci, d, di = G_0.gens # 5,5 coxeter subgroup G_1 = Group.generate([a, b, c]) assert G_0.is_subgroup(G_1) # orientation subgroup L_0 = Group.generate([a * b, a * d]) assert G_0.is_subgroup(L_0) orients = G_0.left_cosets(L_0) assert len(orients) == 2 H_1 = Group.generate([a, b]) self.faces = G_1.left_cosets(H_1) self.act_faces = G_1.action_subgroup(H_1) print("faces:", len(self.faces)) return K_1 = Group.generate([b, c]) vertices = G_1.left_cosets(K_1) J_1 = Group.generate([a, c]) edges = G_1.left_cosets(J_1) print("faces: %d, edges: %d, vertices: %d" % (len(faces), len(edges), len(vertices))) self.faces = faces self.edges = edges self.vertices = vertices self.act_faces = act_faces
def get_perms(items, parts): perms = [] for part in parts: for i in range(len(part) - 1): perm = dict((item, item) for item in items) perm[part[i]] = part[i + 1] perm[part[i + 1]] = part[i] perm = Perm(perm, items) perms.append(perm) if not perms: # identity perms = [Perm(dict((item, item) for item in items), items)] G = Group.generate(perms) return G
def petersen_graph(R=2.0, r=1.0): nodes = range(10) layout = {} w = 2 * pi / 6 for i in range(6): layout[i] = R * cos(w * i), R * sin(w * i) w = 2 * pi / 3 for i in range(6, 9): layout[i] = r * sin(w * i), -r * cos(w * i) layout[9] = (0., 0.) edges = [(i, (i + 1) % 6) for i in range(6)] for i in range(3): edges.append((6 + i, 9)) edges.append((6 + i, 2 * i)) edges.append((6 + i, (2 * i + 3) % 6)) if 0: # TODO: should be able to construct G from all graph # automorphisms. Choose the ones that preserve the distance between nodes. perm = {} for i in range(6): perm[i] = (i + 2) % 6 for i in range(3): perm[i + 6] = (i + 1) % 3 + 6 perm[9] = 9 g = Perm(perm, nodes) perm = {0: 3, 1: 2, 2: 1, 3: 0, 4: 5, 5: 4, 6: 6, 7: 8, 8: 7, 9: 9} h = Perm(perm, nodes) G = Group.generate([g, h]) assert len(G) == 6 yield Graph(nodes, edges, layout) # ------------ edges = [(i, (i + 1) % 5) for i in range(5)] for i in range(5): edges.append((i, i + 5)) edges.append((i + 5, (i + 2) % 5 + 5)) w = 2 * pi / 5 layout = {} for i in range(5): layout[i] = R * sin(w * i), R * cos(w * i) layout[i + 5] = r * sin(w * i), r * cos(w * i) yield Graph(nodes, edges, layout)
def main(): if argv.A_3: W = Weyl.build_A(3) elif argv.A_4: W = Weyl.build_A(4) elif argv.B_2: W = Weyl.build_B(2) elif argv.B_3: W = Weyl.build_B(3) elif argv.D_4: W = Weyl.build_D(4) else: return G = Group.generate(W.gen) # for g in W.gen: # print(g) # # for root in W.roots: # print(root, end=" ") # if root in W.simple: # print("*") # else: # print("") groups = [] for subset in all_subsets(len(W.simple)): #print("subset:", subset) simple = tuple(W.simple[i] for i in subset) H = parabolic(W.roots, simple) #print("H:", len(H)) assert G.is_subgroup(H) groups.append(H) assert len(groups)==2**(len(W.simple)) print("parabolic subgroups:", len(groups)) print("orders:", [len(H) for H in groups]) Hs = conjugacy_subgroups(G, groups) print("conjugacy_subgroups:", len(Hs)) burnside(G, Hs)
def parabolic(roots, simple): "use _generators from reflections of simple roots" for root in simple: assert root in roots n = len(roots[0]) idxs = range(n) lookup = dict((root, i) for (i, root) in enumerate(roots)) gen = [] for alpha in simple: #print "alpha:", alpha r0 = sum(alpha[i]*alpha[i] for i in idxs) perm = [] for root in roots: #print " root:", root r = sum(alpha[i]*root[i] for i in idxs) _root = tuple(root[i] - 2*Fraction(r, r0)*alpha[i] for i in idxs) #print " _root:", _root perm.append(lookup[_root]) perm = Perm(perm, roots) gen.append(perm) return Group.generate(gen, items=roots)
def cayley(gen): G = Group.generate(gen) lookup = dict((g, i) for (i, g) in enumerate(G)) graph = nx.Graph() # undirected graph, must have gen closed under inverse for i, g in enumerate(G): graph.add_node(i) #for g in gen: # assert (g*g).is_identity() for g in gen: assert g.inverse() in gen # undirected graph! edges = set() for g in G: for h in gen: hg = h * g if (hg, g) in edges: continue edges.add((g, hg)) for g, h in edges: graph.add_edge(lookup[g], lookup[h]) return graph
def test_galois(): p = argv.get("p", 2) r = argv.get("r", 2) print("q =", p**r) F = GF(p**r) print("GF(%d) = GF(%d)[x]/(%s)" % (p**r, p, F.mod)) print("omega =", F.omega) omega = F.omega #assert omega**2 == omega + 1 els = F.elements assert len(els) == len(set(els)) == p**r for a in els: for b in els: if b != 0: c = a / b # XXX fails for p=3, r=4 assert c * b == a def orbit(a): items = set([a]) while 1: a = F.frobenius(a) if a in items: break items.add(a) return items lookup = {e: i for (i, e) in enumerate(els)} for i, e in enumerate(els): print("%s: %s" % (i, e)) g = {lookup[e]: lookup[F.frobenius(e)] for e in els} #print(["%s:%s"%(k,v) for (k,v) in g.items()]) values = set(g.values()) assert len(values) == len(g) items = list(range(len(els))) g = Perm(g, items) I = Perm.identity(items) G = [I] h = g print(g) while h != I: G.append(h) h = g * h #print(len(G)) assert len(G) <= p**r print("|G| =", len(G)) G = Group.generate([g]) print("|G| =", len(G)) for i in els: n = len(orbit(i)) if n == 1: print("*", end="") print(n, end=" ") print() def inner(u, v): r = u * F.frobenius(v) - F.frobenius(u) * v return r print("els:", end=" ") for u in els: print(u, end=" ") print() print("inner(u,u):", end=" ") for u in els: print(inner(u, u), end=" ") print() print("inner(u,v):") for u in els: for v in els: print(inner(u, v), end=" ") print() print() for u in els: #print([int(inner(u,v)==0) for v in els]) for v in els: i = int(inner(u, v) == 0) print(i or '.', end=" ") print() print("test_galois: OK")
def get_group(self): gens = self.get_gens() G = Group.generate(gens) return G
def make_bring(): # ------------------------------------------------ # Bring's curve rotation group ngens = 2 a, ai, b, bi = range(2 * ngens) rels = [(ai, a), (bi, b), (a, ) * 5, (b, ) * 2] rels += [(a, a, a, b) * 3] graph = Schreier(2 * ngens, rels) #graph.DEBUG = True graph.build() assert len(graph) == 60 # == 12 * 5 # --------------- Group ------------------ G = graph.get_group() #burnside(G) assert len(G.gens) == 4 ai, a, bi, b = G.gens assert a == ~ai assert b == ~bi assert a.order() == 5 assert b.order() == 2 H = Group.generate([a]) faces = G.left_cosets(H) assert len(faces) == 12 #hom = G.left_action(faces) ab = a * b K = Group.generate([ab]) vertices = G.left_cosets(K) assert len(vertices) == 12 J = Group.generate([b]) edges = G.left_cosets(J) assert len(edges) == 30 from bruhat.solve import shortstr, zeros2, dot2 from numpy import alltrue, zeros, dot 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 Hz = get_adj(faces, edges) Hxt = get_adj(edges, vertices) #print(shortstr(Hz)) #print() #print(shortstr(Hxt)) #print() assert alltrue(dot2(Hz, Hxt) == 0) # ------------ _oriented version --------------- # Bring's curve reflection group ngens = 3 a, ai, b, bi, c, ci = range(2 * ngens) 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) rels += [(3 * a1 + b1) * 3] graph = Schreier(2 * ngens, rels) graph.build() assert len(graph) == 120 # == 12 * 10 # --------------- Group ------------------ G = graph.get_group() assert len(G) == 120 a, ai, b, bi, c, ci = G.gens a1 = b * a b1 = a * c assert a1.order() == 5 assert b1.order() == 2 bc = b * c ba = b * a assert bc.order() == 5 assert ba.order() == 5 L = Group.generate([a1, b1]) assert len(L) == 60, len(L) orients = G.left_cosets(L) assert len(orients) == 2 #L, gL = orients orients = list(orients) H = Group.generate([a, b]) assert len([g for g in H if g in L]) == 5 faces = G.left_cosets(H) assert len(faces) == 12 # unoriented faces #hom = G.left_action(faces) o_faces = [face.intersect(orients[0]) for face in faces] # oriented faces r_faces = [face.intersect(orients[1]) for face in faces] # reverse oriented faces K = Group.generate([b, c]) vertices = G.left_cosets(K) assert len(vertices) == 12 # unoriented vertices o_vertices = [vertex.intersect(orients[0]) for vertex in vertices] # oriented vertices J = Group.generate([a, c]) u_edges = G.left_cosets(J) assert len(u_edges) == 30 # unoriented edges J = Group.generate([c]) edges = G.left_cosets(J) assert len(edges) == 60, len(edges) # oriented edges ? # Here we choose an orientation on each edge: pairs = {} for e in u_edges: pairs[e] = [] for e1 in edges: if e.intersect(e1): pairs[e].append(e1) assert len(pairs[e]) == 2 def shortstr(A): s = str(A) s = s.replace("0", '.') return s Hz = zeros((len(o_faces), len(u_edges)), dtype=int) for i, l in enumerate(o_faces): for j, e in enumerate(u_edges): le = l.intersect(e) if not le: continue e1, e2 = pairs[e] if e1.intersect(le): Hz[i, j] = 1 elif e2.intersect(le): Hz[i, j] = -1 else: assert 0 Hxt = zeros((len(u_edges), len(o_vertices)), dtype=int) for i, e in enumerate(u_edges): for j, v in enumerate(o_vertices): ev = e.intersect(v) if not ev: continue e1, e2 = pairs[e] if e1.intersect(ev): Hxt[i, j] = 1 elif e2.intersect(ev): Hxt[i, j] = -1 else: assert 0 #print(shortstr(Hz)) #print() #print(shortstr(Hxt)) #print() assert alltrue(dot(Hz, Hxt) == 0)
def make_surface_54_oriented(G0): " find integer chain complex " from bruhat.solve import shortstr, zeros2, dot2 from numpy import alltrue, zeros, dot print() print("|G0| =", len(G0)) a, ai, b, bi, c, ci, d, di = G0.gens # 5,5 coxeter subgroup G_55 = Group.generate([a, b, c]) assert G0.is_subgroup(G_55) # orientation subgroup L = Group.generate([a * b, a * d]) #assert len(L) == 60, len(L) print("L:", len(L)) orients = G0.left_cosets(L) assert len(orients) == 2 orients = list(orients) H = Group.generate([a, b]) faces = G_55.left_cosets(H) fold_faces = G0.left_cosets(H) print("faces:", len(faces)) print("fold_faces:", len(fold_faces)) #hom = G.left_action(faces) o_faces = [face.intersect(orients[0]) for face in faces] # oriented faces r_faces = [face.intersect(orients[1]) for face in faces] # reverse oriented faces K = Group.generate([b, c]) vertices = G_55.left_cosets(K) #assert len(vertices) == 12 # unoriented vertices o_vertices = [vertex.intersect(orients[0]) for vertex in vertices] # oriented vertices print("o_vertices:", len(o_vertices)) J0 = Group.generate([a, d]) assert len(J0) == 8 assert G0.is_subgroup(J0) act_edges = G0.action_subgroup(J0) act_fold_faces = G0.action_subgroup(H) #print("stab:", len(act_edges.get_stabilizer())) print("|G0| =", len(G0)) print("edges:", len(G0) // len(J0)) edges = G0.left_cosets(J0) #for e in edges: # k = choice(e.perms) # e1 = e.left_mul(~k) # assert set(e1.perms) == set(J0.perms) fold_perms = [] for i, g in enumerate(G0): assert g in G0 #h_edge = act_edges.tgt[act_edges.send_perms[i]] #h_fold_faces = act_fold_faces.tgt[act_fold_faces.send_perms[i]] h_edge = act_edges[g] h_fold_faces = act_fold_faces[g] n_edge = len(h_edge.fixed()) n_fold_faces = len(h_fold_faces.fixed()) count = 0 #perms = [] # extract action on the fixed edges #for e0 in edges: # #e1 = e0.left_mul(g) # e1 = g*e0 # if e0 != e1: # continue # perm = e0.left_mul_perm(g) # #print(perm, end=" ") # perms.append(perm) # count += 1 #assert count == n_edge if g.order() == 2 and g not in G_55 and g not in L: fold_perms.append(g) else: continue #print([p.order() for p in perms] or '', end="") print( "[|g|=%s,%s.%s.%s.%s]" % ( g.order(), n_edge or ' ', # num fixed edges n_fold_faces or ' ', # num fixed faces+vertexes [" ", "pres" ][int(g in G_55)], # preserves face/vertex distinction ["refl", "rot "][int(g in L)], # oriented or un-oriented ), end=" ", flush=True) print() print() J = Group.generate([a, c]) u_edges = G_55.left_cosets(J) print("u_edges:", len(u_edges)) J = Group.generate([c]) edges = G_55.left_cosets(J) print("edges:", len(edges)) # Here we choose an orientation on each edge: pairs = {} for e in u_edges: pairs[e] = [] for e1 in edges: if e.intersect(e1): pairs[e].append(e1) assert len(pairs[e]) == 2, len(pairs[e]) def shortstr(A): s = str(A) s = s.replace("0", '.') return s Hz = zeros((len(o_faces), len(u_edges)), dtype=int) for i, l in enumerate(o_faces): for j, e in enumerate(u_edges): le = l.intersect(e) if not le: continue e1, e2 = pairs[e] if e1.intersect(le): Hz[i, j] = 1 elif e2.intersect(le): Hz[i, j] = -1 else: assert 0 Hxt = zeros((len(u_edges), len(o_vertices)), dtype=int) for i, e in enumerate(u_edges): for j, v in enumerate(o_vertices): ev = e.intersect(v) if not ev: continue e1, e2 = pairs[e] if e1.intersect(ev): Hxt[i, j] = 1 elif e2.intersect(ev): Hxt[i, j] = -1 else: assert 0 #print(shortstr(Hz)) #print() #print(shortstr(Hxt)) #print() assert alltrue(dot(Hz, Hxt) == 0) for perm in fold_perms: pass import qupy.ldpc.solve import bruhat.solve qupy.ldpc.solve.int_scalar = bruhat.solve.int_scalar from qupy.ldpc.css import CSSCode Hz = Hz % 2 Hx = Hxt.transpose() % 2 code = CSSCode(Hz=Hz, Hx=Hx) print(code)
def make_surface_54(G_0): "find Z/2 chain complex" from bruhat.solve import shortstr, zeros2, dot2 from numpy import alltrue, zeros, dot print("|G_0| =", len(G_0)) a, ai, b, bi, c, ci, d, di = G_0.gens # 5,5 coxeter subgroup G_1 = Group.generate([a, b, c]) assert G_0.is_subgroup(G_1) # orientation subgroup L_0 = Group.generate([a * b, a * d]) assert G_0.is_subgroup(L_0) orients = G_0.left_cosets(L_0) assert len(orients) == 2 H_1 = Group.generate([a, b]) faces = G_1.left_cosets(H_1) #face_vertices = G_0.left_cosets(H_1) # G_0 swaps faces & vertices K_1 = Group.generate([b, c]) vertices = G_1.left_cosets(K_1) J_1 = Group.generate([a, c]) edges_1 = G_1.left_cosets(J_1) print("faces: %d, edges: %d, vertices: %d" % (len(faces), len(edges_1), len(vertices))) J_0 = Group.generate([a, d]) assert len(J_0) == 8 edges_0 = G_0.left_cosets(J_0) print("edges_0:", len(edges_0)) assert G_0.is_subgroup(J_0) act_edges_0 = G_0.action_subgroup(J_0) #print("here") #while 1: # sleep(1) from bruhat.solve import shortstr, zeros2, dot2, array2, solve from numpy import alltrue, zeros, dot 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) > 0 return A Hz = get_adj(faces, edges_0) Hxt = get_adj(edges_0, vertices) Hx = Hxt.transpose() #print(shortstr(Hz)) #print() #print(shortstr(Hxt)) #print() assert alltrue(dot2(Hz, Hxt) == 0) # act_fold_faces = G_0.action_subgroup(H_1) dualities = [] idx = 0 for i, g in enumerate(G_0): assert g in G_0 h_edge_0 = act_edges_0[g] n_edge = len(h_edge_0.fixed()) # h_fold_faces = act_fold_faces[g] # n_fold_faces = len(h_fold_faces.fixed()) count = 0 #perms = [] # extract action on the fixed edges for e0 in edges_0: e1 = g * e0 if e0 != e1: continue count += 1 # perm = e0.left_mul_perm(g) # #print(perm, end=" ") # perms.append(perm) assert count == n_edge if g in G_1: continue elif g.order() != 2: continue #elif g in L_0: # continue #elif g.order() == 2 and g not in G_1 and g not in L_0: perm = h_edge_0.get_idxs() dualities.append(perm) #if g not in L_0: # check_432(Hz, Hx, perm) # return result = is_422_cat_selfdual(Hz, Hx, perm) print( "%d: [|g|=%s,%s.%s.%s.%s]" % ( len(dualities), g.order(), n_edge or ' ', # num fixed edges # n_fold_faces or ' ', # num fixed faces+vertexes [" ", "pres" ][int(g in G_1)], # preserves face/vertex distinction ["refl", "rot "][int(g in L_0)], # oriented or un-oriented [" ", "selfdual"][result], ), end=" ", flush=True) print() print()
def main(): p = argv.get("p", 3) deg = argv.get("deg", 1) field = FiniteField(p) if deg == 1: G = GL2(field) return base, field = field, field.extend(deg) assert len(field.elements) == p**deg print("GF(%d)"%len(field.elements)) print(field.mod) print() items = [a for a in field.elements if a!=0] perm = Perm(dict((a, a**p) for a in items), items) G = Group.generate([perm]) print("|G| =", len(G)) orbits = G.orbits() print("orbits:", len(orbits), end=", ") fixed = 0 for orbit in orbits: if len(orbit)==1: fixed += 1 print(len(orbit), end=" ") print() print("fixed points:", fixed) if 0: # find other solutions to the extension polynomial ring = PolynomialRing(field) poly = ring.evaluate(field.mod) assert str(poly) == str(field.mod) assert poly(field.x) == 0 subs = [] for a in field.elements: if poly(a) == field.zero: subs.append(a) print(a) return lin = Linear(deg, base) zero = field.zero one = field.one x = field.x a = one basis = [] for i in range(deg): basis.append(a) a = x*a for a in field.elements: if a == zero: continue op = [[0 for j in range(deg)] for i in range(deg)] for j, b in enumerate(basis): c = a*b poly = c.value # unwrap for i in range(deg): op[i][j] = poly[i] op = lin.get(op) print(str(op).replace("\n", ""), a) print() if argv.check: zero = field.zero div = {} for a in field.elements: for b in field.elements: c = a*b div[c, a] = b div[c, b] = a for a in field.elements: for b in field.elements: if b != zero: assert (a, b) in div
def main(): # for name in """desargues_graph petersen_graph # dodecahedral_graph icosahedral_graph""".split(): name = argv.next() if name is None: return if name == "cayley": n = argv.get("n", 3) items = range(n) gen = [] 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] gen.append(perm) gen = [Perm(perm, items) for perm in gen] for g in gen: print(g) graph = cayley(gen) elif name == "transpositions": n = argv.get("n", 3) items = range(n) gen = [] for i in range(n - 1): for j in range(i + 1, n): perm = dict((item, item) for item in items) perm[items[i]] = items[j] perm[items[j]] = items[i] gen.append(perm) gen = [Perm(perm, items) for perm in gen] print("gen:", len(gen)) graph = cayley(gen) elif name == "cycles": n = argv.get("n", 3) items = range(n) gen = [] for i in range(n): for j in range(i + 1, n): for k in range(j + 1, n): perm = dict((item, item) for item in items) perm[items[i]] = items[j] perm[items[j]] = items[k] perm[items[k]] = items[i] gen.append(perm) perm = dict((item, item) for item in items) perm[items[i]] = items[k] perm[items[k]] = items[j] perm[items[j]] = items[i] gen.append(perm) gen = [Perm(perm, items) for perm in gen] print("gen:", len(gen)) graph = cayley(gen) else: builder = getattr(small, name, None) if builder is None: builder = getattr(classic, name, None) if builder is None: print(name, "not found") return n = argv.n if n is not None: graph = builder(n) else: graph = builder() print("|nodes|=%d, edges=|%d|" % (len(graph.nodes()), len(graph.edges()))) if argv.visualize: from visualize import draw_graph draw_graph(graph) return if argv.spec: print("spec:", ) spec = nx.adjacency_spectrum(graph) spec = [x.real for x in spec] spec.sort() print(' '.join("%5f" % x for x in spec)) return G = get_autos(graph) print("|G|=%d" % len(G)) if argv.all_subgroups: Hs = list(G.subgroups()) Hs.sort(key=lambda H: len(H)) else: Hs = [Group.generate([G.identity])] for H in Hs: print("|H|=%d" % len(H)) A = build_orbigraph(graph, H) print(A) spec = numpy.linalg.eigvals(A) spec = [x.real for x in spec] spec.sort(reverse=True) s = ' '.join(("%5f" % x).rjust(9) for x in spec) s = s.replace(".000000", "") print("spec:", s) print return