1 2 3 4InstallGlobalFunction("IsPNormal", function( G, p) 5######################################################################### 6## Check if the group G is p-normal for the prime p. ## 7## Zassenhaus defines a finite group to be p-normal if the center of ## 8## one of its Sylow p-groups is the center of every Sylow p-group in ## 9## which it is contained. ## 10######################################################################### 11local SylowCenter, SylowGroups, N, isPnormal, k, j; 12isPnormal := true; 13 14 SylowGroups := ConjugateSubgroups( G, SylowSubgroup( G, p)); 15 N := Size( SylowGroups); 16 17 for j in [1..N] do 18 19 SylowCenter := Center( SylowGroups[j]); 20 21 for k in [1..N] do 22 if k <> j then 23 24 if IsSubset(SylowGroups[k], SylowCenter) then 25 26 if SylowCenter = Center( SylowGroups[k]) then 27 ; ## the condition is fulfilled for this pair ## 28 else 29 isPnormal := false; 30# Print("The group ",G," is not p-normal."); 31 fi; 32 fi; 33 fi; 34 od; 35 od; 36 return isPnormal; 37end); 38 39InstallGlobalFunction("DisplayAvailableCellComplexes", function() 40Exec( Concatenation("ls ",DirectoriesPackageLibrary("HAP")[1]![1], "Perturbations/Gcomplexes/")); 41end); 42 43InstallGlobalFunction( "GetTorsionSubcomplex", function(C, p) 44##################################################################### 45## Here, p is the prime for which to take the torsion subcomplex. ## 46## We extract the cells the stabilizer of which contains p-torsion.## 47##################################################################### 48local vcd, stabilizerCardinalities, celldata, data, torsionPosition, 49torsionCells, numberOfTorsionCells, n, j, returnedData, warned, groupname, admissibilityCheck, x, i, b, tmpCell, cell, boundary, groupName; 50 51 admissibilityCheck := function(celldata) 52 ######################################################### 53 ## A cell complex is admissible in the sense of Brown, ## 54 ## if each cell stabilizer fixes its cell pointwise. ## 55 ## Additionally, ## 56 ## we gather the cardinalities of the stabilizers. ## 57 ######################################################### 58 local stabilizerCardinalities, G, card, n, j, R, vcd, warned; 59 warned := false; 60 stabilizerCardinalities := []; 61 vcd := Length(celldata)-1; 62 63 for n in [0..vcd] do 64 stabilizerCardinalities[n+1] := []; 65 for j in [1..Length(celldata[n+1])] do 66 G := celldata[n+1][j]!.TheMatrixStab; 67 if IsFinite(G) then 68 card := Order(G); 69 stabilizerCardinalities[n+1][j] := card; 70 ## *** Now we have to compare *** ## 71 ## *** with the order of "TheRotSubgroup" *** ## 72 R := celldata[n+1][j]!.TheRotSubgroup; 73 if card > Order(R) and warned = false then 74 Print("****Warning: cell complex not admissible ", 75 "in the sense of Brown!****\n", 76 " Torsion subcomplex reduction requires cell subdivision.\n"); 77 warned := true; 78 fi; 79 fi; 80 od; 81 od; 82 return [stabilizerCardinalities, warned]; 83 end; 84 85 # Case 1: the input is a group name 86 if IsString(C) then 87 groupName:=C; 88 groupname := Filtered( C, function ( x ) 89 return not (x = '(' or x = ')' or x = ',' or x = '[' or x = ']'); 90 end ); 91 Read(Concatenation( DirectoriesPackageLibrary("HAP")[1]![1], 92 "Perturbations/Gcomplexes/",groupname)); 93 celldata := StructuralCopy(HAP_GCOMPLEX_LIST); 94 95 # Case 2: the input is a variable 96 else 97 groupName:=fail; 98 celldata:=[]; 99 i:=0; 100 while C!.dimension(i) > 0 do 101 cell:=[]; 102 for j in [1..C!.dimension(i)] do 103 if not i=0 then 104 boundary:=C!.boundary(i,j); 105 Add(cell,rec(TheMatrixStab :=C!.stabilizer(i,j), 106 TheRotSubgroup:=C!.stabilizer(i,j), 107 BoundaryImage :=rec( 108 ListIFace:=List(boundary,w->AbsInt(w[1])), 109 ListSign:=List(boundary,w->SignInt(w[1])), 110 ListElt:=List(boundary,w->C!.elts[w[2]]) 111 ) 112 ) 113 ); 114 else 115 Add(cell,rec(TheMatrixStab :=C!.stabilizer(i,j), 116 TheRotSubgroup:=C!.stabilizer(i,j), 117 BoundaryImage :=rec( 118 ListIFace:=[], 119 ListSign:=[], 120 ListElt:=[] 121 ) 122 ) 123 ); 124 fi; 125 od; 126 Add(celldata,cell); 127 i:=i+1; 128 od; 129 fi; 130 vcd := Length(celldata) -1; 131# Print("Extracting the ",p,"-torsion subcomplex of the ", 132# vcd,"-dimensional ",groupName,"-cell complex ... \n"); 133 returnedData := admissibilityCheck(celldata); 134 stabilizerCardinalities := returnedData[1]; 135 warned := returnedData[2]; 136 torsionCells := []; 137 numberOfTorsionCells := []; 138 for n in [0..vcd] do 139 torsionCells[n+1] := []; 140 numberOfTorsionCells[n+1] := 0; 141 for j in [1..Length(celldata[n+1])] do 142 ## Check if the stabilizer contains p-torsion ## 143 if stabilizerCardinalities[n+1][j] mod p = 0 then 144# Print("Extracted ",n,"-cell numero ",j, 145# " of stabilizer cardinality ", 146# stabilizerCardinalities[n+1][j],".\n"); 147 numberOfTorsionCells[n+1] 148 := numberOfTorsionCells[n+1]+1; 149 torsionCells[n+1][numberOfTorsionCells[n+1]] 150 :=[n, j]; 151 fi; 152 od; 153 od; 154# return 155# [torsionCells, numberOfTorsionCells, celldata, stabilizerCardinalities, warned]; 156 data:=[]; 157# Print("torsionCells",torsionCells,"\n"); 158 for i in [1..Length(torsionCells)] do 159 data[i]:=[]; 160 for x in torsionCells[i] do 161 Add(data[i],celldata[i][x[2]]); 162 od; 163 od; 164for j in [2..Size(data)] do 165 for i in [1..Size(data[j])] do 166 tmpCell:=StructuralCopy(data[j][i]!.BoundaryImage); 167 b:=List(tmpCell!.ListIFace,w->Position(torsionCells[j-1], [j-2,w])); 168 tmpCell!.ListIFace:=b; 169 data[j][i]!.BoundaryImage:=tmpCell; 170 od; 171od; 172 torsionPosition:=torsionCells; 173 torsionCells:=[]; 174 for i in [1..Size(data)] do 175 torsionCells[i]:=[]; 176 for j in [1..Size(data[i])] do 177 torsionCells[i][j]:=[i-1,j]; 178 od; 179 od; 180 181 return Objectify(HapTorsionSubcomplex, 182 rec( 183 184 torsion:=p, 185 groupname:=groupName, 186 torsionCells:=torsionCells, 187 torsionPosition:=torsionPosition, 188 originalData:=celldata, 189 celldata:= data, 190 numberOfTorsionCells:= numberOfTorsionCells, 191 stabilizerCardinalities:= stabilizerCardinalities, 192 warned:= warned )); 193end); 194 195DeclareGlobalFunction("GetTorsionPowerSubcomplex"); 196InstallGlobalFunction( "GetTorsionPowerSubcomplex", function(C, p, rk) 197##################################################################### 198## Here, p is the prime for which to take the torsion subcomplex. ## 199## We extract the cells the stabilizer of which contains p-torsion.## 200##################################################################### 201local vcd, stabilizerCardinalities, celldata, data, torsionPosition, 202torsionCells, numberOfTorsionCells, n, j, returnedData, warned, groupname, admissibilityCheck, x, i, b, tmpCell, cell, boundary, groupName, elementaryAbelianID, G, H, subgroupTypesOfG, numberOfSubgroups; 203 204 admissibilityCheck := function(celldata) 205 ######################################################### 206 ## A cell complex is admissible in the sense of Brown, ## 207 ## if each cell stabilizer fixes its cell pointwise. ## 208 ## Additionally, ## 209 ## we gather the cardinalities of the stabilizers. ## 210 ######################################################### 211 local stabilizerCardinalities, G, card, n, j, R, vcd, warned; 212 warned := false; 213 stabilizerCardinalities := []; 214 vcd := Length(celldata)-1; 215 216 for n in [0..vcd] do 217 stabilizerCardinalities[n+1] := []; 218 for j in [1..Length(celldata[n+1])] do 219 G := celldata[n+1][j]!.TheMatrixStab; 220 if IsFinite(G) then 221 card := Order(G); 222 stabilizerCardinalities[n+1][j] := card; 223 ## *** Now we have to compare *** ## 224 ## *** with the order of "TheRotSubgroup" *** ## 225 R := celldata[n+1][j]!.TheRotSubgroup; 226 if card > Order(R) and warned = false then 227 Print("****Warning: cell complex not admissible ", 228 "in the sense of Brown!****\n", 229 " Torsion subcomplex reduction requires cell subdivision.\n"); 230 warned := true; 231 fi; 232 fi; 233 od; 234 od; 235 return [stabilizerCardinalities, warned]; 236 end; 237 238 # Case 1: the input is a group name 239 if IsString(C) then 240 groupName:=C; 241 groupname := Filtered( C, function ( x ) 242 return not (x = '(' or x = ')' or x = ',' or x = '[' or x = ']'); 243 end ); 244 Read(Concatenation( DirectoriesPackageLibrary("HAP")[1]![1], 245 "Perturbations/Gcomplexes/",groupname)); 246 celldata := StructuralCopy(HAP_GCOMPLEX_LIST); 247 248 # Case 2: the input is a variable 249 else 250 groupName:=fail; 251 celldata:=[]; 252 i:=0; 253 while C!.dimension(i) > 0 do 254 cell:=[]; 255 for j in [1..C!.dimension(i)] do 256 if not i=0 then 257 boundary:=C!.boundary(i,j); 258 Add(cell,rec(TheMatrixStab :=C!.stabilizer(i,j), 259 TheRotSubgroup:=C!.stabilizer(i,j), 260 BoundaryImage :=rec( 261 ListIFace:=List(boundary,w->AbsInt(w[1])), 262 ListSign:=List(boundary,w->SignInt(w[1])), 263 ListElt:=List(boundary,w->C!.elts[w[2]]) 264 ) 265 ) 266 ); 267 else 268 Add(cell,rec(TheMatrixStab :=C!.stabilizer(i,j), 269 TheRotSubgroup:=C!.stabilizer(i,j), 270 BoundaryImage :=rec( 271 ListIFace:=[], 272 ListSign:=[], 273 ListElt:=[] 274 ) 275 ) 276 ); 277 fi; 278 od; 279 Add(celldata,cell); 280 i:=i+1; 281 od; 282 fi; 283 vcd := Length(celldata) -1; 284# Print("Extracting the ",p,"-torsion subcomplex of the ", 285# vcd,"-dimensional ",groupName,"-cell complex ... \n"); 286 elementaryAbelianID := IdSmallGroup(DirectProduct(List([1..rk], i -> CyclicGroup(p)))); 287 returnedData := admissibilityCheck(celldata); 288 stabilizerCardinalities := returnedData[1]; 289 warned := returnedData[2]; 290 torsionCells := []; 291 numberOfTorsionCells := []; 292 for n in [0..vcd] do 293 torsionCells[n+1] := []; 294 numberOfTorsionCells[n+1] := 0; 295 for j in [1..Length(celldata[n+1])] do 296 ## Check if the stabilizer contains p-torsion ## 297 if stabilizerCardinalities[n+1][j] mod p^rk = 0 then 298 299 G := C!.stabilizer(n,j); 300 subgroupTypesOfG := []; numberOfSubgroups := 0; 301 for H in ConjugacyClassesSubgroups(G) do 302 numberOfSubgroups := numberOfSubgroups+1; 303 subgroupTypesOfG[numberOfSubgroups] := IdSmallGroup(Representative(H)); 304 od; 305 if IsInt(Position(subgroupTypesOfG,elementaryAbelianID)) then 306 307# Print("Extracted ",n,"-cell numero ",j, 308# " of stabilizer cardinality ", 309# stabilizerCardinalities[n+1][j],".\n"); 310 numberOfTorsionCells[n+1] 311 := numberOfTorsionCells[n+1]+1; 312 torsionCells[n+1][numberOfTorsionCells[n+1]] 313 :=[n, j]; 314 fi; 315 fi; 316 od; 317 od; 318# return 319# [torsionCells, numberOfTorsionCells, celldata, stabilizerCardinalities, warned]; 320 data:=[]; 321 for i in [1..Length(torsionCells)] do 322 data[i]:=[]; 323 for x in torsionCells[i] do 324 Add(data[i],celldata[i][x[2]]); 325 od; 326 od; 327 328for j in [2..Size(data)] do 329 for i in [1..Size(data[j])] do 330 tmpCell:=StructuralCopy(data[j][i]!.BoundaryImage); 331 b:=List(tmpCell!.ListIFace,w->Position(torsionCells[j-1], [j-2,w])); 332 tmpCell!.ListIFace:=b; 333 data[j][i]!.BoundaryImage:=tmpCell; 334 od; 335od; 336 torsionPosition:=torsionCells; 337 torsionCells:=[]; 338 for i in [1..Size(data)] do 339 torsionCells[i]:=[]; 340 for j in [1..Size(data[i])] do 341 torsionCells[i][j]:=[i-1,j]; 342 od; 343 od; 344 345 return Objectify(HapTorsionSubcomplex, 346 rec( 347 348 torsion:=p, 349 groupname:=groupName, 350 torsionCells:=torsionCells, 351 torsionPosition:=torsionPosition, 352 originalData:=celldata, 353 celldata:= data, 354 numberOfTorsionCells:= numberOfTorsionCells, 355 stabilizerCardinalities:= stabilizerCardinalities, 356 warned:= warned )); 357end); 358 359 360InstallGlobalFunction("TorsionSubcomplex", function(groupName, p) 361############################################ 362local torsionCells, numberOfTorsionCells, celldata, sortedData, warned, computeIncidenceMatrix; 363 364 365 computeIncidenceMatrix := function(torsionCells, numberOfTorsionCells, celldata) 366 ######################################################## 367 ## The incidence matrix of the 1-skeleton of the ## 368 ## p-torsion subcomplex is returned by this function. ## 369 ######################################################## 370 local incidenceMatrix, j, k, q, endpoints, inverseIndex, ORIGIN, END; 371 incidenceMatrix := []; 372 for j in [1..numberOfTorsionCells[1]] do 373 incidenceMatrix[j] := []; 374 for k in [1..numberOfTorsionCells[1]] do 375 incidenceMatrix[j][k] := 0; 376 od; 377 od; 378# Print("The edges in the quotient by the action on the torsion subcomplex are: "); 379 ## Record the indices in the torsion subcomplex of vertices in ## 380 ## the cell complex, in order to assign the endpoints of an edge## 381 inverseIndex := []; 382 for q in [1..Length(celldata[1])] do 383 inverseIndex[q] := "error: not a p-torsion vertex"; 384 od; 385 for j in [1..numberOfTorsionCells[1]] do 386 inverseIndex[torsionCells[1][j][2]] := j; 387 od; 388 for q in [1..numberOfTorsionCells[2]] do 389 endpoints := celldata[2] 390 [torsionCells[2][q][2]]!.BoundaryImage.ListIFace; 391 ORIGIN := inverseIndex[endpoints[1]]; 392 END := inverseIndex[endpoints[2]]; 393# Print([ORIGIN,END]); 394 incidenceMatrix[ORIGIN][END] := incidenceMatrix[ORIGIN][END] +1; 395 ## If we do not want to have the incidence matrix symmetric, ## 396 ## then deactivate the following line. ## 397 incidenceMatrix[END][ORIGIN] := incidenceMatrix[END][ORIGIN] +1; 398 od; 399# Print(".\n"); 400 return incidenceMatrix; 401 end; 402 403 404 sortedData := GetTorsionSubcomplex(groupName, p); 405 torsionCells := sortedData!.torsionCells; 406 numberOfTorsionCells := sortedData!. numberOfTorsionCells; 407 celldata := sortedData!.celldata; 408 warned := sortedData!.warned; 409 if IsPrime(p) then 410 sortedData := [computeIncidenceMatrix(torsionCells, numberOfTorsionCells, celldata), warned]; 411 else 412 sortedData := "The number p must be prime in order to compute the incidence matrix."; 413 fi; 414 return 415 sortedData; 416end); 417 418 419 420InstallGlobalFunction("VisualizeTorsionSkeleton", function(groupName, p) 421################################################## 422local incidenceMatrix, graphData, returnedData, warned; 423 returnedData := TorsionSubcomplex(groupName, p); 424 if IsPrime(p) then 425 incidenceMatrix := returnedData[1]; 426 warned := returnedData[2]; 427 if warned = false then 428# Print("The quotient by the action on the 1-skeleton of the p-torsion #subcomplex is "); 429 else 430# Print("As the cell stabilizers do not fix the cells pointwise, \n", 431# "we do not obtain the quotient by the action on the 1-skeleton of the p-#torsion subcomplex.\n", 432# " We obtain just some graph, and the latter is "); 433 fi; 434 if Size(incidenceMatrix) = 0 then 435 Print("empty.\n"); 436 fi; 437 if Size(incidenceMatrix) > 0 then 438# Print("displayed in a separate window on screen now.\n"); 439 graphData := StructuralCopy(IncidenceMatrixToGraph(incidenceMatrix)); 440 GraphDisplay(graphData); 441 fi; 442 else 443#Print("The number p must be prime in order to compute the incidence matrix.\n"); 444 fi; 445end); 446 447 448 449 450InstallGlobalFunction("ReduceTorsionSubcomplex", function(arg) ## The input arg consists of groupname, p, and optionally a third argument rk, 451#############################I###################### 452local torsionCells, numberOfTorsionCells, celldata, sortedData, stabilizerCardinalities, fusionCandidates, reducedTorsionCells, groupname, 453terminaljMinus1cells, warned, extractPmultipleTorsionCells, cellcomplex, 454bifurcationFreeCells, pairsIntersection, groupName, p, rk, 455getIdentifier, checkStabilizerConjugacy, mergeCells, printIsotropyGroups, ReduceModP, getTerminalFacets, cutOffCells, 456terminalFacets, data, i, x, tmpCell, 457N, J, n, j, G, B, b; 458 459groupName:=arg[1]; 460p:=arg[2]; 461 462extractPmultipleTorsionCells := function(torsionCells, numberOfTorsionCells, celldata,stabilizerCardinalities, p) 463################################################################## 464## Make lists of n-cells of each stabilizer cardinality ## 465## in the p-torsion subcomplex. ## 466################################################################## 467local vcd, pMultipleTorsionCells, numberOfPmultipleTorsionCells, Pmultiples, PmultipleNumero, m, n, cell, j, getCardinals; 468 469 470getCardinals := function(stabilizerCardinalities, p, n) 471############################################################ 472## Extract the cardinalities of n-cell stabilisers ## 473## containing p-torsion. ## 474############################################################ 475local S, m, Cardinals, counter; 476 Cardinals := []; counter := 0; 477 S := stabilizerCardinalities[n+1]; 478 for m in S do 479 if m mod p = 0 then 480 if counter > 0 then 481 if m in Cardinals then ; 482 else 483 counter := counter +1; 484 Cardinals[counter] := m; 485 fi; 486 else counter := 1; 487 Cardinals[counter] := m; 488 fi; 489 fi; 490 od; 491 return Cardinals; 492end; 493####################################### 494 495 496 vcd := Length(celldata) -1; 497 pMultipleTorsionCells := []; 498 numberOfPmultipleTorsionCells := []; 499 Pmultiples := []; 500 501 for n in [0..vcd] do 502 503 pMultipleTorsionCells[n+1] := []; 504 numberOfPmultipleTorsionCells[n+1] := []; 505 Pmultiples[n+1] := getCardinals(stabilizerCardinalities, p, n); 506 PmultipleNumero := 0; 507 508 for m in Pmultiples[n+1] do 509 510 PmultipleNumero := PmultipleNumero +1; 511 numberOfPmultipleTorsionCells[n+1][PmultipleNumero] := 0; 512 pMultipleTorsionCells[n+1][PmultipleNumero] := []; 513 514 for cell in torsionCells[n+1] do 515 516 ## Check if the stabilizer contains p-torsion of multiple m ## 517 518 519 if stabilizerCardinalities[n+1][cell[2]] = m then 520 521 numberOfPmultipleTorsionCells[n+1] := 522 numberOfPmultipleTorsionCells[n+1] +1; 523 pMultipleTorsionCells[n+1][PmultipleNumero] 524 [numberOfPmultipleTorsionCells[n+1][PmultipleNumero]] := 525 cell; 526 fi; 527 od; 528# Print("There are ",numberOfPmultipleTorsionCells[n+1][PmultipleNumero], 529# " orbits of ",n,"-cells in the ",p,"-torsion subcomplex", 530# ", the stabilizers of which are of cardinality ",m, 531# ", namely the ones numero " 532# ); 533 for j in [1..Length(pMultipleTorsionCells[n+1][PmultipleNumero])-1] do 534# Print(pMultipleTorsionCells[n+1][PmultipleNumero][j][2],", "); 535 od; 536# Print(pMultipleTorsionCells[n+1][PmultipleNumero][ 537# Length(pMultipleTorsionCells[n+1][PmultipleNumero])][2],".\n"); 538 od; 539 od; 540 return [pMultipleTorsionCells, Pmultiples]; 541end; 542 543pairsIntersection := function(sortedData, celldata) 544######################################################################### 545## We establish a preliminary list of cell triples as candidates for ## 546## fusions, consisting of a pair of n-cells that admits precisely ## 547## one adjacent (n-1)-cell in common. ## 548## This pair and their common boundary cell constitute our cell triple.## 549######################################################################### 550local pMultipleTorsionCells, Pmultiples, n, j, f, s, vcd, fusionCandidates, 551numberOfFusionCandidates, firstCell, secondCell, commonBoundary; 552 pMultipleTorsionCells := sortedData[1]; 553 Pmultiples := sortedData[2]; 554 vcd := Length(celldata) -1; 555 fusionCandidates := []; 556 numberOfFusionCandidates := 0; 557 558 for n in [0..vcd] do 559 for j in [1..Length(Pmultiples[n+1])] do 560 for f in [1..Length(pMultipleTorsionCells[n+1][j])] do 561 firstCell := pMultipleTorsionCells[n+1][j][f]; 562 for s in [f+1..Length(pMultipleTorsionCells[n+1][j])] do 563 secondCell := pMultipleTorsionCells[n+1][j][s]; 564 commonBoundary := 565 Set(celldata[n+1][firstCell[2]]!.BoundaryImage!.ListIFace); 566 IntersectSet( commonBoundary, 567 Set(celldata[n+1][secondCell[2]]!.BoundaryImage!.ListIFace) 568 ); 569 570 if Size(commonBoundary)=1 then 571# Print("The boundary of ",n,"-cell numero ",firstCell[2]," is ", 572# celldata[n+1][firstCell[2]]!.BoundaryImage!.ListIFace, 573# " and that of ",n,"-cell numero ",secondCell[2]," is ", 574# celldata[n+1][secondCell[2]]!.BoundaryImage!.ListIFace, 575# " so they have ",n-1,"-cell numero ",commonBoundary[1], 576# " in common.\n"); 577 numberOfFusionCandidates := numberOfFusionCandidates +1; 578 fusionCandidates[numberOfFusionCandidates] := 579 [firstCell, secondCell, commonBoundary[1]]; 580 return fusionCandidates; 581 fi; 582 od; 583 od; 584 od; 585 od; 586 return fusionCandidates; 587end; 588 589 590bifurcationFreeCells := function(fusionCandidates, torsionCells, celldata) 591########################################################################## 592## We keep only those cell triples as candidates for a fusion, ## 593## that are not "bifurcated" in the p-torsion subcomplex : ## 594## Triples such that only n-cells adjacent to the (n-1)-cell ## 595## of the triple are the two n-cells of the triple. ## 596########################################################################## 597local firstCell, secondCell, boundaryCell, cellTriple, n, cell, torsionCell, 598remainingFusionCandidates; 599remainingFusionCandidates := Set(StructuralCopy(fusionCandidates)); 600 601 for cellTriple in fusionCandidates do 602 603 firstCell := cellTriple[1]; 604 secondCell := cellTriple[2]; 605 n := firstCell[1]; 606 boundaryCell := cellTriple[3]; 607 608 for torsionCell in torsionCells[n+1] do 609 610 cell := celldata[n+1][torsionCell[2]]; 611 612 if boundaryCell in cell!.BoundaryImage!.ListIFace then 613 614 if torsionCell in [firstCell, secondCell] then ; 615 # the cell triple remains a candidate for fusion. 616 else 617# Print("The p-torsion subcomplex is bifurcated at the ", 618# n-1,"-cell numero ",boundaryCell,".\n"); 619 RemoveSet(remainingFusionCandidates, cellTriple); 620 fi; 621 fi; 622 od; 623 od; 624 return remainingFusionCandidates; 625end; 626 627 628getIdentifier := function( cell, boundaryCell, celldata) 629############################################################## 630## Retrieve the group element sending the cell to ## 631## a representative that is adjacent to the boundary cell. ## 632############################################################## 633local n, boundaryIndex, j, identifiers, g; 634 n := cell[1]; 635 identifiers := celldata[n+1][cell[2]]!.BoundaryImage!.ListElt; 636 637 for j in [1..Length(identifiers)] do 638 639 if celldata[n+1][cell[2]]!.BoundaryImage!.ListIFace[j] 640 = boundaryCell then 641 642 boundaryIndex := j; 643 fi; 644 od; 645 g := celldata[n+1][cell[2]]!.BoundaryImage!.ListElt[boundaryIndex]; 646 return g; 647end; 648 649 650checkStabilizerConjugacy := function(fusionCandidates, celldata, p) 651################################################################## 652## Eliminate cell triples from the fusion candidates list, ## 653## for which the stabilizers of the n-cells are not conjugate. ## 654## Therefore, we first conjugate the stabilizers of the n-cells ## 655## into stabilizers of representatives ## 656## adjacent to the (n-1)-cell. ## 657## Then we check if we can conjugate them within the stabilizer ## 658## of the (n-1)-cell. ## 659################################################################## 660local firstCell, secondCell, boundaryCell, firstStabilizer, secondStabilizer, boundaryStabilizer, cellTriple, n, g, validated, remainingFusionCandidates, controllingGroupID; 661remainingFusionCandidates := StructuralCopy(fusionCandidates); 662 663 for cellTriple in fusionCandidates do 664 665 firstCell := cellTriple[1]; 666 secondCell := cellTriple[2]; 667 n := firstCell[1]; 668 boundaryCell := cellTriple[3]; 669 firstStabilizer := celldata[n+1][firstCell[2]]!.TheMatrixStab; 670 secondStabilizer := celldata[n+1][secondCell[2]]!.TheMatrixStab; 671 boundaryStabilizer := celldata[n][boundaryCell]!.TheMatrixStab; 672 g := getIdentifier( firstCell, boundaryCell, celldata); 673 firstStabilizer := ConjugateGroup(firstStabilizer, g); 674 g := getIdentifier( secondCell, boundaryCell, celldata); 675 secondStabilizer := ConjugateGroup(secondStabilizer, g); 676 controllingGroupID := IdSmallGroup(ReduceModP(firstStabilizer,p)); 677 678 if controllingGroupID =IdSmallGroup(ReduceModP(secondStabilizer,p)) 679 and controllingGroupID =IdSmallGroup(ReduceModP(boundaryStabilizer,p)) 680 then ; 681 else RemoveSet(remainingFusionCandidates, cellTriple); 682 fi; 683 od; 684 return remainingFusionCandidates; 685end; 686 687 688mergeCells := function( celldata, fusionCandidates, torsionCells) 689#################################################################### 690## Merge the cells in that have been definitively retained ## 691## as fusion candidates. As proven, this does not change ## 692## the p-primary equivariant Farrell cohomology. ## 693#################################################################### 694local firstCell, secondCell, boundaryCell, cellTriple, n, b, t1, t2, BI1, BI2, x,y,t01,t02, 695 i, j, reducedTorsionCells, vcd, mergedBoundary, data, p0, p1, p2, tmpCell, U, V, X; 696 mergedBoundary := []; 697 reducedTorsionCells := StructuralCopy( torsionCells); 698 vcd := Length(reducedTorsionCells) -1; 699 for n in [0..vcd] do 700 reducedTorsionCells[n+1] := Set(reducedTorsionCells[n+1]); 701 mergedBoundary[n+1] := []; 702 od; 703 704 # Extract the data of torsionCells from original cell data 705 data:=[]; 706 for i in [1..Length(reducedTorsionCells)] do 707 data[i]:=[]; 708 for x in reducedTorsionCells[i] do 709 Add(data[i],celldata[i][x[2]]); 710 od; 711 od; 712#Print("reducedTorsionCells", reducedTorsionCells,"\n"); 713#Print("data= ",data,"\n"); 714 for cellTriple in fusionCandidates do 715 716 firstCell := cellTriple[1]; 717 secondCell := cellTriple[2]; 718 n := firstCell[1]; 719 boundaryCell := cellTriple[3]; 720 p0:=Position(reducedTorsionCells[n], [n-1,boundaryCell]); 721 p1:=Position(reducedTorsionCells[n+1], [n,firstCell[2]]); 722 p2:=Position(reducedTorsionCells[n+1], [n,secondCell[2]]); 723 724# Print("The ",n-1,"-cell numero ",boundaryCell, 725# " is amalgamated into the merging ",n,"-cells numero ", 726# firstCell[2]," and ",secondCell[2],".\n"); 727 RemoveSet(reducedTorsionCells[n], [n-1,boundaryCell]); 728 Remove(data[n],p0); 729 mergedBoundary[n+1][firstCell[2]] := Set(Concatenation( 730 celldata[n+1][firstCell[2]]!.BoundaryImage!.ListIFace, 731 celldata[n+1][secondCell[2]]!.BoundaryImage!.ListIFace 732 )); 733 734 RemoveSet(mergedBoundary[n+1][firstCell[2]], boundaryCell); 735 t1:=Position(data[n+1][p1]!. BoundaryImage!.ListIFace,mergedBoundary[n+1][firstCell[2]][1]); 736 if t1=fail then 737 t1:=Position(data[n+1][p1]!. BoundaryImage!.ListIFace,mergedBoundary[n+1][firstCell[2]][2]); 738 t01:=3-t1; 739 t2:=Position(data[n+1][p2]!. BoundaryImage!.ListIFace,mergedBoundary[n+1][firstCell[2]][1]); 740 t02:=3-t2; 741 else t2:=Position(data[n+1][p2]!. BoundaryImage!.ListIFace,mergedBoundary[n+1][firstCell[2]][2]); 742 fi; 743 t01:=3-t1; 744 t02:=3-t2; 745 BI1:=StructuralCopy(celldata[n+1][firstCell[2]]!.BoundaryImage); 746 BI2:=StructuralCopy(celldata[n+1][secondCell[2]]!.BoundaryImage); 747 748 749 x:=BI2!.ListElt[t02]*BI2!.ListElt[t01]^-1; 750 U:=ConjugateGroup(data[n+1][p2]!.TheMatrixStab,(x)^-1); 751 V:=data[n+1][p1]!.TheMatrixStab; 752 X:=ConjugateGroup(celldata[n][BI1!.ListIFace[t01]]!.TheMatrixStab,BI1!.ListElt[t01]); 753 y:=RepresentativeAction(X,U,V); 754 tmpCell:=rec(ListIFace:=[BI1!.ListIFace[t1],BI2!.ListIFace[t2]], 755 ListSign:=BI1!.ListSign, 756 ListElt:=[BI1!.ListElt[t1],y*x*BI2!.ListElt[t2]] 757 ); 758 data[n+1][p1]!.BoundaryImage:=StructuralCopy(tmpCell); 759 Remove(data[n+1],p2); 760 od; 761 for i in [1..Size(data[2])] do 762 tmpCell:=StructuralCopy(data[2][i]!.BoundaryImage); 763 b:=List(tmpCell!.ListIFace,w->Position(reducedTorsionCells[1], [0,w])); 764 tmpCell!.ListIFace:=b; 765 data[2][i]!.BoundaryImage:=tmpCell; 766 od; 767 reducedTorsionCells:=[]; 768 for i in [1..Size(data)] do 769 reducedTorsionCells[i]:=[]; 770 for j in [1..Size(data[i])] do 771 reducedTorsionCells[i][j]:=[i-1,j]; 772 od; 773 od; 774 return [reducedTorsionCells, data]; 775end; 776 777 778printIsotropyGroups := function(reducedTorsionCells, celldata) 779######################################################### 780## Return the stabilizers of the cells in the ## 781## reduced torsion subcomplex. ## 782######################################################### 783local G, n, k, j, tcd; 784 tcd := Length(reducedTorsionCells)-1; 785 Print("The following cells and stabilizers represent ", 786 "the reduced torsion subcomplex.\n"); 787 788 for n in [0..tcd] do 789 for k in [1..Length(reducedTorsionCells[n+1])] do 790 j := reducedTorsionCells[n+1][k][2]; 791 G := celldata[n+1][j]!.TheMatrixStab; 792 if IsFinite(G) then 793 Print(n,"-cell number ",j," has stabilizer ",G,"\n"); 794 Print("of Abelianization ",GroupHomology(G,1),".\n"); 795 fi; 796 od; 797 od; 798end; 799 800 801################################################################### 802# CUT OFF CELLS PROCESS # 803# # 804################################################################### 805cutOffCells := function(terminalFacets, torsionCells, celldata, n) 806#################################################################### 807## Cut off the n-cells that have a terminal facet which has been ## 808## spotted to have the same p-torsion controller. As proven, this ## 809## does not change the p-primary equivariant Farrell cohomology. ## 810#################################################################### 811local facet, nCell, reducedTorsionCells, cutnCells, cellPair; 812 813 cutnCells := []; 814 reducedTorsionCells := StructuralCopy( torsionCells); 815 reducedTorsionCells[n+1] := Set(reducedTorsionCells[n+1]); 816 reducedTorsionCells[n] := Set(reducedTorsionCells[n]); 817 818 for cellPair in terminalFacets do 819 820 facet := cellPair[1]; 821 nCell := cellPair[2]; 822 if not nCell in cutnCells then 823# Print("The terminal ",n-1,"-cell numero ",facet, 824# " is cut against ",n,"-cell numero ",nCell,".\n"); 825 RemoveSet(reducedTorsionCells[n], [n-1,facet]); 826 RemoveSet(reducedTorsionCells[n+1], [n,nCell]); 827 cutnCells := Concatenation(cutnCells,[nCell]); 828 fi; 829 od; 830# Print("Length of reducedTorsionCells after cut off ",n,"-cells",List(reducedTorsionCells,i->Length(i)),"\n"); 831 return reducedTorsionCells; 832end; 833 834 835ReduceModP := function( G, p) 836local K, h, H, Q, P; 837 838 Q := G; 839 K := ConjugacyClassesSubgroups(G); 840 for h in K do 841 if Size(h)=1 then 842 H := Representative(h); 843 if Size(H) > 1 then 844 if Gcd(Size(H),p) = 1 then 845 # We pass to the quotient Q in the extension 846 # 1 -> H -> G -> Q -> 1, 847 # because H has trivial mod p cohomology. 848 # Our loop ends up using the normal subgroup H of maximal size, 849 # because the list K is ordered from small to large. 850 Q := Image( NaturalHomomorphismByNormalSubgroup( G,H )); 851 fi; 852 fi; 853 fi; 854 od; 855 P:=Q; 856 if IsPNormal(Q,p) then P:=Normalizer(Q,Center(SylowSubgroup(Q,p)));fi; 857 return P; 858end; 859 860getTerminalFacets := function(reducedTorsionCells, celldata, p, n) 861############################################################################## 862## We single out the "terminal" (n-1)-facets of the p-torsion subcomplex : ## 863## Those with exactly one adjacent n-cell. ## 864############################################################################## 865local examinedncell, examinedFacet, examinedncellData, numberOfAdjacencies, 866 adjacentncell, reductionCandidates, numberOfTerminalFacets, G, IdGred, H, IdHred, 867 nplus1cell; 868 reductionCandidates:= []; numberOfTerminalFacets := 0; 869 870 for examinedFacet in reducedTorsionCells[n] do 871 872 examinedFacet := examinedFacet[2]; 873 numberOfAdjacencies := 0; 874 875 for examinedncell in reducedTorsionCells[n+1] do 876 examinedncellData := celldata[n+1][examinedncell[2]]; 877 878 if examinedFacet in examinedncellData!.BoundaryImage!.ListIFace then 879 880 numberOfAdjacencies := numberOfAdjacencies +1; 881 adjacentncell := examinedncell[2]; 882 fi; 883 od; 884 if numberOfAdjacencies = 1 then 885 nplus1cell:=0; 886 if IsBound(reducedTorsionCells[n+2]) then 887 for examinedncell in reducedTorsionCells[n+2] do 888 examinedncellData := celldata[n+2][examinedncell[2]]; 889 if adjacentncell in examinedncellData!.BoundaryImage!.ListIFace then 890 nplus1cell := nplus1cell +1; 891 fi; 892 od; 893 fi; 894 if nplus1cell=0 then 895 G := celldata[n+1][adjacentncell]!.TheMatrixStab;; 896 IdGred := IdSmallGroup(ReduceModP(G,p)); 897 H := celldata[n][examinedFacet]!.TheMatrixStab;; 898 IdHred := IdSmallGroup(ReduceModP(H,p)); 899# Print("The ",n-1,"-facet number ",examinedFacet," is terminal.", 900# " Its stabilizer ",IdSmallGroup(H)," is controlled by ", IdHred, 901# ". It is adjacent to the ",n,"-cell number ",adjacentncell, 902# " of stabilizer ",IdSmallGroup(G)," controlled by ",IdGred,".\n"); 903 if IdGred = IdHred then 904# Print("Reduce it against the adjacent ",n,"-cell number ",adjacentncell, 905# " of stabilizer ",IdSmallGroup(G)," controlled by ",IdGred,".\n"); 906 numberOfTerminalFacets := numberOfTerminalFacets +1; 907 reductionCandidates[numberOfTerminalFacets] := 908 [examinedFacet, adjacentncell]; 909 fi; 910 fi; 911 fi; 912 od; 913#Print("Reduction Candidates of dimension",n," ",reductionCandidates,"\n"); 914 return reductionCandidates; 915end; 916############################# 917 if Length(arg)=2 then 918 sortedData := GetTorsionSubcomplex(groupName, p); 919 else 920 rk := arg[3]; 921 sortedData := GetTorsionPowerSubcomplex(groupName, p, rk); 922 fi; 923 torsionCells := sortedData!.torsionCells; 924 numberOfTorsionCells := sortedData!. numberOfTorsionCells; 925 celldata := sortedData!.celldata; 926 stabilizerCardinalities := sortedData!. stabilizerCardinalities; 927 warned := sortedData!.warned; 928 groupname:=sortedData!.groupname; 929# originalData:=sortedData!.originalData; 930#Print("Before cutting off: ", torsionCells,"\n"); 931# torsionCells := reducedTorsionCells; 932# numberOfTorsionCells := sortedData[2]; 933# celldata := sortedData[3]; 934# stabilizerCardinalities := sortedData[4]; 935# warned := sortedData[5]; 936N:=1; 937while IsBound(torsionCells[N]) and (not IsEmpty(torsionCells[N])) do 938 N:=N+1; 939od; 940N:=N-2; 941j:=N; 942 943reducedTorsionCells :=StructuralCopy(torsionCells); 944while j>0 do 945#Print("Dimension ",j,"\n"); 946terminalFacets := getTerminalFacets(reducedTorsionCells, celldata, p,j); 947 948while not terminalFacets = [] do 949 reducedTorsionCells := cutOffCells(terminalFacets, reducedTorsionCells, celldata, j); 950 terminalFacets := getTerminalFacets(reducedTorsionCells, celldata, p,j); 951od; 952 953j:=j-1; 954od; 955 956 # Extract the data of torsionCells from original cell data 957 data:=[]; 958 for i in [1..Length(reducedTorsionCells)] do 959 data[i]:=[]; 960 for x in reducedTorsionCells[i] do 961 Add(data[i],celldata[i][x[2]]); 962 od; 963 od; 964#Print("reducedTorsionCells",reducedTorsionCells,"\n"); 965 for j in [2..Length(data)] do 966 for i in [1..Size(data[j])] do 967 tmpCell:=StructuralCopy(data[j][i]!.BoundaryImage); 968 b:=List(tmpCell!.ListIFace,w->Position(reducedTorsionCells[j-1], [j-2,w])); 969 tmpCell!.ListIFace:=b; 970 data[j][i]!.BoundaryImage:=tmpCell; 971 od; 972 od; 973 reducedTorsionCells:=[]; 974 for i in [1..Size(data)] do 975 reducedTorsionCells[i]:=[]; 976 for j in [1..Size(data[i])] do 977 reducedTorsionCells[i][j]:=[i-1,j]; 978 od; 979 od; 980# originalData:=celldata; 981 celldata:=StructuralCopy(data); 982#########################End of cutting off cells################################# 983 984 torsionCells := reducedTorsionCells; 985 986 if warned = false then 987 sortedData := extractPmultipleTorsionCells(torsionCells, 988 numberOfTorsionCells, celldata,stabilizerCardinalities, p); 989#Print("torsionCells ", torsionCells,"\n"); 990#Print("stabilizerCardinalities ", stabilizerCardinalities,"\n"); 991#Print("stabilizerCardinalities ", stabilizerCardinalities,"\n"); 992 993 fusionCandidates := pairsIntersection(sortedData, celldata); 994 fusionCandidates := bifurcationFreeCells(fusionCandidates, torsionCells, 995 celldata); 996 fusionCandidates := checkStabilizerConjugacy(fusionCandidates, celldata, 997 p); 998 while not fusionCandidates=[] do 999 1000#Print("fusionCandidates ", fusionCandidates,"\n"); 1001 cellcomplex:= mergeCells( celldata, fusionCandidates, 1002 torsionCells); 1003 reducedTorsionCells:=cellcomplex[1]; 1004#Print("reducedTorsionCells ", reducedTorsionCells,"\n"); 1005 celldata:=cellcomplex[2]; 1006 numberOfTorsionCells:=List([1..Size(reducedTorsionCells)], 1007 i->Size(reducedTorsionCells[i])); 1008 stabilizerCardinalities:=List([1..Size(reducedTorsionCells)], 1009 i->List([1..Size(reducedTorsionCells[i])],j->Order(celldata[i][j]!.TheMatrixStab))); 1010 sortedData := extractPmultipleTorsionCells(reducedTorsionCells, 1011 numberOfTorsionCells, celldata,stabilizerCardinalities, p); 1012 fusionCandidates := pairsIntersection(sortedData, celldata); 1013 fusionCandidates := bifurcationFreeCells(fusionCandidates, torsionCells, 1014 celldata); 1015 fusionCandidates := checkStabilizerConjugacy(fusionCandidates, celldata, 1016 p); 1017#Print("fusionCandidates: ", fusionCandidates,"\n"); 1018 od; 1019# terminaljMinus1cells := getterminaljMinus1cells(reducedTorsionCells, celldata); 1020# terminaljMinus1cells := checkGruenSwan( terminaljMinus1cells, celldata, p); 1021#Print("\n At the following terminal vertices, the adjacent edge can be cut off without #changing the equivariant Farrell cohomology : ",terminaljMinus1cells,"\n"); 1022# printIsotropyGroups(reducedTorsionCells, celldata); 1023 fi; 1024 1025N:=Size(celldata); 1026while N>0 do 1027 if celldata[N]=[] then 1028 Remove(reducedTorsionCells,N); 1029 Remove(celldata,N); 1030 fi; 1031 N:=N-1; 1032od; 1033 1034##################################################################################### 1035 1036 1037 return Objectify(HapTorsionSubcomplex, 1038 rec( 1039 1040 torsion:=p, 1041 groupname:=groupname, 1042 torsionCells:=torsionCells, 1043# originalData:=data, 1044 celldata:= celldata )); 1045 1046end); 1047 1048##################################################################################### 1049