|
#############################################################################
##
## 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 the methods for magma rings and their elements.
##
## 1. methods for elements of magma rings in default representation
## 2. methods for free magma rings
## 3. methods for free left modules in magma ring modulo relations
## 4. methods for free magma rings modulo the span of a ``zero'' element
## 5. methods for groups of free magma ring elements
##
#T > Dear Craig,
#T >
#T > you asked for the implementation of magma rings modulo the identification
#T > of a ``zero element'' in the magma with zero.
#T >
#T > Here is my proposal for the basic stuff.
#T > (I have mainly taken the implementation of free magma rings plus the
#T > ideas used for `FreeLieAlgebra'.)
#T > It does not cover the vector space functionality (computing bases etc.),
#T > but I will rearrange the code in `mgmring.gd' and `mgmring.gi' in such a way
#T > that your generalized magma rings can use the mechanisms provided there.
#T get rid of `!.zeroRing'
#T (provide uniform access to the zero coeff. stored in the element;
#T this is also possible for polynomials etc.)
#T get rid of !.defaultType
#T get rid of !.oneMagma
#T best get rid of the families distinction for magma rings ?
#T (would solve problems such as relation between GroupRing( Integers, G )
#T and GroupRing( Rationals, G ))
#############################################################################
##
## 1. methods for elements of magma rings in default representation
##
#############################################################################
##
#R IsMagmaRingObjDefaultRep( <obj> )
##
## <#GAPDoc Label="IsMagmaRingObjDefaultRep">
## <ManSection>
## <Filt Name="IsMagmaRingObjDefaultRep" Arg='obj' Type='Representation'/>
##
## <Description>
## The default representation of a magma ring element is a list of length 2,
## at first position the zero coefficient, at second position a list with
## the coefficients at the even positions, and the magma elements at the
## odd positions, with the ordering as defined for the magma elements.
## <P/>
## It is assumed that arithmetic operations on magma rings produce only
## normalized elements.
## </Description>
## </ManSection>
## <#/GAPDoc>
##
if IsHPCGAP then
DeclareRepresentation( "IsMagmaRingObjDefaultRep", IsAtomicPositionalObjectRep,
[ 1, 2 ] );
else
DeclareRepresentation( "IsMagmaRingObjDefaultRep", IsPositionalObjectRep,
[ 1, 2 ] );
fi;
#############################################################################
##
#M NormalizedElementOfMagmaRingModuloRelations( <Fam>, <descr> )
##
## A free magma ring element is normalized if <descr> is sorted according to
## the involved magma elements.
## Thus normalization is trivial.
##
InstallMethod( NormalizedElementOfMagmaRingModuloRelations,
"for a family of elements in a *free* magma ring, and a list",
[ IsElementOfFreeMagmaRingFamily, IsList ],
function( Fam, descr )
return Immutable(descr);
end );
#############################################################################
##
#F FMRRemoveZero( <coeffs_and_words>, <zero> )
##
## removes all pairs from <coeffs_and_words> where the coefficient
## is <zero>.
## Note that <coeffs_and_words> is assumed to be sorted.
##
BindGlobal( "FMRRemoveZero", function( coeffs_and_words, zero )
local i, # offset of old and new position
lenw, # length of `words' and `coeff'
pos; # loop over the lists
i:= 0;
lenw:= Length( coeffs_and_words );
for pos in [ 2, 4 .. lenw ] do
if coeffs_and_words[ pos ] = zero then
i:= i + 2;
elif i < pos then
coeffs_and_words[ pos-i-1 ]:= coeffs_and_words[ pos-1 ];
coeffs_and_words[ pos-i ]:= coeffs_and_words[ pos ];
fi;
od;
for pos in [ lenw-i+1 .. lenw ] do
Unbind( coeffs_and_words[ pos ] );
od;
return coeffs_and_words;
end );
#############################################################################
##
#M ElementOfMagmaRing( <Fam>, <zerocoeff>, <coeff>, <words> )
##
## check whether <coeff> and <words> lie in the correct domains,
## and remove zeroes.
##
InstallMethod( ElementOfMagmaRing,
"for family, ring element, and two homogeneous lists",
[ IsFamily, IsRingElement, IsHomogeneousList, IsHomogeneousList ],
function( Fam, zerocoeff, coeff, words )
local rep, i, j;
# Check that the data is admissible.
if not IsBound( Fam!.defaultType ) then
TryNextMethod();
elif IsEmpty( coeff ) and IsEmpty( words ) then
return Objectify( Fam!.defaultType, [ zerocoeff, [] ] );
elif not IsIdenticalObj( FamilyObj( coeff ), Fam!.familyRing ) then
Error( "<coeff> are not all in the correct domain" );
elif not IsIdenticalObj( FamilyObj( words ), Fam!.familyMagma ) then
Error( "<words> are not all in the correct domain" );
elif Length( coeff ) <> Length( words ) then
Error( "<coeff> and <words> must have same length" );
fi;
# Make sure that the list of words is strictly sorted.
if not IsSSortedList( words ) then
words:= ShallowCopy( words );
coeff:= ShallowCopy( coeff );
SortParallel( words, coeff );
if not IsSSortedList( words ) then
j:= 1;
for i in [ 2 .. Length( coeff ) ] do
if words[i] = words[j] then
coeff[j]:= coeff[j] + coeff[i];
else
j:= j+1;
words[j]:= words[i];
coeff[j]:= coeff[i];
fi;
od;
for i in [ j+1 .. Length( coeff ) ] do
Unbind( words[i] );
Unbind( coeff[i] );
od;
fi;
fi;
# Create the default representation, and remove zeros.
rep:= [];
j:= 1;
for i in [ 1 .. Length( coeff ) ] do
if coeff[i] <> zerocoeff then
rep[ j ]:= words[i];
rep[ j+1 ]:= coeff[i];
j:= j+2;
fi;
od;
# Normalize the result.
rep:= NormalizedElementOfMagmaRingModuloRelations( Fam,
[ zerocoeff, rep ] );
# Return the result.
return Objectify( Fam!.defaultType, rep );
end );
#############################################################################
##
#M ZeroCoefficient( <elm> )
##
InstallMethod( ZeroCoefficient,
"for magma ring element in default repr.",
[ IsElementOfMagmaRingModuloRelations and IsMagmaRingObjDefaultRep ],
elm -> FamilyObj( elm )!.zeroRing );
#############################################################################
##
#M CoefficientsAndMagmaElements( <elm> )
##
InstallMethod( CoefficientsAndMagmaElements,
"for magma ring element in default repr.",
[ IsElementOfMagmaRingModuloRelations and IsMagmaRingObjDefaultRep ],
elm -> elm![2] );
#############################################################################
##
#M PrintObj( <elm> ) . . . . . . . . for magma ring element in default repr.
##
InstallMethod( PrintObj,
"for magma ring element",
[ IsElementOfMagmaRingModuloRelations ],
function( elm )
local coeffs_and_words,
i;
coeffs_and_words:= CoefficientsAndMagmaElements( elm );
for i in [ 1, 3 .. Length( coeffs_and_words ) - 3 ] do
Print( "(", coeffs_and_words[i+1], ")*", coeffs_and_words[i], "+" );
od;
i:= Length( coeffs_and_words );
if i = 0 then
Print( "<zero> of ..." );
else
Print( "(", coeffs_and_words[i], ")*", coeffs_and_words[i-1] );
fi;
end );
#############################################################################
##
#M String( <elm> ) . . . . . . . . for magma ring element in default repr.
##
InstallMethod( String,
"for magma ring element",
[ IsElementOfMagmaRingModuloRelations ],
function( elm )
local coeffs_and_words,s,i;
s:="";
coeffs_and_words:= CoefficientsAndMagmaElements( elm );
for i in [ 1, 3 .. Length( coeffs_and_words ) - 3 ] do
Append(s,Concatenation("(",String(coeffs_and_words[i+1]), ")*", String(coeffs_and_words[i]),
"+" ));
od;
i:= Length( coeffs_and_words );
if i = 0 then
Append(s, "<zero> of ..." );
else
Append(s, Concatenation("(", String(coeffs_and_words[i]), ")*",
String(coeffs_and_words[i-1]) ));
fi;
return s;
end );
#############################################################################
##
#M \=( <x>, <y> ) . . . . for two free magma ring elements in default repr.
##
InstallMethod( \=,
"for two free magma ring elements",
IsIdenticalObj,
[ IsElementOfMagmaRingModuloRelations,
IsElementOfMagmaRingModuloRelations ],
function( x, y )
return CoefficientsAndMagmaElements( x )
= CoefficientsAndMagmaElements( y );
end );
#############################################################################
##
#M \<( <x>, <y> ) . . . . for two free magma ring elements in default repr.
##
InstallMethod( \<,
"for two free magma ring elements",
IsIdenticalObj,
[ IsElementOfMagmaRingModuloRelations,
IsElementOfMagmaRingModuloRelations ],
function( x, y )
local i;
x:= CoefficientsAndMagmaElements( x );
y:= CoefficientsAndMagmaElements( y );
for i in [ 1 .. Minimum( Length( x ), Length( y ) ) ] do
if x[i] < y[i] then
return true;
elif y[i] < x[i] then
return false;
fi;
od;
return Length( x ) < Length( y );
end );
#############################################################################
##
#M \+( <x>, <y> ) . . . . . . for two magma ring elements in default repr.
##
InstallMethod( \+,
"for two magma ring elements",
IsIdenticalObj,
[ IsElementOfMagmaRingModuloRelations,
IsElementOfMagmaRingModuloRelations ],
function( x, y )
local F, sum, z;
F := FamilyObj( x );
z := ZeroCoefficient( x );
x := CoefficientsAndMagmaElements( x );
y := CoefficientsAndMagmaElements( y );
sum:= ZippedSum( x, y, z, [ \<, \+ ] );
sum:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, sum ] );
return Objectify( F!.defaultType, sum );
end );
#############################################################################
##
#M AdditiveInverseOp( <x> ) . . . . for magma ring element in default repr.
##
InstallMethod( AdditiveInverseOp,
"for magma ring element",
[ IsElementOfMagmaRingModuloRelations ],
function( x )
local ext, i, Fam, inv;
ext:= ShallowCopy( CoefficientsAndMagmaElements( x ) );
for i in [ 2, 4 .. Length( ext ) ] do
ext[i]:= AdditiveInverse( ext[i] );
od;
Fam:= FamilyObj( x );
inv:= NormalizedElementOfMagmaRingModuloRelations( Fam,
[ ZeroCoefficient( x ), ext ] );
return Objectify( Fam!.defaultType, inv );
end );
#############################################################################
##
#M \*( <x>, <y> ) . . . . . . for two magma ring elements in default repr.
##
InstallMethod( \*,
"for two magma ring elements",
IsIdenticalObj,
[ IsElementOfMagmaRingModuloRelations,
IsElementOfMagmaRingModuloRelations ],
function( x, y )
local F, prod, z;
F := FamilyObj( x );
z := ZeroCoefficient( x );
x := CoefficientsAndMagmaElements( x );
y := CoefficientsAndMagmaElements( y );
prod:= ZippedProduct( x, y, z, [ \*, \<, \+, \* ] );
prod:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, prod ] );
return Objectify( F!.defaultType, prod );
end );
#############################################################################
##
#M \*( x, r ) . . . . . . . . . . . for magma ring element and coefficient
##
## Note that multiplication with zero or zero divisors
## may cause zero coefficients in the result.
## So we must normalize the elements.
#T (But we can avoid the argument check)
#T Should these two aspects be treated separately in general?
#T Should multiplication with zero be avoided (store the zero)?
#T Should the nonexistence of zero divisors be known/used?
##
BindGlobal( "ElmTimesRingElm", function( x, y )
local F, i, prod, z;
F:= FamilyObj( x );
z:= ZeroCoefficient( x );
x:= ShallowCopy( CoefficientsAndMagmaElements( x ) );
for i in [ 2, 4 .. Length(x) ] do
x[i]:= x[i] * y;
od;
prod:= NormalizedElementOfMagmaRingModuloRelations( F,
[ z, FMRRemoveZero( x, z ) ] );
return Objectify( F!.defaultType, prod );
end );
InstallMethod( \*,
"for magma ring element, and ring element",
IsMagmaRingsRings,
[ IsElementOfMagmaRingModuloRelations, IsRingElement ],
ElmTimesRingElm );
InstallMethod( \*,
"for magma ring element, and rational",
[ IsElementOfMagmaRingModuloRelations, IsRat ],
ElmTimesRingElm );
#############################################################################
##
#M \*( <r>, <x> ) . . . . . . . . . for coefficient and magma ring element
#M \*( <r>, <x> ) . . . . . . . . . . . for integer and magma ring element
##
BindGlobal( "RingElmTimesElm", function( x, y )
local F, i, prod, z;
F:= FamilyObj( y );
z:= ZeroCoefficient( y );
y:= ShallowCopy( CoefficientsAndMagmaElements( y ) );
for i in [ 2, 4 .. Length(y) ] do
y[i]:= x * y[i];
od;
prod:= NormalizedElementOfMagmaRingModuloRelations( F,
[ z, FMRRemoveZero( y, z ) ] );
return Objectify( F!.defaultType, prod );
end );
InstallMethod( \*,
"for ring element, and magma ring element",
IsRingsMagmaRings,
[ IsRingElement, IsElementOfMagmaRingModuloRelations ],
RingElmTimesElm );
InstallMethod( \*,
"for rational, and magma ring element",
[ IsRat, IsElementOfMagmaRingModuloRelations ],
RingElmTimesElm );
#############################################################################
##
#M InverseOp( <x> ) . . . . . . . . for magma ring element in default repr.
##
InstallOtherMethod( InverseOp,
"for magma ring element",
[ IsElementOfMagmaRingModuloRelations ],
function( x )
local coeffs, inv1, inv2, one, R, B, T;
coeffs:= CoefficientsAndMagmaElements( x );
if IsEmpty( coeffs ) then
# The zero element is not invertible.
return fail;
elif Length( coeffs ) = 2 then
# Inverting a scalar multiple of a magma element
# means to invert the scalar and the magma element.
inv1:= Inverse( coeffs[1] );
if inv1 = fail then
return fail;
fi;
inv2:= Inverse( coeffs[2] );
if inv2 = fail then
return fail;
fi;
return Objectify( FamilyObj( x )!.defaultType,
[ ZeroCoefficient( x ), [ inv1, inv2 ] ] );
fi;
# An invertible element has an identity.
one:= One( x );
if one = fail then
return fail;
fi;
# Get the necessary coefficient ring,
# and a basis for the algebra spanned by `x'.
coeffs:= coeffs{ [ 2, 4 .. Length( coeffs ) ] };
if IsCyclotomicCollection( coeffs ) then
R:= DefaultField( coeffs );
else
R:= DefaultRing( coeffs );
fi;
B:= Basis( FLMLORByGenerators( R, [ x ] ) );
T:= StructureConstantsTable( B );
# If `one' is not in the algebra spanned by `x' then there is no inverse.
coeffs:= Coefficients( B, one );
if coeffs = fail then
return fail;
fi;
# Solve the equation system.
one:= QuotientFromSCTable( T, coeffs, Coefficients( B, x ) );
# If there is a solution then form the inverse.
if one <> fail then
one:= LinearCombination( B, one );
fi;
return one;
end );
#############################################################################
##
#M \* <m>, <x> ) . . . . . . . . for magma element and magma ring element
#M \*( <x>, <m> ) . . . . . . . . for magma ring element and magma element
##
InstallMethod( \*,
"for magma element and magma ring element",
IsMagmasMagmaRings,
[ IsMultiplicativeElement, IsElementOfMagmaRingModuloRelations ],
function( m, x )
local F, z;
F:= FamilyObj( x );
z:= ZeroCoefficient( x );
x:= ZippedProduct( [ m, One( z ) ],
CoefficientsAndMagmaElements( x ),
z,
[ \*, \<, \+, \* ] );
x:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, x ] );
return Objectify( F!.defaultType, x );
end );
InstallMethod( \*,
"for magma ring element and magma element",
IsMagmaRingsMagmas,
[ IsElementOfMagmaRingModuloRelations, IsMultiplicativeElement ],
function( x, m )
local F, z;
F:= FamilyObj( x );
z:= ZeroCoefficient( x );
x:= ZippedProduct( CoefficientsAndMagmaElements( x ),
[ m, One( z ) ],
z,
[ \*, \<, \+, \* ] );
x:= NormalizedElementOfMagmaRingModuloRelations( F,
[ z, x ] );
return Objectify( F!.defaultType, x );
end );
#############################################################################
##
#M \+( <m>, <x> ) . . . . . . . . for magma element and magma ring element
#M \+( <x>, <m> ) . . . . . . . . for magma ring element and magma element
##
InstallOtherMethod( \+,
"for magma element and magma ring element",
IsMagmasMagmaRings,
[ IsMultiplicativeElement, IsElementOfMagmaRingModuloRelations ],
function( m, x )
local F, z;
F:= FamilyObj( x );
z:= ZeroCoefficient( x );
x:= ZippedSum( [ m, One( z ) ],
CoefficientsAndMagmaElements( x ),
z, [ \<, \+ ] );
x:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, x ] );
return Objectify( F!.defaultType, x );
end );
InstallOtherMethod( \+,
"for magma ring element and magma element",
IsMagmaRingsMagmas,
[ IsElementOfMagmaRingModuloRelations, IsMultiplicativeElement ],
function( x, m )
local F, z;
F:= FamilyObj( x );
z:= ZeroCoefficient( x );
x:= ZippedSum( CoefficientsAndMagmaElements( x ),
[ m, One( z ) ],
z, [ \<, \+ ] );
x:= NormalizedElementOfMagmaRingModuloRelations( F, [ z, x ] );
return Objectify( F!.defaultType, x );
end );
#############################################################################
##
#M \-( <x>, <m> ) . . . . . . . . for magma ring element and magma element
#M \-( <m>, <x> ) . . . . . . . . for magma ring element and magma element
##
InstallOtherMethod( \-,
"for magma ring element and magma element",
IsMagmaRingsMagmas,
[ IsElementOfMagmaRingModuloRelations, IsMultiplicativeElement ],
function( x, m )
local F, z;
F:= FamilyObj( x );
z:= ZeroCoefficient( x );
return x - ElementOfMagmaRing( F, z, [ One( z ) ], [ m ] );
end );
InstallOtherMethod( \-,
"for magma ring element and magma element",
IsMagmasMagmaRings,
[ IsMultiplicativeElement, IsElementOfMagmaRingModuloRelations ],
function( m, x )
local F, z;
F:= FamilyObj( x );
z:= ZeroCoefficient( x );
return ElementOfMagmaRing( F, z, [ One( z ) ], [ m ] ) - x;
end );
#############################################################################
##
#M \/( x, r ) . . . . . . . . . . . for magma ring element and coefficient
##
BindGlobal( "ElmDivRingElm", function( x, y )
local F, i, z;
F:= FamilyObj( x );
z:= ZeroCoefficient( x );
x:= ShallowCopy( CoefficientsAndMagmaElements( x ) );
for i in [ 2, 4 .. Length(x) ] do
x[i]:= x[i] / y;
od;
return Objectify( F!.defaultType, [ z, x ] );
end );
InstallOtherMethod( \/,
"for magma ring element, and ring element",
IsMagmaRingsRings,
[ IsElementOfMagmaRingModuloRelations, IsRingElement ],
ElmDivRingElm );
InstallMethod( \/,
"for magma ring element, and integer",
[ IsElementOfMagmaRingModuloRelations, IsInt ],
ElmDivRingElm );
#############################################################################
##
#M OneOp( <elm> )
##
InstallMethod( OneOp,
"for magma ring element",
[ IsElementOfMagmaRingModuloRelations ],
function( elm )
local F, z;
F:= FamilyObj( elm );
if not IsBound( F!.oneMagma ) then
return fail;
fi;
z:= ZeroCoefficient( elm );
return Objectify( F!.defaultType, [ z, MakeImmutable([ F!.oneMagma, One( z ) ]) ] );
end );
#############################################################################
##
#M ZeroOp( <elm> )
##
InstallMethod( ZeroOp,
"for magma ring element",
[ IsElementOfMagmaRingModuloRelations ],
x -> Objectify( FamilyObj(x)!.defaultType,
[ ZeroCoefficient( x ), [] ] ) );
#############################################################################
##
## 2. methods for free magma rings
##
#############################################################################
##
#M IsGroupRing( <RM> ) . . . . . . . . . . . . . . . . . for free magma ring
##
InstallMethod( IsGroupRing,
"for free magma ring",
[ IsFreeMagmaRing ],
RM -> IsGroup( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M PrintObj( <MR> ) . . . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( PrintObj,
"for a free magma ring",
[ IsFreeMagmaRing ],
function( MR )
Print( "FreeMagmaRing( ", LeftActingDomain( MR ), ", ",
UnderlyingMagma( MR ), " )" );
end );
#############################################################################
##
#F FreeMagmaRing( <R>, <M> )
##
InstallGlobalFunction( FreeMagmaRing, function( R, M )
local filter, # implied filter of all elements in the new domain
F, # family of magma ring elements
one, # identity of `R'
zero, # zero of `R'
m, # one element of `M'
RM, # free magma ring, result
gens; # generators of the magma ring
# Check the arguments.
if not IsRing( R ) or One( R ) = fail then
Error( "<R> must be a ring with identity" );
fi;
# Construct the family of elements of our ring.
if IsMultiplicativeElementWithInverseCollection( M ) then
filter:= IsMultiplicativeElementWithInverse;
elif IsMultiplicativeElementWithOneCollection( M ) then
filter:= IsMultiplicativeElementWithOne;
else
filter:= IsMultiplicativeElement;
fi;
if IsAssociativeElementCollection( M ) and
IsAssociativeElementCollection( R ) then
filter:= filter and IsAssociativeElement;
fi;
F:= NewFamily( "FreeMagmaRingObjFamily",
IsElementOfFreeMagmaRing,
filter );
one:= One( R );
zero:= Zero( R );
F!.defaultType := NewType( F, IsMagmaRingObjDefaultRep );
F!.familyRing := FamilyObj( R );
F!.familyMagma := FamilyObj( M );
F!.zeroRing := zero;
#T no !!
# Set the characteristic.
if HasCharacteristic( R ) or HasCharacteristic( FamilyObj( R ) ) then
SetCharacteristic( F, Characteristic( R ) );
fi;
# Just taking `Representative( M )' doesn't work if generators are not
# yet computed (we need them anyway below).
m := GeneratorsOfMagma( M );
if Length(m) > 0 then
m := m[1];
else
m:= Representative( M );
fi;
if IsMultiplicativeElementWithOne( m ) then
F!.oneMagma:= One( m );
#T no !!
fi;
# Make the magma ring object.
if IsMagmaWithOne( M ) then
RM:= Objectify( NewType( CollectionsFamily( F ),
IsFreeMagmaRingWithOne
and IsAttributeStoringRep ),
rec() );
else
RM:= Objectify( NewType( CollectionsFamily( F ),
IsFreeMagmaRing
and IsAttributeStoringRep ),
rec() );
fi;
# Set the necessary attributes.
SetLeftActingDomain( RM, R );
SetUnderlyingMagma( RM, M );
# Deduce useful information.
if HasIsFinite( M ) then
SetIsFiniteDimensional( RM, IsFinite( M ) );
fi;
if HasIsAssociative( M ) then
if IsMagmaWithInverses( M ) then
SetIsGroupRing( RM, IsGroup( M ) );
fi;
if HasIsAssociative( R ) then
SetIsAssociative( RM, IsAssociative( R ) and IsAssociative( M ) );
fi;
fi;
if HasIsCommutative( R ) and HasIsCommutative( M ) then
SetIsCommutative( RM, IsCommutative( R ) and IsCommutative( M ) );
fi;
if HasIsWholeFamily( R ) and HasIsWholeFamily( M ) then
SetIsWholeFamily( RM, IsWholeFamily( R ) and IsWholeFamily( M ) );
fi;
# Construct the generators.
# To get meaningful generators,
# we have to handle the case that the magma is trivial.
if IsMagmaWithOne( M ) then
gens:= GeneratorsOfMagmaWithOne( M );
SetGeneratorsOfLeftOperatorRingWithOne( RM,
List( gens,
x -> ElementOfMagmaRing( F, zero, [ one ], [ x ] ) ) );
if IsEmpty( gens ) then
SetGeneratorsOfLeftOperatorRing( RM,
[ ElementOfMagmaRing( F, zero, [ one ], [ One( M ) ] ) ] );
fi;
SetOne(F, One(RM));
else
SetGeneratorsOfLeftOperatorRing( RM,
List( GeneratorsOfMagma( M ),
x -> ElementOfMagmaRing( F, zero, [ one ], [ x ] ) ) );
fi;
SetZero(F, Zero(RM));
# Return the ring.
return RM;
end );
#############################################################################
##
#F GroupRing( <R>, <G> )
##
InstallGlobalFunction( GroupRing, function( R, G )
if not IsGroup( G ) then
Error( "<G> must be a group" );
fi;
R:= FreeMagmaRing( R, G );
SetIsGroupRing( R, true );
return R;
end );
#############################################################################
##
#M AugmentationIdeal( <RG> ) . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( AugmentationIdeal,
"for a free magma ring",
[ IsFreeMagmaRing ],
function( RG )
local one, G, gens, I;
one:= One( RG );
if one = fail then
TryNextMethod();
fi;
G:= UnderlyingMagma( RG );
gens:= List( GeneratorsOfMagma( G ), g -> g - one );
I:= TwoSidedIdealByGenerators( RG, gens );
SetGeneratorsOfAlgebra( I, gens );
return I;
end );
#############################################################################
##
#R IsCanonicalBasisFreeMagmaRingRep( <B> )
##
DeclareRepresentation( "IsCanonicalBasisFreeMagmaRingRep",
IsCanonicalBasis and IsAttributeStoringRep,
[ "zerovector" ] );
#############################################################################
##
#M Coefficients( <B>, <v> ) . . . . . . for canon. basis of free magma ring
##
InstallMethod( Coefficients,
"for canon. basis of a free magma ring, and a vector",
IsCollsElms,
[ IsCanonicalBasisFreeMagmaRingRep, IsElementOfFreeMagmaRing ],
function( B, v )
local coeffs,
data,
elms,
i;
data:= CoefficientsAndMagmaElements( v );
coeffs:= ShallowCopy( B!.zerovector );
elms:= EnumeratorSorted( UnderlyingMagma( UnderlyingLeftModule( B ) ) );
for i in [ 1, 3 .. Length( data )-1 ] do
coeffs[ Position( elms, data[i] ) ]:= data[i+1];
od;
return coeffs;
end );
#############################################################################
##
#M Basis( <RM> ) . . . . . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( Basis,
"for a free magma ring (delegate to `CanonicalBasis')",
[ IsFreeMagmaRing ], CANONICAL_BASIS_FLAGS,
CanonicalBasis );
#############################################################################
##
#M CanonicalBasis( <RM> ) . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( CanonicalBasis,
"for a free magma ring",
[ IsFreeMagmaRing ],
function( RM )
local B, one, zero, F;
F:= ElementsFamily( FamilyObj( RM ) );
if not IsBound( F!.defaultType ) then
TryNextMethod();
fi;
one := One( LeftActingDomain( RM ) );
zero := Zero( LeftActingDomain( RM ) );
B:= Objectify( NewType( FamilyObj( RM ),
IsFiniteBasisDefault
and IsCanonicalBasisFreeMagmaRingRep ),
rec() );
SetUnderlyingLeftModule( B, RM );
if IsFiniteDimensional( RM ) then
SetBasisVectors( B,
List( EnumeratorSorted( UnderlyingMagma( RM ) ),
x -> ElementOfMagmaRing( F, zero, [ one ], [ x ] ) ) );
B!.zerovector:= List( BasisVectors( B ), x -> zero );
MakeImmutable( B!.zerovector );
fi;
return B;
end );
#############################################################################
##
#M IsFinite( <RM> ) . . . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsFinite,
"for a free magma ring",
[ IsFreeMagmaRing ],
RM -> IsFinite( LeftActingDomain( RM ) )
and IsFinite( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M IsFiniteDimensional( <RM> ) . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsFiniteDimensional,
"for a free magma ring",
[ IsFreeMagmaRing ],
RM -> IsFinite( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M IsFiniteDimensional( <R> ) . . for left module of free magma ring elms.
##
InstallMethod( IsFiniteDimensional,
"for a left module of free magma ring elements",
[ IsFreeLeftModule and IsElementOfFreeMagmaRingCollection
and HasGeneratorsOfLeftOperatorRing ],
function( R )
local gens;
gens:= Concatenation( List( GeneratorsOfLeftOperatorRing( R ),
CoefficientsAndMagmaElements ) );
gens:= gens{ [ 1, 3 .. Length( gens ) - 1 ] };
if IsEmpty( gens ) or IsFinite( Magma( gens ) ) then
return true;
else
TryNextMethod();
fi;
end );
#############################################################################
##
#M Dimension( <RM> ) . . . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( Dimension,
"for a free magma ring",
[ IsFreeMagmaRing ],
RM -> Size( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M GeneratorsOfLeftModule( <RM> ) . . . . . . . . . . for a free magma ring
##
InstallMethod( GeneratorsOfLeftModule,
"for a free magma ring",
[ IsFreeMagmaRing ],
function( RM )
local F, one, zero;
if IsFiniteDimensional( RM ) then
F:= ElementsFamily( FamilyObj( RM ) );
one:= One( LeftActingDomain( RM ) );
zero:= Zero( LeftActingDomain( RM ) );
return List( Enumerator( UnderlyingMagma( RM ) ),
m -> ElementOfMagmaRing( F, zero, [ one ], [ m ] ) );
else
Error( "<RM> is not finite dimensional" );
fi;
end );
#############################################################################
##
#M Centre( <RM> ) . . . . . . . . . . . . . . . . . . . . for a group ring
##
## The centre of a group ring $RG$ of a finite group $G$ is the FLMLOR
## over the centre of $R$ generated by the conjugacy class sums in $G$.
##
## Note that this ring is clearly contained in the centre of $RG$.
## On the other hand, if an element $x = \sum_{g \in G} r_g g$ lies in the
## centre of $RG$ then $( r h ) \cdot x = x \cdot ( r h )$ for each
## $r \in R$ and $h \in G$.
## This means that
## $\sum_{g \in G} (r r_g ) ( h g ) = \sum_{g \in G} (r_g r ) ( g h )$,
## which means that for $k = h g_1 = g_2 h$, the coefficients on both sides,
## which are $r r_{g_1} = r r_{h^{-1} k}$ and $r_{g_2} r = r_{k h^{-1}} r$,
## must be equal.
## Setting $r = 1$ forces $r_g$ to be constant on conjugacy classes of $G$,
## and leaving $r$ arbitrary forces the coefficients to lie in the centre
## of $R$.
##
InstallMethod( Centre,
"for a group ring",
[ IsGroupRing ],
function( RG )
local F, # family of elements of `RG'
one, # identity of the coefficients ring
zero, # zero of the coefficients ring
gens, # list of (module) generators of the result
c, # loop over `ccl'
elms, # set of elements of a conjugacy class
coeff; # coefficients vector
if not IsFiniteDimensional( RG ) then
TryNextMethod();
fi;
F:= ElementsFamily( FamilyObj( RG ) );
one:= One( LeftActingDomain( RG ) );
zero:= Zero( LeftActingDomain( RG ) );
gens:= [];
for c in ConjugacyClasses( UnderlyingMagma( RG ) ) do
elms:= EnumeratorSorted( c );
coeff:= List( elms, x -> one );
Add( gens, ElementOfMagmaRing( F, zero, coeff, elms ) );
od;
c:= FLMLORWithOne( Centre( LeftActingDomain( RG ) ), gens, "basis" );
Assert( 1, IsAbelian( c ) );
SetIsAbelian( c, true );
return c;
end );
#############################################################################
##
#M \in( <r>, <RM> ) . . . . . . . . . for ring element and free magma ring
##
InstallMethod( \in,
"for ring element, and magma ring",
IsElmsColls,
[ IsElementOfMagmaRingModuloRelations, IsMagmaRingModuloRelations ],
function( r, RM )
r:= CoefficientsAndMagmaElements( r );
if ( ForAll( [ 2, 4 .. Length( r ) ],
i -> r[i] in LeftActingDomain( RM ) )
and ForAll( [ 1, 3 .. Length( r ) - 1 ],
i -> r[i] in UnderlyingMagma( RM ) ) ) then
return true;
elif IsFreeMagmaRing( RM ) then
return false;
else
TryNextMethod();
fi;
end );
#############################################################################
##
#M IsAssociative( <RM> ) . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsAssociative,
"for a free magma ring",
[ IsFreeMagmaRing ],
RM -> IsAssociative( LeftActingDomain( RM ) )
and IsAssociative( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M IsCommutative( <RM> ) . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsCommutative,
"for a free magma ring",
[ IsFreeMagmaRing ],
RM -> IsCommutative( LeftActingDomain( RM ) )
and IsCommutative( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M IsWholeFamily( <RM> ) . . . . . . . . . . . . . . . for a free magma ring
##
InstallMethod( IsWholeFamily,
"for a free magma ring",
[ IsFreeMagmaRing ],
RM -> IsWholeFamily( LeftActingDomain( RM ) )
and IsWholeFamily( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M GeneratorsOfRing( <RM> ) . . . . . . . . . . . . . for a free magma ring
#M GeneratorsOfRingWithOne( <RM> ) . . . . . for a free magma ring-with-one
##
## If the underlying magma has an identity and if we know ring generators
## for the ring <R>, we take the left operator ring generators together
## with the images of the ring generators under the natural embedding.
##
InstallMethod( GeneratorsOfRing,
"for a free magma ring",
[ IsFreeMagmaRing ],
function( RM )
local R, emb;
R:= LeftActingDomain( RM );
emb:= Embedding( R, RM );
if emb = fail then
TryNextMethod();
else
return Concatenation( GeneratorsOfLeftOperatorRing( RM ),
List( GeneratorsOfRing( R ),
r -> ImageElm( emb, r ) ) );
fi;
end );
InstallMethod( GeneratorsOfRingWithOne,
"for a free magma ring-with-one",
[ IsFreeMagmaRingWithOne ],
function( RM )
local R, emb;
R:= LeftActingDomain( RM );
emb:= Embedding( R, RM );
if emb = fail then
TryNextMethod();
else
return Concatenation( GeneratorsOfLeftOperatorRingWithOne( RM ),
List( GeneratorsOfRingWithOne( R ),
r -> ImageElm( emb, r ) ) );
fi;
end );
#############################################################################
##
#R IsEmbeddingRingMagmaRing( <R>, <RM> )
##
DeclareRepresentation( "IsEmbeddingRingMagmaRing",
IsSPGeneralMapping
and IsMapping
and IsInjective
and RespectsAddition
and RespectsZero
and RespectsMultiplication
and RespectsOne
and IsAttributeStoringRep,
[] );
#############################################################################
##
#M Embedding( <R>, <RM> ) . . . . . . . . . . . . . for ring and magma ring
##
InstallMethod( Embedding,
"for ring and magma ring",
IsRingCollsMagmaRingColls,
[ IsRing, IsFreeMagmaRing ],
function( R, RM )
local emb;
# Check that this is the right method.
if Parent( R ) <> LeftActingDomain( RM ) then
TryNextMethod();
elif One( UnderlyingMagma( RM ) ) = fail then
return fail;
fi;
# Make the mapping object.
emb := Objectify( TypeOfDefaultGeneralMapping( R, RM,
IsEmbeddingRingMagmaRing ),
rec() );
# Return the embedding.
return emb;
end );
InstallMethod( ImagesElm,
"for embedding of ring into magma ring, and ring element",
FamSourceEqFamElm,
[ IsEmbeddingRingMagmaRing, IsRingElement ],
function ( emb, elm )
local F;
F:= ElementsFamily( FamilyObj( Range( emb ) ) );
return [ ElementOfMagmaRing( F, Zero( elm ), [ elm ],
[ One( UnderlyingMagma( Range( emb ) ) ) ] ) ];
end );
InstallMethod( ImagesRepresentative,
"for embedding of ring into magma ring, and ring element",
FamSourceEqFamElm,
[ IsEmbeddingRingMagmaRing, IsRingElement ],
function ( emb, elm )
local F;
F:= ElementsFamily( FamilyObj( Range( emb ) ) );
return ElementOfMagmaRing( F, Zero( elm ), [ elm ],
[ One( UnderlyingMagma( Range( emb ) ) ) ] );
end );
InstallMethod( PreImagesElm,
"for embedding of ring into magma ring, and free magma ring element",
FamRangeEqFamElm,
[ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ],
function ( emb, elm )
local R, extrep;
R:= Range( emb );
extrep:= CoefficientsAndMagmaElements( elm );
if Length( extrep ) = 2
and extrep[1] = One( UnderlyingMagma( R ) ) then
return [ extrep[2] ];
else
return [];
fi;
end );
InstallMethod( PreImagesRepresentative,
"for embedding of ring into magma ring, and free magma ring element",
FamRangeEqFamElm,
[ IsEmbeddingRingMagmaRing, IsElementOfFreeMagmaRing ],
function ( emb, elm )
local R, extrep;
R:= Range( emb );
extrep:= CoefficientsAndMagmaElements( elm );
if Length( extrep ) = 2
and extrep[1] = One( UnderlyingMagma( R ) ) then
return extrep[2];
else
return fail;
fi;
end );
#############################################################################
##
#R IsEmbeddingMagmaMagmaRing( <M>, <RM> )
##
DeclareRepresentation( "IsEmbeddingMagmaMagmaRing",
IsSPGeneralMapping
and IsMapping
and IsInjective
and RespectsMultiplication
and IsAttributeStoringRep,
[] );
#############################################################################
##
#F Embedding( <M>, <RM> ) . . . . . . . . . . . . for magma and magma ring
##
InstallMethod( Embedding,
"for magma and magma ring",
IsMagmaCollsMagmaRingColls,
[ IsMagma, IsFreeMagmaRing ],
function( M, RM )
local emb;
# Check that this is the right method.
if not IsSubset( UnderlyingMagma( RM ), M ) then
TryNextMethod();
fi;
# Make the mapping object.
emb := Objectify( TypeOfDefaultGeneralMapping( M, RM,
IsEmbeddingMagmaMagmaRing ),
rec() );
if IsMagmaWithInverses( M ) then
SetRespectsInverses( emb, true );
elif IsMagmaWithOne( M ) then
SetRespectsOne( emb, true );
fi;
# Return the embedding.
return emb;
end );
InstallMethod( ImagesElm,
"for embedding of magma into magma ring, and mult. element",
FamSourceEqFamElm,
[ IsEmbeddingMagmaMagmaRing, IsMultiplicativeElement ],
function ( emb, elm )
local R, F;
R:= Range( emb );
F:= ElementsFamily( FamilyObj( R ) );
return [ ElementOfMagmaRing( F, Zero( LeftActingDomain( R ) ),
[ One( LeftActingDomain( R ) ) ], [ elm ] ) ];
end );
InstallMethod( ImagesRepresentative,
"for embedding of magma into magma ring, and mult. element",
FamSourceEqFamElm,
[ IsEmbeddingMagmaMagmaRing, IsMultiplicativeElement ],
function ( emb, elm )
local R, F;
R:= Range( emb );
F:= ElementsFamily( FamilyObj( R ) );
return ElementOfMagmaRing( F, Zero( LeftActingDomain( R ) ),
[ One( LeftActingDomain( R ) ) ], [ elm ] );
end );
InstallMethod( PreImagesElm,
"for embedding of magma into magma ring, and free magma ring element",
FamRangeEqFamElm,
[ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ],
function ( emb, elm )
local R, extrep;
R:= Range( emb );
extrep:= CoefficientsAndMagmaElements( elm );
if Length( extrep ) = 2
and extrep[2] = One( LeftActingDomain( R ) ) then
return [ extrep[1] ];
else
return [];
fi;
end );
InstallMethod( PreImagesRepresentative,
"for embedding of magma into magma ring, and free magma ring element",
FamRangeEqFamElm,
[ IsEmbeddingMagmaMagmaRing, IsElementOfFreeMagmaRing ],
function ( emb, elm )
local R, extrep;
R:= Range( emb );
extrep:= CoefficientsAndMagmaElements( elm );
if Length( extrep ) = 2
and extrep[2] = One( LeftActingDomain( R ) ) then
return extrep[1];
else
return fail;
fi;
end );
#############################################################################
##
#M ExtRepOfObj( <elm> ) . . . . . . . . . . . . . . for magma ring element
##
## The external representation of elements in a free magma ring is defined
## as a list of length 2, the first entry being the zero coefficient,
## the second being a zipped list containing the external representations
## of the monomials and their coefficients.
##
InstallMethod( ExtRepOfObj,
"for magma ring element",
#T eventually more specific!
#T allow this only if the magma elements have an external representation!
#T (make this explicit!)
[ IsElementOfMagmaRingModuloRelations ],
function( elm )
local zero, i;
zero:= ZeroCoefficient( elm );
elm:= ShallowCopy( CoefficientsAndMagmaElements( elm ) );
for i in [ 1, 3 .. Length( elm ) - 1 ] do
elm[i]:= ExtRepOfObj( elm[i] );
od;
return [ zero, elm ];
end );
#############################################################################
##
#M ObjByExtRep( <Fam>, <descr> ) . . . . for free magma ring elements family
##
## This is well-defined only if the magma elements of the free magma ring
## have an external representation.
##
## We need this mainly for free and f.p. algebras.
##
## Note that <descr> must describe a *normalized* element (sorted w.r.t. the
## magma elements, normalized w.r.t. the relations if there are some).
##
InstallMethod( ObjByExtRep,
"for magma ring elements family, and list",
[ IsElementOfMagmaRingModuloRelationsFamily, IsList ],
function( Fam, descr )
local FM, elm, i;
FM:= ElementsFamily( Fam!.familyMagma );
elm:= ShallowCopy( descr[2] );
for i in [ 1, 3 .. Length( elm ) - 1 ] do
elm[i]:= ObjByExtRep( FM, elm[i] );
od;
return Objectify( Fam!.defaultType, [ descr[1], elm ] );
end );
#############################################################################
##
## 3. Free left modules in magma rings modulo relations
##
#############################################################################
##
#M NiceFreeLeftModuleInfo( <V> )
#M NiceVector( <V>, <v> )
#M UglyVector( <V>, <r> )
##
InstallHandlingByNiceBasis( "IsSpaceOfElementsOfMagmaRing", rec(
detect := function( F, gens, V, zero )
return IsElementOfMagmaRingModuloRelationsCollection( V );
end,
NiceFreeLeftModuleInfo := function( V )
local gens,
monomials,
gen,
list,
i,
zero,
info;
gens:= GeneratorsOfLeftModule( V );
monomials:= [];
for gen in gens do
list:= CoefficientsAndMagmaElements( gen );
for i in [ 1, 3 .. Length( list ) - 1 ] do
AddSet( monomials, list[i] );
od;
od;
zero:= Zero( V )![1];
info:= rec( monomials := monomials,
zerocoeff := zero,
family := ElementsFamily( FamilyObj( V ) ) );
# For the zero row vector, catch the case of empty `monomials' list.
if IsEmpty( monomials ) then
info.zerovector := [ Zero( LeftActingDomain( V ) ) ];
else
info.zerovector := ListWithIdenticalEntries( Length( monomials ),
zero );
fi;
MakeImmutable( info.zerovector );
return info;
end,
NiceVector := function( V, v )
local info, c, monomials, i, pos;
info:= NiceFreeLeftModuleInfo( V );
c:= ShallowCopy( info.zerovector );
v:= CoefficientsAndMagmaElements( v );
monomials:= info.monomials;
for i in [ 2, 4 .. Length( v ) ] do
pos:= Position( monomials, v[ i-1 ] );
if pos = fail then return fail; fi;
c[ pos ]:= v[i];
od;
return c;
end,
UglyVector := function( V, r )
local info;
info:= NiceFreeLeftModuleInfo( V );
if Length( r ) <> Length( info.zerovector ) then
return fail;
elif IsEmpty( info.monomials ) then
if IsZero( r ) then
return Zero( V );
else
return fail;
fi;
fi;
return ElementOfMagmaRing( info.family, info.zerocoeff,
r, info.monomials );
end ) );
#############################################################################
##
## 4. methods for free magma rings modulo the span of a ``zero'' element
##
#############################################################################
##
#F MagmaRingModuloSpanOfZero( <R>, <M>, <z> )
##
InstallGlobalFunction( MagmaRingModuloSpanOfZero, function( R, M, z )
local RM, # result
F, # family of magma ring elements
one, # identity of `R'
zero; # zero of `R'
# Construct the family of elements of our ring.
F:= NewFamily( "MagmaRingModuloSpanOfZeroObjFamily",
IsElementOfMagmaRingModuloRelations );
SetFilterObj( F, IsElementOfMagmaRingModuloSpanOfZeroFamily );
one:= One( R );
zero:= Zero( R );
F!.defaultType := NewType( F, IsMagmaRingObjDefaultRep );
F!.familyRing := FamilyObj( R );
F!.familyMagma := FamilyObj( M );
F!.zeroRing := zero;
#T no!
F!.zeroOfMagma := z;
# Do not set the characteristic since we do not know whether we are
# 0-dimensional and the characteristic would then be 0.
# Make the magma ring object.
RM:= Objectify( NewType( CollectionsFamily( F ),
IsMagmaRingModuloSpanOfZero
and IsAttributeStoringRep ),
rec() );
# Store it in its elements family:
F!.magmaring := RM;
# Set the necessary attributes.
SetLeftActingDomain( RM, R );
SetUnderlyingMagma( RM, M );
# Deduce useful information.
if HasIsFinite( M ) then
SetIsFiniteDimensional( RM, IsFinite( M ) );
fi;
if HasIsWholeFamily( R ) and HasIsWholeFamily( M ) then
SetIsWholeFamily( RM, IsWholeFamily( R ) and IsWholeFamily( M ) );
fi;
# Construct the generators.
SetGeneratorsOfLeftOperatorRing( RM,
List( GeneratorsOfMagma( M ),
x -> ElementOfMagmaRing( F, zero, [ one ], [ x ] ) ) );
# Return the ring.
return RM;
end );
#############################################################################
##
#M Characteristic( <A> )
#M Characteristic( <algelm> )
#M Characteristic( <algelmfam> )
##
## (via delegations)
##
InstallMethod( Characteristic,
"for an elements family of a magma ring quotient",
[ IsElementOfMagmaRingModuloSpanOfZeroFamily ],
function( fam )
local A,one;
A := fam!.magmaring;
one := One(A);
if Zero(A) = one then
return 1;
else
return Characteristic(LeftActingDomain(A));
fi;
end );
#############################################################################
##
#M NormalizedElementOfMagmaRingModuloRelations( <Fam>, <descr> )
#M . . . for a magma ring modulo the span of the ``zero''
##
## <Fam> is a family of elements of a magma ring modulo the span of the
## ``zero element'' of the magma.
## <descr> is a list of the form `[ <z>, <list> ]', <z> being the zero
## coefficient of the ring, and <list> being the list of monomials and
## their coefficients.
##
## The function returns the element described by <descr> in normal form,
## that is, with zero coefficient of the ``zero element'' of the magma.
##
InstallMethod( NormalizedElementOfMagmaRingModuloRelations,
"for family of magma rings modulo the span of ``zero'', and list",
[ IsElementOfMagmaRingModuloSpanOfZeroFamily, IsList ],
function( Fam, descr )
local zeromagma, len, i;
zeromagma:= Fam!.zeroOfMagma;
len:= Length( descr[2] );
for i in [ 1, 3 .. len - 1 ] do
if descr[2][i] = zeromagma then
descr:= [ descr[1], Concatenation( descr[2]{ [ 1 .. i-1 ] },
descr[2]{ [ i+2 .. len ] } ) ];
break;
fi;
od;
MakeImmutable( descr );
return descr;
end );
#############################################################################
##
#M IsFinite( <RM> ) . . . . . . . . for magma ring modulo span of ``zero''
##
InstallMethod( IsFinite,
"for a magma ring modulo the span of ``zero''",
[ IsMagmaRingModuloSpanOfZero ],
RM -> IsFinite( LeftActingDomain( RM ) )
and IsFinite( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M IsFiniteDimensional( <RM> ) . . . for magma ring modulo span of ``zero''
##
InstallMethod( IsFiniteDimensional,
"for a magma ring modulo the span of ``zero''",
[ IsMagmaRingModuloSpanOfZero ],
RM -> IsFinite( UnderlyingMagma( RM ) ) );
#############################################################################
##
#M Dimension( <RM> ) . . . . . . . . for magma ring modulo span of ``zero''
##
InstallMethod( Dimension,
"for a magma ring modulo the span of ``zero''",
[ IsMagmaRingModuloSpanOfZero ],
RM -> Size( UnderlyingMagma( RM ) ) - 1 );
#############################################################################
##
#M GeneratorsOfLeftModule( <RM> ) . for magma ring modulo span of ``zero''
##
InstallMethod( GeneratorsOfLeftModule,
"for a magma ring modulo the span of ``zero''",
[ IsMagmaRingModuloSpanOfZero ],
function( RM )
local F, one, zero;
if IsFiniteDimensional( RM ) then
F:= ElementsFamily( FamilyObj( RM ) );
one:= One( LeftActingDomain( RM ) );
zero:= Zero( LeftActingDomain( RM ) );
return List( Difference( AsSSortedList( UnderlyingMagma( RM ) ),
[ F!.zeroOfMagma ] ),
m -> ElementOfMagmaRing( F, zero, [ one ], [ m ] ) );
else
Error( "<RM> is not finite dimensional" );
fi;
end );
#############################################################################
##
## 5. methods for groups of free magma ring elements
##
#############################################################################
##
#M IsGeneratorsOfMagmaWithInverses( <mgmringelms> )
##
## Check that all elements are in fact invertible.
##
InstallMethod( IsGeneratorsOfMagmaWithInverses,
"for a collection of free magma ring elements",
[ IsElementOfMagmaRingModuloRelationsCollection ],
mgmringelms -> ForAll( mgmringelms, x -> Inverse( x ) <> fail ) );
[ Dauer der Verarbeitung: 0.50 Sekunden
(vorverarbeitet)
]
|