|
#############################################################################
##
## This file is part of GAP, a system for computational discrete algebra.
## This file's authors include Thomas Breuer.
##
## Copyright of GAP belongs to its developers, whose names are too numerous
## to list here. Please refer to the COPYRIGHT file for details.
##
## SPDX-License-Identifier: GPL-2.0-or-later
##
## This file contains generic methods for modules.
##
#############################################################################
##
#M LeftModuleByGenerators( <R>, <gens> )
#M LeftModuleByGenerators( <R>, <gens>, <zero> )
##
## Create the <R>-left module generated by <gens>,
## with zero element <zero>.
##
InstallMethod( LeftModuleByGenerators,
"for ring and collection",
[ IsRing, IsCollection ],
function( R, gens )
local V;
V:= Objectify( NewType( FamilyObj( gens ),
IsLeftModule and IsAttributeStoringRep ),
rec() );
SetLeftActingDomain( V, R );
SetGeneratorsOfLeftModule( V, AsList( gens ) );
CheckForHandlingByNiceBasis( R, gens, V, false );
return V;
end );
InstallMethod( LeftModuleByGenerators,
"for ring, homogeneous list, and vector",
[ IsRing, IsHomogeneousList, IsObject ],
function( R, gens, zero )
local V;
V:= Objectify( NewType( CollectionsFamily( FamilyObj( zero ) ),
IsLeftModule and IsAttributeStoringRep ),
rec() );
SetLeftActingDomain( V, R );
SetGeneratorsOfLeftModule( V, AsList( gens ) );
SetZero( V, zero );
if IsEmpty( gens ) then
SetDimension( V, 0 );
fi;
CheckForHandlingByNiceBasis( R, gens, V, zero );
return V;
end );
#############################################################################
##
#M AsLeftModule( <R>, <D> ) . . . . . domain <D>, viewed as left <R>-module
##
InstallMethod( AsLeftModule,
"generic method for a ring and a collection",
[ IsRing, IsCollection ],
function ( R, D )
local S, L;
D := AsSSortedList( D );
L := ShallowCopy( D );
S := TrivialSubmodule( LeftModuleByGenerators( R, D ) );
SubtractSet( L, AsSSortedList( S ) );
while not IsEmpty(L) do
S := ClosureLeftModule( S, L[1] );
SubtractSet( L, AsSSortedList( S ) );
od;
if Length( AsSSortedList( S ) ) <> Length( D ) then
return fail;
fi;
S := LeftModuleByGenerators( R, GeneratorsOfLeftModule( S ) );
SetAsSSortedList( S, D );
SetIsFinite( S, true );
SetSize( S, Length( D ) );
# return the left module
return S;
end );
#############################################################################
##
#M AsLeftModule( <R>, <M> ) . . . . . . . . . . . for ring and left module
##
## View the left module <M> as a left module over the ring <R>.
##
InstallMethod( AsLeftModule,
" for a ring and a left module",
[ IsRing, IsLeftModule ],
function( R, M )
local W, # the space, result
base, # basis vectors of field extension
gen, # loop over generators of `V'
b, # loop over `base'
gens, # generators of `V'
newgens; # extended list of generators
if R = LeftActingDomain( M ) then
# No change of the left acting domain is necessary.
return M;
elif IsSubset( R, LeftActingDomain( M ) ) then
# Check whether `M' is really a module over the bigger field,
# that is, whether the set of elements does not change.
base:= BasisVectors( Basis( AsField( LeftActingDomain( M ), R ) ) );
#T generalize `AsField', at least to `AsAlgebra'!
for gen in GeneratorsOfLeftModule( M ) do
for b in base do
if not b * gen in M then
# The extension would change the set of elements.
return fail;
fi;
od;
od;
# Construct the left module.
W:= LeftModuleByGenerators( R, GeneratorsOfLeftModule(M), Zero(M) );
elif IsSubset( LeftActingDomain( M ), R ) then
# View `M' as a module over a smaller ring.
# For that, the list of generators must be extended.
gens:= GeneratorsOfLeftModule( M );
if IsEmpty( gens ) then
W:= LeftModuleByGenerators( R, [], Zero( M ) );
else
base:= BasisVectors( Basis( AsField( R, LeftActingDomain( M ) ) ) );
#T generalize `AsField', at least to `AsAlgebra'!
newgens:= [];
for b in base do
for gen in gens do
Add( newgens, b * gen );
od;
od;
W:= LeftModuleByGenerators( R, newgens );
fi;
else
# View `M' first as module over the intersection of rings,
# and then over the desired ring.
return AsLeftModule( R,
AsLeftModule( Intersection2( R, LeftActingDomain( M ) ),
M ) );
fi;
UseIsomorphismRelation( M, W );
UseSubsetRelation( M, W );
return W;
end );
#############################################################################
##
#M SetGeneratorsOfLeftModule( <M>, <gens> )
##
## If <M> is a free left module and <gens> is a finite list then <M> is
## finite dimensional.
##
InstallMethod( SetGeneratorsOfLeftModule,
"method that checks for `IsFiniteDimensional'",
IsIdenticalObj,
[ IsFreeLeftModule and IsAttributeStoringRep, IsList ],
function( M, gens )
SetIsFiniteDimensional( M, IsFinite( gens ) );
TryNextMethod();
end );
#############################################################################
##
#M Characteristic( <M> ) . . . . . . . . . . characteristic of a left module
##
## Do we have and/or need a replacement method?
#############################################################################
##
#M Representative( <D> ) . representative of a left operator additive group
##
InstallMethod( Representative,
"for left operator additive group with known generators",
[ IsLeftOperatorAdditiveGroup
and HasGeneratorsOfLeftOperatorAdditiveGroup ],
RepresentativeFromGenerators( GeneratorsOfLeftOperatorAdditiveGroup ) );
#############################################################################
##
#M Representative( <D> ) . representative of a right operator additive group
##
InstallMethod( Representative,
"for right operator additive group with known generators",
[ IsRightOperatorAdditiveGroup
and HasGeneratorsOfRightOperatorAdditiveGroup ],
RepresentativeFromGenerators( GeneratorsOfRightOperatorAdditiveGroup ) );
#############################################################################
##
#M ClosureLeftModule( <V>, <a> ) . . . . . . . . . closure of a left module
##
InstallMethod( ClosureLeftModule,
"for left module and vector",
IsCollsElms,
[ IsLeftModule, IsVector ],
function( V, w )
# if possible test if the element lies in the module already
if w in GeneratorsOfLeftModule( V ) or
( HasAsList( V ) and w in AsList( V ) ) then
return V;
fi;
# Otherwise make a new module.
return LeftModuleByGenerators( LeftActingDomain( V ),
Concatenation( GeneratorsOfLeftModule( V ),
[ w ] ) );
end );
#############################################################################
##
#M ClosureLeftModule( <V>, <W> ) . . . . . . . . . closure of a left module
##
InstallOtherMethod( ClosureLeftModule,
"for two left modules",
IsIdenticalObj,
[ IsLeftModule, IsLeftModule ],
function( V, W )
local C, v;
if LeftActingDomain( V ) = LeftActingDomain( W ) then
C:= V;
for v in GeneratorsOfLeftModule( W ) do
C:= ClosureLeftModule( C, v );
od;
return C;
else
return ClosureLeftModule( V, AsLeftModule( LeftActingDomain(V), W ) );
fi;
end );
#############################################################################
##
#M \+( <U1>, <U2> ) . . . . . . . . . . . . . . . . sum of two left modules
##
InstallOtherMethod( \+,
"for two left modules",
IsIdenticalObj,
[ IsLeftModule, IsLeftModule ],
function( V, W )
local S; # sum of <V> and <W>, result
if LeftActingDomain( V ) <> LeftActingDomain( W ) then
S:= Intersection2( LeftActingDomain( V ), LeftActingDomain( W ) );
S:= \+( AsLeftModule( S, V ), AsLeftModule( S, W ) );
elif IsEmpty( GeneratorsOfLeftModule( V ) ) then
S:= W;
else
S:= LeftModuleByGenerators( LeftActingDomain( V ),
Concatenation( GeneratorsOfLeftModule( V ),
GeneratorsOfLeftModule( W ) ) );
fi;
return S;
end );
#############################################################################
##
#F Submodule( <M>, <gens> ) . . . . . submodule of <M> generated by <gens>
#F SubmoduleNC( <M>, <gens> )
#F Submodule( <M>, <gens>, "basis" )
#F SubmoduleNC( <M>, <gens>, "basis" )
##
InstallGlobalFunction( Submodule, function( arg )
local M, gens, S;
# Check the arguments.
if Length( arg ) < 2
or not IsLeftModule( arg[1] )
or not (IsEmpty(arg[2]) or IsCollection( arg[2] )) then
Error( "first argument must be a left module, second a collection\n" );
fi;
# Get the arguments.
M := arg[1];
gens := AsList( arg[2] );
if IsEmpty( gens ) then
return SubmoduleNC( M, gens );
elif IsIdenticalObj( FamilyObj( M ), FamilyObj( gens ) )
and IsSubset( M, gens ) then
S:= LeftModuleByGenerators( LeftActingDomain( M ), gens );
SetParent( S, M );
if Length( arg ) = 3 and arg[3] = "basis" then
UseBasis( S, gens );
fi;
UseSubsetRelation( M, S );
#
# These cannot be handled by UseSubsetRelation, because they
# depend on M and S having the same LeftActingDomain
#
if IsRowModule(M) then
SetIsRowModule(S, true);
SetDimensionOfVectors(S,DimensionOfVectors(M));
elif IsMatrixModule( M ) then
SetIsMatrixModule( S, true );
SetDimensionOfVectors( S, DimensionOfVectors( M ) );
fi;
if IsGaussianSpace(M) then
SetFilterObj(S, IsGaussianSpace);
fi;
return S;
fi;
Error( "usage: Submodule( <M>, <gens> [, \"basis\"] )" );
end );
InstallGlobalFunction( SubmoduleNC, function( arg )
local S;
if IsEmpty( arg[2] ) then
S:= Objectify( NewType( FamilyObj( arg[1] ),
IsFreeLeftModule
and IsTrivial
and IsAttributeStoringRep ),
rec() );
SetDimension( S, 0 );
SetLeftActingDomain( S, LeftActingDomain( arg[1] ) );
SetGeneratorsOfLeftModule( S, AsList( arg[2] ) );
else
S:= LeftModuleByGenerators( LeftActingDomain( arg[1] ), arg[2] );
fi;
if Length( arg ) = 3 and arg[3] = "basis" then
UseBasis( S, arg[2] );
fi;
SetParent( S, arg[1] );
UseSubsetRelation( arg[1], S );
#
# These cannot be handled by UseSubsetRelation, because they
# depend on M and S having the same LeftActingDomain
#
if IsRowModule(arg[1]) then
SetIsRowModule(S, true);
SetDimensionOfVectors(S, DimensionOfVectors(arg[1]));
elif IsMatrixModule( arg[1] ) then
SetIsMatrixModule( S, true );
SetDimensionOfVectors( S, DimensionOfVectors( arg[1] ) );
fi;
if IsGaussianSpace(arg[1]) then
SetFilterObj(S, IsGaussianSpace);
fi;
return S;
end );
#############################################################################
##
#M TrivialSubadditiveMagmaWithZero( <M> ) . . . . . . . . for a left module
##
InstallMethod( TrivialSubadditiveMagmaWithZero,
"generic method for left modules",
[ IsLeftModule ],
M -> SubmoduleNC( M, [] ) );
#############################################################################
##
#M DimensionOfVectors( <M> ) . . . . . . . . . . . . . . . for a left module
##
InstallMethod( DimensionOfVectors,
"generic method for left modules",
[ IsFreeLeftModule ],
function( M )
M:= Representative( M );
if IsMatrix( M ) then
return DimensionsMat( M );
elif IsRowVector( M ) then
return Length( M );
else
TryNextMethod();
fi;
end );
# This setter method is installed to implement filter settings in response
# to an objects size as part of setting the size. This used to be handled
# instead by immediate methods, but in a situation as here it would trigger
# multiple immediate methods, several of which could apply and each changing
# the type of the object. Doing so can be costly and thus should be
# avoided.
InstallOtherMethod(SetDimension,true,[IsFreeLeftModule and IsAttributeStoringRep,IsObject],
100, # override system setter
function(obj,dim)
local filt;
if HasDimension(obj) and IsBound(obj!.Dimension) then
CHECK_REPEATED_ATTRIBUTE_SET(obj, "Dimension", dim);
return;
fi;
if dim=0 then
filt := IsTrivial and IsFiniteDimensional;
elif dim = infinity then
filt := IsNonTrivial and HasIsFiniteDimensional and HasIsFinite;
else
filt := IsNonTrivial and IsFiniteDimensional;
fi;
filt := filt and HasDimension;
obj!.Dimension := dim;
SetFilterObj(obj, filt);
end);
[ Dauer der Verarbeitung: 0.33 Sekunden
(vorverarbeitet)
]
|