############################################################################# ## ## 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 methods for *row modules*, that is, ## free left modules consisting of row vectors. ## ## Especially methods for *full row modules* $R^n$ are contained. ## ## (See the file `modulmat.gi' for the methods for matrix modules.) ##
############################################################################# ## #F FullRowModule( <R>, <n> ) ##
InstallGlobalFunction( FullRowModule, function( R, n )
local M,typ; # the free module record, result
if not ( IsRing( R ) and IsInt( n ) and 0 <= n ) then
Error( "usage: FullRowModule( <R>, <n> ) for ring <R>" ); fi;
typ:=IsFreeLeftModule and IsFullRowModule and IsAttributeStoringRep
and HasIsEmpty;
if IsDivisionRing( R ) then
typ:=typ and IsGaussianSpace; fi;
if n=0then
typ:=typ and IsTrivial; else
typ:=typ and IsNonTrivial; fi;
if n<>infinity and HasIsFinite(R) and IsFinite(R) then
typ:=typ and IsFinite; elif n<>0 and HasIsFinite(R) and not IsFinite(R) then
typ:=typ and HasIsFinite; fi;
M:= Objectify( NewType( CollectionsFamily( FamilyObj( R ) ),
typ ),
rec() );
SetLeftActingDomain( M, R );
SetDimensionOfVectors( M, n );
return M; end );
############################################################################# ## #M \^( <R>, <n> ) . . . . . . . . . . . . . . . full row module over a ring ##
InstallOtherMethod( \^, "for ring and integer (delegate to `FullRowModule')",
[ IsRing, IsInt ],
FullRowModule );
############################################################################# ## #M IsRowModule . return `false' for objects which are not free left modules ##
InstallOtherMethod( IsRowModule, "return `false' for objects which are not free left modules",
true, [ IsObject ], 0, function ( obj ) if not IsFreeLeftModule(obj) then
return false; else
TryNextMethod(); fi; end );
############################################################################# ## #M IsRowModule( <M> ) ##
InstallMethod( IsRowModule, "for a free left module",
[ IsFreeLeftModule ],
M -> IsRowVector( Zero( M ) ) );
############################################################################# ## #M IsFullRowModule( M ) ##
InstallMethod( IsFullRowModule, "for free left (row) module",
[ IsFreeLeftModule ],
M -> IsRowModule( M )
and Dimension( M ) = DimensionOfVectors( M )
and ForAll( GeneratorsOfLeftModule( M ),
v -> IsSubset( LeftActingDomain( M ), v ) ) );
############################################################################# ## #M Dimension( <M> ) ##
InstallMethod( Dimension, "for full row module",
[ IsFreeLeftModule and IsFullRowModule ],
DimensionOfVectors );
############################################################################# ## #M Random( <M> ) ##1
InstallMethodWithRandomSource( Random, "for a random source and a full row module",
[ IsRandomSource, IsFreeLeftModule and IsFullRowModule ], function( rs, M )
local R,v;
R:= LeftActingDomain( M );
v := List( [ 1 .. DimensionOfVectors( M ) ], x -> Random( rs, R ) ); if IsField(R) then if IsHPCGAP then if Size(R) <= 256then
v := CopyToVectorRep(v,Size(R)); fi; else
ConvertToVectorRep(v,R); fi; fi;
return v; end );
############################################################################# ## #M Representative( <M> ) ##
InstallMethod( Representative, "for full row module",
[ IsFreeLeftModule and IsFullRowModule ],
M -> ListWithIdenticalEntries( DimensionOfVectors( M ),
Zero( LeftActingDomain( M ) ) ) );
############################################################################# ## #M GeneratorsOfLeftModule( <V> ) ##
InstallMethod( GeneratorsOfLeftModule, "for full row module",
[ IsFreeLeftModule and IsFullRowModule ],
M -> IdentityMat( DimensionOfVectors( M ), LeftActingDomain( M ) ) );
############################################################################# ## #M ViewObj( <M> ) ##
InstallMethod( ViewObj, "for full row module",
[ IsFreeLeftModule and IsFullRowModule ], function( M )
Print( "( " );
View( LeftActingDomain( M ) );
Print( "^", DimensionOfVectors( M ), " )" ); end );
############################################################################# ## #M \in( <v>, <V> ) ##
InstallMethod( \in, "for full row module",
IsElmsColls,
[ IsRowVector, IsFreeLeftModule and IsFullRowModule ], function( v, M )
return Length( v ) = DimensionOfVectors( M )
and IsSubset( LeftActingDomain( M ), v ); end );
############################################################################# ## #M BasisVectors( <B> ) . . . . . for a canonical basis of a full row module ##
InstallMethod( BasisVectors, "for canonical basis of a full row module",
[ IsBasis and IsCanonicalBasis and IsCanonicalBasisFullRowModule ], function( B )
B:= UnderlyingLeftModule( B );
return IdentityMat( DimensionOfVectors( B ), LeftActingDomain( B ) ); end );
############################################################################# ## #M CanonicalBasis( <V> ) ##
InstallMethod( CanonicalBasis, "for a full row module",
[ IsFreeLeftModule and IsFullRowModule ], function( V )
local B;
B:= Objectify( NewType( FamilyObj( V ),
IsFiniteBasisDefault
and IsCanonicalBasis
and IsCanonicalBasisFullRowModule
and IsAttributeStoringRep ),
rec() );
SetUnderlyingLeftModule( B, V );
return B; end );
############################################################################# ## #M Basis( <M> ) . . . . . . . . . . . . . . . . . . . . for full row module ##
InstallMethod( Basis, "for full row module (delegate to `CanonicalBasis')",
[ IsFreeLeftModule and IsFullRowModule ], CANONICAL_BASIS_FLAGS,
CanonicalBasis );
############################################################################# ## #M Coefficients( <B>, <v> ) . . for a canonical basis of a full row module ##
InstallMethod( Coefficients, "for canonical basis of a full row module",
IsCollsElms,
[ IsBasis and IsCanonicalBasisFullRowModule, IsRowVector ], function( B, v )
local V, R;
V:= UnderlyingLeftModule( B );
R:= LeftActingDomain( V ); if Length( v ) = DimensionOfVectors( V ) and IsSubset( R, v ) then
return ShallowCopy( v ); else
return fail; fi; end );
############################################################################# ## #M IsCanonicalBasisFullRowModule( <B> ) . . . . . . . . . . . . for a basis ##
InstallMethod( IsCanonicalBasisFullRowModule, "for a basis",
[ IsBasis ],
B -> IsFullRowModule( UnderlyingLeftModule( B ) )
and IsCanonicalBasis( B ) );
############################################################################# ## #M EnumeratorByBasis( <B> ) . . . . for canonical basis of full row module ##
BindGlobal( "NumberElement_FiniteFullRowModule", function( e, v )
local len, n, i, pos;
if not IsDenseList( v ) then
return fail; fi;
len:= Length( v ); if len <> e!.dimension then
return fail; fi;
n:= 0;
i:= 1;
while i <= len and v[i] = e!.coeffszero do
i:= i+1;
od;
while i <= len do
pos:= Position( e!.coeffsenum, v[i], 0 ); if pos = fail then
return fail; fi;
n:= e!.q * n + pos - 1;
i:= i+1;
od;
return n + 1; end );
BindGlobal( "PosVecEnumFF", function( enum, v )
local i,l;
if not IsCollsElms( FamilyObj( enum ), FamilyObj( v ) )
or not IsRowVector( v )
or Length( v ) <> enum!.dimension then
return fail; fi;
# test whether the vector is indeed compact over a finite field if not IsDataObjectRep(v) then
# the degree of the field extension q provides
l:= LogInt( enum!.q, Characteristic(v) ); for i in v do if not (IsFFE(i) and IsInt(l/DegreeFFE(i))) then # cannot convert, wrong type of object
return NumberElement_FiniteFullRowModule( enum, v ); fi;
od;
v := ImmutableVector( enum!.q, v ); if not IsDataObjectRep(v) then # cannot convert, wrong type of object
return NumberElement_FiniteFullRowModule( enum, v ); fi; fi; # Problem with GF(4) vectors over GF(2) if ( IsGF2VectorRep(v) and enum!.q <> 2 )
or ( Is8BitVectorRep(v) and enum!.q = 2 ) then
return NumberElement_FiniteFullRowModule( enum, v ); fi;
# compute index via number
v:= NumberFFVector( v, enum!.q ); if v <> fail then
v:= v+1; fi;
return v; end);
BindGlobal( "ElementNumber_FiniteFullRowModule", function( enum, n )
local v, i;
if Size( enum ) < n then
Error( "<enum>[", n, "] must have an assigned value" ); fi;
v:= ShallowCopy( enum!.zerovector );
i:= Length( v );
n:= n-1; while0 < n do
v[i]:= enum!.coeffsenum[ RemInt( n, enum!.q ) + 1 ];
n:= QuoInt( n, enum!.q );
i:= i-1;
od; if IsFFE( enum!.coeffszero ) then
v := ImmutableVector( enum!.q, v ); fi;
MakeImmutable( v );
return v; end );
BindGlobal( "NumberElement_InfiniteFullRowModule", function( enum, vector )
local n,
i,
max,
maxpos,
pos,
len;
if not IsCollsElms( FamilyObj( enum ), FamilyObj( vector ) )
or not IsList( vector ) then
return fail; fi;
n:= Length( vector ); if n <> enum!.dimension then
return fail; fi;
# Replace the entries of `vector' by their positions.
vector:= List( vector, x -> Position( enum!.coeffsenum, x, 0 ) ); if fail in vector then
return fail; fi;
vector:= vector - 1;
# Find the maximal entry in the vector, and its number.
max:= vector[1]; for i in [ 2 .. n ] do if max < vector[i] then
max:= vector[i]; fi;
od; if max = 0then
return 1; fi;
# Compute the positions of `max' in `vector',
maxpos:= []; for i in [ 1 .. n ] do if vector[i] = max then
Add( maxpos, i-1 ); fi;
od;
# Compute the number of those elements with same distribution # of `max' as in `vector' that come before `vector'.
pos:= 0; for i in [ n, n-1 .. 1 ] do if vector[i] <> max then
pos:= pos * max + vector[i]; fi;
od;
pos:= pos + 1;
# Compute the number of those elements with smaller distribution # of `max'. # Consider the following example. # 1 3 4 7 # m ? m m ? ? m ? ... ? (`vector', the `?' mean entries < `m') # * * * * * * ? ? ... ? gives (m+1)^6 m^{n-6} # * * * ? ? ? m ? ... ? gives (m+1)^3 m^{n-3-1} # * * ? m ? ? m ? ... ? gives (m+1)^2 m^{n-2-2} # ? ? m m ? ? m ? ... ? gives (m+1)^0 m^{n-0-3}
len:= Length( maxpos ); for i in [ len, len-1 .. 1 ] do
pos:= pos + ( max + 1 )^maxpos[i] * max^( n - len - maxpos[i] + i );
od;
return pos; end );
BindGlobal( "ElementNumber_InfiniteFullRowModule", function( enum, N )
local n,
val,
max,
maxpos,
pos,
vector,
i,
quorem;
# Catch the special case.
n:= enum!.dimension; if N = 1then
val:= enum!.coeffsenum[1];
return List( [ 1 .. n ], x -> val ); fi;
# Compute the maximal entry of the element.
max:= 1; while max^n < N do
max:= max + 1;
od;
# Compute the positions of the maximal entry.
maxpos:= [];
repeat
pos:= 0;
val:= (max-1)^( n - Length( maxpos ) ); while val < N do
pos:= pos + 1;
val:= val * max / ( max - 1 );
od; if0 < pos then
N:= N - val * ( max - 1 ) / max;
Add( maxpos, pos ); fi;
until pos = 0;
maxpos:= Reversed( maxpos );
# Compute the values of the element that are strictly smaller than `max'.
vector:= [];
N:= N - 1; for i in [ 1 .. n ] do if i in maxpos then
vector[i]:= max; else
quorem:= QuotientRemainder( Integers, N, max-1 );
vector[i]:= quorem[2] + 1;
N:= quorem[1]; fi;
od;
# Translate the positions to values. for i in [ 1 .. n ] do
vector[i]:= enum!.coeffsenum[ vector[i] ];
od;
# Return the element.
return Immutable( vector ); end );
InstallMethod( EnumeratorByBasis, "for enumerator via canonical basis of a full row module",
[ IsBasis and IsCanonicalBasis and IsCanonicalBasisFullRowModule ], function( B )
local V, F, enum;
V:= UnderlyingLeftModule( B );
F:= LeftActingDomain( V );
coeffsenum := Enumerator( F ),
q := Size( F ),
coeffszero := Zero( F ),
zerovector := Zero( V ),
dimension := Dimension( V ) ) );
if IsField( F ) and Size( F ) < 256 and IsInternalRep( One( F ) ) then # Use a more efficient method for `Position'.
enum!.NumberElement:= PosVecEnumFF;
SetFilterObj( enum, IsQuickPositionList ); fi;
SetFilterObj( enum, IsSSortedList );
return enum;
elif IsFiniteDimensional( V ) then
# The ring is infinite, use the canonical ordering of $\N_0^n$ # as defined for the iterator.
return EnumeratorByFunctions( V, rec(
ElementNumber := ElementNumber_InfiniteFullRowModule,
NumberElement := NumberElement_InfiniteFullRowModule,
dimension := Dimension( V ),
coeffsenum := Enumerator( F ) ) );
else
Error( "not implemented for infinite dimensional free modules" ); fi; end );
############################################################################# ## #M IteratorByBasis( <B> ) . . . . . . for canon. basis of a full row module ##
BindGlobal( "NextIterator_FiniteFullRowModule", function( iter )
local pos;
# Increase the counter.
pos:= iter!.dimension; while iter!.counter[ pos ] = iter!.q do
iter!.counter[ pos ]:= 1;
pos:= pos - 1;
od;
iter!.counter[ pos ]:= iter!.counter[ pos ] + 1;
# Return the linear combination.
return iter!.ringelements{ iter!.counter }; end );
BindGlobal( "IsDoneIterator_FiniteFullRowModule",
iter -> iter!.counter = iter!.limit );
BindGlobal( "NextIterator_InfiniteFullRowModule", function( iter )
local dim, # dimension of the free module
vector, # positions of the coefficients in `iter!.coeffsenum' # of the previous element
result, # coefficients of the previous element
max1, # one less than the maximal entry in `vector'
max, # maximal entry in `vector'
firstval, # first entry in `iter!.coeffsenum'
i; # loop variable
# (Increase the counter.)
dim := iter!.dimension;
vector := iter!.vector;
result := iter!.result;
max1 := iter!.maxentry - 1;
firstval := iter!.firstval;
# If not all entries in `vector' are `max1' or `max1 + 1' then # increase the counter formed by the positions with entry # different from `max1 + 1', and return the result. for i in [ 1 .. dim ] do if vector[i] < max1 then
vector[i]:= vector[i] + 1;
result[i]:= iter!.coeffsenum[ vector[i] ];
return ShallowCopy( result ); elif vector[i] = max1 then
vector[i]:= 1;
result[i]:= firstval; fi;
od;
# Otherwise if all entries are `max1 + 1', increase the maximum.
max:= iter!.maxentry; if dim < PositionNot( vector, max ) then
max:= max + 1;
iter!.maxentry:= max;
vector[1]:= max;
iter!.maxval:= iter!.coeffsenum[ max ];
result[1]:= iter!.maxval; for i in [ 2 .. dim ] do
vector[i]:= 1;
result[i]:= firstval;
od;
return ShallowCopy( result ); fi;
# Otherwise get the next start configuration with maximum `max'. # (The entries of `vector' are now either `1' or `max'.) for i in [ 1 .. dim ] do if vector[i] = max then
vector[i]:= 1;
result[i]:= firstval; else
vector[i]:= max;
result[i]:= iter!.maxval;
return ShallowCopy( result ); fi;
od;
Assert( 2, true, "there should be a position with value different from `max'" ); end );
InstallMethod( IteratorByBasis, "for canonical basis of a full row module",
[ IsBasis and IsCanonicalBasisFullRowModule ], function( B )
local V,
F,
dim,
counter,
q,
enum,
vector,
firstval,
result;
V:= UnderlyingLeftModule( B );
dim:= Dimension( V );
if dim = 0then
return TrivialIterator( Zero( V ) );
elif IsFinite( LeftActingDomain( V ) ) then
F:= LeftActingDomain( V );
counter := List( [ 1 .. dim ], x -> 1 );
counter[ Length( counter ) ]:= 0;
q:= Size( F );
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.