Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


SSL HomalgModule.gi   Interaktion und
Portierbarkeitunbekannt

 
# 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

--> --------------------

[ zur Elbe Produktseite wechseln0.68Quellennavigators  Analyse erneut starten  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     neueste Artikel weltweit

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge