SSL gp2obj.gi
Sprache: unbekannt
|
|
Columbo aufrufen.gi Download desUnknown {[0] [0] [0]}Datei anzeigen #############################################################################
##
#W gp2obj.gi GAP4 package `XMod' Chris Wensley
#W & Murat Alp
#Y Copyright (C) 2001-2025, Chris Wensley et al,
##
## This file contains generic methods for (pre-)crossed modules and
## (pre-)cat1-groups.
##
##############################################################################
##
## Global constants which determine whether to read cat1data.g
## CAT1_LIST_CLASS_SIZES for groups of size <= CAT1_LIST_MAX_SIZE
##
CAT1_LIST_MAX_SIZE := 60; ## reduced from 70 (10/06/20)
CAT1_LIST_CLASS_SIZES :=
List( [1..CAT1_LIST_MAX_SIZE], NumberSmallGroups );
CAT1_LIST_NUMBERS :=
[ [ 1 ], [ 2 ], [ 2 ], [ 2, 4 ], [ 2 ], [ 2, 4 ], [ 2 ], [ 2, 6, 3, 1, 6 ],
[ 2, 4 ], [ 2, 4 ], [ 2 ], [ 2, 4, 2, 4, 8 ], [ 2 ], [ 2, 4 ], [ 4 ],
[ 2, 5, 4, 3, 6, 2, 2, 2, 1, 12, 9, 3, 2, 9 ], [ 2 ], [ 2, 4, 4, 4, 8 ],
[ 2 ], [ 2, 4, 2, 4, 8 ], [ 2, 4 ], [ 2, 4 ], [ 2 ],
[ 2, 4, 1, 2, 4, 4, 6, 4, 12, 6, 2, 2, 4, 8, 12 ], [ 2, 4 ], [ 2, 4 ],
[ 2, 6, 2, 2, 6 ], [ 2, 4, 4, 8 ], [ 2 ], [ 4, 4, 4, 8 ], [ 2 ],
[ 2, 3, 8, 3, 4, 3, 1, 1, 2, 1, 2, 3, 3, 3, 1, 6, 2, 2, 2, 1, 14, 13, 11,
6, 9, 3, 7, 6, 3, 2, 2, 1, 2, 5, 4, 12, 6, 2, 6, 6, 3, 2, 2, 1, 20, 18,
6, 8, 5, 1, 12 ], [ 4 ], [ 2, 4 ], [ 4 ],
[ 2, 4, 2, 4, 8, 4, 4, 8, 2, 4, 4, 8, 8, 16 ], [ 2 ], [ 2, 4 ], [ 2, 4 ],
[ 2, 4, 2, 2, 4, 4, 6, 4, 12, 6, 2, 4, 8, 12 ], [ 2 ], [ 2, 4, 4, 4, 4, 8 ],
[ 2 ], [ 2, 4, 4, 8 ], [ 4, 8 ], [ 2, 4 ], [ 2 ],
[ 2, 4, 2, 4, 4, 4, 4, 2, 6, 2, 6, 2, 6, 4, 2, 2, 2, 2, 6, 10, 8, 6, 12, 4,
4, 4, 2, 1, 1, 2, 4, 3, 1, 6, 12, 12, 4, 6, 2, 2, 2, 12, 12, 24, 18, 6,
4, 4, 8, 4, 12, 18 ], [ 2, 4 ], [ 2, 4, 4, 4, 8 ], [ 4 ],
[ 2, 4, 2, 4, 8 ], [ 2 ], [ 2, 4, 4, 4, 3, 2, 6, 2, 12, 4, 4, 8, 8, 6, 12 ],
[ 2, 4 ], [ 2, 4, 2, 4, 4, 6, 4, 12, 6, 2, 2, 8, 12 ], [ 2, 4 ], [ 2, 4 ],
[ 2 ], [ 4, 4, 4, 8, 1, 4, 4, 4, 4, 8, 8, 8, 16 ], [ 2 ], [ 2, 4 ],
[ 2, 4, 4, 8 ],
[ 2, 6, 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 6, 3, 1, 3, 3, 1, 2, 1,
2, 8, 3, 2, 4, 1, 2, 2, 2, 2, 2, 1, 1, 2, 1, 2, 1, 1, 1, 3, 1, 2, 3, 3,
1, 6, 2, 2, 2, 1, 8, 11, 4, 15, 12, 8, 12, 4, 4, 3, 8, 7, 13, 1, 2, 5,
9, 4, 5, 3, 3, 3, 1, 1, 1, 1, 1, 1, 26, 10, 8, 6, 14, 5, 2, 9, 2, 3, 3,
1, 8, 5, 2, 1, 2, 1, 6, 2, 11, 4, 1, 10, 11, 5, 3, 3, 1, 6, 1, 2, 9, 6,
6, 6, 6, 3, 3, 1, 3, 2, 1, 3, 3, 4, 3, 1, 4, 3, 1, 4, 1, 2, 1, 4, 2, 3,
3, 3, 3, 1, 1, 6, 6, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 1, 2, 1, 1, 1, 8, 8, 4, 2, 3, 1, 4, 1, 4, 3, 12, 6, 2, 6, 6,
3, 2, 2, 1, 31, 28, 24, 23, 33, 11, 9, 11, 1, 5, 20, 22, 11, 8, 11, 8,
4, 6, 2, 14, 12, 9, 5, 7, 7, 1, 4, 3, 1, 1, 1, 1, 3, 4, 9, 7, 3, 3, 5,
3, 4, 1, 1, 1, 1, 1, 1, 2, 1, 3, 3, 1, 1, 1, 20, 12, 8, 3, 12, 12, 6,
8, 6, 3, 2, 2, 2, 1, 28, 30, 10, 17, 14, 3, 3, 16 ], [ 4 ],
[ 4, 4, 4, 8 ], [ 2 ], [ 2, 4, 2, 4, 8 ], [ 4 ], [ 4, 4, 4, 8 ] ];
CAT1_LIST_LOADED := false;
CAT1_LIST := [ ];
#############################################################################
##
#M Size2d( <D> ) . . . . . . . . . . . . . size of a 2-dimensional domain
##
InstallMethod( Size2d, "generic method for a 2d-object", true,
[ Is2DimensionalDomain ], 0,
function ( obj )
return [ Size( Source( obj ) ), Size( Range( obj ) ) ];
end );
InstallOtherMethod( Size, "generic method for a 2d-object",
[ Is2DimensionalDomain ], 0,
function ( obj )
Error( "use operation Size2d for 2d-objects" );
return fail;
end );
#############################################################################
##
#M IsTrivial( <D> ) . . . . . . . . . . . . . . for a 2-dimensional domain
#M IsNonTrivial( <D> ) . . . . . . . . . . . . . for a 2-dimensional domain
#M IsFinite( <D> ) . . . . . . . . . . . . . . . for a 2-dimensional domain
#M IsAssociative( <XM> ) . . . . . . . . . . . . for a 2-dimensional domain
##
InstallMethod( IsTrivial, "generic method for a 2d-object", true,
[ Is2DimensionalDomain ], 0,
function ( obj )
return Size2d( obj ) = [ 1, 1 ];
end );
InstallMethod( IsNonTrivial, "generic method for a 2d-object", true,
[ Is2DimensionalDomain ], 0,
function ( obj )
return Size2d( obj ) <> [ 1, 1 ];
end );
InstallMethod( IsFinite, "generic method for a 2d-object", true,
[ Is2DimensionalDomain ], 0,
function ( obj )
return ( Size2d(obj)[1] < infinity ) and ( Size2d(obj)[2] < infinity );
end );
InstallOtherMethod( IsAssociative, "generic method for 2d-objects", true,
[ Is2DimensionalDomain ], 0,
function( XM )
return IsAssociative( Source(XM) ) and IsAssociative( Range(XM) );
end );
#############################################################################
##
#M IsPerm2DimensionalGroup . check whether source and range are perm groups
#M IsFp2DimensionalGroup . . . check whether source and range are fp groups
#M IsPc2DimensionalGroup . . . check whether source and range are pc groups
##
InstallMethod( IsPerm2DimensionalGroup,
"generic method for 2d-group objects", true, [ Is2DimensionalGroup ], 0,
function( obj )
return ( IsPermGroup( Source( obj ) ) and IsPermGroup( Range( obj ) ) );
end );
InstallMethod( IsFp2DimensionalGroup, "generic method for 2d-group objects",
true, [ Is2DimensionalGroup ], 0,
function( obj )
return ( IsFpGroup( Source( obj ) ) and IsFpGroup( Range( obj ) ) );
end );
InstallMethod( IsPc2DimensionalGroup, "generic method for 2d-group objects",
true, [ Is2DimensionalGroup ], 0,
function( obj )
return ( IsPcGroup( Source( obj ) ) and IsPcGroup( Range( obj ) ) );
end );
#############################################################################
##
#M IsPreXMod . . . . . . . . check that the first crossed module axiom holds
##
InstallMethod( IsPreXMod, "generic method for 2d-group",
true, [ Is2DimensionalGroup ], 0,
function( P )
local Xsrc, Xrng, bdy, a, aut, act, gensrc, ngsrc, genrng, ngrng,
ssrc, x1, y1, z1, x2, y2, z2, w2;
if not IsPreXModObj( P ) then
return false;
fi;
Xrng := Range( P );
genrng := GeneratorsOfGroup( Xrng );
ngrng := Length( genrng );
Xsrc := Source( P );
gensrc := GeneratorsOfGroup( Xsrc );
ngsrc := Length( gensrc );
ssrc := Size( Xsrc );
bdy := Boundary( P );
# Check P.boundary: P.source -> P.range
if not ( ( Source( bdy ) = Xsrc ) and ( Range( bdy ) = Xrng ) ) then
Info( InfoXMod, 2,
"Error: require X.boundary : X.source -> X.range" );
return false;
fi;
# checking IsHomomorphism(bdy) gives cokernel error when Xsrc = [ ]
if ( ssrc > 1 ) then
if not IsGroupHomomorphism( bdy ) then
Info( InfoXMod, 2,
"Error: the boundary map is NOT a homomorphism!" );
return false;
fi;
fi;
act := XModAction( P );
aut := Range( act );
# Check X.aut is a group of automorphisms X.source -> X.source
if not ( IsGroup( aut ) ) then
Info( InfoXMod, 2,
"Error: group of actions on X.source does not exist!" );
return false;
fi;
if ( aut = Group( IdentityMapping( Xsrc ) ) ) then
SetIsTrivialAction2DimensionalGroup( P, true );
else
a := GeneratorsOfGroup( aut )[1];
if not ( ( Source( a ) = Xsrc ) and ( Range( a ) = Xsrc )
and IsBijective( a ) ) then
Info( InfoXMod, 2,
"Require automorphism X.aut.1 on X.source" );
return false;
fi;
fi;
# Check X.action: X.range -> X.aut
if not ( ( Source( act ) = Xrng ) and ( Range( act ) = aut ) ) then
Info( InfoXMod, 2,
"Error: require X.action : X.range -> X.aut" );
return false;
fi;
if ( Size( aut ) = 1 ) then
Info( InfoXMod, 2,
"X.action trivial => not checking a homomorphism!" );
else
if not IsGroupHomomorphism( act ) then
Info( InfoXMod, 2, " X.action is not a homomorphism|" );
return false;
fi;
fi;
Info( InfoXMod, 3,
"Checking CM1) bdy(x2^x1) = (bdy(x2))^x1 " );
for x1 in genrng do
for x2 in gensrc do
# Print( "x1,x2 = ", x1, ", ", x2, "\n" );
y1 := ( x2 ^ ( x1^act ) ) ^ bdy;
z1 := ( x2 ^ bdy ) ^ x1;
if ( y1 <> z1 ) then
Info( InfoXMod, 3,
"CM1) fails at x1 = ", x1, ", x2 = ", x2, "\n",
" bdy(x2^x1) = ", y1, "\n", "(bdy(x2))^x1 = ", z1 );
return false;
fi;
od;
od;
return true;
end );
#############################################################################
##
#M \=( <P>, <Q> ) . . . . . . . test if two pre-crossed modules are equal
##
InstallMethod( \=, "generic method for two pre-crossed modules",
IsIdenticalObj, [ IsPreXMod, IsPreXMod ], 0,
function ( P, Q )
return ( ( Boundary(P) = Boundary(Q) )
and ( XModAction(P) = XModAction(Q) ) );
end );
#############################################################################
##
#M IsTrivialAction2DimensionalGroup . . . . check whether action is trivial
##
InstallMethod( IsTrivialAction2DimensionalGroup,
"generic method for pre-crossed modules", true, [ IsPreXMod ], 0,
function( PM )
local act, genrng, onesrc;
act := XModAction( PM );
genrng := GeneratorsOfGroup( Range( PM ) );
onesrc := IdentityMapping( Source( PM ) );
return ForAll( genrng, r -> ( ImageElm( act, r ) = onesrc ) );
end );
#############################################################################
##
#M IsCentralExtension2DimensionalGroup( <xmod> ) . . . . . check the axioms
##
InstallMethod( IsCentralExtension2DimensionalGroup, "for an xmod",
true, [ IsXMod ], 0,
function( X0 )
local S, R, bdy, act, genS, genR, preR, len, i, r, pr, actr, s;
S := Source( X0 );
R := Range( X0 );
bdy := Boundary( X0 );
if not IsSurjective( bdy ) then
return false;
fi;
if not IsSubgroup( Centre( S ), Kernel( bdy ) ) then
return false;
fi;
act := XModAction( X0 );
genS := GeneratorsOfGroup( S );
genR := GeneratorsOfGroup( R );
preR := List( genR, r -> PreImagesRepresentativeNC( bdy, r ) );
len := Length( genR );
for i in [1..len] do
r := genR[i];
pr := preR[i];
actr := ImageElm( act, r );
for s in genS do
if not ( ImageElm( actr, s ) = s^pr ) then
return false;
fi;
od;
od;
return true;
end );
#############################################################################
##
#M PreXModObj( <bdy>, <act> ) . . . . . . . . . . make a pre-crossed module
##
InstallMethod( PreXModObj, "for homomorphism and action", true,
[ IsGroupHomomorphism, IsGroupHomomorphism ], 0,
function( bdy, act )
local type, PM, ok, src, rng, aut, name;
src := Source( bdy );
rng := Range( bdy );
if not ( rng = Source( act ) ) then
Error( "require Range( bdy ) = Source( act )" );
fi;
aut := Range( act );
if not IsGroupOfAutomorphisms( aut ) then
Error( "Range( act ) must be a group of automorphisms" );
fi;
if ( IsPermGroup( src ) and IsPermGroup( rng ) ) then
type := PermPreXModObjType;
elif ( IsPcGroup( src ) and IsPcGroup( rng ) ) then
type := PcPreXModObjType;
else
type := PreXModObjType;
fi;
PM := rec();
ObjectifyWithAttributes( PM, type,
Source, src,
Range, rng,
Boundary, bdy,
XModAction, act,
IsPreXModDomain, true,
Is2DimensionalGroup, true );
if not IsPreXMod( PM ) then
Info( InfoXMod, 1, "Warning: not a pre-crossed module." );
else
ok := IsXMod( PM ); # for running properly the function AllXMods
fi;
# name := Name( PM );
## check the types
if ( IsPermGroup(src) and IsPermGroup(rng) ) then
SetIsPerm2DimensionalGroup( PM, true );
elif ( IsPcGroup(src) and IsPcGroup(rng) ) then
SetIsPc2DimensionalGroup( PM, true );
fi;
return PM;
end );
#############################################################################
##
#M ImageElmXModAction( <pxmod>, <s>, <r> ) pre-xmod module action of s on r
##
InstallMethod( ImageElmXModAction, "method for a precrossed module", true,
[ Is2DimensionalDomain, IsObject, IsObject ], 0,
function( PM, s, r )
local actr, im;
if ( HasIsPreXModWithObjects(PM) and IsPreXModWithObjects(PM) ) then
## this is the crossed module of groupoids case
actr := ImageElm( XModAction( PM ), r )![2];
return ImageElm( actr, s );
else
im := ImageElm( XModAction(PM), r );
return ImageElm( im, s );
fi;
end );
#############################################################################
##
#M ExternalSetXMod( <pxm> ) . . . . . . . source group as a range group set
##
InstallMethod( ExternalSetXMod, "method for a precrossed module", true,
[ IsPreXMod ], 0,
function( PM )
local rng, genR, act;
rng := Range( PM );
genR := GeneratorsOfGroup( rng );
act := XModAction( PM );
return ExternalSet( rng, Source(PM), genR,
List( genR, g -> ImageElm( act, g ) ) );
end );
#############################################################################
##
#M String, ViewString, PrintString, ViewObj, PrintObj
## . . . . . . . . . . . . . . . . . . . . . . for two-dimensional domains
##
InstallMethod( String, "for a 2d-domain", true, [ Is2DimensionalDomain ], 0,
function( g2d )
return( STRINGIFY( "[", String( Source(g2d) ), " -> ",
String( Range(g2d) ), "]" ) );
end );
InstallMethod( ViewString, "for a 2d-domain", true, [ Is2DimensionalDomain ],
0, String );
InstallMethod( PrintString, "for a 2d-domain", true, [ Is2DimensionalDomain ],
0, String );
InstallMethod( ViewObj, "for a 2d-domain", true, [ Is2DimensionalDomain ],
0,
function( g2d )
if HasName( g2d ) then
Print( Name( g2d ), "\n" );
elif ( HasIsPreXModDomain( g2d ) and IsPreXModDomain( g2d ) ) then
Print( "[", Source( g2d ), "->", Range( g2d ), "]" );
elif ( HasIsPreCat1Domain( g2d ) and IsPreCat1Domain( g2d ) ) then
Print( "[", Source( g2d ), " => ", Range( g2d ), "]" );
else
TryNextMethod();
fi;
end );
InstallMethod( PrintObj, "for a 2d-domain", true, [Is2DimensionalDomain], 0,
function( g2d )
if HasName( g2d ) then
Print( Name( g2d ), "\n" );
elif ( HasIsPreXModDomain( g2d ) and IsPreXModDomain( g2d ) ) then
Print( "[", Source( g2d ) );
if IsGroupoid( Source( g2d ) ) then
Print( "\n-> " );
else
Print( " -> " );
fi;
Print( Range( g2d ), "]" );
elif ( HasIsPreCat1Domain( g2d ) and IsPreCat1Domain( g2d ) ) then
Print( "[", Source( g2d ) );
if IsGroupoid( Source( g2d ) ) then
Print( "\n=> " );
else
Print( " => " );
fi;
Print( Range( g2d ), "]" );
else
TryNextMethod();
fi;
end );
#############################################################################
##
#F Display( <g2d> ) . . . . . . . . . . . . . . print details of a 2d-group
##
InstallMethod( Display, "method for prexmods and precat2groups", true,
[ Is2DimensionalGroup ], 20,
function( g2d )
local name, bdy, act, aut, len, i, ispar, src, rng,
gensrc, genrng, ker, genker, mor, triv, imact, a,
t, h, e, b, k, imt, imh, ime, imb, imk;
src := Source( g2d );
rng := Range( g2d );
if ( HasName(src) and HasName(rng) ) then
name := Name( g2d );
else
name := "[??->??]";
fi;
gensrc := GeneratorsOfGroup( src );
genrng := GeneratorsOfGroup( rng );
if ( HasIsPreXMod( g2d ) and IsPreXMod( g2d ) ) then
if ( HasIsXMod( g2d ) and IsXMod( g2d ) ) then
Print( "Crossed module " );
else
Print( "Pre-crossed module " );
fi;
elif ( HasIsPreCat1Group( g2d ) and IsPreCat1Group( g2d ) ) then
if ( HasIsCat1Group( g2d ) and IsCat1Group( g2d ) ) then
Print( "Cat1-group " );
else
Print( "Pre-cat1-group " );
fi;
else
Print( "WARNING: neither a PreXMod nor a PreCat1Group" );
fi;
if HasName( g2d ) then
Print( Name(g2d), " :- \n" );
else
Print( ":- \n" );
fi;
ispar := not HasParent( src );
if ( ispar and HasName( src ) ) then
Print( ": Source group ", src );
elif ( ispar and HasName( Parent( src ) ) ) then
Print( ": Source group has parent ( ", Parent( src), " ) and" );
else
Print( ": Source group" );
fi;
Print( " has generators:\n" );
Print( " ", gensrc, "\n" );
ispar := not HasParent( rng );
if ( ispar and HasName( rng ) ) then
Print( ": Range group ", rng );
elif ( ispar and HasName( Parent( rng ) ) ) then
Print( ": Range group has parent ( ", Parent( rng ), " ) and" );
else
Print( ": Range group" );
fi;
Print( " has generators:\n" );
Print( " ", genrng, "\n" );
if ( HasIsPreXMod( g2d ) and IsPreXMod( g2d ) ) then
Print( ": Boundary homomorphism maps source generators to:\n" );
bdy := Boundary( g2d );
Print( " ", List( gensrc, s -> ImageElm( bdy, s ) ), "\n" );
act := XModAction( g2d );
imact := List( genrng, r -> ImageElm( act, r ) );
aut := Range( act );
triv := ( aut = Group( InclusionMappingGroups( src, src ) ) );
len := Length( genrng );
if ( len = 0 ) then
triv := true;
else
for i in [1..len] do
a := imact[i];
od;
fi;
if not triv then
Print( ": Action homomorphism maps" );
Print( " range generators to automorphisms:\n" );
for i in [1..len] do
Print( " ", genrng[i], " --> { source gens --> " );
Print( List( gensrc, s -> ImageElm(imact[i],s) ), " }\n" );
od;
fi;
if triv then
Print( " The automorphism group is trivial\n" );
else
if ( len = 1 ) then
Print( " This automorphism generates" );
else
Print( " These ", len, " automorphisms generate" );
fi;
Print( " the group of automorphisms.\n" );
fi;
else ## g2d is at least a PreCat1Group
ker := Kernel( g2d );
genker := GeneratorsOfGroup( ker );
t := TailMap( g2d );
h := HeadMap( g2d );
e := RangeEmbedding( g2d );
b := Boundary( g2d );
k := KernelEmbedding( g2d );
imt := List( gensrc, x -> ImageElm( t, x ) );
imh := List( gensrc, x -> ImageElm( h, x ) );
ime := List( genrng, x -> ImageElm( e, x ) );
imb := List( genker, x -> ImageElm( b, x ) );
imk := List( genker, x -> ImageElm( k, x ) );
Print( ": tail homomorphism maps source generators to:\n" );
Print( " ", imt, "\n" );
Print( ": head homomorphism maps source generators to:\n" );
Print( " ", imh, "\n" );
Print( ": range embedding maps range generators to:\n" );
Print( " ", ime, "\n" );
if ( Size( ker ) = 1 ) then
Print( ": the kernel is trivial.\n" );
else
Print( ": kernel has generators:\n" );
Print( " ", genker, "\n" );
Print( ": boundary homomorphism maps generators of kernel to:\n" );
Print( " ", imb, "\n" );
Print( ": kernel embedding maps generators of kernel to:\n" );
Print( " ", imk, "\n" );
fi;
fi;
if ( HasIsXMod( g2d ) and IsXMod( g2d )
and HasCat1GroupOfXMod( g2d ) ) then
Print( ": associated cat1-group is ",
Cat1GroupOfXMod( g2d ), "\n" );
elif ( HasIsCat1Group( g2d ) and IsCat1Group( g2d )
and HasXModOfCat1Group( g2d ) ) then
Print( ": associated crossed module is ",
XModOfCat1Group( g2d ), "\n" );
fi;
end );
#############################################################################
##
#M IdGroup . . . . . . . . . . . . . . . . . . . for a 2Dimensional-domain
#M StructureDescription . . . . . . . . . . . . for a 2Dimensional-domain
##
InstallOtherMethod( IdGroup, "method for a 2d-domain", true,
[ Is2DimensionalDomain ], 0,
function( dom )
return [ IdGroup( Source(dom) ), IdGroup( Range(dom) ) ];
end );
InstallOtherMethod( StructureDescription, "method for a 2d-domain", true,
[ Is2DimensionalDomain ], 0,
function( dom )
return [ StructureDescription( Source(dom) ),
StructureDescription( Range(dom) ) ];
end );
#############################################################################
##
#M Name . . . . . . . . . . . . . . . . . . . . for a 2Dimensional-domain
##
InstallMethod( Name, "method for a 2d-domain", true,
[ Is2DimensionalDomain ], 0,
function( dom )
local nsrc, nrng, name, arrow;
if HasName( Source( dom ) ) then
nsrc := Name( Source( dom ) );
else
nsrc := "..";
fi;
if HasName( Range( dom ) ) then
nrng := Name( Range( dom ) );
else
nrng := "..";
fi;
if ( HasIsPreXModDomain( dom ) and IsPreXModDomain( dom ) ) then
arrow := "->";
elif ( HasIsPreCat1Domain( dom ) and IsPreCat1Domain( dom ) ) then
arrow := " => ";
else
arrow := "->-";
fi;
name := Concatenation( "[", nsrc, arrow, nrng, "]" );
SetName( dom, name );
return name;
end );
#############################################################################
##
#M PreXModByBoundaryAndAction
##
InstallMethod( PreXModByBoundaryAndAction,
"pre-crossed module from boundary and action maps",
true, [ IsGroupHomomorphism, IsGroupHomomorphism ], 0,
function( bdy, act )
local rng, src, genrng, gensrc, aut, genaut, imact, i, a0, ima, a, PX;
src := Source( bdy );
gensrc := GeneratorsOfGroup( src );
rng := Range( bdy );
genrng := GeneratorsOfGroup( rng );
if not ( Source( act ) = rng ) then
Info( InfoXMod, 2,
"The range group is not the source of the action." );
return fail;
fi;
aut := Range( act );
genaut := GeneratorsOfGroup( aut );
if not IsGroupOfAutomorphisms( aut ) then
Info( InfoXMod, 2, "<aut> is not a group of automorphisms" );
return fail;
fi;
for a in genaut do
if not ( ( Source( a ) = src ) and ( Range( a ) = src ) ) then
Info( InfoXMod, 2, "error in source and range of automorphism" );
return fail;
fi;
od;
if not ( One( aut ) = IdentityMapping( src ) ) then
Info( InfoXMod, 2,
"aut.identity <> IdentityMapping( src )" );
return fail;
fi;
imact := List( genrng, r -> ImageElm( act, r ) );
for i in [ 1..Length( imact ) ] do
a0 := imact[i];
ima := List( gensrc, s -> ImageElm( a0, s ) );
a := GroupHomomorphismByImages( src, src, gensrc, ima );
imact[i] := a;
od;
PX := PreXModObj( bdy, act );
if not IsPreXMod( PX ) then
Info( InfoXMod, 1, "PX fails to be a pre-crossed module" );
return fail;
fi;
return PX;
end );
#############################################################################
##
#M PreXModWithTrivialRange
##
InstallMethod( PreXModWithTrivialRange, "pre-crossed module from two groups",
true, [ IsGroup, IsGroup ], 0,
function( G, H )
local genG, bdy, act, aut, triv, id, one;
one := One( H );
triv := Subgroup( H, [ one ] );
genG := GeneratorsOfGroup( G );
id := IdentityMapping( G );
aut := Group( [ id ] );
act := GroupHomomorphismByImages( triv, aut, [ one ], [ id ] );
bdy := GroupHomomorphismByImages( G, triv, genG, List( genG, g -> one ) );
if IsAbelian( G ) then
return XModByBoundaryAndAction( bdy, act );
else
return PreXModByBoundaryAndAction( bdy, act );
fi;
end );
#############################################################################
##
#M IsPreCat1Group check that the first pre-cat1-group axiom holds
##
InstallMethod( IsPreCat1Group, "generic method for 2dim-group", true,
[ Is2DimensionalGroup ], 0,
function( C1G )
local Csrc, Crng, x, e, t, h, idrng, he, te, kert, kerh, kerth;
if not IsPreCat1Obj( C1G ) then
return false;
fi;
Crng := Range( C1G );
h := HeadMap( C1G );
t := TailMap( C1G );
e := RangeEmbedding( C1G );
# checking the first condition of cat-1 group
idrng := IdentityMapping( Crng );
he := CompositionMapping( h, e );
te := CompositionMapping( t, e );
if not ( te = idrng ) then
Print( "te <> range identity \n" );
return false;
fi;
if not ( he = idrng ) then
Print( "he <> range identity \n" );
return false;
fi;
return true;
end );
#############################################################################
##
#M \=( <C1>, <C2> ) . . . . . . . . . test if two pre-cat1-groups are equal
##
InstallMethod( \=, "generic method for pre-cat1-groups",
IsIdenticalObj, [ IsPreCat1Group, IsPreCat1Group ], 0,
function( C1, C2 )
return ( ( TailMap(C1) = TailMap(C2) ) and ( HeadMap(C1) = HeadMap(C2) )
and ( RangeEmbedding(C1) = RangeEmbedding(C2) ) );
end );
#############################################################################
##
#M PreCat1Obj . . . . . . . . . . . . . . . . . . . . make a pre-cat1-group
##
InstallMethod( PreCat1Obj, "for tail, head, embedding", true,
[ IsGroupHomomorphism, IsGroupHomomorphism, IsGroupHomomorphism ], 0,
function( t, h, e )
local src, rng, type, C1G, ok, name;
src := Source( t );
rng := Range( t );
if not ( ( src = Source( h ) ) and ( rng = Range( h ) ) ) then
Error( "tail & head must have same source and range" );
fi;
if not ( ( Source( e ) = rng ) and ( Range( e ) = src ) ) then
Error( "tail, embedding must have opposite source and range" );
fi;
if ( IsPermGroup( src ) and IsPermGroup( rng ) ) then
type := PermPreCat1ObjType;
elif ( IsPcGroup( src ) and IsPcGroup( rng ) ) then
type := PcPreCat1ObjType;
else
type := PreCat1ObjType;
fi;
C1G := rec();
ObjectifyWithAttributes( C1G, type,
Source, src,
Range, rng,
TailMap, t,
HeadMap, h,
RangeEmbedding, e,
IsPreCat1Domain, true,
Is2DimensionalGroup, true );
ok := IsPreCat1Group( C1G );
if not ok then
return fail;
fi;
ok := IsPreCat1GroupWithIdentityEmbedding( C1G );
ok := IsCat1Group( C1G );
## check the types
if ( IsPermGroup( src ) and IsPermGroup( rng ) ) then
SetIsPerm2DimensionalGroup( C1G, true );
elif ( IsPcGroup( src ) and IsPcGroup( rng ) ) then
SetIsPc2DimensionalGroup( C1G, true );
fi;
if ( HasName( src ) and HasName( rng ) ) then
name := Name( C1G );
fi;
return C1G;
end );
#############################################################################
##
#M Elements( <P> ) . . . . . . . . . . . elements for a pre-crossed module
##
## replaced by Enumerator ???
#############################################################################
##
#M TransposeCat1Group for a pre-cat1-group
##
InstallMethod( TransposeCat1Group, "method for a cat1-group", true,
[ IsPreCat1Group ], 0,
function( C1G )
local rev;
rev := PreCat1Group( HeadMap(C1G), TailMap(C1G), RangeEmbedding(C1G ) );
SetTransposeCat1Group( rev, C1G );
return rev;
end );
#############################################################################
##
#F PreCat1Group( <t>, <h>, <e> ) pre-cat1-group from given tail, head, embed
#F PreCat1Group( <t>, <h> ) pre-cat1-group from tail, head endomorphisms
##
InstallGlobalFunction( PreCat1Group, function( arg )
local nargs, usage, C1G;
nargs := Length( arg );
usage := "standard usage: PreCat1Group( tail, head [,embed] );";
if not ForAll( arg, a -> IsGroupHomomorphism(a) ) then
Error( usage );
fi;
# one endomorphism
if ( ( nargs=1 ) and IsEndoMapping( arg[1] ) ) then
return PreCat1GroupWithIdentityEmbedding( arg[1], arg[1] );
# two endomorphisms
elif ( nargs=2 ) then
if ( IsSubEndoMapping( arg[1] ) and IsSubEndoMapping( arg[2] ) ) then
return PreCat1GroupWithIdentityEmbedding( arg[1], arg[2] );
elif ( Image( arg[1] ) = Source( arg[2] ) ) then
return PreCat1GroupByTailHeadEmbedding( arg[1], arg[1], arg[2] );
fi;
# two homomorphisms and an embedding
elif ( nargs=3 ) then
return PreCat1GroupByTailHeadEmbedding( arg[1], arg[2], arg[3] );
fi;
# other alternatives not allowed
Error( usage );
end );
##############################################################################
##
#M PreCat1GroupRecordOfPreXMod . convert pre-crossed module to pre-cat1-group
##
InstallMethod( PreCat1GroupRecordOfPreXMod,
"convert a pre-crossed module to a pre-cat1-group", true,
[ IsPreXMod ], 0,
function( X0 )
local S0, genS0, R0, genR0, iso, Xact, Xbdy, one, imbdy, info, G, genG,
t, h, f, eR, eS, imeR, imeS, projS, imt, imh, ime, imf, C,
mgiR, mgiS, pcrec;
S0 := Source( X0 );
genS0 := GeneratorsOfGroup( S0 );
R0 := Range( X0 );
genR0 := GeneratorsOfGroup( R0 );
genS0 := GeneratorsOfGroup( S0 );
genR0 := GeneratorsOfGroup( R0 );
one := One( R0 );
Xact := XModAction( X0 );
Xbdy := Boundary( X0 );
if IsTrivialAction2DimensionalGroup( X0 ) then
Info( InfoXMod, 2, "Using direct product: ", R0, " x ", S0 );
G := DirectProduct( R0, S0 );
genG := GeneratorsOfGroup( G );
info := DirectProductInfo( G );
if ( HasName( S0 ) and HasName( R0 ) ) then
SetName( G, Concatenation( "(", Name(R0), " x ", Name(S0), ")" ) );
fi;
t := Projection( G, 1 );
projS := Projection( G, 2 );
f := projS * Xbdy;
imh := List( genG, g -> ImageElm(t,g) * ImageElm(f,g) );
h := GroupHomomorphismByImages( G, R0, genG, imh );
eR := Embedding( G, 1 );
eS := Embedding( G, 2 );
else
Info( InfoXMod, 2, "Using semidirect product: ", R0, " |X ", S0 );
G := SemidirectProduct( R0, Xact, S0 );
info := SemidirectProductInfo( G );
if ( HasName( S0 ) and HasName( R0 ) ) then
SetName( G,
Concatenation( "(", Name(R0), " |X ", Name(S0), ")" ) );
else
SetName( G, "(..|X..)" );
fi;
genG := GeneratorsOfGroup( G );
eR := Embedding( G, 1 );
imeR := List( genR0, r -> ImageElm( eR, r ) );
eS := Embedding( G, 2 );
imeS := List( genS0, s -> ImageElm( eS, s ) );
t := Projection( G );
imt := List( genG, g -> ImageElm( t, g ) );
t := GroupHomomorphismByImages( G, R0, genG, imt );
projS := List( imt, r -> ImageElm( eR, r^-1 ) );
projS := List( [ 1..Length( genG ) ], i -> projS[i] * genG[i] );
projS := List( projS, x -> PreImagesRepresentativeNC( eS, x ) );
imh := List( [ 1..Length( genG ) ],
i -> imt[i] * ImageElm( Xbdy, projS[i] ) );
h := GroupHomomorphismByImages( G, R0, genG, imh );
fi;
C := PreCat1GroupByTailHeadEmbedding( t, h, eR );
if HasName( X0 ) then
SetName( C, Concatenation( "cat1(", Name( X0 ), ")" ) );
fi;
## trying this out 13/06/20
mgiR := MappingGeneratorsImages( eR );
eR := GroupHomomorphismByImages(
Source(eR), Range(eR), mgiR[1], mgiR[2] );
mgiS := MappingGeneratorsImages( eS );
eS := GroupHomomorphismByImages(
Source(eS), Range(eS), mgiS[1], mgiS[2] );
pcrec := rec( precat1 := C,
xmodRangeEmbedding := Image( eR ),
xmodRangeEmbeddingIsomorphism := eR,
xmodSourceEmbedding := Image( eS ),
xmodSourceEmbeddingIsomorphism := eS );
if HasIsXMod( X0 ) and IsXMod( X0 ) then
pcrec.iscat1 := true;
fi;
return pcrec;
end );
#############################################################################
##
#M IsXMod . . . . . . . . check that the second crossed module axiom holds
##
InstallMethod( IsXMod, "generic method for pre-crossed modules",
true, [ IsPreXMod ], 0,
function( XM )
local gensrc, genrng, x2, y2, w2, z2, hom, act;
hom := Boundary( XM );
act := XModAction( XM );
gensrc := GeneratorsOfGroup( Source( XM ) );
genrng := GeneratorsOfGroup( Range( XM ) );
for x2 in gensrc do
for y2 in gensrc do
# Print( "x2,y2 = ", x2, ", ", y2, "\n" );
z2 := x2 ^ ((y2 ^ hom) ^ act);
w2 := x2 ^ y2;
if ( z2 <> w2 ) then
Info( InfoXMod, 2,
"CM2) fails at x2 = ", x2, ", y2 = ", y2, "\n",
"x2^(hom(y2)) = ", z2, "\n",
" x2^y2 = ", w2, "\n" );
return false;
fi;
od;
od;
return true;
end );
InstallOtherMethod( IsXMod, "generic method for pre-cat1-groups", true,
[ IsPreCat1Group ], 0,
function( C0 )
Info( InfoXMod, 1,
"this is a pre-cat1-group, not a pre-crossed module" );
return false;
end );
#############################################################################
##
#M XModByBoundaryAndAction
##
InstallMethod( XModByBoundaryAndAction,
"crossed module from boundary and action maps", true,
[ IsGroupHomomorphism, IsGroupHomomorphism ], 0,
function( bdy, act )
local PM;
PM := PreXModByBoundaryAndAction( bdy, act );
if ( PM = fail ) then
return fail;
fi;
if not IsXMod( PM ) then
Info( InfoXMod, 1, "these maps only define a pre-crossed module" );
return fail;
fi;
return PM;
end );
#############################################################################
##
#M XModByTrivialAction
##
InstallMethod( XModByTrivialAction, "crossed module with trivial action",
true, [ IsGroupHomomorphism ], 0,
function( f )
local R, ZR, S, XM, aut, act, name;
S := Source( f );
if not IsAbelian( S ) then
Error( "the source of f must be abelian" );
fi;
R := Range( f );
ZR := Centre( R );
if not IsSubgroup( ZR, Image( f, S ) ) then
Error( "image of source must lie in the centre of range" );
fi;
aut := Group( IdentityMapping( S ) );
act := MappingToOne( R, aut );
XM := XModByBoundaryAndAction( f, act );
SetIsTrivialAction2DimensionalGroup( XM, true );
return XM;
end );
#############################################################################
##
#F XModByNormalSubgroup create a crossed module from normal N in G
##
InstallMethod( XModByNormalSubgroup, "conjugation crossed module",
true, [ IsGroup, IsGroup ], 0,
function( G, N )
local XM, bdy, act, aut, genrng, gensrc, name, a, triv, idsrc,
autgen, imautgen, phi, j, g, n, genN, f2pN, imgenN;
if not IsNormal( G, N ) then
return fail;
fi;
genrng := GeneratorsOfGroup( G );
gensrc := GeneratorsOfGroup( N );
bdy := GroupHomomorphismByImages( N, G, gensrc, gensrc );
autgen := [ ];
for g in genrng do
imautgen := List( gensrc, n -> n^g );
a := GroupHomomorphismByImages( N, N, gensrc, imautgen );
Add( autgen, a );
od;
if ( Length( genrng ) = 0 ) then
idsrc := IdentityMapping( N );
aut := Group( idsrc );
Info( InfoXMod, 2,
"Group of conjugations has size ", Size( aut ) );
else
aut := Group( autgen );
fi;
SetIsGroupOfAutomorphisms( aut, true );
act := GroupHomomorphismByImages( G, aut, genrng, autgen );
XM := PreXModObj( bdy, act );
SetIsNormalSubgroup2DimensionalGroup( XM, true );
if ( Length( autgen ) = 0 ) then
SetIsTrivialAction2DimensionalGroup( XM, true );
fi;
return XM;
end );
#############################################################################
##
#F XModByCentralExtension xmod from surjection with central kernel
##
InstallMethod( XModByCentralExtension, "central extension crossed module",
true, [ IsGroupHomomorphism ], 0,
function( hom )
local rng, src, Zsrc, ker, gensrc, ngsrc, imhom, genrng, autgen,
j, imsrc, aut, act, XM, ok, idsrc;
if not IsSurjective( hom ) then
Error( "homomorphism must be surjective" );
fi;
src := Source( hom );
rng := Range( hom );
Zsrc := Centre( src );
ker := Kernel( hom );
if not IsSubgroup( Zsrc, ker ) then
Error( "Kernel of surjection is not central" );
fi;
gensrc := GeneratorsOfGroup( src );
ngsrc := Length( gensrc );
imhom := List( gensrc, s -> ImageElm( hom, s ) );
genrng := GeneratorsOfGroup( rng );
autgen := ListWithIdenticalEntries( ngsrc, 0 );
for j in [1..ngsrc] do
imsrc := List( gensrc, s -> s^gensrc[j] );
autgen[j] := GroupHomomorphismByImages( src, src, gensrc, imsrc );
od;
aut := Group( autgen );
SetIsGroupOfAutomorphisms( aut, true );
Info( InfoXMod, 2, "Group of conjugations has size ", Size(aut) );
act := GroupHomomorphismByImages( rng, aut, imhom, autgen );
if ( not IsGroupHomomorphism( act ) ) then
Error( "action is not a homomorphism" );
fi;
XM := PreXModObj( hom, act );
SetIsCentralExtension2DimensionalGroup( XM, true );
idsrc := IdentityMapping( src );
if ForAll( autgen, a -> ( a = idsrc ) ) then
SetIsTrivialAction2DimensionalGroup( XM, true );
fi;
ok := IsXMod( XM );
return XM;
end );
#############################################################################
##
#M XModByAbelianModule( <abmod> ) crossed module [zero : abmod -> grp]
##
InstallMethod( XModByAbelianModule, "abelian module crossed module", true,
[ IsAbelianModule ], 0,
function( abmod )
local aut, act, z;
act := AbelianModuleAction( abmod );
z := MappingToOne( AbelianModuleGroup( abmod ), Source( act ) );
return XModByBoundaryAndAction( z, act );
end );
#############################################################################
##
#M XModByGroupOfAutomorphisms crossed module [G -> A]
##
InstallMethod( XModByGroupOfAutomorphisms, "automorphism crossed module",
true, [ IsGroup, IsGroup ], 0,
function( G, A )
local genA, autG, innG, abelian, genG, oneA, imbdy, g, ima, a, bdy, act,
iso1, A1, bdy1, act1, iso2, iso12, bdy2, act2, XM;
if not IsGroupOfAutomorphisms( A ) then
Error( "A is not a group of automorphisms" );
fi;
genA := GeneratorsOfGroup( A );
autG := AutomorphismGroup( G );
if not IsSubgroup( autG, A ) then
Error( "A is not a group of automorphisms of G" );
fi;
innG := InnerAutomorphismsAutomorphismGroup( autG );
if not IsSubgroup( A, innG ) then
Error( "the inner automorphism group of G is not a subgroup of A" );
fi;
abelian := IsAbelian( G );
genG := GeneratorsOfGroup( G );
oneA := One( A );
if abelian then
imbdy := List( genG, g -> oneA );
else
imbdy := [ ];
for g in genG do
ima := List( genG, h -> h^g );
a := GroupHomomorphismByImages( G, G, genG, ima );
Add( imbdy, a );
od;
fi;
bdy := GroupHomomorphismByImages( G, A, genG, imbdy );
XM := PreXModObj( bdy, IdentityMapping( A ) );
SetIsAutomorphismGroup2DimensionalGroup( XM, true );
if not IsXMod( XM ) then
Error( "this boundary and action only defines a pre-crossed module" );
fi;
return XM;
end );
#############################################################################
##
#M XModByAutomorphismGroup( <G> ) crossed module [G -> Aut(G)]
#M XModByInnerAutomorphismGroup( <G> ) crossed module [G -> Inn(G)]
##
InstallMethod( XModByAutomorphismGroup, "automorphism xmod of a group",
true, [ IsGroup ], 0,
function( G )
local autG, innG, a;
autG := AutomorphismGroup( G );
if ( not HasName( autG ) and HasName( G ) ) then
SetName( autG, Concatenation( "Aut(", Name( G ), ")" ) );
fi;
SetIsGroupOfAutomorphisms( autG, true );
return XModByGroupOfAutomorphisms( G, autG );
end );
InstallMethod( XModByInnerAutomorphismGroup, "inner automorphism xmod",
true, [ IsGroup ], 0,
function( G )
local A, innG, a;
A := InnerAutomorphismsByNormalSubgroup( G, G );
if ( not HasName( A ) and HasName( G ) ) then
SetName( A, Concatenation( "Inn(", Name( G ), ")" ) );
fi;
SetIsGroupOfAutomorphisms( A, true );
return XModByGroupOfAutomorphisms( G, A );
end );
#############################################################################
##
#M XModOfCat1Group
##
InstallMethod( XModOfCat1Group, "generic method for cat1-groups",
true, [ IsCat1Group ], 0,
function( C1 )
local X1;
X1 := PreXModRecordOfPreCat1Group( C1 ).prexmod;
SetIsXMod( X1, true );
SetXModOfCat1Group( C1, X1 );
SetCat1GroupOfXMod( X1, C1 );
return X1;
end );
#############################################################################
##
#M Cat1GroupOfXMod
##
InstallMethod( Cat1GroupOfXMod, "generic method for crossed modules",
true, [ IsXMod ], 0,
function( X1 )
local PC1, C1;
PC1 := PreCat1GroupRecordOfPreXMod( X1 );
C1 := PC1.precat1;
SetXModOfCat1Group( C1, X1 );
return C1;
end );
#############################################################################
##
#M PeifferSubgroupPreXMod . . . . normally generated by Peiffer commutators
##
InstallMethod( PeifferSubgroupPreXMod,
"generic method for pre-crossed xmods", true, [ IsPreXMod ], 0,
function( PM )
local Pf, s1, s2, a1, src, gensrc, comm, bdy, act, ok, XPf;
# this code mimics that of DerivedSubgroup
src := Source( PM );
bdy := Boundary( PM );
act := XModAction( PM );
gensrc := GeneratorsOfGroup( src );
Pf := TrivialSubgroup( src );
for s1 in gensrc do
a1 := ImageElm( act, ImageElm( bdy, s1 ) );
for s2 in gensrc do
comm := (s2^-1)^s1 * ImageElm( a1, s2 );
if not ( comm in Pf ) then
Pf := ClosureSubgroup( Pf, comm );
fi;
od;
od;
Pf := NormalClosure( src, Pf );
if ( Pf = src ) then
Pf := src;
fi;
XPf := Sub2DimensionalGroup( PM, Pf, TrivialSubgroup( Range(PM) ) );
ok := IsNormal( PM, XPf );
SetPeifferSub2DimensionalGroup( PM, XPf );
return Pf;
end );
#############################################################################
##
#M PeifferSubgroupPreCat1Group . . . commutator of kernels of tail and head
##
InstallMethod( PeifferSubgroupPreCat1Group,
"generic method for pre-cat1-groups", true, [ IsPreCat1Group ], 0,
function( PCG )
local src, kerh, kert, Pf;
src := Source( PCG );
kert := Kernel( TailMap( PCG ) );
kerh := Kernel( HeadMap( PCG ) );
Pf := CommutatorSubgroup( kert, kerh );
if ( Pf = src ) then
Pf := src;
fi;
return Pf;
end );
#############################################################################
##
#M PeifferSubgroup . . . . . . . .
##
InstallMethod( PeifferSubgroup, "generic method for 2d-groups",
true, [ Is2DimensionalGroup ], 0,
function( obj )
local P, ok, NP;
if IsPreXModObj( obj ) then
if IsXMod( obj ) then
return Subgroup( Source( obj ), [ One( Source( obj ) ) ] );
else
P := PeifferSubgroupPreXMod( obj );
NP := SubPreXMod( obj, P, TrivialSubgroup( Range(obj) ) );
ok := IsNormal( obj, NP );
return P;
fi;
elif IsPreCat1Obj( obj ) then
if IsCat1Group( obj ) then
return Subgroup( Source( obj ), [ One( Source( obj ) ) ] );
else
P := PeifferSubgroupPreCat1Group( obj );
NP := SubPreCat1Group( obj, P, TrivialSubgroup( Range(obj) ) );
ok := IsNormal( obj, NP );
return P;
fi;
else
return fail;
fi;
end );
##############################################################################
##
#A XModByPeifferQuotient . . . . . xmod from prexmod and Peiffer subgroup
##
InstallMethod( XModByPeifferQuotient,
"crossed module from a pre-crossed module and Peiffer subgroup", true,
[ IsPreXMod ], 0,
function( PM )
local pfsub, pfxmod, name, nat, ok, FM;
if IsXMod( PM ) then
Info( InfoXMod, 1, "this object is already a crossed module!" );
return PM;
fi;
pfsub := PeifferSubgroup( PM );
if not IsNormal( Source( PM ), pfsub ) then
Error( "Peiffer subgroup not normal in source group" );
fi;
pfxmod := SubPreXMod( PM, pfsub, TrivialSubgroup( Range(PM) ) );
ok := IsNormal( PM, pfxmod );
if not ok then
Error( "Peiffer precrossed module not normal!" );
fi;
FM := FactorPreXMod( PM, pfxmod );
nat := ProjectionOfFactorPreXMod( FM );
if HasName( PM ) then
name := Name( PM );
SetName( FM, Concatenation( "Peiffer(", name, ")" ) );
fi;
return FM;
end );
#############################################################################
##
#O XModByPullback . . . . . . . xmod from an xmod and a group homomorphism
##
InstallMethod( XModByPullback,
"crossed module from a crossed module and a group homomorphism", true,
[ IsXMod, IsGroupHomomorphism ], 0,
function( X0, nu )
local M, P, act0, N, L, genL, lenL, info, dp, emb1, emb2, lambda,
kappa, genLN, genLM, autL, genN, lenN, imact1, i, n, an,
actLN, actLM, prod, act1, X1, mor;
M := Source( X0 );
P := Range( X0 );
if not ( Range( nu ) = P ) then
Error( "Range(hom) <> Range(X0)" );
fi;
act0 := XModAction( X0 );
N := Source( nu );
L := Pullback( Boundary( X0 ), nu );
genL := GeneratorsOfGroup( L );
lenL := Length( genL );
info := PullbackInfo( L );
dp := info!.directProduct;
emb1 := Embedding( dp, 1 );
emb2 := Embedding( dp, 2 );
kappa := info!.projections[1];
lambda := info!.projections[2];
genLN := List( genL, g -> ImageElm( lambda, g ) );
genLM := List( genL, g -> ImageElm( kappa, g ) );
autL := AutomorphismGroup( L );
genN := GeneratorsOfGroup( N );
lenN := Length( genN );
imact1 := ListWithIdenticalEntries( lenN, 0 );
for i in [1..lenN] do
n := genN[i];
an := ImageElm( act0, ImageElm( nu, n ) );
actLN := List( genLN, g -> g^n );
actLM := List( genLM, g -> ImageElm( an, g ) );
prod := List( [1..lenL], j -> ImageElm( emb1, actLM[j] )
* ImageElm( emb2, actLN[j] ) );
imact1[i] := GroupHomomorphismByImages( L, L, genL, prod );
od;
act1 := GroupHomomorphismByImages( N, autL, genN, imact1 );
X1 := XMod( lambda, act1 );
mor := XModMorphismByGroupHomomorphisms( X1, X0, kappa, nu );
SetMorphismOfPullback( X1, mor );
return X1;
end );
#############################################################################
##
#A KernelCokernelXMod . . . . ( ker(bdy) -> range/image(bdy) ) for an xmod
##
InstallMethod( KernelCokernelXMod,
"kernel -> cokernel xmod for a cat1-group", true, [ IsCat1Group ], 0,
function( C0 )
return KernelCokernelXMod( XModOfCat1Group( C0 ) );
end );
InstallMethod( KernelCokernelXMod, "kernel -> cokernel for an xmod", true,
[ IsXMod ], 0,
function( X0 )
local S, R, bdy, act, K, J, nat, F, genK, imres, res,
genF, preF, imact, i, g, p, ap, im, autK, actF;
S := Source( X0 );
R := Range( X0 );
bdy := Boundary( X0 );
act := XModAction( X0 );
K := Kernel( bdy );
J := ImagesSource( bdy );
nat := NaturalHomomorphismByNormalSubgroup( R, J );
F := FactorGroup( R, J );
genK := GeneratorsOfGroup( K );
imres := List( genK, g -> Image( nat, Image( bdy, g ) ) );
res := GroupHomomorphismByImages( K, F, genK, imres );
genF := GeneratorsOfGroup( F );
preF := List( genF, g -> PreImagesRepresentativeNC( nat, g ) );
imact := ShallowCopy( genF );
if ( genF = [ ] ) then
genF := [ One( F ) ];
imact := [ IdentityMapping( K ) ];
else
for i in [1..Length( genF )] do
g := genF[i];
p := preF[i];
ap := ImageElm( act, p );
im := List( genK, k -> ImageElm( ap, k ) );
imact[i] := GroupHomomorphismByImages( K, K, genK, im );
od;
fi;
autK := Group( imact );
SetIsGroupOfAutomorphisms( autK, true );
actF := GroupHomomorphismByImages( F, autK, genF, imact );
return XModByBoundaryAndAction( res, actF );
end );
#############################################################################
##
#F XMod( <bdy>, <act> ) crossed module from given boundary & action
#F XMod( <G>, <N> ) crossed module from a normal inclusion
#F XMod( <surj> ) crossed module from a surjective hom
#F XMod( <cat1> ) crossed module associated to a cat1-group
#F XMod( <aut> ) crossed module from automorphism group
#F XMod( <pxm> ) crossed module by Peiffer quotient
##
InstallGlobalFunction( XMod, function( arg )
local nargs;
nargs := Length( arg );
# two homomorphisms
if ( ( nargs = 2 ) and IsGroupHomomorphism( arg[1] )
and IsGroupHomomorphism( arg[2] ) ) then
return XModByBoundaryAndAction( arg[1], arg[2] );
# group and normal subgroup
elif ( ( nargs = 2 ) and IsGroup( arg[1] ) and IsGroup( arg[2] )
and IsSubgroup( arg[1], arg[2] ) and IsNormal( arg[1], arg[2] ) ) then
return XModByNormalSubgroup( arg[1], arg[2] );
# xmod plus list of objects plus boolean
elif ( ( nargs = 3 ) and IsXMod( arg[1] )
and IsList( arg[2] ) and IsBool( arg[3] ) ) then
return SinglePiecePreXModWithObjects( arg[1], arg[2], arg[3] );
# surjective homomorphism
elif ( ( nargs = 1 ) and IsGroupHomomorphism( arg[1] )
and IsSurjective( arg[1] ) ) then
return XModByCentralExtension( arg[1] );
# convert a cat1-group
elif ( ( nargs = 1 ) and HasIsCat1Group( arg[1] )
and IsCat1Group( arg[1] ) ) then
return PreXModRecordOfPreCat1Group( arg[1] ).prexmod;
# group of automorphisms
elif ( ( nargs = 1 ) and IsGroupOfAutomorphisms( arg[1] ) ) then
return XModByAutomorphismGroup( arg[1] );
# just a group
elif ( ( nargs = 1 ) and IsGroup( arg[1] ) ) then
return XModByNormalSubgroup( arg[1], arg[1] );
# pre-crossed module
elif ( ( nargs = 1 ) and IsPreXMod( arg[1] ) ) then
return XModByPeifferQuotient( arg[1] );
fi;
# alternatives not allowed
Error( "usage: XMod( bdy, act ); or XMod( G, N );" );
end );
#############################################################################
##
#M IsSubPreXMod
##
InstallMethod( IsSubPreXMod, "generic method for pre-crossed modules", true,
[ Is2DimensionalGroup, Is2DimensionalGroup ], 0,
function( PM, SM )
local ok, Ssrc, Srng, gensrc, genrng, s, r, r1, r2, im1, im2;
if not ( IsPreXMod( PM ) and IsPreXMod( SM ) ) then
return false;
fi;
if ( HasParent( SM ) and ( Parent( SM ) = PM ) ) then
return true;
fi;
Ssrc := Source( SM );
Srng := Range( SM );
if not ( IsSubgroup( Source( PM ), Ssrc )
and IsSubgroup( Range( PM ), Srng ) ) then
Info( InfoXMod, 3, "IsSubgroup failure in IsSubPreXMod" );
return false;
fi;
ok := true;
gensrc := GeneratorsOfGroup( Ssrc );
genrng := GeneratorsOfGroup( Srng );
for s in gensrc do
if ( ImageElm( Boundary(PM), s ) <> ImageElm( Boundary(SM), s ) ) then
ok := false;
fi;
od;
if not ok then
Info( InfoXMod, 3, "boundary maps have different images" );
return false;
fi;
for r in genrng do
r1 := ImageElm( XModAction( PM ), r );
r2 := ImageElm( XModAction( SM ), r );
for s in gensrc do
im1 := ImageElm( r1, s );
im2 := ImageElm( r2, s );
if ( im1 <> im2 ) then
ok := false;
Info( InfoXMod, 3, "s,im1,im2 = ", [s,im1,im2] );
fi;
od;
od;
if not ok then
Info( InfoXMod, 3, "actions have different images" );
return false;
fi;
if ( PM <> SM ) then
SetParent( SM, PM );
fi;
return true;
end );
#############################################################################
##
#M IsSubXMod( <XM>, <SM> )
##
InstallMethod( IsSubXMod, "generic method for crossed modules", true,
[ Is2DimensionalGroup, Is2DimensionalGroup ], 0,
function( XM, SM )
if not ( IsXMod( XM ) and IsXMod( SM ) ) then
return false;
fi;
return IsSubPreXMod( XM, SM );
end );
#############################################################################
##
#M IsSubPreCat1Group
##
InstallMethod( IsSubPreCat1Group, "generic method for pre-cat1-groups", true,
[ Is2DimensionalGroup, Is2DimensionalGroup ], 0,
function( C0, S0 )
local ok, Ssrc, Srng, gensrc, genrng, tc, hc, ec, ts, hs, es, s, r;
if not ( IsPreCat1Group( C0 ) and IsPreCat1Group( S0 ) ) then
return false;
fi;
if ( HasParent( S0 ) and ( Parent( S0 ) = C0 ) ) then
return true;
fi;
Ssrc := Source( S0 );
Srng := Range( S0 );
if not ( IsSubgroup( Source( C0 ), Ssrc )
and IsSubgroup( Range( C0 ), Srng ) ) then
Info( InfoXMod, 3, "IsSubgroup failure in IsSubPreCat1Group" );
return false;
fi;
ok := true;
gensrc := GeneratorsOfGroup( Ssrc );
genrng := GeneratorsOfGroup( Srng );
tc := TailMap(C0); hc := HeadMap(C0); ec := RangeEmbedding(C0);
ts := TailMap(S0); hs := HeadMap(S0); es := RangeEmbedding(S0);
for s in gensrc do
if ( ImageElm( tc, s ) <> ImageElm( ts, s ) ) then
ok := false;
fi;
if ( ImageElm( hc, s ) <> ImageElm( hs, s ) ) then
ok := false;
fi;
od;
if not ok then
Info( InfoXMod, 3, "tail/head maps have different images" );
return false;
fi;
for r in genrng do
if ( ImageElm( ec, r ) <> ImageElm( es, r ) ) then
ok := false;
fi;
od;
if not ok then
Info( InfoXMod, 3, "embeddingss have different images" );
return false;
fi;
if ( C0 <> S0 ) then
SetParent( S0, C0 );
fi;
return true;
end );
#############################################################################
##
#M IsSubCat1Group( <C1>, <S1> )
##
InstallMethod( IsSubCat1Group, "generic method for cat1-groups", true,
[ Is2DimensionalGroup, Is2DimensionalGroup ], 0,
function( C1, S1 )
if not ( IsCat1Group( C1 ) and IsCat1Group( S1 ) ) then
return false;
fi;
return IsSubPreCat1Group( C1, S1 );
end );
#############################################################################
##
#M IsNormalSub2DimensionalDomain( <XM>, <SM> )
##
InstallMethod( IsNormalSub2DimensionalDomain, "for xmod and subxmod etc.",
true, [ Is2DimensionalGroup, Is2DimensionalGroup ], 0,
function( X0, X1 )
local ispx, ok, S0, R0, S1, R1, r0, s0, r1, s1;
ispx := IsPreXMod( X0 );
if ispx then
ok := IsSubPreXMod( X0, X1 );
else
ok := IsSubPreCat1Group( X0, X1 );
fi;
if not ok then
return false;
fi;
if not ispx then
Error( "not yet installed for cat1-groups" );
fi;
S0 := Source( X0 );
R0 := Range( X0 );
S1 := Source( X1 );
R1 := Range( X1 );
if not IsNormal( R0, R1 ) then
return false;
fi;
## apparently no requirement for S1 to be normal in S0
for r0 in GeneratorsOfGroup( R0 ) do
for s1 in GeneratorsOfGroup( S1 ) do
if not ImageElmXModAction( X0, s1, r0 ) in S1 then
return false;
fi;
od;
od;
for r1 in GeneratorsOfGroup( R1 ) do
for s0 in GeneratorsOfGroup( S0 ) do
if not s0^-1 * ImageElmXModAction( X0, s0, r1 ) in S1 then
return false;
fi;
od;
od;
return true;
end );
#############################################################################
##
#M Sub2DimensionalGroup . creates Sub2bObject from Ssrc<=Osrc & Srng<=Orng
##
InstallMethod( Sub2DimensionalGroup, "generic method for 2d-objects", true,
[ Is2DimensionalGroup, IsGroup, IsGroup ], 0,
function( obj, src, rng )
if ( HasIsXMod(obj) and IsXMod(obj) ) then
return SubXMod( obj, src, rng );
elif ( HasIsPreXMod(obj) and IsPreXMod(obj) ) then
return SubPreXMod( obj, src, rng );
elif ( HasIsCat1Group(obj) and IsCat1Group(obj) ) then
return SubCat1Group( obj, src, rng );
elif ( HasIsPreCat1Group(obj) and IsPreCat1Group(obj) ) then
return SubPreCat1Group( obj, src, rng );
else
Error( "unknown type of 2d-object" );
fi;
end );
#############################################################################
##
#M IsSub2DimensionalGroup . . tests whethere sub is a sub-structure of obj
##
InstallMethod( IsSub2DimensionalGroup, "generic method for 2d-objects", true,
[ Is2DimensionalGroup, Is2DimensionalGroup ], 0,
function( obj, sub )
if IsPreXMod( obj ) then
return IsSubPreXMod( obj, sub );
elif IsPreCat1Group( obj ) then
return IsSubPreCat1Group( obj, sub );
else
return fail;
fi;
end );
##############################################################################
##
#M SubPreXMod creates SubPreXMod from Ssrc<=Psrc & Srng<=Prng
##
InstallMethod( SubPreXMod, "generic method for pre-crossed modules", true,
[ IsPreXMod, IsGroup, IsGroup ], 0,
function( PM, Ssrc, Srng )
local Psrc, Prng, Pbdy, Pact, Paut, genSsrc, genSrng, Pname, Sname,
SM, Sbdy, Saut, Sact, r, innaut, genPrng, genPsrc, ssrc,
trivsrc, trivrng, incSsrc, idSsrc, imact, imgen, imbdy, imSsrc,
imalpha, alpha;
Psrc := Source( PM );
Prng := Range( PM );
Pbdy := Boundary( PM );
Pact := XModAction( PM );
Paut := Range( Pact );
if not IsSubgroup( Psrc, Ssrc ) then
Info( InfoXMod, 1, "Ssrc is not a subgroup of Psrc" );
return fail;
fi;
if not ( IsSubgroup( Prng, Srng ) ) then
Info( InfoXMod, 1, "Srng is not a subgroup of Prng" );
return fail;
fi;
ssrc := Size( Ssrc );
genPsrc := GeneratorsOfGroup( Psrc );
genPrng := GeneratorsOfGroup( Prng );
genSsrc := GeneratorsOfGroup( Ssrc );
genSrng := GeneratorsOfGroup( Srng );
incSsrc := InclusionMappingGroups( Psrc, Ssrc );
imgen := List( genSsrc, x -> ImageElm( Pbdy, x ) );
imSsrc := Subgroup( Prng, imgen );
if not IsSubgroup( Srng, imSsrc ) then
Info( InfoXMod, 2, "Pbdy(Ssrc) is not a subgroup of Srng" );
return fail;
fi;
trivsrc := ( Size( Ssrc ) = 1 );
trivrng := ( Size( Srng ) = 1 );
if ( trivrng or trivsrc ) then
Sbdy := MappingToOne( Ssrc, Srng );
else
Sbdy:= GroupHomomorphismByImages( Ssrc, Srng, genSsrc, imgen );
fi;
innaut := [ ];
for r in genSrng do
alpha := ImageElm( Pact, r );
imgen := List( genSsrc, x -> ImageElm( alpha, x ) );
if not ForAll( imgen, x -> ( x in Ssrc ) ) then
return fail;
fi;
imalpha := Subgroup( Ssrc, imgen );
if not ( IsSubgroup( Ssrc, imalpha ) ) then
Info( InfoXMod, 2, "Srng does not act correctly on Ssrc" );
return fail;
fi;
alpha:=GroupHomomorphismByImages( Ssrc, Ssrc, genSsrc, imgen );
Add( innaut, alpha );
od;
idSsrc := IdentityMapping( Ssrc );
if ( ssrc = 1 ) then
Saut := Group( idSsrc );
innaut := List( genSrng, s -> idSsrc );
else
Saut := Group( innaut, idSsrc );
fi;
Sact := GroupHomomorphismByImages( Srng, Saut, genSrng, innaut );
if ( not IsGroupHomomorphism( Sact ) ) then
Print( "Sact is not a homomorphism\n" );
return fail;
fi;
SM := PreXModByBoundaryAndAction( Sbdy, Sact );
if HasParent( PM ) then
SetParent( SM, Parent( PM ) );
else
SetParent( SM, PM );
fi;
return SM;
end );
#############################################################################
##
#M SubXMod . . . . . . . . . creates SubXMod from Ssrc<=Psrc & Srng<=Prng
##
InstallMethod( SubXMod, "generic method for crossed modules", true,
[ IsXMod, IsGroup, IsGroup ], 0,
function( XM, Ssrc, Srng )
local SM;
SM := SubPreXMod( XM, Ssrc, Srng );
if ( SM = fail ) then
return fail;
fi;
if not IsXMod( SM ) then
Error( "the result is only a pre-crossed module" );
fi;
return SM;
end );
#############################################################################
##
#M SubPreCat1Group . created from PreCat1Group and a subgroup of the source
##
InstallMethod( SubPreCat1Group, "generic method for (pre-)cat1-groups", true,
[ IsPreCat1Group, IsGroup, IsGroup ], 0,
function( C, G, R )
local Csrc, Crng, Ct, Ch, Ce, t, h, e, SC, ok;
Csrc := Source( C );
Crng := Range( C );
Ct := TailMap( C );
Ch := HeadMap( C );
Ce := RangeEmbedding( C );
ok := true;
if not ( IsSubgroup( Csrc, G ) ) then
Print( "G is not a subgroup of Csrc\n" );
ok := false;
fi;
if not ( ( R = Image( Ct, G ) ) and
( R = Image( Ch, G ) ) ) then
Print( "restrictions of Ct, Ch to G must have common image R\n" );
ok := false;
fi;
t := GeneralRestrictedMapping( Ct, G, R );
h := GeneralRestrictedMapping( Ch, G, R );
e := GeneralRestrictedMapping( Ce, R, G );
SC := PreCat1GroupByTailHeadEmbedding( t, h, e );
if not ( C = SC ) then
SetParent( SC, C );
fi;
return SC;
end );
#############################################################################
##
#M SubCat1Group . creates SubCat1Group from Cat1Group and subgroup of source
##
InstallMethod( SubCat1Group, "generic method for cat1-groups", true,
[ IsCat1Group, IsGroup, IsGroup ], 0,
function( C, G, R )
local S;
S := SubPreCat1Group( C, G, R );
if not IsCat1Group( S ) then
Error( "result is only a pre-cat1-group" );
fi;
return S;
end );
#############################################################################
##
#M IsCat1Group check that the second cat1-group axiom holds
##
InstallMethod( IsCat1Group, "generic method for pre-cat1-groups", true,
[ IsPreCat1Group ], 0,
function( C1G )
local Csrc, Crng, h, t, e, f, kerC, kert, kerh, kerth;
Csrc := Source( C1G );
Crng := Range( C1G );
h := HeadMap( C1G );
t := TailMap( C1G );
e := RangeEmbedding( C1G );
kerC := Kernel( C1G );
f := KernelEmbedding( C1G );
kert := Kernel( t );
kerh := Kernel( h );
kerth := CommutatorSubgroup( kert, kerh );
if not ( Size( kerth ) = 1 ) then
Info( InfoXMod, 1, "condition [kert,kerh] = 1 is not satisfied");
Info( InfoXMod, 4, " kert = ", kert, " has Id ", IdGroup(kert) );
Info( InfoXMod, 4, " kerh = ", kerh, " has Id ", IdGroup(kerh) );
Info( InfoXMod, 4, "kerth = ", kerth, " has Id ", IdGroup(kerth) );
return false;
fi;
if not ( ( Source( f ) = kerC ) and ( Range( f ) = Csrc ) ) then
Print( "Warning: KernelEmbedding( C1G ) incorrectly defined?\n" );
fi;
return true;
end );
InstallOtherMethod( IsCat1Group, "generic method for pre-xmods", true,
[ IsPreXMod ], 0,
function( X0 )
Print( "this is a pre-crossed module, not a pre-cat1-group\n" );
return false;
end );
#############################################################################
##
#M IsIdentityPreCat1Group( precat1 )
#M IsSymmetric2DimensionalGroup( obj )
##
InstallMethod( IsIdentityPreCat1Group, "test a pre-cat1-group", true,
[ IsPreCat1Group ], 0,
function( C1G )
return ( ( TailMap( C1G ) = IdentityMapping( Source( C1G ) ) ) and
( HeadMap( C1G ) = IdentityMapping( Source( C1G ) ) ) );
end );
InstallMethod( IsSymmetric2DimensionalGroup, "test a pre-cat1-group", true,
[ IsPreCat1Group ], 0,
function( pc1 )
return ( TailMap( pc1 ) = HeadMap( pc1 ) );
end );
--> --------------------
--> maximum size reached
--> --------------------
[ Original von:0.159Diese Quellcodebibliothek enthält Beispiele in vielen Programmiersprachen.
Man kann per Verzeichnistruktur darin navigieren.
Der Code wird farblich markiert angezeigt.
]
|
2026-03-28
|