############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Thomas Breuer. ## ## Copyright of GAP belongs to its developers, whose names are too numerous ## to list here. Please refer to the COPYRIGHT file for details. ## ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This file contains generic methods for magmas. ##
InstallMethod( PrintString, "for a magma with generators",
true,
[ IsMagma and HasGeneratorsOfMagma ], 0, function( M )
return STRINGIFY( "Magma( ", GeneratorsOfMagma( M ), " )" ); end );
InstallMethod( PrintString, "for a magma-with-one with generators",
true,
[ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], 0, function( M ) if IsEmpty( GeneratorsOfMagmaWithOne( M ) ) then
return STRINGIFY("MagmaWithOne( ", One( M ), " )" ); else
return STRINGIFY( "MagmaWithOne( ", GeneratorsOfMagmaWithOne( M ), " )" ); fi; end );
InstallMethod( PrintString, "for a magma-with-inverses with generators",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0, function( M ) if IsEmpty( GeneratorsOfMagmaWithInverses( M ) ) then
return STRINGIFY("MagmaWithInverses( ", One( M ), " )" ); else
return STRINGIFY("MagmaWithInverses( ", GeneratorsOfMagmaWithInverses(M), " )" ); fi; end );
############################################################################# ## #M ViewObj( <M> ) . . . . . . . . . . . . . . . . . . . . . . view a magma ##
InstallMethod( ViewString, "for a magma",
true,
[ IsMagma ], 0, function( M )
return "<magma>"; end );
InstallMethod( ViewString, "for a magma with generators",
true,
[ IsMagma and HasGeneratorsOfMagma ], 0, function( M )
local nrgens;
nrgens := Length( GeneratorsOfMagma(M) );
return STRINGIFY( "<magma with ", Pluralize( nrgens, "generator" ), ">" ); end );
InstallMethod( ViewString, "for a magma-with-one with generators",
true,
[ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], 0, function( M )
local nrgens;
nrgens := Length( GeneratorsOfMagmaWithOne(M) ); if nrgens = 0then
return "<trivial magma-with-one>" ; fi;
return STRINGIFY( "<magma-with-one with ",
Pluralize( nrgens, "generator" ), ">" ); end );
InstallMethod( ViewString, "for a magma-with-inverses with generators",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0, function( M )
local nrgens;
nrgens := Length( GeneratorsOfMagmaWithInverses( M ) ); if nrgens = 0then
return "<trivial magma-with-inverses>"; fi;
return STRINGIFY( "<magma-with-inverses with ",
Pluralize( nrgens, "generator" ), ">" ); end );
############################################################################# ## #M IsTrivial( <M> ) . . . . . . . . . . . . test whether a magma is trivial ##
InstallImmediateMethod( IsTrivial,
IsMagmaWithOne and HasGeneratorsOfMagmaWithOne, 0, function( M ) if IsEmpty( GeneratorsOfMagmaWithOne( M ) ) then
return true; else
TryNextMethod(); fi; end );
InstallMethod( IsTrivial,
[IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses], 0, function( M ) if IsEmpty( GeneratorsOfMagmaWithInverses( M ) ) then
return true; else
TryNextMethod(); fi; end );
############################################################################# ## #M IsAssociative( <M> ) . . . . . test whether a collection is associative ##
InstallMethod( IsAssociative, "for a collection",
[ IsCollection ], function( M )
local elms, # list of elements
i, j, k; # loop variables
# Test associativity for all triples of elements.
elms:= Enumerator( M ); for i in elms do for j in elms do for k in elms do if ( i * j ) * k <> i * ( j * k ) then
return false; fi;
od;
od;
od;
# No associativity test failed.
return true; end );
############################################################################# ## #M IsCommutative( <M> ) . . . . . test whether a collection is commutative ##
InstallImmediateMethod( IsCommutative,
IsMagma and IsAssociative and HasGeneratorsOfMagma, 0, function( M ) if Length( GeneratorsOfMagma( M ) ) = 1then
return true; else
TryNextMethod(); fi; end );
InstallImmediateMethod( IsCommutative,
IsMagmaWithOne and IsAssociative and HasGeneratorsOfMagmaWithOne, 0, function( M ) if Length( GeneratorsOfMagmaWithOne( M ) ) = 1then
return true; else
TryNextMethod(); fi; end );
# This used to be an immediate method. It was replaced by an ordinary # method, as the filter is now set when creating groups.
InstallMethod( IsCommutative,true,
[IsMagmaWithInverses and IsAssociative
and HasGeneratorsOfMagmaWithInverses], 0, function( M ) if Length( GeneratorsOfMagmaWithInverses( M ) ) = 1then
return true; else
TryNextMethod(); fi; end );
InstallMethod( IsCommutative, "for a collection",
[ IsCollection ], function( C )
local elms, n, x, y, i, j;
elms:= Enumerator( C );
n := Length( elms ); for i in [ 1 .. n ] do for j in [ i + 1 .. n ] do
x := elms[ i ];
y := elms[ j ]; if x * y <> y * x then
return false; fi;
od;
od;
return true; end);
InstallMethod( IsCommutative, "for an associative magma",
true,
[ IsMagma and IsAssociative ], 0,
IsCommutativeFromGenerators( GeneratorsOfMagma ) );
InstallMethod( IsCommutative, "for an associative magma with one",
true,
[ IsMagmaWithOne and IsAssociative ], 0,
IsCommutativeFromGenerators( GeneratorsOfMagmaWithOne ) );
InstallMethod( IsCommutative, "for an associative magma with inverses",
true,
[ IsMagmaWithInverses and IsAssociative ], 0,
IsCommutativeFromGenerators( GeneratorsOfMagmaWithInverses ) );
############################################################################# ## #P IsFinitelyGeneratedMagma( <M> ) . . . . test whether a magma is fin. gen. ##
InstallMethod( IsFinitelyGeneratedMagma,
[ IsMagma and HasGeneratorsOfMagma ], function( M ) if IsFinite( GeneratorsOfMagma( M ) ) then
return true; fi;
TryNextMethod(); end );
InstallMethod( IsFinitelyGeneratedMagma,
[ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], function( M ) if IsFinite( GeneratorsOfMagmaWithOne( M ) ) then
return true; fi;
TryNextMethod(); end );
InstallMethod( IsFinitelyGeneratedMagma,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], function( M ) if IsFinite( GeneratorsOfMagmaWithInverses( M ) ) then
return true; fi;
TryNextMethod(); end );
############################################################################# ## #M Centralizer( <M>, <elm> ) . . . . . centralizer of an element in a magma #M Centralizer( <M>, <N> ) . . . . . . . . centralizer of a magma in a magma ##
InstallMethod( CentralizerOp, "for a magma, and a mult. element",
IsCollsElms,
[ IsMagma, IsMultiplicativeElement ], 0, function( M, obj )
return Filtered( AsList( M ), x -> x * obj = obj * x ); end );
InstallMethod( CentralizerOp, "for a commutative magma, and a mult. element",
IsCollsElms,
[ IsMagma and IsCommutative, IsMultiplicativeElement ],
SUM_FLAGS, # for commutative magmas this is best possible function( M, obj ) if obj in M then
return M; else
TryNextMethod(); fi; end );
InstallMethod( CentralizerOp, "for two magmas",
IsIdenticalObj,
[ IsMagma, IsMagma ], 0, function( M, N )
return Filtered( M, x -> ForAll( N, y -> x * y = y * x ) ); end );
InstallMethod( CentralizerOp, "for two magmas, the first being commutative",
IsIdenticalObj,
[ IsMagma and IsCommutative, IsMagma ],
SUM_FLAGS, # for commutative magmas this is best possible function( M, N ) if IsSubset( M, N ) then
return M; else
TryNextMethod(); fi; end );
InstallOtherMethod( CentralizerOp, "dummy to ignore optional third argument",
true,
[ IsMagma, IsObject,IsObject ], 0, function( M, obj, x )
return CentralizerOp( M, obj ); end );
############################################################################# ## #M Centre( <M> ) . . . . . . . . . . . . . . . . . . . . . centre of a magma ##
InstallMethod( Centre, "generic method for a magma",
[ IsMagma ], function( M )
local T;
T:= Tuples( M, 2 );
M:= Filtered( M, x -> ForAll( M, y -> x * y = y * x ) and
ForAll( T, p -> (p[1]*p[2])*x = p[1]*(p[2]*x) and
(p[1]*x)*p[2] = p[1]*(x*p[2]) and
(x*p[1])*p[2] = x*(p[1]*p[2]) ) ); if IsDomain( M ) then
Assert( 1, IsAbelian( M ) );
SetIsAbelian( M, true ); fi;
return M; end );
InstallMethod( Centre, "for an associative magma",
[ IsMagma and IsAssociative ], function( M )
M:= Centralizer( M, M ); if IsDomain( M ) then
Assert( 1, IsAbelian( M ) );
SetIsAbelian( M, true ); fi;
return M; end );
InstallMethod( Centre, "for an associative and commutative magma",
[ IsMagma and IsAssociative and IsCommutative ],
SUM_FLAGS, # for commutative magmas this is best possible
IdFunc );
############################################################################# ## #A Idempotents( <M> ) . . . . . . . . . . . . . . . . idempotents of a magma ##
InstallMethod(Idempotents,"for finite magmas", true,
[IsMagma], 0, function(M)
local I, m;
I := [];
for m in AsList(M) do if m*m=m then
Add(I,m); fi;
od;
return I; end);
# no argument given, error
Error("usage: Magma(<gens>), Magma(<Fam>,<gens>)"); end );
############################################################################# ## #F Submagma( <M>, <gens> ) . . . . . . . submagma of <M> generated by <gens> ##
InstallGlobalFunction( Submagma, function( M, gens )
if not IsMagma( M ) then
Error( "<M> must be a magma" ); elif IsEmpty( gens ) then
return SubmagmaNC( M, gens ); elif not IsHomogeneousList(gens) then
Error( "<gens> must be a homogeneous list of elements" ); elif not IsIdenticalObj( FamilyObj(M), FamilyObj(gens) ) then
Error( "families of <gens> and <M> are different" ); fi; if not ForAll( gens, x -> x in M ) then
Error( "<gens> must be elements in <M>" ); fi;
return SubmagmaNC( M, gens ); end );
############################################################################# ## #F SubmagmaNC( <M>, <gens> ) ## ## Note that `SubmagmaNC' is allowed to call `Objectify' ## in the case that <gens> is empty. ##
InstallGlobalFunction( SubmagmaNC, function( M, gens )
local K, S;
if IsEmpty( gens ) then
K:= NewType( FamilyObj(M),
IsMagma
and IsEmpty
and IsAttributeStoringRep );
S:= Objectify( K, rec() );
SetGeneratorsOfMagma( S, [] ); else
S:= MagmaByGenerators(gens); fi;
SetParent( S, M );
return S; end );
# list of generators if Length( arg ) = 1 and IsList( arg[1] ) and 0 < Length( arg[1] ) then
return MagmaWithOneByGenerators( arg[1] );
# family plus list of generators elif Length( arg ) = 2 and IsFamily( arg[1] ) and IsList( arg[2] ) then
return MagmaWithOneByGenerators( arg[1], arg[2] );
# no argument given, error
Error("usage: MagmaWithOne(<gens>), MagmaWithOne(<Fam>,<gens>)"); end );
############################################################################# ## #F SubmagmaWithOne( <M>, <gens> ) . submagma-with-one of <M> gen. by <gens> ##
InstallGlobalFunction( SubmagmaWithOne, function( M, gens )
if not IsMagmaWithOne( M ) then
Error( "<M> must be a magma-with-one" ); elif IsEmpty( gens ) then
return SubmagmaWithOneNC( M, gens ); elif not IsHomogeneousList(gens) then
Error( "<gens> must be a homogeneous list of elements" ); elif not IsIdenticalObj( FamilyObj(M), FamilyObj(gens) ) then
Error( "families of <gens> and <M> are different" ); fi; if not ForAll( gens, x -> x in M ) then
Error( "<gens> must be elements in <M>" ); fi;
return SubmagmaWithOneNC( M, gens ); end );
############################################################################# ## #F SubmagmaWithOneNC( <M>, <gens> ) ## ## Note that `SubmagmaWithOneNC' is allowed to call `Objectify' ## in the case that <gens> is empty. ## ## Furthermore note that a trivial submagma-with-one is automatically ## a group. ##
InstallGlobalFunction( SubmagmaWithOneNC, function( M, gens )
local K, S;
if IsEmpty( gens ) then
K:= NewType( FamilyObj(M),
IsMagmaWithInverses
and IsTrivial
and IsAttributeStoringRep );
S:= Objectify( K, rec() );
SetGeneratorsOfMagmaWithInverses( S, [] );
SetSize( S, 1 ); #T should be unnecessary since `IsTrivial' implies a good `Size' method else
S:= MagmaWithOneByGenerators(gens); fi;
SetParent( S, M );
return S; end );
# list of generators if Length( arg ) = 1 and IsList( arg[1] ) and 0 < Length( arg[1] ) then
return MagmaWithInversesByGenerators( arg[1] );
# family plus list of generators elif Length( arg ) = 2 and IsFamily( arg[1] ) and IsList( arg[2] ) then
return MagmaWithInversesByGenerators( arg[1], arg[2] );
# no argument given, error
Error("usage: MagmaWithInverses(<gens>), ", "MagmaWithInverses(<Fam>,<gens>)"); end );
############################################################################# ## #F SubmagmaWithInverses( <M>, <gens> ) #F . . . . . . . submagma-with-inv. of <M> gen. by <gens> ##
InstallGlobalFunction( SubmagmaWithInverses, function(arg)
local M,gens,S;
M:=arg[1]; if not IsMagmaWithInverses( M ) then
Error( "<M> must be a magma-with-inverses" ); fi; if Length(arg)=1then
S:=Objectify(NewType( FamilyObj(M),
IsMagmaWithInverses
and IsAttributeStoringRep), rec() );
SetParent(S,M);
return S; else
gens:=arg[2]; fi; if IsEmpty( gens ) then
return SubmagmaWithInversesNC( M, gens ); elif not IsHomogeneousList(gens) then
Error( "<gens> must be a homogeneous list of elements" ); elif not IsIdenticalObj( FamilyObj(M), FamilyObj(gens) ) then
Error( "families of <gens> and <M> are different" ); fi; if not ForAll( gens, x -> x in M ) then
Error( "<gens> must be elements in <M>" ); fi;
return SubmagmaWithInversesNC( M, gens ); end );
############################################################################# ## #F SubmagmaWithInversesNC( <M>, <gens> ) ## ## Note that `SubmagmaWithInversesNC' is allowed to call `Objectify' ## in the case that <gens> is empty. ##
InstallGlobalFunction( SubmagmaWithInversesNC, function( M, gens )
local K, S;
if IsEmpty( gens ) then
K:= NewType( FamilyObj(M),
IsMagmaWithInverses
and IsTrivial
and IsAttributeStoringRep
and HasGeneratorsOfMagmaWithInverses);
S:=rec();
ObjectifyWithAttributes(S, K, GeneratorsOfMagmaWithInverses, [] ); else
S:= MagmaWithInversesByGenerators(gens); fi;
SetParent( S, M );
return S; end );
############################################################################# ## #M MagmaByGenerators( <gens> ) . . . . . . . . . . . . . . for a collection ##
InstallMethod( MagmaByGenerators, "for collection",
true,
[ IsCollection ] , 0, function( gens )
local M;
M:= Objectify( NewType( FamilyObj( gens ),
IsMagma and IsAttributeStoringRep ),
rec() );
SetGeneratorsOfMagma( M, AsList( gens ) );
return M; end );
############################################################################# ## #M MagmaByGenerators( <Fam>, <gens> ) . . . . . . . . . for family and list ##
InstallOtherMethod( MagmaByGenerators, "for family and list",
true,
[ IsFamily, IsList ], 0, function( family, gens )
local M; if not ( IsEmpty(gens) or IsIdenticalObj( FamilyObj(gens), family ) ) then
Error( "<family> and family of <gens> do not match" ); fi;
M:= Objectify( NewType( family,
IsMagma and IsAttributeStoringRep ),
rec() );
SetGeneratorsOfMagma( M, AsList( gens ) );
return M; end );
############################################################################# ## #M MagmaWithOneByGenerators( <gens> ) . . . . . . . . . . for a collection ##
InstallMethod( MagmaWithOneByGenerators, "for collection",
true,
[ IsCollection ] , 0, function( gens )
local M;
M:= Objectify( NewType( FamilyObj( gens ),
IsMagmaWithOne and IsAttributeStoringRep ),
rec() );
SetGeneratorsOfMagmaWithOne( M, AsList( gens ) );
return M; end );
############################################################################# ## #M MagmaWithOneByGenerators( <Fam>, <gens> ) . . . . . . for family and list ##
InstallOtherMethod( MagmaWithOneByGenerators, "for family and list",
true,
[ IsFamily, IsList ], 0, function( family, gens )
local M; if not ( IsEmpty(gens) or IsIdenticalObj( FamilyObj(gens), family ) ) then
Error( "<family> and family of <gens> do not match" ); fi;
M:= Objectify( NewType( family,
IsMagmaWithOne and IsAttributeStoringRep ),
rec() );
SetGeneratorsOfMagmaWithOne( M, AsList( gens ) );
return M; end );
############################################################################# ## #M MagmaWithInversesByGenerators( <gens> ) . . . . . . . . for a collection ##
BindGlobal( "MakeMagmaWithInversesByFiniteGenerators", function(family,gens)
local M;
############################################################################# ## #M MagmaWithInversesByGenerators( <Fam>, <gens> ) . . . for family and list ##
InstallOtherMethod( MagmaWithInversesByGenerators, "for family and list",
true, [ IsFamily, IsList and IsFinite], 0, function( family, gens ) if not ( IsEmpty(gens) or IsIdenticalObj( FamilyObj(gens), family ) ) then
Error( "<family> and family of <gens> do not match" ); fi;
return MakeMagmaWithInversesByFiniteGenerators(family,gens); end );
############################################################################# ## #M TrivialSubmagmaWithOne( <M> ) . . . . . . . . . . . for a magma-with-one ##
InstallMethod( TrivialSubmagmaWithOne, "for magma-with-one",
true,
[ IsMagmaWithOne ], 0, # use the `Parent' to avoid too many nonmaximal parents
M -> SubmagmaWithOneNC( Parent(M), [] ) );
############################################################################# ## #M GeneratorsOfMagma( <M> ) ## ## If nothing special is known about the magma <M> we delegate to ## `GeneratorsOfDomain'. ## ## If <M> is in fact a magma-with-one or a magma-with-inverses with known ## generators of one of these kinds then magma generators can be computed ## from them. ## ## Adding identity and inverses can be avoided if the elements in the magma ## are known to have finite order; ## this holds for example for permutation groups. ##
InstallMethod( GeneratorsOfMagma, "generic method for a magma (take domain generators)",
true,
[ IsMagma ], 0,
GeneratorsOfDomain );
InstallMethod( GeneratorsOfMagma, "for a magma-with-one with known generators",
true,
[ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], 0, function(M)
local c;
c:=Concatenation( GeneratorsOfMagmaWithOne( M ), [ One(M) ] ); if CanEasilySortElements(One(M)) then
return Set(c); elif CanEasilyCompareElements(One(M)) then
return Unique(c); fi;
return c; end);
InstallMethod( GeneratorsOfMagma, "for a magma-with-inverses with known generators",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0, function(M)
local c;
c:=Concatenation( GeneratorsOfMagmaWithInverses( M ),
[ One( M ) ],
List( GeneratorsOfMagmaWithInverses( M ), Inverse ) ); if CanEasilySortElements(One(M)) then
return Set(c); elif CanEasilyCompareElements(One(M)) then
return Unique(c); fi;
return c; end);
InstallMethod( GeneratorsOfMagma, "for a magma-with-one with generators, all elms. of finite order",
true,
[ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne
and IsFiniteOrderElementCollection ], 0, function( M )
local gens;
gens:= GeneratorsOfMagmaWithOne( M ); if IsEmpty( gens ) then
return [ One( M ) ]; else
return gens; fi; end );
InstallMethod( GeneratorsOfMagma, "for a magma-with-inv. with gens., all elms. of finite order",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses
and IsFiniteOrderElementCollection ], 0, function( M )
local gens;
gens:= GeneratorsOfMagmaWithInverses( M ); if IsEmpty( gens ) then
return [ One( M ) ]; else
return gens; fi; end );
############################################################################# ## #M GeneratorsOfMagmaWithOne( <M> ) ## ## A known `GeneratorsOfMagma' value can be taken for ## `GeneratorsOfMagmaWithOne'. ## ## If <M> is in fact a magma-with-inverses with known ## generators of this kind then magma-with-one generators can be computed ## from them. ## ## Adding inverses can be avoided if the elements in the magma ## are known to have finite order; ## this holds for example for permutation groups. ##
InstallMethod( GeneratorsOfMagmaWithOne, "for a magma-with-one with known magma generators (take them)",
true,
[ IsMagmaWithOne and HasGeneratorsOfMagma ], 0,
GeneratorsOfMagma );
InstallMethod( GeneratorsOfMagmaWithOne, "for a magma-with-inverses with generators",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0, function(M)
local c;
c:=Concatenation( GeneratorsOfMagmaWithInverses( M ),
List( GeneratorsOfMagmaWithInverses( M ), Inverse ) ); if CanEasilySortElements(One(M)) then
return Set(c); elif CanEasilyCompareElements(One(M)) then
return Unique(c); fi;
return c; end);
InstallMethod( GeneratorsOfMagmaWithOne, "for a magma-with-inv. with gens., all elms. of finite order",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses
and IsFiniteOrderElementCollection ], 0,
GeneratorsOfMagmaWithInverses );
############################################################################# ## #M GeneratorsOfMagmaWithInverses( <M> ) ## ## A known `GeneratorsOfMagma' or `GeneratorsOfMagmaWithOne' value ## can be taken for `GeneratorsOfMagmaWithInverses'. ##
InstallMethod( GeneratorsOfMagmaWithInverses, "for a magma-with-inverses with known magma generators (take them)",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagma ], 0,
GeneratorsOfMagma );
InstallMethod( GeneratorsOfMagmaWithInverses, "for a magma-with-inverses with known magma-with-one gen.s (take them)",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithOne ], 0,
GeneratorsOfMagmaWithOne );
############################################################################# ## #M Representative( <M> ) . . . . . . . . . . . . . . one element of a magma ##
InstallMethod( Representative, "for magma with generators",
true,
[ IsMagma and HasGeneratorsOfMagma ], 0,
RepresentativeFromGenerators( GeneratorsOfMagma ) );
InstallMethod( Representative, "for magma-with-one with generators",
true,
[ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], 0,
RepresentativeFromGenerators( GeneratorsOfMagmaWithOne ) );
InstallMethod( Representative, "for magma-with-inverses with generators",
true,
[ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0,
RepresentativeFromGenerators( GeneratorsOfMagmaWithInverses ) );
InstallMethod( Representative, "for magma-with-one with known one",
true,
[ IsMagmaWithOne and HasOne ], SUM_FLAGS,
One );
InstallMethod( Representative, "for magma-with-one with stored parent",
[ IsMagmaWithOne and HasParentAttr ], function( M ) if not IsIdenticalObj( M, Parent( M ) ) then
return One( Representative( Parent( M ) ) ); fi;
TryNextMethod(); end );
############################################################################# ## #M MultiplicativeNeutralElement( <M> ) . . . . . . . . . . . . . for a magma ##
InstallMethod( MultiplicativeNeutralElement, "for a magma",
true,
[ IsMagma ], 0, function( M )
local m; if IsFinite( M ) then for m in M do if ForAll( M, n -> n * m = n and m * n = n ) then
return m; fi;
od;
return fail; else
TryNextMethod(); fi; end );
############################################################################# ## ## HasMultiplicativeNeutralElement( <M> ) ## ## always true for a magma-with-one ##
InstallTrueMethod(HasMultiplicativeNeutralElement, IsMagmaWithOne);
############################################################################# ## #M MultiplicativeNeutralElement( <M> ) . . . . . . . . for a magma-with-one ##
InstallMethod(MultiplicativeNeutralElement, "for a magma-with-one",
true,
[HasMultiplicativeNeutralElement and IsMagmaWithOne], GETTER_FLAGS+1,
One );
InstallMethod(SetMultiplicativeNeutralElement, "for a magma-with-one",
true,
[IsMagma, IsBool], 0, function(m, b) if b<>fail then
TryNextMethod(); fi; end);
############################################################################# ## #M One( <M> ) . . . . . . . . . . . . . . . . . . . . . identity of a magma ##
InstallOtherMethod( One, "for a magma",
true,
[ IsMagma ], 0, function( M )
local one;
one:= One( Representative( M ) ); if one <> fail and one in M then
return one; else
return fail; fi; end );
InstallOtherMethod( One, "partial method for a magma-with-one (ask family)",
true,
[ IsMagmaWithOne ], 100, #T high priority? function( M )
M:= ElementsFamily( FamilyObj( M ) ); if HasOne( M ) then
return One( M ); else
TryNextMethod(); fi; end );
InstallOtherMethod( One, "for a magma-with-one that has a parent",
true,
[ IsMagmaWithOne and HasParent ], SUM_FLAGS, function( M ) if not IsIdenticalObj( M, Parent( M ) ) then
return One( Parent( M ) ); fi;
TryNextMethod(); end );
InstallOtherMethod( One, "for a magma-with-one",
true,
[ IsMagmaWithOne ], 0,
M -> One( Representative( M ) ) );
############################################################################# ## #M Enumerator( <M> ) . . . . . . . . . enumerator of trivial magma with one ##
BindGlobal( "EnumeratorOfTrivialMagmaWithOne",
M -> Immutable( [ One( M ) ] ) );
############################################################################# ## #F ClosureMagmaDefault( <M>, <elm> ) . . . . . closure of magma with element ##
BindGlobal( "ClosureMagmaDefault", function( M, elm )
local C, # closure of `M' with `obj', result
gens, # generators of `M'
gen, # generator of `M' or `C'
Celements, # intermediate list of elements
len; # current number of elements
gens:= GeneratorsOfMagma( M );
# try to avoid adding an element to a magma that already contains it if elm in gens
or ( HasAsSSortedList( M ) and elm in AsSSortedList( M ) ) then
return M; fi;
# make the closure magma
gens:= Concatenation( gens, [ elm ] );
C:= MagmaByGenerators( gens );
UseSubsetRelation( C, M );
# if the elements of <M> are known then extend this list # (multiply each element from the left and right with the new # generator, and then multiply with all elements until the # list becomes stable) if HasAsSSortedList( M ) then
Celements := ShallowCopy( AsSSortedList( M ) );
AddSet( Celements, elm );
UniteSet( Celements, Celements * elm );
UniteSet( Celements, elm * Celements );
repeat
len:= Length( Celements ); for gen in Celements do
UniteSet( Celements, Celements * gen );
UniteSet( Celements, gen * Celements );
od;
until len = Length( Celements );
############################################################################# ## #M Enumerator( <M> ) . . . . . . . . . . . . set of the elements of a magma ##
BindGlobal( "EnumeratorOfMagma", function( M )
local gens, # magma generators of <M>
H, # submagma of the first generators of <M>
gen; # generator of <M>
# The following code only does not work infinite magmas. if HasIsFinite( M ) and not IsFinite( M ) then
TryNextMethod(); fi;
# handle the case of an empty magma
gens:= GeneratorsOfMagma( M ); if IsEmpty( gens ) then
return []; fi;
# start with the empty magma and its element list
H:= Submagma( M, [] );
SetAsSSortedList( H, Immutable( [ ] ) );
# Add the generators one after the other. # We use a function that maintains the elements list for the closure. for gen in gens do
H:= ClosureMagmaDefault( H, gen );
od;
# return the list of elements
Assert( 2, HasAsSSortedList( H ) );
return AsSSortedList( H ); end );
InstallMethod( Enumerator, "generic method for a magma",
true,
[ IsMagma and IsAttributeStoringRep ], 0,
EnumeratorOfMagma );
############################################################################# ## #M IsCentral( <M>, <elm> ) ##
InstallMethod( IsCentral, "for a magma and an element",
IsCollsElms,
[ IsMagma, IsObject ], 0,
IsCentralElementFromGenerators( GeneratorsOfMagma ) );
InstallMethod( IsCentral, "for a magma-with-one and an element",
IsCollsElms,
[ IsMagmaWithOne, IsObject ], 0,
IsCentralElementFromGenerators( GeneratorsOfMagmaWithOne ) );
InstallMethod( IsCentral, "for a magma-with-inverses and an element",
IsCollsElms,
[ IsMagmaWithInverses, IsObject ], 0,
IsCentralElementFromGenerators( GeneratorsOfMagmaWithInverses ) );
############################################################################# ## #M IsSubset( <M>, <N> ) . . . . . . . . . . . . . . . . . . for two magmas ##
InstallMethod( IsSubset, "for two magmas",
IsIdenticalObj,
[ IsMagma, IsMagma ], 0, function( M, N )
return IsSubset( M, GeneratorsOfMagma( N ) ); end );
############################################################################# ## #M IsSubset( <M>, <N> ) . . . . . . . . . . . . . . for two magmas with one ##
InstallMethod( IsSubset, "for two magmas with one",
IsIdenticalObj,
[ IsMagmaWithOne, IsMagmaWithOne ], 0, function( M, N )
return IsSubset( M, GeneratorsOfMagmaWithOne( N ) ); end );
############################################################################# ## #M IsSubset( <M>, <N> ) . . . . . . . . . . . for two magmas with inverses ##
InstallMethod( IsSubset, "for two magmas with inverses",
IsIdenticalObj,
[ IsMagmaWithInverses, IsMagmaWithInverses ], 0, function( M, N )
return IsSubset( M, GeneratorsOfMagmaWithInverses( N ) ); end );
############################################################################# ## #M AsMagma( <D> ) . . . . . . . . . . . . . . domain <D>, regarded as magma ##
InstallMethod( AsMagma, "for a magma (return the argument)",
true,
[ IsMagma ], 100,
IdFunc );
InstallMethod( AsMagma, "generic method for collections",
true,
[ IsCollection ], 0, function( D )
local M, L;
D := AsSSortedList( D );
L := ShallowCopy( D );
M := Submagma( MagmaByGenerators( D ), [] );
SubtractSet( L, AsSSortedList( M ) ); while not IsEmpty(L) do
M := ClosureMagmaDefault( M, L[1] );
SubtractSet( L, AsSSortedList( M ) );
od; if Length( AsSSortedList( M ) ) <> Length( D ) then
return fail; fi;
M := MagmaByGenerators( GeneratorsOfMagma( M ) );
SetAsSSortedList( M, D );
SetIsFinite( M, true );
SetSize( M, Length( D ) );
# return the magma
return M; end );
############################################################################# ## #M AsSubmagma( <G>, <U> ) ##
InstallMethod( AsSubmagma, "generic method for a domain and a collection",
IsIdenticalObj,
[ IsDomain, IsCollection ], 0, function( G, U )
local S; if not IsSubset( G, U ) then
return fail; fi; if IsMagma( U ) then
S:= SubmagmaNC( G, GeneratorsOfMagma( U ) ); else
S:= SubmagmaNC( G, AsList( U ) ); fi;
UseIsomorphismRelation( U, S );
UseSubsetRelation( U, S );
return S; end );
############################################################################# ## #M IsEmpty( <M> ) . . . . . . . . . . . . . . test whether a magma is empty ##
InstallMethod(IsEmpty, "for a magma with generators of magma",
[IsMagma and HasGeneratorsOfMagma],
M -> IsEmpty(GeneratorsOfMagma(M)));
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.