Using Computational Group Theory Alexander Hulpke Department of Mathematics Colorado State University Fort Collins, CO, 80523, USA http://www.math.colostate.edu/~hulpke/villanova Let be a Group But graphs occur naturally • Domains for actions • Automorphism groups • Cayley Graphs • Geometric Group Theory Graph But interesting graphs often have symmetry groups. Groups can be used to describe graphs in compact form. Computational Group Theory What can CGT Software (main systems: Magma and GAP) do for you? Used here • Convenient Language • Memory Management, List/Set data types • Exact arithmetic: Rationals, Fin. fields, Extensions • Linear Algebra, Polynomials • Permutations, Words, User-defined objects with user-defined equality test. • Combinatorics specific packages (GRAPE, DESIGN, …) What Am I Doing Here ? I will not give a description of algorithms and methods of Computational Group Theory. But describe some calculations that can be done and describe functionality that (in my view) should be better known. Some of these calculations are potentially expensive: My time is more valuable than the computer's. ``Generalized’’ Petersen 1 2 9 8 Do the same kind of construction as for the Petersen graph, but on 2·7 vertices. 7 14 11 13 6 12 4 5 There are two options, steps 2 or 3 on the inner circle. 1 2 9 8 Naive construction with GRAPE by adding all edges to empty graph. 3 10 7 3 14 10 11 13 12 6 4 5 ``Generalized’’ Petersen 1 9 8 Do the same kind of construction as for the Petersen graph, but on 2·7 vertices. 7 14 3 10 11 13 6 12 4 5 There are two options, steps File dotgraph.g on web 2 or 3 on the inner circle. pages exports GRAPE Naive construction withformat. graphs in graphviz GRAPE by adding allinedges Arraged/Printed to empty graph. OmniGraffle on a Mac. 2 1 2 9 8 7 3 14 10 11 13 12 6 4 5 gap> LoadPackage(“grape");; Loading GRAPE 4.6.1 (GRaph Algorithms using PErmutation by Leonard H. Soicher (www.maths.qmul.ac.uk/~leonard/). gap> Gam:=NullGraph(Group(()),14); rec( adjacencies := [ [ ], [ ],[…]], group := Group(()), isGraph := true, isSimple := true, order := 14, […] ) gap> for i in [1..7] do AddEdgeOrbit(Gam,[i,i+7]); AddEdgeOrbit(Gam,[i+7,i]);od; gap> for i in [0..6] do AddEdgeOrbit(Gam,[i+1,((i+1) mod 7)+1]); AddEdgeOrbit(Gam,[((i+1) mod 7)+1,i+1]); AddEdgeOrbit(Gam,[i+8,((i+2) mod 7)+8]); AddEdgeOrbit(Gam,[((i+2) mod 7)+8,i+8]); od; gap> au:=AutomorphismGroup(Gam); Group([ (2,7)(3,6)(4,5)(9,14)(10,13)(11,12), (1,2)(3,7)(4,6)(8,9)(10,14)(11,13) ]) gap> Orbits(au,[1..14]); [ [ 1, 2, 7, 3, 6, 4, 5 ], [ 8, 9, 14, 10, 13, 11, 12 ] ] gap> Size(Action(au,[1..7])); 14 Working With Groups • Assume that Arithmetic for Elements is available • Groups are given by a generating set, storage size roughly log |G|. • Basic operations (using data structures): • Order / Index • Constructive Membership: Test membership, evaluate homomorphisms given on generators. This Means In Practice • Building the data structures initially takes time. • How a group is represented can have huge influence on how well a calculation works. • If you fall back in a generic routine (enumerating elements), this can waste memory and runtime. Interdependence Black Box Forcing a Representation • Constructors allow to prescribe a representation: CyclicGroup(IsPermGroup,10); • The commands IsomorphismXXXGroup create a homomorphism that converts from one representation to another: iso:=IsomorphismPcGroup(permgrp); • Products of group in different representations may degrade to a generic representation. Paradigms • Work with generators, not element lists • O Classify up to conjugacy — Orbit algorithm • Generator number grows with index • Use (pseudo-)random elements, verify results Composition Series becomes the key operation. S‣ Reduce to Subgroups. H ‣ Homomorphisms (Solvable Radical, Trivial Fitting) • ‣ Reduce to case of kernel being vector space. O Orbit/Stabilizer Algorithm Find orbit ∆ =ωG of point, generators for stabilizer, Representatives for ωg= δ. T is transversal, or transporter. • Schreier vector for T • Cost is in γ∈∆, T [γ]: Dictionaries, Data-type specific code. • Remove redundant generators! • Backtrack code for a few permutation group actions. ∆ := [ω];T:=[1];S:=⟨1⟩; for δ ∈ ∆ do for i ∈ {1,...,m} do γ := δgi; if γ∉ ∆ then Append γ to ∆; Append T[δ]·gi to T; else S:=⟨S, T [δ]·gi /T [γ]⟩; fi; od; od; return ∆; More Orbits Orbit-style functions in GAP allow for: • Action implemented by a (user) function. • Action by images of the generators (e.g. permutation group acting linearly) • Homomorphisms to Sn, given by action. • If stabilizers are of large index, try to find intermediate subgroups (block stabilizers?) first. gap> g:=MathieuGroup(12);;S12:=SymmetricGroup(12); gap> sets:=Combinations([1..12],6);; gap> orb:=OrbitsDomain(g,sets,OnSets);;List(orb,Length); [ 792, 132 ] gap> Stabilizer(S12,orb[2],OnSetsSets); Error, Action not well-defined. […] ! gap> Stabilizer(S12,Set(orb[2]),OnSetsSets); Group([ (1,11,10,9,8,7,6,5,4,3,2),(1,2,12, […]]) gap> Size(last); 95040 ! ! ! Tutte-Coxeter Graph gap> duads:=Combinations([1..6],2);;Length(duads); 15 gap> synthemes:=Filtered(Combinations(duads,2), > x->1 in x[1] and Size(Intersection(x[1],x[2]))=0); gap> synthemes:=Set(List(synthemes, > x->Union(x,[Difference([1..6],Union(x[1],x[2]))]))); gap> tc:=Graph(Group(()),Union(duads,synthemes), function(x,g) return x;end, > function(a,b) return a in b or b in a;end);; gap> Length(UndirectedEdges(tc)); 45 gap> Diameter(tc); 4 gap> Girth(tc); 8 gap> au:=AutomorphismGroup(tc);;Size(au); 1440 gap> IsDistanceRegular(tc); true Tutte-Coxeter Graph gap> duads:=Combinations([1..6],2);;Length(duads); 15 gap> synthemes:=Filtered(Combinations(duads,2), > x->1 in x[1] and Size(Intersection(x[1],x[2]))=0); gap> synthemes:=Set(List(synthemes, > x->Union(x,[Difference([1..6],Union(x[1],x[2]))]))); gap> tc:=Graph(Group(()),Union(duads,synthemes), function(x,g) return x;end, > function(a,b) return a in b or b in a;end);; gap> Length(UndirectedEdges(tc)); 45 gap> Diameter(tc); 4 gap> Girth(tc); 8 gap> au:=AutomorphismGroup(tc);;Size(au); 1440 gap> IsDistanceRegular(tc); true [ [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 1, 5 ], [ 1, 6 ], [ 2, 3 ], [ 2, 4 ], [ 2, 5 ], [ 2, 6 ], [ 3, 4 ], [ 3, 5 ], [ 3, 6 ], [ 4, 5 ], [ 4, 6 ], [ 5, 6 ] ] Tutte-Coxeter Graph gap> duads:=Combinations([1..6],2);;Length(duads); 15 gap> synthemes:=Filtered(Combinations(duads,2), > x->1 in x[1] and Size(Intersection(x[1],x[2]))=0); gap> synthemes:=Set(List(synthemes, > x->Union(x,[Difference([1..6],Union(x[1],x[2]))]))); gap> tc:=Graph(Group(()),Union(duads,synthemes), function(x,g) return x;end, > function(a,b) return a in b or b in a;end);; gap> Length(UndirectedEdges(tc)); 45 gap> Diameter(tc); 4 gap> Girth(tc); 8 gap> au:=AutomorphismGroup(tc);;Size(au); 1440 gap> IsDistanceRegular(tc); true [[[1,2],[3,4],[5,6]], [[1,2],[3,5],[4,6]], [[1,2],[3,6],[4,5]], [[1,3],[2,4],[5,6]], [[1,3],[2,5],[4,6]], [[1,3],[2,6],[4,5]], [[1,4],[2,3],[5,6]], [[1,4],[2,5],[3,6]], [[1,4],[2,6],[3,5]], [[1,5],[2,3],[4,6]], [[1,5],[2,4],[3,6]], [[1,5],[2,6],[3,4]], [[1,6],[2,3],[4,5]], [[1,6],[2,4],[3,5]], [[1,6],[2,5],[3,4]]] gap> w:=WreathProduct(SymmetricGroup(6),Group((1,2))); Group([ (1,2,3,4,5,6), (1,2), (7,8,9,10,11,12), (7,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12) ]) gap> IsomorphicSubgroups(w,au); [[(2,4,5,3)(6,8,9,7)(10,11,15,14)[…] ] -> [(3,4,5,6)(7,8,9,11),(1,7)(2,8)(3,9)(4,10)(5,11)(6,12)]] ! gap> b:=Blocks(au,MovedPoints(au)); gap> beta:=ActionHomomorphism(au,b,OnSets,”surjective");; gap> u:=Stabilizer(au,b[1],OnSets);; gap> m:=MaximalSubgroupClassReps(u);; gap> List(m,x->Index(u,x)); [ 2, 15, 6, 15, 10, 6 ] gap> alpha:=FactorCosetAction(u,m[3]); <action epimorphism> gap> KuKGenerators(au,beta,alpha); [ (1,6)(2,4)(7,12)(8,10), (2,4)(3,5)(7,8)(10,12), […] ] gap> GroupHomomorphismByImages(au,Group(last), GeneratorsOfGroup(au),last);; H Homomorphisms Three ways to construct homomorphisms: 1. By giving group generators and their images under the homomorphism: GroupHomomorphismByImagesNC 2. By acting on a set of objects, obtaining permutation images ActionHomomorphism( […] ,”surjective”); 3. Functions to find homomorphisms with given • Kernel: NaturalHomomorphismByNormalSubgroupNC • Image (all): GQuotients • Source and injective (all): IsomorphicSubgroups S Finding Subgroups ConjugacyClassesSubgroups exists. Uses data base of simple groups. Limited scope (storage!) Otherwise try to restrict: G • Sylow/Hall subgroup NU • Maximal Subs. (MaximalSubgroupClassReps) • Orbit or block stabilizers • Subgroup in homomorphic image • If kernel intersection known, complement (or correct generators with N). N U N∩U 〈1〉 Construction In Parts Construct all objects combined from two parts, Ω and Δ, automorphism groups are respectively G and H. Ω Select the joining parts ω∈Ω, δ∈Δ up to ω=δ action of G, let A=StabG(ω). Ditto B=StabH(δ). If K is the group of symmetries of the possible combinations, both A and B induce subgroups. The G x H orbits of combinations correspond to double cosets A\K/B. Δ Intransitive Groups Let U be intransitive on Ω∪Δ with projections α:U→A≤SΩ, β:U→B≤SΔ. Images chosen up to SΩ, SΔ conjugacy. A α U β ker β ker α 〈1〉 B Intransitive Groups Let U be intransitive on Ω∪Δ with projections α:U→A≤SΩ, β:U→B≤SΔ. Images chosen up to SΩ, SΔ conjugacy. D=(ker β)α⊲A and E=(ker α)β⊲B. A α U β D 〈1〉 B E ker β ker α 〈1〉 〈1〉 Intransitive Groups Let U be intransitive on Ω∪Δ with projections α:U→A≤SΩ, β:U→B≤SΔ. Images chosen up to SΩ, SΔ conjugacy. D=(ker β)α⊲A and E=(ker α)β⊲B. χ: A/D→B/E isom. of factor groups A/D A 〈1〉 D 〈1〉 α U β ker β ker α 〈1〉 B B/E E 〈1〉 〈1〉 Intransitive Groups Let U be intransitive on Ω∪Δ with projections α:U→A≤SΩ, β:U→B≤SΔ. Images chosen up to SΩ, SΔ conjugacy. D=(ker β)α⊲A and E=(ker α)β⊲B. χ: A/D→B/E isom. of factor groups χ A/D A 〈1〉 D 〈1〉 Possible isomorphisms A/D→B/E correspond to Aut(A/D), if any exist. α U β ker β ker α 〈1〉 B B/E E 〈1〉 〈1〉 Intransitive Groups To construct all such groups, select • A≤SΩ, B≤SΔ up to conjugacy. • Select D⊲A up to NSΩ(A)-conjugacy. A/D • • • Ditto E⊲B such that A/D≅B/E. 〈1〉 χ A α U β D 〈1〉 ker β ker α χ from representatives of N(D) \ Aut(A/D) / N(E) . Not covered: Swap Ω and Δ. 〈1〉 B B/E E 〈1〉 〈1〉 GAP function intransitive.g IntransitiveGroups:=function(A,B) local gps,SOm,NA,SDe,NB,P,emb,D,qd,f,E,qe,iso,au,gens,auperm,dc,chi,new; gps:=[]; SOm:=SymmetricGroup(MovedPoints(A)); NA:=Normalizer(SOm,A); SDe:=SymmetricGroup(MovedPoints(B)); NB:=Normalizer(SDe,B); P:=DirectProduct(SOm,SDe); emb:=List([1,2],x->Embedding(P,x)); for D in SubgroupsOrbitsAndNormalizers(NA,NormalSubgroups(A),false) do qd:=NaturalHomomorphismByNormalSubgroup(A,D.representative); f:=Image(qd); gens:=GeneratorsOfGroup(f); for E in SubgroupsOrbitsAndNormalizers(NB,NormalSubgroups(B),false) do qe:=NaturalHomomorphismByNormalSubgroup(B,E.representative); iso:=IsomorphismGroups(Image(qd),Image(qe)); if iso<>fail then au:=AutomorphismGroup(f); auperm:=IsomorphismPermGroup(au); for dc in DoubleCosetRepsAndSizes(Image(auperm), Subgroup(Image(auperm), List(GeneratorsOfGroup(D.normalizer), g->ImagesRepresentative(auperm, GroupHomomorphismByImages(f,f,gens, List(gens,x->Image(qd, PreImagesRepresentative(qd,x)^g)))))), Subgroup(Image(auperm), List(GeneratorsOfGroup(E.normalizer), g->ImagesRepresentative(auperm, GroupHomomorphismByImages(f,f,gens, List(gens,x->PreImagesRepresentative(iso,Image(qe, PreImagesRepresentative(qe, Image(iso,x))^g))))))) ) do chi:=PreImagesRepresentative(auperm,dc[1])*iso; # construct one product, embedded into P: # Generators for A, fused for A/D, together # with generators for E new:=List(GeneratorsOfGroup(A),x->Image(emb[1],x)* Image(emb[2],PreImagesRepresentative(qe, Image(chi,Image(qd,x))))); Append(new,List(GeneratorsOfGroup(E.representative), x->Image(emb[2],x))); Add(gps,Subgroup(P,new)); od; fi; od; od; return gps; end; gap> IntransitiveGroups(SymmetricGroup(4), SymmetricGroup(3)); [ Group([ (1,2,3,4)(5,6), (1,2)(6,7) ]), Group([ (1,2,3,4)(6,7), (1,2)(6,7), (5,6,7) ]), Group([ (1,2,3,4), (1,2), (5,6,7), (5,6) ]) ] gap> List(last,Size); [ 24, 72, 144 ] ! gap> as:=AllTransitiveGroups(NrMovedPoints,4);; gap> bs:=AllTransitiveGroups(NrMovedPoints,3);; gap> r:=Concatenation(List(Cartesian(as,bs), x->IntransitiveGroups(x[1],x[2])));; gap> Collected(List(r,Size)); [ [12,5], [24,7], [36,1], [48,1], [72,3], [144,1] ] ! gap> u:=ConjugacyClassesSubgroups(SymmetricGroup(7));; gap> u:=List(u,Representative);; gap> s:=Filtered(u, x->Set(List(Orbits(x,[1..7]),Length))=[3,4]); gap> Collected(List(s,Size)); [ [12,5], [24,7], [36,1], [48,1], [72,3], [144,1] ] Own Objects Create your own objects with their own arithmetic: DeclareCategory("IsMyCategory",IsMultiplicativeElementWithInverse); MyFam:=NewFamily("MyFam",IsMultiplicativeElementWithInverse, IsMultiplicativeElementWithInverse,IsObject); DeclareRepresentation(“IsMyRep",IsPositionalObjectRep and IsMyCategory,[]); ! MyObj:=function(r,i) if r=0 and i=0 then Error("zero");fi; return Objectify(NewType(MyFam,IsMyCategory and IsMyRep), [r,i]); end; ! InstallMethod(PrintObj,"Identifier String",true,[IsMyRep],0, function(o) Print("MyObj(",o![1],",",o![2],")"); end); InstallMethod(OneOp,"mine",true,[IsMyRep],0, function (a) return MyObj(1,0); end); ! InstallMethod(\*,"mine",true,[IsMyRep,IsMyRep],0, function (a,b) return MyObj(a![1]*b![1]-a![2]*b![2],a![1]*b![2]+a![2]*b![1]); end); ! InstallMethod(InverseOp,"mine",true,[IsMyRep],0, function (a) local n; n:=a![1]^2+a![2]^2; return MyObj(a![1]/n,-a![2]/n); end); ! InstallMethod(\=,"mine",true,[IsMyRep,IsMyRep],0, function (a,b) return a![1]=b![1] and a![2]=b![2]; end); ! InstallMethod(\<,"mine",true,[IsMyRep,IsMyRep],0, function (a,b) return a![1]<b![1] or (a![1]=b![1] and a![2]<b![2]); end); gap> Read("myobj.g"); gap> a:=MyObj(0,1); MyObj(0,1) gap> b:=MyObj(3,2); MyObj(3,2) gap> a/b; MyObj(2/13,3/13) gap> a^17=a; true gap> b^40; MyObj(-794950134656302081199,-18988330689345532174800) gap> g:=Group(a); #I default `IsGeneratorsOfMagmaWithInverses’ method returns `true' for [ MyObj(0,1) ] <group with 1 generators> gap> Size(g); 4 gap> IsomorphismPcGroup(g); [ MyObj(0,1) ] -> [ f1 ] gap> Elements(g); [ MyObj(-1,0), MyObj(0,-1), MyObj(0,1), MyObj(1,0) ] Matrix Group Recognition The default code for matrix groups currently still uses a faithful permutation action (on vectors). This is problematic, as orbits can be very long. Matrix Group Recognition, instead uses the group structure. It is not yet used by default. The basic idea is to decompose the group into simple factors, using homomorphisms based on group actions. Composition Tree Group represented by homomorphisms. ! . N = ker ⇤ G with ⇥ ! . & Image(⇥) ! ker ⇥ N ! G with ⇤ & F = Image(⇤) with . & ker F Image( ) At each node, we can evaluate the homomorphism. The recog package in GAP provides a concrete implementation of the process. Solvable Radical / Trivial Fitting Consider homomorphism by action on nonabelian composition factors Ti . Kernel R=Rad(G ) largest solvable normal. Image G/R < Aut(S */R ) ×i Aut(Ti )≀Ski where S */R = Soc(G/R ) is permutation group. G Pker S* R R can be represented by polycyclic presentation. Many algorithms use this data structure. ⟨1⟩ gap> Read(“recogradical.g"); [Packages forms, orb, genes, AtlasRep, recog, recogbase] gap> g:=AtlasSubgroup("Th",3); <matrix group of size 92897280 with 2 generators> gap> ff:=FittingFreeLiftSetup(g);; gap> Image(ff.factorhom); <permutation group of size 181440 with 11 generators> gap> Length(ff.pcgs); 9 gap> Length(ConjugacyClasses(g)); 52 gap> m:=MaximalSubgroupClassReps(g);; gap> List(m,x->Size(g)/Size(x)); # not use Index [ 126, 84, 36, 9, 280, 840, 120, 120 ]