Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346############################################################################# ## ## HomalgModule.gi Modules package Mohamed Barakat ## ## Copyright 2007-2010, Mohamed Barakat, University of Kaiserslautern ## ## 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( 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 .. NrRows( gens ) ], i -> CertainRows( gens, [ i ] ) ); else gens := List( [ 1 .. NrColumns( 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 BasisOfModule( M ); 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 ) and HasRankOfObject( M ) 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[ ## 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 := RightPresentation( M ); ## <A right module on 2 generators satisfying 3 relations> ## gap> ByASmallerPresentation( M ); ## <A cyclic torsion right module on a cyclic generator satisfying 1 relation> ## gap> Display( last ); ## Z/< 3 > ## ]]></Example> ## </Description> ## </ManSection> ## <#/GAPDoc> ## InstallMethod( RightPresentation, "constructor for homalg modules", [ IsHomalgMatrix ], function( mat ) return Presentation( HomalgRelationsForRightModule( mat ) ); end ); ## <#GAPDoc Label="HomalgFreeLeftModule"> ## <ManSection> ## <Oper Arg="r, R" Name="HomalgFreeLeftModule" Label="constructor for free left modules"/> ## <Returns>a &homalg; module</Returns> ## <Description> ## This constructor returns a free left module of rank <A>r</A> over the &homalg; ring <A>R</A>. ## <Example><![CDATA[ ## gap> ZZ := HomalgRingOfIntegers( );; ## gap> F := HomalgFreeLeftModule( 1, ZZ ); ## <A free left module of rank 1 on a free generator> ## gap> 1 * ZZ; ## <The free left module of rank 1 on a free generator> ## gap> F := HomalgFreeLeftModule( 2, ZZ ); ## <A free left module of rank 2 on free generators> ## gap> 2 * ZZ; ## <A free left module of rank 2 on free generators> ## ]]></Example> ## </Description> ## </ManSection> ## <#/GAPDoc> ## InstallMethod( HomalgFreeLeftModule, "constructor for homalg free modules", [ IsInt, IsHomalgRing ], function( rank, R ) return LeftPresentation( HomalgZeroMatrix( 0, rank, R ) ); end ); ## <#GAPDoc Label="HomalgFreeRightModule"> ## <ManSection> ## <Oper Arg="r, R" Name="HomalgFreeRightModule" Label="constructor for free right modules"/> ## <Returns>a &homalg; module</Returns> ## <Description> ## This constructor returns a free right module of rank <A>r</A> over the &homalg; ring <A>R</A>. ## <Example><![CDATA[ ## gap> ZZ := HomalgRingOfIntegers( );; ## gap> F := HomalgFreeRightModule( 1, ZZ ); ## <A free right module of rank 1 on a free generator> ## gap> ZZ * 1; ## <The free right module of rank 1 on a free generator> ## gap> F := HomalgFreeRightModule( 2, ZZ ); ## <A free right module of rank 2 on free generators> ## gap> ZZ * 2; ## <A free right module of rank 2 on free generators> ## ]]></Example> ## </Description> ## </ManSection> ## <#/GAPDoc> ## InstallMethod( HomalgFreeRightModule, "constructor for homalg free modules", [ IsInt, IsHomalgRing ], function( rank, R ) return RightPresentation( HomalgZeroMatrix( rank, 0, R ) ); end ); ## <#GAPDoc Label="HomalgZeroLeftModule"> ## <ManSection> ## <Oper Arg="r, R" Name="HomalgZeroLeftModule" Label="constructor for zero left modules"/> ## <Returns>a &homalg; module</Returns> ## <Description> ## This constructor returns a zero left module of rank <A>r</A> over the &homalg; ring <A>R</A>. ## <Example><![CDATA[ ## gap> ZZ := HomalgRingOfIntegers( );; ## gap> F := HomalgZeroLeftModule( ZZ ); ## <A zero left module> ## gap> 0 * ZZ; ## <The zero left module> ## ]]></Example> ## </Description> ## </ManSection> ## <#/GAPDoc> ## InstallMethod( HomalgZeroLeftModule, "constructor for homalg zero modules", [ IsHomalgRing ], function( R ) return HomalgFreeLeftModule( 0, R ); end ); ## <#GAPDoc Label="HomalgZeroRightModule"> ## <ManSection> ## <Oper Arg="r, R" Name="HomalgZeroRightModule" Label="constructor for zero right modules"/> ## <Returns>a &homalg; module</Returns> ## <Description> ## This constructor returns a zero right module of rank <A>r</A> over the &homalg; ring <A>R</A>. ## <Example><![CDATA[ ## gap> ZZ := HomalgRingOfIntegers( );; ## gap> F := HomalgZeroRightModule( ZZ ); ## <A zero right module> ## gap> ZZ * 0; ## <The zero right module> ## ]]></Example> ## </Description> ## </ManSection> ## <#/GAPDoc> ## InstallMethod( HomalgZeroRightModule, "constructor for homalg zero modules", [ IsHomalgRing ], function( R ) return HomalgFreeRightModule( 0, R ); end ); ## InstallMethod( \*, "constructor for homalg free modules", [ IsInt, IsHomalgRing ], function( rank, R ) if rank = 0 then return ZeroLeftModule( R ); elif rank = 1 then return AsLeftObject( R ); elif rank > 1 then return HomalgFreeLeftModule( rank, R ); fi; Error( "virtual modules are not supported (yet)\n" ); end ); ## InstallMethod( \*, "constructor for homalg free modules", [ IsHomalgRing, IsInt ], function( R, rank ) if rank = 0 then return ZeroRightModule( R ); elif rank = 1 then return AsRightObject( R ); elif rank > 1 then return HomalgFreeRightModule( rank, R ); fi; Error( "virtual modules are not supported (yet)\n" ); end ); ## InstallMethod( RingMap, "for homalg rings", [ IsHomalgModule, IsHomalgRing, IsHomalgRing ], function( M, S, T ) return RingMap( GeneratorsOfModule( M ), S, T ); end ); ## InstallMethod( Pullback, "for a ring map and a module", [ IsHomalgRingMap, IsFinitelyPresentedModuleRep ], function( phi, M ) local rel; rel := MatrixOfRelations( M ); rel := Pullback( phi, rel ); if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then return LeftPresentation( rel ); else return RightPresentation( rel ); fi; end ); ## InstallMethod( IsRegularSequence, "for a list of ring elements and a module", [ IsList, IsFinitelyPresentedModuleRep ], function( a, M ) local phi; for phi in a do phi := phi * HomalgIdentityMap( M ); if not IsZero( KernelSubobject( phi ) ) then return false; fi; M := Cokernel( phi ); od; if IsZero( M ) then return false; fi; return true; end ); #################################### # # View, Print, and Display methods: # #################################### ## InstallMethod( ViewObj, "for categories of homalg modules", [ IsCategoryOfModules ], function( C ) local parity; if IsCategoryOfFinitelyPresentedLeftModulesRep( C ) then parity := "left"; else parity := "right"; fi; Print( "<The Abelian category of f.p. ", parity, " modules over the ring " ); ViewObj( C!.ring ); Print( ">" ); end ); ## InstallMethod( ViewObj, "for homalg modules", [ IsHomalgModule ], function( o ) if IsBound( o!.distinguished ) then Print( "<The" ); else Print( "<A" ); fi; Print( ViewString( o ) ); Print( ">" ); end ); ## InstallMethod( ViewString, "for homalg modules", [ IsHomalgModule ], function( o ) local is_submodule, M, R, left_module, num_gen, first_properties, properties, nz, num_rel, gen_string, rel_string, rel, locked; num_gen := NrGenerators( o ); ## NrGenerators might set IsZero or more generally IsFree to true if HasIsFree( o ) and IsFree( o ) then return ViewString( o ); fi; is_submodule := IsFinitelyPresentedSubmoduleRep( o ); if is_submodule and HasEmbeddingInSuperObject( o ) then M := UnderlyingObject( o ); if HasIsZero( M ) and IsZero( M ) then SetIsZero( o, true ); return ViewString( o ); elif HasIsFree( M ) and IsFree( M ) then SetIsFree( o, true ); return ViewString( o ); fi; else M := o; fi; R := HomalgRing( M ); left_module := IsHomalgLeftObjectOrMorphismOfLeftObjects( M ); num_gen := NrGenerators( M ); ## NrGenerators might set IsZero or more generally IsFree to true if HasIsFree( M ) and IsFree( M ) then return ViewString( o ); fi; if num_gen = 1 then SetIsCyclic( M, true ); num_gen := "a cyclic"; fi; first_properties := ""; properties := ""; if HasIsCyclic( M ) and IsCyclic( M ) then if is_submodule then Append( properties, " principal" ); else Append( properties, " cyclic" ); fi; fi; if HasIsStablyFree( M ) and IsStablyFree( M ) then Append( properties, " stably free" ); if HasIsFree( M ) and not IsFree( M ) then ## the "not"s are obsolete but kept for better readability Append( properties, " non-free" ); nz := true; fi; elif HasIsProjective( M ) and IsProjective( M ) then Append( properties, " projective" ); if HasIsStablyFree( M ) and not IsStablyFree( M ) then Append( properties, " non-stably free" ); nz := true; elif HasIsFree( M ) and not IsFree( M ) then Append( properties, " non-free" ); nz := true; fi; elif HasIsReflexive( M ) and IsReflexive( M ) then Append( properties, " reflexive" ); if HasIsProjective( M ) and not IsProjective( M ) then Append( properties, " non-projective" ); nz := true; elif HasIsStablyFree( M ) and not IsStablyFree( M ) then Append( properties, " non-stably free" ); nz := true; elif HasIsFree( M ) and not IsFree( M ) then Append( properties, " non-free" ); nz := true; fi; elif HasIsTorsionFree( M ) and IsTorsionFree( M ) then if HasCodegreeOfPurity( M ) then if CodegreeOfPurity( M ) = [ 1 ] then Append( properties, Concatenation( " codegree-", String( 1 ), "-pure" ) ); else Append( properties, Concatenation( " codegree-", String( CodegreeOfPurity( M ) ), "-pure" ) ); fi; if not ( HasRankOfObject( M ) and RankOfObject( M ) > 0 ) then first_properties := Concatenation( first_properties, " torsion-free" ); fi; nz := true; else Append( properties, " torsion-free" ); if HasIsReflexive( M ) and not IsReflexive( M ) then Append( properties, " non-reflexive" ); nz := true; elif HasIsProjective( M ) and not IsProjective( M ) then Append( properties, " non-projective" ); nz := true; elif HasIsStablyFree( M ) and not IsStablyFree( M ) then Append( properties, " non-stably free" ); nz := true; elif HasIsFree( M ) and not IsFree( M ) then Append( properties, " non-free" ); nz := true; fi; fi; fi; if HasIsTorsion( M ) and IsTorsion( M ) then if HasGrade( M ) then if HasIsPure( M ) then if IsPure( M ) then ## only display the purity information if the global dimension of the ring is > 1: if not ( left_module and HasLeftGlobalDimension( R ) and LeftGlobalDimension( R ) <= 1 ) and not ( not left_module and HasRightGlobalDimension( R ) and RightGlobalDimension( R ) <= 1 ) then if HasCodegreeOfPurity( M ) then if CodegreeOfPurity( M ) = [ 0 ] then Append( properties, " reflexively " ); elif CodegreeOfPurity( M ) = [ 1 ] then Append( properties, Concatenation( " codegree-", String( 1 ), "-" ) ); else Append( properties, Concatenation( " codegree-", String( CodegreeOfPurity( M ) ), "-" ) ); fi; else Append( properties, " " ); fi; Append( properties, "pure" ); fi; else Append( properties, " non-pure" ); fi; fi; ## only display the grade if the global dimension of the ring is > 1: if ( ( left_module and HasLeftGlobalDimension( R ) and LeftGlobalDimension( R ) <= 1 ) or ( not left_module and HasRightGlobalDimension( R ) and RightGlobalDimension( R ) <= 1 ) ) and ( HasIsZero( M ) and not IsZero( M ) ) ## we actually no that IsZero( M ) = false (but anyway) and not ( IsBound( nz ) and nz = true ) then properties := Concatenation( " non-zero", properties ); Append( properties, " torsion" ); else Append( properties, " grade " ); Append( properties, String( Grade( M ) ) ); fi; else if HasIsPure( M ) then if IsPure( M ) then ## only display the purity information if the global dimension of the ring is > 1: if not ( left_module and HasLeftGlobalDimension( R ) and LeftGlobalDimension( R ) <= 1 ) and not ( not left_module and HasRightGlobalDimension( R ) and RightGlobalDimension( R ) <= 1 ) then if HasCodegreeOfPurity( M ) then if CodegreeOfPurity( M ) = [ 0 ] then Append( properties, " reflexively " ); elif CodegreeOfPurity( M ) = [ 1 ] then Append( properties, Concatenation( " codegree-", String( 1 ), "-" ) ); else Append( properties, Concatenation( " codegree-", String( CodegreeOfPurity( M ) ), "-" ) ); fi; else Append( properties, " " ); fi; Append( properties, "pure" ); fi; else Append( properties, " non-pure" ); fi; elif HasIsZero( M ) and not IsZero( M ) then properties := Concatenation( " non-zero", properties ); fi; Append( properties, " torsion" ); fi; else if HasIsPure( M ) and not IsPure( M ) then Append( properties, " non-pure" ); fi; if HasRankOfObject( M ) then Append( properties, " rank " ); Append( properties, String( RankOfObject( M ) ) ); if RankOfObject( M ) = 0 and HasIsZero( M ) and not IsZero( M ) then properties := Concatenation( " non-zero", properties ); fi; elif HasIsTorsion( M ) and not IsTorsion( M ) and not ( HasIsPure( M ) or ( HasIsTorsionFree( M ) and IsTorsionFree( M ) ) ) then Append( properties, " non-torsion" ); elif HasIsZero( M ) and not IsZero( M ) and not ( HasIsPure( M ) and not IsPure( M ) ) and not ( IsBound( nz ) and nz = true ) then properties := Concatenation( " non-zero", properties ); fi; fi; if left_module then if IsInt( num_gen ) then gen_string := " generators"; else gen_string := " generator"; fi; if not is_submodule then if HasNrRelations( o ) = true then num_rel := NrRelations( o ); if num_rel = 0 then num_rel := ""; rel_string := "no relations for "; elif num_rel = 1 then rel_string := " relation for "; else rel_string := " relations for "; fi; else rel := RelationsOfModule( o ); if rel = "unknown relations" then num_rel := "unknown"; elif not HasEvaluatedMatrixOfRelations( rel ) then num_rel := "yet unknown"; else num_rel := "an unknown number of"; fi; rel_string := " relations for "; fi; fi; if IsLockedObject( o ) then locked := " (locked)"; else locked := ""; fi; if is_submodule then if ConstructedAsAnIdeal( o ) then if HasIsCommutative( R ) and IsCommutative( R ) then if IsBound( HOMALG.SuppressParityInViewObjForCommutativeStructureObjects ) and HOMALG.SuppressParityInViewObjForCommutativeStructureObjects = true then return Concatenation( first_properties, properties, " ideal given by ", String( num_gen ), gen_string, locked ); else return Concatenation( first_properties, properties, " (left) ideal given by ", String( num_gen ), gen_string, locked ); fi; else return Concatenation( first_properties, properties, " left ideal given by ", String( num_gen ), gen_string, locked ); fi; else return Concatenation( first_properties, properties, " left submodule given by ", String( num_gen ), gen_string, locked ); fi; else return Concatenation( first_properties, properties, " left module presented by ", String( num_rel ), rel_string, String( num_gen ), gen_string, locked ); fi; else if is_submodule then if IsInt( num_gen ) then gen_string := " generators"; else gen_string := " generator"; fi; else if IsInt( num_gen ) then gen_string := " generators satisfying "; else gen_string := " generator satisfying "; fi; fi; if not is_submodule then if HasNrRelations( o ) = true then num_rel := NrRelations( o ); if num_rel = 0 then num_rel := ""; rel_string := "no relations"; elif num_rel = 1 then rel_string := " relation"; else rel_string := " relations"; fi; else rel := RelationsOfModule( o ); if rel = "unknown relations" then num_rel := "unknown"; elif not HasEvaluatedMatrixOfRelations( rel ) then num_rel := "yet unknown"; else num_rel := "an unknown number of"; fi; rel_string := " relations"; fi; fi; if IsLockedObject( o ) then locked := " (locked)"; else locked := ""; fi; if is_submodule then if ConstructedAsAnIdeal( o ) then if HasIsCommutative( R ) and IsCommutative( R ) then if IsBound( HOMALG.SuppressParityInViewObjForCommutativeStructureObjects ) and HOMALG.SuppressParityInViewObjForCommutativeStructureObjects = true then return Concatenation( first_properties, properties, " ideal given by ", String( num_gen ), gen_string, locked ); else return Concatenation( first_properties, properties, " (right) ideal given by ", String( num_gen ), gen_string, locked ); fi; else return Concatenation( first_properties, properties, " right ideal given by ", String( num_gen ), gen_string, locked ); fi; else return Concatenation( first_properties, properties, " right submodule given by ", String( num_gen ), gen_string, locked ); fi; else return Concatenation( first_properties, properties, " right module on ", String( num_gen ), gen_string, String( num_rel ), rel_string, locked ); fi; fi; end ); ## InstallMethod( ViewString, "for homalg modules", [ IsFinitelyPresentedModuleRep and IsFree ], 1001, ## since we don't use the filter IsHomalgLeftObjectOrMorphismOfLeftObjects it is good to set the ranks high function( M ) local R, vs, result, r, rk, l, rel, num_rel; R := HomalgRing( M ); vs := HasIsDivisionRingForHomalg( R ) and IsDivisionRingForHomalg( R ); result := ""; if vs then Append( result, " " ); else Append( result, " free " ); fi; if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then Append( result, "left" ); else Append( result, "right" ); fi; if vs then Append( result, " vector space" ); else Append( result, " module" ); fi; r := NrGenerators( M ); if HasRankOfObject( M ) then rk := RankOfObject( M ); if vs then Append( result, Concatenation( " of dimension ", String( rk ) ) ); else Append( result, Concatenation( " of rank ", String( rk ) ) ); fi; Append( result, " on " ); if r = rk then if r = 1 then Append( result, "a free generator" ); else Append( result, "free generators" ); fi; else ## => r > 1 Append( result, Concatenation( String( r ), " non-free generators satisfying " ) ); if HasNrRelations( M ) = true then l := NrRelations( M ); if l = 1 then Append( result, "a single relation" ); else Append( result, Concatenation( String( l ), " relations" ) ); fi; else rel := RelationsOfModule( M ); if rel = "unknown relations" then num_rel := "unknown"; elif not HasEvaluatedMatrixOfRelations( rel ) then num_rel := "yet unknown"; else num_rel := "an unknown number of"; fi; Append( result, num_rel ); Append( result, " relations" ); fi; fi; else if vs then Append( result, " of yet unkown dimension" ); else Append( result, " of yet unkown rank" ); fi; Append( result, Concatenation( " on ", String( r ), " generators satisfying " ) ); if HasNrRelations( M ) = true then l := NrRelations( M ); if l = 1 then Append( result, "a single relation" ); else Append( result, Concatenation( String( l ), " relations" ) ); fi; else rel := RelationsOfModule( M ); if rel = "unknown relations" then num_rel := "unknown"; elif not HasEvaluatedMatrixOfRelations( rel ) then num_rel := "yet unknown"; else num_rel := "an unknown number of"; fi; Append( result, num_rel ); Append( result, " relations" ); fi; fi; return result; end ); ## InstallMethod( ViewString, "for homalg modules", [ IsFinitelyPresentedModuleRep and IsZero ], 1001, ## since we don't use the filter IsHomalgLeftObjectOrMorphismOfLeftObjects we need to set the ranks high function( M ) local R, vs, result; R := HomalgRing( M ); vs := HasIsDivisionRingForHomalg( R ) and IsDivisionRingForHomalg( R ); result := " zero "; if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then Append( result, "left" ); else Append( result, "right" ); fi; if vs then Append( result, " vector space" ); else Append( result, " module" ); fi; return result; end ); ## InstallMethod( Display, "for homalg modules", [ IsFinitelyPresentedModuleRep ], function( M ) Display( M, "" ); end ); ## InstallMethod( Display, "for homalg modules", [ IsFinitelyPresentedModuleRep, IsString ], function( M, extra_information ) local R, l, D, esc; R := HomalgRing( M ); R := RingName( R ); l := 10; if Length( R ) < l then D := R; else D := "R"; fi; Display( MatrixOfRelations( M ) ); if extra_information <> "" then Print( "\n", extra_information, "\n" ); fi; Print( "\nCokernel of the map\n\n" ); if IsBound( HOMALG.color_display ) and HOMALG.color_display = true then esc := "\033[0m"; if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then Print( D, "^(1x\033[01m", NrRelations( M ), esc, ") --> ", D, "^(1x\033[01m", NrGenerators( M ), esc, ")," ); else Print( D, "^(\033[01m", NrRelations( M ), esc, "x1) --> ", D, "^(\033[01m", NrGenerators( M ), esc, "x1)," ); fi; else esc := ""; if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then Print( D, "^(1x", NrRelations( M ), ") --> ", D, "^(1x", NrGenerators( M ), ")," ); else Print( D, "^(", NrRelations( M ), "x1) --> ", D, "^(", NrGenerators( M ), "x1)," ); fi; fi; if not IsSubset( R, "a way to display" ) and not Length( R ) < l then Print( " ( for ", D, " := ", R, esc, " )" ); fi; Print( "\n\ncurrently represented by the above matrix\n" ); end ); ## InstallMethod( Display, "for homalg modules", [ IsFinitelyPresentedModuleRep, IsString ], 1000, function( M, extra_information ) local r, rel, R, RP, name, elements, display, rk, get_string, color; r := NrRelations( M ); rel := MatrixOfRelations( M ); if not NrGenerators( M ) = 1 then TryNextMethod( ); fi; R := HomalgRing( M ); RP := homalgTable( R ); name := RingName( R ); if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then elements := List( [ 1 .. r ], i -> MatElm( rel, i, 1 ) ); else elements := List( [ 1 .. r ], j -> MatElm( rel, 1, j ) ); fi; elements := Filtered( elements, x -> not IsZero( x ) ); if IsHomalgInternalRingRep( R ) then get_string := String; else get_string := Name; fi; if IsBound( HOMALG.color_display ) and HOMALG.color_display = true then color := true; else color := false; fi; if elements <> [ ] then ## this will never happen, since the below method will catch it if color then display := List( elements, x -> [ "\033[01m", get_string( x ), "\033[0m, " ] ); else display := List( elements, x -> [ get_string( x ), ", " ] ); fi; display := Concatenation( display ); display := Concatenation( display ); Print( name, "/< ", display{ [ 1 .. Length( display ) - 2 ] }, " >" ); if extra_information <> "" then Print( " ", extra_information ); fi; else Print( "something went wrong!" ); fi; Print( "\n" ); end ); ## InstallMethod( Display, "for homalg modules", [ IsFinitelyPresentedModuleRep, IsString ], 1001, function( M, extra_information ) local rel, R, RP, name, diag, display, rk, get_string, color; rel := MatrixOfRelations( M ); if not HasElementaryDivisors( M ) and not IsDiagonalMatrix( rel ) then TryNextMethod( ); fi; R := HomalgRing( M ); RP := homalgTable( R ); name := RingName( R ); if HasElementaryDivisors( M ) then diag := ElementaryDivisors( M ); rk := Length( Filtered( diag, IsZero ) ); else diag := DiagonalEntries( rel ); rk := Length( Filtered( diag, IsZero ) ) + NrGenerators( M ) - Length( diag ); fi; ## rk is the rank if R is a domain if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) and not HasRankOfObject( M ) then SetRankOfObject( M, rk ); fi; diag := Filtered( diag, x -> not IsOne( x ) and not IsZero( x ) ); if IsHomalgInternalRingRep( R ) then get_string := String; else get_string := Name; fi; if IsBound( HOMALG.color_display ) and HOMALG.color_display = true then color := true; else color := false; fi; if diag <> [ ] then if color then display := List( diag, x -> [ name, "/< \033[01m", get_string( x ), "\033[0m > + " ] ); else display := List( diag, x -> [ name, "/< ", get_string( x ), " > + " ] ); fi; display := Concatenation( display ); display := Concatenation( display ); else BasisOfModule( M ); SetIsFree( M, true ); display := ""; fi; if rk <> 0 then if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then if color then Print( display, name, "^(1 x", " \033[01m", rk, "\033[0m)" ); else Print( display, name, "^(1 x", " ", rk, ")" ); fi; else if color then Print( display, name, "^(\033[01m", rk, "\033[0m x 1)" ); else Print( display, name, "^(", rk, " x 1)" ); fi; fi; elif HasIsZero( M ) and IsZero( M ) then ## MatrixOfRelations = [ [ 1 ] ] Print( "0" ); else Print( display{ [ 1 .. Length( display ) - 2 ] } ); fi; if extra_information <> "" then Print( " ", extra_information ); fi; Print( "\n" ); end ); ## InstallMethod( Display, "for homalg modules", [ IsHomalgModule and IsZero, IsString ], 2001, ## since we don't use the filter IsHomalgLeftObjectOrMorphismOfLeftObjects we need to set the ranks high function( M, extra_information ) Print( 0, extra_information, "\n" ); end ); ## InstallMethod( Display, "for homalg modules", [ IsHomalgModule, IsString ], 3001, function( M, extra_information ) if not IsBound( M!.DisplayString ) then TryNextMethod( ); fi; Print( M!.DisplayString, extra_information, "\n" ); end );