|
# SPDX-License-Identifier: GPL-2.0-or-later
# Modules: A homalg based package for the Abelian category of finitely presented modules over computable rings
#
# Implementations
#
## Implementation stuff for homalg modules.
## <#GAPDoc Label="Modules:intro">
## A &homalg; module is a data structure for a finitely presented module. A presentation is given by
## a set of generators and a set of relations among these generators. The data structure for modules in &homalg;
## has two novel features:
## <List>
## <Item> The data structure allows several presentations linked with so-called transition matrices.
## One of the presentations is marked as the default presentation, which is usually the last added one.
## A new presentation can always be added provided it is linked to the default presentation by a transition matrix.
## If needed, the user can reset the default presentation by choosing one of the other presentations saved
## in the data structure of the &homalg; module. Effectively, a module is then given by <Q>all</Q> its presentations
## (as <Q>coordinates</Q>) together with isomorphisms between them (as <Q>coordinate changes</Q>).
## Being able to <Q>change coordinates</Q> makes the realization of a module in &homalg; <E>intrinsic</E>
## (or <Q>coordinate free</Q>). </Item>
## <Item> To present a left/right module it suffices to take a matrix <A>M</A> and interpret its rows/columns
## as relations among <M>n</M> <E>abstract</E> generators, where <M>n</M> is the number of columns/rows
## of <A>M</A>. Only that these abstract generators are useless when it comes to specific modules like
## modules of homomorphisms, where one expects the generators to be maps between modules. For this
## reason a presentation of a module in &homalg; is not merely a matrix of relations, but together with
## a set of generators. </Item>
## </List>
## <#/GAPDoc>
####################################
#
# representations:
#
####################################
## <#GAPDoc Label="IsFinitelyPresentedModuleOrSubmoduleRep">
## <ManSection>
## <Filt Type="Representation" Arg="M" Name="IsFinitelyPresentedModuleOrSubmoduleRep"/>
## <Returns><C>true</C> or <C>false</C></Returns>
## <Description>
## The &GAP; representation of finitley presented &homalg; modules or submodules. <P/>
## (It is a representation of the &GAP; category <Ref Filt="IsHomalgModule"/>,
## which is a subrepresentation of the &GAP; representations
## <C>IsStaticFinitelyPresentedObjectOrSubobjectRep</C>.)
## <Listing Type="Code"><![CDATA[
DeclareRepresentation( "IsFinitelyPresentedModuleOrSubmoduleRep",
IsHomalgModule and
IsStaticFinitelyPresentedObjectOrSubobjectRep,
[ ] );
## ]]></Listing>
## </Description>
## </ManSection>
## <#/GAPDoc>
## <#GAPDoc Label="IsFinitelyPresentedModuleRep">
## <ManSection>
## <Filt Type="Representation" Arg="M" Name="IsFinitelyPresentedModuleRep"/>
## <Returns><C>true</C> or <C>false</C></Returns>
## <Description>
## The &GAP; representation of finitley presented &homalg; modules. <P/>
## (It is a representation of the &GAP; category <Ref Filt="IsHomalgModule"/>,
## which is a subrepresentation of the &GAP; representations
## <C>IsFinitelyPresentedModuleOrSubmoduleRep</C>,
## <C>IsStaticFinitelyPresentedObjectRep</C>, and <C>IsHomalgRingOrFinitelyPresentedModuleRep</C>.)
## <Listing Type="Code"><![CDATA[
DeclareRepresentation( "IsFinitelyPresentedModuleRep",
IsFinitelyPresentedModuleOrSubmoduleRep and
IsStaticFinitelyPresentedObjectRep and
IsHomalgRingOrFinitelyPresentedModuleRep,
[ "SetsOfGenerators", "SetsOfRelations",
"PresentationMorphisms",
"Resolutions",
"TransitionMatrices",
"PositionOfTheDefaultPresentation" ] );
## ]]></Listing>
## </Description>
## </ManSection>
## <#/GAPDoc>
## <#GAPDoc Label="IsFinitelyPresentedSubmoduleRep">
## <ManSection>
## <Filt Type="Representation" Arg="M" Name="IsFinitelyPresentedSubmoduleRep"/>
## <Returns><C>true</C> or <C>false</C></Returns>
## <Description>
## The &GAP; representation of finitley generated &homalg; submodules. <P/>
## (It is a representation of the &GAP; category <Ref Filt="IsHomalgModule"/>,
## which is a subrepresentation of the &GAP; representations
## <C>IsFinitelyPresentedModuleOrSubmoduleRep</C>,
## <C>IsStaticFinitelyPresentedSubobjectRep</C>, and <C>IsHomalgRingOrFinitelyPresentedModuleRep</C>.)
## <Listing Type="Code"><![CDATA[
DeclareRepresentation( "IsFinitelyPresentedSubmoduleRep",
IsFinitelyPresentedModuleOrSubmoduleRep and
IsStaticFinitelyPresentedSubobjectRep and
IsHomalgRingOrFinitelyPresentedModuleRep,
[ "map_having_subobject_as_its_image" ] );
## ]]></Listing>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareRepresentation( "IsCategoryOfFinitelyPresentedLeftModulesRep",
IsHomalgCategoryOfLeftObjectsRep and
IsCategoryOfModules,
[ ] );
##
DeclareRepresentation( "IsCategoryOfFinitelyPresentedRightModulesRep",
IsHomalgCategoryOfRightObjectsRep and
IsCategoryOfModules,
[ ] );
DeclareFilter( "AdmissibleInputForHomalgFunctors" );
####################################
#
# families and types:
#
####################################
# a new family:
BindGlobal( "TheFamilyOfHomalgModules",
NewFamily( "TheFamilyOfHomalgModules" ) );
# two new types:
BindGlobal( "TheTypeHomalgLeftFinitelyPresentedModule",
NewType( TheFamilyOfHomalgModules,
AdmissibleInputForHomalgFunctors and
IsFinitelyPresentedModuleRep and
IsHomalgLeftObjectOrMorphismOfLeftObjects ) );
BindGlobal( "TheTypeHomalgRightFinitelyPresentedModule",
NewType( TheFamilyOfHomalgModules,
AdmissibleInputForHomalgFunctors and
IsFinitelyPresentedModuleRep and
IsHomalgRightObjectOrMorphismOfRightObjects ) );
# two new types:
BindGlobal( "TheTypeCategoryOfFinitelyPresentedLeftModules",
NewType( TheFamilyOfHomalgCategories,
IsCategoryOfFinitelyPresentedLeftModulesRep ) );
BindGlobal( "TheTypeCategoryOfFinitelyPresentedRightModules",
NewType( TheFamilyOfHomalgCategories,
IsCategoryOfFinitelyPresentedRightModulesRep ) );
####################################
#
# methods for operations:
#
####################################
## <#GAPDoc Label="HomalgRing:module">
## <ManSection>
## <Oper Arg="M" Name="HomalgRing" Label="for modules"/>
## <Returns>a &homalg; ring</Returns>
## <Description>
## The &homalg; ring of the &homalg; module <A>M</A>.
## <#Include Label="HomalgRing:module:example">
## </Description>
## </ManSection>
## <#/GAPDoc>
##
InstallMethod( HomalgRing,
"for homalg modules",
[ IsHomalgModule ],
function( M )
return M!.ring;
end );
##
InstallMethod( StructureObject,
"for homalg modules",
[ IsHomalgModule ],
function( M )
return M!.ring;
end );
##
InstallOtherMethod( Zero,
"for homalg modules",
[ IsHomalgModule and IsHomalgRightObjectOrMorphismOfRightObjects ], 10001, ## FIXME: is it O.K. to use such a high ranking
function( M )
return ZeroRightModule( HomalgRing( M ) );
end );
##
InstallOtherMethod( Zero,
"for homalg modules",
[ IsHomalgModule and IsHomalgLeftObjectOrMorphismOfLeftObjects ], 10001, ## FIXME: is it O.K. to use such a high ranking
function( M )
return ZeroLeftModule( HomalgRing( M ) );
end );
##
InstallMethod( SetsOfGenerators,
"for homalg modules",
[ IsHomalgModule ],
function( M )
if IsBound(M!.SetsOfGenerators) then
return M!.SetsOfGenerators;
fi;
return fail;
end );
##
InstallMethod( SetsOfRelations,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
if IsBound(M!.SetsOfRelations) then
return M!.SetsOfRelations;
fi;
return fail;
end );
##
InstallMethod( ListOfPositionsOfKnownSetsOfRelations,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
return SetsOfRelations( M )!.ListOfPositionsOfKnownSetsOfRelations;
end );
##
InstallMethod( PartOfPresentationRelevantForOutputOfFunctors,
"for homalg modules",
[ IsHomalgModule, IsInt ],
GeneratorsOfModule );
##
InstallMethod( ComparePresentationsForOutputOfFunctors,
"for a homalg module and two integers",
[ IsFinitelyPresentedModuleRep, IsInt, IsInt ],
function( M, p, q )
return IsOne( TransitionMatrix( M, p, q ) );
end );
##
InstallMethod( PositionOfTheDefaultPresentation,
"for homalg modules",
[ IsHomalgModule ],
function( M )
if IsBound(M!.PositionOfTheDefaultPresentation) then
return M!.PositionOfTheDefaultPresentation;
fi;
return fail;
end );
##
InstallMethod( SetPositionOfTheDefaultPresentation,
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
M!.PositionOfTheDefaultPresentation := pos;
end );
##
InstallMethod( PositionOfLastStoredSetOfRelations,
"for homalg modules",
[ IsHomalgModule ],
function( M )
return PositionOfLastStoredSetOfRelations( SetsOfRelations( M ) );
end );
##
InstallMethod( SetAsOriginalPresentation,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local pos;
pos := PositionOfTheDefaultPresentation( M );
M!.PositionOfOriginalPresentation := pos;
end );
##
InstallMethod( OnOriginalPresentation,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local pos;
if IsBound( M!.PositionOfOriginalPresentation ) then
pos := M!.PositionOfOriginalPresentation;
SetPositionOfTheDefaultPresentation( M, pos );
fi;
return M;
end );
##
InstallMethod( SetAsPreferredPresentation,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local pos;
pos := PositionOfTheDefaultPresentation( M );
M!.PositionOfPreferredPresentation := pos;
end );
##
InstallMethod( OnPreferredPresentation,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local pos;
if IsBound( M!.PositionOfPreferredPresentation ) then
pos := M!.PositionOfPreferredPresentation;
SetPositionOfTheDefaultPresentation( M, pos );
fi;
return M;
end );
##
InstallMethod( OnFirstStoredPresentation,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local pos;
SetPositionOfTheDefaultPresentation( M, 1 );
return M;
end );
##
InstallMethod( OnLastStoredPresentation,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local pos;
pos := PositionOfLastStoredSetOfRelations( M );
SetPositionOfTheDefaultPresentation( M, pos );
return M;
end );
##
InstallMethod( GeneratorsOfModule, ### defines: GeneratorsOfModule (GeneratorsOfPresentation)
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
if IsBound(SetsOfGenerators(M)!.(pos)) then
return SetsOfGenerators(M)!.(pos);
fi;
return fail;
end );
##
InstallMethod( GeneratorsOfModule, ### defines: GeneratorsOfModule (GeneratorsOfPresentation)
"for homalg modules",
[ IsHomalgModule ],
function( M )
local gens;
gens := GeneratorsOfModule( M, PositionOfTheDefaultSetOfGenerators( M ) );
if not HasProcedureToNormalizeGenerators( gens ) and HasProcedureToNormalizeGenerators( M ) then
SetProcedureToNormalizeGenerators( gens, ProcedureToNormalizeGenerators( M ) );
fi;
if not HasProcedureToReadjustGenerators( gens ) and HasProcedureToReadjustGenerators( M ) then
SetProcedureToReadjustGenerators( gens, ProcedureToReadjustGenerators( M ) );
fi;
return gens;
end );
##
InstallMethod( GeneratingElements,
"for homalg modules",
[ IsHomalgModule and IsStaticFinitelyPresentedObjectRep ],
function( M )
local gen_set, n, R, gens;
gen_set := GeneratorsOfModule( M );
if IsBound( gen_set!.GeneratingElements ) then
return gen_set!.GeneratingElements;
fi;
n := NrGenerators( M );
R := HomalgRing( M );
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
gens := StandardBasisRowVectors( n, R );
else
gens := StandardBasisColumnVectors( n, R );
fi;
gens := List( gens, b -> HomalgElement( MorphismConstructor( b, One( M ), M ) ) );
gen_set!.GeneratingElements := gens;
return gens;
end );
##
InstallMethod( GeneratingElements,
"for homalg submodules",
[ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep ],
function( N )
local gens, M;
gens := MatrixOfGenerators( N );
if IsHomalgLeftObjectOrMorphismOfLeftObjects( N ) then
gens := List( [ 1 .. NumberRows( gens ) ], i -> CertainRows( gens, [ i ] ) );
else
gens := List( [ 1 .. NumberColumns( gens ) ], i -> CertainColumns( gens, [ i ] ) );
fi;
M := SuperObject( N );
return List( gens, b -> HomalgElement( MorphismConstructor( b, One( M ), M ) ) );
end );
##
InstallMethod( RelationsOfModule, ### defines: RelationsOfModule (NormalizeInput)
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
if IsBound(SetsOfRelations( M )!.(pos)) then;
return SetsOfRelations( M )!.(pos);
fi;
return fail;
end );
##
InstallMethod( RelationsOfModule, ### defines: RelationsOfModule (NormalizeInput)
"for homalg modules",
[ IsHomalgModule ],
function( M )
return RelationsOfModule( M, PositionOfTheDefaultPresentation( M ) );
end );
##
InstallMethod( RelationsOfHullModule, ### defines: RelationsOfHullModule
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
local gen;
gen := GeneratorsOfModule( M );
if gen <> fail then;
return RelationsOfHullModule( gen );
fi;
return fail;
end );
##
InstallMethod( RelationsOfHullModule, ### defines: RelationsOfHullModule
"for homalg modules",
[ IsFinitelyPresentedModuleRep, IsPosInt ],
function( M, pos )
local gen;
gen := GeneratorsOfModule( M, pos );
if gen <> fail then;
return RelationsOfHullModule( gen );
fi;
return fail;
end );
##
InstallMethod( MatrixOfGenerators,
"for homalg modules",
[ IsHomalgModule ],
function( M )
return MatrixOfGenerators( GeneratorsOfModule( M ) );
end );
##
InstallMethod( MatrixOfGenerators,
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
local gen;
gen := GeneratorsOfModule( M, pos );
if IsHomalgGenerators( gen ) then
return MatrixOfGenerators( gen );
fi;
return fail;
end );
##
InstallMethod( MatrixOfRelations,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local rel;
rel := RelationsOfModule( M );
if IsHomalgRelations( rel ) then
return EvaluatedMatrixOfRelations( rel );
fi;
return fail;
end );
##
InstallMethod( MatrixOfRelations,
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
local rel;
rel := RelationsOfModule( M, pos );
if IsHomalgRelations( rel ) then
return MatrixOfRelations( rel );
fi;
return fail;
end );
##
InstallMethod( PresentationMorphism,
"for homalg modules",
[ IsFinitelyPresentedModuleRep, IsPosInt ],
function( M, pos )
local rel, pres, epi;
if IsBound(M!.PresentationMorphisms.( pos )) then
return M!.PresentationMorphisms.( pos );
fi;
rel := RelationsOfModule( M );
## "COMPUTE_SMALLER_BASIS" saves computations
pres := ReducedBasisOfModule( rel, "COMPUTE_SMALLER_BASIS" );
pres := HomalgMap( pres );
if not HasCokernelEpi( pres ) then
## the zero'th component of the quasi-isomorphism,
## which in this case is simply the natural epimorphism onto the module
epi := HomalgIdentityMap( Range( pres ), M );
SetIsEpimorphism( epi, true );
SetCokernelEpi( pres, epi );
fi;
M!.PresentationMorphisms.( pos ) := pres;
return pres;
end );
##
InstallMethod( PresentationMorphism,
"for homalg modules",
[ IsHomalgModule ],
function( M )
return PresentationMorphism( M, PositionOfTheDefaultPresentation( M ) );
end );
##
InstallMethod( HasNrGenerators,
"for homalg modules",
[ IsHomalgModule ],
function( M )
return HasNrGenerators( GeneratorsOfModule( M ) );
end );
##
InstallMethod( NrGenerators,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local g;
g := NrGenerators( GeneratorsOfModule( M ) );
if g = 0 then
SetIsZero( M, true );
elif IsFinitelyPresentedModuleOrSubmoduleRep( M ) and
HasRankOfObject( M ) and RankOfObject( M ) = g then
SetIsFree( M, true );
fi;
return g;
end );
##
InstallMethod( HasNrGenerators,
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
local gen;
gen := GeneratorsOfModule( M, pos );
if IsHomalgGenerators( gen ) then
return HasNrGenerators( gen );
fi;
return fail;
end );
##
InstallMethod( NrGenerators,
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
local gen;
gen := GeneratorsOfModule( M, pos );
if IsHomalgGenerators( gen ) then
return NrGenerators( gen );
fi;
return fail;
end );
##
InstallMethod( CertainGenerators,
"for homalg modules",
[ IsHomalgModule, IsList ],
function( M, list )
return CertainGenerators( GeneratorsOfModule( M ), list );
end );
##
InstallMethod( CertainGenerator,
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
return CertainGenerator( GeneratorsOfModule( M ), pos );
end );
##
InstallMethod( GetGenerators,
"for a homalg static object, fail, and a positive integer",
[ IsHomalgStaticObject, IsObject, IsPosInt ],
function( M, g, pos )
return GetGenerators( M, [ 1 .. NrGenerators( M ) ], pos );
end );
##
InstallMethod( GetGenerators,
"for a homalg module and two positive integers",
[ IsHomalgModule, IsPosInt, IsPosInt ],
function( M, g, pos )
local AdjustedGenerators, G, Functor, proc;
if not IsBound( M!.AdjustedGenerators ) then
M!.AdjustedGenerators := rec( );
fi;
AdjustedGenerators := M!.AdjustedGenerators;
if not IsBound( AdjustedGenerators.(String( pos )) ) then
AdjustedGenerators.(String( pos )) := [ ];
fi;
AdjustedGenerators := AdjustedGenerators.(String( pos ));
if IsBound( AdjustedGenerators[g] ) then
return AdjustedGenerators[g];
fi;
G := GetGenerators( GeneratorsOfModule( M, pos ), g );
# we want ot search the latest functor first, because this
# functor should be able to override the functors it uses.
for Functor in Reversed( FunctorsOfGenesis( M ) ) do
if IsBound( Functor!.GlobalName ) then
Functor := ValueGlobal( Functor!.GlobalName );
fi;
if IsHomalgFunctor( Functor )
and HasProcedureToReadjustGenerators( Functor ) then
proc := ProcedureToReadjustGenerators( Functor );
G := CallFuncList( proc, Concatenation( [ G ], ArgumentsOfGenesis( M ) ) );
break;
fi;
od;
AdjustedGenerators[g] := G;
return G;
end );
##
InstallMethod( GetGenerators,
"for a homalg static object, a list, and a positive integer",
[ IsHomalgStaticObject, IsList, IsPosInt ],
function( M, g, pos )
return List( g, i -> GetGenerators( M, i, pos ) );
end );
##
InstallMethod( GetGenerators,
"for a homalg static object and a positive integer",
[ IsHomalgStaticObject, IsPosInt ],
function( M, g )
return GetGenerators( M, g, PositionOfTheDefaultSetOfGenerators( M ) );
end );
##
InstallMethod( GetGenerators,
"for a homalg static object, a list, and a positive integer",
[ IsHomalgStaticObject, IsList ],
function( M, g )
return GetGenerators( M, g, PositionOfTheDefaultSetOfGenerators( M ) );
end );
##
InstallMethod( GetGenerators,
"for a homalg static object, a list, and a positive integer",
[ IsHomalgStaticObject ],
function( M )
return GetGenerators( M, [ 1 .. NrGenerators( M ) ] );
end );
##
InstallMethod( HasNrRelations,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local rel;
rel := RelationsOfModule( M );
if IsHomalgRelations( rel ) then
return HasNrRelations( rel );
fi;
return fail;
end );
##
InstallMethod( NrRelations,
"for homalg modules",
[ IsHomalgModule ],
function( M )
local rel, r;
rel := RelationsOfModule( M );
if IsHomalgRelations( rel ) then
r := NrRelations( rel );
if r = 0 then
SetIsFree( M, true );
fi;
return r;
fi;
return fail;
end );
##
InstallMethod( HasNrRelations,
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
local rel;
rel := RelationsOfModule( M, pos );
if IsHomalgRelations( rel ) then
return HasNrRelations( rel );
fi;
return fail;
end );
##
InstallMethod( NrRelations,
"for homalg modules",
[ IsHomalgModule, IsPosInt ],
function( M, pos )
local rel;
rel := RelationsOfModule( M, pos );
if IsHomalgRelations( rel ) then
return NrRelations( rel );
fi;
return fail;
end );
##
InstallMethod( TransitionMatrix,
"for homalg modules",
[ IsFinitelyPresentedModuleRep, IsInt, IsInt ],
function( M, pos1, pos2 )
local pres_a, pres_b, sets_of_generators, tr, sign, i, j;
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
pres_a := pos2;
pres_b := pos1;
else
pres_a := pos1;
pres_b := pos2;
fi;
if pres_a < 1 then
pres_a := PositionOfTheDefaultPresentation( M );
fi;
if pres_b < 1 then
pres_b := PositionOfTheDefaultPresentation( M );
fi;
sets_of_generators := M!.SetsOfGenerators;
if not IsBound( sets_of_generators!.( pres_a ) ) then
Error( "the module given as the first argument has no ", pres_a, ". set of generators\n" );
elif not IsBound( sets_of_generators!.( pres_b ) ) then
Error( "the module given as the first argument has no ", pres_b, ". set of generators\n" );
elif pres_a = pres_b then
return HomalgIdentityMatrix( NrGenerators( sets_of_generators!.( pres_a ) ), HomalgRing( M ) );
else
## starting with the identity is no waste of performance since the subpackage LIMAT is active:
tr := HomalgIdentityMatrix( NrGenerators( sets_of_generators!.( pres_a ) ), HomalgRing( M ) );
sign := SignInt( pres_b - pres_a );
i := pres_a;
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
while AbsInt( pres_b - i ) > 0 do
for j in pres_b - sign * [ 0 .. AbsInt( pres_b - i ) - 1 ] do
if IsBound( M!.TransitionMatrices.( String( [ j, i ] ) ) ) then
tr := M!.TransitionMatrices.( String( [ j, i ] ) ) * tr;
i := j;
break;
fi;
od;
od;
else
while AbsInt( pres_b - i ) > 0 do
for j in pres_b - sign * [ 0 .. AbsInt( pres_b - i ) - 1 ] do
if IsBound( M!.TransitionMatrices.( String( [ i, j ] ) ) ) then
tr := tr * M!.TransitionMatrices.( String( [ i, j ] ) );
i := j;
break;
fi;
od;
od;
fi;
return tr;
fi;
end );
##
InstallMethod( LockObjectOnCertainPresentation,
"for homalg modules",
[ IsFinitelyPresentedModuleRep, IsInt ],
function( M, p )
## first save the current setting
M!.LockObjectOnCertainPresentation := PositionOfTheDefaultPresentation( M );
SetPositionOfTheDefaultPresentation( M, p );
end );
##
InstallMethod( LockObjectOnCertainPresentation,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
LockObjectOnCertainPresentation( M, PositionOfTheDefaultPresentation( M ) );
end );
##
InstallMethod( UnlockObject,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
## first restore the saved settings
if IsBound( M!.LockObjectOnCertainPresentation ) then
SetPositionOfTheDefaultPresentation( M, M!.LockObjectOnCertainPresentation );
Unbind( M!.LockObjectOnCertainPresentation );
fi;
end );
##
InstallMethod( IsLockedObject,
"for homalg modules",
[ IsHomalgModule ],
function( M )
return IsBound( M!.LockObjectOnCertainPresentation );
end );
##
InstallMethod( AddANewPresentation,
"for homalg modules",
[ IsHomalgModule, IsGeneratorsOfFinitelyGeneratedModuleRep ],
function( M, gen )
local rels, gens, d, l, id, tr, itr;
if not ( IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) and IsHomalgGeneratorsOfLeftModule( gen ) )
and not ( IsHomalgRightObjectOrMorphismOfRightObjects( M ) and IsHomalgGeneratorsOfRightModule( gen ) ) then
Error( "the module and the new set of generators must either be both left or both right\n" );
fi;
rels := SetsOfRelations( M );
gens := SetsOfGenerators( M );
d := PositionOfTheDefaultPresentation( M );
l := PositionOfLastStoredSetOfRelations( rels );
## define the (l+1)st set of generators:
gens!.(l+1) := gen;
## adjust the list of positions:
gens!.ListOfPositionsOfKnownSetsOfGenerators[l+1] := l+1; ## the list is allowed to contain holes (sparse list)
## define the (l+1)st set of relations:
if IsBound( rels!.(d) ) then
rels!.(l+1) := rels!.(d);
fi;
## adjust the list of positions:
rels!.ListOfPositionsOfKnownSetsOfRelations[l+1] := l+1; ## the list is allowed to contain holes (sparse list)
id := HomalgIdentityMatrix( NrGenerators( M ), HomalgRing( M ) );
## no need to distinguish between left and right modules here:
M!.TransitionMatrices.( String( [ d, l+1 ] ) ) := id;
M!.TransitionMatrices.( String( [ l+1, d ] ) ) := id;
if d <> l then
## starting with the identity is no waste of performance since the subpackage LIMAT is active:
tr := id; itr := id;
if IsHomalgGeneratorsOfLeftModule( gen ) then
tr := tr * TransitionMatrix( M, d, l );
itr := TransitionMatrix( M, l, d ) * itr;
M!.TransitionMatrices.( String( [ l+1, l ] ) ) := tr;
M!.TransitionMatrices.( String( [ l, l+1 ] ) ) := itr;
else
tr := TransitionMatrix( M, l, d ) * tr;
itr := itr * TransitionMatrix( M, d, l );
M!.TransitionMatrices.( String( [ l, l+1 ] ) ) := tr;
M!.TransitionMatrices.( String( [ l+1, l ] ) ) := itr;
fi;
fi;
## adjust the default position:
if IsLockedObject( M ) then
M!.LockObjectOnCertainPresentation := l+1;
else
SetPositionOfTheDefaultPresentation( M, l+1 );
fi;
if NrGenerators( gen ) = 0 then
SetIsZero( M, true );
elif NrGenerators( gen ) = 1 then
SetIsCyclic( M, true );
fi;
return M;
end );
##
InstallMethod( AddANewPresentation,
"for homalg modules",
[ IsFinitelyPresentedModuleRep, IsRelationsOfFinitelyPresentedModuleRep ],
function( M, rel )
local rels, rev_lpos, d, gens, l, id, tr, itr;
if not ( IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) and IsHomalgRelationsOfLeftModule( rel ) )
and not ( IsHomalgRightObjectOrMorphismOfRightObjects( M ) and IsHomalgRelationsOfRightModule( rel ) ) then
Error( "the module and the new set of relations must either be both left or both right\n" );
fi;
rels := SetsOfRelations( M );
## we reverse since we want to check the recent sets of relations first
rev_lpos := Reversed( rels!.ListOfPositionsOfKnownSetsOfRelations );
## don't add an old set of relations, but let it be the default set of relations instead:
for d in rev_lpos do
if IsIdenticalObj( rel, rels!.(d) ) then
if IsLockedObject( M ) then
M!.LockObjectOnCertainPresentation := d;
else
SetPositionOfTheDefaultPresentation( M, d );
fi;
return M;
fi;
od;
for d in rev_lpos do
if MatrixOfRelations( rel ) = MatrixOfRelations( rels!.(d) ) then
if IsLockedObject( M ) then
M!.LockObjectOnCertainPresentation := d;
else
SetPositionOfTheDefaultPresentation( M, d );
fi;
return M;
fi;
od;
gens := SetsOfGenerators( M );
d := PositionOfTheDefaultPresentation( M );
l := PositionOfLastStoredSetOfRelations( rels );
## define the (l+1)st set of generators:
gens!.(l+1) := gens!.(d);
## adjust the list of positions:
gens!.ListOfPositionsOfKnownSetsOfGenerators[l+1] := l+1; ## the list is allowed to contain holes (sparse list)
## define the (l+1)st set of relations:
rels!.(l+1) := rel;
## adjust the list of positions:
rels!.ListOfPositionsOfKnownSetsOfRelations[l+1] := l+1; ## the list is allowed to contain holes (sparse list)
id := HomalgIdentityMatrix( NrGenerators( M ), HomalgRing( M ) );
## no need to distinguish between left and right modules here:
M!.TransitionMatrices.( String( [ d, l+1 ] ) ) := id;
M!.TransitionMatrices.( String( [ l+1, d ] ) ) := id;
if d <> l then
## starting with the identity is no waste of performance since the subpackage LIMAT is active:
tr := id; itr := id;
if IsHomalgRelationsOfLeftModule( rel ) then
tr := tr * TransitionMatrix( M, d, l );
itr := TransitionMatrix( M, l, d ) * itr;
M!.TransitionMatrices.( String( [ l+1, l ] ) ) := tr;
M!.TransitionMatrices.( String( [ l, l+1 ] ) ) := itr;
else
tr := TransitionMatrix( M, l, d ) * tr;
itr := itr * TransitionMatrix( M, d, l );
M!.TransitionMatrices.( String( [ l, l+1 ] ) ) := tr;
M!.TransitionMatrices.( String( [ l+1, l ] ) ) := itr;
fi;
fi;
## adjust the default position:
if IsLockedObject( M ) then
M!.LockObjectOnCertainPresentation := l+1;
else
SetPositionOfTheDefaultPresentation( M, l+1 );
fi;
SetParent( rel, M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( rel, M );
return M;
end );
##
InstallMethod( AddANewPresentation,
"for homalg modules",
[ IsFinitelyPresentedModuleRep, IsRelationsOfFinitelyPresentedModuleRep, IsHomalgMatrix, IsHomalgMatrix ],
function( M, rel, T, TI )
local rels, gens, d, l, gen, tr, itr;
if not ( IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) and IsHomalgRelationsOfLeftModule( rel ) )
and not ( IsHomalgRightObjectOrMorphismOfRightObjects( M ) and IsHomalgRelationsOfRightModule( rel ) ) then
Error( "the module and the new set of relations must either be both left or both right\n" );
fi;
rels := SetsOfRelations( M );
gens := SetsOfGenerators( M );
d := PositionOfTheDefaultPresentation( M );
l := PositionOfLastStoredSetOfRelations( rels );
gen := TI * GeneratorsOfModule( M );
## define the (l+1)st set of generators:
gens!.(l+1) := gen;
## adjust the list of positions:
gens!.ListOfPositionsOfKnownSetsOfGenerators[l+1] := l+1; ## the list is allowed to contain holes (sparse list)
## define the (l+1)st set of relations:
rels!.(l+1) := rel;
## adjust the list of positions:
rels!.ListOfPositionsOfKnownSetsOfRelations[l+1] := l+1; ## the list is allowed to contain holes (sparse list)
if IsHomalgRelationsOfLeftModule( rel ) then
M!.TransitionMatrices.( String( [ d, l+1 ] ) ) := T;
M!.TransitionMatrices.( String( [ l+1, d ] ) ) := TI;
else
M!.TransitionMatrices.( String( [ l+1, d ] ) ) := T;
M!.TransitionMatrices.( String( [ d, l+1 ] ) ) := TI;
fi;
if d <> l then
tr := TI; itr := T;
if IsHomalgRelationsOfLeftModule( rel ) then
tr := tr * TransitionMatrix( M, d, l );
itr := TransitionMatrix( M, l, d ) * itr;
M!.TransitionMatrices.( String( [ l+1, l ] ) ) := tr;
M!.TransitionMatrices.( String( [ l, l+1 ] ) ) := itr;
else
tr := TransitionMatrix( M, l, d ) * tr;
itr := itr * TransitionMatrix( M, d, l );
M!.TransitionMatrices.( String( [ l, l+1 ] ) ) := tr;
M!.TransitionMatrices.( String( [ l+1, l ] ) ) := itr;
fi;
fi;
## adjust the default position:
if IsLockedObject( M ) then
M!.LockObjectOnCertainPresentation := l+1;
else
SetPositionOfTheDefaultPresentation( M, l+1 );
fi;
if NrGenerators( rel ) = 0 then
SetIsZero( M, true );
elif NrGenerators( rel ) = 1 then
SetIsCyclic( M, true );
fi;
SetParent( rel, M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( rel, M );
return M;
end );
##
InstallMethod( BasisOfModule, ### CAUTION: has the side effect of possibly affecting the module M
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
local rel, bas, mat, R, rk;
rel := RelationsOfModule( M );
if not ( HasCanBeUsedToDecideZeroEffectively( rel ) and CanBeUsedToDecideZeroEffectively( rel ) ) then
bas := BasisOfModule( rel ); ## CAUTION: might have a side effect on rel
if not IsIdenticalObj( rel, bas ) then
AddANewPresentation( M, bas ); ## this might set CanBeUsedToDecideZeroEffectively( rel ) to true
fi;
fi;
return RelationsOfModule( M );
end );
##
InstallMethod( OnBasisOfPresentation,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
BasisOfModule( M );
return M;
end );
##
InstallMethod( DecideZero,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
local gen, red;
gen := GeneratorsOfModule( M );
if HasIsReduced( gen ) and IsReduced( gen ) then
return gen;
fi;
red := DecideZero( gen );
if IsIdenticalObj( gen, red ) then
return gen;
fi;
AddANewPresentation( M, red );
return red;
end );
##
InstallMethod( DecideZero,
"for homalg modules",
[ IsHomalgMatrix, IsFinitelyPresentedModuleRep ],
function( mat, M )
local rel;
rel := RelationsOfModule( M );
return DecideZero( mat, rel );
end );
##
InstallMethod( UnionOfRelations,
"for homalg modules",
[ IsHomalgMatrix, IsFinitelyPresentedModuleRep ],
function( mat, M )
return UnionOfRelations( mat, RelationsOfModule( M ) );
end );
##
InstallMethod( SyzygiesGenerators,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
return SyzygiesGenerators( RelationsOfModule( M ) );
end );
##
InstallMethod( SyzygiesGenerators,
"for homalg modules",
[ IsHomalgMatrix, IsFinitelyPresentedModuleRep ],
function( mat, M )
return SyzygiesGenerators( mat, RelationsOfModule( M ) );
end );
##
InstallMethod( ReducedSyzygiesGenerators,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
return ReducedSyzygiesGenerators( RelationsOfModule( M ) );
end );
##
InstallMethod( ReducedSyzygiesGenerators,
"for homalg modules",
[ IsHomalgMatrix, IsFinitelyPresentedModuleRep ],
function( mat, M )
return ReducedSyzygiesGenerators( mat, RelationsOfModule( M ) );
end );
##
InstallMethod( NonZeroGenerators,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
return NonZeroGenerators( BasisOfModule( RelationsOfModule( M ) ) ); ## don't delete RelationsOfModule, since we don't want to add too much new relations to the module in an early stage!
end );
##
InstallMethod( GetRidOfZeroGenerators, ### defines: GetRidOfZeroGenerators (BetterPresentation)
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
local bl, rel, id, T, TI;
bl := NonZeroGenerators( M );
if Length( bl ) < NrGenerators( M ) then
rel := MatrixOfRelations( M );
id := HomalgIdentityMatrix( NrGenerators( M ), HomalgRing( M ) );
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
rel := CertainColumns( rel, bl );
rel := CertainRows( rel, NonZeroRows( rel ) );
rel := HomalgRelationsForLeftModule( rel, M );
T := CertainColumns( id, bl );
TI := CertainRows( id, bl );
else
rel := CertainRows( rel, bl );
rel := CertainColumns( rel, NonZeroColumns( rel ) );
rel := HomalgRelationsForRightModule( rel, M );
T := CertainRows( id, bl );
TI := CertainColumns( id, bl );
fi;
AddANewPresentation( M, rel, T, TI );
if NrGenerators( M ) = 1 then
SetIsCyclic( M, true );
fi;
fi;
return M;
end );
#=======================================================================
# Compute a smaller presentation allowing the transformation of the generators
# (i.e. allowing column/row operations for left/right relation matrices)
#_______________________________________________________________________
##
InstallMethod( OnLessGenerators,
"for homalg modules",
[ IsFinitelyPresentedModuleRep and IsHomalgRightObjectOrMorphismOfRightObjects ],
function( M )
local R, rel_old, rel, U, UI;
R := HomalgRing( M );
rel_old := MatrixOfRelations( M );
U := HomalgVoidMatrix( R );
UI := HomalgVoidMatrix( R );
rel := SimplerEquivalentMatrix( rel_old, U, UI, "", "", "" );
if not rel_old = rel then
rel := HomalgRelationsForRightModule( rel, M );
AddANewPresentation( M, rel, U, UI );
fi;
return GetRidOfZeroGenerators( M );
end );
##
InstallMethod( OnLessGenerators,
"for homalg modules",
[ IsFinitelyPresentedModuleRep and IsHomalgLeftObjectOrMorphismOfLeftObjects ],
function( M )
local R, rel_old, rel, V, VI;
R := HomalgRing( M );
rel_old := MatrixOfRelations( M );
V := HomalgVoidMatrix( R );
VI := HomalgVoidMatrix( R );
rel := SimplerEquivalentMatrix( rel_old, V, VI, "", "" );
if not rel_old = rel then
rel := HomalgRelationsForLeftModule( rel, M );
AddANewPresentation( M, rel, V, VI );
fi;
return GetRidOfZeroGenerators( M );
end );
## <#GAPDoc Label="ByASmallerPresentation:module">
## <ManSection>
## <Meth Arg="M" Name="ByASmallerPresentation" Label="for modules"/>
## <Returns>a &homalg; module</Returns>
## <Description>
## Use different strategies to reduce the presentation of the given &homalg; module <A>M</A>.
## This method performs side effects on its argument <A>M</A> and returns it.
## <Example><![CDATA[
## gap> zz := HomalgRingOfIntegers( );;
## gap> M := HomalgMatrix( "[ \
## > 2, 3, 4, \
## > 5, 6, 7 \
## > ]", 2, 3, zz );
## <A 2 x 3 matrix over an internal ring>
## gap> M := LeftPresentation( M );
## <A non-torsion left module presented by 2 relations for 3 generators>
## gap> Display( M );
## [ [ 2, 3, 4 ],
## [ 5, 6, 7 ] ]
##
## Cokernel of the map
##
## Z^(1x2) --> Z^(1x3),
##
## currently represented by the above matrix
## gap> ByASmallerPresentation( M );
## <A rank 1 left module presented by 1 relation for 2 generators>
## gap> Display( last );
## Z/< 3 > + Z^(1 x 1)
## gap> SetsOfGenerators( M );
## <A set containing 2 sets of generators of a homalg module>
## gap> SetsOfRelations( M );
## <A set containing 2 sets of relations of a homalg module>
## gap> M;
## <A rank 1 left module presented by 1 relation for 2 generators>
## gap> SetPositionOfTheDefaultPresentation( M, 1 );
## gap> M;
## <A rank 1 left module presented by 2 relations for 3 generators>
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
InstallMethod( ByASmallerPresentation,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
local g, r, p, rel;
while true do
g := NrGenerators( M );
r := NrRelations( M );
p := PositionOfTheDefaultSetOfGenerators( M );
OnLessGenerators( M );
if NrGenerators( M ) = g then ## try to compute a basis first
rel := RelationsOfModule( M, p );
if not ( HasCanBeUsedToDecideZeroEffectively( rel ) and
CanBeUsedToDecideZeroEffectively( rel ) ) then
SetPositionOfTheDefaultSetOfGenerators( M, p ); ## just in case
if not ValueOption( "BasisOfModule" ) = false then
BasisOfModule( M );
fi;
OnLessGenerators( M );
fi;
fi;
if NrGenerators( M ) = g then ## there is nothing we can do more!
break;
fi;
od;
if not ( IsBound( HOMALG_MODULES.ByASmallerPresentationDoesNotDecideZero ) and
HOMALG_MODULES.ByASmallerPresentationDoesNotDecideZero = true )
and NrRelations( M ) > 0 then
## Fixme: also generators of free modules can be reduced;
## this should become lazy with the introduction of intrinsic categories
DecideZero( M );
fi;
return M;
end );
##
InstallMethod( ElementaryDivisors,
"for homalg modules",
[ IsFinitelyPresentedModuleRep ],
function( M )
local rel, b, R, RP, e;
R := HomalgRing( M );
RP := homalgTable( R );
if IsBound( RP!.ElementaryDivisors ) then
e := RP!.ElementaryDivisors( MatrixOfRelations( M ) );
if IsString( e ) then
e := StringToElementStringList( e );
e := List( e, a -> HomalgRingElement( a, R ) );
fi;
## since the computer algebra systems have different
## conventions for elementary divisors, we fix our own here:
e := Filtered( e, x -> not IsOne( x ) and not IsZero( x ) );
Append( e, ListWithIdenticalEntries( RankOfObject( M ), Zero( R ) ) );
return e;
fi;
TryNextMethod( );
end );
##
InstallMethod( ElementaryDivisors,
"for homalg modules",
[ IsFinitelyPresentedModuleRep and IsZero ],
function( M )
return [ ];
end );
##
InstallMethod( ElementaryDivisors,
"for homalg modules",
[ IsFinitelyPresentedModuleRep and IsFree ],
function( M )
local R;
R := HomalgRing( M );
return ListWithIdenticalEntries( NrGenerators( M ), Zero( R ) );
end );
##
InstallMethod( SetUpperBoundForProjectiveDimension,
"for homalg modules",
[ IsHomalgModule, IsInfinity ],
function( M, ub_pd )
## do nothing
end );
##
InstallMethod( SetUpperBoundForProjectiveDimension,
"for homalg modules",
[ IsHomalgModule, IsInt ],
function( M, ub_pd )
local left, R, ub, min;
if not HasProjectiveDimension( M ) then ## otherwise don't do anything
if ub_pd < 0 then
## decrease the upper bound by |ub_pd| *relative* to the left/right global dimension of the ring:
left := IsHomalgLeftObjectOrMorphismOfLeftObjects( M );
R := HomalgRing( M );
if left and HasLeftGlobalDimension( R ) and IsInt( LeftGlobalDimension( R ) ) then
ub := LeftGlobalDimension( R ) + ub_pd; ## recall, ub_pd < 0
if ub < 0 then
SetProjectiveDimension( M, 0 );
else
SetUpperBoundForProjectiveDimension( M, ub ); ## ub >= 0
fi;
elif not left and HasRightGlobalDimension( R ) and IsInt( RightGlobalDimension( R ) ) then
ub := RightGlobalDimension( R ) + ub_pd; ## recall, ub_pd < 0
if ub < 0 then
SetProjectiveDimension( M, 0 );
else
SetUpperBoundForProjectiveDimension( M, ub ); ## ub >= 0
fi;
fi;
else
## set the upper bound to ub_pd:
if IsBound( M!.UpperBoundForProjectiveDimension ) then
min := Minimum( M!.UpperBoundForProjectiveDimension, ub_pd );
else
min := ub_pd;
fi;
M!.UpperBoundForProjectiveDimension := min;
if min = 0 then
SetProjectiveDimension( M, 0 );
elif min = 1 and HasIsProjective( M ) and not IsProjective( M ) then
SetProjectiveDimension( M, 1 );
fi;
fi;
fi;
end );
####################################
#
# constructor functions and methods:
#
####################################
##
InstallMethod( ZeroLeftModule,
"for homalg rings",
[ IsHomalgRing ],
function( R )
local zero;
if IsBound(R!.ZeroLeftModule) then
return R!.ZeroLeftModule;
fi;
zero := HomalgZeroLeftModule( R );
zero!.distinguished := true;
R!.ZeroLeftModule := zero;
return zero;
end );
##
InstallMethod( ZeroRightModule,
"for homalg rings",
[ IsHomalgRing ],
function( R )
local zero;
if IsBound(R!.ZeroRightModule) then
return R!.ZeroRightModule;
fi;
zero := HomalgZeroRightModule( R );
zero!.distinguished := true;
R!.ZeroRightModule := zero;
return zero;
end );
##
InstallMethod( AsLeftObject,
"for homalg rings",
[ IsHomalgRing ],
function( R )
local left;
if IsBound(R!.AsLeftObject) then
return R!.AsLeftObject;
fi;
left := HomalgFreeLeftModule( 1, R );
left!.distinguished := true;
left!.not_twisted := true;
R!.AsLeftObject := left;
return left;
end );
##
InstallMethod( AsRightObject,
"for homalg rings",
[ IsHomalgRing ],
function( R )
local right;
if IsBound(R!.AsRightObject) then
return R!.AsRightObject;
fi;
right := HomalgFreeRightModule( 1, R );
right!.distinguished := true;
right!.not_twisted := true;
R!.AsRightObject := right;
return right;
end );
##
InstallMethod( HomalgCategory,
"constructor for module categories",
[ IsHomalgRing, IsString ],
function( R, parity )
local A;
if parity = "right" and IsBound( R!.category_of_fp_right_modules ) then
return R!.category_of_fp_right_modules;
elif IsBound( R!.category_of_fp_left_modules ) then
return R!.category_of_fp_left_modules;
fi;
A := ShallowCopy( HOMALG_MODULES.category );
A.containers := rec( );
A.ring := R;
if parity = "right" then
Objectify( TheTypeCategoryOfFinitelyPresentedRightModules, A );
R!.category_of_fp_right_modules := A;
else
Objectify( TheTypeCategoryOfFinitelyPresentedLeftModules, A );
R!.category_of_fp_left_modules := A;
fi;
if IsHomalgInternalRingRep( R ) then
A!.do_not_cache_values_of_some_functors := true;
fi;
return A;
end );
##
InstallGlobalFunction( RecordForPresentation,
function( R, gens, rels )
local string, string_plural, M;
if HasIsDivisionRingForHomalg( R ) and IsDivisionRingForHomalg( R ) then
string := "vector space";
string_plural := "vector spaces";
else
string := "module";
string_plural := "modules";
fi;
M := rec( string := string,
string_plural := string_plural,
ring := R,
SetsOfGenerators := gens,
SetsOfRelations := rels,
PresentationMorphisms := rec( ),
Resolutions := rec( ),
TransitionMatrices := rec( ),
PositionOfTheDefaultPresentation := 1 );
if IsHomalgRelationsOfLeftModule( rels ) then
M.category := HomalgCategory( R, "left" );
else
M.category := HomalgCategory( R, "right" );
fi;
return M;
end );
##
InstallMethod( Presentation,
"constructor for homalg modules",
[ IsRelationsOfFinitelyPresentedModuleRep and IsHomalgRelationsOfLeftModule ],
function( rel )
local R, is_zero_module, gens, rels, M;
R := HomalgRing( rel );
if NrGenerators( rel ) = 0 then ## since one doesn't specify generators here giving no relations defines the zero module
gens := CreateSetsOfGeneratorsForLeftModule( [ ], R );
is_zero_module := true;
else
gens := CreateSetsOfGeneratorsForLeftModule(
HomalgIdentityMatrix( NrGenerators( rel ), R ), rel );
fi;
rels := CreateSetsOfRelationsForLeftModule( rel );
M := RecordForPresentation( R, gens, rels );
## Objectify:
if IsBound( is_zero_module ) then
ObjectifyWithAttributes(
M, TheTypeHomalgLeftFinitelyPresentedModule,
LeftActingDomain, R,
GeneratorsOfLeftOperatorAdditiveGroup, M!.SetsOfGenerators!.1,
IsZero, true );
else
ObjectifyWithAttributes(
M, TheTypeHomalgLeftFinitelyPresentedModule,
LeftActingDomain, R,
GeneratorsOfLeftOperatorAdditiveGroup, M!.SetsOfGenerators!.1 );
if HasLeftGlobalDimension( R ) then
SetUpperBoundForProjectiveDimension( M, LeftGlobalDimension( R ) );
fi;
fi;
# SetParent( gens, M );
SetParent( rel, M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( rel, M );
return M;
end );
##
InstallMethod( Presentation,
"constructor for homalg modules",
[ IsGeneratorsOfFinitelyGeneratedModuleRep and IsHomalgGeneratorsOfLeftModule,
IsRelationsOfFinitelyPresentedModuleRep and IsHomalgRelationsOfLeftModule ],
function( gen, rel )
local R, is_zero_module, gens, rels, M;
if NrGenerators( gen ) <> NrGenerators( rel ) then
Error( "the first argument is a set of ", NrGenerators( gen ), " generator(s) while the second argument is a set of relations for ", NrGenerators( rel ), " generators\n" );
fi;
R := HomalgRing( rel );
gens := CreateSetsOfGeneratorsForLeftModule( gen );
if NrGenerators( rel ) = 0 then
is_zero_module := true;
fi;
rels := CreateSetsOfRelationsForLeftModule( rel );
M := RecordForPresentation( R, gens, rels );
## Objectify:
if IsBound( is_zero_module ) then
ObjectifyWithAttributes(
M, TheTypeHomalgLeftFinitelyPresentedModule,
LeftActingDomain, R,
GeneratorsOfLeftOperatorAdditiveGroup, M!.SetsOfGenerators!.1,
IsZero, true );
else
ObjectifyWithAttributes(
M, TheTypeHomalgLeftFinitelyPresentedModule,
LeftActingDomain, R,
GeneratorsOfLeftOperatorAdditiveGroup, M!.SetsOfGenerators!.1 );
if HasLeftGlobalDimension( R ) then
SetUpperBoundForProjectiveDimension( M, LeftGlobalDimension( R ) );
fi;
fi;
# SetParent( gens, M );
SetParent( rel, M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( rel, M );
return M;
end );
##
InstallMethod( Presentation,
"constructor for homalg modules",
[ IsRelationsOfFinitelyPresentedModuleRep and IsHomalgRelationsOfRightModule ],
function( rel )
local R, is_zero_module, gens, rels, M;
R := HomalgRing( rel );
if NrGenerators( rel ) = 0 then ## since one doesn't specify generators here giving no relations defines the zero module
gens := CreateSetsOfGeneratorsForRightModule( [ ], R );
is_zero_module := true;
else
gens := CreateSetsOfGeneratorsForRightModule(
HomalgIdentityMatrix( NrGenerators( rel ), R ), rel );
fi;
rels := CreateSetsOfRelationsForRightModule( rel );
M := RecordForPresentation( R, gens, rels );
## Objectify:
if IsBound( is_zero_module ) then
ObjectifyWithAttributes(
M, TheTypeHomalgRightFinitelyPresentedModule,
RightActingDomain, R,
GeneratorsOfRightOperatorAdditiveGroup, M!.SetsOfGenerators!.1,
IsZero, true );
else
ObjectifyWithAttributes(
M, TheTypeHomalgRightFinitelyPresentedModule,
RightActingDomain, R,
GeneratorsOfRightOperatorAdditiveGroup, M!.SetsOfGenerators!.1 );
if HasRightGlobalDimension( R ) then
SetUpperBoundForProjectiveDimension( M, RightGlobalDimension( R ) );
fi;
fi;
# SetParent( gens, M );
SetParent( rel, M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( rel, M );
return M;
end );
##
InstallMethod( Presentation,
"constructor for homalg modules",
[ IsGeneratorsOfFinitelyGeneratedModuleRep and IsHomalgGeneratorsOfRightModule,
IsRelationsOfFinitelyPresentedModuleRep and IsHomalgRelationsOfRightModule ],
function( gen, rel )
local R, is_zero_module, gens, rels, M;
if NrGenerators( gen ) <> NrGenerators( rel ) then
Error( "the first argument is a set of ", NrGenerators( gen ), " generator(s) while the second argument is a set of relations for ", NrGenerators( rel ), " generators\n" );
fi;
R := HomalgRing( rel );
gens := CreateSetsOfGeneratorsForRightModule( gen );
if NrGenerators( rel ) = 0 then
is_zero_module := true;
fi;
rels := CreateSetsOfRelationsForRightModule( rel );
M := RecordForPresentation( R, gens, rels );
## Objectify:
if IsBound( is_zero_module ) then
ObjectifyWithAttributes(
M, TheTypeHomalgRightFinitelyPresentedModule,
RightActingDomain, R,
GeneratorsOfRightOperatorAdditiveGroup, M!.SetsOfGenerators!.1,
IsZero, true );
else
ObjectifyWithAttributes(
M, TheTypeHomalgRightFinitelyPresentedModule,
RightActingDomain, R,
GeneratorsOfRightOperatorAdditiveGroup, M!.SetsOfGenerators!.1 );
if HasRightGlobalDimension( R ) then
SetUpperBoundForProjectiveDimension( M, RightGlobalDimension( R ) );
fi;
fi;
# SetParent( gens, M );
SetParent( rel, M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( rel, M );
return M;
end );
##
InstallMethod( LeftPresentation,
"constructor for homalg modules",
[ IsList, IsHomalgRing ],
function( rel, R )
local gens, rels, M, is_zero_module;
if Length( rel ) = 0 then ## since one doesn't specify generators here giving no relations defines the zero module
gens := CreateSetsOfGeneratorsForLeftModule( [ ], R );
is_zero_module := true;
elif IsList( rel[1] ) and ForAll( rel[1], IsRingElement ) then
gens := CreateSetsOfGeneratorsForLeftModule(
HomalgIdentityMatrix( Length( rel[1] ), R ), rel );
else ## only one generator
gens := CreateSetsOfGeneratorsForLeftModule(
HomalgIdentityMatrix( 1, R ), rel );
fi;
rels := CreateSetsOfRelationsForLeftModule( rel, R );
M := RecordForPresentation( R, gens, rels );
## Objectify:
if IsBound( is_zero_module ) then
ObjectifyWithAttributes(
M, TheTypeHomalgLeftFinitelyPresentedModule,
LeftActingDomain, R,
GeneratorsOfLeftOperatorAdditiveGroup, M!.SetsOfGenerators!.1,
IsZero, true );
else
ObjectifyWithAttributes(
M, TheTypeHomalgLeftFinitelyPresentedModule,
LeftActingDomain, R,
GeneratorsOfLeftOperatorAdditiveGroup, M!.SetsOfGenerators!.1 );
if HasLeftGlobalDimension( R ) then
SetUpperBoundForProjectiveDimension( M, LeftGlobalDimension( R ) );
fi;
fi;
# SetParent( gens, M );
SetParent( RelationsOfModule( M ), M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( RelationsOfModule( M ), M );
return M;
end );
##
InstallMethod( LeftPresentation,
"constructor for homalg modules",
[ IsList, IsList, IsHomalgRing ],
function( gen, rel, R )
local gens, rels, M;
gens := CreateSetsOfGeneratorsForLeftModule( gen, R );
if rel = [ ] and gen <> [ ] then
rels := CreateSetsOfRelationsForLeftModule( "unknown relations", R );
else
rels := CreateSetsOfRelationsForLeftModule( rel, R );
fi;
M := RecordForPresentation( R, gens, rels );
## Objectify:
ObjectifyWithAttributes(
M, TheTypeHomalgLeftFinitelyPresentedModule,
LeftActingDomain, R,
GeneratorsOfLeftOperatorAdditiveGroup, M!.SetsOfGenerators!.1 );
if HasLeftGlobalDimension( R ) then
SetUpperBoundForProjectiveDimension( M, LeftGlobalDimension( R ) );
fi;
# SetParent( gens, M );
SetParent( RelationsOfModule( M ), M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( RelationsOfModule( M ), M );
return M;
end );
## <#GAPDoc Label="LeftPresentation">
## <ManSection>
## <Oper Arg="mat" Name="LeftPresentation" Label="constructor for left modules"/>
## <Returns>a &homalg; module</Returns>
## <Description>
## This constructor returns the finitely presented left module with relations given by the
## rows of the &homalg; matrix <A>mat</A>.
## <Example><![CDATA[
## gap> zz := HomalgRingOfIntegers( );;
## gap> M := HomalgMatrix( "[ \
## > 2, 3, 4, \
## > 5, 6, 7 \
## > ]", 2, 3, zz );
## <A 2 x 3 matrix over an internal ring>
## gap> M := LeftPresentation( M );
## <A non-torsion left module presented by 2 relations for 3 generators>
## gap> Display( M );
## [ [ 2, 3, 4 ],
## [ 5, 6, 7 ] ]
##
## Cokernel of the map
##
## Z^(1x2) --> Z^(1x3),
##
## currently represented by the above matrix
## gap> ByASmallerPresentation( M );
## <A rank 1 left module presented by 1 relation for 2 generators>
## gap> Display( last );
## Z/< 3 > + Z^(1 x 1)
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
InstallMethod( LeftPresentation,
"constructor for homalg modules",
[ IsHomalgMatrix ],
function( mat )
return Presentation( HomalgRelationsForLeftModule( mat ) );
end );
##
InstallMethod( RightPresentation,
"constructor for homalg modules",
[ IsList, IsHomalgRing ],
function( rel, R )
local gens, rels, M, is_zero_module;
if Length( rel ) = 0 then ## since one doesn't specify generators here giving no relations defines the zero module
gens := CreateSetsOfGeneratorsForRightModule( [ ], R );
is_zero_module := true;
elif IsList( rel[1] ) and ForAll( rel[1], IsRingElement ) then
gens := CreateSetsOfGeneratorsForRightModule(
HomalgIdentityMatrix( Length( rel ), R ), rel );
else ## only one generator
gens := CreateSetsOfGeneratorsForRightModule(
HomalgIdentityMatrix( 1, R ), rel );
fi;
rels := CreateSetsOfRelationsForRightModule( rel, R );
M := RecordForPresentation( R, gens, rels );
## Objectify:
if IsBound( is_zero_module ) then
ObjectifyWithAttributes(
M, TheTypeHomalgRightFinitelyPresentedModule,
RightActingDomain, R,
GeneratorsOfRightOperatorAdditiveGroup, M!.SetsOfGenerators!.1,
IsZero, true );
else
ObjectifyWithAttributes(
M, TheTypeHomalgRightFinitelyPresentedModule,
RightActingDomain, R,
GeneratorsOfRightOperatorAdditiveGroup, M!.SetsOfGenerators!.1 );
if HasRightGlobalDimension( R ) then
SetUpperBoundForProjectiveDimension( M, RightGlobalDimension( R ) );
fi;
fi;
# SetParent( gens, M );
SetParent( RelationsOfModule( M ), M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( RelationsOfModule( M ), M );
return M;
end );
##
InstallMethod( RightPresentation,
"constructor for homalg modules",
[ IsList, IsList, IsHomalgRing ],
function( gen, rel, R )
local gens, rels, M;
gens := CreateSetsOfGeneratorsForRightModule( gen, R );
if rel = [ ] and gen <> [ ] then
rels := CreateSetsOfRelationsForRightModule( "unknown relations", R );
else
rels := CreateSetsOfRelationsForRightModule( rel, R );
fi;
M := RecordForPresentation( R, gens, rels );
## Objectify:
ObjectifyWithAttributes(
M, TheTypeHomalgRightFinitelyPresentedModule,
RightActingDomain, R,
GeneratorsOfRightOperatorAdditiveGroup, M!.SetsOfGenerators!.1 );
if HasRightGlobalDimension( R ) then
SetUpperBoundForProjectiveDimension( M, RightGlobalDimension( R ) );
fi;
# SetParent( gens, M );
SetParent( RelationsOfModule( M ), M );
INSTALL_TODO_LIST_ENTRIES_FOR_RELATIONS_OF_MODULES( RelationsOfModule( M ), M );
return M;
end );
## <#GAPDoc Label="RightPresentation">
## <ManSection>
## <Oper Arg="mat" Name="RightPresentation" Label="constructor for right modules"/>
## <Returns>a &homalg; module</Returns>
## <Description>
## This constructor returns the finitely presented right module with relations given by the
## columns of the &homalg; matrix <A>mat</A>.
## <Example><![CDATA[
--> --------------------
--> maximum size reached
--> --------------------
[ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet)
]
|