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 do_rank(): n = argv.get("n", 6) for n in [n]: G = Group.cyclic(range(n)) chis = burnside(G) print(n, len(chis)) #G = make_dicyclic(n) #chis = burnside(G) #print(len(chis)) return for n in range(25): #print(n, end=" ") G = Group.cyclic(range(n)) rank_C = burnside(G) #print(rank, end=" ") if n != 2: G = Group.dihedral(range(n)) rank_D = burnside(G) #print(rank, end=" ") #else: #print("?", end=" ") G = make_dicyclic(n) rank_Dic = burnside(G) #print(rank, end=" ") #print() print(r" %d & %d & %d & %d \\" % (n, rank_C, rank_D, rank_Dic))
def orbiplex(G, k=4): #import numpy #from gelim import zeros, dotx, rank, nullity print("orbiplex: |G|=%d" % len(G)) items = G.items k = argv.get("k", k) for n in range(k): write("|C_%d| ="%n) #if n > len(items): # break tpls = list(uniqtuples(items, n)) perms = [] for perm in G: _perm = {} for key in tpls: value = tuple(perm[i] for i in key) _perm[key] = value _perm = Perm(_perm, tpls) perms.append(_perm) G2 = Group(perms, tpls) orbits = list(G2.orbits()) d = len(orbits) write("%d,"%d)
def show_qpoly(G): gen = G.gen roots = G.roots els = G.generate() e = G.identity 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()) lookup = dict((g, g) for g in G) # remember canonical word n = len(gen) for i in range(n): gen1 = gen[:i] + gen[i + 1:] H = mulclose_short([e] + gen1) eH = Coset(H, roots) H = Group(H, roots) #gHs = G.left_cosets(H) cosets = set([eH]) bdy = set(cosets) while bdy: _bdy = set() for coset in bdy: for g in gen: gH = Coset([g * h for h in coset], roots) if gH not in cosets: cosets.add(gH) _bdy.add(gH) bdy = _bdy value = zero for gH in cosets: 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())
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 test(): n = 9 G = Group.symmetric(n) t = Young(G, (4, 3, 1, 1)) assert t.rows == [[0, 1, 2, 3], [4, 5, 6], [7], [8]] assert t.cols == [[0, 4, 7, 8], [1, 5], [2, 6], [3]] G = t.get_rowperms() assert len(G) == factorial(4) * factorial(3)
def get_autos(nxgraph): graph0 = mkgraph(nxgraph) graph1 = mkgraph(nxgraph) items = [point.idx for point in graph0] perms = [] for f in isomorph.search(graph0, graph1): perm = Perm(f, items) perms.append(perm) #print perm G = Group(perms, items) return G
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 get_isoms(self): "find the graph autos that act by isometries (on the layout)" nodes = self.nodes edges = self.edges G = get_autos(nodes, edges) A0 = self.get_metric() perms = [] for g in G: graph = self.permute(g) A1 = graph.get_metric() if numpy.allclose(A0, A1): perms.append(g) G = Group(perms, g.items) return G
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 make_group(ops): ops = list(ops) lookup = dict((numrepr(A), i) for (i, A) in enumerate(ops)) #for A in ops: # print(repr(numrepr(A))) items = list(range(len(ops))) perms = [] for i, A in enumerate(ops): perm = {} for j, B in enumerate(ops): C = dot(A, B) k = lookup[numrepr(C)] perm[j] = k perm = Perm(perm, items) perms.append(perm) G = Group(perms, items) return G
def cayley(elements): "build the regular permutation representation" elements = list(elements) lookup = {} for idx, e in enumerate(elements): lookup[e] = idx items = list(range(len(elements))) perms = [] for i, e in enumerate(elements): perm = {} for j, f in enumerate(elements): g = e*f k = lookup[g] perm[j] = k perm = Perm(perm, items) perms.append(perm) G = Group(perms, items) return 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 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 test(): ring = element.Q n = argv.get("n", 3) G = Group.symmetric(n) tp = Cat(G, ring) burnside(tp) return rep = Rep.perm_rep(G, cat) rep.check() r2 = rep @ rep r2.check() r2.dump()
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 main(): name = argv.next() or "icosahedron" geometry = make_geometry(name) graph = geometry.get_bag() graph1 = geometry.get_bag() #print graph n = len(graph) items = [i for i in range(n) if graph[i].desc=="vert"] #print items perms = [] for f in isomorph.search(graph, graph1): #print f f = dict((i, f[i]) for i in items) perm = Perm(f, items) perms.append(perm) write('.') print("symmetry:", len(perms)) assert len(set(perms)) == len(perms) G = Group(perms, items) orbiplex(G)
from bruhat.action import Perm, Group from bruhat.util import factorial from bruhat.argv import argv p = argv.get("p", 5) if 0: items = [i for i in range(1, p**2) if i % p] print(items) perms = [] for i in items: perm = dict((j, (j * i) % p**2) for j in items) perms.append(Perm(perm, items)) G = Group(perms, items) print(len(G)) print(G.is_cyclic()) def div(a, b): # a/b = c mod p # a = c*b mod p assert 0 <= a < p assert 0 < b < p for c in range(p): if a == (c * b) % p: return c assert 0
def make_cyclic(n, check=False): R = PolynomialRing(Z) p = cyclotomic(R, n) #print(p) #print(p(R.x*2)) ring = R / p zeta = ring.x #print("zeta: %r"%zeta) izeta = zeta**(n - 1) # inverse #print(zeta, izeta) #print(zeta.conj()) #G = mulclose([zeta]) #for g in G: # print(g, end=" ") #print() #G = cayley(G) items = list(range(n)) perms = [] e = Perm(dict((i, i) for i in range(n)), items) a = Perm(dict((i, (i + 1) % n) for i in range(n)), items) perms = [e, a] for i in range(2, n): b = perms[-1] * a perms.append(b) G = Group(perms, items, check=True) # complex characters -------------------------------------------------- c_chars = [] for k in range(n): chi = dict((perms[i], zeta**(i * k)) for i in range(n)) chi = CFunc(G, chi) c_chars.append(chi) G.c_chars = c_chars for f in c_chars: for g in c_chars: r = f.dot(g) assert (f == g) == (r == 1) #print(f.dot(g), end=" ") #print() # real characters -------------------------------------------------- r_chars = [c_chars[0]] # triv if n % 2: for k in range(1, (n + 1) // 2): a = c_chars[k] + c_chars[n - k] r_chars.append(a) else: chi = dict((perms[i], (-1)**i) for i in range(n)) chi = CFunc(G, chi) r_chars.append(chi) for k in range(1, n // 2): #print("a = c_chars[k] + c_chars[n-k]") a = c_chars[k] + c_chars[n - k] r_chars.append(a) for f in r_chars: for g in r_chars: r = f.dot(g) assert (f == g) == (r != 0) #print(f.dot(g), end=" ") #print() G.r_chars = r_chars return G
def test(): ring = element.Q n = argv.get("n", 3) d = argv.get("d", 2) G = Group.symmetric(n) algebra = GroupAlgebra(G, ring) v = algebra.zero for g in G: v = v + g assert 2 * v == v + v assert v - v == algebra.zero for g in algebra.basis: assert g * v == v assert v * g == v center = algebra.get_center() for v in center: for g in algebra.basis: assert g * v == v * g # --------------------------------------- # build standard representation of symmetric group act = G.left_action(list(range(n))) #print(act) tp = Cat(G, ring) rep = Rep.mk_rep(act, tp) #rep.dump() module = algebra.extend(rep) #print(module.action(v)) # --------------------------------------- # build representation of symmetric group on tensor product space = Space(d, ring) rep = tensor_rep(G, space) #rep.check() module = algebra.extend(rep) #print(module.action(v)) # --------------------------------------- # Build the young symmetrizers projs = [] part = argv.get("part") parts = [part] if part else partitions(n) for part in parts: items = G.items A = algebra.zero for g in G: labels = [g[item] for item in items] tableau = Young(G, part, labels) P = algebra.get_symmetrizer(tableau) A = A + P #tableau = Young(G, part) #A = algebra.get_symmetrizer(tableau) print("partition:", part) #print("H:") #print(module.action(H)) #print("V:") #print(module.action(V)) print([g * A == A * g for g in algebra.basis]) specht = [] for v in algebra.basis: u = v * A specht.append(u.to_array()) hom = Space(len(G), ring).endo_hom() specht = Map.from_array(specht, hom) specht = specht.image() #print(specht) dim = specht.shape[1] print("S(n)-algebra dim:", dim) if len(part) > d: continue print("A:", A) P = module.action(A) #P = P.transpose() P = P.image() print(P.longstr()) print(P.shape) return print("multiplicity:", P.shape[1]) src = P.src for v in src.get_basis(): u = P * v #print(u.longstr()) items = [] for g in algebra.basis: g = module.action(g) w = g * u #print(w.longstr()) items.append(w) A = find_span(items) print("dimension:", A.shape[1])
def get_group(self): gens = self.get_gens() G = Group.generate(gens) return G
for j in items: if (i * j) % n: continue if i in mul: mul.remove(i) items = list(mul) items.sort() perms = [] for i in items: perm = dict((j, (j * i) % n) for j in items) perm = Perm(perm, items) perms.append(perm) G = Group(perms, items) print(" ", end="") for jdx, qerm in enumerate(perms): j = items[jdx] print("%3d" % j, end="") print() print(" ", "---" * len(items)) for idx, perm in enumerate(perms): i = items[idx] print("%3d" % i, end="") for jdx, qerm in enumerate(perms): j = items[jdx] kdx = perms.index(perm * qerm) k = items[kdx] print("%3d" % k, end="") 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 build_group(self): perms = self.generate() G = Group(perms, self.roots) return G
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 super_young(U, V, part): ring = U.ring n = sum(part) lookup = {} summands = [] for idxs in cross([(0, 1)] * n): spaces = [[U, V][idx] for idx in idxs] space = reduce(matmul, spaces) lookup[idxs] = len(summands) summands.append(space) #print(idxs, end=" ") #print(space.n) src = reduce(add, summands) G = Group.symmetric(n) hom = {} colim = src.identity() for action in G: perm = tuple(action[i] for i in range(n)) #print(perm) sumswap = [None] * len(summands) fs = [] for i, idxs in enumerate(cross([(0, 1)] * n)): jdxs = tuple(idxs[i] for i in perm) #print(idxs, "-->", jdxs) sumswap[lookup[jdxs]] = i space = src.items[i] f = space.get_swap(perm) fs.append(f) #print(sumswap) f = reduce(dsum, fs) #print(f.src.name, "-->", f.tgt.name) g = f.tgt.get_swap(sumswap) #print(g.src.name, "-->", g.tgt.name) assert f.tgt == g.src assert g.tgt == src hom[action] = (g, f) #print() young = Young(G, part) #print("Young:") #print(young) rowperms = young.get_rowperms() colperms = young.get_colperms() #print("rowperms", len(rowperms)) #print("colperms", len(colperms)) horiz = None for action in rowperms: (g, f) = hom[action] gf = g * f horiz = gf if horiz is None else (horiz + gf) assert horiz is not None vert = None for action in colperms: sign = action.sign() * ring.one g, f = hom[action] g = sign * g gf = g * f vert = gf if vert is None else (vert + gf) assert vert is not None P = horiz * vert P = P.row_reduce() #print(P.rank()) #print(P) #for a in src.items: # print(a) even = src.identity() odd = src.identity() i = 0 j = 0 for space in src.items: j += space.n while i < j: if space.grade % 2 == 0: odd[i, i] = ring.zero else: even[i, i] = ring.zero i += 1 return (P * even).rank(), (P * odd).rank()
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")
#!/usr/bin/env python3 """ Verifying that the normalizer of a subgroup is the automorphism group of the corresponding G-set. """ from bruhat.action import Group, Perm from bruhat.argv import argv G = Group.symmetric(4) print(len(G)) Hs = G.subgroups() print(len(Hs)) def setpromote(items): if isinstance(items, Perm): items = {items} else: items = set(items) for item in items: assert isinstance(item, Perm) return items def setmul(*itemss): items = itemss[0] items = setpromote(items)