############################################################################# ## #W mwo.gi GAP4 package `groupoids' Chris Wensley ## ## This file contains the declarations of elements, magma, etc., and their ## families in the case of many objects. So each algebraic structure comes ## with a set of objects, and each element $e$ has a tail object $te$ and a ## head object $he$, and multiplies partially if composable: on the left ## with those elements in its family which have head $te$, and on the right ## with those elements of its family which have tail $he$. Non-composable ## elements return $fail$ when multiplied. ##
########################### DOMAIN WITH OBJECTS ###########################
############################################################################# ## #M KindOfDomainWithObjects( <dwo> ) ##
InstallMethod( KindOfDomainWithObjects, "for a list of domains with objects",
true, [ IsList ], 0, function( pieces )
local kind;
## kind: 1=gpd, 2=mon, 3=sgp, 4=mgm, 5=dom
kind := 0; if ForAll( pieces, p -> ( FamilyObj(p) = IsGroupoidFamily ) ) then
kind := 1; elif ForAll( pieces, p -> ( ( FamilyObj(p) = IsMonoidWithObjectsFamily )
or ( FamilyObj(p) = IsGroupoidFamily ) ) ) then
kind := 2; elif ForAll( pieces, p -> ( ( FamilyObj(p) = IsSemigroupWithObjectsFamily )
or ( FamilyObj(p) = IsMonoidWithObjectsFamily )
or ( FamilyObj(p) = IsGroupoidFamily ) ) ) then
kind := 3; elif ForAll( pieces, p ->
( "IsMagmaWithObjects" in CategoriesOfObject(p) ) ) then
kind := 4; elif ForAll( pieces, p ->
( "IsDomainWithObjects" in CategoriesOfObject(p) ) ) then
kind := 5; else
Info( InfoGroupoids, 2, "just an ordinary list?" ); fi;
return kind; end );
##################### MULT ELTS WITH OBJECTS ##############################
Info( InfoGroupoids, 3, "standard method for ArrowNC" ); if isge then
fam := IsGroupoidElementFamily;
elt := Objectify( IsGroupoidElementType, [ mwo, e, t, h ] ); else
fam := IsMultiplicativeElementWithObjectsFamily;
elt := Objectify( IsMultiplicativeElementWithObjectsType,
[ mwo, e, t, h ] ); fi;
return elt; end );
InstallMethod( Arrow, "for general magma with objects, element, tail and head", true,
[ IsMagmaWithObjects, IsMultiplicativeElement, IsObject, IsObject ], 0, function( mwo, e, t, h )
local piece, obs, fam, mag, pwo, pos, homset, pose;
if IsSinglePiece( mwo ) then
piece := mwo; else
piece := PieceOfObject( mwo, t ); fi;
mag := piece!.magma; if not ( e in mag ) then
Error( "<e> not in magma <mag>," ); fi;
obs := piece!.objects; if not ( ( t in obs ) and ( h in obs ) ) then
Error( "<t> and <h> must be objects in <piece>," ); fi; if not IsDirectProductWithCompleteDigraph( piece ) then if not IsBound( piece!.table ) then
TryNextMethod(); fi;
pos := [ Position( obs, t ), Position( obs, h ) ]; if not HasMultiplicationTable( mag ) then
Error( "expecting magma defined by multiplication table," ); fi;
homset := piece!.table[pos[1]][pos[2]];
pose := Position( GeneratorsOfMagma( mag ), e ); if not ( pose in homset ) then
Error( "(e : t -> h) not an element in <piece>," ); fi; fi;
return ArrowNC( mwo, false, e, t, h ); end );
############################################################################# ## #M ElementOfArrow #M TailOfArrow #M HeadOfArrow #M GroupoidOfArrow ##
InstallMethod( ElementOfArrow, "generic method for magma with objects element",
true, [ IsMultiplicativeElementWithObjects ], 0, e -> e![2] );
InstallMethod( TailOfArrow, "generic method for magma with objects element",
true, [ IsMultiplicativeElementWithObjects ], 0, e -> e![3] );
InstallMethod( HeadOfArrow, "generic method for magma with objects element",
true, [ IsMultiplicativeElementWithObjects ], 0, e -> e![4] );
InstallMethod( GroupoidOfArrow, "generic method for magma with objects element",
true, [ IsMultiplicativeElementWithObjects ], 0, e -> e![1] );
############################################################################# ## #M String, ViewString, PrintString, ViewObj, PrintObj ## . . . . . . . . . . . . . . . . . . for elements in a magma with objects ##
InstallMethod( String, "for an element in a magma with objects", true,
[ IsMultiplicativeElementWithObjects ], 0, function( e )
return( STRINGIFY( "[", String( e![2] ), " : ", String( e![3] ), " -> ", String( e![4] ), "]" ) ); end );
InstallMethod( ViewString, "for an element in a magma with objects", true,
[ IsMultiplicativeElementWithObjects ], 0, String );
InstallMethod( PrintString, "for an element in a magma with objects", true,
[ IsMultiplicativeElementWithObjects ], 0, String );
InstallMethod( ViewObj, "for an element in a magma with objects", true,
[ IsMultiplicativeElementWithObjects ], 0, PrintObj );
InstallMethod( PrintObj, "for an element in a magma with objects",
[ IsMultiplicativeElementWithObjects ], function ( e )
Print( "[", e![2], " : ", e![3], " -> ", e![4], "]" ); end );
InstallMethod( ViewObj, "for an element in a magma with objects",
[ IsMultiplicativeElementWithObjects ], PrintObj );
############################################################################# ## #M \=( <e1>, <e2> ) . . . . . . equality of elements in a magma with objects ##
InstallMethod( \=, "for two multiplicative elements with objects",
IsIdenticalObj, [ IsMultiplicativeElementWithObjects,
IsMultiplicativeElementWithObjects ], 0, function( e1, e2 )
return ForAll( [1..4], i -> ( e1![i] = e2![i] ) ); end );
############################################################################# ## #M \<( <e1>, <e2> ) . . . . . . equality of elements in a magma with objects ##
InstallMethod( \<, "for two multiplicative elements with objects",
IsIdenticalObj, [ IsMultiplicativeElementWithObjects,
IsMultiplicativeElementWithObjects ], 0, function( e1, e2 ) if ( e1![1] <> e2![1] ) then
Error( "e1, e2 belong to different mwos" ); fi; if ( e1![3] < e2![3] ) then
return true; elif ( (e1![3] = e2![3]) and (e1![4] < e2![4]) ) then
return true; elif ( (e1![3] = e2![3]) and (e1![4] = e2![4]) and (e1![2] < e2![2]) ) then
return true; else
return false; fi; end );
############################################################################# ## #M \*( e1, e2 ) . . . . . . composition of elements in a magma with objects ##
InstallMethod( \*, "for two elements in a magma with objects", IsIdenticalObj,
[IsMultiplicativeElementWithObjects, IsMultiplicativeElementWithObjects], 0, function( e1, e2 )
local prod;
if ( e1![1] <> e2![1] ) then
Error( "e1, e2 belong to different mwos" ); fi; ## elements are composable? if ( e1![4] = e2![3] ) then
return ArrowNC( e1![1], false, e1![2]*e2![2], e1![3], e2![4] ); else
return fail; fi; end );
############################################################################# ## #M \^( e, p ) . . . . . . power (inverse) of element in a magma with objects ##
InstallMethod( \^, "for an element in a magma with objects and a PosInt",
true, [ IsMultiplicativeElementWithObjects, IsPosInt ], 0, function( e, p ) ## should be able to invert an identity element ## groupoids use their own method if ( e![4] = e![3] ) then
return ArrowNC( e![1], false, e![2]^p, e![3], e![4] ); else
return fail; fi; end );
############################################################################# ## #M Order( <e> ) . . . . . . . . . . . . . . . . . . . . . of an mwo element ##
InstallOtherMethod( Order, "for a multiplicative element with objects", true,
[ IsMultiplicativeElementWithObjects ], 0, function( e )
local ord;
if not ( e![3] = e![4] ) then
Error( "tail of e <> head of e," ); fi;
return Order( e![2] ); end );
############################################################################# ## #M \=( <m1>, <m2> ) . . . . . . . test if two magmas with objects are equal ##
InstallMethod( \=, "for magmas with objects", IsIdenticalObj,
[ IsMagmaWithObjects, IsMagmaWithObjects ], 0, function ( m1, m2 )
local i, p1, p2;
if ( IsSinglePiece(m1) and IsSinglePiece(m2) ) then
return ( ( m1!.objects=m2!.objects ) and ( m1!.magma=m2!.magma ) ); elif ( IsSinglePiece(m1) or IsSinglePiece(m2) ) then
return false; else
p1 := Pieces( m1 );
p2 := Pieces( m2 ); if not ( Length( p1 ) = Length( p2 ) ) then
return false; else for i in [1..Length( p1 )] do if ( p1[i] <> p2[i] ) then
return false; fi;
od;
return true; fi; fi; end );
############################################################################# ## #M \in( <elt>, <mwo> ) . . . . test if an element is in a magma with objects ##
InstallMethod( \in, "for mwo element and a standard magma with objects", true,
[ IsMultiplicativeElementWithObjects,
IsMagmaWithObjects and IsSinglePiece ], 0, function( e, mwo )
return ( e![1] = mwo ); end );
InstallMethod( \in, "for mwo element and a union of pieces", true,
[ IsMultiplicativeElementWithObjects, IsMagmaWithObjects and HasPieces ], 0, function( e, mwo )
return e in PieceOfObject( mwo, e![3] ); end );
############################################################################# ## #M Size ##
InstallOtherMethod( Size, "generic method for a magma with objects", true,
[ IsMagmaWithObjects ], 0, function( mwo )
local p, s;
if ( HasIsDirectProductWithCompleteDigraph( mwo ) and
IsDirectProductWithCompleteDigraph( mwo ) ) then
return Size( mwo!.magma ) * Length( mwo!.objects )^2; elif ( HasIsDiscreteDomainWithObjects( mwo ) and
IsDiscreteDomainWithObjects( mwo ) ) then
return Size( mwo!.magma ) * Length( mwo!.objects ); elif ( HasIsSinglePieceDomain( mwo ) and
IsSinglePieceDomain( mwo ) ) then
return Size( mwo!.magma ) * Length( mwo!.objects )^2;
Print("reached here\n"); elif HasPieces( mwo ) then
s := 0; for p in Pieces( mwo ) do
s := s + Size(p);
od;
return s; else
TryNextMethod(); fi; end );
############################################################################# ## #M String, ViewString, PrintString, ViewObj, PrintObj ## . . . . . . . . . . . . . . . . . . . . . . . . for a magma with objects ##
InstallMethod( String, "for a magma with objects", true,
[ IsMagmaWithObjects ], 0, function( mwo )
local kind;
kind := KindOfDomainWithObjects( [ mwo ] ); if ( kind = 1 ) then
return( STRINGIFY( "groupoid" ) ); elif ( kind = 2 ) then
return( STRINGIFY( "monoid with objects" ) ); elif ( kind = 3 ) then
return( STRINGIFY( "semigroup with objects" ) ); elif ( kind = 4 ) then
return( STRINGIFY( "magma with objects" ) ); else
return( STRINGIFY( "domain with objects" ) ); fi; end );
InstallMethod( ViewString, "for an element in a magma with objects", true,
[ IsMultiplicativeElementWithObjects ], 0, String );
InstallMethod( PrintString, "for an element in a magma with objects", true,
[ IsMultiplicativeElementWithObjects ], 0, String );
InstallMethod( ViewObj, "for an element in a magma with objects", true,
[ IsMultiplicativeElementWithObjects ], 0, PrintObj );
InstallMethod( ViewObj, "for a single piece magma with objects", true,
[ IsSinglePiece ], 0, function( mwo )
local kind;
kind := KindOfDomainWithObjects( [ mwo ] ); if ( kind = 1 ) or ( kind = 5 ) then
Print( "#I should be using special groupoid method!\n" ); elif ( kind = 2 ) then
Print( "monoid with objects :-\n" ); elif ( kind = 3 ) then
Print( "semigroup with objects :-\n" ); elif ( kind = 4 ) then
Print( "magma with objects :-\n" ); else
Print( "not yet implemented for general domains with objects\n" ); fi;
Print( " magma = ", mwo!.magma, "\n" );
Print( " objects = ", mwo!.objects, "\n" ); end );
InstallMethod( PrintObj, "for a single piece magma with objects", true,
[ IsSinglePiece ], 0, function( mwo )
local kind;
kind := KindOfDomainWithObjects( [ mwo ] ); if ( kind = 1 ) or ( kind = 5 ) then
Print( "#I should be using special groupoid method!\n" ); elif ( kind = 2 ) then
Print( "monoid with objects :-\n" ); elif ( kind = 3 ) then
Print( "semigroup with objects :-\n" ); elif ( kind = 4 ) then
Print( "magma with objects :-\n" ); else
Print( "not yet implemented for general domains with objects\n" ); fi;
Print( " magma = ", mwo!.magma, "\n" );
Print( " objects = ", mwo!.objects, "\n" ); end );
InstallMethod( ViewObj, "for more than one piece", true,
[ IsDomainWithObjects and IsPiecesRep ], 10, function( dwo )
local i, pieces, np, kind;
pieces := Pieces( dwo );
np := Length( pieces );
kind := KindOfDomainWithObjects( Pieces( dwo ) ); if (kind=1) then Print( "groupoid" ); elif (kind=2) then Print( "monoid with objects" ); elif (kind=3) then Print( "semigroup with objects" ); elif (kind=4) then Print( "magma with objects" ); elif (kind=5) then Print( "double groupoid" ); elif (kind=0) then Error( "invalid domain with objects," ); fi;
Print( " having ", np, " pieces :-\n" ); for i in [1..np] do
Print( i, ": ", pieces[i] ); if HasName( pieces[i] ) then
Print( "\n" ); fi;
od; end );
InstallMethod( PrintObj, "for more than one piece", true,
[ IsMagmaWithObjects and IsPiecesRep ], 0, function( mwo )
local i, pieces, np;
pieces := Pieces( mwo );
np := Length( pieces );
Print( "domain with objects having ", np, " pieces :-\n" ); for i in [1..np] do
Print( pieces[i] ); if HasName( pieces[i] ) then
Print( "\n" ); fi;
od; end );
############################################################################## ## #M Display( <mwo> ) . . . . . . . . . . . . . . display a magma with objects ##
InstallMethod( Display, "for a mwo", true, [ IsMagmaWithObjects ], 0, function( mwo )
local comp, c, i, m, len;
if IsSinglePiece( mwo ) then if IsDirectProductWithCompleteDigraph( mwo ) then
Print( "Single constituent magma with objects: " ); if HasName( mwo ) then
Print( mwo ); fi;
Print( "\n" );
Print( " objects: ", mwo!.objects, "\n" );
m := mwo!.magma;
Print( " magma: " ); if HasName( m ) then
Print( m, " = <", GeneratorsOfMagma( m ), ">\n" ); else
Print( m, "\n" ); fi; else
TryNextMethod(); fi; else
comp := Pieces( mwo );
len := Length( comp );
Print( "Magma with objects with ", len, " pieces:\n" ); for i in [1..len] do
c := comp[i]; if IsDirectProductWithCompleteDigraph( c ) then
Print( "< objects: ", c!.objects, "\n" );
m := c!.magma;
Print( " magma: " ); if HasName( m ) then
Print( m, " = <", GeneratorsOfMagma( m ), "> >\n" ); else
Print( m, " >\n" ); fi; else
TryNextMethod(); fi;
od; fi; end );
############################################################################# ## #M RootObject( <mwo> ) for a connected or many-piece magma with objects ##
InstallMethod( RootObject, "for a single piece mwo", true,
[ IsSinglePiece ], 0, function( mwo )
return mwo!.objects[1]; end );
InstallOtherMethod( RootObject, "for a mwo with pieces", true,
[ IsDomainWithObjects and IsPiecesRep ], 0, function( mwo )
Print( "#I only a single piece magma with objects has a root object\n" );
return fail; end );
############################################################################# ## #M GeneratorsOfMagmaWithObjects( <mwo> ) for a connected magma with objects #M GeneratorsOfSemigroupWithObjects( <swo> ) #M GeneratorsOfMonoidWithObjects( <mwo> ) ##
InstallMethod( GeneratorsOfMagmaWithObjects, "for a single piece mwo",
true, [ IsSinglePiece ], 0, function( mwo )
local obs, nobs, o1, m, mgens, kind, gens, i, j, k, g;
obs := mwo!.objects;
nobs := Length( obs );
o1 := obs[1];
m := mwo!.magma;
kind := 1; if ( "IsGroupoid" in CategoriesOfObject( mwo ) ) then
return GeneratorsOfGroupoid( mwo ); fi; if not ( HasIsDirectProductWithCompleteDigraph( mwo ) and
IsDirectProductWithCompleteDigraph( mwo ) ) then
Info( InfoGroupoids, 1, "expecting product with complete graph" );
return fail; fi; if ( "IsMonoidWithObjects" in CategoriesOfObject( mwo ) ) then
return GeneratorsOfMonoidWithObjects( mwo ); fi; if ( "IsSemigroupWithObjects" in CategoriesOfObject( mwo ) ) then
kind := 2;
mgens := GeneratorsOfSemigroup( m ); else
mgens := GeneratorsOfMagma( m ); fi;
gens := ListWithIdenticalEntries( nobs * nobs * Length(mgens), 0 );
k := 0; for i in obs do for j in obs do for g in mgens do
k := k+1;
gens[k] := ArrowNC( mwo, false, g, i, j );
od;
od;
od; if ( kind = 2 ) then
SetGeneratorsOfSemigroupWithObjects( mwo, gens ); fi;
return gens; end );
InstallMethod( GeneratorsOfMagmaWithObjects, "for discrete domain",
true, [ IsGroupoid and IsSinglePiece and IsDiscreteDomainWithObjects ], 0, function( mwo )
local o, ogens, gens;
gens := [ ]; for o in mwo!.objects do
ogens := GeneratorsOfGroup( ObjectGroup( mwo, o ) );
Add( gens, List( ogens, g -> GroupoidElement( mwo, g, o, o ) ) );
od;
return gens; end );
InstallMethod( GeneratorsOfSemigroupWithObjects, "for a semigroup with objects",
true, [ IsSemigroupWithObjects ], 0, GeneratorsOfMagmaWithObjects );
InstallMethod( GeneratorsOfMonoidWithObjects, "for a monoid with objects",
true, [ IsMonoidWithObjects and IsSinglePiece], 0, function( mwo )
local obs, nobs, o1, m, mgens, id, gens1, gens2, gens, i, k;
obs := mwo!.objects;
nobs := Length( obs );
o1 := obs[1];
m := mwo!.magma;
mgens := GeneratorsOfMonoid( m );
id := One( m );
gens1 := List( mgens, g -> ArrowNC( mwo, false, g, o1, o1 ) );
gens2 := ListWithIdenticalEntries( (nobs-1)^2, 0 );
k := 0; for i in [2..nobs] do
gens2[k+1] := ArrowNC( mwo, false, id, o1, obs[i] );
gens2[k+2] := ArrowNC( mwo, false, id, obs[i], o1 );
k := k+2;
od;
gens := Immutable( Concatenation( gens1, gens2 ) );
SetGeneratorsOfMonoidWithObjects( mwo, gens );
return gens; end );
############################# MORE THAN ONE PIECE #########################
############################################################################# ## #M Pieces . . . . . . . . . . connected components of a domain with objects ##
InstallMethod( Pieces, "for a single piece domain with objects",
true, [ IsSinglePieceDomain ], 0, function( dwo )
return [ dwo ]; end );
############################################################################# ## #M ObjectList . . . . . . . . . . . . . . . . . . . for a magma with objects ##
InstallMethod( ObjectList, "for a magma with objects",
true, [ IsMagmaWithObjects ], 0, function( mwo )
local obs;
if ( HasIsSinglePiece( mwo ) and IsSinglePiece( mwo ) ) then
return mwo!.objects; else
obs := Concatenation(
List( Pieces( mwo ), c -> c!.objects ) ); if not IsDuplicateFree( obs ) then
Error( "same object in more than one constituent," ); fi;
Sort( obs );
return obs; fi; end );
############################################################################# ## #M UnionOfPieces . . . . . . . . for a list of connected magmas with objects #M UnionOfPiecesOp ##
InstallGlobalFunction( UnionOfPieces, function( arg )
local L, npa, part, pieces, p, nco, obs, obp, i, gi, nobj;
if IsList( arg[1] ) then
L := arg[1]; else
L := arg; fi;
npa := Length( L );
pieces := [ ]; if ( Length( L ) = 1 ) then
return L[1]; fi; for part in L do if not IsDomainWithObjects( part ) then
Info( InfoGroupoids, 1, "part ", part, "not an mwo" );
return fail; fi; if ( HasIsSinglePiece(part) and IsSinglePiece(part) ) then
Add( pieces, part ); else
Append( pieces, Pieces( part ) ); fi;
od;
obs := [ ]; for p in pieces do
obp := ObjectList( p ); if ( Intersection( obs, obp ) <> [ ] ) then
Info( InfoGroupoids, 1, "pieces must have disjoint object sets" );
return fail; fi;
obs := Union( obs, obp );
od;
return UnionOfPiecesOp( pieces, pieces[1] ); end );
InstallMethod( UnionOfPiecesOp, "method for magmas with objects",
true, [ IsList, IsDomainWithObjects ], 0, function( comps, dom )
local kind, len, pieces, L, fam, filter, mwo, i, obs, par;
## determine which kind: 1=gpd, 2=mon, 3=sgp, 4=mgm, 5=dgpd, 6=dom if ForAll( comps, c -> "IsGroupoid" in CategoriesOfObject( c ) ) then
kind := 1; elif ForAll( comps,
c -> "IsDoubleGroupoid" in CategoriesOfObject( c ) ) then
kind := 5; elif ForAll( comps,
c -> "IsMonoidWithObjects" in CategoriesOfObject( c ) ) then
kind := 2; elif ForAll( comps,
c -> "IsSemigroupWithObjects" in CategoriesOfObject( c ) ) then
kind := 3; elif ForAll( comps,
c -> "IsMagmaWithObjects" in CategoriesOfObject( c ) ) then
kind := 4; else
Print( "kind not in {1,2,3,4,5} so TryNextMethod()\n" );
TryNextMethod(); fi;
Info( InfoGroupoids, 2, "kind = ", kind ); ## order pieces by first object
len := Length( comps );
obs := List( comps, g -> g!.objects[1] );
L := [1..len];
SortParallel( obs, L ); if ( L = [1..len] ) then
pieces := comps; else
Info( InfoGroupoids, 2, "reordering pieces by first object" );
pieces := List( L, i -> comps[i] ); fi; if ( kind = 1 ) then
fam := IsGroupoidFamily;
filter := IsPiecesRep and IsGroupoid and IsAssociative;
mwo := Objectify( IsGroupoidPiecesType, rec() ); elif ( kind = 5 ) then
fam := IsDoubleGroupoidFamily;
filter := IsPiecesRep and IsDoubleGroupoid and IsAssociative;
mwo := Objectify( IsDoubleGroupoidPiecesType, rec() ); elif ( kind = 2 ) then
fam := IsMonoidWithObjectsFamily;
filter := IsPiecesRep and IsMonoidWithObjects;
mwo := Objectify( IsMonoidWOPiecesType, rec() ); elif ( kind = 3 ) then
fam := IsSemigroupWithObjectsFamily;
filter := IsPiecesRep and IsSemigroupWithObjects;
mwo := Objectify( IsSemigroupWOPiecesType, rec() ); elif ( kind = 4 ) then
fam := IsMagmaWithObjectsFamily;
filter := IsPiecesRep and IsMagmaWithObjects;
mwo := Objectify( IsMagmaWOPiecesType, rec() ); else ## ?? (23/04/10) fam := FamilyObj( [ pieces ] );
Error( "union of unstructured domains not yet implemented," ); fi;
SetIsSinglePieceDomain( mwo, false );
SetIsDirectProductWithCompleteDigraphDomain( mwo, false );
SetPieces( mwo, pieces ); if HasParent( pieces[1] ) then
par := Ancestor( pieces[1] ); if ForAll( pieces, c -> ( Ancestor( c ) = par ) ) then
SetParent( mwo, par ); fi; fi; if ( kind = 1 ) then if ForAll( pieces, p -> HasIsPermGroupoid(p) and IsPermGroupoid(p) ) then SetIsPermGroupoid( mwo, true ); elif ForAll( pieces, p -> HasIsPcGroupoid(p) and IsPcGroupoid(p) ) then SetIsPcGroupoid( mwo, true ); elif ForAll( pieces, p -> HasIsFpGroupoid(p) and IsFpGroupoid(p) ) then SetIsFpGroupoid( mwo, true ); fi; fi;
return mwo; end );
############################################################################# ## #M MagmaWithSingleObject ## ## Note that there is another method for [ IsGroup, IsObject ] in gpd.gi ##
InstallMethod( MagmaWithSingleObject, "generic method for magma, object",
true, [ IsMagma, IsObject ], 0, function( mgm, obj )
local o;
if ( IsList( obj ) and ( Length(obj) = 1 ) ) then
Info( InfoGroupoids, 2, "object given as a singleton list" );
o := obj[1]; else
o := obj; fi; if not IsObject( o ) then
Error( "<obj> not a scalar or singleton list," ); fi; if ( HasIsAssociative( mgm ) and IsAssociative( mgm )
and ( "IsMagmaWithInverses" in CategoriesOfObject( mgm ) )
and IsMagmaWithInverses( mgm ) ) then
return SinglePieceGroupoidNC( mgm, [o] ); elif ( HasIsMonoid( mgm ) and IsMonoid( mgm ) ) then
return SinglePieceMonoidWithObjects( mgm, [o] ); elif ( HasIsSemigroup( mgm ) and IsSemigroup( mgm ) ) then
return SinglePieceSemigroupWithObjects( mgm, [o] ); elif ( ( "IsMagma" in CategoriesOfObject(mgm) ) and IsMagma(mgm) ) then
return SinglePieceMagmaWithObjects( mgm, [o] ); else
Error( "unstructured domains with objects not yet implemented," ); fi; end );
############################################################################# ## #M PieceOfObject ##
InstallMethod( PieceOfObject, "generic method for magma with objects",
true, [ IsDomainWithObjects, IsObject ], 0, function( dwo, obj )
local pieces, p, objp;
if IsSinglePiece( dwo ) then if not ( obj in dwo!.objects ) then
Error( "<obj> not an object of <dwo>," ); else
return dwo; fi; elif not ( obj in ObjectList( dwo ) ) then
Info( InfoGroupoids, 1, "<obj> not an object of <dwo>" );
return fail; fi;
pieces := Pieces( dwo ); for p in pieces do
objp := p!.objects; if ( obj in objp ) then
return p; fi;
od;
Info( InfoGroupoids, 1, "it appears that <obj> is not an object in <dwo>" );
return fail; end );
pieces := Pieces( dwo ); for i in [1..Length( pieces )] do
objp := pieces[i]!.objects; if ( obj in objp ) then
return i; fi;
od;
Info( InfoGroupoids, 1, "it appears that <obj> is not an object in <dwo>" );
return fail; end );
############################################################################# ## #M IsDiscreteDomainWithObjects ##
InstallMethod( IsDiscreteDomainWithObjects, "for a magma with objects", true,
[ IsDomainWithObjects ], 0, function( dwo )
local p;
for p in Pieces( dwo ) do if not ( Length( p!.objects ) = 1 ) then
return false; fi;
od;
return true; end );
############################################################################# ## #M IsHomogeneousDomainWithObjects ##
InstallMethod( IsHomogeneousDomainWithObjects, "for a magma with objects",
true, [ IsDiscreteDomainWithObjects ], 0, function( dwo )
local pieces, g, j, iso;
pieces := Pieces( dwo );
g := pieces[1]!.magma;
return ForAll( [2..Length(pieces)], j -> ( g = pieces[j]!.magma ) ); end );
InstallMethod( IsHomogeneousDomainWithObjects, "for a magma with objects",
true, [ IsDomainWithObjects ], 0, function( dwo )
local pieces, sizes, g, j, iso;
pieces := Pieces( dwo );
sizes := Set( List( pieces, Size ) ); if not ( Length( sizes ) = 1 ) then
return false; fi;
g := pieces[1]!.magma;
return ForAll( [2..Length(pieces)], j -> ( g = pieces[j]!.magma ) ); end );
############################################################################# ## #F IsSubdomainWithObjects( <M>, <U> ) ##
InstallMethod( IsSubdomainWithObjects, "for two domains with objects", true,
[ IsDomainWithObjects, IsDomainWithObjects ], 0, function( D, U )
local compU, obj, genU, p, ok;
## insisting that a subdomain of a groupoid is a groupoid
ok := false; if not ( IsMagmaWithObjects(D) and IsMagmaWithObjects(U) ) then
Error( "not yet implemented for unstructured domains," ); fi; if ( HasParentAttr(U) and ( ParentAttr(U) = D ) ) then
return true; fi; if not IsSubset( ObjectList(D), ObjectList(U) ) then
return false; fi; if ( IsSinglePiece(D) and IsSinglePiece(U) ) then
obj := U!.objects[1]; if ( IsGroupoid(D) and IsGroupoid(U) ) then
genU := GeneratorsOfGroupoid(U);
ok := ForAll( genU, g -> g in D ); ## elif ( IsMonoid(D) and IsMonoid(U) ) then ## ok := ( IsSubsemigroup( D!.magma, U!.magma ) ## and IsMonoid( D!.magma ) ); ## elif ( IsSemigroup(D) and IsSemigroup(U) ) then ## ok := IsSubsemigroup( D!.magma, U!.magma ); else
ok := IsSubset( GeneratorsOfMagma( D!.magma ),
GeneratorsOfMagma( U!.magma ) ); fi; elif IsSinglePiece(U) then
obj := U!.objects[1];
p := PieceOfObject( D, obj );
ok := IsSubdomainWithObjects( p, U ); else
compU := Pieces(U);
ok := ForAll( compU, p -> IsSubdomainWithObjects( D, p ) ); fi; if ( ok and not HasParentAttr( U ) ) then
SetParent( U, D ); fi;
return ok; end );
# list of objects and a monoid if ( ( Length(arg) = 2 ) and IsMonoid( arg[1] ) and IsSet( arg[2] ) ) then
mon := arg[1];
obs := arg[2]; if HasGeneratorsOfMagmaWithInverses( mon ) then
return SinglePieceGroupoid( mon, obs ); else## it's just a monoid
return SinglePieceMonoidWithObjects( mon, obs ); fi; else
Error( "Current usage: MonoidWithObjects( <mon>, <obs> )," ); fi; end );
################################## GROUPS ################################# ## A *group with objects* is a magma with objects where the vertex magmas ## are groups, and so is a *groupoid* - see file gpd.gi.
############################################################################# ## #M IsSubmagmaWithObjectsGeneratingTable( <mag>, <A> ) ##
InstallMethod( IsSubmagmaWithObjectsGeneratingTable, "for magma and array",
true, [ IsMagma, IsList ], 0, function( mag, A )
local n, s, a, b, e;
n := Length( A ); ## number of objects
s := Size( mag );
e := [1..s]; for a in A do if not ( IsList(a) and ( Length(a) = n ) ) then
return false; fi; for b in a do if not IsSubset( e, b ) then
return false; fi;
od;
od;
return true; end );
############################################################################# ## #M SubmagmaWithObjectsElementsTable( <mag>, <A> ) ##
InstallMethod( SubmagmaWithObjectsElementsTable, "for magma and array",
true, [ IsMagma, IsList ], 0, function( mag, A )
local t, done, B, C, T, n, s, i, j, k, Lij, Lik, Ljk, a, b, ab;
if not IsSubmagmaWithObjectsGeneratingTable( mag, A ) then
Error( "array A is not a generating table for a submagma over mag," ); fi;
T := MultiplicationTable( mag );
s := Size( mag );
n := Length( A ); done := false;
C := StructuralCopy( A );
t := 0; while not donedo
t := t+1;
B := StructuralCopy( C ); ## C stores all the elements for i in [1..n] do for j in [1..n] do
Lij := C[i][j]; for k in [1..n] do
Ljk := C[j][k]; for a in Lij do for b in Ljk do
ab := T[a][b];
C[i][k] := Union( C[i][k], [ab] );
od;
od;
od;
od;
od; done := ( B = C );
od;
return C; end );
############################################################################# ## #M SubmagmaWithObjectsByElementsTable( <mwo>, <A> ) . . for mwo and elements ##
InstallMethod( SubmagmaWithObjectsByElementsTable, "for objects, magma and table of generating elements", true,
[ IsSinglePiece, IsList ], 0, function( mwo, A )
local C, mag, obs, cf, isa, isc, swo;
obs := mwo!.objects;
mag := mwo!.magma;
C := SubmagmaWithObjectsElementsTable( mag, A ); ## ?? (23/04/10) cf := mwo!.eltsfam;
cf := IsMagmaWithObjectsFamily;
isa := IsAssociative( mag );
isc := IsCommutative( mag );
swo := rec( objects := obs, magma := mag, table := C );
ObjectifyWithAttributes( swo,
NewType( cf, IsSubmagmaWithObjectsTableRep ),
ParentAttr, mwo,
IsAssociative, IsAssociative( mag ),
IsCommutative, IsCommutative( mag ),
IsFinite, IsFinite( mag ),
IsSinglePieceDomain, true ); #? (13/10/08) still need to set GeneratorsOfMagmaWithObjects ??
return swo; end );
############################################################################# ## #M PrintObj( <swo> ) . . . . . for submagma with objects and elements table ##
InstallMethod( PrintObj, "for a submagma with objects and elements table",
true, [ IsSubmagmaWithObjectsTableRep ], 0, function( M )
Print( "submagma with objects:-\n" );
Print( "objects = ", M!.objects, "\n" );
Print( " magma = ", M!.magma, "\n" );
Print( " table = ", M!.table, "\n" ); end );
############################################################################# ## #M Ancestor ##
InstallMethod( Ancestor, "method for a domain with objects",
true, [ IsDomainWithObjects ], 0, function( dom )
local found, d;
d := dom;
found := ( HasParent( d ) and ( Parent( d ) = d ) ); while not found do if not HasParent( d ) then
return fail; else
d := Parent( d );
found := ( Parent( d ) = d ); fi;
od;
return d; end );
############################################################################# ## #M Iterator( <mwo> ) . . . . iterator for a single piece magma with objects ##
InstallMethod( Iterator, "for a single piece magma with objects",
[ IsSinglePiece ], function( mwo )
return IteratorByFunctions( rec(
IsDoneIterator := function( iter )
return ( IsDoneIterator( iter!.magmaIterator )
and ( iter!.tpos = iter!.len )
and ( iter!.hpos = iter!.len ) ); end,
NextIterator := function( iter ) if ( iter!.tpos = 0 ) then
iter!.melt := NextIterator( iter!.magmaIterator );
iter!.tpos := 1;
iter!.hpos := 1; elif ((iter!.tpos = iter!.len) and (iter!.hpos = iter!.len)) then
iter!.melt := NextIterator( iter!.magmaIterator );
iter!.tpos := 1;
iter!.hpos := 1; elif ( iter!.hpos = iter!.len ) then
iter!.hpos := 1;
iter!.tpos := iter!.tpos + 1; else
iter!.hpos := iter!.hpos + 1; fi; if ( HasIsDirectProductWithCompleteDigraph( mwo )
and IsDirectProductWithCompleteDigraph( mwo ) ) then
return Arrow( mwo, iter!.melt,
iter!.obs[iter!.tpos], iter!.obs[iter!.hpos] ); else
return fail; fi; end,
ShallowCopy := iter ->
rec( magmaIterator := ShallowCopy( iter!.magmaIterator ),
melt := iter!.melt,
obs := iter!.obs,
len := iter!.len,
tpos := iter!.tpos,
hpos := iter!.hpos ),
magmaIterator := Iterator( mwo!.magma ),
melt := 0,
obs := mwo!.objects,
len := Length( mwo!.objects ),
tpos := 0,
hpos := 0 ) ); end );
InstallMethod( Iterator, "generic method for a magma with objects",
[ IsMagmaWithObjects ], function( mwo )
return IteratorByFunctions( rec(
IsDoneIterator := function( iter )
return ( IsDoneIterator( iter!.mwoIterator )
and ( iter!.cpos = iter!.len ) ); end,
NextIterator := function( iter ) if IsDoneIterator( iter!.mwoIterator ) then
iter!.cpos := iter!.cpos + 1;
iter!.mwoIterator :=
Iterator( iter!.pieces[iter!.cpos] ); fi;
return NextIterator( iter!.mwoIterator ); end,
ShallowCopy := iter ->
rec( pieces := iter!.pieces,
len := iter!.len,
mwoIterator := ShallowCopy( iter!.mwoIterator ),
cpos := iter!.cpos ),
pieces := Pieces( mwo ),
len := Length( Pieces( mwo ) ),
mwoIterator := Iterator( Pieces( mwo )[1] ),
cpos := 1 ) ); end );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.