############################################################################# ## ## 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;
# 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 = 0then
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 = 0then
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 ) = 2then # 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 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!.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) > 0then
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 ] ) ) );
############################################################################# ## #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 ) );
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 ##
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 );
# 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 ) );
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.29Angebot
¤
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.