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


Quelle  LIMOD.gi   Sprache: unbekannt

 
# 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
#

##         LIMOD = Logical Implications for homalg MODules

####################################
#
# global variables:
#
####################################

# a central place for configuration variables:

InstallValue( LIMOD,
        rec(
            color := "\033[4;30;46m",
            
            ## used in a InstallLogicalImplicationsForHomalgSubobjects call below
            intrinsic_properties_specific_shared_with_subobjects_and_ideals :=
            [ 
              "IsFree",
              "IsStablyFree",
              "IsCyclic",
              "HasConstantRank",
              ],
            
            ## used in a InstallLogicalImplicationsForHomalgSubobjects call below
            intrinsic_properties_specific_shared_with_factors_modulo_ideals :=
            [ 
              "IsPrimeModule",
              "IsHolonomic",
              "IsReduced",
              ],
            
            intrinsic_properties_specific_not_shared_with_subobjects :=
            [ 
              ],
            
            ## used in a InstallLogicalImplicationsForHomalgSubobjects call below
            intrinsic_properties_specific_shared_with_subobjects_which_are_not_ideals :=
            Concatenation(
                    ~.intrinsic_properties_specific_shared_with_subobjects_and_ideals,
                    ~.intrinsic_properties_specific_shared_with_factors_modulo_ideals ),
            
            ## needed to define intrinsic_properties below
            intrinsic_properties_specific :=
            Concatenation(
                    ~.intrinsic_properties_specific_not_shared_with_subobjects,
                    ~.intrinsic_properties_specific_shared_with_subobjects_which_are_not_ideals ),
            
            ## needed for MatchPropertiesAndAttributes in HomalgSubmodule.gi
            intrinsic_properties_shared_with_subobjects_and_ideals :=
            Concatenation(
                    LIOBJ.intrinsic_properties_shared_with_subobjects_and_ideals,
                    ~.intrinsic_properties_specific_shared_with_subobjects_and_ideals ),
            
            ##
            intrinsic_properties_shared_with_factors_modulo_ideals :=
            Concatenation(
                    LIOBJ.intrinsic_properties_shared_with_factors_modulo_ideals,
                    ~.intrinsic_properties_specific_shared_with_factors_modulo_ideals ),
            
            ## needed for MatchPropertiesAndAttributes in HomalgSubmodule.gi
            intrinsic_properties_shared_with_subobjects_which_are_not_ideals :=
            Concatenation(
                    LIOBJ.intrinsic_properties_shared_with_subobjects_which_are_not_ideals,
                    ~.intrinsic_properties_specific_shared_with_subobjects_which_are_not_ideals ),
            
            ## needed for UpdateObjectsByMorphism
            intrinsic_properties :=
            Concatenation(
                    LIOBJ.intrinsic_properties,
                    ~.intrinsic_properties_specific ),
            
            ## used in a InstallLogicalImplicationsForHomalgSubobjects call below
            intrinsic_attributes_specific_shared_with_subobjects_and_ideals :=
            [ 
              ],
            
            ## used in a InstallLogicalImplicationsForHomalgSubobjects call below
            intrinsic_attributes_specific_shared_with_factors_modulo_ideals :=
            [ 
              "AffineDimension",
              "AffineDegree",
              "ProjectiveDegree",
              "PrimaryDecomposition", ## wrong, we need the preimages of this
              "RadicalDecomposition", ## wrong, we need the preimages of this
              "RadicalSubobject",     ## wrong, we need the preimages of this
              "ElementaryDivisors",
              "FittingIdeal",
              "NonFlatLocus",
              "LargestMinimalNumberOfLocalGenerators",
              ],
            
            intrinsic_attributes_specific_not_shared_with_subobjects :=
            [ 
              ],
            
            ## used in a InstallLogicalImplicationsForHomalgSubobjects call below
            intrinsic_attributes_specific_shared_with_subobjects_which_are_not_ideals :=
            Concatenation(
                    ~.intrinsic_attributes_specific_shared_with_subobjects_and_ideals,
                    ~.intrinsic_attributes_specific_shared_with_factors_modulo_ideals ),
            
            ## needed to define intrinsic_attributes below
            intrinsic_attributes_specific :=
            Concatenation(
                    ~.intrinsic_attributes_specific_not_shared_with_subobjects,
                    ~.intrinsic_attributes_specific_shared_with_subobjects_which_are_not_ideals ),
            
            ## needed for MatchPropertiesAndAttributes in HomalgSubmodule.gi
            intrinsic_attributes_shared_with_subobjects_and_ideals :=
            Concatenation(
                    LIOBJ.intrinsic_attributes_shared_with_subobjects_and_ideals,
                    ~.intrinsic_attributes_specific_shared_with_subobjects_and_ideals ),
            
            ##
            intrinsic_attributes_shared_with_factors_modulo_ideals :=
            Concatenation(
                    LIOBJ.intrinsic_attributes_shared_with_factors_modulo_ideals,
                    ~.intrinsic_attributes_specific_shared_with_factors_modulo_ideals ),
            
            ## needed for MatchPropertiesAndAttributes in HomalgSubmodule.gi
            intrinsic_attributes_shared_with_subobjects_which_are_not_ideals :=
            Concatenation(
                    LIOBJ.intrinsic_attributes_shared_with_subobjects_which_are_not_ideals,
                    ~.intrinsic_attributes_specific_shared_with_subobjects_which_are_not_ideals ),
            
            ## needed for UpdateObjectsByMorphism
            intrinsic_attributes :=
            Concatenation(
                    LIOBJ.intrinsic_attributes,
                    ~.intrinsic_attributes_specific ),
            
            )
        );

##
## take care that we distinguish between objects and subobjects:
## some properties of a subobject might be those of the factor
## and not of the underlying object
##
InstallValue( LogicalImplicationsForHomalgModules,
        [ 
          ## IsTorsionFree:
          
          [ IsZero,
            "implies", IsFree ],
          
          [ IsFree,
            "implies", IsStablyFree ],
          
          [ IsStablyFree,
            "implies", IsProjective ],
          
          ## Serre's 1955 remark:
          ## for a module with a finite free resolution (FFR)
          ## "projective" and "stably free" are equivalent
          [ IsProjective, "and", FiniteFreeResolutionExists,
            "imply", IsStablyFree ],
          
          ## IsTorsion:
          
          [ IsZero, "and", IsFinitelyPresentedModuleRep,
            "imply", IsHolonomic ],
          
          [ IsZero, "and", IsFinitelyPresentedSubmoduleRep, "and", NotConstructedAsAnIdeal,
            "imply", IsHolonomic ],
          
          ## [ IsHolonomic,
          ##  "implies", IsTorsion ], false for fields
          
          ## [ IsHolonomic,
          ##  "implies", IsArtinian ], there is no clear definition of holonomic
          
          ## see homalg/LIOBJ.gi for more implications
          
          ] );

##
InstallValue( LogicalImplicationsForHomalgModulesOverSpecialRings,
        [ ## logical implications for modules over special rings
          
          ## Kaplansky's theorem [Lam06, Theorem II.2.2]
          [ [ IsTorsionFree ],
            HomalgRing,
            [ [ IsLeftHereditary ],
              [ IsRightHereditary ],
              [ IsHereditary ]
              ],
            "imply", IsProjective,
            0 ],
          
          ## Serre's 1955 remark
          [ [ IsProjective ],
            HomalgRing,
            [ [ IsLeftFiniteFreePresentationRing ],
              [ IsRightFiniteFreePresentationRing ],
              [ IsFiniteFreePresentationRing ],
              ],
            "imply", IsStablyFree,
            0 ],
          
          ## by definition [Lam06, Definition I.4.6]
          [ [ IsStablyFree ],
            HomalgRing,
            [ [ IsLeftHermite ],
              [ IsRightHermite ],
              [ IsHermite ]
              ],
            "imply", IsFree,
            0 ],
          
          ## projective modules over local domains are free
          [ [ IsProjective ],
            HomalgRing,
            [ [ IsLocal, IsIntegralDomain ]
              ],
            "imply", IsFree,
            1001 ],
          
          ] );

####################################
#
# logical implications methods:
#
####################################

InstallLogicalImplicationsForHomalgSubobjects(
        List( LIMOD.intrinsic_properties_specific_shared_with_subobjects_which_are_not_ideals, ValueGlobal ),
        IsFinitelyPresentedSubmoduleRep and NotConstructedAsAnIdeal,
        HasEmbeddingInSuperObject,
        UnderlyingObject );

InstallLogicalImplicationsForHomalgSubobjects(
        List( LIMOD.intrinsic_properties_specific_shared_with_subobjects_and_ideals, ValueGlobal ),
        IsFinitelyPresentedSubmoduleRep and ConstructedAsAnIdeal,
        HasEmbeddingInSuperObject,
        UnderlyingObject );

InstallLogicalImplicationsForHomalgSubobjects(
        List( LIMOD.intrinsic_properties_specific_shared_with_factors_modulo_ideals, ValueGlobal ),
        IsFinitelyPresentedSubmoduleRep and ConstructedAsAnIdeal,
        HasFactorObject,
        FactorObject );

InstallLogicalImplicationsForHomalgSubobjects(
        List( LIMOD.intrinsic_attributes_specific_shared_with_subobjects_which_are_not_ideals, ValueGlobal ),
        IsFinitelyPresentedSubmoduleRep and NotConstructedAsAnIdeal,
        HasEmbeddingInSuperObject,
        UnderlyingObject );

InstallLogicalImplicationsForHomalgSubobjects(
        List( LIMOD.intrinsic_attributes_specific_shared_with_subobjects_and_ideals, ValueGlobal ),
        IsFinitelyPresentedSubmoduleRep and ConstructedAsAnIdeal,
        HasEmbeddingInSuperObject,
        UnderlyingObject );

InstallLogicalImplicationsForHomalgSubobjects(
        List( LIMOD.intrinsic_attributes_specific_shared_with_factors_modulo_ideals, ValueGlobal ),
        IsFinitelyPresentedSubmoduleRep and ConstructedAsAnIdeal,
        HasFactorObject,
        FactorObject );

####################################
#
# immediate methods for properties:
#
####################################

##
InstallImmediateMethod( IsZero,
        IsFinitelyPresentedModuleRep and HasAffineDimension, 0,
        
  function( M )
    
    return AffineDimension( M ) <= HOMALG_MATRICES.DimensionOfZeroModules;
    
end );

##
InstallImmediateMethod( IsTorsion,
        IsElementOfAnObjectGivenByAMorphismRep, 0,
        
  function( m )
    local M;
    
    M := SuperObject( m );
    
    if HasIsTorsionFree( M ) and IsTorsionFree( M ) then
        ## in a torsion-free module only zero is torsion
        if HasIsZero( m ) and not IsZero( m ) then
            return false;
        fi;
    elif HasIsTorsion( M ) and IsTorsion( M ) then
        ## every element in a torsion module is torsion
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsTorsion,
        IsElementOfAnObjectGivenByAMorphismRep and HasAnnihilator, 0,
        
  function( m )
    local Ann, M, R;
    
    Ann := Annihilator( m );
    
    if HasIsZero( Ann ) then
        
        M := SuperObject( m );
        
        ## we assume that the ring R ≠ 0
        if IsZero( Ann ) then
            
            ## 0 ≠ R = R / Ann( m ) ≅ R m ≤ M
            SetIsTorsion( M, false );
            
            return false;
            
        elif not HasIsZero( m ) then
            
            TryNextMethod( );
            
        elif IsZero( m ) then
            
            return true;
            
        fi;
        
        ## we now know that m ≠ 0 and Ann( m ) ≠ 0
        
        R := HomalgRing( m );
        
        ## Z/2 is torsion-free over Z/6 with annihilator <3>
        if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
            
            SetIsTorsionFree( M, false );
            
            return true;
        fi;
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsTorsion,
        IsElementOfAnObjectGivenByAMorphismRep and IsZero, 0,
        
  function( m )
    
    return true;
    
end );

##
InstallImmediateMethod( IsArtinian,
        IsFinitelyPresentedModuleRep and HasGrade, 0,
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and
       ( ( HasIsFreePolynomialRing( R ) and IsFreePolynomialRing( R ) ) or
         ( HasIsWeylRing( R ) and IsWeylRing( R ) ) or
         ( HasIsLocalizedWeylRing( R ) and IsLocalizedWeylRing( R ) ) ) then
        
        return Grade( M ) = global_dimension( R );
        
    fi;
    
    TryNextMethod( );
    
end );

## a presentation must be on a single generator
InstallImmediateMethod( IsCyclic,
        IsFinitelyPresentedModuleRep, 0,
        
  function( M )
    local l, p, rel;
    
    l := ListOfPositionsOfKnownSetsOfRelations( M );
    
    for p in l do;
        
        rel := RelationsOfModule( M, p );
        
        if IsHomalgRelations( rel ) then
            if HasNrGenerators( rel ) and NrGenerators( rel ) = 1 then
                return true;
            fi;
        fi;
        
    od;
    
    TryNextMethod( );
    
end );

## [Coutinho, A Primer of Algebraic D-modules, Thm. 10.25, p. 90]
InstallImmediateMethod( IsCyclic,
        IsFinitelyPresentedModuleRep and IsArtinian, 0,
        
  function( M )
    local R;
    
    R := HomalgRing( M );
    
    if not ( HasIsSimpleRing( R ) and IsSimpleRing( R ) ) then
        TryNextMethod( );
    fi;
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        if HasIsLeftNoetherian( R ) and IsLeftNoetherian( R ) and
           HasIsLeftArtinian( R ) and not IsLeftArtinian( R ) then
            return true;
        fi;
    else
        if HasIsRightNoetherian( R ) and IsRightNoetherian( R ) and
           HasIsRightArtinian( R ) and not IsRightArtinian( R ) then
            return true;
        fi;
    fi;
    
    TryNextMethod( );
    
end );

## strictly less relations than generators => not IsTorsion
InstallImmediateMethod( IsTorsion,
        IsFinitelyPresentedModuleRep, 0,
        
  function( M )
    local l, p, rel;
    
    l := ListOfPositionsOfKnownSetsOfRelations( M );
    
    for p in l do;
        
        rel := RelationsOfModule( M, p );
        
        if IsHomalgRelations( rel ) then
            if HasNrGenerators( rel ) and HasNrRelations( rel ) and
               NrGenerators( rel ) > NrRelations( rel ) then
                return false;
            fi;
        fi;
        
    od;
    
    TryNextMethod( );
    
end );

## a non trivial set of relations for a single generator over a domain => IsTorsion
InstallImmediateMethod( IsTorsion,
        IsFinitelyPresentedModuleRep and IsCyclic, 0,
        
  function( M )
    local l, p, rel, R, torsion;
    
    l := ListOfPositionsOfKnownSetsOfRelations( M );
    for p in l do;
        
        rel := RelationsOfModule( M, p );
        
        if IsHomalgRelations( rel ) and HasEvaluatedMatrixOfRelations( rel ) then
            if HasNrGenerators( rel ) and NrGenerators( rel ) = 1 and
               HasIsZero( MatrixOfRelations( rel ) ) then
                
                R := HomalgRing( rel );
                
                if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
                    
                    torsion := not IsZero( MatrixOfRelations( rel ) );
                    
                    SetIsTorsion( rel, torsion );
                    
                    return torsion;
                    
                fi;
            fi;
        fi;
        
    od;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsTorsion,
        IsFinitelyPresentedModuleOrSubmoduleRep and HasRankOfObject, 0,
        
  function( M )
    local R;
    
    R := HomalgRing( M );
    
    ## Z/2 is torsion-free over Z/6 with annihilator <3>
    if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
        return RankOfObject( M ) = 0;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsTorsionFree,
        IsFinitelyPresentedModuleRep and HasIsProjective, 0,
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) <= 1 and not IsProjective( M ) then
        return false;
    fi; ## the true case is taken care of elsewhere
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsReflexive,
        IsFinitelyPresentedModuleRep and HasIsProjective, 0,
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) <= 2 and not IsProjective( M ) then
        return false;
    fi; ## the true case is taken care of elsewhere
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsProjective,
        IsFinitelyPresentedModuleRep and IsTorsionFree, 0,
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) <= 1 then
        return true;
    fi; ## the false case is taken care of elsewhere
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsProjective,
        IsFinitelyPresentedModuleRep and IsReflexive, 0,
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) <= 2 then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsFree,
        IsFinitelyPresentedModuleRep, 0,
        
  function( M )
    
    ## NrRelations is not an attribute and HasNrRelations might return fail!
    if HasNrRelations( M ) = true and NrRelations( M ) = 0 then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsFree,
        IsFinitelyPresentedModuleRep, 0,
        
  function( M )
    local R;
    
    R := HomalgRing( M );
    
    ## modules over divison rings are free
    if HasIsDivisionRingForHomalg( R ) and IsDivisionRingForHomalg( R ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsFree,
        IsFinitelyPresentedModuleRep and IsTorsionFree and HasRankOfObject, 0,
        
  function( M )
    local R;
    
    ## HasNrGenerators is allowed to return fail
    if HasNrGenerators( M ) = true and
       RankOfObject( M ) = NrGenerators( M ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsFree,
        IsFinitelyPresentedModuleRep and IsStablyFree and HasRankOfObject, 0,
        
  function( M )
    local R;
    
    R := HomalgRing( M );
    
    if HasIsCommutative( R ) and IsCommutative( R ) and RankOfObject( M ) = 1 then
        ## [Lam06, Theorem I.4.11], this is in principle the Cauchy-Binet formula
        return true;
    elif HasGeneralLinearRank( R ) and GeneralLinearRank( R ) <= RankOfObject( M ) then
        ## [McCRob, Theorem 11.1.14]
        return true;
    elif HasElementaryRank( R ) and ElementaryRank( R ) <= RankOfObject( M ) then
        ## [McCRob, Theorem 11.1.14 and Proposition 11.3.11]
        return true;
    elif HasStableRank( R ) and StableRank( R ) <= RankOfObject( M ) then
        ## [McCRob, Theorem 11.1.14 and Proposition 11.3.11]
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsPure,
        IsFinitelyPresentedModuleRep and IsTorsion, 0,
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) <= 1 then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsPure,
        IsFinitelyPresentedModuleRep and HasGrade, 0,
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) = Grade( M ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

####################################
#
# immediate methods for attributes:
#
####################################

##
InstallImmediateMethod( RankOfObject,
        IsFinitelyPresentedModuleRep, 0,
        
  function( M )
    local m;
    
    ## NrRelations is not an attribute and HasNrRelations might return fail!
    if HasNrGenerators( M ) and HasNrRelations( M ) = true then
        
        m := MatrixOfRelations( M );
        
        if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
            if HasIsLeftRegular( m ) and IsLeftRegular( m ) then
                return NumberColumns( m ) - NumberRows( m );
            fi;
        else
            if HasIsRightRegular( m ) and IsRightRegular( m ) then
                return NumberRows( m ) - NumberColumns( m );
            fi;
        fi;
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( RankOfObject,
        IsFinitelyPresentedModuleRep and IsFree, 0,
        
  function( M )
    
    ## NrRelations is not an attribute and HasNrRelations might return fail!
    if HasNrRelations( M ) = true and NrRelations( M ) = 0 then
        return NrGenerators( M );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( Grade,
        IsFinitelyPresentedModuleRep and IsTorsion and HasIsZero, 0,
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if not IsZero( M ) and Tester( global_dimension )( R ) and global_dimension( R ) = 1 then
        return 1;
    fi;
    
    TryNextMethod( );
    
end );

####################################
#
# methods for properties:
#
####################################

## A module element over a commutative ring is torsion,
## if it is annihilated by a regular element of the ring.
InstallMethod( IsTorsion,
        "LIOBJ: for homalg object elements",
        [ IsElementOfAnObjectGivenByAMorphismRep ],
        
  function( m )
    local M, Ann, R, gens;
    
    if IsZero( m ) then
        return true;
    fi;
    
    ## M ≠ 0 since m ≠ 0
    M := SuperObject( m );
    
    if HasIsTorsionFree( M ) and IsTorsionFree( M ) then
        ## in a torsion-free module only zero is torsion
        ## and we already know that m ≠ 0
        return false;
    elif HasIsTorsion( M ) and IsTorsion( M ) then
        ## every element in a torsion module is torsion
        return true;
    fi;
    
    Ann := Annihilator( m );
    
    if IsZero( Ann ) then
        
        ## we assume that the ring R ≠ 0, so
        ## 0 ≠ R = R / Ann( m ) ≅ R m ≤ M
        SetIsTorsion( M, false );
        
        return false;
        
    fi;
    
    ## we now know that m ≠ 0 and Ann( m ) ≠ 0
    
    R := HomalgRing( m );
    
    ## Z/2 is torsion-free over Z/6 with annihilator <3>
    if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
        
        SetIsTorsionFree( M, false );
        
        return true;
        
    fi;
    
    ## I am not sure about the appropriate definition in the
    ## noncommutative setting
    if not ( HasIsCommutative( R ) and IsCommutative( R ) ) then
        TryNextMethod( );
    fi;
    
    ## now that the annihilator is nontrivial
    ## check if any of its generators is regular (i.e., a nonzerodivisor)
    gens := GeneratingElements( Ann );
    
    if ForAny( gens, a -> IsZero( Annihilator( a ) ) ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsZero,
        "LIMOD: for homalg submodules",
        [ IsFinitelyPresentedSubmoduleRep ],
        
  function( M )
    local is_zero;
    
    is_zero := IsZero( DecideZero( MatrixOfSubobjectGenerators( M ), SuperObject( M ) ) );
    
    if HasEmbeddingInSuperObject( M ) then
        SetIsZero( UnderlyingObject( M ), is_zero );
    fi;
    
    return is_zero;
    
end );

##
InstallMethod( IsZero,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    
    return NrGenerators( GetRidOfZeroGenerators( M ) ) = 0;
    
end );

##
InstallMethod( IsZero,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep and HasUnderlyingSubobject ],
        
  function( M )
    local N;
    
    N := UnderlyingSubobject( M );
    
    if HasNrRelations( M ) and
       NrGenerators( M ) <= NrGenerators( SuperObject( N ) ) then
        TryNextMethod( );
    fi;
    
    ## avoids computing syzygies
    return IsZero( N );
    
end );

##
InstallMethod( IsZero,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, K, RP;
    
    R := HomalgRing( M );
    
    if not ( HasIsCommutative( R ) and IsCommutative( R ) ) or
       not HasCoefficientsRing( R ) then
        TryNextMethod( );
    fi;
    
    K := CoefficientsRing( R );
    
    if not ( HasIsFieldForHomalg( K ) and IsFieldForHomalg( K ) ) then
        TryNextMethod( );
    fi;
    
    RP := homalgTable( R );
    
    if not ( IsBound( RP!.AffineDimension ) or
             IsBound( RP!.CoefficientsOfUnreducedNumeratorOfHilbertPoincareSeries ) or
             IsBound( RP!.CoefficientsOfNumeratorOfHilbertPoincareSeries ) ) then
        TryNextMethod( );
    fi;
    
    return AffineDimension( M ) <= HOMALG_MATRICES.DimensionOfZeroModules;
    
end );

##
InstallMethod( IsArtinian,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R;
    
    R := HomalgRing( M );
    
    if HasGlobalDimension( R ) and ## FIXME: declare an appropriate property for such rings
       ( ( HasIsIntegersForHomalg( R ) and IsIntegersForHomalg( R ) ) or
         ( HasIsFreePolynomialRing( R ) and IsFreePolynomialRing( R ) ) or
         ( HasIsWeylRing( R ) and IsWeylRing( R ) ) or
         ( HasIsLocalizedWeylRing( R ) and IsLocalizedWeylRing( R ) ) ) then
        
        return Grade( M ) >= GlobalDimension( R );
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsCyclic,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    
    ByASmallerPresentation( M );
    
    if HasIsCyclic( M ) then
        return IsCyclic( M );
    fi;
    
    TryNextMethod( );
    
end );

##
RedispatchOnCondition( IsCyclic, true, [ IsFinitelyPresentedModuleRep ], [ IsArtinian ], 0 );

##
InstallMethod( IsHolonomic,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R;
    
    R := HomalgRing( M );
    
    if HasGlobalDimension( R ) and ## FIXME: declare an appropriate property for such rings
       ( ( HasIsIntegersForHomalg( R ) and IsIntegersForHomalg( R ) ) or
         ( HasIsFreePolynomialRing( R ) and IsFreePolynomialRing( R ) ) or
         ( HasIsWeylRing( R ) and IsWeylRing( R ) ) or
         ( HasIsLocalizedWeylRing( R ) and IsLocalizedWeylRing( R ) ) ) then
        
        return IsArtinian( M );
        
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsReflexive,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) <= 1 then
        return IsTorsionFree( M );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsProjective,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, proj;
    
    R := HomalgRing( M );
    
    if FiniteFreeResolution( M ) = fail then
        TryNextMethod( );
    fi;
    
    proj := ProjectiveDimension( M ) = 0;
    
    if proj then
        M!.UpperBoundForProjectiveDimension := 0;
    fi;
    
    return proj;
    
end );

##
InstallGlobalFunction( IsProjectiveByCheckingIfExt1WithValuesInFirstSyzygiesModuleIsZero,
  function( M )
    local R, K, proj;
    
    R := HomalgRing( M );
    
    if not ( HasIsCommutative( R ) and IsCommutative( R ) ) then
        return fail;
    fi;
    
    K := SyzygiesObject( M );
    
    proj := IsZero( Ext( 1, M, K ) );
    
    if proj then
        M!.UpperBoundForProjectiveDimension := 0;
    fi;
    
    SetIsProjective( M, proj );
    
    return proj;
    
end );

##
InstallMethod( IsProjective,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local b;
    
    b := IsProjectiveByCheckingForASplit( M );
    
    if b = fail then
        TryNextMethod( );
    fi;
    
    return b;
    
end );

##
InstallMethod( IsProjective,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, proj;
    
    R := HomalgRing( M );
    
    if not ( HasIsFiniteFreePresentationRing( R ) and IsFiniteFreePresentationRing( R ) ) then
        TryNextMethod( );
    fi;
    
    if FiniteFreeResolution( M ) = fail then
        TryNextMethod( );
    fi;
    
    proj := ProjectiveDimension( M ) = 0;
    
    if proj then
        M!.UpperBoundForProjectiveDimension := 0;
    fi;
    
    return proj;
    
end );

##
InstallMethod( IsProjective,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) < infinity then
        return DegreeOfTorsionFreeness( M ) = infinity;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsProjective,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, global_dimension;
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        global_dimension := LeftGlobalDimension;
    else
        global_dimension := RightGlobalDimension;
    fi;
    
    if Tester( global_dimension )( R ) and global_dimension( R ) <= 2 then
        return IsReflexive( M );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallGlobalFunction( IsProjectiveOfConstantRankByCheckingFittingsCondition,
  function( M )
    local R, b;
    
    R := HomalgRing( M );
    
    if not ( HasIsCommutative( R ) and IsCommutative( R ) ) then
        return fail;
    fi;
    
    b := ( FittingIdeal( M ) = R );
    
    SetIsProjectiveOfConstantRank( M, b );
    
    return b;
    
end );

##
InstallMethod( IsProjectiveOfConstantRank,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local b;
    
    b := IsProjectiveOfConstantRankByCheckingFittingsCondition( M );
    
    if b = fail then
        TryNextMethod( );
    fi;
    
    return b;
    
end );

##
InstallMethod( IsStablyFree,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    
    if not IsProjective( M ) then
        return false;
    fi;
    
    if FiniteFreeResolution( M ) = fail then
        TryNextMethod( );
    fi;
    
    ## Serre's 1955 remark:
    ## for a module with a finite free resolution (FFR)
    ## "projective" and "stably free" are equivalent
    return IsProjective( M );
    
end );

##
InstallMethod( IsFree,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, par, img, free;
    
    R := HomalgRing( M );
    
    if not HasRankOfObject( M ) then
        ## automatically sets the rank if it succeeds
        ## to compute a complete free resolution:
        Resolution( M );
    fi;
    
    if HasRankOfObject( M ) and RankOfObject( M ) = 1 then
        
        ## this returns a minimal parametrization of M
        ## (minimal = cokernel is torsion);
        ## I learned this from Alban Quadrat
        par := MinimalParametrization( M );
        
        if IsMonomorphism( par ) then
            
            img := MatrixOfMap( par );
            
            ## Plesken: a good notion of basis (involutive/groebner/...)
            ## should respect principal ideals and hence,
            ## due to the uniqueness of the basis,
            ## can be used to decide if an ideal is principal or not
            if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
                img := BasisOfRows( img );
                free := NumberRows( img ) <= 1;
            else
                img := BasisOfColumns( img );
                free := NumberColumns( img ) <= 1;
            fi;
            
            if free then
                return true;
            elif HasBasisAlgorithmRespectsPrincipalIdeals( R ) and
              BasisAlgorithmRespectsPrincipalIdeals( R ) then
                return false;
            fi;
        else
            return false;
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsFree,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R;
    
    R := HomalgRing( M );
    
    if not IsStablyFree( M ) then
        return false;
    fi;
    
    if not HasRankOfObject( M ) then
        ## this should set the rank if it doesn't fail
        if FiniteFreeResolution( M ) = fail then
            TryNextMethod( );
        fi;
    fi;
    
    ## by now RankOfObject will exist and this
    ## should trigger immediate methods to check IsFree
    if  HasIsFree( M ) then
        return IsFree( M );
    fi;
    
    if IsStablyFree( M ) then
        ## FIXME: sometimes the immediate methods are not triggered and do not set IsFree
        if HasIsCommutative( R ) and IsCommutative( R ) and RankOfObject( M ) = 1 then
            ## [Lam06, Theorem I.4.11], this is in principle the Cauchy-Binet formula
            return true;
        elif HasGeneralLinearRank( R ) and GeneralLinearRank( R ) <= RankOfObject( M ) then
            ## [McCRob, Theorem 11.1.14]
            return true;
        elif HasElementaryRank( R ) and ElementaryRank( R ) <= RankOfObject( M ) then
            ## [McCRob, Theorem 11.1.14 and Proposition 11.3.11]
            return true;
        elif HasStableRank( R ) and StableRank( R ) <= RankOfObject( M ) then
            ## [McCRob, Theorem 11.1.14 and Proposition 11.3.11]
            return true;
        fi;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsReduced,
        "LIMOD: for homalg modules",
        [ IsHomalgModule ],
        
  function( M )
    local I;
    
    I := Annihilator( M );
    
    return IsSubset( I, RadicalSubobject( I ) );
    
end );

## fallback method
InstallMethod( IsPrimeModule,
        "for homalg modules",
        [ IsHomalgModule ],
        
  function( M )
    local dec;
    
    dec := PrimaryDecomposition( M );
    
    return Length( dec ) = 1 and IsSubset( dec[1][1], dec[1][2] );
    
end );

##
InstallMethod( IsPrimeModule,
        "for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, RP, tr, subobject, mat;
    
    R := HomalgRing( M );
    
    RP := homalgTable( R );
    
    if not IsBound( RP!.IsPrime ) then
        TryNextMethod( );
    fi;
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        tr := IdFunc;
    else
        tr := Involution;
    fi;
    
    mat := MatrixOfRelations( M );
    
    return IsPrimeModule( tr( mat ) );
    
end );

## IsPrime is unfortunately hijacked as an operation
InstallMethod( IsPrime,
        "for homalg modules",
        [ IsHomalgModule ],
        
  IsPrimeModule );

####################################
#
# methods for attributes:
#
####################################

##
InstallMethod( Annihilator,
        "for homalg module elements",
        [ IsElementOfAModuleGivenByAMorphismRep ],
        
  function( e )
    local mat, rel;
    
    mat := MatrixOfMap( UnderlyingMorphism( e ) );
    rel := RelationsOfModule( SuperObject( e ) );
    
    return Annihilator( mat, rel );
    
end );

##
InstallMethod( Annihilator,
        "for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, gens, Ann, i;
    
    if IsZero( M ) then
        
        return FullSubobject( One( M ) );
        
    elif HasIsTorsion( M ) and not IsTorsion( M ) then
        
        R := HomalgRing( M );
      
        ## Z/2 is torsion-free over Z/6 with annihilator <3>
        if HasIsIntegralDomain( R ) and IsIntegralDomain( R ) then
            return ZeroSubobject( One( M ) );
        fi;
        
    fi;
    
    gens := GeneratingElements( M );
    
    ## since M is nontrivial gens is nonempty
    Ann := Annihilator( gens[1] );
    
    for i in [ 2 .. Length( gens ) ] do
        
        if IsZero( Ann ) then
            ## return the standard zero ideal
            return ZeroSubobject( One( M ) );
        fi;
        
        Ann := Intersect2( Ann, Annihilator( gens[i] ) );
        
    od;
    
    if IsZero( Ann ) then
        ## return the standard zero ideal
        return ZeroSubobject( One( M ) );
    fi;
    
    return Ann;
    
end );

##
InstallMethod( TorsionSubobject,
        "LIMOD: for homalg modules",
        [ IsHomalgModule ],
        
  function( M )
    local par, emb, tor;
    
    if HasIsTorsion( M ) and IsTorsion( M ) then
        return FullSubobject( M );
    fi;
    
    ## compute any parametrization since computing
    ## a "minimal" parametrization requires the
    ## rank which if unknown would probably trigger Resolution
    par := AnyParametrization( M );
    
    tor := KernelSubobject( par );
    
    SetIsTorsion( tor, true );
    
    return tor;
    
end );

##
InstallMethod( TheMorphismToZero,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    
    return HomalgZeroMap( M, 0*M ); ## never set its Kernel to M, since a possibly existing NaturalGeneralizedEmbedding in M will be overwritten!
    
end );

##
InstallMethod( TheIdentityMorphism,
        "LIMOD: for homalg modules",
        [ IsHomalgModule ],
        
  function( M )
    
    return HomalgIdentityMap( M );
    
end );

##
InstallMethod( FullSubobject,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local subobject;
    
    if HasIsFree( M ) and IsFree( M ) then
        subobject := ImageSubobject( TheIdentityMorphism( M ) );
    else
        subobject := Subobject( HomalgIdentityMatrix( NrGenerators( M ), HomalgRing( M ) ), M );
    fi;
    
    MatchPropertiesAndAttributesOfSubobjectAndUnderlyingObject( subobject, M );
    
    SetEmbeddingInSuperObject( subobject, TheIdentityMorphism( M ) );
    
    return subobject;
    
end );

##
InstallMethod( ZeroSubobject,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local n, R, zero;
    
    n := NrGenerators( M );
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        zero := HomalgZeroMatrix( 0, n, R );
    else
        zero := HomalgZeroMatrix( n, 0, R );
    fi;
    
    return Subobject( zero, M );
    
end );

##
InstallMethod( RankOfObject,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R;
    
    R := HomalgRing( M );
    
    if not ( HasIsCommutative( R ) and IsCommutative( R ) ) then
        ## cannot use the Fitting ideal criterion below
        TryNextMethod( );
    elif HasGlobalDimension( R ) and GlobalDimension( R ) < infinity then
        ## try computing the rank via a free resolution
        ## which is hopefully cheaper
        TryNextMethod( );
    fi;
    
    return NumberOfFirstNonZeroFittingIdeal( M );
    
end );

##
InstallMethod( RankOfObject,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local l, p, m;
    
    l := ListOfPositionsOfKnownSetsOfRelations( M );
    
    for p in l do
        
        m := MatrixOfRelations( M, p );
        
        if IsHomalgMatrix( m ) then
            if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
                if IsLeftRegular( m ) then
                    return NumberColumns( m ) - NumberRows( m );
                fi;
            else
                if IsRightRegular( m ) then
                    return NumberRows( m ) - NumberColumns( m );
                fi;
            fi;
        fi;
    od;
    
    TryNextMethod( );
    
end );

##
InstallMethod( RankOfObject,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, K, RP, d, dim;
    
    R := HomalgRing( M );
    
    if not ( HasIsCommutative( R ) and IsCommutative( R ) and
       HasCoefficientsRing( R ) and HasKrullDimension( R ) ) then
        TryNextMethod( );
    fi;
    
    K := CoefficientsRing( R );
    
    if not ( HasIsFieldForHomalg( K ) and IsFieldForHomalg( K ) ) then
        TryNextMethod( );
    fi;
    
    RP := homalgTable( R );
    
    if not ( IsBound( RP!.CoefficientsOfUnreducedNumeratorOfHilbertPoincareSeries ) or
             IsBound( RP!.CoefficientsOfNumeratorOfHilbertPoincareSeries ) ) then
        TryNextMethod( );
    fi;
    
    d := KrullDimension( R );
    
    dim := AffineDimension( M );
    
    if dim >  d then
        Error( "the dimension of the module is greater than the Krull dimension of the ring\n" );
    fi;
    
    if dim < d then
        return 0;
    fi;
    
    return AffineDegree( M );
    
end );

##
InstallMethod( DegreeOfTorsionFreeness,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local DM, k, R, gdim, bound;
    
    DM := AuslanderDual( M );
    
    if IsTorsionFree( M ) then
        k := 2;
    else
        return 0;
    fi;
    
    if IsReflexive( M ) then
        k := 3;
    fi; ## do not return 1 in case the ring has global dimension 0
    
    R := HomalgRing( M );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        if not HasLeftGlobalDimension( R ) then
            TryNextMethod( );
        fi;
        gdim := LeftGlobalDimension( R );
    else
        if not HasRightGlobalDimension( R ) then
            TryNextMethod( );
        fi;
        gdim := RightGlobalDimension( R );
    fi;
    
    if gdim = infinity then
        bound := BoundForResolution( M );
    else
        bound := gdim;
    fi;
    
    while k <= bound do
        if not IsZero( Ext( k, DM ) ) then
            return k - 1;
        fi;
        k := k + 1;
    od;
    
    if gdim < infinity then
        return infinity;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( ProjectiveDimension,
        "LIMOD: for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local d, ld, pd, s;
    
    ## in future Resolution( M ) might compute a free resolution only up to
    ## an a priori known upper bound of the projective dimension (+1), which
    ## would mean that such an "incomplete" resolution is not acyclic in general
    ## and ShortenResolution will not apply. Therefore:
    d := FiniteFreeResolution( M );
    
    if d = fail then
        TryNextMethod( );
    fi;
    
    ld := Length( MorphismDegreesOfComplex( d ) );
    
    d := ShortenResolution( d );
    
    pd := Length( MorphismDegreesOfComplex( d ) );
    
    if pd < ld then
        SetAFiniteFreeResolution( M, d );
    fi;
    
    ## Serre's 1955 remark:
    ## for a module with a finite free resolution (FFR)
    ## "projective" and "stably free" are equivalent
    ## (so now we check stably freeness)
    if pd = 1 then
        s := PostInverse( LowestDegreeMorphism( d ) );
        if not IsBool( s ) then
            pd := 0;
        fi;
    fi;
    
    return pd;
    
end );

##
InstallMethod( CoefficientsOfUnreducedNumeratorOfHilbertPoincareSeries,
        "for a homalg module",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local mat;
    
    mat := MatrixOfRelations( M );
    
    if IsHomalgRightObjectOrMorphismOfRightObjects( M ) then
        mat := Involution( mat );
    fi;
    
    mat := BasisOfRows( mat );
    
    return CoefficientsOfUnreducedNumeratorOfHilbertPoincareSeries( mat );
    
end );

##
InstallMethod( CoefficientsOfNumeratorOfHilbertPoincareSeries,
        "for a homalg module",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local mat;
    
    mat := MatrixOfRelations( M );
    
    if IsHomalgRightObjectOrMorphismOfRightObjects( M ) then
        mat := Involution( mat );
    fi;
    
    mat := BasisOfRows( mat );
    
    return CoefficientsOfNumeratorOfHilbertPoincareSeries( mat );
    
end );

##
InstallMethod( UnreducedNumeratorOfHilbertPoincareSeries,
        "for a homalg module",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local mat;
    
    mat := MatrixOfRelations( M );
    
    if IsHomalgRightObjectOrMorphismOfRightObjects( M ) then
        mat := Involution( mat );
    fi;
    
    mat := BasisOfRows( mat );
    
    return UnreducedNumeratorOfHilbertPoincareSeries( mat );
    
end );

##
InstallMethod( NumeratorOfHilbertPoincareSeries,
        "for a homalg module",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local mat;
    
    mat := MatrixOfRelations( M );
    
    if IsHomalgRightObjectOrMorphismOfRightObjects( M ) then
        mat := Involution( mat );
    fi;
    
    mat := BasisOfRows( mat );
    
    return NumeratorOfHilbertPoincareSeries( mat );
    
end );

##
InstallMethod( HilbertPoincareSeries,
        "for a homalg module",
        [ IsHomalgModule ],
        
  function( M )
    
    return HilbertPoincareSeries( M, VariableForHilbertPoincareSeries( ) );
    
end );

##
InstallMethod( HilbertPoincareSeries,
        "for a homalg submodule",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep ],
        
  function( M )
    
    return HilbertPoincareSeries( SuperObject( M ) ) - HilbertPoincareSeries( FactorObject( M ) );
    
end );

##
InstallMethod( HilbertPolynomial,
        "for a homalg module",
        [ IsHomalgModule ],
        
  function( M )
    
    return HilbertPolynomial( M, VariableForHilbertPolynomial( ) );
    
end );

##
InstallMethod( HilbertPolynomial,
        "for a homalg submodule",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep ],
        
  function( M )
    
    return HilbertPolynomial( SuperObject( M ) ) - HilbertPolynomial( FactorObject( M ) );
    
end );

##
InstallMethod( DataOfHilbertFunction,
        "for a homalg module",
        [ IsHomalgModule and IsFinitelyPresentedObjectRep ],
        
  function( M )
    local HP;
    
    HP := HilbertPoincareSeries( M );
    
    return DataOfHilbertFunction( HP );
    
end );

##
InstallMethod( HilbertFunction,
        "for a homalg module",
        [ IsHomalgModule and IsFinitelyPresentedObjectRep ],
        
  function( M )
    local HP;
    
    HP := HilbertPoincareSeries( M );
    
    return HilbertFunction( HP );
    
end );

##
InstallMethod( IndexOfRegularity,
        "for a homalg module",
        [ IsHomalgModule and IsFinitelyPresentedObjectRep ],
        
  function( M )
    local range;
    
    if IsZero( M ) then
        Error( "GAP does not support -infinity yet\n" );
    fi;
    
    range := DataOfHilbertFunction( M )[1][2];
    
    return range[Length( range )] + 1;
    
end );

##
InstallMethod( ElementOfGrothendieckGroup,
        "for a homalg module",
        [ IsHomalgModule and IsFinitelyPresentedObjectRep ],
        
  function( M )
    local chi, dim;
    
    chi := HilbertPolynomial( M );
    
    dim := Length( Indeterminates( HomalgRing( M ) ) ) - 1;
    
    return CreateElementOfGrothendieckGroupOfProjectiveSpace( chi, dim );
    
end );

##
InstallMethod( ChernPolynomial,
        "for a homalg module",
        [ IsHomalgModule and IsFinitelyPresentedObjectRep ],
        
  function( M )
    local P;
    
    P := ElementOfGrothendieckGroup( M );
    
    return ChernPolynomial( P );
    
end );

##
InstallMethod( ChernCharacter,
        "for a homalg module",
        [ IsHomalgModule and IsFinitelyPresentedObjectRep ],
        
  function( M )
    local c;
    
    c := ChernPolynomial( M );
    
    return ChernCharacter( c );
    
end );

##
InstallMethod( PrimaryDecomposition,
        "for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local tr, subobject, mat;
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        tr := IdFunc;
        subobject := LeftSubmodule;
    else
        tr := Involution;
        subobject := RightSubmodule;
    fi;
    
    ## FIXME: PrimaryDecompostion of submodules is delegated to the factor object,
    ## this is a bad. Until we fix it we have to take care of the unit ideal
    if IsZero( M ) then
        mat := HomalgIdentityMatrix( 1, HomalgRing( M ) );
        return [ ListWithIdenticalEntries( 2, subobject( mat ) ) ];
    fi;
    
    mat := MatrixOfRelations( M );
    
    return
      List( PrimaryDecompositionOp( tr( mat ) ),
            function( pp )
              local primary, prime;
              
              primary := subobject( tr( pp[1] ) );
              prime := subobject( tr( pp[2] ) );
              
              return [ primary, prime ];
              
            end
          );
    
end );

## fallback method
InstallMethod( RadicalDecomposition,
        "for homalg modules",
        [ IsHomalgModule and IsFinitelyPresentedObjectRep ],
        
  function( M )
    
    return List( PrimaryDecomposition( M ), a -> a[2] );
    
end );

##
InstallMethod( RadicalDecomposition,
        "for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, RP, tr, subobject, mat;
    
    R := HomalgRing( M );
    
    RP := homalgTable( R );
    
    if not IsBound( RP!.RadicalDecomposition ) then
        TryNextMethod( );
    fi;
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
        tr := IdFunc;
        subobject := LeftSubmodule;
    else
        tr := Involution;
        subobject := RightSubmodule;
    fi;
    
    ## FIXME: PrimaryDecompostion of submodules is delegated to the factor object,
    ## this is a bad. Until we fix it we have to take care of the unit ideal
    if IsZero( M ) then
        mat := HomalgIdentityMatrix( 1, HomalgRing( M ) );
        return [ subobject( mat ) ];
    fi;
    
    mat := MatrixOfRelations( M );
    
    return List( RadicalDecompositionOp( tr( mat ) ),
                 pp -> subobject( tr( pp ) ) );
    
end );

## fallback method
InstallMethod( RadicalSubobject,
        "for homalg modules",
        [ IsHomalgModule and IsFinitelyPresentedObjectRep ],
        
  function( J )
    
    return Intersect( RadicalDecomposition( J ) );
    
end );

##
InstallMethod( ResidueClassRing,
        "for homalg ideals",
        [ IsFinitelyPresentedSubmoduleRep and ConstructedAsAnIdeal ],
        
  function( J )
    local A, ring_rel, R;
    
    A := HomalgRing( J );
    
    Assert( 3, not J = A );
    
    ring_rel := MatrixOfGenerators( J );
    
    if IsHomalgLeftObjectOrMorphismOfLeftObjects( J ) then
        ring_rel := HomalgRingRelationsAsGeneratorsOfLeftIdeal( ring_rel );
    else
        ring_rel := HomalgRingRelationsAsGeneratorsOfRightIdeal( ring_rel );
    fi;
    
    R := A / ring_rel;
    
    if HasContainsAField( A ) and ContainsAField( A ) then
        SetContainsAField( R, true );
        if HasCoefficientsRing( A ) then
            SetCoefficientsRing( R, CoefficientsRing( A ) );
        fi;
    fi;
    
    SetDefiningIdeal( R, J );
    
    return R;
    
end );

##
InstallMethod( FittingIdeal,
        "for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local r, Fitt, R;
    
    r := RankOfObject( M );
    
    Fitt := FittingIdeal( r, M );
    
    R := HomalgRing( M );
    
    SetIsZero( Fitt, IsZero( R ) );
    
    if Fitt = R then
        ## if Fitt < R, then M might still be projective
        ## but with non-constant rank
        SetIsProjective( M, true );
        SetHasConstantRank( M, true );
    elif HasIsProjective( M ) and IsProjective( M ) then
        SetHasConstantRank( M, false );
    elif HasHasConstantRank( M ) and HasConstantRank( M ) then
        SetIsProjective( M, false );
    fi;
    
    return Fitt;
    
end );

##
InstallMethod( NonFlatLocus,
        "for homalg modules",
        [ IsFinitelyPresentedModuleRep ],
        
  function( M )
    local R, i, Fitt;
    
    R := HomalgRing( M );
    
    if not ( HasIsCommutative( R ) and IsCommutative( R ) ) then
        TryNextMethod( );
    fi;
    
    return FactorObject( FittingIdeal( M ) );
    
end );


##
InstallMethod( LargestMinimalNumberOfLocalGenerators,
        "for homalg modules",
        [ IsHomalgModule and IsStaticFinitelyPresentedObjectRep ],
        
  function( M )
    local R, i, Fitt_i;
    
    if IsZero( M ) then
        return 0;
    fi;
    
    R := HomalgRing( M );
    
    if not ( HasIsCommutative( R ) and IsCommutative( R ) ) then
        TryNextMethod( );
    fi;
    
    for i in Reversed( [ 0 .. NrGenerators( M ) - 1 ] ) do
        
        Fitt_i := FittingIdeal( i, M );
        
        if not Fitt_i = R then
            return i + 1;
        fi;
        
    od;
    
    ## should never be reached
    Error( "something went wrong\n" );
    
end );

##
InstallMethod( SymmetricAlgebra,
        "for a homalg matrix",
        [ IsHomalgMatrix, IsList ],
        
  function( M, gvar )
    local n, Sym, rel;
    
    n := NumberColumns( M );
    
    if not n = Length( gvar ) then
        Error( "the length of the list of variables is ",
               "not equal to the number of columns of the matrix\n" );
    fi;
    
    Sym := HomalgRing( M ) * gvar;
    
    gvar := RelativeIndeterminatesOfPolynomialRing( Sym );
    gvar := HomalgMatrix( gvar, Length( gvar ), 1, Sym );
    
    rel := LeftSubmodule( ( Sym * M ) * gvar );
    
    Sym := Sym / rel;
    
    SetDefiningIdeal( Sym, rel );
    
    return Sym;
    
end );

##
InstallMethod( SymmetricAlgebra,
        "for homalg modules",
        [ IsHomalgModule and IsStaticFinitelyPresentedObjectRep, IsList ],
        
  function( M, gvar )
    local rel;
    
    rel := MatrixOfRelations( M );
    
    if IsHomalgRightObjectOrMorphismOfRightObjects( M ) then
        rel := Involution( rel );
    fi;
    
    return SymmetricAlgebra( rel, gvar );
    
end );

##
InstallMethod( SymmetricAlgebra,
        "for homalg submodules",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep, IsList ],
        
  function( M, gvar )
    
    return SymmetricAlgebra( UnderlyingObject( M ), gvar );
    
end );

##
InstallMethod( SymmetricAlgebra,
        "for homalg modules",
        [ IsHomalgModule and IsStaticFinitelyPresentedObjectRep, IsString ],
        
  function( M, str )
    local n;
    
    n := NrGenerators( M );
    
    str := ParseListOfIndeterminates( SplitString( str, "," ) );
    
    if Length( str ) = 1 and not n = 1 then
        str := str[1];
        str := List( [ 1 .. n ], i -> Concatenation( str, String( i ) ) );
    fi;
    
    return SymmetricAlgebra( M, str );
    
end );

##
InstallMethod( SymmetricAlgebra,
        "for homalg submodules",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep, IsString ],
        
  function( M, str )
    
    return SymmetricAlgebra( UnderlyingObject( M ), str );
    
end );

##
InstallMethod( SymmetricAlgebraFromSyzygiesObject,
        "for homalg submodules",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep, IsList ],
        
  function( M, gvar )
    
    M := MatrixOfSubobjectGenerators( M );
    
    return SymmetricAlgebra( M, gvar );
    
end );

##
InstallMethod( SymmetricAlgebraFromSyzygiesObject,
        "for homalg submodules",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep, IsString ],
        
  function( M, str )
    local n;
    
    n := NrGenerators( M );
    
    str := ParseListOfIndeterminates( SplitString( str, "," ) );
    
    if Length( str ) = 1 and not n = 1 then
        str := str[1];
        str := List( [ 1 .. n ], i -> Concatenation( str, String( i ) ) );
    fi;
    
    return SymmetricAlgebraFromSyzygiesObject( M, str );
    
end );

##
InstallMethod( ExteriorAlgebra,
        "for a homalg matrix",
        [ IsHomalgMatrix, IsList ],
        
  function( M, gvar )
    local n, A, rel;
    
    n := NumberColumns( M );
    
    if not n = Length( gvar ) then
        Error( "the length of the list of variables is ",
               "not equal to the number of columns of the matrix\n" );
    fi;
    
    A := ExteriorRing( HomalgRing( M ) * List( gvar, v -> Concatenation( "XX", v ) ), gvar );
    
    gvar := IndeterminateAntiCommutingVariablesOfExteriorRing( A );
    gvar := HomalgMatrix( gvar, Length( gvar ), 1, A );
    
    rel := LeftSubmodule( ( A * M ) * gvar );
    
    A := A / rel;
    
    SetDefiningIdeal( A, rel );
    
    return A;
    
end );

##
InstallMethod( ExteriorAlgebra,
        "for homalg modules",
        [ IsHomalgModule and IsStaticFinitelyPresentedObjectRep, IsList ],
        
  function( M, gvar )
    local rel;
    
    rel := MatrixOfRelations( M );
    
    if IsHomalgRightObjectOrMorphismOfRightObjects( M ) then
        rel := Involution( rel );
    fi;
    
    return ExteriorAlgebra( rel, gvar );
    
end );

##
InstallMethod( ExteriorAlgebra,
        "for homalg submodules",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep, IsList ],
        
  function( M, gvar )
    
    return ExteriorAlgebra( UnderlyingObject( M ), gvar );
    
end );

##
InstallMethod( ExteriorAlgebra,
        "for homalg modules",
        [ IsHomalgModule and IsStaticFinitelyPresentedObjectRep, IsString ],
        
  function( M, str )
    local n;
    
    n := NrGenerators( M );
    
    str := ParseListOfIndeterminates( SplitString( str, "," ) );
    
    if Length( str ) = 1 and not n = 1 then
        str := str[1];
        str := List( [ 1 .. n ], i -> Concatenation( str, String( i ) ) );
    fi;
    
    return ExteriorAlgebra( M, str );
    
end );

##
InstallMethod( ExteriorAlgebra,
        "for homalg submodules",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep, IsString ],
        
  function( M, str )
    
    return ExteriorAlgebra( UnderlyingObject( M ), str );
    
end );

##
InstallMethod( ExteriorAlgebraFromSyzygiesObject,
        "for homalg submodules",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep, IsList ],
        
  function( M, gvar )
    
    M := MatrixOfSubobjectGenerators( M );
    
    return ExteriorAlgebra( M, gvar );
    
end );

##
InstallMethod( ExteriorAlgebraFromSyzygiesObject,
        "for homalg submodules",
        [ IsHomalgModule and IsStaticFinitelyPresentedSubobjectRep, IsString ],
        
  function( M, str )
    local n;
    
    n := NrGenerators( M );
    
    str := ParseListOfIndeterminates( SplitString( str, "," ) );
    
    if Length( str ) = 1 and not n = 1 then
        str := str[1];
        str := List( [ 1 .. n ], i -> Concatenation( str, String( i ) ) );
    fi;
    
    return ExteriorAlgebraFromSyzygiesObject( M, str );
    
end );

####################################
#
# logical implications methods:
#
####################################

InstallLogicalImplicationsForHomalgObjects( LogicalImplicationsForHomalgModules, IsHomalgModule );

InstallLogicalImplicationsForHomalgObjects( LogicalImplicationsForHomalgModulesOverSpecialRings, IsHomalgModule, IsHomalgRing );

[ 0.82Quellennavigators  Projekt   ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

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