|
#############################################################################
##
#W gp3obj.gi GAP4 package `XMod' Chris Wensley
## Alper Odabas
## This file implements generic methods for (pre-)crossed squares
## and (pre-)cat2-groups.
##
#Y Copyright (C) 2001-2025, Chris Wensley et al,
#############################################################################
##
#M IsPerm3DimensionalGroup . . check whether the 4 sides are perm 2d-groups
#M IsFp3DimensionalGroup . . . . check whether the 4 sides are fp 2d-groups
#M IsPc3DimensionalGroup . . . . check whether the 4 sides are pc 2d-groups
##
InstallMethod( IsPerm3DimensionalGroup,
"generic method for 3d-group objects", true,
[ IsHigherDimensionalGroup ], 0,
function( obj )
return ( IsPermGroup( Up2DimensionalGroup(obj) )
and IsPermGroup( Left2DimensionalGroup(obj) )
and IsPermGroup( Right2DimensionalGroup(obj) )
and IsPermGroup( Down2DimensionalGroup(obj) )
and IsPermGroup( Diagonal2DimensionalGroup(obj) ) );
end );
InstallMethod( IsFp3DimensionalGroup, "generic method for 3d-group objects",
true, [ IsHigherDimensionalGroup ], 0,
function( obj )
return ( IsFpGroup( Up2DimensionalGroup(obj) )
and IsFpGroup( Left2DimensionalGroup(obj) )
and IsFpGroup( Right2DimensionalGroup(obj) )
and IsFpGroup( Down2DimensionalGroup(obj) )
and IsFpGroup( Diagonal2DimensionalGroup(obj) ) );
end );
InstallMethod( IsPc3DimensionalGroup, "generic method for 3d-group obj ects",
true, [ IsHigherDimensionalGroup ], 0,
function( obj )
return ( IsPcGroup( Up2DimensionalGroup(obj) )
and IsPcGroup( Left2DimensionalGroup(obj) )
and IsPcGroup( Right2DimensionalGroup(obj) )
and IsPcGroup( Down2DimensionalGroup(obj) )
and IsPcGroup( Diagonal2DimensionalGroup(obj) ) );
end );
#############################################################################
##
#M CrossedPairingByCommutators( <grp>, <grp>, <grp> ) . . . . make an xpair
##
InstallMethod( CrossedPairingByCommutators, "for three groups", true,
[ IsGroup, IsGroup, IsGroup ], 0,
function( N, M, L )
local xp;
if not IsSubgroup( L, CommutatorSubgroup(N,M) ) then
Error( "require CommutatorSubgroup(N,M) <= L" );
fi;
xp := function( n, m ) return Comm( n, m ); end ;
return xp;
end );
#############################################################################
##
#M CrossedPairingByConjugators( <grp> ) . . . make an xpair : Inn(M)^2 -> M
##
InstallMethod( CrossedPairingByConjugators, "for inner automorphism group",
true, [ IsGroup ], 0,
function( innM )
local gens, xp;
gens := GeneratorsOfGroup( innM );
if not ForAll( gens, HasConjugatorOfConjugatorIsomorphism ) then
Error( "innM is not a group of inner automorphisms" );
fi;
xp := function( n, m )
local cn, cm;
cn := ConjugatorOfConjugatorIsomorphism( n );
cm := ConjugatorOfConjugatorIsomorphism( m );
return Comm( cn, cm );
end;
return xp;
end );
#############################################################################
##
#M CrossedPairingByDerivations( <xmod> ) . . make an actor crossed pairing
##
InstallMethod( CrossedPairingByDerivations, "for a crossed module", true,
[ IsXMod ], 0,
function( X0 )
local SX, RX, Winv, WR, eWR, WP, reg, imlist, xp;
SX := Source( X0 );
RX := Range( X0 );
Winv := WhiteheadGroupInverseIsomorphism( X0 );
WR := WhiteheadRegularGroup( X0 );
eWR := Elements( WR );
WP := WhiteheadPermGroup( X0 );
reg := RegularDerivations( X0 );
imlist := ImagesList( reg );
xp := function( r, t )
local pos, chi;
pos := Position( eWR, Image( Winv, t ) );
chi := DerivationByImages( X0, imlist[pos] );
return DerivationImage( chi, r );
end;
return xp;
end );
#############################################################################
##
#M CrossedPairingByPreImages( <xmod>, <xmod> ) . . inner autos -> x-pairing
##
InstallMethod( CrossedPairingByPreImages, "for two crossed modules",
true, [ IsXMod, IsXMod ], 0,
function( up, lt )
local L, M, N, kappa, lambda, xp;
L := Source( up );
if not ( Source( lt ) = L ) then
Error( "up and lt should have the same source" );
fi;
M := Range( up );
N := Range( lt );
kappa := Boundary( up );
lambda := Boundary( lt );
xp := function( n, m )
local lm, ln;
ln := PreImagesRepresentativeNC( lambda, n );
lm := PreImagesRepresentativeNC( kappa, m );
return Comm( ln, lm );
end;
return xp;
end );
#############################################################################
##
#M CrossedPairingBySingleXModAction( <xmod>, <subxmod> )
## . . . . . . . . . . . . . . . . action -> x-pairing
#M PrincipalCrossedPairing( <xmod > )
##
InstallMethod( CrossedPairingBySingleXModAction,
"for xmod and normal subxmod", true, [ IsXMod, IsXMod ], 0,
function( rt, lt )
local M, L, N, act, xp;
if not IsNormalSub2DimensionalDomain( rt, lt ) then
Error( "lt not a normal subxmod of rt" );
fi;
M := Source( rt );
L := Source( lt );
N := Range( lt );
act := XModAction( rt );
xp := function( n, m )
return ImageElm( ImageElm(act,n), m^(-1) ) * m;
end;
return xp;
end );
InstallMethod( PrincipalCrossedPairing, "for an xmod", true, [ IsXMod ], 0,
function( X0 )
return CrossedPairingBySingleXModAction( X0, X0 );
end );
#############################################################################
##
#M IsPreCrossedSquare . . . . . . . . . . . . check that the square commutes
##
InstallMethod( IsPreCrossedSquare, "generic method for a pre-crossed square",
true, [ IsHigherDimensionalGroup ], 0,
function( PXS )
local up, lt, rt, dn, dg, L, M, N, P, kappa, lambda, mu, nu, delta,
lambdanu, kappamu, ok, actrt, rngactrt, actdn, rngactdn,
genN, genM, imactNM, actNM, imactMN, actMN, morupdn, morltrt;
if not IsPreCrossedSquareObj( PXS ) then
return false;
fi;
up := Up2DimensionalGroup( PXS );
lt := Left2DimensionalGroup( PXS );
rt := Right2DimensionalGroup( PXS );
dn := Down2DimensionalGroup( PXS );
dg := Diagonal2DimensionalGroup( PXS );
L := Source( up );
M := Range( up );
N := Source( dn );
P := Range( dn );
if not ( ( L = Source(lt) ) and ( N = Range(lt) ) and
( L = Source(dg) ) and ( P = Range(dg) ) and
( M = Source(rt) ) and ( P = Range(rt) ) ) then
Info( InfoXMod, 2, "Incompatible source/range" );
return false;
fi;
## checks for the diagonal
delta := Boundary( dg );
lambda := Boundary( lt );
nu := Boundary( dn );
lambdanu := lambda * nu;
kappa := Boundary( up );
mu := Boundary( rt );
kappamu := kappa * mu;
if not ( lambdanu = delta ) and ( kappamu = delta ) then
Info( InfoXMod, 2, "boundaries in square do not commute" );
return false;
fi;
# construct the cross-diagonal actions
actrt := XModAction( rt );
rngactrt := Range( actrt );
actdn := XModAction( dn );
rngactdn := Range( actdn );
genM := GeneratorsOfGroup( M );
genN := GeneratorsOfGroup( N );
imactNM := List( genN, n -> ImageElm( actrt, ImageElm( nu, n ) ) );
actNM := GroupHomomorphismByImages( N, rngactrt, genN, imactNM );
imactMN := List( genM, m -> ImageElm( actdn, ImageElm( mu, m ) ) );
actMN := GroupHomomorphismByImages( M, rngactdn, genM, imactMN );
SetCrossDiagonalActions( PXS, [ actNM, actMN ] );
#? compatible actions to be checked?
morupdn := PreXModMorphism( up, dn, lambda, mu );
morltrt := PreXModMorphism( lt, rt, kappa, nu );
if not ( IsPreXModMorphism(morupdn) and IsPreXModMorphism(morltrt) ) then
Info( InfoXMod, 2, "morupdn and/or modltrt not prexmod morphisms" );
return false;
fi;
return true;
end );
#############################################################################
##
#M IsCrossedSquare . . . . . . . check all the axioms for a crossed square
##
InstallMethod( IsCrossedSquare, "generic method for a crossed square",
true, [ IsHigherDimensionalGroup ], 0,
function( XS )
local up, lt, rt, dn, L, M, N, P, kappa, lambda, mu, nu,
autu, autl, actdg, dg, ok, morud, morlr,
genL, genM, genN, genP, actup, actlt, actrt, actdn, l, p,
xp, x, y, z, m, n, m2, n2, am, an, apdg, aprt, apdn, nboxm;
if not ( IsPreCrossedSquare( XS ) and HasCrossedPairing( XS ) ) then
return false;
fi;
up := Up2DimensionalGroup( XS );
lt := Left2DimensionalGroup( XS );
rt := Right2DimensionalGroup( XS );
dn := Down2DimensionalGroup( XS );
dg := Diagonal2DimensionalGroup( XS );
L := Source( up );
M := Range( up );
N := Source( dn );
P := Range( dn );
kappa := Boundary( up );
lambda := Boundary( lt );
mu := Boundary( rt );
nu := Boundary( dn );
genL := GeneratorsOfGroup( L );
genM := GeneratorsOfGroup( M );
genN := GeneratorsOfGroup( N );
genP := GeneratorsOfGroup( P );
actup := XModAction( up );
actlt := XModAction( lt );
actrt := XModAction( rt );
actdn := XModAction( dn );
actdg := XModAction( dg );
## check that kappa,lambda preserve the action of P
for p in genP do
apdg := ImageElm( actdg, p );
aprt := ImageElm( actrt, p );
apdn := ImageElm( actdn, p );
for l in genL do
if not ( ImageElm( kappa, ImageElm( apdg, l ) )
= ImageElm( aprt, ImageElm( kappa, l ) ) ) then
Info( InfoXMod, 2, "action of P on up is not preserved" );
return false;
fi;
if not ( ImageElm( lambda, ImageElm( apdg, l ) )
= ImageElm( apdn, ImageElm( lambda, l ) ) ) then
Info( InfoXMod, 2, "action of P on lt is not preserved" );
return false;
fi;
od;
od;
## check the axioms for a crossed pairing
xp := CrossedPairing( XS );
for n in genN do
for n2 in genN do
for m in genM do
x := xp( n*n2, m );
an := ImageElm( actlt, n2 );
y := ImageElm( an, xp( n, m ) );
z := xp( n2, m );
if not x = y * z then
Info( InfoXMod, 2,
"n1,n2,m crossed pairing axiom fails" );
return false;
fi;
od;
od;
od;
for n in genN do
for m in genM do
for m2 in genM do
x := xp( n, m*m2 );
am := ImageElm( actup, m2 );
y := ImageElm( am, xp( n, m ) );
if not x = xp( n, m2 ) * y then
Info( InfoXMod, 2,
"n,m1,m2 crossed pairing axiom fails" );
return false;
fi;
od;
od;
od;
for p in genP do
apdg := ImageElm( actdg, p );
aprt := ImageElm( actrt, p );
apdn := ImageElm( actdn, p );
for n in genN do
for m in genM do
if not ImageElm( apdg, xp( n, m ) )
= xp( ImageElm(apdn,n), ImageElm(aprt,m) ) then
Info( InfoXMod, 2, "n,m,p crossed pairing axiom fails" );
return false;
fi;
od;
od;
od;
## check that kappa,lambda correctly map (n box m)
for n in genN do
an := ImageElm( actrt, ImageElm( nu, n ) );
for m in genM do
am := ImageElm( actdn, ImageElm( mu, m ) );
nboxm := xp( n, m );
if not ImageElm( lambda, nboxm ) = n^(-1) * ImageElm( am, n )
and ImageElm( kappa, nboxm ) = ImageElm( an, m^(-1) ) * m then
Info( InfoXMod, 2,
"kappa,lambda do not map nboxm correctly" );
return false;
fi;
od;
od;
## check crossed pairing on images of kappa,lambda
for m in genM do
## am := ImageElm( actdg, ImageElm( mu, m ) );
am := ImageElm( actup, m );
for l in genL do
if not ( xp( ImageElm( lambda, l ), m )
= l^(-1) * ImageElm( am, l ) ) then
Info( InfoXMod, 2, "incorrect image for (lambda(l) box n)" );
return false;
fi;
od;
od;
for n in genN do
## an := ImageElm( actdg, ImageElm( nu, n ) );
an := ImageElm( actlt, n );
for l in genL do
if not ( xp( n, ImageElm( kappa, l ) )
= ImageElm( an, l^(-1) ) * l ) then
Info( InfoXMod, 2, "incorrect image for (n box kappa(l))" );
return false;
fi;
od;
od;
return true;
end );
#############################################################################
##
#M PreCrossedSquareObj ( <up>, <left>, <right>, <down>, <diag>, <pair> )
## . . . make a PreCrossedSquare
##
InstallMethod( PreCrossedSquareObj, "for prexmods, action and pairing", true,
[ IsPreXMod, IsPreXMod, IsPreXMod, IsPreXMod, IsObject, IsObject ], 0,
function( up, lt, rt, dn, dg, xp )
local PS;
## test commutativity here?
PS := rec();
ObjectifyWithAttributes( PS, PreCrossedSquareObjType,
Up2DimensionalGroup, up,
Left2DimensionalGroup, lt,
Right2DimensionalGroup, rt,
Down2DimensionalGroup, dn,
Diagonal2DimensionalGroup, dg,
CrossedPairing, xp,
HigherDimension, 3,
Is3DimensionalGroup, true );
if not IsPreCrossedSquare( PS ) then
Info( InfoXMod, 1, "Warning: not a pre-crossed square." );
fi;
return PS;
end );
#############################################################################
##
#F PreCrossedSquare( <up>, <lt>, <rt>, <dn>, <dg>, <xp> )
## . . . . . . . . . . . comprising 5 prexmods + pairing
#F PreCrossedSquare( <PC2> ) . . . . . . . . . . . . for a pre-cat2-group
##
InstallGlobalFunction( PreCrossedSquare, function( arg )
local nargs, PXS, ok;
nargs := Length( arg );
ok := true;
if ( nargs = 1 ) then
if ( HasIsPreCat2Group( arg[1] ) and IsPreCat2Group( arg[1] ) ) then
Info( InfoXMod, 1, "pre-crossed square of a pre-cat2-group" );
PXS := PreCrossedSquareOfPreCat2Group( arg[1] );
else
ok := false;
fi;
elif ( nargs = 6 ) then
PXS := PreCrossedSquareByPreXMods(
arg[1], arg[2], arg[3], arg[4], arg[5], arg[6] );
else
ok := false;
fi;
if not ok then
Print( "standard usage for the function PreCrossedSquare:\n" );
Print( " PreCrossedSquare(<up>,<lt>,<rt>,<dn>,<dg>,<xp>);\n" );
Print( " for 5 pre-crossed modules and a crossed pairing\n" );
Print( "or: PreCrossedSquare( <PC2G> ); for a pre-cat2-group> );\n" );
return fail;
fi;
return PXS;
end );
#############################################################################
##
#F CrossedSquare( <up>, <lt>, <rt>, <dn>, <dg>, <xp> ) 5 xmods and a pairing
#F CrossedSquare( <L>, <M>, <N>, <P> ) . . . . . . . . by normal subgroups
#F CrossedSquare( <X0> ) . . . . . . . . . . . . . . . actor crossed square
#F CrossedSquare( <X0>, <X1> ) . . . . . . . . . . . . by pullback
#F CrossedSquare( <X0>, <X1> ) . . . . . . . . . . . . by normal subxmod
#F CrossedSquare( <C2G> ) . . . . . . . . . . . . . . for a cat2-group
##
InstallGlobalFunction( CrossedSquare, function( arg )
local nargs, XS, ok;
nargs := Length( arg );
ok := true;
if ( nargs = 1 ) then
if ( HasIsXMod( arg[1] ) and IsXMod( arg[1] ) ) then
Info( InfoXMod, 1, "crossed square by splitting" );
XS := CrossedSquareByXModSplitting( arg[1] );
elif ( HasIsCat2Group( arg[1] ) and IsCat2Group( arg[1] ) ) then
Info( InfoXMod, 1, "crossed square of a cat2-group" );
XS := PreCrossedSquareOfPreCat2Group( arg[1] );
else
ok := false;
fi;
elif ( nargs = 2 ) then
if ( HasIsXMod( arg[1] ) and IsXMod( arg[1] )
and HasIsXMod( arg[2] ) and IsXMod( arg[2] ) ) then
if Range( arg[1] ) = Range( arg[2] ) then
Info( InfoXMod, 1, "crossed square by pullback" );
XS := CrossedSquareByPullback( arg[1], arg[2] );
elif IsNormalSub2DimensionalDomain( arg[1], arg[2] ) then
Info( InfoXMod, 1, "crossed square by normal subxmod" );
XS := CrossedSquareByNormalSubXMod( arg[1], arg[2] );
else
ok := false;
fi;
else
ok := false;
fi;
elif ( nargs = 4 ) and ForAll( arg, IsGroup ) then
XS := CrossedSquareByNormalSubgroups(arg[1],arg[2],arg[3],arg[4]);
elif ( nargs = 6 ) then
XS := CrossedSquareByXMods(arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
else
ok := false;
fi;
if not ok then
Print( "standard usage for the function CrossedSquare:\n" );
Print( " CrossedSquare( <up>, <lt>, <rt>, <dn>, <dg>, <xp> );\n" );
Print( " for 5 crossed modules and a crossed pairing\n" );
Print( "or: CrossedSquare( <L>, <M>, <N>, <P> ); " );
Print( "for 3 normal subgroups of P\n" );
Print( "or: CrossedSquare( <X0>, <X1> ); for a pullback\n" );
Print( "or: CrossedSquare( <X0>, <X1> ); for a normal subxmod\n" );
Print( "or: CrossedSquare( <X0> ); for splitting an xmod\n" );
Print( "or: CrossedSquare( <C2G> ); for a cat2-group> );\n" );
return fail;
fi;
return XS;
end );
#############################################################################
##
#M PreCrossedSquareByPreXMods . pre-crossed square from 5 pre-xmods + xpair
#M CrossedSquareByXMods . . . . . . . . crossed square from 5 xmods + xpair
##
InstallMethod( PreCrossedSquareByPreXMods, "default pre-crossed square",
true,
[ IsPreXMod, IsPreXMod, IsPreXMod,
IsPreXMod, IsPreXMod, IsFunction ], 0,
function( up, left, right, down, diag, xp )
local L, M, N, P, kappa, lambda, mu, nu, delta, n, m, PXS;
L := Source( up );
M := Range( up );
N := Source( down );
P := Range( down );
kappa := Boundary( up );
lambda := Boundary( left );
mu := Boundary( right );
nu := Boundary( down );
delta := Boundary( diag );
## checks
if not ( ( L = Source( left ) ) and ( N = Range( left ) )
and ( M = Source( right ) ) and ( P = Range( right ) )
and ( L = Source( diag ) ) and ( P = Range( diag ) ) ) then
Error( "sources and ranges not matching" );
fi;
for n in GeneratorsOfGroup( N ) do
for m in GeneratorsOfGroup( M ) do
if not ( xp( n, m ) in L ) then
Error( "incorrect source/range for crossed pairing" );
fi;
od;
od;
PXS := PreCrossedSquareObj( up, left, right, down, diag, xp );
if not IsPreCrossedSquare( PXS ) then
Error( "PXS fails to be a crossed square" );
fi;
return PXS;
end );
InstallMethod( CrossedSquareByXMods, "default crossed square", true,
[ IsXMod, IsXMod, IsXMod, IsXMod, IsXMod, IsFunction ], 0,
function( up, left, right, down, diag, xp )
local XS;
XS := PreCrossedSquareByPreXMods( up, left, right, down, diag, xp );
if not IsCrossedSquare( XS ) then
Info( InfoXMod, 1, "XS fails to be a crossed square" );
return fail;
fi;
return XS;
end );
#############################################################################
##
#M CrossedSquareByNormalSubgroups . . crossed square from normal L,M,N in P
##
InstallMethod( CrossedSquareByNormalSubgroups, "conjugation crossed square",
true, [ IsGroup, IsGroup, IsGroup, IsGroup ], 0,
function( L, M, N, P )
local XS, up, lt, rt, dn, dg, xp, diag;
if not ( IsNormal(P,M) and IsNormal(P,N) and IsNormal(L,P) ) then
Error( "M,N,L fail to be normal subgroups of P" );
fi;
if not ( IsNormal( M, L ) and IsNormal( N, L ) ) then
Error( "L fails to be a normal subgroup of both M and N" );
fi;
if not ( IsSubgroup( Intersection(M,N), L )
and IsSubgroup( L, CommutatorSubgroup(M,N) ) ) then
Error( "require CommutatorSubgroup(M,N) <= L <= Intersection(M,N)" );
fi;
up := XModByNormalSubgroup( M, L );
lt := XModByNormalSubgroup( N, L );
rt := XModByNormalSubgroup( P, M );
dn := XModByNormalSubgroup( P, N );
dg := XModByNormalSubgroup( P, L );
## define the pairing as a commutator
xp := CrossedPairingByCommutators( N, M, L );
XS := PreCrossedSquareObj( up, lt, rt, dn, dg, xp );
## SetIsCrossedSquare( XS, true );
## SetIs3DimensionalGroup( XS, true );
SetDiagonal2DimensionalGroup( XS, dg );
if not IsCrossedSquare( XS ) then
Error( "XS fails to be a crossed square by normal subgroups" );
fi;
return XS;
end );
InstallMethod( CrossedSquareByNormalSubgroups,
"conjugation crossed square", true, [ IsGroup, IsGroup, IsGroup ], 0,
function( M, N, P )
local XS, genP, genM, genN, L, genL, u, d, l, r, a, p, diag;
if not ( IsNormal( P, M ) and IsNormal( P, N ) ) then
return fail;
fi;
L := Intersection( M, N );
return CrossedSquareByNormalSubgroups( L, M, N, P );
end );
#############################################################################
##
#M CrossedSquareByNormalSubXMod . crossed square from xmod + normal subxmod
##
InstallMethod( CrossedSquareByNormalSubXMod,
"for an xmod and normal subxmod", true, [ IsXMod, IsXMod ], 0,
function( rt, lt )
local M, L, up, P, N, dn, xp, dg, XS;
if not IsNormalSub2DimensionalDomain( rt, lt ) then
return fail;
fi;
M := Source( rt );
L := Source( lt );
up := XModByNormalSubgroup( M, L );
P := Range( rt );
N := Range( lt );
dn := XModByNormalSubgroup( P, N );
xp := CrossedPairingBySingleXModAction( rt, lt );
dg := SubXMod( rt, L, P );
XS := PreCrossedSquareObj( up, lt, rt, dn, dg, xp );
if not IsCrossedSquare( XS ) then
Error( "XS fails to be a crossed square by normal subxmod" );
fi;
return XS;
end );
#############################################################################
##
#M CrossedSquareByXModSplitting . . xsq by surjection followed by injection
##
InstallMethod( CrossedSquareByXModSplitting, "for an xmod", true,
[ IsXMod ], 0,
function( X0 )
local S, R, bdy, Q, up, dn, xp, XS;
S := Source( X0 );
R := Range( X0 );
Q := ImagesSource( Boundary( X0 ) );
up := SubXMod( X0, S, Q );
dn := XModByNormalSubgroup( R, Q );
xp := CrossedPairingByPreImages( up, up );
XS := PreCrossedSquareObj( up, up, dn, dn, X0, xp );
## SetIsCrossedSquare( XS, true );
if not IsCrossedSquare( XS ) then
Error( "XS fails to be a crossed square by xmod splitting" );
fi;
return XS;
end );
#############################################################################
##
#M CrossedSquareByPullback . . . . . . . . for two xmods with a common range
##
InstallMethod( CrossedSquareByPullback, "for 2 xmods with a common range",
true, [ IsXMod, IsXMod ], 0,
function( dn, rt )
local M, N, P, actM, actN, mu, nu, L, genL, lenL, Linfo, dp, dpinfo,
embM, embN, kappa, lambda, map, xp, autL, genLN, genLM, genLNP,
genLMP, genP, lenP, imactPL, i, g, ima, a, actPL, genN, lenN,
imactNL, actNL, lt, genM, lenM, imactML, actML, up,
imdelta, delta, dg, XS;
M := Source( rt );
N := Source( dn );
P := Range( rt );
if not ( Range( dn ) = P ) then
Error( "the two xmods should have a common range" );
fi;
actM := XModAction( rt );
actN := XModAction( dn );
mu := Boundary( rt );
nu := Boundary( dn );
L := Pullback( nu, mu );
genL := GeneratorsOfGroup( L );
lenL := Length( genL );
Linfo := PullbackInfo( L );
if HasName(M) and HasName(N) and HasName(P) then
SetName( L, Concatenation( "(", Name(N), " x_", Name(P),
" ", Name(M), ")" ) );
fi;
dp := Linfo!.directProduct;
dpinfo := DirectProductInfo( dp );
embN := Embedding( dp, 1 );
embM := Embedding( dp, 2 );
lambda := Linfo!.projections[1];
genLN := List( genL, l -> ImageElm( lambda, l ) );
kappa := Linfo!.projections[2];
genLM := List( genL, l -> ImageElm( kappa, l ) );
## construct the crossed pairing
xp := function( n, m )
local nun, mum, n2, m2, l;
nun := ImageElm( nu, n );
mum := ImageElm( mu, m );
## h(n,m) = (n^{-1}.n^mum, (m^{-1})^nun.m)
n2 := n^(-1) * ImageElm( ImageElm( actN, mum ), n );
m2 := ImageElm( ImageElm( actM, nun ), m^(-1) ) * m;
l := ImageElm( embN, n2 ) * ImageElm( embM, m2 );
if not ( l in L ) then
Error( "element l appears not to be in L" );
fi;
return l;
end;
autL := AutomorphismGroup( L );
genP := GeneratorsOfGroup( P );
lenP := Length( genP );
imactPL := ListWithIdenticalEntries( lenP, 0 );
for i in [1..lenP] do
g := genP[i];
genLNP := List( genLN, n -> ImageElm( ImageElm( actN, g ), n ) );
genLMP := List( genLM, m -> ImageElm( ImageElm( actM, g ), m ) );
ima := List( [1..lenL], j -> ImageElm( embN, genLNP[j] )
* ImageElm( embM, genLMP[j] ) );
a := GroupHomomorphismByImages( L, L, genL, ima );
imactPL[i] := a;
od;
actPL := GroupHomomorphismByImages( P, autL, genP, imactPL );
imdelta := List( genL, l -> ImageElm( nu, ImageElm( lambda, l ) ) );
delta := GroupHomomorphismByImages( L, P, genL, imdelta );
dg := XModByBoundaryAndAction( delta, actPL );
genN := GeneratorsOfGroup( N );
lenN := Length( genN );
imactNL := ListWithIdenticalEntries( lenN, 0 );
for i in [1..lenN] do
g := ImageElm( nu, genN[i] );
a := ImageElm( actPL, g );
imactNL[i] := a;
od;
actNL := GroupHomomorphismByImages( N, autL, genN, imactNL );
lt := XMod( lambda, actNL );
genM := GeneratorsOfGroup( M );
lenM := Length( genM );
imactML := ListWithIdenticalEntries( lenM, 0 );
for i in [1..lenM] do
g := ImageElm( mu, genM[i] );
a := ImageElm( actPL, g );
imactML[i] := a;
od;
actML := GroupHomomorphismByImages( M, autL, genM, imactML );
up := XMod( kappa, actML );
XS := PreCrossedSquareObj( up, lt, rt, dn, dg, xp );
## SetIsCrossedSquare( XS, true );
if not IsCrossedSquare( XS ) then
Error( "XS fails to be a crossed square by pullback" );
fi;
return XS;
end );
#############################################################################
##
#M ActorCrossedSquare . . create a crossed square from an xmod and its actor
##
InstallMethod( ActorCrossedSquare, "actor crossed square", true,
[ IsXMod ], 0,
function( X0 )
local XS, WX, LX, NX, AX, xp;
AX := ActorXMod( X0 );
WX := WhiteheadXMod( X0 );
NX := NorrieXMod( X0 );
LX := LueXMod( X0 );
## define the pairing as evaluation of a derivation
xp := CrossedPairingByDerivations( X0 );
## XS := PreCrossedSquareObj( X0, WX, NX, AX, da, xp );
XS := PreCrossedSquareObj( WX, X0, AX, NX, LX, xp );
## SetIsCrossedSquare( XS, true );
## Error("here");
if not IsCrossedSquare( XS ) then
Error( "XS fails to be an actor crossed square" );
fi;
return XS;
end );
#############################################################################
##
#M CrossedSquareByAutomorphismGroup . . crossed square G -> Inn(G) -> Aut(G)
##
InstallMethod( CrossedSquareByAutomorphismGroup, "G -> Inn(G) -> Aut(G)",
true, [ IsGroup ], 0,
function( G )
local genG, innG, up, autG, dn, dg, xp, XS;
genG := GeneratorsOfGroup( G );
innG := InnerAutomorphismsByNormalSubgroup( G, G );
if ( not HasName( innG ) and HasName( G ) ) then
SetName( innG, Concatenation( "Inn(", Name( G ), ")" ) );
fi;
SetIsGroupOfAutomorphisms( innG, true );
up := XModByGroupOfAutomorphisms( G, innG );
autG := AutomorphismGroup( G );
if ( not HasName( autG ) and HasName( G ) ) then
SetName( autG, Concatenation( "Aut(", Name( G ), ")" ) );
fi;
if not IsSubgroup( autG, innG ) then
Error( "innG is not a subgroup of autG" );
fi;
dg := XModByAutomorphismGroup( G );
dn := XModByNormalSubgroup( autG, innG );
## define the pairing
xp := CrossedPairingByConjugators( innG );
XS := PreCrossedSquareObj( up, up, dn, dn, dg, xp );
## SetIsCrossedSquare( XS, true );
if not IsCrossedSquare( XS ) then
Error( "XS fails to be a crossed square by automorphism group" );
fi;
return XS;
end );
#############################################################################
##
#M Name . . . . . . . . . . . . . . . . . . . . . for a 3-dimensional group
##
InstallOtherMethod( Name, "method for a pre-crossed square", true,
[ IsHigherDimensionalGroup ], 0,
function( PS )
local nul, nur, ndl, ndr, name, mor;
if not ( HigherDimension( PS ) = 3 ) then
TryNextMethod();
else
if HasName( Source( Up2DimensionalGroup( PS ) ) ) then
nul := Name( Source( Up2DimensionalGroup( PS ) ) );
else
nul := "..";
fi;
if HasName( Range( Up2DimensionalGroup( PS ) ) ) then
nur := Name( Range( Up2DimensionalGroup( PS ) ) );
else
nur := "..";
fi;
if HasName( Source( Down2DimensionalGroup( PS ) ) ) then
ndl := Name( Source( Down2DimensionalGroup( PS ) ) );
else
ndl := "..";
fi;
if HasName( Range( Down2DimensionalGroup( PS ) ) ) then
ndr := Name( Range( Down2DimensionalGroup( PS ) ) );
else
ndr := "..";
fi;
name := Concatenation( "[", nul, "->", nur, ",", ndl, "->", ndr, "]" );
SetName( PS, name );
return name;
fi;
end );
#############################################################################
##
#M Size3d . . . . . . . . . . . . . . . . . . . . for a 3-dimensional group
##
InstallMethod( Size3d, "method for a 3d-object", true,
[ Is3DimensionalDomain ], 0,
function( PS )
return [ Size( Source( Up2DimensionalGroup( PS ) ) ),
Size( Range( Up2DimensionalGroup( PS ) ) ),
Size( Source( Down2DimensionalGroup( PS ) ) ),
Size( Range( Down2DimensionalGroup( PS ) ) ) ];
end );
InstallOtherMethod( Size, "generic method for a 3d-object",
[ Is3DimensionalDomain ], 0,
function ( obj )
Error( "use operation Size3d for 3d-objects" );
return fail;
end );
#############################################################################
##
#M IdGroup . . . . . . . . . . . . . . . . . . . . for a 3-dimensional group
##
InstallOtherMethod( IdGroup, "method for a 3-dimensional group", true,
[ IsHigherDimensionalGroup ], 0,
function( PS )
return [ IdGroup( Source( Up2DimensionalGroup( PS ) ) ),
IdGroup( Range( Up2DimensionalGroup( PS ) ) ),
IdGroup( Source( Down2DimensionalGroup( PS ) ) ),
IdGroup( Range( Down2DimensionalGroup( PS ) ) ) ];
end );
#############################################################################
##
#M StructureDescription . . . . . . . . . . . . . for a 3-dimensional group
##
InstallOtherMethod( StructureDescription, "method for a 3-dimensional group",
true, [ IsHigherDimensionalGroup ], 0,
function( PS )
return [ StructureDescription( Source( Up2DimensionalGroup( PS ) ) ),
StructureDescription( Range( Up2DimensionalGroup( PS ) ) ),
StructureDescription( Source( Down2DimensionalGroup( PS ) ) ),
StructureDescription( Range( Down2DimensionalGroup( PS ) ) ) ];
end );
#############################################################################
##
#M \=( <dom1>, <dom2> ) . . . . . . . . . . test if two 3d-objects are equal
##
InstallMethod( \=,
"generic method for two 3d-domains", IsIdenticalObj,
[ IsHigherDimensionalGroup, IsHigherDimensionalGroup ], 0,
function ( dom1, dom2 )
if not ( ( HigherDimension( dom1 ) = 3 )
and ( HigherDimension( dom2 ) = 3 ) ) then
TryNextMethod();
else
return(
( Up2DimensionalGroup(dom1) = Up2DimensionalGroup(dom2) )
and ( Left2DimensionalGroup(dom1) = Left2DimensionalGroup(dom2) )
and ( Right2DimensionalGroup(dom1) = Right2DimensionalGroup(dom2) )
and ( Down2DimensionalGroup(dom1) = Down2DimensionalGroup(dom2) )
and ( Diagonal2DimensionalGroup(dom1)
= Diagonal2DimensionalGroup(dom2) ) );
fi;
end );
#############################################################################
##
#M String, ViewString, PrintString, ViewObj, PrintObj . . . . for a 3d-group
##
InstallMethod( String, "for a 3d-group", true, [ IsPreCrossedSquare ], 0,
function( g3d )
return( STRINGIFY( "pre-crossed square" ) );
end );
InstallMethod( ViewString, "for a 3d-group", true, [ IsPreCrossedSquare ],
0, String );
InstallMethod( PrintString, "for a 3d-group", true, [ IsPreCrossedSquare ],
0, String );
InstallMethod( PrintObj, "method for a 3d-group", true,
[ IsPreCrossedSquare ], 0,
function( g3d )
local L, M, N, P, lenL, lenM, lenN, lenP, len1, len2, j, q1, q2,
ispsq, arrow, ok, n, i;
if HasName( g3d ) then
Print( Name( g3d ), "\n" );
else
if ( HasIsPreCrossedSquare( g3d )
and IsPreCrossedSquare( g3d ) ) then
ispsq := true;
arrow := " -> ";
else
ispsq := false;
arrow := " => ";
fi;
L := Source( Up2DimensionalGroup( g3d ) );
M := Range( Up2DimensionalGroup( g3d ) );
N := Source( Down2DimensionalGroup( g3d ) );
P := Range( Down2DimensionalGroup( g3d ) );
ok := HasName(L) and HasName(M) and HasName(N) and HasName(P);
if ok then
lenL := Length( Name( L ) );
lenM := Length( Name( M ) );
lenN := Length( Name( N ) );
lenP := Length( Name( P ) );
len1 := Maximum( lenL, lenN );
len2 := Maximum( lenM, lenP );
q1 := QuoInt( len1, 2 );
q2 := QuoInt( len2, 2 );
Print( "[ " );
for j in [1..lenN-lenL] do Print(" "); od;
Print( Name(L), arrow, Name(M) );
for j in [1..lenP-lenM] do Print(" "); od;
Print( " ]\n[ " );
for j in [1..q1] do Print(" "); od;
Print( "|" );
for j in [1..q1+RemInt(len1,2)+2+q2+RemInt(len2,2)] do
Print(" ");
od;
Print( "|" );
for j in [1..q2] do Print(" "); od;
Print( " ]\n" );
Print( "[ " );
for j in [1..lenL-lenN] do Print(" "); od;
Print( Name(N), " -> ", Name(P) );
for j in [1..lenM-lenP] do Print(" "); od;
Print( " ]\n" );
else
if ispsq then
if ( HasIsCrossedSquare(g3d) and IsCrossedSquare(g3d) ) then
Print( "crossed square with crossed modules:\n" );
else
Print( "pre-crossed square with pre-crossed modules:\n" );
fi;
fi;
Print( " up = ", Up2DimensionalGroup( g3d ), "\n" );
Print( " left = ", Left2DimensionalGroup( g3d ), "\n" );
Print( " right = ", Right2DimensionalGroup( g3d ), "\n" );
Print( " down = ", Down2DimensionalGroup( g3d ), "\n" );
fi;
fi;
end );
InstallMethod( ViewObj, "method for a 3d-group", true,
[ IsPreCrossedSquare ], 0, PrintObj );
#############################################################################
##
#M Display( <g3d> . . . . . . . . . . . . . . . . . . . . display a 3d-group
##
InstallMethod( DisplayLeadMaps, "method for a pre-cat2-group", true,
[ IsPreCat2Group ], 0,
function( g3d )
local up, tup, hup, lt, tlt, hlt;
up := Up2DimensionalGroup( g3d );
tup := TailMap( up );
hup := HeadMap( up );
lt := Left2DimensionalGroup( g3d );
tlt := TailMap( lt );
hlt := HeadMap( lt );
Print( "(pre-)cat2-group with up-left group: ",
MappingGeneratorsImages( tup )[1], "\n" );
if ( tup = hup ) then
Print( " up tail=head images: ",
MappingGeneratorsImages( tup )[2], "\n" );
else
Print( " up tail/head images: ",
MappingGeneratorsImages( tup )[2], ", ",
MappingGeneratorsImages( hup )[2], "\n" );
fi;
if ( tlt = hlt ) then
Print( " left tail=head images: ",
MappingGeneratorsImages( tlt )[2], "\n" );
else
Print( " left tail/head images: ",
MappingGeneratorsImages( tlt )[2], ", ",
MappingGeneratorsImages( hlt )[2], "\n" );
fi;
end );
#############################################################################
##
#M Display( <g3d> . . . . . . . . . . . . . . . . . . . . display a 3d-group
##
InstallMethod( Display, "method for a pre-cat2-group", true,
[ IsPreCat2Group ], 0,
function( g3d )
local up, tup, hup, lt, tlt, hlt, rt, trt, hrt, dn, tdn, hdn;
up := Up2DimensionalGroup( g3d );
tup := TailMap( up );
hup := HeadMap( up );
lt := Left2DimensionalGroup( g3d );
tlt := TailMap( lt );
hlt := HeadMap( lt );
rt := Right2DimensionalGroup( g3d );
trt := TailMap( rt );
hrt := HeadMap( rt );
dn := Down2DimensionalGroup( g3d );
tdn := TailMap( dn );
hdn := HeadMap( dn );
Print( "(pre-)cat2-group with groups: ",
[ Source(up), Range(up), Range(lt), Range(dn) ], "\n" );
if ( tup = hup ) then
Print( " up tail=head: ",
MappingGeneratorsImages( tup ), "\n" );
else
Print( " up tail/head: ",
MappingGeneratorsImages( tup ),
MappingGeneratorsImages( hup ), "\n" );
fi;
if ( tlt = hlt ) then
Print( " left tail=head: ",
MappingGeneratorsImages( tlt ), "\n" );
else
Print( " left tail/head: ",
MappingGeneratorsImages( tlt ),
MappingGeneratorsImages( hlt ), "\n" );
fi;
if ( trt = hrt ) then
Print( "right tail=head: ",
MappingGeneratorsImages( trt ), "\n" );
else
Print( "right tail/head: ",
MappingGeneratorsImages( trt ),
MappingGeneratorsImages( hrt ), "\n" );
fi;
if ( tdn = hdn ) then
Print( " down tail=head: ",
MappingGeneratorsImages( tdn ), "\n" );
else
Print( " down tail/head: ",
MappingGeneratorsImages( tdn ),
MappingGeneratorsImages( hdn ), "\n" );
fi;
end );
InstallMethod( Display, "method for a pre-crossed square", true,
[ IsPreCrossedSquare ], 0,
function( g3d )
local L, M, N, P, lenL, lenM, lenN, lenP, len1, len2, j, q1, q2,
ispsq, arrow, ok, n, i;
arrow := " -> ";
L := Source( Up2DimensionalGroup( g3d ) );
M := Range( Up2DimensionalGroup( g3d ) );
N := Source( Down2DimensionalGroup( g3d ) );
P := Range( Down2DimensionalGroup( g3d ) );
ok := HasName(L) and HasName(M) and HasName(N) and HasName(P);
if ok then
lenL := Length( Name( L ) );
lenM := Length( Name( M ) );
lenN := Length( Name( N ) );
lenP := Length( Name( P ) );
len1 := Maximum( lenL, lenN );
len2 := Maximum( lenM, lenP );
q1 := QuoInt( len1, 2 );
q2 := QuoInt( len2, 2 );
Print( "[ " );
for j in [1..lenN-lenL] do Print(" "); od;
Print( Name(L), arrow, Name(M) );
for j in [1..lenP-lenM] do Print(" "); od;
Print( " ]\n[ " );
for j in [1..q1] do Print(" "); od;
Print( "|" );
for j in [1..q1+RemInt(len1,2)+2+q2+RemInt(len2,2)] do
Print(" ");
od;
Print( "|" );
for j in [1..q2] do Print(" "); od;
Print( " ]\n" );
Print( "[ " );
for j in [1..lenL-lenN] do Print(" "); od;
Print( Name(N), " -> ", Name(P) );
for j in [1..lenM-lenP] do Print(" "); od;
Print( " ]\n" );
else
Print( "(pre-)crossed square with (pre-)crossed modules:\n" );
Print( " up = ", Up2DimensionalGroup( g3d ), "\n" );
Print( " left = ", Left2DimensionalGroup( g3d ), "\n" );
Print( " right = ", Right2DimensionalGroup( g3d ), "\n" );
Print( " down = ", Down2DimensionalGroup( g3d ), "\n" );
fi;
end );
#############################################################################
##
#M IsPreCat2Group . . . . . . . . . . . check that this is a pre-cat2-group
#M IsCat2Group . . . . . . . . . . . . check that the object is a cat2-group
##
InstallMethod( IsPreCat2Group, "generic method for a pre-cat2-group",
true, [ IsHigherDimensionalGroup ], 0,
function( P )
if not ( IsPreCatnObj( P ) ) then
return false;
fi;
if ( IsPreCatnGroup( P ) and ( HigherDimension( P ) = 3 ) ) then
return true;
else
return false;
fi;
end );
InstallMethod( IsCat2Group, "generic method for a cat2-group",
true, [ IsHigherDimensionalGroup ], 0,
function( P )
local ok;
ok := ( HigherDimension( P ) = 3 )
and IsCat1Group( Up2DimensionalGroup( P ) )
and IsCat1Group( Left2DimensionalGroup( P ) )
and IsCat1Group( Right2DimensionalGroup( P ) )
and IsCat1Group( Down2DimensionalGroup( P ) )
and IsPreCat1Group( Diagonal2DimensionalGroup( P ) );
return ok;
end );
#############################################################################
##
#M PreCat2GroupObj( [<up>,<left>,<right>,<down>,<diag>] )
##
InstallMethod( PreCat2GroupObj, "for a list of pre-cat1-groups", true,
[ IsList ], 0,
function( L )
local PC, ok;
if not ( Length( L ) = 5 ) then
Error( "there should be 5 pre-cat1-groups in the list L" );
fi;
PC := rec();
ObjectifyWithAttributes( PC, PreCat2GroupObjType,
Up2DimensionalGroup, L[1],
Left2DimensionalGroup, L[2],
Right2DimensionalGroup, L[3],
Down2DimensionalGroup, L[4],
Diagonal2DimensionalGroup, L[5],
GeneratingCat1Groups, [ L[1], L[2] ],
HigherDimension, 3,
IsHigherDimensionalGroup, true,
IsPreCat2Group, true,
IsPreCatnGroup, true );
ok := IsCat2Group( PC );
return PC;
end );
#############################################################################
##
#F (Pre)Cat2Group( [ up, lt (,diag) ) cat2-group from 2/3 (pre)cat1-groups
#F (Pre)Cat2Group( XS ) cat2-group from (pre)crossed square
##
InstallGlobalFunction( PreCat2Group, function( arg )
local nargs, up, left, diag, C2G, G1, G2, G3, isoG, genG,
imt, t12, imh, h12, e12, idQ, isoleft, drd, ok;
nargs := Length( arg );
if not ( nargs in [1,2] ) then
Print( "standard usage: (Pre)Cat2Group( up, left );\n" );
Print( " or: (Pre)Cat2Group( XS );\n" );
return fail;
fi;
if ( nargs = 1 ) then
C2G := PreCat2GroupOfPreCrossedSquare( arg[1] );
else
up := arg[1];
left := arg[2];
G1 := Source( up );
G2 := Source( left );
## if the two sources are unequal but isomorphic then make
## an isomorphic copy of left with the same source as up
if not ( G1 = G2 ) then
isoG := IsomorphismGroups( G2, G1 );
if ( isoG = fail ) then
Error( "the two arguments do now have the same source" );
else
idQ := IdentityMapping( Range( left ) );
isoleft := IsomorphismByIsomorphisms( left, [ isoG, idQ ] );
left := Range( isoleft );
fi;
fi;
drd := DetermineRemainingCat1Groups( up, left );
if ( drd = fail ) then
Info( InfoXMod, 2, "failure determining remaining cat1-groups" );
return fail;
fi;
C2G := PreCat2GroupByPreCat1Groups( up,left,drd[1],drd[2],drd[3] );
if ( C2G = fail ) then
return fail; ## Error( "C2G fails to be a PreCat2Group" );
fi;
fi;
ok := IsPreCat2Group( C2G );
if ok then
ok := IsCat2Group( C2G );
return C2G;
else
return fail;
fi;
end );
InstallGlobalFunction( Cat2Group, function( arg )
local C2G, ok;
C2G := PreCat2Group( arg[1], arg[2] );
ok := not ( C2G = fail ) and IsCat2Group( C2G );
if ok then
return C2G;
else
return fail;
fi;
end );
#############################################################################
##
#M DetermineRemainingCat1Groups . . . . . . . . . . . for 2 pre-cat1-groups
##
InstallMethod( DetermineRemainingCat1Groups, "for up, left pre-cat1-groups",
true, [ IsPreCat1Group, IsPreCat1Group ], 0,
function( up, left )
local G, genG, Q, genQ, R, genR, tu, hu, eu, tl, hl, el, tea, hea,
P, genP, diag, imtd, td, imhd, hd, imed, ed, down,
imtr, tr, imhr, hr, imer, er, right;
G := Source( up );
if not ( G = Source( left ) ) then
Print( "the two pre-cat1-groups should have the same source\n" );
fi;
genG := GeneratorsOfGroup( G );
R := Range( up );
genR := GeneratorsOfGroup( R );
Q := Range( left );
genQ := GeneratorsOfGroup( Q );
tu := TailMap( up );
hu := HeadMap( up );
eu := RangeEmbedding( up );
tl := TailMap( left );
hl := HeadMap( left );
el := RangeEmbedding( left );
## check that the up-maps commute with the lt-maps
tea := tu*eu*tl*el;
hea := hu*eu*hl*el;
if not ( ( tea = tl*el*tu*eu )
and ( hea = hl*el*hu*eu )
and ( tu*eu*hl*el = hl*el*tu*eu )
and ( hu*eu*tl*el = tl*el*hu*eu ) ) then
Info( InfoXMod, 2, "up-maps do not commute with lt-maps" );
return fail;
fi;
Info( InfoXMod, 2, "yes : up-maps do commute with the lt-maps" );
## more checks?
## determine the group P
P := Image( tea );
if not ( Image( hea ) = P ) then
Error( "t*e*a and h*e*a do not have the same range" );
fi;
genP := GeneratorsOfGroup( P );
diag := PreCat1GroupWithIdentityEmbedding( tea, hea );
if ( diag = fail ) then
Print( "diag fails to be a cat1-group\n" );
return fail;
fi;
## now construct down
imtd := List( genQ, q -> ImageElm( el * tea, q ) );
td := GroupHomomorphismByImages( Q, P, genQ, imtd );
imhd := List( genQ, q -> ImageElm( el * hea, q ) );
hd := GroupHomomorphismByImages( Q, P, genQ, imhd );
imed := List( genP, p -> ImageElm( tl, p ) );
ed := GroupHomomorphismByImages( P, Q, genP, imed );
down := PreCat1GroupByTailHeadEmbedding( td, hd, ed );
## now construct right
imtr := List( genR, r -> ImageElm( eu * tea, r ) );
tr := GroupHomomorphismByImages( R, P, genR, imtr );
imhr := List( genR, r -> ImageElm( eu * hea, r ) );
hr := GroupHomomorphismByImages( R, P, genR, imhr );
imer := List( genP, p -> ImageElm( tu, p ) );
er := GroupHomomorphismByImages( P, R, genP, imer );
right := PreCat1GroupByTailHeadEmbedding( tr, hr, er );
if ( ( right = fail ) or ( down = fail) ) then
Info( InfoXMod, 2, "right or down fail to be cat1-groups" );
return fail;
fi;
return [ right, down, diag ];
end );
#############################################################################
##
#M PreCat2GroupByPreCat1Groups . . . . . . . . . . for five pre-cat1-groups
##
InstallMethod( PreCat2GroupByPreCat1Groups, "for five pre-cat1-groups",
true, [ IsPreCat1Group, IsPreCat1Group, IsPreCat1Group,
IsPreCat1Group, IsPreCat1Group ], 0,
function( up, left, right, down, diag )
local G, R, Q, P, genG, tu, hu, tl, hl, tr, hr, td, hd, ta, ha,
imtld, imtur, imhld, imhur, dtld, dtur, dhld, dhur, PC2, ok;
G := Source( up );
genG := GeneratorsOfGroup( G );
R := Range( up );
Q := Range( left );
P := Range( diag );
if not ( ( G = Source( left ) ) and ( G = Source( diag ) )
and ( R = Source( right ) ) and ( P = Range( right ) )
and ( Q = Source( down ) ) and ( P = Range( down ) ) ) then
Info( InfoXMod, 2, "sources and/or ranges do not agree" );
return fail;
fi;
tu := TailMap( up );
hu := HeadMap( up );
tl := TailMap( left );
hl := HeadMap( left );
tr := TailMap( right );
hr := HeadMap( right );
td := TailMap( down );
hd := HeadMap( down );
ta := TailMap( diag );
ha := HeadMap( diag );
imtld := List( genG, g -> ImageElm( td, ImageElm( tl, g ) ) );
dtld := GroupHomomorphismByImages( G, P, genG, imtld );
imtur := List( genG, g -> ImageElm( tr, ImageElm( tu, g ) ) );
dtur := GroupHomomorphismByImages( G, P, genG, imtur );
imhld := List( genG, g -> ImageElm( hd, ImageElm( hl, g ) ) );
dhld := GroupHomomorphismByImages( G, P, genG, imhld );
imhur := List( genG, g -> ImageElm( hr, ImageElm( hu, g ) ) );
dhur := GroupHomomorphismByImages( G, P, genG, imhur );
if not ( ( dtld = ta ) and ( dtur= ta )
and ( dhld = ha ) and ( dhur = ha ) ) then
Info( InfoXMod, 2, "tail and head maps are inconsistent" );
return fail;
fi;
PC2 := PreCat2GroupObj( [ up, left, right, down, diag ] );
SetIsPreCat2Group( PC2, true );
SetIsPreCatnGroup( PC2, true );
SetHigherDimension( PC2, 3 );
ok := IsCat2Group( PC2 );
ok := IsPreCatnGroupWithIdentityEmbeddings( PC2 );
return PC2;
end );
#############################################################################
##
#M Subdiagonal2DimensionalGroup . . . . . . . . . . . . for a pre-cat2-group
##
InstallMethod( Subdiagonal2DimensionalGroup, "for a pre-cat2-group",
true, [ IsPreCat2Group ], 0,
function( cat2 )
local up, ktup, lt, ktlt, L, genL, dg, edg, mgiedg, P, genPL, PL, sdg;
up := Up2DimensionalGroup( cat2 );
lt := Left2DimensionalGroup( cat2 );
L := Intersection( Kernel( TailMap( up ) ), Kernel( TailMap( lt ) ) );
genL := GeneratorsOfGroup( L );
dg := Diagonal2DimensionalGroup( cat2 );
edg := RangeEmbedding( dg );
mgiedg := MappingGeneratorsImages( edg );
P := Range( dg );
genPL := Concatenation( genL, GeneratorsOfGroup( Image( edg ) ) );
PL := Subgroup( Source( up ), genPL );
sdg := PreCat1GroupByTailHeadEmbedding(
RestrictedMapping( TailMap( dg ), PL ),
RestrictedMapping( HeadMap( dg ), PL ),
GroupHomomorphismByImages( P, PL, mgiedg[1], mgiedg[2] ) );
if not IsCat1Group( sdg ) then
Error( "expecting sdg to be a cat1-group" );
fi;
return sdg;
end );
#############################################################################
##
#M DirectProductOp . . . . . . . . . . . . . . . . . for two pre-cat2-groups
##
InstallOtherMethod( DirectProductOp,
"method for pre-cat2-groups", true, [ IsList, IsPreCat2Group ], 0,
function( list, A )
local C, i, B, upA, ltA, rtA, dnA, dgA, upB, ltB, rtB, dnB, dgB,
G, R, Q, P, eG1, eG2, eR1, eR2, eQ1, eQ2, eP1, eP2,
mtuA, mhuA, meuA, mtuB, mhuB, meuB, mtlA, mhlA, melA,
mtlB, mhlB, melB, mtrA, mhrA, merA, mtrB, mhrB, merB,
mtdA, mhdA, medA, mtdB, mhdB, medB, mtgA, mhgA, megA,
mtgB, mhgB, megB, mtuC, mhuC, meuC, tuC, huC, euC, upC,
mtlC, mhlC, melC, tlC, hlC, elC, ltC, mtrC, mhrC, merC,
trC, hrC, erC, rtC, mtdC, mhdC, medC, tdC, hdC, edC, dnC,
mtgC, mhgC, megC, tgC, hgC, egC, dgC,
eupA, eupB, eltA, eltB, embA, embB, pG1, pG2,
pR1, pR2, pQ1, pQ2, pupA, pupB, pltA, pltB, proA, proB, info;
if not ( list[1] = A ) then
Error( "second argument should be first entry in first argument list" );
fi;
if ( Length( list ) > 2 ) then
C := DirectProductOp( [ A, list[2] ], A );
for i in [3..Length(list)] do
C := DirectProductOp( [ C, list[i] ], C );
od;
return C;
fi;
B := list[2];
upA := Up2DimensionalGroup( A );
ltA := Left2DimensionalGroup( A );
rtA := Right2DimensionalGroup( A );
dnA := Down2DimensionalGroup( A );
dgA := Diagonal2DimensionalGroup( A );
upB := Up2DimensionalGroup( B );
ltB := Left2DimensionalGroup( B );
rtB := Right2DimensionalGroup( B );
dnB := Down2DimensionalGroup( B );
dgB := Diagonal2DimensionalGroup( B );
G := DirectProductOp( [ Source(upA), Source(upB) ], Source(upA) );
R := DirectProductOp( [ Range(upA), Range(upB) ], Range(upA) );
Q := DirectProductOp( [ Source(dnA), Source(dnB) ], Source(dnA) );
P := DirectProductOp( [ Range(dnA), Range(dnB) ], Range(dnA) );
eG1 := Embedding( G, 1 );
eG2 := Embedding( G, 2 );
eR1 := Embedding( R, 1 );
eR2 := Embedding( R, 2 );
eQ1 := Embedding( Q, 1 );
eQ2 := Embedding( Q, 2 );
eP1 := Embedding( P, 1 );
eP2 := Embedding( P, 2 );
## construct the up cat2-group for C
mtuA := MappingGeneratorsImages( TailMap( upA ) );
mtuA := [ List( mtuA[1], x -> ImageElm( eG1, x ) ),
List( mtuA[2], x -> ImageElm( eR1, x ) ) ];
mtuB := MappingGeneratorsImages( TailMap( upB ) );
mtuB := [ List( mtuB[1], x -> ImageElm( eG2, x ) ),
List( mtuB[2], x -> ImageElm( eR2, x ) ) ];
mtuC := [ Concatenation(mtuA[1],mtuB[1]), Concatenation(mtuA[2],mtuB[2]) ];
tuC := GroupHomomorphismByImages( G, R, mtuC[1], mtuC[2] );
mhuA := MappingGeneratorsImages( HeadMap( upA ) );
mhuA := [ List( mhuA[1], x -> ImageElm( eG1, x ) ),
List( mhuA[2], x -> ImageElm( eR1, x ) ) ];
mhuB := MappingGeneratorsImages( HeadMap( upB ) );
mhuB := [ List( mhuB[1], x -> ImageElm( eG2, x ) ),
List( mhuB[2], x -> ImageElm( eR2, x ) ) ];
mhuC := [ Concatenation(mhuA[1],mhuB[1]),
Concatenation(mhuA[2],mhuB[2]) ];
huC := GroupHomomorphismByImages( G, R, mhuC[1], mhuC[2] );
meuA := MappingGeneratorsImages( RangeEmbedding( upA ) );
meuA := [ List( meuA[1], x -> ImageElm( eR1, x ) ),
List( meuA[2], x -> ImageElm( eG1, x ) ) ];
meuB := MappingGeneratorsImages( RangeEmbedding( upB ) );
meuB := [ List( meuB[1], x -> ImageElm( eR2, x ) ),
List( meuB[2], x -> ImageElm( eG2, x ) ) ];
meuC := [ Concatenation(meuA[1],meuB[1]),
Concatenation(meuA[2],meuB[2]) ];
euC := GroupHomomorphismByImages( R, G, meuC[1], meuC[2] );
upC := PreCat1GroupByTailHeadEmbedding( tuC, huC, euC );
## construct the left cat2-group for C
mtlA := MappingGeneratorsImages( TailMap( ltA ) );
mtlA := [ List( mtlA[1], x -> ImageElm( eG1, x ) ),
List( mtlA[2], x -> ImageElm( eQ1, x ) ) ];
mtlB := MappingGeneratorsImages( TailMap( ltB ) );
mtlB := [ List( mtlB[1], x -> ImageElm( eG2, x ) ),
List( mtlB[2], x -> ImageElm( eQ2, x ) ) ];
mtlC := [ Concatenation(mtlA[1],mtlB[1]),
Concatenation(mtlA[2],mtlB[2]) ];
tlC := GroupHomomorphismByImages( G, Q, mtlC[1], mtlC[2] );
mhlA := MappingGeneratorsImages( HeadMap( ltA ) );
mhlA := [ List( mhlA[1], x -> ImageElm( eG1, x ) ),
List( mhlA[2], x -> ImageElm( eQ1, x ) ) ];
mhlB := MappingGeneratorsImages( HeadMap( ltB ) );
mhlB := [ List( mhlB[1], x -> ImageElm( eG2, x ) ),
List( mhlB[2], x -> ImageElm( eQ2, x ) ) ];
mhlC := [ Concatenation(mhlA[1],mhlB[1]),
Concatenation(mhlA[2],mhlB[2]) ];
hlC := GroupHomomorphismByImages( G, Q, mhlC[1], mhlC[2] );
melA := MappingGeneratorsImages( RangeEmbedding( ltA ) );
melA := [ List( melA[1], x -> ImageElm( eQ1, x ) ),
List( melA[2], x -> ImageElm( eG1, x ) ) ];
melB := MappingGeneratorsImages( RangeEmbedding( ltB ) );
melB := [ List( melB[1], x -> ImageElm( eQ2, x ) ),
List( melB[2], x -> ImageElm( eG2, x ) ) ];
melC := [ Concatenation(melA[1],melB[1]),
Concatenation(melA[2],melB[2]) ];
elC := GroupHomomorphismByImages( Q, G, melC[1], melC[2] );
ltC := PreCat1GroupByTailHeadEmbedding( tlC, hlC, elC );
## construct the right cat2-group for C
mtrA := MappingGeneratorsImages( TailMap( rtA ) );
mtrA := [ List( mtrA[1], x -> ImageElm( eR1, x ) ),
List( mtrA[2], x -> ImageElm( eP1, x ) ) ];
mtrB := MappingGeneratorsImages( TailMap( rtB ) );
mtrB := [ List( mtrB[1], x -> ImageElm( eR2, x ) ),
List( mtrB[2], x -> ImageElm( eP2, x ) ) ];
mtrC := [ Concatenation(mtrA[1],mtrB[1]),
Concatenation(mtrA[2],mtrB[2]) ];
trC := GroupHomomorphismByImages( R, P, mtrC[1], mtrC[2] );
mhrA := MappingGeneratorsImages( HeadMap( rtA ) );
mhrA := [ List( mhrA[1], x -> ImageElm( eR1, x ) ),
List( mhrA[2], x -> ImageElm( eP1, x ) ) ];
mhrB := MappingGeneratorsImages( HeadMap( rtB ) );
mhrB := [ List( mhrB[1], x -> ImageElm( eR2, x ) ),
List( mhrB[2], x -> ImageElm( eP2, x ) ) ];
mhrC := [ Concatenation(mhrA[1],mhrB[1]),
Concatenation(mhrA[2],mhrB[2]) ];
hrC := GroupHomomorphismByImages( R, P, mhrC[1], mhrC[2] );
merA := MappingGeneratorsImages( RangeEmbedding( rtA ) );
merA := [ List( merA[1], x -> ImageElm( eP1, x ) ),
List( merA[2], x -> ImageElm( eR1, x ) ) ];
merB := MappingGeneratorsImages( RangeEmbedding( rtB ) );
merB := [ List( merB[1], x -> ImageElm( eP2, x ) ),
List( merB[2], x -> ImageElm( eR2, x ) ) ];
merC := [ Concatenation(merA[1],merB[1]),
Concatenation(merA[2],merB[2]) ];
erC := GroupHomomorphismByImages( P, R, merC[1], merC[2] );
rtC := PreCat1GroupByTailHeadEmbedding( trC, hrC, erC );
## construct the down cat2-group for C
mtdA := MappingGeneratorsImages( TailMap( dnA ) );
mtdA := [ List( mtdA[1], x -> ImageElm( eQ1, x ) ),
List( mtdA[2], x -> ImageElm( eP1, x ) ) ];
mtdB := MappingGeneratorsImages( TailMap( dnB ) );
mtdB := [ List( mtdB[1], x -> ImageElm( eQ2, x ) ),
List( mtdB[2], x -> ImageElm( eP2, x ) ) ];
mtdC := [ Concatenation(mtdA[1],mtdB[1]),
Concatenation(mtdA[2],mtdB[2]) ];
tdC := GroupHomomorphismByImages( Q, P, mtdC[1], mtdC[2] );
mhdA := MappingGeneratorsImages( HeadMap( dnA ) );
mhdA := [ List( mhdA[1], x -> ImageElm( eQ1, x ) ),
List( mhdA[2], x -> ImageElm( eP1, x ) ) ];
mhdB := MappingGeneratorsImages( HeadMap( dnB ) );
mhdB := [ List( mhdB[1], x -> ImageElm( eQ2, x ) ),
List( mhdB[2], x -> ImageElm( eP2, x ) ) ];
mhdC := [ Concatenation(mhdA[1],mhdB[1]),
Concatenation(mhdA[2],mhdB[2]) ];
hdC := GroupHomomorphismByImages( Q, P, mhdC[1], mhdC[2] );
medA := MappingGeneratorsImages( RangeEmbedding( dnA ) );
medA := [ List( medA[1], x -> ImageElm( eP1, x ) ),
List( medA[2], x -> ImageElm( eQ1, x ) ) ];
medB := MappingGeneratorsImages( RangeEmbedding( dnB ) );
medB := [ List( medB[1], x -> ImageElm( eP2, x ) ),
List( medB[2], x -> ImageElm( eQ2, x ) ) ];
medC := [ Concatenation(medA[1],medB[1]),
Concatenation(medA[2],medB[2]) ];
edC := GroupHomomorphismByImages( P, Q, medC[1], medC[2] );
dnC := PreCat1GroupByTailHeadEmbedding( tdC, hdC, edC );
## construct the diagonal cat2-group for C
mtgA := MappingGeneratorsImages( TailMap( dgA ) );
mtgA := [ List( mtgA[1], x -> ImageElm( eG1, x ) ),
List( mtgA[2], x -> ImageElm( eP1, x ) ) ];
mtgB := MappingGeneratorsImages( TailMap( dgB ) );
mtgB := [ List( mtgB[1], x -> ImageElm( eG2, x ) ),
List( mtgB[2], x -> ImageElm( eP2, x ) ) ];
mtgC := [ Concatenation(mtgA[1],mtgB[1]),
Concatenation(mtgA[2],mtgB[2]) ];
tgC := GroupHomomorphismByImages( G, P, mtgC[1], mtgC[2] );
mhgA := MappingGeneratorsImages( HeadMap( dgA ) );
mhgA := [ List( mhgA[1], x -> ImageElm( eG1, x ) ),
List( mhgA[2], x -> ImageElm( eP1, x ) ) ];
mhgB := MappingGeneratorsImages( HeadMap( dgB ) );
mhgB := [ List( mhgB[1], x -> ImageElm( eG2, x ) ),
List( mhgB[2], x -> ImageElm( eP2, x ) ) ];
mhgC := [ Concatenation(mhgA[1],mhgB[1]),
Concatenation(mhgA[2],mhgB[2]) ];
hgC := GroupHomomorphismByImages( G, P, mhgC[1], mhgC[2] );
megA := MappingGeneratorsImages( RangeEmbedding( dgA ) );
megA := [ List( megA[1], x -> ImageElm( eP1, x ) ),
List( megA[2], x -> ImageElm( eG1, x ) ) ];
megB := MappingGeneratorsImages( RangeEmbedding( dgB ) );
megB := [ List( megB[1], x -> ImageElm( eP2, x ) ),
List( megB[2], x -> ImageElm( eG2, x ) ) ];
megC := [ Concatenation(megA[1],megB[1]),
Concatenation(megA[2],megB[2]) ];
egC := GroupHomomorphismByImages( P, G, megC[1], megC[2] );
dgC := PreCat1GroupByTailHeadEmbedding( tgC, hgC, egC );
C := PreCat2GroupByPreCat1Groups( upC, ltC, rtC, dnC, dgC );
## now for the embeddings and projections
eupA := PreCat1GroupMorphismByGroupHomomorphisms( upA, upC, eG1, eR1 );
eupB := PreCat1GroupMorphismByGroupHomomorphisms( upB, upC, eG2, eR2 );
eltA := PreCat1GroupMorphismByGroupHomomorphisms( ltA, ltC, eG1, eQ1 );
eltB := PreCat1GroupMorphismByGroupHomomorphisms( ltB, ltC, eG2, eQ2 );
embA := PreCat2GroupMorphismByPreCat1GroupMorphisms( A, C, eupA, eltA );
embB := PreCat2GroupMorphismByPreCat1GroupMorphisms( B, C, eupB, eltB );
pG1 := Projection( G, 1 );
pG2 := Projection( G, 2 );
pR1 := Projection( R, 1 );
pR2 := Projection( R, 2 );
pQ1 := Projection( Q, 1 );
pQ2 := Projection( Q, 2 );
pupA := PreCat1GroupMorphismByGroupHomomorphisms( upC, upA, pG1, pR1 );
pupB := PreCat1GroupMorphismByGroupHomomorphisms( upC, upB, pG2, pR2 );
pltA := PreCat1GroupMorphismByGroupHomomorphisms( ltC, ltA, pG1, pQ1 );
pltB := PreCat1GroupMorphismByGroupHomomorphisms( ltC, ltB, pG2, pQ2 );
proA := PreCat2GroupMorphismByPreCat1GroupMorphisms( C, A, pupA, pltA );
proB := PreCat2GroupMorphismByPreCat1GroupMorphisms( C, B, pupB, pltB );
info := rec( embeddings := [ embA, embB ],
objects := list,
projections := [ proA, proB ] );
SetDirectProductInfo( C, info );
return C;
end );
#############################################################################
##
#M AllCat2GroupsWithImagesIterator . . .at2-groups with given up,left range
#M DoAllCat2GroupsWithImagesIterator
#M AllCat2GroupsWithImages . . cat2-groups with specified range for up,left
#M AllCat2GroupsWithImagesNumber . # cat2-groups with specified up,left gps
#M AllCat2GroupsWithImagesUpToIsomorphism . . iso class reps of cat2-groups
##
BindGlobal( "NextIterator_AllCat2GroupsWithImages", function ( iter )
local ok, pair, C;
ok := false;
while ( not ok ) and ( not IsDoneIterator( iter ) ) do
pair := NextIterator( iter!.pairsIterator );
Info( InfoXMod, 1, pair );
if ( fail in pair ) then
return fail;
fi;
C := Cat2Group( pair[1], pair[2] );
if ( not ( C = fail ) and IsCat2Group( C ) ) then
return C;
fi;
od;
return fail;
end );
BindGlobal( "IsDoneIterator_AllCat2GroupsWithImages",
iter -> IsDoneIterator( iter!.pairsIterator )
);
BindGlobal( "ShallowCopy_AllCat2GroupsWithImages",
iter -> rec( group := iter!.group,
pairsIterator := ShallowCopy( iter!.pairsIterator )
)
);
InstallGlobalFunction( "DoAllCat2GroupsWithImagesIterator",
function( G, R, Q )
local upIterator, pairsIterator, ltIterator, iter;
--> --------------------
--> maximum size reached
--> --------------------
[ Verzeichnis aufwärts0.76unsichere Verbindung
Übersetzung europäischer Sprachen durch Browser
]
|