1############################################################################# 2## 3## This file is part of GAP, a system for computational discrete algebra. 4## This file's authors include Werner Nickel, Alexander Hulpke. 5## 6## Copyright of GAP belongs to its developers, whose names are too numerous 7## to list here. Please refer to the COPYRIGHT file for details. 8## 9## SPDX-License-Identifier: GPL-2.0-or-later 10## 11## This file contains the implementation of the methods for SchurMultiplier 12## and Darstellungsgruppen. 13## 14 15## Take a finite presentation F/R for a group G and compute a presentation 16## of one of G's representation groups (Darstellungsgruppen, Schur covers). 17## This is done by assembling a presentation for F/[R,F] and then finding a 18## generating set for a complement C/[R,F] for the intersection of R and 19## [F,F] in R/[R,F]. 20## 21## No attempt is made to reduce the number of generators in the 22## presentation. This can be done using the Tietze routines from the GAP 23## library. 24 25BindGlobal("SchurCoverFP",function( G ) 26local g, i, m, n, r, D, I, M, M2,fgens,rels,gens,Drels,nam; 27 28 fgens:=FreeGeneratorsOfFpGroup(G); 29 rels:=RelatorsOfFpGroup(G); 30 n := Length( fgens ); 31 m := Length( rels ); 32 nam:=List(fgens,String); 33 if not ForAny(nam,x->'k' in x) then 34 r:="k"; 35 else 36 r:=First(Concatenation(CHARS_LALPHA,CHARS_UALPHA), 37 x->not ForAny(nam,y->x in y)); 38 if r=fail then 39 r:="extra"; # unlikely to have the same name, will just print weirdly 40 # but not calculate wrongly 41 else 42 r:=[r]; 43 fi; 44 fi; 45 46 for i in [1..m] do 47 Add(nam,Concatenation(r,String(i))); 48 od; 49 50 D := FreeGroup(nam); 51 gens:=GeneratorsOfGroup(D); 52 Drels := []; 53 for i in [1..m] do 54 r := rels[i]; 55 Add(Drels, MappedWord( r, fgens, gens{[1..n]} ) / gens[n+i] ); 56 od; 57 for g in gens{[1..n]} do 58 for r in gens{[n+1..n+m]} do 59 Add( Drels, Comm( r, g ) ); 60 od; 61 od; 62 63 M := []; 64 for r in rels do 65 Add( M, List( fgens, g->ExponentSumWord( r, g ) ) ); 66 od; 67 68 M{[1..m]}{[n+1..n+m]} := IdentityMat(m); 69 M := HermiteNormalFormIntegerMat( M ); 70 M:=Filtered(M,i->not IsZero(i)); 71 72 r := 1; i := 1; 73 while r <= m and i <= n do 74 while i <= n and M[r][i] = 0 do 75 i := i+1; 76 od; 77 if i <= n then r := r+1; fi; 78 od; 79 r := r-1; 80 81 if r > 0 then 82 M2 := M{[1..r]}{[n+1..n+m]}; 83 M2 := HermiteNormalFormIntegerMat( M2 ); 84 M2:=Filtered(M2,i->not IsZero(i)); 85 for i in [1..Length(M2)] do 86 Add(Drels,LinearCombinationPcgs(gens{[n+1..n+m]},M2[i])); 87 od; 88 fi; 89 90 # make the group 91 D:=D/Drels; 92 return D; 93end); 94 95InstallMethod(SchurCover,"of fp group",true,[IsSubgroupFpGroup],0, 96 SchurCoverFP); 97 98InstallMethod(EpimorphismSchurCover,"generic, via fp group",true,[IsGroup],1, 99 function(G) 100 local iso, 101 hom, 102 F,D,p,gens,Fgens,Dgens; 103 104 ## Check to see if G is trivial -- if so then just return 105 ## the map from the trivial FP group and G. 106 if IsTrivial(G) then 107 F := FreeGroup(1); 108 D := F/[F.1]; 109 return GroupHomomorphismByImages( 110 D, G, 111 GeneratorsOfGroup(D), AsSSortedList(G)); 112 fi; 113 ## 114 ## 115 iso:=IsomorphismFpGroup(G); 116 F:=ImagesSource(iso); 117 Fgens:=GeneratorsOfGroup(F); 118 D:=SchurCoverFP(F); 119 120 # simplify the fp group 121 p:=PresentationFpGroup(D); 122 Dgens:=GeneratorsOfPresentation(p); 123 TzInitGeneratorImages(p); 124 TzOptions(p).printLevel:=0; 125 TzGo(p); 126 D:=FpGroupPresentation(p); 127 gens:=TzPreImagesNewGens(p); 128 Dgens:=List(gens,i->MappedWord(i,Dgens, 129 Concatenation(Fgens,List([1..(Length(Dgens)-Length(Fgens))], 130 j->One(F))))); 131 132 hom:=GroupHomomorphismByImagesNC(D,G,GeneratorsOfGroup(D), 133 List(Dgens,i->PreImagesRepresentative(iso,i))); 134 Dgens:=TzImagesOldGens(p); 135 Dgens:=List(Dgens{[Length(Fgens)+1..Length(Dgens)]}, 136 i->MappedWord(i,p!.generators,GeneratorsOfGroup(D))); 137 SetKernelOfMultiplicativeGeneralMapping(hom,SubgroupNC(D,Dgens)); 138 139 return hom; 140end); 141 142 143# compute commutators and their images so that we know the image on `mul', 144# create out relations v=v^g. 145BindGlobal("CommutGenImgs",function(pcgs,g,h,mul) 146local u,a,b,i,j,c,x,y; 147 u:=TrivialSubgroup(mul); 148 a:=[]; 149 b:=[]; 150 x:=One(mul); 151 y:=One(h[1]); 152 repeat 153 for i in [1..Length(g)] do 154 for j in [1..i-1] do 155 c:=Comm(g[i],g[j]^x); 156 if not c in u then 157 Add(a,c); 158 Add(b,Comm(h[i],h[j]^y)); 159 u:=ClosureGroup(u,c); 160 if IsSubgroup(u,mul) then 161 a:=CanonicalPcgsByGeneratorsWithImages(pcgs,a,b); 162 return List(GeneratorsOfGroup(mul), 163 i->i/PcElementByExponentsNC(a[2],ExponentsOfPcElement(a[1],i))); 164 fi; 165 fi; 166 od; 167 od; 168 #in rare cases we also need commutators of conjugates. 169 if Size(mul)=1 then 170 return []; 171 else 172 Info(InfoSchur,2,"the commutators do not generate!"); 173 i:=Random(1,Length(g)); 174 x:=x*g[i]; 175 y:=y*h[i]; 176 fi; 177 until false; 178end); 179 180InstallGlobalFunction(SchuMu,function(g,p) 181local s,pcgs,n,iso,H,l,cov,der,pco,ng,gens,imgs,ran,zer,i,j,e,a, 182 mult,rels,de,epi,mul,hom,dc,q,qs,mq; 183 s:=SylowSubgroup(g,p); 184 if IsCyclic(s) then 185 return InverseGeneralMapping(IsomorphismPcGroup(s)); 186 fi; 187 188 pcgs:=Pcgs(s); 189 n:=Normalizer(g,s); 190 l:=LogInt(Size(s),p); 191 192 # compute a Darstellungsgruppe as PC-Group 193 de:=EpimorphismSchurCover(s); 194 195 # exponent of M(G) is at most p^(n/2) 196 epi:=EpimorphismPGroup(Source(de),p,PClassPGroup(s)+Int(l/2)); 197 cov:=Range(epi); 198 mul:=Image(epi,KernelOfMultiplicativeGeneralMapping(de)); 199 if Size(mul)=1 then 200 return InverseGeneralMapping(IsomorphismPcGroup(s)); 201 fi; 202 203 # get a decent pcgs for the cover 204 pco:=List(pcgs,i->Image(epi,PreImagesRepresentative(de,i))); 205 Append(pco,Pcgs(mul)); 206 pco:=PcgsByPcSequenceNC(FamilyObj(One(cov)),pco); 207 208 # the induced action of n on the derived subgroup of the cover: 209 # we prescribe images on the commutator factor group. These may not be 210 # entirely correct -- multiplicator elements are missing. However on [G,G] 211 # they are unique -- the wrong central parts cancel out 212 # (use Burnside's basis theorem) 213 214 der:=DerivedSubgroup(cov); 215 ng:=GeneratorsOfGroup(n); 216 gens:=[]; 217 imgs:=List(ng,i->[]);; 218 ran:=[1..Length(pcgs)]; 219 zer:=ListWithIdenticalEntries(Length(pco)-Length(pcgs),0); 220 for i in pco do 221 Add(gens,i); 222 a:=PcElementByExponentsNC(pcgs,ExponentsOfPcElement(pco,i){ran}); 223 for j in [1..Length(ng)] do 224 e:=ExponentsOfPcElement(pcgs,a^ng[j]); 225 Append(e,zer); 226 Add(imgs[j],PcElementByExponentsNC(pco,e)); 227 od; 228 od; 229 230 # now we add new relators: x^g=x for all central x 231 rels:=TrivialSubgroup(cov); 232 for j in [1..Length(ng)] do 233 # extend homomorphically 234 rels:=ClosureGroup(rels,CommutGenImgs(pco,gens,imgs[j],mul)); 235 od; 236 237 if Size(rels)=Size(mul) then 238 # total vanish 239 return InverseGeneralMapping(IsomorphismPcGroup(s)); 240 fi; 241 242 # form the quotient, make it the new cover and the new multiplicator. 243 hom:=NaturalHomomorphismByNormalSubgroupNC(cov,rels); 244 mul:=Image(hom,mul); 245 cov:=Image(hom,cov); 246 pco:=List(pco{[1..Length(pcgs)]},i->Image(hom,i)); 247 Append(pco,Pcgs(mul)); 248 pco:=PcgsByPcSequenceNC(FamilyObj(One(cov)),pco); 249 epi:=GroupHomomorphismByImagesNC(cov,s,pco, 250 Concatenation(pcgs,List(Pcgs(mul),i->One(s)))); 251 SetKernelOfMultiplicativeGeneralMapping(epi,mul); 252 253 # now extend to the full group 254 rels:=TrivialSubgroup(cov); 255 dc:=List(DoubleCosetRepsAndSizes(g,n,n),i->i[1]); 256 i:=1; 257 while i<=Length(dc) and Index(mul,rels)>1 do 258 if Order(dc[i])>1 then # the trivial element will not do anything 259 q:=Intersection(s,ConjugateSubgroup(s,dc[i]^-1)); 260 if Size(q)>1 then 261 qs:=PreImage(epi,q); 262 # factor generators 263 gens:=GeneratorsOfGroup(qs); 264 # their conjugates 265 imgs:=List(gens,j->PreImagesRepresentative(epi,Image(epi,j)^dc[i])); 266 rels:=ClosureGroup(rels,CommutGenImgs(pco,gens,imgs, 267 Intersection(mul,DerivedSubgroup(qs)))); 268 fi; 269 fi; 270 i:=i+1; 271 od; 272 hom:=NaturalHomomorphismByNormalSubgroupNC(cov,rels); 273 mul:=Image(hom,mul); 274 cov:=Image(hom,cov); 275 pco:=List(pco{[1..Length(pcgs)]},i->Image(hom,i)); 276 Append(pco,Pcgs(mul)); 277 pco:=PcgsByPcSequenceNC(FamilyObj(One(cov)),pco); 278 epi:=GroupHomomorphismByImagesNC(cov,s,pco, 279 Concatenation(pcgs,List(Pcgs(mul),i->One(s)))); 280 SetKernelOfMultiplicativeGeneralMapping(epi,mul); 281 return epi; 282 283end); 284 285InstallMethod(AbelianInvariantsMultiplier,"naive",true, 286 [IsGroup],1, G->AbelianInvariants(KernelOfMultiplicativeGeneralMapping(EpimorphismSchurCover(G)))); 287 288InstallMethod(AbelianInvariantsMultiplier,"via Sylow Subgroups",true, 289 [IsGroup],0, 290function(G) 291local a,f,i; 292 Info(InfoWarning,1,"Warning: AbelianInvariantsMultiplier via Sylow subgroups is under construction"); 293 a:=[]; 294 f:=Filtered(Collected(Factors(Size(G))),i->i[2]>1); 295 for i in f do 296 Append(a,AbelianInvariants(KernelOfMultiplicativeGeneralMapping( 297 SchuMu(G,i[1])))); 298 od; 299 return a; 300end); 301 302# <hom> is a homomorphism from a finite group onto an fp group. It returns 303# an isomorphism from the same group onto an isomorphic fp group <F>, such 304# that no negative exponent occurs in the relators of <F>. 305# 306BindGlobal("PositiveExponentsPresentationFpHom",function(hom) 307local G,F,geni,ro,fam,r,i,j,rel,n,e; 308 G:=Image(hom); 309 F:=FreeGeneratorsOfFpGroup(G); 310 geni:=List(GeneratorsOfGroup(G),i->PreImagesRepresentative(hom,i)); 311 ro:=List(geni,Order); 312 fam:=FamilyObj(F[1]); 313 r:=[]; 314 for i in RelatorsOfFpGroup(G) do 315 rel:=[]; 316 for j in [1..NrSyllables(i)] do 317 n:=GeneratorSyllable(i,j); 318 Add(rel,n); 319 e:=ExponentSyllable(i,j); 320 if e<0 then 321 e:=e mod ro[n]; 322 fi; 323 Add(rel,e); 324 od; 325 Add(r,ObjByExtRep(fam,rel)); 326 od; 327 # ensure the relative orders are relators. 328 for i in [1..Length(ro)] do 329 if not F[i]^ro[i] in r then 330 Add(r,F[i]^ro[i]); 331 fi; 332 od; 333 # new fp group 334 F:=FreeGroupOfFpGroup(G)/r; 335 hom:=GroupHomomorphismByImagesNC(Source(hom),F,geni,GeneratorsOfGroup(F)); 336 return hom; 337end); 338 339InstallGlobalFunction(CorestEval,function(FG,s) 340# This has plenty of space for optimization. 341local G,H,D,T,i,j,k,l,a,h,nk,evals,rels,gens,r,np,g,invlist,el,elp,TL,rp,pos; 342 343 G:=Image(FG); 344 H:=Image(s); 345 D:=Source(s); 346 Info(InfoSchur,2,"lift index:",Index(G,H)); 347 T:=RightTransversal(G,H); 348 TL:=List(T,i->i); # we need to refer to the elements very often 349 350 rels:=RelatorsOfFpGroup(Source(FG)); 351 gens:=List(GeneratorsOfGroup(Source(FG)),i->Image(FG,i)); 352 353 # this will guarantee we always take the same preimages 354 el:=AsSSortedListNonstored(H); 355 elp:=List(el,i->PreImagesRepresentative(s,i)); 356 #ensure the preimage of identity is one 357 if IsOne(el[1]) then 358 pos:=1; 359 else 360 pos:=Position(el,One(H)); 361 fi; 362 elp[pos]:=One(elp[pos]); 363 364 # deal with inverses 365 invlist:=[]; 366 for g in gens do 367 h:=One(D); 368 for k in T do 369 np:=k*g; 370 nk:=TL[PositionCanonical(T,np)]; 371 h:= h*elp[Position(el,np/nk)]*elp[Position(el,nk/g/k)];; 372 od; 373 Add(invlist,h); 374 od; 375 376 evals:=[]; 377 378 for rp in [1..Length(rels)] do 379 380 CompletionBar(InfoSchur,2,"Relator Loop: ",rp/Length(rels)); 381 r:=rels[rp]; 382 i:=LetterRepAssocWord(r); 383 a:=One(D); 384 385 # take care of inverses 386 for l in [1..Length(i)] do 387 if i[l]<0 then 388 #i[l]:=-i[l]; 389 a:=a*invlist[-i[l]]; 390 fi; 391 od; 392 393 for j in [1..Length(T)] do 394 395 k:=T[j]; 396 h:=One(D); 397 for l in i do 398 if l<0 then 399 g:=Inverse(gens[-l]); 400 else 401 g:=gens[l]; 402 fi; 403 np:=k*g; 404 nk:=TL[PositionCanonical(T,np)]; 405 #h:=h*PreImagesRepresentative(s,np/nk); 406 h:=h*elp[Position(el,np/nk)]; 407 k:=nk; 408 od; 409 410 #Print(PreImagesRepresentative(s,Image(s,h))*h,"\n"); 411 #a:=a/PreImagesRepresentative(s,Image(s,h))*h; 412 a:=a/h*elp[Position(el,Image(s,h))]; 413 414 od; 415 Add(evals,[r,a]); 416 od; 417 CompletionBar(InfoSchur,2,"Relator Loop: ",false); 418 return evals; 419end); 420 421InstallGlobalFunction(RelatorFixedMultiplier,function(hom,p) 422local G,B,P,F,FH,U,s,D,shom,i,j,v,r,ri,iso,rank,bas,basr,row,rel,sol, 423 Dg,Dgi,car,dgh,snf,mat; 424 G:=Source(hom); 425 rank:=Length(GeneratorsOfGroup(G)); 426 B:=ImagesSource(hom); 427 P:=SylowSubgroup(B,p); 428 # the corresponding free group (where the relators live) 429 F:=FreeGroupOfFpGroup(G); 430 FH:=GroupHomomorphismByImagesNC(F,B,FreeGeneratorsOfFpGroup(G), 431 List(GeneratorsOfGroup(G),i->Image(hom,i))); 432 433 s:=SchuMu(B,p); 434 D:=Source(s); 435 ri:=CorestEval(hom,s); 436 437 # now rel is a list of relators and their images in M(B). 438 # find relator relations in F/F' and evaluate these in M(B) to find 439 # M_R(B). 440 bas := []; 441 basr := []; 442 mat:=[]; 443 for rel in ri do 444 row := ListWithIdenticalEntries(rank,0); 445 for i in [1..NrSyllables(rel[1])] do 446 j := GeneratorSyllable(rel[1],i); 447 row[j]:=row[j]+ExponentSyllable(rel[1],i); 448 od; 449 Add(mat,row); 450 od; 451 # SNF 452 snf:=NormalFormIntMat(mat,15); 453 mat:=mat*snf.coltrans; # changed coordinates (parent presentation) 454 bas:=snf.rowtrans*mat; 455 v:=Filtered([1..Length(bas)],i-> not IsZero(bas[i])); 456 # express the basis elements 457 bas:=bas{v}; 458 basr:=[]; 459 for i in v do 460 rel:=One(Source(s)); 461 for j in [1..Length(mat)] do 462 rel:=rel*ri[j][2]^snf.rowtrans[i][j]; 463 od; 464 Add(basr,rel); 465 od; 466 467 # now collect relations 468 v:=TrivialSubgroup(D); 469 for i in [1..Length(mat)] do 470 sol:=SolutionMat(bas,mat[i]); 471 rel:=ri[i][2]; 472 for j in [1..Length(sol)] do 473 rel:=rel/basr[j]^sol[j]; 474 od; 475 if not rel in v then 476 #NC is safe 477 v:=ClosureSubgroupNC(v,rel); 478 fi; 479 od; 480 481 for i in basr do 482 for j in basr do 483 # NC is safe 484 v:=ClosureSubgroupNC(v,Comm(i,j)); 485 od; 486 od; 487 488 Info(InfoSchur,1,"Extra central part:", 489 Index(KernelOfMultiplicativeGeneralMapping(s),v)); 490 # form the quotient 491 j:=NaturalHomomorphismByNormalSubgroupNC(D,v); 492 i:=GeneratorsOfGroup(Image(j)); 493 i:=GroupHomomorphismByImagesNC(Image(j),P,i, 494 List(i,k->ImageElm(s,PreImagesRepresentative(j,k)))); 495 SetKernelOfMultiplicativeGeneralMapping(i, 496 Image(j,KernelOfMultiplicativeGeneralMapping(s))); 497 return i; 498 499end); 500 501BindGlobal("MulExt",function(G,pl) 502local hom, #isomorphism fp 503 ng,ngl, # nr generators,list 504 s,sl, # SchuMu,list 505 ab,ms, # abelian invariants, multiplier size 506 pll, # relevant primes 507 F, # free group 508 rels, # relators 509 rel2, # cohomology relators 510 ce, # corestriction 511 p,pp, # prime, index 512 mg, # multiplier generators 513 sdc, # decomposition function 514 gens,free,# generators 515 i,j, # loop 516 q,qhom; # quotient 517 518 519 520 # eliminate useless primes 521 pl:=Intersection(pl, 522 List(Filtered(Collected(Factors(Size(G))),i->i[2]>1),i->i[1])); 523 524 hom:=IsomorphismFpGroup(G); 525 hom:=hom*IsomorphismSimplifiedFpGroup(Image(hom)); 526 Info(InfoSchur,2,Length(RelatorsOfFpGroup(Range(hom)))," relators"); 527 528 # think positive... 529 #if SYF then 530 # hom:=PositiveExponentsPresentationFpHom(hom); 531 #fi; 532 533 hom:=InverseGeneralMapping(hom); 534 ng:=Length(GeneratorsOfGroup(Source(hom))); 535 536 sl:=[]; 537 ngl:=[ng]; 538 pll:=[]; 539 ms:=1; 540 for p in pl do 541 s:=SchuMu(G,p); 542 if Size(KernelOfMultiplicativeGeneralMapping(s))>1 then 543 Add(pll,p); 544 Add(sl,SchuMu(G,p)); 545 ab:=AbelianInvariants(KernelOfMultiplicativeGeneralMapping(s)); 546 ms:=ms*Product(ab); 547 Add(ngl,ngl[Length(ngl)]+Length(ab)); 548 fi; 549 od; 550 Info(InfoSchur,1,"Relevant primes:",pll); 551 Info(InfoSchur,1,"Multiplicator size:",ms); 552 if Length(pll)=0 then 553 return IdentityMapping(G); 554 fi; 555 556 #F:=FreeGroup(List([1..ngl[Length(ngl)]],x->Concatenation("@",String(x)))); 557 F:=FreeGroup(ngl[Length(ngl)]); 558 559 rels:=[]; 560 rel2:=[]; 561 for pp in [1..Length(pll)] do 562 p:=pll[pp]; 563 Info(InfoSchur,2,"Cohomology for prime :",p); 564 s:=sl[pp]; 565 mg:=IsomorphismPermGroup(KernelOfMultiplicativeGeneralMapping(s)); 566 mg:=List(IndependentGeneratorsOfAbelianGroup(Image(mg)), 567 i->PreImagesRepresentative(mg,i)); 568 sdc:=ListWithIdenticalEntries(ngl[Length(ngl)],One(Source(s))); 569 sdc{[ngl[pp]+1..ngl[pp+1]]}:=mg; 570 571 sdc:=GroupHomomorphismByImagesNC(F,KernelOfMultiplicativeGeneralMapping(s), 572 GeneratorsOfGroup(F),sdc); 573 574 gens:=GeneratorsOfGroup(F){[ngl[pp]+1..ngl[pp+1]]}; 575 ce:=CorestEval(hom,s); 576 577 for i in gens do 578 Add(rels,i^Order(Image(sdc,i))); 579 for j in GeneratorsOfGroup(F) do 580 if i<>j then 581 Add(rels,Comm(i,j)); 582 fi; 583 od; 584 od; 585 586 q:=[]; 587 for i in ce do 588 Add(q,PreImagesRepresentative(sdc,i[2])); 589 od; 590 rel2[pp]:=q; 591 od; 592 593 # now run through the last ce 594 gens:=GeneratorsOfGroup(F){[1..ng]}; 595 free:=FreeGeneratorsOfFpGroup(Source(hom)); 596 for i in [1..Length(ce)] do 597 q:=One(F); 598 for j in [1..Length(pll)] do 599 q:=q*rel2[j][i]; 600 od; 601 Add(rels,MappedWord(ce[i][1],free,gens)/q); 602 od; 603 604 q:=F/rels; 605 if AssertionLevel()>0 then 606 if Size(q)<>Size(G)*ms then 607 Error("oops!"); 608 fi; 609 else 610 SetSize(q,Size(G)*ms); 611 fi; 612 qhom:=GroupHomomorphismByImages(q,G,GeneratorsOfGroup(q), 613 Concatenation(List(GeneratorsOfGroup(Source(hom)),i->Image(hom,i)), 614 List([ng+1..Length(GeneratorsOfGroup(q))], 615 i->One(G)) )); 616 SetIsSurjective(qhom,true); 617 SetSize(Source(qhom),Size(G)*ms); 618 619 return qhom; 620end); 621 622DoMulExt:=function(arg) 623local G,pl; 624 G:=arg[1]; 625 if not IsFinite(G) then 626 Error("cover is only defined for finite groups"); 627 elif Size(G)=1 then 628 return IdentityMapping(G); 629 elif IsPGroup(G) then 630 TryNextMethod(); # we recursively call the algorithm for the p-sylow 631 fi; 632 Info(InfoWarning,1,"Warning: EpimorphismSchurCover via Holt's algorithm is under construction"); 633 if Length(arg)>1 then 634 pl:=arg[2]; 635 else 636 pl:=PrimeDivisors(Size(G)); 637 fi; 638 return MulExt(G,pl); 639end; 640 641InstallMethod(EpimorphismSchurCover,"Holt's algorithm",true,[IsGroup],0, 642 DoMulExt); 643 644InstallOtherMethod(EpimorphismSchurCover,"Holt's algorithm, primes",true, 645 [IsGroup,IsList],0,DoMulExt); 646 647InstallMethod(SchurCover,"general: Holt's algorithm",true,[IsGroup],0, 648 G->Source(EpimorphismSchurCover(G))); 649 650############################################################################ 651############################################################################ 652## 653## Additional attributes and properties Robert F. Morse 654## derived from computing the Schur Cover 655## of a group. 656## 657## A Epicentre 658## O NonabelianExteriorSquare 659## O EpimorphismNonabelianExteriorSquare 660## P IsCapable 661## 662############################################################################ 663## 664#A Epicentre(<G>) 665## 666## There are various ways of describing the epicentre of a group. It is 667## the smallest normal subgroup $N$ of $G$ such that $G/N$ is a central 668## quotient of some group $H$. It is also the exterior center of a group. 669## 670InstallMethod(Epicentre,"Naive Method",true,[IsGroup],0, 671 function(G) 672 local epi; 673 epi := EpimorphismSchurCover(G); 674 return Image(epi,Center(Source(epi))); 675 end 676); 677 678############################################################################# 679## 680#A Epicentre(G,N) 681## 682## Place holder attribute for computing the epicentre relative to a normal 683## subgroup $N$. This is an attribute of $N$. 684## 685InstallOtherMethod(Epicentre,"Naive method",true,[IsGroup,IsGroup],0, 686 function(G,N) 687 TryNextMethod(); 688 end 689); 690 691############################################################################# 692## 693#O NonabelianExteriorSquare 694## 695## Computes the Nonabelian Exterior Square $G\wedge G$ of a group $G$. 696## For finitely generated groups this is the derived subgroup of the 697## Schur cover -- which is an invariant for all Schur covers of group. 698## 699InstallMethod(NonabelianExteriorSquare, "Naive method", true, [IsGroup],0, 700 G->DerivedSubgroup(SchurCover(G))); 701 702############################################################################# 703## 704#O EpimorphismNonabelianExteriorSquare(<G>) 705## 706## Computes the mapping $G\wedge G \to G$. The kernel of this 707## mapping is isomorphic to the Schur Multiplicator. 708## 709InstallMethod(EpimorphismNonabelianExteriorSquare, "Naive method", true, 710 [IsGroup],0, 711 function(G) 712 local epi, ## Epimorphism from the Schur cover to G 713 D; ## Derived subgroup of the Schur Cover 714 715 epi := EpimorphismSchurCover(G); 716 D := DerivedSubgroup(Source(epi)); 717 718 ## Compute the restricted mapping of epi from 719 ## D --> G 720 ## 721 ## Need to check that D is trivial i.e. has no generators. 722 ## In this case we create the homomorphism using the group's 723 ## elements rather than generators. 724 ## 725 if IsTrivial(D) then 726 727 return GroupHomomorphismByImages( 728 D, Image(epi,D), 729 AsSSortedList(D), AsSSortedList(Image(epi,D))); 730 fi; 731 732 return GroupHomomorphismByImages( 733 D, Image(epi,D), 734 GeneratorsOfGroup(D), 735 List(GeneratorsOfGroup(D),x->Image(epi,x))); 736 737 end 738); 739 740############################################################################# 741## 742#P IsCentralFactor(<G>) 743## 744## Dertermines if $G$ is a central factor of some group $H$ or not. 745## 746InstallMethod(IsCentralFactor, "Naive method", true, [IsGroup], 0, 747 G -> IsTrivial(Epicentre(G))); 748