1############################################################################## 2## 3#W gp3obj.gi GAP4 package `XMod' Chris Wensley 4## Alper Odabas 5## This file implements generic methods for (pre-)crossed squares 6## and (pre-)cat2-groups. 7## 8#Y Copyright (C) 2001-2019, Chris Wensley et al, 9#Y School of Computer Science, Bangor University, U.K. 10 11############################################################################# 12## 13#M IsPerm3DimensionalGroup . . check whether the 4 sides are perm 2d-groups 14#M IsFp3DimensionalGroup . . . . check whether the 4 sides are fp 2d-groups 15#M IsPc3DimensionalGroup . . . . check whether the 4 sides are pc 2d-groups 16## 17InstallMethod( IsPerm3DimensionalGroup, "generic method for 3d-group objects", 18 true, [ IsHigherDimensionalGroup ], 0, 19function( obj ) 20 return ( IsPermGroup( Up2DimensionalGroup(obj) ) 21 and IsPermGroup( Left2DimensionalGroup(obj) ) 22 and IsPermGroup( Right2DimensionalGroup(obj) ) 23 and IsPermGroup( Down2DimensionalGroup(obj) ) 24 and IsPermGroup( Diagonal2DimensionalGroup(obj) ) ); 25end ); 26 27InstallMethod( IsFp3DimensionalGroup, "generic method for 3d-group objects", 28 true, [ IsHigherDimensionalGroup ], 0, 29function( obj ) 30 return ( IsFpGroup( Up2DimensionalGroup(obj) ) 31 and IsFpGroup( Left2DimensionalGroup(obj) ) 32 and IsFpGroup( Right2DimensionalGroup(obj) ) 33 and IsFpGroup( Down2DimensionalGroup(obj) ) 34 and IsFpGroup( Diagonal2DimensionalGroup(obj) ) ); 35end ); 36 37InstallMethod( IsPc3DimensionalGroup, "generic method for 3d-group obj ects", 38 true, [ IsHigherDimensionalGroup ], 0, 39function( obj ) 40 return ( IsPcGroup( Up2DimensionalGroup(obj) ) 41 and IsPcGroup( Left2DimensionalGroup(obj) ) 42 and IsPcGroup( Right2DimensionalGroup(obj) ) 43 and IsPcGroup( Down2DimensionalGroup(obj) ) 44 and IsPcGroup( Diagonal2DimensionalGroup(obj) ) ); 45end ); 46 47############################################################################## 48## 49#M IsCrossedPairing 50#M CrossedPairingObj( [<src1>,<src2>],<rng>,<map> ) .. make a crossed pairing 51## 52InstallMethod( IsCrossedPairing, "generic method for mappings", true, 53 [ IsGeneralMapping ], 0, 54function( map ) 55 return ( HasSource( map ) and HasRange( map ) 56 and HasCrossedPairingMap( map ) ); 57end ); 58 59InstallMethod( CrossedPairingObj, "for a general mapping", true, 60 [ IsList, IsGroup, IsGeneralMapping ], 0, 61function( src, rng, map ) 62 63 local obj; 64 65 obj := rec(); 66 if not ( Length(src)=2 ) and IsGroup(src[1]) and IsGroup(src[2]) then 67 Error( "the first parameter should be a list of two groups" ); 68 fi; 69 ObjectifyWithAttributes( obj, CrossedPairingType, 70 Source, src, 71 Range, rng, 72 CrossedPairingMap, map, 73 IsCrossedPairing, true ); 74 return obj; 75end ); 76 77InstallMethod( PrintObj, "method for a crossed pairing", true, 78 [ IsCrossedPairing ], 0, 79function( h ) 80 local map; 81 map := CrossedPairingMap( h ); 82 Print( "crossed pairing: ", Source(map), " -> ", Range(map) ); 83end ); 84 85############################################################################# 86## 87#M ImageElmCrossedPairing( <map>, <elm> ) . . . . . . . for crossed pairing 88## 89InstallMethod( ImageElmCrossedPairing, "for crossed pairing", true, 90 [ IsCrossedPairing, IsList ], 0, 91function ( xp, elm ) 92 return ImageElmMapping2ArgumentsByFunction( CrossedPairingMap(xp), elm ); 93end ); 94 95############################################################################## 96## 97#M CrossedPairingByCommutators( <grp>, <grp>, <grp> ) . . . . . make an xpair 98## 99InstallMethod( CrossedPairingByCommutators, "for three groups", true, 100 [ IsGroup, IsGroup, IsGroup ], 0, 101function( N, M, L ) 102 103 local map, xp; 104 105 if not IsSubgroup( L, CommutatorSubgroup(N,M) ) then 106 Error( "require CommutatorSubgroup(N,M) <= L" ); 107 fi; 108 map := Mapping2ArgumentsByFunction( [N,M], L, 109 function(c) return Comm( c[1], c[2] ); end ); 110 xp := CrossedPairingObj( [N,M], L, map ); 111 return xp; 112end ); 113 114############################################################################## 115## 116#M CrossedPairingByConjugators( <grp> ) . . . make an xpair : Inn(M)^2 -> M 117## 118InstallMethod( CrossedPairingByConjugators, "for an inner automorphism group", 119 true, [ IsGroup ], 0, 120function( innM ) 121 122 local gens, M, map, xp; 123 124 gens := GeneratorsOfGroup( innM ); 125 if not ForAll( gens, g -> HasConjugatorOfConjugatorIsomorphism(g) ) then 126 Error( "innM is not a group of inner automorphisms" ); 127 fi; 128 M := Source( gens[1] ); 129 map := Mapping2ArgumentsByFunction( [ innM, innM ], M, 130 function(p) 131 local c1, c2; 132 c1 := ConjugatorOfConjugatorIsomorphism( p[1] ); 133 c2 := ConjugatorOfConjugatorIsomorphism( p[2] ); 134 return Comm( c1, c2 ); end ); 135 xp := CrossedPairingObj( [ innM, innM ], M, map ); 136 return xp; 137end ); 138 139############################################################################## 140## 141#M CrossedPairingByDerivations( <xmod> ) . . . make an actor crossed pairing 142## 143InstallMethod( CrossedPairingByDerivations, "for a crossed module", true, 144 [ IsXMod ], 0, 145function( X0 ) 146 147 local SX, RX, WX, reg, imlist, map; 148 149 SX := Source( X0 ); 150 RX := Range( X0 ); 151 WX := WhiteheadPermGroup( X0 ); 152 reg := RegularDerivations( X0 ); 153 imlist := ImagesList( reg ); 154 map := Mapping2ArgumentsByFunction( [RX,WX], SX, 155 function(t) 156 local pos, chi; 157 pos := Position( Elements( WX ), t[2] ); 158 chi := DerivationByImages( X0, imlist[pos] ); 159 return DerivationImage( chi, t[1] ); 160 end ); 161 return CrossedPairingObj( [RX,WX], SX, map ); 162end ); 163 164############################################################################## 165## 166#M CrossedPairingByPreImages( <xmod>, <xmod> ) . . . inner autos -> x-pairing 167## 168InstallMethod( CrossedPairingByPreImages, "for two crossed modules", 169 true, [ IsXMod, IsXMod ], 0, 170function( up, lt ) 171 172 local L, M, N, kappa, lambda, map, xp; 173 174 L := Source( up ); 175 if not ( Source( lt ) = L ) then 176 Error( "up and lt should have the same source" ); 177 fi; 178 M := Range( up ); 179 N := Range( lt ); 180 kappa := Boundary( up ); 181 lambda := Boundary( lt ); 182 map := Mapping2ArgumentsByFunction( [N,M], L, 183 function( c ) 184 local lm, ln; 185 lm := PreImagesRepresentative( kappa, c[2] ); 186 ln := PreImagesRepresentative( lambda, c[1] ); 187 return Comm( ln, lm ); 188 end ); 189 xp := CrossedPairingObj( [N,M], L, map ); 190 return xp; 191end ); 192 193############################################################################## 194## 195#M CrossedPairingBySingleXModAction( <xmod>, <subxmod> ) . action -> x-pairing 196#M PrincipalCrossedPairing( <xmod > ) 197## 198InstallMethod( CrossedPairingBySingleXModAction, "for xmod and normal subxmod", 199 true, [ IsXMod, IsXMod ], 0, 200function( rt, lt ) 201 202 local M, L, N, act, map, xp; 203 204 if not IsNormalSub2DimensionalDomain( rt, lt ) then 205 Error( "lt not a normal subxmod of rt" ); 206 fi; 207 M := Source( rt ); 208 L := Source( lt ); 209 N := Range( lt ); 210 act := XModAction( rt ); 211 map := Mapping2ArgumentsByFunction( [N,M], L, 212 function( c ) 213 return ImageElm( ImageElm( act, c[1] ), c[2]^(-1) ) * c[2]; 214 end ); 215 xp := CrossedPairingObj( [N,M], L, map ); 216 return xp; 217end ); 218 219InstallMethod( PrincipalCrossedPairing, "for an xmod", true, [ IsXMod ], 0, 220function( X0 ) 221 return CrossedPairingBySingleXModAction( X0, X0 ); 222end ); 223 224############################################################################# 225## 226#M IsPreCrossedSquare . . . . . . . . . . . . check that the square commutes 227## 228InstallMethod( IsPreCrossedSquare, "generic method for a pre-crossed square", 229 true, [ IsHigherDimensionalGroup ], 0, 230function( PXS ) 231 232 local up, lt, rt, dn, dg, L, M, N, P, kappa, lambda, mu, nu, delta, 233 lambdanu, kappamu, ok, actrt, rngactrt, actdn, rngactdn, 234 genN, genM, imactNM, actNM, imactMN, actMN, morupdn, morltrt; 235 236 if not IsPreCrossedSquareObj( PXS ) then 237 return false; 238 fi; 239 up := Up2DimensionalGroup( PXS ); 240 lt := Left2DimensionalGroup( PXS ); 241 rt := Right2DimensionalGroup( PXS ); 242 dn := Down2DimensionalGroup( PXS ); 243 dg := Diagonal2DimensionalGroup( PXS ); 244 L := Source( up ); 245 M := Range( up ); 246 N := Source( dn ); 247 P := Range( dn ); 248 if not ( ( L = Source(lt) ) and ( N = Range(lt) ) and 249 ( L = Source(dg) ) and ( P = Range(dg) ) and 250 ( M = Source(rt) ) and ( P = Range(rt) ) ) then 251 Info( InfoXMod, 2, "Incompatible source/range" ); 252 return false; 253 fi; 254 ## checks for the diagonal 255 delta := Boundary( dg ); 256 lambda := Boundary( lt ); 257 nu := Boundary( dn ); 258 lambdanu := lambda * nu; 259 kappa := Boundary( up ); 260 mu := Boundary( rt ); 261 kappamu := kappa * mu; 262 if not ( lambdanu = delta ) and ( kappamu = delta ) then 263 Info( InfoXMod, 2, "boundaries in square do not commute" ); 264 return false; 265 fi; 266 # construct the cross-diagonal actions 267 actrt := XModAction( rt ); 268 rngactrt := Range( actrt ); 269 actdn := XModAction( dn ); 270 rngactdn := Range( actdn ); 271 genM := GeneratorsOfGroup( M ); 272 genN := GeneratorsOfGroup( N ); 273 imactNM := List( genN, n -> ImageElm( actrt, ImageElm( nu, n ) ) ); 274 actNM := GroupHomomorphismByImages( N, rngactrt, genN, imactNM ); 275 imactMN := List( genM, m -> ImageElm( actdn, ImageElm( mu, m ) ) ); 276 actMN := GroupHomomorphismByImages( M, rngactdn, genM, imactMN ); 277 SetCrossDiagonalActions( PXS, [ actNM, actMN ] ); 278 #? compatible actions to be checked? 279 morupdn := PreXModMorphism( up, dn, lambda, mu ); 280 morltrt := PreXModMorphism( lt, rt, kappa, nu ); 281 if not ( IsPreXModMorphism(morupdn) and IsPreXModMorphism(morltrt) ) then 282 Info( InfoXMod, 2, "morupdn and/or modltrt not prexmod morphisms" ); 283 return false; 284 fi; 285 return true; 286end ); 287 288############################################################################# 289## 290#M IsCrossedSquare . . . . . . . . check all the axioms for a crossed square 291## 292InstallMethod( IsCrossedSquare, "generic method for a crossed square", 293 true, [ IsHigherDimensionalGroup ], 0, 294function( XS ) 295 296 local up, lt, rt, dn, L, M, N, P, kappa, lambda, mu, nu, 297 lambdanu, kappamu, autu, autl, actdg, dg, ok, morud, morlr, 298 genL, genM, genN, genP, actup, actlt, actrt, actdn, l, p, 299 xp, x, y, z, m, n, m2, n2, am, an, apdg, aprt, apdn, nboxm; 300 301 if not ( IsPreCrossedSquare( XS ) and HasCrossedPairing( XS ) ) then 302 return false; 303 fi; 304 up := Up2DimensionalGroup( XS ); 305 lt := Left2DimensionalGroup( XS ); 306 rt := Right2DimensionalGroup( XS ); 307 dn := Down2DimensionalGroup( XS ); 308 dg := Diagonal2DimensionalGroup( XS ); 309 L := Source( up ); 310 M := Range( up ); 311 N := Source( dn ); 312 P := Range( dn ); 313 kappa := Boundary( up ); 314 lambda := Boundary( lt ); 315 mu := Boundary( rt ); 316 nu := Boundary( dn ); 317 genL := GeneratorsOfGroup( L ); 318 genM := GeneratorsOfGroup( M ); 319 genN := GeneratorsOfGroup( N ); 320 genP := GeneratorsOfGroup( P ); 321 actup := XModAction( up ); 322 actlt := XModAction( lt ); 323 actrt := XModAction( rt ); 324 actdn := XModAction( dn ); 325 actdg := XModAction( dg ); 326 ## check that kappa,lambda preserve the action of P 327 for p in genP do 328 apdg := ImageElm( actdg, p ); 329 aprt := ImageElm( actrt, p ); 330 apdn := ImageElm( actdn, p ); 331 for l in genL do 332 if not ( ImageElm( kappa, ImageElm( apdg, l ) ) 333 = ImageElm( aprt, ImageElm( kappa, l ) ) ) then 334 Info( InfoXMod, 2, "action of P on up is not preserved" ); 335 return false; 336 fi; 337 if not ( ImageElm( lambda, ImageElm( apdg, l ) ) 338 = ImageElm( apdn, ImageElm( lambda, l ) ) ) then 339 Info( InfoXMod, 2, "action of P on lt is not preserved" ); 340 return false; 341 fi; 342 od; 343 od; 344 ## check the axioms for a crossed pairing 345 xp := CrossedPairing( XS ); 346 for n in genN do 347 for n2 in genN do 348 for m in genM do 349 x := ImageElmCrossedPairing( xp, [ n*n2, m ] ); 350 an := ImageElm( actlt, n2 ); 351 y := ImageElm( an, ImageElmCrossedPairing( xp, [n,m] ) ); 352 z := ImageElmCrossedPairing( xp, [n2,m] ); 353 if not x = y * z then 354 Info( InfoXMod, 2, "n1,n2,m crossed pairing axiom fails" ); 355 return false; 356 fi; 357 od; 358 od; 359 od; 360 for n in genN do 361 for m in genM do 362 for m2 in genM do 363 x := ImageElmCrossedPairing( xp, [ n, m*m2 ] ); 364 am := ImageElm( actup, m2 ); 365 y := ImageElm( am, ImageElmCrossedPairing( xp, [n,m] ) ); 366 if not x = ImageElmCrossedPairing( xp, [n,m2] ) * y then 367 Info( InfoXMod, 2, "n,m1,m2 crossed pairing axiom fails" ); 368 return false; 369 fi; 370 od; 371 od; 372 od; 373 for p in genP do 374 apdg := ImageElm( actdg, p ); 375 aprt := ImageElm( actrt, p ); 376 apdn := ImageElm( actdn, p ); 377 for n in genN do 378 for m in genM do 379 if not ImageElm( apdg, ImageElmCrossedPairing( xp, [n,m] ) ) 380 = ImageElmCrossedPairing( xp, 381 [ ImageElm( apdn, n ), ImageElm( aprt, m ) ] ) then 382 Info( InfoXMod, 2, "n,m,p crossed pairing axiom fails" ); 383 return false; 384 fi; 385 od; 386 od; 387 od; 388 ## check that kappa,lambda correctly map (n box m) 389 for n in genN do 390 an := ImageElm( actrt, ImageElm( nu, n ) ); 391 for m in genM do 392 am := ImageElm( actdn, ImageElm( mu, m ) ); 393 nboxm := ImageElmCrossedPairing( xp, [n,m] ); 394 if not ImageElm( lambda, nboxm ) = n^(-1) * ImageElm( am, n ) 395 and ImageElm( kappa, nboxm ) = ImageElm( an, m^(-1) ) * m then 396 Info( InfoXMod, 2, "kappa,lambda do not map nboxm correctly" ); 397 return false; 398 fi; 399 od; 400 od; 401 ## check crossed pairing on images of kappa,lambda 402 for m in genM do 403 ## am := ImageElm( actdg, ImageElm( mu, m ) ); 404 am := ImageElm( actup, m ); 405 for l in genL do 406 if not ( ImageElmCrossedPairing( xp, [ImageElm(lambda,l),m] ) 407 = l^(-1) * ImageElm( am, l ) ) then 408 Info( InfoXMod, 2, "incorrect image for (lambda(l) box n)" ); 409 return false; 410 fi; 411 od; 412 od; 413 for n in genN do 414 ## an := ImageElm( actdg, ImageElm( nu, n ) ); 415 an := ImageElm( actlt, n ); 416 for l in genL do 417 if not ( ImageElmCrossedPairing( xp, [n,ImageElm(kappa,l)] ) 418 = ImageElm( an, l^(-1) ) * l ) then 419 Info( InfoXMod, 2, "incorrect image for (n box kappa(l))" ); 420 return false; 421 fi; 422 od; 423 od; 424 return true; 425end ); 426 427############################################################################## 428## 429#M PreCrossedSquareObj ( <up>, <left>, <right>, <down>, <diag>, <pair> ) 430## . . . make a PreCrossedSquare 431## 432InstallMethod( PreCrossedSquareObj, "for prexmods, action and pairing", true, 433 [ IsPreXMod, IsPreXMod, IsPreXMod, IsPreXMod, IsObject, IsObject ], 0, 434function( up, lt, rt, dn, dg, xp ) 435 436 local PS; 437 438 ## test commutativity here? 439 PS := rec(); 440 ObjectifyWithAttributes( PS, PreCrossedSquareObjType, 441 Up2DimensionalGroup, up, 442 Left2DimensionalGroup, lt, 443 Right2DimensionalGroup, rt, 444 Down2DimensionalGroup, dn, 445 Diagonal2DimensionalGroup, dg, 446 CrossedPairing, xp, 447 HigherDimension, 3, 448 IsHigherDimensionalGroup, true ); 449 if not IsPreCrossedSquare( PS ) then 450 Info( InfoXMod, 1, "Warning: not a pre-crossed square." ); 451 fi; 452 return PS; 453end ); 454 455############################################################################### 456## 457#F PreCrossedSquare( <up>, <lt>, <rt>, <dn>, <dg>, <xp> ) 5 prexmods + pairing 458#F PreCrossedSquare( <PC2> ) . . . . . . . . . . . . . . for a pre-cat2-group 459## 460InstallGlobalFunction( PreCrossedSquare, function( arg ) 461 462 local nargs, PXS, ok; 463 464 nargs := Length( arg ); 465 ok := true; 466 if ( nargs = 1 ) then 467 if ( HasIsPreCat2Group( arg[1] ) and IsPreCat2Group( arg[1] ) ) then 468 Info( InfoXMod, 1, "pre-crossed square of a pre-cat2-group" ); 469 PXS := PreCrossedSquareOfPreCat2Group( arg[1] ); 470 else 471 ok := false; 472 fi; 473 elif ( nargs = 6 ) then 474 PXS := PreCrossedSquareByPreXMods( 475 arg[1], arg[2], arg[3], arg[4], arg[5], arg[6] ); 476 else 477 ok := false; 478 fi; 479 if not ok then 480 Print( "standard usage for the function PreCrossedSquare:\n" ); 481 Print( " PreCrossedSquare( <up>, <lt>, <rt>, <dn>, <dg>, <xp> );\n" ); 482 Print( " for 5 pre-crossed modules and a crossed pairing\n" ); 483 Print( "or: PreCrossedSquare( <PC2G> ); for a pre-cat2-group> );\n" ); 484 return fail; 485 fi; 486 return PXS; 487end ); 488 489 490############################################################################# 491## 492#F CrossedSquare( <up>, <lt>, <rt>, <dn>, <dg>, <xp> ) 5 xmods and a pairing 493#F CrossedSquare( <L>, <M>, <N>, <P> ) . . . . . . . . by normal subgroups 494#F CrossedSquare( <X0> ) . . . . . . . . . . . . . . . actor crossed square 495#F CrossedSquare( <X0>, <X1> ) . . . . . . . . . . . . by pullback 496#F CrossedSquare( <X0>, <X1> ) . . . . . . . . . . . . by normal subxmod 497#F CrossedSquare( <C2G> ) . . . . . . . . . . . . . . for a cat2-group 498## 499InstallGlobalFunction( CrossedSquare, function( arg ) 500 501 local nargs, XS, ok; 502 503 nargs := Length( arg ); 504 ok := true; 505 if ( nargs = 1 ) then 506 if ( HasIsXMod( arg[1] ) and IsXMod( arg[1] ) ) then 507 Info( InfoXMod, 1, "crossed square by splitting" ); 508 XS := CrossedSquareByXModSplitting( arg[1] ); 509 elif ( HasIsCat2Group( arg[1] ) and IsCat2Group( arg[1] ) ) then 510 Info( InfoXMod, 1, "crossed square of a cat2-group" ); 511 XS := PreCrossedSquareOfPreCat2Group( arg[1] ); 512 else 513 ok := false; 514 fi; 515 elif ( nargs = 2 ) then 516 if ( HasIsXMod( arg[1] ) and IsXMod( arg[1] ) 517 and HasIsXMod( arg[2] ) and IsXMod( arg[2] ) ) then 518 if Range( arg[1] ) = Range( arg[2] ) then 519 Info( InfoXMod, 1, "crossed square by pullback" ); 520 XS := CrossedSquareByPullback( arg[1], arg[2] ); 521 elif IsNormalSub2DimensionalDomain( arg[1], arg[2] ) then 522 Info( InfoXMod, 1, "crossed square by normal subxmod" ); 523 XS := CrossedSquareByNormalSubXMod( arg[1], arg[2] ); 524 else 525 ok := false; 526 fi; 527 else 528 ok := false; 529 fi; 530 elif ( nargs = 4 ) and ForAll( arg, a -> IsGroup(a) ) then 531 XS := CrossedSquareByNormalSubgroups(arg[1],arg[2],arg[3],arg[4]); 532 elif ( nargs = 6 ) then 533 XS := CrossedSquareByXMods(arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]); 534 else 535 ok := false; 536 fi; 537 if not ok then 538 Print( "standard usage for the function CrossedSquare:\n" ); 539 Print( " CrossedSquare( <up>, <lt>, <rt>, <dn>, <dg>, <xp> );\n" ); 540 Print( " for 5 crossed modules and a crossed pairing\n" ); 541 Print( "or: CrossedSquare( <L>, <M>, <N>, <P> ); " ); 542 Print( "for 3 normal subgroups of P\n" ); 543 Print( "or: CrossedSquare( <X0>, <X1> ); for a pullback\n" ); 544 Print( "or: CrossedSquare( <X0>, <X1> ); for a normal subxmod\n" ); 545 Print( "or: CrossedSquare( <X0> ); for splitting an xmod\n" ); 546 Print( "or: CrossedSquare( <C2G> ); for a cat2-group> );\n" ); 547 return fail; 548 fi; 549 return XS; 550end ); 551 552############################################################################## 553## 554#M PreCrossedSquareByPreXMods . . pre-crossed square from 5 pre-xmods + xpair 555#M CrossedSquareByXMods . . . . . . . . . crossed square from 5 xmods + xpair 556## 557InstallMethod( PreCrossedSquareByPreXMods, "default pre-crossed square", true, 558 [ IsPreXMod, IsPreXMod, IsPreXMod, IsPreXMod, IsPreXMod, IsCrossedPairing ], 559 0, 560function( up, left, right, down, diag, xp ) 561 562 local L, M, N, P, kappa, lambda, mu, nu, delta, PXS; 563 564 L := Source( up ); 565 M := Range( up ); 566 N := Source( down ); 567 P := Range( down ); 568 kappa := Boundary( up ); 569 lambda := Boundary( left ); 570 mu := Boundary( right ); 571 nu := Boundary( down ); 572 delta := Boundary( diag ); 573 ## checks 574 if not ( ( L = Source( left ) ) and ( N = Range( left ) ) 575 and ( M = Source( right ) ) and ( P = Range( right ) ) 576 and ( L = Source( diag ) ) and ( P = Range( diag ) ) ) then 577 Error( "sources and ranges not matching" ); 578 fi; 579 if not ( ( L = Range( xp ) ) and ( [N,M] = Source( xp ) ) ) then 580 Error( "incorrect source/range for crossed pairing" ); 581 fi; 582 583 PXS := PreCrossedSquareObj( up, left, right, down, diag, xp ); 584 if not IsPreCrossedSquare( PXS ) then 585 Error( "PXS fails to be a crossed square" ); 586 fi; 587 return PXS; 588end ); 589 590InstallMethod( CrossedSquareByXMods, "default crossed square", true, 591 [ IsXMod, IsXMod, IsXMod, IsXMod, IsXMod, IsCrossedPairing ], 0, 592function( up, left, right, down, diag, xp ) 593 594 local XS; 595 596 XS := PreCrossedSquareByPreXMods( up, left, right, down, diag, xp ); 597 if not IsCrossedSquare( XS ) then 598 Info( InfoXMod, 1, "XS fails to be a crossed square" ); 599 return fail; 600 fi; 601 return XS; 602end ); 603 604############################################################################## 605## 606#M CrossedSquareByNormalSubgroups . . . crossed square from normal L,M,N in P 607## 608InstallMethod( CrossedSquareByNormalSubgroups, "conjugation crossed square", 609 true, [ IsGroup, IsGroup, IsGroup, IsGroup ], 0, 610function( L, M, N, P ) 611 612 local XS, up, lt, rt, dn, dg, xp, diag; 613 614 if not ( IsNormal( P, M ) and IsNormal( P, N ) and IsNormal( L, P ) ) then 615 Error( "M,N,L fail to be normal subgroups of P" ); 616 fi; 617 if not ( IsNormal( M, L ) and IsNormal( N, L ) ) then 618 Error( "L fails to be a normal subgroup of both M and N" ); 619 fi; 620 if not ( IsSubgroup( Intersection(M,N), L ) 621 and IsSubgroup( L, CommutatorSubgroup(M,N) ) ) then 622 Error( "require CommutatorSubgroup(M,N) <= L <= Intersection(M,N)" ); 623 fi; 624 up := XModByNormalSubgroup( M, L ); 625 lt := XModByNormalSubgroup( N, L ); 626 rt := XModByNormalSubgroup( P, M ); 627 dn := XModByNormalSubgroup( P, N ); 628 dg := XModByNormalSubgroup( P, L ); 629 ## define the pairing as a commutator 630 xp := CrossedPairingByCommutators( N, M, L ); 631 XS := PreCrossedSquareObj( up, lt, rt, dn, dg, xp ); 632## SetIsCrossedSquare( XS, true ); 633## SetIs3DimensionalGroup( XS, true ); 634 SetDiagonal2DimensionalGroup( XS, dg ); 635 if not IsCrossedSquare( XS ) then 636 Error( "XS fails to be a crossed square by normal subgroups" ); 637 fi; 638 return XS; 639end ); 640 641InstallMethod( CrossedSquareByNormalSubgroups, 642 "conjugation crossed square", true, [ IsGroup, IsGroup, IsGroup ], 0, 643function( M, N, P ) 644 645 local XS, genP, genM, genN, L, genL, u, d, l, r, a, p, diag; 646 647 if not ( IsNormal( P, M ) and IsNormal( P, N ) ) then 648 return fail; 649 fi; 650 L := Intersection( M, N ); 651 return CrossedSquareByNormalSubgroups( L, M, N, P ); 652end ); 653 654############################################################################### 655## 656#M CrossedSquareByNormalSubXMod . crossed square from xmod and normal subxmod 657## 658InstallMethod( CrossedSquareByNormalSubXMod, "for an xmod and normal subxmod", 659 true, [ IsXMod, IsXMod ], 0, 660function( rt, lt ) 661 662 local M, L, up, P, N, dn, xp, dg, XS; 663 664 if not IsNormalSub2DimensionalDomain( rt, lt ) then 665 return fail; 666 fi; 667 M := Source( rt ); 668 L := Source( lt ); 669 up := XModByNormalSubgroup( M, L ); 670 P := Range( rt ); 671 N := Range( lt ); 672 dn := XModByNormalSubgroup( P, N ); 673 xp := CrossedPairingBySingleXModAction( rt, lt ); 674 dg := SubXMod( rt, L, P ); 675 XS := PreCrossedSquareObj( up, lt, rt, dn, dg, xp ); 676 if not IsCrossedSquare( XS ) then 677 Error( "XS fails to be a crossed square by normal subxmod" ); 678 fi; 679 return XS; 680end ); 681 682############################################################################### 683## 684#M CrossedSquareByXModSplitting . . . xsq by surjection followed by injection 685## 686InstallMethod( CrossedSquareByXModSplitting, "for an xmod", true, [ IsXMod ], 0, 687function( X0 ) 688 689 local S, R, bdy, Q, up, dn, xp, XS; 690 691 S := Source( X0 ); 692 R := Range( X0 ); 693 Q := ImagesSource( Boundary( X0 ) ); 694 up := SubXMod( X0, S, Q ); 695 dn := XModByNormalSubgroup( R, Q ); 696 xp := CrossedPairingByPreImages( up, up ); 697 XS := PreCrossedSquareObj( up, up, dn, dn, X0, xp ); 698## SetIsCrossedSquare( XS, true ); 699 if not IsCrossedSquare( XS ) then 700 Error( "XS fails to be a crossed square by xmod splitting" ); 701 fi; 702 return XS; 703end ); 704 705############################################################################## 706## 707#M CrossedSquareByPullback . . . . . . . . for two xmods with a common range 708## 709InstallMethod( CrossedSquareByPullback, "for 2 xmods with a common range", 710 true, [ IsXMod, IsXMod ], 0, 711function( dn, rt ) 712 713 local M, N, P, actM, actN, mu, nu, L, genL, lenL, Linfo, dp, dpinfo, 714 embM, embN, kappa, lambda, map, xp, autL, genLN, genLM, genLNP, 715 genLMP, genP, lenP, imactPL, i, g, ima, a, actPL, genN, lenN, 716 imactNL, actNL, lt, genM, lenM, imactML, actML, up, 717 imdelta, delta, dg, XS; 718 719 M := Source( rt ); 720 N := Source( dn ); 721 P := Range( rt ); 722 if not ( Range( dn ) = P ) then 723 Error( "the two xmods should have a common range" ); 724 fi; 725 actM := XModAction( rt ); 726 actN := XModAction( dn ); 727 mu := Boundary( rt ); 728 nu := Boundary( dn ); 729 L := Pullback( nu, mu ); 730 genL := GeneratorsOfGroup( L ); 731 lenL := Length( genL ); 732 Linfo := PullbackInfo( L ); 733 if HasName(M) and HasName(N) and HasName(P) then 734 SetName( L, Concatenation("(",Name(N)," x_",Name(P)," ",Name(M),")") ); 735 fi; 736 dp := Linfo!.directProduct; 737 dpinfo := DirectProductInfo( dp ); 738 embN := Embedding( dp, 1 ); 739 embM := Embedding( dp, 2 ); 740 lambda := Linfo!.projections[1]; 741 genLN := List( genL, l -> ImageElm( lambda, l ) ); 742 kappa := Linfo!.projections[2]; 743 genLM := List( genL, l -> ImageElm( kappa, l ) ); 744 ## construct the crossed pairing 745 map := Mapping2ArgumentsByFunction( [N,M], L, 746 function( c ) 747 local n, m, nun, mum, n2, m2, l; 748 n := c[1]; 749 m := c[2]; 750 nun := ImageElm( nu, n ); 751 mum := ImageElm( mu, m ); 752 ## h(n,m) = (n^{-1}.n^mum, (m^{-1})^nun.m) 753 n2 := n^(-1) * ImageElm(ImageElm(actN,mum),n); 754 m2 := ImageElm(ImageElm(actM,nun),m^(-1)) * m; 755 l := ImageElm( embN, n2 ) * ImageElm( embM, m2 ); 756 if not ( l in L ) then 757 Error( "element l appears not to be in L" ); 758 fi; 759 return l; 760 end ); 761 xp := CrossedPairingObj( [N,M], L, map ); 762 autL := AutomorphismGroup( L ); 763 genP := GeneratorsOfGroup( P ); 764 lenP := Length( genP ); 765 imactPL := ListWithIdenticalEntries( lenP, 0 ); 766 for i in [1..lenP] do 767 g := genP[i]; 768 genLNP := List( genLN, n -> ImageElm( ImageElm( actN, g ), n ) ); 769 genLMP := List( genLM, m -> ImageElm( ImageElm( actM, g ), m ) ); 770 ima := List( [1..lenL], j -> ImageElm( embN, genLNP[j] ) 771 * ImageElm( embM, genLMP[j] ) ); 772 a := GroupHomomorphismByImages( L, L, genL, ima ); 773 imactPL[i] := a; 774 od; 775 actPL := GroupHomomorphismByImages( P, autL, genP, imactPL ); 776 imdelta := List( genL, l -> ImageElm( nu, ImageElm( lambda, l ) ) ); 777 delta := GroupHomomorphismByImages( L, P, genL, imdelta ); 778 dg := XModByBoundaryAndAction( delta, actPL ); 779 genN := GeneratorsOfGroup( N ); 780 lenN := Length( genN ); 781 imactNL := ListWithIdenticalEntries( lenN, 0 ); 782 for i in [1..lenN] do 783 g := ImageElm( nu, genN[i] ); 784 a := ImageElm( actPL, g ); 785 imactNL[i] := a; 786 od; 787 actNL := GroupHomomorphismByImages( N, autL, genN, imactNL ); 788 lt := XMod( lambda, actNL ); 789 genM := GeneratorsOfGroup( M ); 790 lenM := Length( genM ); 791 imactML := ListWithIdenticalEntries( lenM, 0 ); 792 for i in [1..lenM] do 793 g := ImageElm( mu, genM[i] ); 794 a := ImageElm( actPL, g ); 795 imactML[i] := a; 796 od; 797 actML := GroupHomomorphismByImages( M, autL, genM, imactML ); 798 up := XMod( kappa, actML ); 799 XS := PreCrossedSquareObj( up, lt, rt, dn, dg, xp ); 800## SetIsCrossedSquare( XS, true ); 801 if not IsCrossedSquare( XS ) then 802 Error( "XS fails to be a crossed square by pullback" ); 803 fi; 804 return XS; 805end ); 806 807############################################################################### 808## 809#M ActorCrossedSquare . . . create a crossed square from an xmod and its actor 810## 811InstallMethod( ActorCrossedSquare, "actor crossed square", true, [ IsXMod ], 0, 812function( X0 ) 813 814 local XS, WX, LX, NX, AX, xp; 815 816 AX := ActorXMod( X0 ); 817 WX := WhiteheadXMod( X0 ); 818 NX := NorrieXMod( X0 ); 819 LX := LueXMod( X0 ); 820 ## define the pairing as evaluation of a derivation 821 xp := CrossedPairingByDerivations( X0 ); 822 ## XS := PreCrossedSquareObj( X0, WX, NX, AX, da, xp ); 823 XS := PreCrossedSquareObj( WX, X0, AX, NX, LX, xp ); 824## SetIsCrossedSquare( XS, true ); 825 if not IsCrossedSquare( XS ) then 826 Error( "XS fails to be an actor crossed square" ); 827 fi; 828 return XS; 829end ); 830 831############################################################################### 832## 833#M CrossedSquareByAutomorphismGroup . . . crossed square G -> Inn(G) -> Aut(G) 834## 835InstallMethod( CrossedSquareByAutomorphismGroup, "G -> Inn(G) -> Aut(G)", 836 true, [ IsGroup ], 0, 837function( G ) 838 839 local genG, innG, up, autG, lt, dg, xp, XS; 840 841 genG := GeneratorsOfGroup( G ); 842 innG := InnerAutomorphismsByNormalSubgroup( G, G ); 843 if ( not HasName( innG ) and HasName( G ) ) then 844 SetName( innG, Concatenation( "Inn(", Name( G ), ")" ) ); 845 fi; 846 SetIsGroupOfAutomorphisms( innG, true ); 847 up := XModByGroupOfAutomorphisms( G, innG ); 848 autG := AutomorphismGroup( G ); 849 if ( not HasName( autG ) and HasName( G ) ) then 850 SetName( autG, Concatenation( "Aut(", Name( G ), ")" ) ); 851 fi; 852 if not IsSubgroup( autG, innG ) then 853 Error( "innG is not a subgroup of autG" ); 854 fi; 855 dg := XModByAutomorphismGroup( G ); 856 lt := XModByNormalSubgroup( autG, innG ); 857 ## define the pairing 858 xp := CrossedPairingByConjugators( innG ); 859 XS := PreCrossedSquareObj( up, up, lt, lt, dg, xp ); 860## SetIsCrossedSquare( XS, true ); 861 if not IsCrossedSquare( XS ) then 862 Error( "XS fails to be a crossed square by automorphism group" ); 863 fi; 864 return XS; 865end ); 866 867############################################################################# 868## 869#M Name . . . . . . . . . . . . . . . . . . . . . for a 3-dimensional group 870## 871InstallOtherMethod( Name, "method for a pre-crossed square", true, 872 [ IsHigherDimensionalGroup ], 0, 873function( PS ) 874 875 local nul, nur, ndl, ndr, name, mor; 876 877 if not ( HigherDimension( PS ) = 3 ) then 878 TryNextMethod(); 879 else 880 if HasName( Source( Up2DimensionalGroup( PS ) ) ) then 881 nul := Name( Source( Up2DimensionalGroup( PS ) ) ); 882 else 883 nul := ".."; 884 fi; 885 if HasName( Range( Up2DimensionalGroup( PS ) ) ) then 886 nur := Name( Range( Up2DimensionalGroup( PS ) ) ); 887 else 888 nur := ".."; 889 fi; 890 if HasName( Source( Down2DimensionalGroup( PS ) ) ) then 891 ndl := Name( Source( Down2DimensionalGroup( PS ) ) ); 892 else 893 ndl := ".."; 894 fi; 895 if HasName( Range( Down2DimensionalGroup( PS ) ) ) then 896 ndr := Name( Range( Down2DimensionalGroup( PS ) ) ); 897 else 898 ndr := ".."; 899 fi; 900 name := Concatenation( "[", nul, "->", nur, ",", ndl, "->", ndr, "]" ); 901 SetName( PS, name ); 902 return name; 903 fi; 904end ); 905 906############################################################################# 907## 908#M Size . . . . . . . . . . . . . . . . . . . . . for a 3-dimensional group 909## 910InstallOtherMethod( Size, "method for a 3-dimensional group", true, 911 [ IsHigherDimensionalGroup ], 0, 912function( PS ) 913 return [ Size( Source( Up2DimensionalGroup( PS ) ) ), 914 Size( Range( Up2DimensionalGroup( PS ) ) ), 915 Size( Source( Down2DimensionalGroup( PS ) ) ), 916 Size( Range( Down2DimensionalGroup( PS ) ) ) ]; 917end ); 918 919############################################################################# 920## 921#M IdGroup . . . . . . . . . . . . . . . . . . . . for a 3-dimensional group 922## 923InstallOtherMethod( IdGroup, "method for a 3-dimensional group", true, 924 [ IsHigherDimensionalGroup ], 0, 925function( PS ) 926 return [ IdGroup( Source( Up2DimensionalGroup( PS ) ) ), 927 IdGroup( Range( Up2DimensionalGroup( PS ) ) ), 928 IdGroup( Source( Down2DimensionalGroup( PS ) ) ), 929 IdGroup( Range( Down2DimensionalGroup( PS ) ) ) ]; 930end ); 931 932############################################################################# 933## 934#M StructureDescription . . . . . . . . . . . . . for a 3-dimensional group 935## 936InstallOtherMethod( StructureDescription, "method for a 3-dimensional group", 937 true, [ IsHigherDimensionalGroup ], 0, 938function( PS ) 939 return [ StructureDescription( Source( Up2DimensionalGroup( PS ) ) ), 940 StructureDescription( Range( Up2DimensionalGroup( PS ) ) ), 941 StructureDescription( Source( Down2DimensionalGroup( PS ) ) ), 942 StructureDescription( Range( Down2DimensionalGroup( PS ) ) ) ]; 943end ); 944 945############################################################################## 946## 947#M \=( <dom1>, <dom2> ) . . . . . . . . . . test if two 3d-objects are equal 948## 949InstallMethod( \=, 950 "generic method for two 3d-domains", 951 IsIdenticalObj, [ IsHigherDimensionalGroup, IsHigherDimensionalGroup ], 0, 952function ( dom1, dom2 ) 953 if not ( ( HigherDimension( dom1 ) = 3 ) 954 and ( HigherDimension( dom2 ) = 3 ) ) then 955 TryNextMethod(); 956 else 957 return( 958 ( Up2DimensionalGroup(dom1) = Up2DimensionalGroup(dom2) ) 959 and ( Left2DimensionalGroup(dom1) = Left2DimensionalGroup(dom2) ) 960 and ( Right2DimensionalGroup(dom1) = Right2DimensionalGroup(dom2) ) 961 and ( Down2DimensionalGroup(dom1) = Down2DimensionalGroup(dom2) ) 962 and ( Diagonal2DimensionalGroup(dom1) 963 = Diagonal2DimensionalGroup(dom2) ) ); 964 fi; 965end ); 966 967############################################################################# 968## 969#M String, ViewString, PrintString, ViewObj, PrintObj . . . . for a 3d-group 970## 971InstallMethod( String, "for a 3d-group", true, [ IsPreCrossedSquare ], 0, 972function( g3d ) 973 return( STRINGIFY( "pre-crossed square" ) ); 974end ); 975 976InstallMethod( ViewString, "for a 3d-group", true, [ IsPreCrossedSquare ], 977 0, String ); 978 979InstallMethod( PrintString, "for a 3d-group", true, [ IsPreCrossedSquare ], 980 0, String ); 981 982InstallMethod( PrintObj, "method for a 3d-group", true, 983 [ IsPreCrossedSquare ], 0, 984function( g3d ) 985 986 local L, M, N, P, lenL, lenM, lenN, lenP, len1, len2, j, q1, q2, 987 ispsq, arrow, ok, n, i; 988 989 if HasName( g3d ) then 990 Print( Name( g3d ), "\n" ); 991 else 992 if ( HasIsPreCrossedSquare( g3d ) and IsPreCrossedSquare( g3d ) ) then 993 ispsq := true; 994 arrow := " -> "; 995 else 996 ispsq := false; 997 arrow := " => "; 998 fi; 999 L := Source( Up2DimensionalGroup( g3d ) ); 1000 M := Range( Up2DimensionalGroup( g3d ) ); 1001 N := Source( Down2DimensionalGroup( g3d ) ); 1002 P := Range( Down2DimensionalGroup( g3d ) ); 1003 ok := HasName(L) and HasName(M) and HasName(N) and HasName(P); 1004 if ok then 1005 lenL := Length( Name( L ) ); 1006 lenM := Length( Name( M ) ); 1007 lenN := Length( Name( N ) ); 1008 lenP := Length( Name( P ) ); 1009 len1 := Maximum( lenL, lenN ); 1010 len2 := Maximum( lenM, lenP ); 1011 q1 := QuoInt( len1, 2 ); 1012 q2 := QuoInt( len2, 2 ); 1013 Print( "[ " ); 1014 for j in [1..lenN-lenL] do Print(" "); od; 1015 Print( Name(L), arrow, Name(M) ); 1016 for j in [1..lenP-lenM] do Print(" "); od; 1017 Print( " ]\n[ " ); 1018 for j in [1..q1] do Print(" "); od; 1019 Print( "|" ); 1020 for j in [1..q1+RemInt(len1,2)+2+q2+RemInt(len2,2)] do 1021 Print(" "); 1022 od; 1023 Print( "|" ); 1024 for j in [1..q2] do Print(" "); od; 1025 Print( " ]\n" ); 1026 Print( "[ " ); 1027 for j in [1..lenL-lenN] do Print(" "); od; 1028 Print( Name(N), " -> ", Name(P) ); 1029 for j in [1..lenM-lenP] do Print(" "); od; 1030 Print( " ]\n" ); 1031 else 1032 if ispsq then 1033 if ( HasIsCrossedSquare(g3d) and IsCrossedSquare(g3d) ) then 1034 Print( "crossed square with crossed modules:\n" ); 1035 else 1036 Print( "pre-crossed square with pre-crossed modules:\n" ); 1037 fi; 1038 fi; 1039 Print( " up = ", Up2DimensionalGroup( g3d ), "\n" ); 1040 Print( " left = ", Left2DimensionalGroup( g3d ), "\n" ); 1041 Print( " right = ", Right2DimensionalGroup( g3d ), "\n" ); 1042 Print( " down = ", Down2DimensionalGroup( g3d ), "\n" ); 1043 fi; 1044 fi; 1045end ); 1046 1047InstallMethod( ViewObj, "method for a 3d-group", true, [ IsPreCrossedSquare ], 1048 0, PrintObj ); 1049 1050############################################################################# 1051## 1052#M Display( <g3d> . . . . . . . . . . . . . . . . . . . . display a 3d-group 1053## 1054InstallMethod( Display, "method for a pre-cat2-group", true, 1055 [ IsPreCat2Group ], 0, 1056function( g3d ) 1057 1058 local up, tup, hup, lt, tlt, hlt, rt, trt, hrt, dn, tdn, hdn; 1059 1060 up := Up2DimensionalGroup( g3d ); 1061 tup := TailMap( up ); 1062 hup := HeadMap( up ); 1063 lt := Left2DimensionalGroup( g3d ); 1064 tlt := TailMap( lt ); 1065 hlt := HeadMap( lt ); 1066 rt := Right2DimensionalGroup( g3d ); 1067 trt := TailMap( rt ); 1068 hrt := HeadMap( rt ); 1069 dn := Down2DimensionalGroup( g3d ); 1070 tdn := TailMap( dn ); 1071 hdn := HeadMap( dn ); 1072 Print( "cat2-group with groups: ", 1073 [ Source(up), Range(up), Range(lt), Range(dn) ], "\n" ); 1074 if ( tup = hup ) then 1075 Print( " up tail=head: ", 1076 MappingGeneratorsImages( tup ), "\n" ); 1077 else 1078 Print( " up tail/head: ", 1079 MappingGeneratorsImages( tup ), 1080 MappingGeneratorsImages( hup ), "\n" ); 1081 fi; 1082 if ( tlt = hlt ) then 1083 Print( " left tail=head: ", 1084 MappingGeneratorsImages( tlt ), "\n" ); 1085 else 1086 Print( " left tail/head: ", 1087 MappingGeneratorsImages( tlt ), 1088 MappingGeneratorsImages( hlt ), "\n" ); 1089 fi; 1090 if ( trt = hrt ) then 1091 Print( " left tail=head: ", 1092 MappingGeneratorsImages( trt ), "\n" ); 1093 else 1094 Print( "right tail/head: ", 1095 MappingGeneratorsImages( trt ), 1096 MappingGeneratorsImages( hrt ), "\n" ); 1097 fi; 1098 if ( tdn = hdn ) then 1099 Print( " left tail=head: ", 1100 MappingGeneratorsImages( tdn ), "\n" ); 1101 else 1102 Print( " down tail/head: ", 1103 MappingGeneratorsImages( tdn ), 1104 MappingGeneratorsImages( hdn ), "\n" ); 1105 fi; 1106end ); 1107 1108InstallMethod( Display, "method for a pre-crossed square", true, 1109 [ IsPreCrossedSquare ], 0, 1110function( g3d ) 1111 1112 local L, M, N, P, lenL, lenM, lenN, lenP, len1, len2, j, q1, q2, 1113 ispsq, arrow, ok, n, i; 1114 1115 arrow := " -> "; 1116 L := Source( Up2DimensionalGroup( g3d ) ); 1117 M := Range( Up2DimensionalGroup( g3d ) ); 1118 N := Source( Down2DimensionalGroup( g3d ) ); 1119 P := Range( Down2DimensionalGroup( g3d ) ); 1120 ok := HasName(L) and HasName(M) and HasName(N) and HasName(P); 1121 if ok then 1122 lenL := Length( Name( L ) ); 1123 lenM := Length( Name( M ) ); 1124 lenN := Length( Name( N ) ); 1125 lenP := Length( Name( P ) ); 1126 len1 := Maximum( lenL, lenN ); 1127 len2 := Maximum( lenM, lenP ); 1128 q1 := QuoInt( len1, 2 ); 1129 q2 := QuoInt( len2, 2 ); 1130 Print( "[ " ); 1131 for j in [1..lenN-lenL] do Print(" "); od; 1132 Print( Name(L), arrow, Name(M) ); 1133 for j in [1..lenP-lenM] do Print(" "); od; 1134 Print( " ]\n[ " ); 1135 for j in [1..q1] do Print(" "); od; 1136 Print( "|" ); 1137 for j in [1..q1+RemInt(len1,2)+2+q2+RemInt(len2,2)] do 1138 Print(" "); 1139 od; 1140 Print( "|" ); 1141 for j in [1..q2] do Print(" "); od; 1142 Print( " ]\n" ); 1143 Print( "[ " ); 1144 for j in [1..lenL-lenN] do Print(" "); od; 1145 Print( Name(N), " -> ", Name(P) ); 1146 for j in [1..lenM-lenP] do Print(" "); od; 1147 Print( " ]\n" ); 1148 else 1149 Print( "(pre-)crossed square with (pre-)crossed modules:\n" ); 1150 Print( " up = ", Up2DimensionalGroup( g3d ), "\n" ); 1151 Print( " left = ", Left2DimensionalGroup( g3d ), "\n" ); 1152 Print( " right = ", Right2DimensionalGroup( g3d ), "\n" ); 1153 Print( " down = ", Down2DimensionalGroup( g3d ), "\n" ); 1154 fi; 1155end ); 1156 1157############################################################################# 1158## 1159#M IsPreCat2Group . . . . . . . . . . . check that this is a pre-cat2-group 1160#M IsCat2Group . . . . . . . . . . . . check that the object is a cat2-group 1161## 1162InstallMethod( IsPreCat2Group, "generic method for a pre-cat2-group", 1163 true, [ IsHigherDimensionalGroup ], 0, 1164function( P ) 1165 if not ( IsPreCatnObj( P ) ) then 1166 return false; 1167 fi; 1168 if ( IsPreCatnGroup( P ) and ( HigherDimension( P ) = 3 ) ) then 1169 return true; 1170 else 1171 return false; 1172 fi; 1173end ); 1174 1175InstallMethod( IsCat2Group, "generic method for a cat2-group", 1176 true, [ IsHigherDimensionalGroup ], 0, 1177function( P ) 1178 local ok; 1179 ok := ( HigherDimension( P ) = 3 ) 1180 and IsCat1Group( Up2DimensionalGroup( P ) ) 1181 and IsCat1Group( Left2DimensionalGroup( P ) ) 1182 and IsCat1Group( Right2DimensionalGroup( P ) ) 1183 and IsCat1Group( Down2DimensionalGroup( P ) ) 1184 and IsPreCat1Group( Diagonal2DimensionalGroup( P ) ); 1185 return ok; 1186end ); 1187 1188############################################################################## 1189## 1190#M PreCat2GroupObj( [<up>,<left>,<right>,<down>,<diag>] ) 1191## 1192InstallMethod( PreCat2GroupObj, "for a list of pre-cat1-groups", true, 1193 [ IsList ], 0, 1194function( L ) 1195 1196 local PC, ok; 1197 1198 if not ( Length( L ) = 5 ) then 1199 Error( "there should be 5 pre-cat1-groups in the list L" ); 1200 fi; 1201 PC := rec(); 1202 ObjectifyWithAttributes( PC, PreCat2GroupObjType, 1203 Up2DimensionalGroup, L[1], 1204 Left2DimensionalGroup, L[2], 1205 Right2DimensionalGroup, L[3], 1206 Down2DimensionalGroup, L[4], 1207 Diagonal2DimensionalGroup, L[5], 1208 GeneratingCat1Groups, [ L[1], L[2] ], 1209 HigherDimension, 3, 1210 IsHigherDimensionalGroup, true, 1211 IsPreCat2Group, true, 1212 IsPreCatnGroup, true ); 1213 ok := IsCat2Group( PC ); 1214 return PC; 1215end ); 1216 1217############################################################################# 1218## 1219#F (Pre)Cat2Group( [ up, lt (,diag) ) cat2-group from 2/3 (pre)cat1-groups 1220#F (Pre)Cat2Group( XS ) cat2-group from (pre)crossed square 1221## 1222InstallGlobalFunction( PreCat2Group, function( arg ) 1223 1224 local nargs, up, left, diag, C2G, G1, G2, G3, isoG, genG, 1225 imt, t12, imh, h12, e12, idQ, isoleft, drd, ok; 1226 1227 nargs := Length( arg ); 1228 if not ( nargs in [1,2] ) then 1229 Print( "standard usage: (Pre)Cat2Group( up, left );\n" ); 1230 Print( " or: (Pre)Cat2Group( XS );\n" ); 1231 return fail; 1232 fi; 1233 if ( nargs = 1 ) then 1234 C2G := PreCat2GroupOfPreCrossedSquare( arg[1] ); 1235 else 1236 up := arg[1]; 1237 left := arg[2]; 1238 G1 := Source( up ); 1239 G2 := Source( left ); 1240 ## if the two sources are unequal but isomorphic then make 1241 ## an isomorphic copy of left with the same source as up 1242 if not ( G1 = G2 ) then 1243 isoG := IsomorphismGroups( G2, G1 ); 1244 if ( isoG = fail ) then 1245 Error( "the two arguments do now have the same source" ); 1246 else 1247 idQ := IdentityMapping( Range( left ) ); 1248 isoleft := IsomorphismByIsomorphisms( left, [ isoG, idQ ] ); 1249 left := Range( isoleft ); 1250 fi; 1251 fi; 1252 drd := DetermineRemainingCat1Groups( up, left ); 1253 if ( drd = fail ) then 1254 Info( InfoXMod, 2, "failure determining remaining cat1-groups" ); 1255 return fail; 1256 fi; 1257 C2G := PreCat2GroupByPreCat1Groups( up, left, drd[1], drd[2], drd[3] ); 1258 if ( C2G = fail ) then 1259 return fail; ## Error( "C2G fails to be a PreCat2Group" ); 1260 fi; 1261 fi; 1262 ok := IsPreCat2Group( C2G ); 1263 if ok then 1264 ok := IsCat2Group( C2G ); 1265 return C2G; 1266 else 1267 return fail; 1268 fi; 1269end ); 1270 1271InstallGlobalFunction( Cat2Group, function( arg ) 1272 1273 local C2G, ok; 1274 1275 C2G := PreCat2Group( arg[1], arg[2] ); 1276 ok := not ( C2G = fail ) and IsCat2Group( C2G ); 1277 if ok then 1278 return C2G; 1279 else 1280 return fail; 1281 fi; 1282end ); 1283 1284############################################################################## 1285## 1286#M DetermineRemainingCat1Groups . . . . . . . . . . . . for 2 pre-cat1-groups 1287## 1288InstallMethod( DetermineRemainingCat1Groups, "for up, left pre-cat1-groups", 1289 true, [ IsPreCat1Group, IsPreCat1Group ], 0, 1290function( up, left ) 1291 1292 local G, genG, Q, genQ, R, genR, tu, hu, eu, tl, hl, el, tea, hea, 1293 P, genP, diag, imtd, td, imhd, hd, imed, ed, down, 1294 imtr, tr, imhr, hr, imer, er, right; 1295 1296 G := Source( up ); 1297 if not ( G = Source( left ) ) then 1298 Print( "the two pre-cat1-groups should have the same source\n" ); 1299 fi; 1300 genG := GeneratorsOfGroup( G ); 1301 R := Range( up ); 1302 genR := GeneratorsOfGroup( R ); 1303 Q := Range( left ); 1304 genQ := GeneratorsOfGroup( Q ); 1305 tu := TailMap( up ); 1306 hu := HeadMap( up ); 1307 eu := RangeEmbedding( up ); 1308 tl := TailMap( left ); 1309 hl := HeadMap( left ); 1310 el := RangeEmbedding( left ); 1311 ## check that the 1-maps commute with the 2-maps 1312 tea := tu*eu*tl*el; 1313 hea := hu*eu*hl*el; 1314 if not ( ( tea = tl*el*tu*eu ) 1315 and ( hea = hl*el*hu*eu ) 1316 and ( tu*eu*hl*el = hl*el*tu*eu ) 1317 and ( hu*eu*tl*el = tl*el*hu*eu ) ) then 1318 Info( InfoXMod, 2, "1-maps do not commute with 2-maps" ); 1319 return fail; 1320 fi; 1321 Info( InfoXMod, 2, "yes : 1-maps do commute with the 2-maps" ); 1322 ## more checks? 1323 ## determine the group P 1324 P := Image( tea ); 1325 if not ( Image( hea ) = P ) then 1326 Error( "t*e*a and h*e*a do not have the same range" ); 1327 fi; 1328 genP := GeneratorsOfGroup( P ); 1329 diag := PreCat1GroupByEndomorphisms( tea, hea ); 1330 if ( diag = fail ) then 1331 Print( "diag fails to be a cat1-group\n" ); 1332 return fail; 1333 fi; 1334 ## now construct down 1335 imtd := List( genQ, q -> ImageElm( el * tea, q ) ); 1336 td := GroupHomomorphismByImages( Q, P, genQ, imtd ); 1337 imhd := List( genQ, q -> ImageElm( el * hea, q ) ); 1338 hd := GroupHomomorphismByImages( Q, P, genQ, imhd ); 1339 imed := List( genP, p -> ImageElm( tl, p ) ); 1340 ed := GroupHomomorphismByImages( P, Q, genP, imed ); 1341 down := PreCat1GroupByTailHeadEmbedding( td, hd, ed ); 1342 ## now construct right 1343 imtr := List( genR, r -> ImageElm( eu * tea, r ) ); 1344 tr := GroupHomomorphismByImages( R, P, genR, imtr ); 1345 imhr := List( genR, r -> ImageElm( eu * hea, r ) ); 1346 hr := GroupHomomorphismByImages( R, P, genR, imhr ); 1347 imer := List( genP, p -> ImageElm( tu, p ) ); 1348 er := GroupHomomorphismByImages( P, R, genP, imer ); 1349 right := PreCat1GroupByTailHeadEmbedding( tr, hr, er ); 1350 if ( ( right = fail ) or ( down = fail) ) then 1351 Info( InfoXMod, 2, "right or down fail to be cat1-groups" ); 1352 return fail; 1353 fi; 1354 return [ right, down, diag ]; 1355end ); 1356 1357############################################################################## 1358## 1359#M PreCat2GroupByPreCat1Groups . . . . . . . . . . . for five pre-cat1-groups 1360## 1361InstallMethod( PreCat2GroupByPreCat1Groups, "for five pre-cat1-groups", 1362 true, [ IsPreCat1Group, IsPreCat1Group, IsPreCat1Group, 1363 IsPreCat1Group, IsPreCat1Group ], 0, 1364function( up, left, right, down, diag ) 1365 1366 local G, R, Q, P, genG, tu, hu, tl, hl, tr, hr, td, hd, ta, ha, 1367 imtld, imtur, imhld, imhur, dtld, dtur, dhld, dhur, PC2, ok; 1368 1369 G := Source( up ); 1370 genG := GeneratorsOfGroup( G ); 1371 R := Range( up ); 1372 Q := Range( left ); 1373 P := Range( diag ); 1374 if not ( ( G = Source( left ) ) and ( G = Source( diag ) ) 1375 and ( R = Source( right ) ) and ( P = Range( right ) ) 1376 and ( Q = Source( down ) ) and ( P = Range( down ) ) ) then 1377 Info( InfoXMod, 2, "sources and/or ranges do not agree" ); 1378 return fail; 1379 fi; 1380 tu := TailMap( up ); 1381 hu := HeadMap( up ); 1382 tl := TailMap( left ); 1383 hl := HeadMap( left ); 1384 tr := TailMap( right ); 1385 hr := HeadMap( right ); 1386 td := TailMap( down ); 1387 hd := HeadMap( down ); 1388 ta := TailMap( diag ); 1389 ha := HeadMap( diag ); 1390 1391 imtld := List( genG, g -> ImageElm( td, ImageElm( tl, g ) ) ); 1392 dtld := GroupHomomorphismByImages( G, P, genG, imtld ); 1393 imtur := List( genG, g -> ImageElm( tr, ImageElm( tu, g ) ) ); 1394 dtur := GroupHomomorphismByImages( G, P, genG, imtur ); 1395 imhld := List( genG, g -> ImageElm( hd, ImageElm( hl, g ) ) ); 1396 dhld := GroupHomomorphismByImages( G, P, genG, imhld ); 1397 imhur := List( genG, g -> ImageElm( hr, ImageElm( hu, g ) ) ); 1398 dhur := GroupHomomorphismByImages( G, P, genG, imhur ); 1399 if not ( ( dtld = ta ) and ( dtur= ta ) 1400 and ( dhld = ha ) and ( dhur = ha ) ) then 1401 Info( InfoXMod, 2, "tail and head maps are inconsistent" ); 1402 return fail; 1403 fi; 1404 PC2 := PreCat2GroupObj( [ up, left, right, down, diag ] ); 1405 SetIsPreCat2Group( PC2, true ); 1406 SetIsPreCatnGroup( PC2, true ); 1407 SetHigherDimension( PC2, 3 ); 1408 ok := IsCat2Group( PC2 ); 1409 ok := IsPreCatnGroupByEndomorphisms( PC2 ); 1410 return PC2; 1411end ); 1412 1413############################################################################## 1414## 1415#M AllCat2GroupsWithImagesIterator . . . cat2-groups with given up,left range 1416#M DoAllCat2GroupsWithImagesIterator 1417#M AllCat2GroupsWithImages . . . cat2-groups with specified range for up,left 1418#M AllCat2GroupsWithImagesNumber . . . . # cat2-groups with specified up,left 1419#M AllCat2GroupsWithImagesUpToIsomorphism . . . iso class reps of cat2-groups 1420## 1421BindGlobal( "NextIterator_AllCat2GroupsWithImages", function ( iter ) 1422 1423 local ok, pair, C; 1424 1425 ok := false; 1426 while ( not ok ) and ( not IsDoneIterator( iter ) ) do 1427 pair := NextIterator( iter!.pairsIterator ); 1428 Info( InfoXMod, 1, pair ); 1429 if ( fail in pair ) then 1430 return fail; 1431 fi; 1432 C := Cat2Group( pair[1], pair[2] ); 1433 if ( not ( C = fail ) and IsCat2Group( C ) ) then 1434 return C; 1435 fi; 1436 od; 1437 return fail; 1438end ); 1439 1440BindGlobal( "IsDoneIterator_AllCat2GroupsWithImages", 1441 iter -> IsDoneIterator( iter!.pairsIterator ) 1442); 1443 1444BindGlobal( "ShallowCopy_AllCat2GroupsWithImages", 1445 iter -> rec( group := iter!.group, 1446 pairsIterator := ShallowCopy( iter!.pairsIterator ) 1447 ) 1448); 1449 1450InstallGlobalFunction( "DoAllCat2GroupsWithImagesIterator", 1451function( G, R, Q ) 1452 1453 local upIterator, pairsIterator, ltIterator, iter; 1454 1455 upIterator := AllCat1GroupsWithImageIterator( G, R ); 1456 if ( R = Q ) then 1457 pairsIterator := UnorderedPairsIterator( upIterator ); 1458 else 1459 ltIterator := AllCat1GroupsWithImageIterator( G, Q ); 1460 pairsIterator := CartesianIterator( upIterator, ltIterator ); 1461 fi; 1462 iter := IteratorByFunctions( 1463 rec( group := G, 1464 pairsIterator := ShallowCopy( pairsIterator ), 1465 NextIterator := NextIterator_AllCat2GroupsWithImages, 1466 IsDoneIterator := IsDoneIterator_AllCat2GroupsWithImages, 1467 ShallowCopy := ShallowCopy_AllCat2GroupsWithImages ) ); 1468 return iter; 1469end ); 1470 1471InstallMethod( AllCat2GroupsWithImagesIterator, 1472 "for a group and two subgroups", [ IsGroup, IsGroup, IsGroup ], 0, 1473function ( G, R, Q ) 1474 if not ( IsSubgroup( G, R ) and IsSubgroup( G, Q ) ) then 1475 Error( "R,Q are not subgroups of G" ); 1476 fi; 1477 return DoAllCat2GroupsWithImagesIterator( G, R, Q ); 1478end ); 1479 1480InstallMethod( AllCat2GroupsWithImages, 1481 "for a group and two subgroups", [ IsGroup, IsGroup, IsGroup ], 0, 1482function ( G, R, Q ) 1483 1484 local L0, C; 1485 1486 if not ( IsSubgroup( G, R ) and IsSubgroup( G, Q ) ) then 1487 Error( "R,Q are not subgroups of G" ); 1488 fi; 1489 L0 := [ ]; 1490 for C in AllCat2GroupsWithImagesIterator( G, R, Q ) do 1491 if not ( C = fail ) then 1492 Add( L0, C ); 1493 fi; 1494 od; 1495 return L0; 1496end ); 1497 1498InstallMethod( AllCat2GroupsWithImagesNumber, 1499 "for a group and two subgroups", [ IsGroup, IsGroup, IsGroup ], 0, 1500function ( G, R, Q ) 1501 1502 local num, C; 1503 1504 if not ( IsSubgroup( G, R ) and IsSubgroup( G, Q ) ) then 1505 Error( "R,Q are not subgroups of G" ); 1506 fi; 1507 num := 0; 1508 for C in AllCat2GroupsWithImagesIterator( G, R, Q ) do 1509 if not ( C = fail ) then 1510 num := num+1; 1511 fi; 1512 od; 1513 return num; 1514end ); 1515 1516InstallMethod( AllCat2GroupsWithImagesUpToIsomorphism, 1517 "for a group and two subgroups", [ IsGroup, IsGroup, IsGroup ], 0, 1518function ( G, R, Q ) 1519 1520 local L0, len0, num, GRiter, upiter, up, GQiter, leftiter, left, 1521 C, j, found, iso; 1522 1523 if not ( IsSubgroup( G, R ) and IsSubgroup( G, Q ) ) then 1524 Error( "R,Q are not subgroups of G" ); 1525 fi; 1526 L0 := [ ]; 1527 len0 := 0; 1528 num := 0; 1529 GRiter := AllCat1GroupsWithImageIterator( G, R ); 1530 GQiter := AllCat1GroupsWithImageIterator( G, Q ); 1531 upiter := ShallowCopy( GRiter ); 1532 for up in upiter do 1533 leftiter := ShallowCopy( GQiter ); 1534 for left in leftiter do 1535 C := Cat2Group( up, left ); 1536 if ( not ( C = fail ) and IsCat2Group( C ) ) then 1537 num := num+1; 1538 j := 0; 1539 found := false; 1540 while ( not found ) and ( j < len0 ) do 1541 j := j+1; 1542 iso := IsomorphismPreCat2Groups( C, L0[j] ); 1543 if not ( iso = fail ) then 1544 found := true; 1545 fi; 1546 od; 1547 if not found then 1548 Add( L0, C ); 1549 len0 := len0+1; 1550 if ( InfoLevel( InfoXMod ) > 0 ) then 1551 Display( C ); 1552 Print( "-------------------------------------\n" ); 1553 fi; 1554 fi; 1555 fi; 1556 od; 1557 od; 1558 Info( InfoXMod, 1, "cat2-groups: ", num, " found, ", len0, " classes" ); 1559 return L0; 1560end ); 1561 1562############################################################################## 1563## 1564#M AllCat2Groups . . . . . . . list of cat2-group structures on a given group 1565#O AllCat2GroupsIterator( <gp> ) . . . . . . . iterator for the previous list 1566#F NextIterator_AllCat2Groups( <iter> ) 1567#F IsDoneIterator_AllCat2Groups( <iter> ) 1568#F ShallowCopy_AllCat2Groups( <iter> ) 1569#A AllCat2GroupsNumber( <gp> ) . . . . . . . . . number of these cat2-groups 1570#M AllCat2GroupsUpToIsomorphism . . . iso class reps of cat2-group structures 1571## 1572BindGlobal( "NextIterator_AllCat2Groups", function ( iter ) 1573 local pair, next; 1574 if IsDoneIterator( iter!.imagesIterator ) then 1575 pair := NextIterator( iter!.pairsIterator ); 1576 iter!.imagesIterator := 1577 AllCat2GroupsWithImagesIterator( iter!.group, pair[1], pair[2] ); 1578 fi; 1579 next := NextIterator( iter!.imagesIterator ); 1580 if ( next <> fail ) then 1581 iter!.count := iter!.count + 1; 1582 fi; 1583 return next; 1584end ); 1585 1586BindGlobal( "IsDoneIterator_AllCat2Groups", 1587 iter -> ( IsDoneIterator( iter!.pairsIterator ) 1588 and IsDoneIterator( iter!.imagesIterator ) ) 1589); 1590 1591BindGlobal( "ShallowCopy_AllCat2Groups", 1592 iter -> rec( group := iter!.group, 1593 count := iter!.count, 1594 pairsIterator := ShallowCopy( iter!.pairsIterator ), 1595 imagesIterator := ShallowCopy( iter!.imagesIterator ) 1596 ) 1597); 1598 1599BindGlobal( "DoAllCat2GroupsIterator", 1600function( G ) 1601 1602 local subsIterator, pairsIterator, imagesIterator, iter; 1603 1604 subsIterator := AllSubgroupsIterator( G ); 1605 pairsIterator := UnorderedPairsIterator( subsIterator ); 1606 imagesIterator := IteratorList( [ ] ); 1607 iter := IteratorByFunctions( 1608 rec( group := G, 1609 count := 0, 1610 subsIterator := ShallowCopy( subsIterator ), 1611 pairsIterator := ShallowCopy( pairsIterator ), 1612 imagesIterator := ShallowCopy( imagesIterator ), 1613 NextIterator := NextIterator_AllCat2Groups, 1614 IsDoneIterator := IsDoneIterator_AllCat2Groups, 1615 ShallowCopy := ShallowCopy_AllCat2Groups ) ); 1616 return iter; 1617end ); 1618 1619InstallMethod( AllCat2GroupsIterator, "for a group", [ IsGroup ], 0, 1620 G -> DoAllCat2GroupsIterator( G ) ); 1621 1622InstallMethod( AllCat2Groups, "for a group", [ IsGroup ], 0, 1623function( G ) 1624 1625 local L, omit, pairs, all1, C, genC; 1626 1627 InitCatnGroupRecords( G ); 1628 L := [ ]; 1629 omit := CatnGroupLists( G ).omit; 1630 if not omit then 1631 all1 := AllCat1Groups( G ); 1632 pairs := [ ]; 1633 fi; 1634 for C in AllCat2GroupsIterator( G ) do 1635 if not ( C = fail ) then 1636 Add( L, C ); 1637 if not omit then 1638 genC := GeneratingCat1Groups( C ); 1639 Add( pairs, 1640 [ Position( all1, genC[1] ), Position( all1, genC[2] ) ] ); 1641 fi; 1642 fi; 1643 od; 1644 if not IsBound( CatnGroupNumbers( G ).cat2 ) then 1645 CatnGroupNumbers( G ).cat2 := Length( L ); 1646 fi; 1647 if not omit then 1648 Sort( pairs ); 1649 CatnGroupLists( G ).cat2pairs := pairs; 1650 fi; 1651 return L; 1652end ); 1653 1654InstallMethod( AllCat2GroupsNumber, "for a group", [ IsGroup ], 0, 1655function( G ) 1656 1657 local n, C, all; 1658 1659 InitCatnGroupRecords( G ); 1660 if IsBound( CatnGroupNumbers( G ).cat2 ) then 1661 return CatnGroupNumbers( G ).cat2; 1662 fi; 1663 ## not already known, so perform the calculation 1664 all := AllCat2Groups( G ); 1665 return CatnGroupNumbers( G ).cat2; 1666end ); 1667 1668InstallMethod( AllCat2GroupsUpToIsomorphism, "iso class reps of cat2-groups", 1669 true, [ IsGroup ], 0, 1670function( G ) 1671 1672 local all1, iso1, omit, classes, L, numL, posL, symmnum, symmpos, 1673 prediag, prediagpos, i, C, k, found, iso, genC, perm; 1674 1675 InitCatnGroupRecords( G ); 1676 if not IsBound( CatnGroupNumbers( G ).iso1 ) then 1677 iso1 := AllCat1GroupsUpToIsomorphism( G ); 1678 fi; 1679 all1 := AllCat1Groups( G ); 1680 omit := CatnGroupLists( G ).omit; 1681 if not omit then 1682 classes := [ ]; 1683 fi; 1684 L := [ ]; 1685 numL := 0; 1686 posL := [ ]; 1687 symmnum := 0; 1688 symmpos := [ ]; 1689 prediag := 0; 1690 prediagpos := [ ]; 1691 i := 0; 1692 for C in AllCat2GroupsIterator( G ) do 1693 if not ( C = fail ) then 1694 genC := GeneratingCat1Groups( C ); 1695 i := i+1; 1696 k := 0; 1697 found := false; 1698 while ( not found ) and ( k < numL ) do 1699 k := k+1; 1700 iso := IsomorphismCat2Groups( C, L[k] ); 1701 if ( iso <> fail ) then 1702 found := true; 1703 if not omit then 1704 Add( classes[k], [ Position( all1, genC[1] ), 1705 Position( all1, genC[2] ) ] ); 1706 fi; 1707 fi; 1708 od; 1709 if not found then 1710 Add( L, C ); 1711 Add( posL, i ); 1712 numL := numL + 1; 1713 if ( genC[1] = genC[2] ) then 1714 symmnum := symmnum + 1; 1715 Add( symmpos, numL ); 1716 fi; 1717 if not IsCat1Group( Diagonal2DimensionalGroup( C ) ) then 1718 prediag := prediag + 1; 1719 Add( prediagpos, numL ); 1720 fi; 1721 if not omit then 1722 Add( classes, 1723 [ [ Position(all1,genC[1]), Position(all1,genC[2]) ] ] ); 1724 fi; 1725 fi; 1726 fi; 1727 od; 1728 if not IsBound( CatnGroupNumbers( G ).cat2 ) then 1729 CatnGroupNumbers( G ).cat2 := i; 1730 fi; 1731 if not IsBound( CatnGroupLists( G ).allcat2pos ) then 1732 CatnGroupLists( G ).allcat2pos := posL; 1733 fi; 1734 if not IsBound( CatnGroupNumbers( G ).iso2 ) then 1735 CatnGroupNumbers( G ).iso2 := numL; 1736 CatnGroupNumbers( G ).symm2 := symmnum; 1737 if ( prediag > 0 ) then 1738 CatnGroupNumbers( G ).prediag2 := prediag; 1739 fi; 1740 fi; 1741 Info( InfoXMod, 1, "reps found at positions ", posL ); 1742 if not omit then 1743 perm := Sortex( classes ); 1744 L := Permuted( L, perm ); 1745 CatnGroupLists( G ).cat2classes := classes; 1746 symmpos := List( symmpos, i -> i^perm ); 1747 prediagpos := List( prediagpos, i -> i^perm ); 1748 CatnGroupLists( G ).symmpos := symmpos; 1749 if ( prediag > 0 ) then 1750 CatnGroupLists( G ).prediagpos := prediagpos; 1751 fi; 1752 fi; 1753 return L; 1754end ); 1755 1756InstallMethod( AllCat2GroupFamilies, "gives lists of isomorphic cat2-groups", 1757 true, [ IsGroup ], 0, 1758function( G ) 1759 1760 local reps, cat2, iso2, classes, i, C, k, found, iso; 1761 1762 reps := AllCat2GroupsUpToIsomorphism( G ); 1763 cat2 := CatnGroupNumbers( G ).cat2; 1764 iso2 := CatnGroupNumbers( G ).iso2; 1765 classes := ListWithIdenticalEntries( iso2, 0 ); 1766 for k in [1..iso2] do 1767 classes[k] := [ ]; 1768 od; 1769 i := 0; 1770 for C in AllCat2GroupsIterator( G ) do 1771 if not ( C = fail ) then 1772 i := i+1; 1773 k := 0; 1774 found := false; 1775 while ( not found ) do 1776 k := k+1; 1777 iso := IsomorphismCat2Groups( C, reps[k] ); 1778 if ( iso <> fail ) then 1779 found := true; 1780 Add( classes[k], i ); 1781 fi; 1782 od; 1783 fi; 1784 od; 1785 return classes; 1786end ); 1787 1788############################################################################## 1789## 1790#M TableRowForCat1Groups . . . . . . . . cat1-structure data for a group G 1791#M TableRowForCat2Groups . . . . . . . . cat2-structure data for a group G 1792## 1793InstallMethod( TableRowForCat1Groups, "for a group G", true, [ IsGroup ], 0, 1794function( G ) 1795 1796 local Eler, Iler, i, j, allprecat1, allcat1, B; 1797 1798 allprecat1 := []; 1799 Eler := AllHomomorphisms( G, G ); 1800 Iler := Filtered( Eler, h -> CompositionMapping( h, h ) = h ); 1801 for i in [1..Length(Iler)] do 1802 for j in [1..Length(Iler)] do 1803 if PreCat1GroupByEndomorphisms(Iler[i],Iler[j]) <> fail then 1804 Add(allprecat1,PreCat1GroupByEndomorphisms(Iler[i],Iler[j])); 1805 else 1806 continue; 1807 fi; 1808 od; 1809 od; 1810 allcat1 := Filtered( allprecat1,IsCat1Group ); 1811 B := AllCat1GroupsUpToIsomorphism( G ); 1812 Print( "-----------------------------------------------------------", 1813 "-------------------------------- \n" ); 1814 Print( "-----------------------------------------------------------", 1815 "-------------------------------- \n" ); 1816 Print( "GAP id", "\t\t", "Group Name", "\t", "|End(G)|", "\t", 1817 "|IE(G)|", "\t\t", "C(G)", "\t\t", "|C/~| \n" ); 1818 Print( "-----------------------------------------------------------", 1819 "-------------------------------- \n" ); 1820 Print( "-----------------------------------------------------------", 1821 "-------------------------------- \n" ); 1822 Print( IdGroup(G), "\t", StructureDescription(G), "\t\t", 1823 Length(Eler), "\t\t", Length(Iler), "\t\t", Length(allcat1), 1824 "\t\t", Length(B), "\n" ); 1825 Print( "-----------------------------------------------------------", 1826 "-------------------------------- \n" ); 1827 Print( "-----------------------------------------------------------", 1828 "-------------------------------- \n" ); 1829 return B; 1830end ); 1831 1832InstallMethod( TableRowForCat2Groups, "for a group G", true, [ IsGroup ], 0, 1833function( G ) 1834 1835 local Eler, Iler, i, j, allcat1, Cat2_ler, B, a, n, C1, c1, c2, 1836 PreCat2_ler, Cat2_ler2; 1837 1838 i := IdGroup(G)[1]; 1839 j := IdGroup(G)[2]; 1840 n := Cat1Select(i,j,0);; 1841 Cat2_ler := AllCat2Groups(G); 1842 B := AllCat2GroupsUpToIsomorphism(G);; 1843 Print( "-----------------------------------------------------------", 1844 "-------------------------------- \n" ); 1845 Print( "-----------------------------------------------------------", 1846 "-------------------------------- \n" ); 1847 Print( "GAP id", "\t\t", "Group Name", "\t\t", "C2(G)", "\t\t", 1848 "|C2/~| \n"); 1849 Print( "-----------------------------------------------------------", 1850 "-------------------------------- \n" ); 1851 Print( "-----------------------------------------------------------", 1852 "-------------------------------- \n" ); 1853 Print( IdGroup(G), "\t", StructureDescription(G), "\t\t\t", 1854 Length(Cat2_ler), "\t\t", Length(B), "\n" ); 1855 Print( "-----------------------------------------------------------", 1856 "-------------------------------- \n" ); 1857 Print( "-----------------------------------------------------------", 1858 "-------------------------------- \n" ); 1859 return B; 1860end ); 1861 1862############################################################################## 1863## 1864#M ConjugationActionForCrossedSquare 1865## . . . . conjugation action for crossed square from cat2-group 1866## 1867InstallMethod( ConjugationActionForCrossedSquare, 1868 "conjugation action for crossed square with G acting on N", 1869 true, [ IsGroup, IsGroup ], 0, 1870function( G, N ) 1871 1872 local genG, genN, autgen, g, imautgen, a, idN, aut, act; 1873 1874 genG := GeneratorsOfGroup( G ); 1875 genN := GeneratorsOfGroup( N ); 1876 autgen := [ ]; 1877 for g in genG do 1878 imautgen := List( genN, n -> n^g ); 1879 a := GroupHomomorphismByImages( N, N, genN, imautgen ); 1880 Add( autgen, a ); 1881 od; 1882 if ( Length( genG ) = 0 ) then 1883 idN := IdentityMapping( N ); 1884 aut := Group( idN ); 1885 else 1886 aut := Group( autgen ); 1887 fi; 1888 SetIsGroupOfAutomorphisms( aut, true ); 1889 act := GroupHomomorphismByImages( G, aut, genG, autgen ); 1890 return act; 1891end ); 1892 1893############################################################################# 1894## 1895#M PreCrossedSquareOfPreCat2Group 1896#M PreCat2GroupOfPreCrossedSquare 1897#M CrossedSquareOfCat2Group 1898#M Cat2GroupOfCrossedSquare 1899## 1900InstallMethod( PreCrossedSquareOfPreCat2Group, true, 1901 [ IsPreCat2Group ], 0, 1902function( C2G ) 1903 1904 local n, l, i, j, k, up, down, left, right, isolar, liste1, liste2, 1905 G, gensrc, x, C1, C2, h1, t1, h2, t2, L, M, N, P, XS, 1906 diag, genL, imdelta, delta, liste, partial, action, aut, actML, 1907 XM, kappa, CM1, CM2, lambda, actNL, CM3, mu, actPM, CM4, nu, actPN, 1908 xp, actPL; 1909 1910 C1 := GeneratingCat1Groups( C2G )[1]; 1911 C2 := GeneratingCat1Groups( C2G )[2]; 1912 if not ( IsPerm2DimensionalGroup( C1 ) ) then 1913 C1 := Image(IsomorphismPermObject( C1 ) ); 1914 fi; 1915 if not ( IsPerm2DimensionalGroup( C2 ) ) then 1916 C2 := Image(IsomorphismPermObject( C2 ) ); 1917 fi; 1918 h1 := HeadMap( C1 ); 1919 t1 := TailMap( C1 ); 1920 h2 := HeadMap( C2 ); 1921 t2 := TailMap( C2 ); 1922 G := Image( IsomorphismPermObject( Source( t1 ) ) ); 1923 gensrc := GeneratorsOfGroup( G ); 1924 t1 := GroupHomomorphismByImagesNC( G, G, gensrc, 1925 List(gensrc, x -> ImageElm( t1, x ) ) ); 1926 h1 := GroupHomomorphismByImagesNC( G, G, gensrc, 1927 List(gensrc, x -> ImageElm( h1, x ) ) ); 1928 t2 := GroupHomomorphismByImagesNC( G, G, gensrc, 1929 List(gensrc, x -> ImageElm( t2, x ) ) ); 1930 h2 := GroupHomomorphismByImagesNC( G, G, gensrc, 1931 List(gensrc, x -> ImageElm( h2, x ) ) ); 1932 L := Intersection( Kernel( t1 ), Kernel( t2 ) ) ; 1933 M := Intersection( Image( t1 ), Kernel( t2 ) ); 1934 N := Intersection( Kernel ( t1 ), Image( t2 ) ); 1935 P := Intersection( Image( t1 ), Image( t2 ) ) ; 1936 Info( InfoXMod, 4, "G = ", G ); 1937 Info( InfoXMod, 4, "L = ", L ); 1938 Info( InfoXMod, 4, "M = ", M ); 1939 Info( InfoXMod, 4, "N = ", N ); 1940 Info( InfoXMod, 4, "P = ", P ); 1941 kappa := GroupHomomorphismByFunction( L, M, x -> ImageElm(h1,x) ); 1942 actML := ConjugationActionForCrossedSquare( M, L ); 1943 up := XModByBoundaryAndAction( kappa, actML ); 1944 lambda := GroupHomomorphismByFunction( L, N, x -> ImageElm(h2,x) ); 1945 actNL := ConjugationActionForCrossedSquare( N, L ); 1946 left := XModByBoundaryAndAction( lambda, actNL ); 1947 mu := GroupHomomorphismByFunction( M, P, x -> ImageElm(h2,x) ); 1948 actPM := ConjugationActionForCrossedSquare( P, M ); 1949 right := XModByBoundaryAndAction( mu, actPM ); 1950 nu := GroupHomomorphismByFunction( N, P, x -> ImageElm(h1,x) ); 1951 actPN := ConjugationActionForCrossedSquare( P, N ); 1952 down := XModByBoundaryAndAction( nu, actPN ); 1953 Info( InfoXMod, 3, " up = ", up ); 1954 Info( InfoXMod, 3, " left = ", left ); 1955 Info( InfoXMod, 3, "right = ", right ); 1956 Info( InfoXMod, 3, " down = ", down ); 1957 actPL := ConjugationActionForCrossedSquare( P, L ); 1958 genL := GeneratorsOfGroup( L ); 1959 imdelta := List( genL, l -> ImageElm( nu, ImageElm( lambda, l ) ) ); 1960 delta := GroupHomomorphismByImages( L, P, genL, imdelta ); 1961 diag := XModByBoundaryAndAction( delta, actPL ); 1962 xp := CrossedPairingByCommutators( N, M, L ); 1963 XS := PreCrossedSquareObj( up, left, right, down, diag, xp ); 1964## SetIsCrossedSquare( XS, true ); 1965 if ( HasIsCat2Group( C2G ) and IsCat2Group( C2G ) ) then 1966 if not IsCrossedSquare( XS ) then 1967 Error( "XS fails to be the crossed square of a cat2-group" ); 1968 fi; 1969 fi; 1970 if HasName( C2G ) then 1971 SetName( XS, Concatenation( "xsq(", Name( C2G ), ")" ) ); 1972 fi; 1973 return XS; 1974end ); 1975 1976InstallMethod( PreCat2GroupOfPreCrossedSquare, true, 1977 [ IsPreCrossedSquare ], 0, 1978function( XS ) 1979 1980 local up, left, right, down, diag, L, M, N, P, genL, genM, genN, genP, 1981 kappa, lambda, nu, mu, 1982 act_up, act_lt, act_dn, act_rt, act_dg, xpair, 1983 Cup, NxL, genNxL, e1NxL, e2NxL, Cleft, MxL, genMxL, e1MxL, e2MxL, 1984 Cdown, PxM, genPxM, e1PxM, e2PxM, Cright, PxN, genPxN, e1PxN, e2PxN, 1985 MxLbyP, MxLbyN, autgenMxL, autMxL, actPNML, NxLbyP, NxLbyM, 1986 autgenNxL, autNxL, actPMNL, imPNML, bdyPNML, XPNML, CPNML, PNML, 1987 e1PNML, e2PNML, genPNML, imPMNL, bdyPMNL, XPMNL, CPMNL, PMNL, 1988 e1PMNL, e2PMNL, genPMNL, imiso, iso, inv, iminv, tup, hup, eup, 1989 C2PNML, tlt, hlt, elt, tdn, hdn, edn, trt, hrt, ert, tdi, hdi, edi, 1990 PC, Cdiag, imnukappa, nukappa, morCleftCright, immulambda, mulambda, 1991 morCupCdown; 1992 1993 Info( InfoXMod, 1, "these conversion functions are under development\n" ); 1994 1995 up := Up2DimensionalGroup( XS ); 1996 left := Left2DimensionalGroup( XS ); 1997 right := Right2DimensionalGroup( XS ); 1998 down := Down2DimensionalGroup( XS ); 1999 diag := Diagonal2DimensionalGroup( XS ); 2000 L := Source( up ); 2001 M := Range( up ); 2002 N := Source( down ); 2003 P := Range( down ); 2004 genL := GeneratorsOfGroup( L ); 2005 genM := GeneratorsOfGroup( M ); 2006 genN := GeneratorsOfGroup( N ); 2007 genP := GeneratorsOfGroup( P ); 2008 Info( InfoXMod, 4, "L = ", L ); 2009 Info( InfoXMod, 4, "M = ", M ); 2010 Info( InfoXMod, 4, "N = ", N ); 2011 Info( InfoXMod, 4, "P = ", P ); 2012 kappa := Boundary( up ); 2013 lambda := Boundary( left ); 2014 mu := Boundary( right ); 2015 nu := Boundary( down ); 2016 act_up := XModAction( up ); 2017 act_lt := XModAction( left ); 2018 act_rt := XModAction( right ); 2019 act_dn := XModAction( down ); 2020 act_dg := XModAction( diag ); 2021 xpair := CrossedPairing( XS ); 2022 2023 Cup := Cat1GroupOfXMod( up ); 2024 MxL := Source( Cup ); 2025 e1MxL := Embedding( MxL, 1 ); 2026 e2MxL := Embedding( MxL, 2 ); 2027 genMxL := Concatenation( List( genM, m -> ImageElm( e1MxL, m ) ), 2028 List( genL, l -> ImageElm( e2MxL, l ) ) ); 2029 Cleft := Cat1GroupOfXMod( left ); 2030 NxL := Source( Cleft ); 2031 e1NxL := Embedding( NxL, 1 ); 2032 e2NxL := Embedding( NxL, 2 ); 2033 genNxL := Concatenation( List( genN, n -> ImageElm( e1NxL, n ) ), 2034 List( genL, l -> ImageElm( e2NxL, l ) ) ); 2035 Cright := Cat1GroupOfXMod( right ); 2036 PxM := Source( Cright ); 2037 e1PxM := Embedding( PxM, 1 ); 2038 e2PxM := Embedding( PxM, 2 ); 2039 genPxM := Concatenation( List( genP, p -> ImageElm( e1PxM, p ) ), 2040 List( genM, m -> ImageElm( e2PxM, m ) ) ); 2041 2042 ## construct the cat1-morphism Cleft => Cright 2043 imnukappa := Concatenation( 2044 List( genN, n -> ImageElm( e1PxM, ImageElm( nu, n ) ) ), 2045 List( genL, l -> ImageElm( e2PxM, ImageElm( kappa, l ) ) ) ); 2046 nukappa := GroupHomomorphismByImages( NxL, PxM, genNxL, imnukappa ); 2047 morCleftCright := Cat1GroupMorphism( Cleft, Cright, nukappa, nu ); 2048 if ( InfoLevel( InfoXMod ) > 2 ) then 2049 Display( morCleftCright ); 2050 fi; 2051 Cdown := Cat1GroupOfXMod( down ); 2052 PxN := Source( Cdown ); 2053 e1PxN := Embedding( PxN, 1 ); 2054 e2PxN := Embedding( PxN, 2 ); 2055 genPxN := Concatenation( List( genP, p -> ImageElm( e1PxN, p ) ), 2056 List( genN, n -> ImageElm( e2PxN, n ) ) ); 2057 2058 ## construct the cat1-morphism Cup => Cdown 2059 immulambda := Concatenation( 2060 List( genM, m -> ImageElm( e1PxN, ImageElm( mu, m ) ) ), 2061 List( genL, l -> ImageElm( e2PxN, ImageElm( lambda, l ) ) ) ); 2062 mulambda := GroupHomomorphismByImages( MxL, PxN, genMxL, immulambda ); 2063 morCupCdown := Cat1GroupMorphism( Cup, Cdown, mulambda, mu ); 2064 if ( InfoLevel( InfoXMod ) > 2 ) then 2065 Display( morCupCdown ); 2066 fi; 2067 ## construct the action of PxM on NxL using: 2068 ## (n,l)^(p,m) = ( n^p, (n^p \box m).l^{pm} ) 2069 NxLbyP := List( genP, p -> GroupHomomorphismByImages( NxL, NxL, genNxL, 2070 Concatenation( 2071 List( genN, n -> ImageElm( e1NxL, 2072 ImageElm( ImageElm( act_dn, p ), n ) )), 2073 List( genL, l -> ImageElm( e2NxL, 2074 ImageElm( ImageElm( act_dg, p ), l ))) ))); 2075 NxLbyM := List( genM, m -> GroupHomomorphismByImages( NxL, NxL, genNxL, 2076 Concatenation( 2077 List( genN, n -> ImageElm( e1NxL, n ) * 2078 ImageElm( e2NxL, 2079 ImageElmCrossedPairing( xpair, [n,m] ))), 2080 List( genL, l -> ImageElm( e2NxL, 2081 ImageElm( ImageElm( act_up, m ), l ))) ))); 2082 autgenNxL := Concatenation( NxLbyP, NxLbyM ); 2083 Info( InfoXMod, 2, "autgenNxL = ", autgenNxL ); 2084 autNxL := Group( autgenNxL ); 2085 Info( InfoXMod, 2, "autNxL has size ", Size( autNxL ) ); 2086 SetIsGroupOfAutomorphisms( autNxL, true ); 2087 actPMNL := GroupHomomorphismByImages( PxM, autNxL, genPxM, autgenNxL ); 2088 imPMNL := Concatenation( 2089 List( genN, n -> ImageElm( e1PxM, ImageElm( nu, n ) ) ), 2090 List( genL, l -> ImageElm( e2PxM, ImageElm( kappa, l ) ) ) ); 2091 Info( InfoXMod, 2, "imPMNL = ", imPMNL ); 2092 bdyPMNL := GroupHomomorphismByImages( NxL, PxM, genNxL, imPMNL ); 2093 XPMNL := XModByBoundaryAndAction( bdyPMNL, actPMNL ); 2094 if ( InfoLevel( InfoXMod ) > 1 ) then 2095 Print( "crossed module XPMNL:\n" ); 2096 Display( XPMNL ); 2097 fi; 2098 CPMNL := Cat1GroupOfXMod( XPMNL ); 2099 Info( InfoXMod, 2, "cat1-group CPMNL: ", StructureDescription(CPMNL) ); 2100 PMNL := Source( CPMNL ); 2101 e1PMNL := Embedding( PMNL, 1 ); 2102 e2PMNL := Embedding( PMNL, 2 ); 2103 genPMNL := Concatenation( List( genPxM, g -> ImageElm( e1PMNL, g ) ), 2104 List( genNxL, g -> ImageElm( e2PMNL, g ) ) ); 2105 ## construct the action of PxN on MxL using the transpose action: 2106 ## (m,l)^(p,n) = (m^p, (n \box m^p)^{-1}.l^{pn} ) 2107 MxLbyP := List( genP, p -> GroupHomomorphismByImages( MxL, MxL, genMxL, 2108 Concatenation( 2109 List( genM, m -> ImageElm( e1MxL, 2110 ImageElm( ImageElm( act_rt, p ), m ) )), 2111 List( genL, l -> ImageElm( e2MxL, 2112 ImageElm( ImageElm( act_dg, p ), l ))) ))); 2113 MxLbyN := List( genN, n -> GroupHomomorphismByImages( MxL, MxL, genMxL, 2114 Concatenation( 2115 List( genM, m -> ImageElm( e1MxL, m ) * 2116 ImageElm( e2MxL, 2117 ImageElmCrossedPairing( xpair, [n,m] )^(-1) )), 2118 List( genL, l -> ImageElm( e2MxL, 2119 ImageElm( ImageElm( act_lt, n ), l ))) ))); 2120 autgenMxL := Concatenation( MxLbyP, MxLbyN ); 2121 Info( InfoXMod, 2, "autgenMxL = ", autgenMxL ); 2122 autMxL := Group( autgenMxL ); 2123 SetIsGroupOfAutomorphisms( autMxL, true ); 2124 actPNML := GroupHomomorphismByImages( PxN, autMxL, genPxN, autgenMxL ); 2125 imPNML := Concatenation( 2126 List( genM, m -> ImageElm( e1PxN, ImageElm( mu, m ) ) ), 2127 List( genL, l -> ImageElm( e2PxN, ImageElm( lambda, l ) ) ) ); 2128 bdyPNML := GroupHomomorphismByImages( MxL, PxN, genMxL, imPNML ); 2129 XPNML := XModByBoundaryAndAction( bdyPNML, actPNML ); 2130 if ( InfoLevel( InfoXMod ) > 2 ) then 2131 Print( "crossed module XPNML:\n" ); 2132 Display( XPNML ); 2133 fi; 2134 CPNML := Cat1GroupOfXMod( XPNML ); 2135 Info( InfoXMod, 2, "cat1-group CPNML: ", StructureDescription(CPNML) ); 2136 PNML := Source( CPNML ); 2137 e1PNML := Embedding( PNML, 1 ); 2138 e2PNML := Embedding( PNML, 2 ); 2139 genPNML := Concatenation( List( genPxN, g -> ImageElm( e1PNML, g ) ), 2140 List( genMxL, g -> ImageElm( e2PNML, g ) ) ); 2141 ## now find the isomorphism between the sources PMNL and PNML 2142 imiso := Concatenation( 2143 List( genP, p -> ImageElm( e1PNML, ImageElm( e1PxN, p ) ) ), 2144 List( genM, m -> ImageElm( e2PNML, ImageElm( e1MxL, m ) ) ), 2145 List( genN, n -> ImageElm( e1PNML, ImageElm( e2PxN, n ) ) ), 2146 List( genL, l -> ImageElm( e2PNML, ImageElm( e2MxL, l ) ) ) ); 2147 iso := GroupHomomorphismByImages( PMNL, PNML, genPMNL, imiso ); 2148 inv := InverseGeneralMapping( iso ); 2149 iminv := List( genPNML, g -> ImageElm( inv, g ) ); 2150 Info( InfoXMod, 2, "iminv = ", iminv ); 2151 2152 ## construct an isomorphic up cat1-group 2153 tup := iso * TailMap( CPNML ); 2154 hup := iso * HeadMap( CPNML ); 2155 eup := e1PNML * inv; 2156 C2PNML := PreCat1GroupByTailHeadEmbedding( tup, hup, eup ); 2157 2158 ## now see if a cat2-group has been constructed 2159 tlt := TailMap( CPMNL ); 2160 hlt := HeadMap( CPMNL ); 2161 elt := e1PMNL; 2162 tdn := TailMap( Cright ); 2163 hdn := HeadMap( Cright ); 2164 edn := e1PxM; 2165 trt := TailMap( Cdown ); 2166 hrt := HeadMap( Cdown ); 2167 ert := e1PxN; 2168 tdi := tlt * tdn; 2169 if not ( tdi = tup * trt ) then 2170 Error( "tlt * tdn <> tup * trt" ); 2171 fi; 2172 hdi := hlt * hdn; 2173 if not ( hdi = hup * hrt ) then 2174 Error( "hlt * hdn <> hup * hrt" ); 2175 fi; 2176 edi := edn * elt; 2177 if not ( edi = ert * eup ) then 2178 Error( "edn * elt <> ert * eup" ); 2179 fi; 2180 Cdiag := PreCat1GroupByTailHeadEmbedding( tdi, hdi, edi ); 2181 PC := PreCat2GroupByPreCat1Groups( CPMNL, C2PNML, Cright, Cdown, Cdiag ); 2182 return PC; 2183end ); 2184 2185InstallMethod( CrossedSquareOfCat2Group, "generic method for cat2-groups", 2186 true, [ IsCat2Group ], 0, 2187function( C2 ) 2188 2189 local XS; 2190 XS := PreCrossedSquareOfPreCat2Group( C2 ); 2191## SetIsCrossedSquare( XS, true ); 2192 if not IsCrossedSquare( XS ) then 2193 Error( "XS fails to be the crossed square of a cat2-group" ); 2194 fi; 2195 SetCrossedSquareOfCat2Group( C2, XS ); 2196## SetCat2GroupOfCrossedSquare( XS, C2 ); 2197 return XS; 2198end ); 2199 2200InstallMethod( Cat2GroupOfCrossedSquare, "generic method for crossed squares", 2201 true, [ IsCrossedSquare ], 0, 2202function( XS ) 2203 2204 local C2; 2205 C2 := PreCat2GroupOfPreCrossedSquare( XS ); 2206 SetCrossedSquareOfCat2Group( C2, XS ); 2207 SetCat2GroupOfCrossedSquare( XS, C2 ); 2208 return C2; 2209end ); 2210 2211############################################################################## 2212## 2213#M Transpose3DimensionalGroup . . transpose of a crossed square or cat2-group 2214## 2215InstallMethod( Transpose3DimensionalGroup, "transposed crossed square", true, 2216 [ IsCrossedSquare ], 0, 2217function( XS ) 2218 2219 local xpS, NxM, L, map, xpT, XT; 2220 2221 xpS := CrossedPairing( XS ); 2222 NxM := Reversed( Source( xpS ) ); 2223 L := Range( xpS ); 2224 map := Mapping2ArgumentsByFunction( NxM, L, 2225 function(c) 2226 return ImageElmCrossedPairing( xpS, Reversed(c) )^(-1); 2227 end ); 2228 xpT := CrossedPairingObj( NxM, L, map ); 2229 XT := PreCrossedSquareObj( Left2DimensionalGroup(XS), 2230 Up2DimensionalGroup(XS), Down2DimensionalGroup(XS), 2231 Right2DimensionalGroup(XS), Diagonal2DimensionalGroup(XS), xpT ); 2232## SetIsCrossedSquare( XT, true ); 2233 return XT; 2234end ); 2235 2236InstallMethod( Transpose3DimensionalGroup, "transposed cat2-group", true, 2237 [ IsCat2Group ], 0, 2238function( C2G ) 2239 return PreCat2GroupByPreCat1Groups( 2240 Left2DimensionalGroup( C2G ), 2241 Up2DimensionalGroup( C2G ), 2242 Down2DimensionalGroup( C2G ), 2243 Right2DimensionalGroup( C2G ), 2244 Diagonal2DimensionalGroup( C2G ) ); 2245end ); 2246 2247############################################################################## 2248## 2249#M LeftRightMorphism . . . . . . . . . . . . . . . . for a precrossed square 2250#M UpDownMorphism . . . . . . . . . . . . . . . . . for a precrossed square 2251## 2252InstallMethod( LeftRightMorphism, "for a precrossed square", true, 2253 [ IsPreCrossedSquare ], 0, 2254function( s ) 2255 return XModMorphismByGroupHomomorphisms( 2256 Left2DimensionalGroup(s), Right2DimensionalGroup(s), 2257 Boundary( Up2DimensionalGroup(s) ), 2258 Boundary( Down2DimensionalGroup(s) ) ); 2259end ); 2260 2261InstallMethod( UpDownMorphism, "for a precrossed square", true, 2262 [ IsPreCrossedSquare ], 0, 2263function( s ) 2264 return XModMorphismByGroupHomomorphisms( 2265 Up2DimensionalGroup(s), Down2DimensionalGroup(s), 2266 Boundary( Left2DimensionalGroup(s) ), 2267 Boundary( Right2DimensionalGroup(s) ) ); 2268end ); 2269 2270############################################################################## 2271## 2272#M IsSymmetric3DimensionalGroup . . . . check whether a 3d-group is symmetric 2273## 2274InstallMethod( IsSymmetric3DimensionalGroup, 2275 "generic method for 3d-groups", true, [ IsHigherDimensionalGroup ], 0, 2276function( XS ) 2277 return IsHigherDimensionalGroup( XS ) 2278 and HigherDimension( XS ) = 3 2279 and ( Up2DimensionalGroup( XS ) = Left2DimensionalGroup( XS ) ) 2280 and ( Right2DimensionalGroup( XS ) = Down2DimensionalGroup( XS ) ); 2281end ); 2282