1############################################################################## 2## 3#W isoclinic.gi GAP4 package `XMod' Alper Odabas 4#W & Enver Uslu 5#Y Copyright (C) 2001-2019, Chris Wensley et al 6#Y 7## This file contains generic methods for finding isoclinism classes 8## of crossed modules. 9## 10 11############################################################################# 12## 13#M FixedPointSubgroupXMod . . . . elements of the range fixed by the source 14## 15InstallMethod( FixedPointSubgroupXMod, "generic method for precrossed modules", 16 true, [ IsPreXMod, IsGroup, IsGroup ], 0, 17function( XM, T, Q ) 18 19 local genQ, act, ext, orb, elts, fix, gens; 20 21 if not ( IsSubgroup( Source(XM), T ) and IsSubgroup( Range(XM), Q ) ) then 22 Error( "T,Q not subgroups of S,R" ); 23 fi; 24 genQ := GeneratorsOfGroup( Q ); 25 act := XModAction( XM ); 26 ext := ExternalSet( Q, T, genQ, List( genQ, g -> ImageElm(act,g) ) ); 27 orb := Orbits( ext ); 28 elts := Concatenation( Filtered( orb, o -> Length(o) = 1) ); 29 fix := Subgroup( T, elts ); 30 gens := SmallGeneratingSet( fix ); 31 return Subgroup( T, gens ); 32end ); 33 34############################################################################# 35## 36#M StabilizerSubgroupXMod . . . . elements of Q<=R which fix T<=S pointwise 37## 38InstallMethod( StabilizerSubgroupXMod, 39 "generic method for a crossed module and subgroups of source, range", 40 true, [ IsPreXMod, IsGroup, IsGroup ], 0, 41function( XM, T, Q ) 42 43 local alpha, sonuc, t, q, list, sgp; 44 45 if not ( IsSubgroup( Source(XM), T ) and IsSubgroup( Range(XM), Q ) ) then 46 Error( "T,Q not subgroups of S,R" ); 47 fi; 48 alpha := XModAction( XM ); 49 list := []; 50 for q in Q do 51 if ForAll( T, t -> ImageElm(ImageElm(alpha,q),t)=t ) then 52 Add( list, q ); 53 fi; 54 od; 55 ## if the lists consist only the identity element then there is a bug 56 ## in the function AsMagma. 57 if ( Length( Set(list) ) = 1 ) then 58 return TrivialSubgroup( Q ); 59 fi; 60 sgp := Subgroup( Q, list ); 61 sgp := Subgroup( Q, SmallGeneratingSet(sgp) ); 62 return sgp; 63end ); 64 65############################################################################# 66## 67#M CentreXMod . . . . . . . . . the centre of a crossed module 68## 69InstallMethod( CentreXMod, "generic method for crossed modules", true, 70 [ IsXMod ], 0, 71function( XM ) 72 73 local T, G, K, fix; 74 75 T := Source( XM ); 76 G := Range( XM ); 77 K := Intersection( Centre(G), StabilizerSubgroupXMod( XM, T, G ) ); 78 fix := FixedPointSubgroupXMod( XM, T, G ); 79 return SubXMod( XM, fix, K ); 80end ); 81 82############################################################################# 83## 84#M Centralizer . . . . . . . . for a subcrossed module of a crossed module 85## 86InstallOtherMethod( Centralizer, "generic method for crossed modules", true, 87 [ IsXMod, IsXMod ], 0, 88function( XM, YM ) 89 90 local srcX, rngY, genR, actY, ext, orb, elts, fix, gens, srcC, rngC; 91 92 if not IsSubXMod( XM, YM ) then 93 Error( "YM is not a subcrossed module of XM" ); 94 fi; 95 srcX := Source( XM ); 96 rngY := Range( YM ); 97 genR := GeneratorsOfGroup( rngY ); 98 actY := XModAction( YM ); 99 ext := ExternalSet( rngY, srcX, genR, List( genR, g -> ImageElm(actY,g) ) ); 100 orb := Orbits( ExternalSetXMod( XM ) ); 101 elts := Concatenation( Filtered( orb, o -> Length(o) = 1) ); 102 fix := Subgroup( srcX, elts ); 103 gens := SmallGeneratingSet( fix ); 104 srcC := Subgroup( srcX, gens ); 105 rngC := Intersection( StabilizerSubgroupXMod( XM, srcX, rngY ), 106 Centralizer( Range( XM ), rngY ) ); 107 if ( srcC = srcX ) then 108 srcC := srcX; 109 if ( rngC = Range( XM ) ) then 110 return XM; 111 fi; 112 fi; 113 return SubXMod( XM, srcC, rngC ); 114end ); 115 116############################################################################# 117## 118#M Displacement 119## 120InstallMethod( Displacement, "generic method for hom, element, element", 121 true, [ IsGroupHomomorphism, IsObject, IsObject ], 0, 122function( alpha, r, s ) 123 124 local a; 125 126 if not ( r in Source(alpha) ) then 127 Error( "r not in Source(alpha)" ); 128 fi; 129 a := ImageElm( alpha, r ); 130 if not ( ( Range(a) = Source(a) ) and ( s in Source(a) ) ) then 131 Error( "alpha not an automorphism of group containing s" ); 132 fi; 133 return ImageElm( a, s^-1 ) * s; 134end ); 135 136############################################################################# 137## 138#M DisplacementGroup . . . . . subgroup of source generated by displacements 139## 140InstallMethod( DisplacementGroup, "generic method for crossed modules", 141 true, [ IsXMod, IsGroup, IsGroup ], 0, 142function( XM, H, S ) 143 144 local alpha, alp, sonuc, T, G, t, t0, g, list, one; 145 146 T := Source( XM ); 147 G := Range( XM ); 148 if not ( IsSubgroup( T, S ) and IsSubgroup( G, H ) ) then 149 Error( "S <= T and H <= G fails" ); 150 fi; 151 alpha := XModAction( XM ); 152 list := []; 153 one := One( T ); 154 #? surely we do not need to calculate all the displacements? 155 for g in H do 156 alp := ImageElm( alpha, g ); 157 for t in S do 158 t0 := ImageElm( alp, t^-1 ) * t; 159 if ( ( t0 <> one ) and ( Position(list,t0) = fail ) ) then 160 Add( list, t0 ); 161 fi; 162 od; 163 od; 164 if ( Length( Set(list) ) = 0 ) then 165 list := [ one ]; 166 fi; 167 sonuc := Subgroup( T, list ); 168 return Subgroup( T, SmallGeneratingSet( sonuc ) ); 169end ); 170 171InstallMethod( DisplacementSubgroup, "generic method for crossed modules", 172 true, [ IsXMod ], 0, 173function( XM ) 174 return DisplacementGroup( XM, Range(XM), Source(XM) ); 175end ); 176 177############################################################################# 178## 179#M Normalizer . . . . . . . . . for a subcrossed module of a crossed module 180## 181InstallOtherMethod( Normalizer, "generic method for crossed modules", true, 182 [ IsXMod, IsXMod ], 0, 183function( XM, YM ) 184 185 local act, T, G, S, H, t, h, d, pos, elts, gens, srcN, rngN; 186 187 if not IsSubXMod( XM, YM ) then 188 Error( "YM is not a subcrossed module of XM" ); 189 fi; 190 elts := [ ]; 191 act := XModAction( XM ); 192 T := Source( XM ); 193 G := Range( XM ); 194 S := Source( YM ); 195 H := Range( YM ); 196 ## is there a more efficient method, just using generators? 197 for t in T do 198 for h in H do 199 d := Displacement( act, h, t ); 200 if ( d in S ) then 201 pos := Position( elts, d ); 202 if ( pos = fail ) then 203 Add( elts, d ); 204 fi; 205 fi; 206 od; 207 od; 208 srcN := Subgroup( S, elts ); 209 gens := SmallGeneratingSet( srcN ); 210 srcN := Subgroup( S, gens ); 211 rngN := Intersection( Normalizer( G, H ), 212 StabilizerSubgroupXMod( XM, S, G ) ); 213 rngN := Subgroup( G, SmallGeneratingSet( rngN ) ); 214 return SubXMod( XM, srcN, rngN ); 215end ); 216 217############################################################################# 218## 219#M CrossActionSubgroup . . . . . . . . . source group for CommutatorSubXMod 220## 221InstallMethod( CrossActionSubgroup, "generic method for two normal subxmods", 222 true, [ IsXMod, IsXMod, IsXMod ], 0, 223function( TG, SH, RK ) 224 225 local alpha, alp, T, s, s0, k, r, r0, h, list, one, cas; 226 227 ## if not ( IsSub2DimensionalDomain(TG,SH) 228 ## and IsSub2DimensionalDomain(TG,RK) ) then 229 ## Error( "SH,RK not subcrossed modules of TG" ); 230 ## fi; 231 T := Source(TG); 232 alpha := XModAction(TG); 233 list := []; 234 one := One( T ); 235 for k in GeneratorsOfGroup( Range(RK) ) do 236 alp := ImageElm( alpha, k ); 237 for s in GeneratorsOfGroup( Source(SH) ) do 238 s0 := s^-1 * ImageElm( alp, s ); 239 if ( ( s0 <> one ) and ( Position(list,s0) = fail ) ) then 240 Add( list, s0 ); 241 fi; 242 od; 243 od; 244 for h in GeneratorsOfGroup( Range(SH) ) do 245 alp := ImageElm( alpha, h ); 246 for r in GeneratorsOfGroup( Source(RK) ) do 247 r0 := ImageElm( alp, r^-1 ) * r; 248 if ( ( r0 <> one ) and ( Position(list,r0) = fail ) ) then 249 Add( list, r0 ); 250 fi; 251 od; 252 od; 253 if ( Length( Set(list) ) = 0 ) then 254 list := [ one ]; 255 fi; 256 cas := Subgroup( T, list ); 257 cas := Subgroup( T, SmallGeneratingSet( cas ) ); 258 return cas; 259end ); 260 261############################################################################# 262## 263#M IntersectionSubXMods . . . . intersection of subcrossed modules SH and RK 264## 265InstallMethod( IntersectionSubXMods, "generic method for crossed modules", 266 true, [ IsXMod, IsXMod, IsXMod ], 0, 267function( XM, SH, RK) 268 269 local alpha, T, G, S, H, R, K, bdy, k_bdy, k_alpha, SR, HK; 270 271 T := Source( XM ); 272 G := Range( XM ); 273 alpha := XModAction( XM ); 274 bdy := Boundary( XM ); 275 S := Source(SH); 276 H := Range(SH); 277 R := Source(RK); 278 K := Range(RK); 279 SR := Intersection(S,R); 280 HK := Intersection(H,K); 281 return SubXMod(XM,SR,HK); 282end ); 283 284############################################################################# 285## 286#M NaturalMorphismByNormalSubPreXMod . . . . . the quotient prexmod morphism 287## 288InstallMethod( NaturalMorphismByNormalSubPreXMod, 289 "generic method for crossed modules", true, [ IsPreXMod, IsPreXMod ], 0, 290function( XM, SM ) 291 292 local actX, bdyX, nhomQ, nhomF, T, G, S, H, Q, F, sgQ, sgF, imbdy, bdy, 293 lenF, psgQ, psgF, asgF, i, autF, aut, act, FM, nat; 294 295 if not IsNormal( XM, SM ) then 296 Error( "not a normal subcrossed module" ); 297 fi; 298 actX := XModAction( XM ); 299 bdyX := Boundary( XM ); 300 T := Source( XM ); 301 S := Source( SM ); 302 nhomQ := NaturalHomomorphismByNormalSubgroup( T, S ); 303 Q := Image( nhomQ ); 304 sgQ := SmallGeneratingSet( Q ); 305 Q := GroupWithGenerators( sgQ, One(Q) ); # T/S bölüm grubu 306 psgQ := List( sgQ, q -> PreImagesRepresentative( nhomQ, q ) ); 307 G := Range( XM ); 308 H := Range( SM ); 309 if IsTrivial( H ) then 310 F := G; 311 nhomF := IdentityMapping( G ); 312 sgF := SmallGeneratingSet( G ); 313 psgF := SmallGeneratingSet( G ); 314 else 315 nhomF := NaturalHomomorphismByNormalSubgroup( G, H ); 316 F := Image( nhomF ); 317 sgF := SmallGeneratingSet( F ); 318 F := GroupWithGenerators( sgF, One(F) ); # G/H bölüm grubu 319 psgF := List( sgF, f -> PreImagesRepresentative( nhomF, f ) ); 320 fi; 321 imbdy := List( psgQ, t -> ImageElm( nhomF, ImageElm( bdyX, t ) ) ); 322 bdy := GroupHomomorphismByImages( Q, F, sgQ, imbdy ); 323 lenF := Length( psgF ); 324 asgF := List( psgF, g -> ImageElm( actX, g ) ); 325 autF := ListWithIdenticalEntries( lenF, 0 ); 326 for i in [1..lenF] do 327 autF[i] := GroupHomomorphismByImages( Q, Q, sgQ, 328 List( psgQ, t -> ImageElm( nhomQ, ImageElm(asgF[i],t) ) ) ); 329 od; 330 if ( lenF = 0 ) then 331 aut := Group( IdentityMapping( Q ) ); 332 else 333 aut := Group( autF ); 334 fi; 335 SetIsGroupOfAutomorphisms( aut, true ); 336 act := GroupHomomorphismByImages( F, aut, sgF, autF ); 337 FM := XModByBoundaryAndAction( bdy, act ); 338 if ( HasName( XM ) and HasName( SM ) ) then 339 SetName( FM, Concatenation( Name( XM ), "/", Name( SM ) ) ); 340 fi; 341 nat := PreXModMorphismByGroupHomomorphisms( XM, FM, nhomQ, nhomF ); 342 SetProjectionOfFactorPreXMod( FM, nat ); 343 return nat; 344end ); 345 346############################################################################# 347## 348#M FactorPreXMod . . . . . . . . . . . . . . the quotient precrossed module 349## 350InstallMethod( FactorPreXMod, "generic method for precrossed modules", true, 351 [ IsPreXMod, IsPreXMod ], 0, 352function( XM, SM ) 353 return Range( NaturalMorphismByNormalSubPreXMod( XM, SM ) ); 354end ); 355 356############################################################################# 357## 358#M DerivedSubXMod . . . . . . . . . . the commutator of the crossed module 359## 360InstallMethod( DerivedSubXMod, "generic method for crossed modules", true, 361 [ IsXMod ], 0, 362function( XM ) 363 364 local D, dgt; 365 366 D := DerivedSubgroup( Range( XM ) ); 367 dgt := DisplacementSubgroup( XM ); 368 return SubXMod( XM, dgt, D ); 369end ); 370 371############################################################################# 372## 373#M CommutatorSubXMod . . . . . . . commutator subxmod of two normal subxmods 374## 375InstallMethod( CommutatorSubXMod, "generic method for crossed modules", true, 376 [ IsXMod, IsXMod, IsXMod ], 0, 377function( TG, SH, RK ) 378 379 local cas, com; 380 381 cas := CrossActionSubgroup( TG, SH, RK ); 382 com := CommutatorSubgroup( Range(SH), Range(RK) ); 383 return SubXMod( TG, cas, com ); 384end ); 385 386############################################################################# 387## 388#M LowerCentralSeries . . . . . . . . . the lower central series of an xmod 389## 390InstallOtherMethod( LowerCentralSeries, "generic method for crossed modules", 391 true, [ IsXMod ], 0, 392function( XM ) 393 394 local list, C; 395 396 list := [ XM ]; 397 C := DerivedSubXMod( XM ); 398 while ( C <> list[ Length(list) ] ) do 399 Add( list, C ); 400 C := CommutatorSubXMod( XM, C, XM ); 401 od; 402 return list; 403end ); 404 405############################################################################# 406## 407#M IsAbelian2DimensionalGroup . . . . check that a crossed module is abelian 408## 409InstallMethod( IsAbelian2DimensionalGroup, 410 "generic method for crossed modules", true, [ IsXMod ], 0, 411function( XM ) 412 return ( XM = CentreXMod( XM ) ); 413end ); 414 415############################################################################# 416## 417#M IsAspherical2DimensionalGroup . check that a crossed module is aspherical 418## 419InstallMethod( IsAspherical2DimensionalGroup, 420 "generic method for crossed modules", true, [ IsXMod ], 0, 421function( XM ) 422 return ( Size( Kernel( Boundary( XM ) ) ) = 1 ); 423end ); 424 425############################################################################# 426## 427#M IsSimplyConnected2DimensionalGroup . . check an xmod is simply connected 428## 429InstallMethod( IsSimplyConnected2DimensionalGroup, 430 "generic method for crossed modules", true, [ IsXMod ], 0, 431function( XM ) 432 return ( Size( CoKernel( Boundary( XM ) ) ) = 1 ); 433end ); 434 435############################################################################# 436## 437#M IsFaithful2DimensionalGroup . . . check that a crossed module is faithful 438## 439InstallMethod( IsFaithful2DimensionalGroup, 440 "generic method for crossed modules", true, [ IsXMod ], 0, 441function( XM ) 442 return ( Size( StabilizerSubgroupXMod( XM, Source( XM ), Range( XM ) ) ) = 1 ); 443end ); 444 445############################################################################# 446## 447#M IsNilpotent2DimensionalGroup . . . . . . check that an xmod is nilpotent 448## 449InstallMethod( IsNilpotent2DimensionalGroup, 450 "generic method for crossed modules", true, [ IsXMod ], 0, 451function( XM ) 452 453 local S, n, sonuc; 454 455 S := LowerCentralSeries( XM ); 456 n := Length(S); 457 if ( Size(S[n]) = [1,1] ) then 458 sonuc := true; 459 else 460 sonuc := false; 461 fi; 462return sonuc; 463end ); 464 465############################################################################# 466## 467#M NilpotencyClassOf2DimensionalGroup . nilpotency degree of a crossed module 468## 469InstallMethod( NilpotencyClassOf2DimensionalGroup, 470 "generic method for crossed modules", true, [ IsXMod ], 0, 471function( XM ) 472 473 if not IsNilpotent2DimensionalGroup( XM ) then 474 return 0; 475 else 476 return Length( LowerCentralSeries( XM ) ) - 1; 477 fi; 478end ); 479 480############################################################################# 481## 482#M IsomorphismXMods . . check that the given crossed modules are isomorphic 483## 484InstallMethod( IsomorphismXMods, "generic method for crossed modules", true, 485 [ Is2DimensionalGroup, Is2DimensionalGroup ], 0, 486function(XM1,XM2) 487 488 local T1, G1, T2, G2, isoT, isoG, iterT, iterG, alp, ph, mor; 489 490 T1 := Source(XM1); 491 G1 := Range(XM1); 492 T2 := Source(XM2); 493 G2 := Range(XM2); 494 isoT := IsomorphismGroups(T1,T2); 495 isoG := IsomorphismGroups(G1,G2); 496 if ( ( isoT = fail ) or ( isoG = fail ) ) then 497 return fail; 498 fi; 499 iterT := Iterator( AllAutomorphisms( T2 ) ); 500 while not IsDoneIterator( iterT ) do 501 iterG := Iterator( AllAutomorphisms( G2 ) ); 502 alp := isoT * NextIterator( iterT ); 503 while not IsDoneIterator( iterG ) do 504 ph := isoG * NextIterator( iterG ); 505 mor := Make2DimensionalGroupMorphism( [ XM1, XM2, alp, ph ] ); 506 if ( not( mor = fail ) and IsPreXModMorphism( mor ) 507 and IsXModMorphism( mor ) ) then 508 return mor; 509 fi; 510 od; 511 od; 512 return fail; 513end ); 514 515############################################################################# 516## 517#M AllXModsWithGroups . . . . . . . . all xmods with given source and range 518## 519InstallMethod( AllXModsWithGroups, "generic method for a pair of groups", 520 true, [ IsGroup, IsGroup ], 0, 521function( T, G ) 522 523 local list, A, itTG, itGA, b1, a1, obj; 524 525 list := [ ]; 526 A := AutomorphismGroup(T); 527 itTG := Iterator( AllHomomorphisms(T,G) ); 528 while not IsDoneIterator( itTG ) do 529 b1 := NextIterator( itTG ); 530 itGA := Iterator( AllHomomorphisms(G,A) ); 531 while not IsDoneIterator( itGA ) do 532 a1 := NextIterator( itGA ); 533 obj := PreXModObj( b1, a1 ); 534 if ( IsPreXMod( obj ) and IsXMod( obj ) ) then 535 Add( list, obj ); 536 fi; 537 od; 538 od; 539 return list; 540end ); 541 542InstallMethod( AllXModsWithGroups0, "generic method for a pair of groups", 543 true, [ IsGroup, IsGroup ], 0, 544function( T, G ) 545 546 local list, A, allTG, allGA, b1, a1, obj; 547 548 list := [ ]; 549 A := AutomorphismGroup(T); 550 allTG := AllHomomorphisms(T,G); 551 allGA := AllHomomorphisms(G,A); 552 for b1 in allTG do 553 for a1 in allGA do 554 obj := PreXModObj( b1, a1 ); 555 if ( IsPreXMod( obj ) and IsXMod( obj ) ) then 556 Add( list, obj ); 557 fi; 558 od; 559 od; 560 return list; 561end ); 562 563InstallMethod( AllXModsWithGroups1, "generic method for a pair of groups", 564 true, [ IsGroup, IsGroup ], 0, 565function( T, G ) 566 567 local list, A, itTG, itGA, b1, a1, obj; 568 569 list := [ ]; 570 A := AutomorphismGroup(T); 571 itTG := Iterator( AllHomomorphismClasses(T,G) ); 572 while not IsDoneIterator( itTG ) do 573 b1 := NextIterator( itTG ); 574 itGA := Iterator( AllHomomorphisms(G,A) ); 575 while not IsDoneIterator( itGA ) do 576 a1 := NextIterator( itGA ); 577 obj := PreXModObj( b1, a1 ); 578 if ( IsPreXMod( obj ) and IsXMod( obj ) ) then 579 Add( list, obj ); 580 fi; 581 od; 582 od; 583 return list; 584end ); 585 586InstallMethod( AllXModsWithGroups2, "generic method for a pair of groups", 587 true, [ IsGroup, IsGroup ], 0, 588function( T, G ) 589 590 local list, A, itTG, itGA, b1, a1, obj; 591 592 list := [ ]; 593 A := AutomorphismGroup(T); 594 itTG := Iterator( AllHomomorphisms(T,G) ); 595 while not IsDoneIterator( itTG ) do 596 b1 := NextIterator( itTG ); 597 itGA := Iterator( AllHomomorphismClasses(G,A) ); 598 while not IsDoneIterator( itGA ) do 599 a1 := NextIterator( itGA ); 600 obj := PreXModObj( b1, a1 ); 601 if ( IsPreXMod( obj ) and IsXMod( obj ) ) then 602 Add( list, obj ); 603 fi; 604 od; 605 od; 606 return list; 607end ); 608 609InstallMethod( AllXModsWithGroups3, "generic method for a pair of groups", 610 true, [ IsGroup, IsGroup ], 0, 611function( T, G ) 612 613 local list, A, itTG, itGA, b1, a1, obj; 614 615 list := [ ]; 616 A := AutomorphismGroup(T); 617 itTG := Iterator( AllHomomorphismClasses(T,G) ); 618 while not IsDoneIterator( itTG ) do 619 b1 := NextIterator( itTG ); 620 itGA := Iterator( AllHomomorphismClasses(G,A) ); 621 while not IsDoneIterator( itGA ) do 622 a1 := NextIterator( itGA ); 623 obj := PreXModObj( b1, a1 ); 624 if ( IsPreXMod( obj ) and IsXMod( obj ) ) then 625 Add( list, obj ); 626 fi; 627 od; 628 od; 629 return list; 630end ); 631 632############################################################################# 633## 634#F AllXMods( <T>, <G> ) xmods with given source and range 635#F AllXMods( <size> ) xmods with a given size 636#F AllXMods( <order> ) xmods whose cat1-group has a given order 637## 638InstallGlobalFunction( AllXMods, function( arg ) 639 640 local nargs, a, list, s1, j1, s2, j2, T, G, sizes; 641 642 nargs := Length( arg ); 643 if ( nargs = 2 ) then 644 ## given source and range 645 if ( IsGroup( arg[1] ) and IsGroup( arg[2] ) ) then 646 return AllXModsWithGroups( arg[1], arg[2] ); 647 fi; 648 elif ( nargs = 1 ) then 649 a := arg[1]; 650 ## given size 651 if ( IsList(a) and (Length(a)=2) and IsInt(a[1]) and IsInt(a[2]) ) then 652 list := [ ]; 653 s1 := NumberSmallGroups( a[1] ); 654 for j1 in [1..s1] do 655 T := SmallGroup( a[1], j1 ); 656 s2 := NumberSmallGroups( a[2] ); 657 for j2 in [1..s2] do 658 G := SmallGroup( a[2], j2 ); 659 Append( list, AllXModsWithGroups( T, G ) ); 660 od; 661 od; 662 return list; 663 ## given total size 664 elif IsInt(a) then 665 sizes := List( DivisorsInt(a), d -> [d,a/d] ); 666 list := [ ]; 667 for s1 in sizes do 668 Append( list, AllXMods( s1 ) ); 669 od; 670 return list; 671 fi; 672 fi; 673 Error( "standard usage: AllXMods(S,R), AllXMods([n,m]), AllXMods(n)" ); 674end ); 675 676 677############################################################################# 678##### FUNCTIONS FOR ISOCLINISM OF GROUPS ##### 679############################################################################# 680 681############################################################################# 682## 683#M IsStemDomain . . . check that the centre is a subgroup of the derived group 684## 685InstallMethod( IsStemDomain, "generic method for groups", true, [ IsGroup ], 0, 686function(G) 687 return IsSubgroup( DerivedSubgroup(G), Centre(G) ); 688end ); 689 690############################################################################# 691## 692#M AllStemGroupIds . . . list of all IdGroup's of stem groups of chosen order 693## 694InstallMethod( AllStemGroupIds, "generic method for posint", true, 695 [ IsPosInt ], 0, 696function(a) 697 698 local g, i, j, sonuc, sayi; 699 700 sonuc := [ ]; 701 for g in AllSmallGroups( a ) do 702 if IsStemDomain( g ) then 703 Add( sonuc, IdGroup( g ) ); 704 fi; 705 od; 706 return sonuc; 707end ); 708 709############################################################################# 710## 711#M AllStemGroupFamilies . . . split stem groups of chosen order into families 712## 713InstallMethod( AllStemGroupFamilies, "generic method for posint", true, 714 [ IsPosInt ], 0, 715function(a) 716 717 local ids, len, found, id, gi, g, i, j, sonuc, new, sayi; 718 719 ids := AllStemGroupIds( a ); 720 len := Length( ids ); 721 found := ListWithIdenticalEntries( len, false ); 722 sonuc := [ ]; 723 for i in [1..len] do 724 if not found[i] then 725 found[i] := true; 726 id := ids[i]; 727 new := [ id ]; 728 gi := SmallGroup( id ); 729 for j in [i+1..len] do 730 if not found[j] then 731 if AreIsoclinicDomains( gi, SmallGroup( ids[j] ) ) then 732 found[j] := true; 733 Add( new, ids[j] ); 734 fi; 735 fi; 736 od; 737 Add( sonuc, ShallowCopy( new ) ); 738 fi; 739 od; 740 return sonuc; 741end ); 742 743############################################################################# 744## 745#M CentralQuotient . . . . . . . . . . . . . . . . . . . . (G -> G/Z(G)) 746## 747InstallMethod( CentralQuotient, "generic method for groups", true, 748 [ IsGroup ], 0, 749function( G ) 750 751 local ZG, Q, nat, XQ; 752 753 ZG := Centre( G ); 754 nat := NaturalHomomorphismByNormalSubgroup( G, ZG ); 755 Q := Image( nat ); 756 if HasName(G) then 757 if not HasName(ZG) then 758 SetName( ZG, Concatenation( "Z(", Name(G), ")" ) ); 759 fi; 760 SetName( Q, Concatenation( Name(G), "/", Name(ZG) ) ); 761 fi; 762 XQ := XModByCentralExtension( nat ); 763 return XQ; 764end ); 765 766InstallMethod( CentralQuotient, "generic method for crossed modules", 767 true, [ IsXMod ], 0, 768function( lt ) 769 770 local actlt, zlt, rt, L, M, N, P, nat, kappa, lambda, nu, up, dn, genL, 771 genN, nugenN, agenN, adg, imdelta, delta, dg, map, xp, xs; 772 773 actlt := XModAction( lt ); 774 zlt := CentreXMod( lt ); 775 nat := NaturalMorphismByNormalSubPreXMod( lt, zlt ); 776 kappa := SourceHom( nat ); 777 lambda := Boundary( lt ); 778 nu := RangeHom( nat ); 779 rt := Image( nat ); 780 L := Source( lt ); 781 N := Range( lt ); 782 M := Source( rt ); 783 P := Range( rt ); 784 if ( HasName( lt ) and not HasName(zlt) ) then 785 SetName( zlt, Concatenation( "Z(", Name( lt ), ")" ) ); 786 fi; 787 if HasName( lt ) then 788 if not HasName( zlt ) then 789 SetName( zlt, Concatenation( "Z(", Name( lt ), ")" ) ); 790 fi; 791 SetName( rt, Concatenation( Name(lt), "/", Name(zlt) ) ); 792 fi; 793 up := XModByCentralExtension( kappa ); 794 dn := XModByCentralExtension( nu ); 795 genL := GeneratorsOfGroup( L ); 796 genN := GeneratorsOfGroup( N ); 797 nugenN := List( genN, n -> ImageElm( nu, n ) ); 798 agenN := List( genN, n -> ImageElm( actlt, n ) ); 799 adg := GroupHomomorphismByImages( P, Range(actlt), nugenN, agenN ); 800 imdelta := List( genL, l ->ImageElm( nu, ImageElm( lambda, l ) ) ); 801 delta := GroupHomomorphismByImages( L, P, genL, imdelta ); 802 dg := XModByBoundaryAndAction( delta, adg ); 803 map := Mapping2ArgumentsByFunction( [N,M], L, 804 function(c) 805 local a, l; 806 a := ImageElm( actlt, c[1] ); 807 l := PreImagesRepresentative( kappa, c[2] ); 808 return ImageElm( a, l^(-1) ) * l; 809 end ); 810 xp := CrossedPairingObj( [N,M], L, map ); 811 xs := PreCrossedSquareObj( up, lt, rt, dn, dg, xp ); 812## SetIsCrossedSquare( xs, true ); 813 if not IsCrossedSquare( xs ) then 814 Error( "xs fails to be a crossed square by central quotient" ); 815 fi; 816 return xs; 817end ); 818 819############################################################################# 820## 821#M AreIsoclinicDomains . . . . . . . . . . . for two domains: groups or xmods 822## 823InstallMethod( AreIsoclinicDomains, "generic method for two groups or xmods", 824 true, [ IsDomain, IsDomain ], 0, 825function( D1, D2 ) 826 827 local iso; 828 829 if not ( ( IsGroup(D1) and IsGroup(D2) ) or 830 ( Is2DimensionalGroup(D1) and Is2DimensionalGroup(D2) ) ) then 831 Error( "D1 and D2 should be groups or 2DimensionalGroups" ); 832 fi; 833 iso := Isoclinism( D1, D2 ); 834 if ( ( iso = fail ) or ( iso = false ) ) then 835 return false; 836 else 837 return true; 838 fi; 839end ); 840 841############################################################################## 842## 843#M Isoclinism . . . . . . . . . . . . . . . . . . . . . . . . . . . for groups 844## 845InstallMethod( Isoclinism, "generic method for two groups", true, 846 [ IsGroup, IsGroup ], 0, 847function( G1, G2 ) 848 849 local CQ1, CQ2, Q1, Q2, D1, D2, nhom1, nhom2, sgQ1, lsgQ1, itAQ2, itAD2, 850 isoQ, isoD, p1, q1, p2, q2, i, iq1, iq2, j, g1, h1, 851 g2, h2, gor1, gor2, ok; 852 853 if ( IsomorphismGroups(G1,G2) <> fail ) then 854 Error( "not yet implemented" ); 855 return true; 856 fi; 857 CQ1 := CentralQuotient(G1); 858 Q1 := Range(CQ1); 859 CQ2 := CentralQuotient(G2); 860 Q2 := Range(CQ2); 861 D1 := DerivedSubgroup(G1); 862 D2 := DerivedSubgroup(G2); 863 isoQ := IsomorphismGroups(Q1,Q2); 864 isoD := IsomorphismGroups(D1,D2); 865 if ( ( isoQ = fail ) or ( isoD = fail ) ) then 866 return fail; 867 fi; 868 nhom1 := Boundary( CQ1 ); 869 nhom2 := Boundary( CQ2 ); 870 itAQ2 := Iterator( AllAutomorphisms(Q2) ); 871 ## there is a problem here! 872 ## examples have been found where using SmallGeneratingSet 873 ## gives an incorrect answer! 874 ## perhaps GeneratorsOfGroup would be insuffient, but, 875 ## to play safe, we use Elements(Q1) for now, though very slow! 876 ## sgQ1 := SmallGeneratingSet( Q1 ); 877 ## sgQ1 := GeneratorsOfGroup( Q1 ); 878 sgQ1 := Elements( Q1 ); 879 lsgQ1 := Length( sgQ1 ); 880 while not IsDoneIterator( itAQ2 ) do 881 i := isoQ * NextIterator( itAQ2 ); 882 ok := true; 883 itAD2 := Iterator( AllAutomorphisms(D2) ); 884 while not IsDoneIterator( itAD2 ) do 885 j := isoD * NextIterator(itAD2); 886 ok := true; 887 p1 := 0; 888 while ( ok and ( p1 < lsgQ1 ) ) do 889 p1 := p1+1; 890 q1 := sgQ1[p1]; 891 g1 := PreImagesRepresentative( nhom1, q1 ); 892 iq1 := ImageElm( i, q1 ); 893 h1 := PreImagesRepresentative( nhom2, iq1 ); 894 p2 := 0; 895 while ( ok and ( p2 < lsgQ1 ) ) do 896 p2 := p2+1; 897 q2 := sgQ1[p2]; 898 g2 := PreImagesRepresentative( nhom1, q2 ); 899 iq2 := ImageElm( i, q2 ); 900 h2 := PreImagesRepresentative( nhom2, iq2 ); 901 gor1 := ImageElm( j, Comm(g1,g2) ); 902 gor2 := Comm( h1, h2 ); 903 ok := ( gor1 = gor2 ); 904 od; 905 od; 906 if ok then 907 return [i,j]; 908 fi; 909 od; 910 od; 911 return fail; 912end ); 913 914############################################################################# 915## 916#M IsoclinicStemDomain . . . ?? is this really the best way ?? 917## 918InstallMethod( IsoclinicStemDomain, "generic method for a group", true, 919 [ IsGroup ], 0, 920function(G) 921 922 local i, len, divs, id, gi; 923 924 if ( HasIsAbelian(G) and IsAbelian(G) ) then 925 return [ [ 1, 1 ] ]; 926 fi; 927 if IsStemDomain(G) then 928 return G; 929 fi; 930 divs := DivisorsInt( Size(G) ); 931 len := Length( divs ); 932 for i in divs{[2..len-1]} do 933 for gi in AllSmallGroups( i ) do 934 if IsStemDomain( gi ) then 935 if AreIsoclinicDomains( G, gi ) then 936 return gi; 937 fi; 938 fi; 939 od; 940 od; 941 return fail; 942end ); 943 944 945############################################################################# 946##### FUNCTIONS FOR ISOCLINISM OF CROSSED MODULES ##### 947############################################################################# 948 949############################################################################# 950## 951#M IsStemDomain . check that the centre xmod is a subxmod of the derived xmod 952## 953InstallMethod( IsStemDomain, "generic method for crossed modules", true, 954 [ IsXMod ], 0, 955function(X0) 956 return IsSubXMod( DerivedSubXMod(X0), CentreXMod(X0) ); 957end ); 958 959InstallMethod( Isoclinism, "generic method for crossed modules", true, 960 [ IsXMod, IsXMod ], 0, 961function( X1, X2 ) 962 963 local SX1, RX1, SX2, RX2, D1, D2, isoD, autD2, CX1, Q1, CX2, Q2, isoQ, 964 SQ1, RQ1, SQ2, RQ2, actX1, actX2, autQ2, nhom1, shom1, rhom1, 965 nhom2, shom2, rhom2, sgRQ1, lsgRQ1, sgSQ1, lsgSQ1, a, i, si, ri, 966 ok, b, j, sj, rj, p1, r1, x1, ir1, d1, p2, r2, x2, ir2, d2, 967 gor1, gor2, p3, s1, y1, is1, e1; 968 969 SX1 := Source(X1); 970 RX1 := Range(X1); 971 SX2 := Source(X2); 972 RX2 := Range(X2); 973 actX1 := XModAction( X1 ); 974 actX2 := XModAction( X2 ); 975 D1 := DerivedSubXMod(X1); 976 D2 := DerivedSubXMod(X2); 977 ## check condition 2 : require D1 ~ D2 978 isoD := IsomorphismXMods( D1, D2 ); 979 if ( isoD = fail ) then 980 Info( InfoXMod, 1, "derived subcrossed modules are not isomorphic" ); 981 return fail; 982 fi; 983 autD2 := AutomorphismPermGroup( D2 ); 984 985 CX1 := CentralQuotient( X1 ); 986 Q1 := Right2DimensionalGroup( CX1 ); 987 CX2 := CentralQuotient( X2 ); 988 Q2 := Right2DimensionalGroup( CX2 ); 989 ## check condition 1 : require Q1 ~ Q2 990 isoQ := IsomorphismXMods( Q1, Q2 ); 991 if ( isoQ = fail ) then 992 Info( InfoXMod, 1, "factor crossed modules X/ZX are not isomorphic" ); 993 return fail; 994 fi; 995 996 SQ1 := Source(Q1); 997 RQ1 := Range(Q1); 998 SQ2 := Source(Q2); 999 RQ2 := Range(Q2); 1000 autQ2 := AutomorphismPermGroup( Q2 ); 1001 nhom1 := LeftRightMorphism( CX1 ); 1002 shom1 := SourceHom( nhom1 ); 1003 rhom1 := RangeHom( nhom1 ); 1004 nhom2 := LeftRightMorphism( CX2 ); 1005 shom2 := SourceHom( nhom2 ); 1006 rhom2 := RangeHom( nhom2 ); 1007 sgRQ1 := SmallGeneratingSet( RQ1 ); 1008 lsgRQ1 := Length( sgRQ1 ); 1009 sgSQ1 := SmallGeneratingSet( SQ1 ); 1010 lsgSQ1 := Length( sgSQ1 ); 1011 1012 for a in autQ2 do 1013 i := isoQ * PermAutomorphismAsXModMorphism( Q2, a ); 1014 si := SourceHom( i ); 1015 ri := RangeHom( i ); 1016 ok := true; 1017 for b in autD2 do 1018 j := isoD * PermAutomorphismAsXModMorphism( D2, b ); 1019 sj := SourceHom( j ); 1020 rj := RangeHom( j ); 1021 ok := true; 1022 p1 := 0; 1023 while ( ok and ( p1 < lsgRQ1 ) ) do 1024 p1 := p1+1; 1025 r1 := sgRQ1[p1]; 1026 x1 := PreImagesRepresentative( rhom1, r1 ); 1027 ir1 := ImageElm( ri, r1 ); 1028 d1 := PreImagesRepresentative( rhom2, ir1 ); 1029 p2 := 0; 1030 while ( ok and ( p2 < lsgRQ1 ) ) do 1031 p2 := p2+1; 1032 r2 := sgRQ1[p2]; 1033 x2 := PreImagesRepresentative( rhom1, r2 ); 1034 ir2 := ImageElm( ri, r2 ); 1035 d2 := PreImagesRepresentative( rhom2, ir2 ); 1036 gor1 := ImageElm( rj, Comm(x1,x2) ); 1037 gor2 := Comm( d1, d2 ); 1038 ok := ( gor1 = gor2 ); 1039 od; 1040 p3 := 0; 1041 while ( ok and ( p3 < lsgSQ1 ) ) do 1042 p3 := p3+1; 1043 s1 := sgSQ1[p3]; 1044 y1 := PreImagesRepresentative( shom1, s1 ); 1045 is1 := ImageElm( si, s1 ); 1046 e1 := PreImagesRepresentative( shom2, is1 ); 1047 gor1 := ImageElm( sj, Displacement( actX1, x1, y1 ) ); 1048 gor2 := Displacement( actX2, d1, e1 ); 1049 ok := ( gor1 = gor2 ); 1050 od; 1051 od; 1052 if ok then 1053 return [i,j]; 1054 fi; 1055 od; 1056 od; 1057 Info( InfoXMod, 1, "no morphism exists satisfying the conditions" ); 1058 return fail; 1059end ); 1060 1061 1062############################################################################# 1063## 1064#M IsoclinicXModFamily . . . . all xmods in the list isoclinic to the xmod 1065## 1066InstallMethod( IsoclinicXModFamily, "generic method for crossed modules", 1067 true, [ Is2DimensionalGroup, IsList ], 0, 1068function( XM, XM1_ler ) 1069 1070 local sonuc, XM1; 1071 1072 sonuc := [ ]; 1073 for XM1 in XM1_ler do 1074 if AreIsoclinicDomains( XM, XM1 ) then 1075 Info( InfoXMod, 2, XM, " ~ ", XM1 ); 1076 Add( sonuc, Position(XM1_ler,XM1) ); 1077 else 1078 Info( InfoXMod, 2, XM, " |~ ", XM1 ); 1079 fi; 1080 od; 1081 return sonuc; 1082end ); 1083 1084############################################################################# 1085## 1086#M IsomorphicXModFamily . . . all xmods in the list isomorphic to the xmod 1087## 1088InstallMethod( IsomorphicXModFamily, "generic method for crossed modules", 1089 true, [ Is2DimensionalGroup, IsList ], 0, 1090function( XM, XM1_ler ) 1091 1092 local sonuc, iso, XM1; 1093 1094 sonuc := [ ]; 1095 for XM1 in XM1_ler do 1096 iso := IsomorphismXMods( XM, XM1 ); 1097 if ( iso <> fail ) then 1098 Add( sonuc, Position(XM1_ler,XM1) ); 1099 fi; 1100 od; 1101 return sonuc; 1102end ); 1103 1104############################################################################# 1105## 1106#M AllXModsUpToIsomorphism . . . . . all crossed modules up to isomorphism 1107## 1108InstallMethod( AllXModsUpToIsomorphism, "generic method for list of xmods", 1109 true, [ IsList ], 0, 1110function( allxmods ) 1111 1112 local n, found, all, i, j, k, isolar, list; 1113 1114 n := Length( allxmods ); 1115 found := ListWithIdenticalEntries( n, 0 ); 1116 all := ShallowCopy( allxmods ); 1117 list := []; 1118 for i in [1..n] do 1119 if ( found[i] = 0 ) then 1120 Add( list, allxmods[i] ); 1121 isolar := IsomorphicXModFamily( allxmods[i], all ); 1122 for j in isolar do 1123 k := Position( allxmods, all[j] ); 1124 found[k] := 1; 1125 od; 1126 fi; 1127 od; 1128 return list; 1129end ); 1130 1131############################################################################# 1132## 1133#M IsoclinicMiddleLength . . the middle length of a group or crossed module 1134#M IsoclinicRank . . . . . . . . . . . the rank of a group or crossed module 1135## 1136InstallMethod( IsoclinicRank, "generic method for groups", true, 1137 [ IsGroup ], 0, 1138function(G) 1139 1140 local ZG, DG, QG, KG; 1141 1142 if not IsPrimePowerInt( Size(G) ) then 1143 return fail; 1144 fi; 1145 ZG := Centre(G); 1146 DG := DerivedSubgroup(G); 1147 QG := G/ZG; 1148 KG := Intersection( ZG, DG ); 1149 return Tau( Size(KG) ) + Tau( Size(QG) ) - 2; 1150end ); 1151 1152InstallMethod( IsoclinicRank, "generic method for crossed modules", true, 1153 [ Is2DimensionalGroup ], 0, 1154function( XM ) 1155 1156 local size, ZXMod, DXMod, QXMod, KXMod, m1, m2, l1, l2; 1157 1158 size := Size( XM ); 1159 if not ( IsPrimePowerInt(size[1]) and IsPrimePowerInt(size[2]) ) then 1160 return fail; 1161 fi; 1162 ZXMod := CentreXMod( XM ); 1163 DXMod := DerivedSubXMod( XM ); 1164 QXMod := FactorPreXMod( XM, ZXMod ); 1165 KXMod := IntersectionSubXMods( XM, ZXMod, DXMod ); 1166 m1 := Size( QXMod ); 1167 m2 := Size( KXMod ); 1168 l1 := Tau( m1[1] ) + Tau( m2[1] ) - 2; 1169 l2 := Tau( m1[2] ) + Tau( m2[2] ) - 2; 1170 return [l1,l2]; 1171end ); 1172 1173InstallMethod( IsoclinicMiddleLength, "generic method for groups", true, 1174 [ IsGroup ], 0, 1175function(G) 1176 1177 local ZG, DG, QG, KG; 1178 1179 if not IsPrimePowerInt( Size(G) ) then 1180 return fail; 1181 fi; 1182 ZG := Centre( G ); 1183 DG := DerivedSubgroup( G ); 1184 KG := Intersection( ZG, DG ); 1185 QG := DG/KG; 1186 return Tau( Size(QG) ) - 1; 1187end ); 1188 1189InstallMethod( IsoclinicMiddleLength, 1190 "generic method for crossed modules", true, [ Is2DimensionalGroup ], 0, 1191function( XM ) 1192 1193 local size, ZXMod, DXMod, QXMod, KXMod; 1194 1195 size := Size( XM ); 1196 if not ( IsPrimePowerInt(size[1]) and IsPrimePowerInt(size[2]) ) then 1197 Info( InfoXMod, 1, "not a crossed module of prime power order" ); 1198 return fail; 1199 fi; 1200 ZXMod := CentreXMod( XM ); 1201 DXMod := DerivedSubXMod( XM ); 1202 KXMod := IntersectionSubXMods( XM, ZXMod, DXMod ); 1203 QXMod := FactorPreXMod( DXMod, KXMod ); 1204 size := Size( QXMod ); 1205 return [ Tau(size[1])-1, Tau(size[2])-1 ]; 1206end ); 1207 1208############################################################################# 1209## 1210#M TableRowXMod . . . table row for isoclinism families of crossed modules 1211## 1212InstallMethod( TableRowXMod, "generic method for crossed modules", true, 1213 [ Is2DimensionalGroup, IsList ], 0, 1214function( XM, XM_ler ) 1215 1216 local Eler, Iler, i, j, sinif, B; 1217 1218 sinif := IsoclinicXModFamily( XM, XM_ler ); 1219 B := LowerCentralSeries( XM ); 1220 1221Print("---------------------------------------------------------------------------------------------------------------------------------- \n"); 1222Print("---------------------------------------------------------------------------------------------------------------------------------- \n"); 1223Print("Number","\t","Rank","\t\t","M. L.","\t\t","Class","\t","|G/Z|","\t\t", 1224 "|g2|","\t\t","|g3|","\t\t","|g4|","\t\t","|g5| \n"); 1225Print("---------------------------------------------------------------------------------------------------------------------------------- \n"); 1226Print( Length(sinif), "\t", IsoclinicRank( XM ), "\t", 1227 IsoclinicMiddleLength( XM ), "\t", 1228 NilpotencyClassOf2DimensionalGroup( XM ), "\t", 1229 Size( FactorPreXMod( XM, CentreXMod( XM ) ) ) ); 1230 1231 if Length(B) > 1 then 1232 for i in [2..Length(B)] do 1233 Print( "\t" ); 1234 Print( Size( B[i] ) ); 1235 od; 1236 fi; 1237Print("\n---------------------------------------------------------------------------------------------------------------------------------- \n"); 1238 return sinif; 1239end ); 1240