GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
## LIGrMOD.gi LIGrMOD subpackage
##
## LIGrMOD = Logical Implications for Graded MODules
##
## Copyright 2010, Mohamed Barakat, University of Kaiserslautern
## Markus Lange-Hegermann, RWTH Aachen
##
## Implementations for the LIGrMOD subpackage.
##
#############################################################################
####################################
#
# global variables:
#
####################################
# a central place for configuration variables:
InstallValue( LIGrMOD,
rec(
color := "\033[4;30;46m",
## used in a InstallLogicalImplicationsForHomalgSubobjects call below
intrinsic_properties_specific_shared_with_subobjects_and_ideals :=
[
"IsCohenMacaulay",
],
## used in a InstallLogicalImplicationsForHomalgSubobjects call below
intrinsic_properties_specific_shared_with_factors_modulo_ideals :=
[
],
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 GradedSubmodule.gi
intrinsic_properties_shared_with_subobjects_and_ideals :=
Concatenation(
LIMOD.intrinsic_properties_shared_with_subobjects_and_ideals,
~.intrinsic_properties_specific_shared_with_subobjects_and_ideals ),
##
intrinsic_properties_shared_with_factors_modulo_ideals :=
Concatenation(
LIMOD.intrinsic_properties_shared_with_factors_modulo_ideals,
~.intrinsic_properties_specific_shared_with_factors_modulo_ideals ),
## needed for MatchPropertiesAndAttributes in GradedSubmodule.gi
intrinsic_properties_shared_with_subobjects_which_are_not_ideals :=
Concatenation(
LIMOD.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(
LIMOD.intrinsic_properties,
~.intrinsic_properties_specific ),
## used in a InstallLogicalImplicationsForHomalgSubobjects call below
intrinsic_attributes_specific_shared_with_subobjects_and_ideals :=
[
"BettiTable",
"LinearRegularityInterval",
"LinearRegularity",
"CastelnuovoMumfordRegularity",
"CastelnuovoMumfordRegularityOfSheafification",
],
## 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
"HilbertPolynomial",
],
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 GradedSubmodule.gi
intrinsic_attributes_shared_with_subobjects_and_ideals :=
Concatenation(
LIMOD.intrinsic_attributes_shared_with_subobjects_and_ideals,
~.intrinsic_attributes_specific_shared_with_subobjects_and_ideals ),
##
intrinsic_attributes_shared_with_factors_modulo_ideals :=
Concatenation(
LIMOD.intrinsic_attributes_shared_with_factors_modulo_ideals,
~.intrinsic_attributes_specific_shared_with_factors_modulo_ideals ),
## needed for MatchPropertiesAndAttributes in GradedSubmodule.gi
intrinsic_attributes_shared_with_subobjects_which_are_not_ideals :=
Concatenation(
LIMOD.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(
LIMOD.intrinsic_attributes,
~.intrinsic_attributes_specific ),
exchangeable_properties :=
[
"IsZero",
"IsProjective",
"IsProjectiveOfConstantRank",
"IsReflexive",
"IsTorsionFree",
"IsTorsion",
"IsArtinian",
"IsPure",
"IsFree",
"IsStablyFree",
"IsCyclic",
"HasConstantRank",
"IsHolonomic",
],
exchangeable_attributes :=
[
"RankOfObject",
"ProjectiveDimension",
"DegreeOfTorsionFreeness",
"CodegreeOfPurity",
"Grade",
],
)
);
####################################
#
# logical implications methods:
#
####################################
InstallLogicalImplicationsForHomalgSubobjects(
List( LIGrMOD.intrinsic_properties_specific_shared_with_subobjects_which_are_not_ideals, ValueGlobal ),
IsGradedSubmoduleRep and NotConstructedAsAnIdeal,
HasEmbeddingInSuperObject,
UnderlyingObject );
InstallLogicalImplicationsForHomalgSubobjects(
List( LIGrMOD.intrinsic_properties_specific_shared_with_subobjects_and_ideals, ValueGlobal ),
IsGradedSubmoduleRep and ConstructedAsAnIdeal,
HasEmbeddingInSuperObject,
UnderlyingObject );
InstallLogicalImplicationsForHomalgSubobjects(
List( LIGrMOD.intrinsic_properties_specific_shared_with_factors_modulo_ideals, ValueGlobal ),
IsGradedSubmoduleRep and ConstructedAsAnIdeal,
HasFactorObject,
FactorObject );
InstallLogicalImplicationsForHomalgSubobjects(
List( LIGrMOD.intrinsic_attributes_specific_shared_with_subobjects_which_are_not_ideals, ValueGlobal ),
IsGradedSubmoduleRep and NotConstructedAsAnIdeal,
HasEmbeddingInSuperObject,
UnderlyingObject );
InstallLogicalImplicationsForHomalgSubobjects(
List( LIGrMOD.intrinsic_attributes_specific_shared_with_subobjects_and_ideals, ValueGlobal ),
IsGradedSubmoduleRep and ConstructedAsAnIdeal,
HasEmbeddingInSuperObject,
UnderlyingObject );
InstallLogicalImplicationsForHomalgSubobjects(
List( LIGrMOD.intrinsic_attributes_specific_shared_with_factors_modulo_ideals, ValueGlobal ),
IsGradedSubmoduleRep and ConstructedAsAnIdeal,
HasFactorObject,
FactorObject );
####################################
#
# immediate methods for properties:
#
####################################
##
InstallImmediateMethod( IsZero,
IsGradedModuleRep and HasAffineDimension, 0,
function( M )
return AffineDimension( M ) <= HOMALG_MODULES.DimensionOfZeroModules;
end );
##
InstallImmediateMethodToPullPropertiesOrAttributes(
IsHomalgGradedModule,
IsHomalgGradedModule,
LIGrMOD.exchangeable_properties,
Concatenation( LIGrMOD.intrinsic_properties, LIGrMOD.intrinsic_attributes ),
UnderlyingModule );
##
InstallImmediateMethodToPushPropertiesOrAttributes( Twitter,
IsHomalgGradedModule,
LIGrMOD.exchangeable_properties,
UnderlyingModule );
####################################
#
# immediate methods for attributes:
#
####################################
##
InstallImmediateMethodToPullPropertiesOrAttributes(
IsHomalgGradedModule,
IsHomalgGradedModule,
LIGrMOD.exchangeable_attributes,
Concatenation( LIGrMOD.intrinsic_properties, LIGrMOD.intrinsic_attributes ),
UnderlyingModule );
##
InstallImmediateMethodToPushPropertiesOrAttributes( Twitter,
IsHomalgGradedModule,
LIGrMOD.exchangeable_attributes,
UnderlyingModule );
# ##
# InstallImmediateMethod( IsModuleOfGlobalSectionsTruncatedAtCertainDegree,
# IsHomalgGradedModule, 0,
#
# function( M )
# local UM;
#
# UM := UnderlyingModule( M );
#
# if DegreesOfGenerators( M ) <> [] and HasIsFree( UM ) and IsFree( UM ) then
# return Minimum( DegreesOfGenerators( M ) );
# fi;
#
# TryNextMethod( );
#
# end );
# ##
# InstallImmediateMethod( IsModuleOfGlobalSectionsTruncatedAtCertainDegree,
# IsHomalgGradedModule and HasCastelnuovoMumfordRegularity, 0,
#
# function( M )
# local UM;
#
# if DegreesOfGenerators( M ) <> [] and CastelnuovoMumfordRegularity( M ) <= Minimum( DegreesOfGenerators( M ) ) then
# return Minimum( DegreesOfGenerators( M ) );
# fi;
#
# TryNextMethod( );
#
# end );
##
InstallImmediateMethod( IsModuleOfGlobalSectionsTruncatedAtCertainDegree,
IsHomalgGradedModule and HasIsZero and IsZero, 0,
function( M )
local UM;
return true;
end );
##
InstallImmediateMethod( LinearRegularity,
IsGradedModuleRep and HasLinearRegularityInterval, 0,
function( M )
local linreg;
linreg := LinearRegularityInterval( M );
return linreg[Length( linreg )];
end );
####################################
#
# methods for properties:
#
####################################
##
InstallMethod( IsZero,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ],
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( UnderlyingNonGradedRing( R ) );
if IsBound( RP!.AffineDimension ) or
IsBound( RP!.CoefficientsOfUnreducedNumeratorOfHilbertPoincareSeries ) or
IsBound( RP!.CoefficientsOfNumeratorOfHilbertPoincareSeries ) then
## hand over to UnderlyingModule;
## this avoids the unnecessary degree calls triggered by AffineDimension( M ) below
TryNextMethod( );
fi;
if not ( IsBound( RP!.CoefficientsOfUnreducedNumeratorOfWeightedHilbertPoincareSeries ) or
IsBound( RP!.CoefficientsOfNumeratorOfWeightedHilbertPoincareSeries ) ) then
TryNextMethod( );
fi;
return AffineDimension( M ) <= HOMALG_MODULES.DimensionOfZeroModules;
end );
##
# Fallback, works in general
InstallMethod( IsArtinian,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ], -10,
function( M )
return IsEmptyMatrix( GeneratorsOfHomogeneousPart( HomalgElementToInteger( CastelnuovoMumfordRegularity( M ) ) + 1, M ) );
end );
##
# faster, needs a field as CoefficientsRing and a medthod AffineDimension
InstallMethod( IsArtinian,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local S, R, K, RP;
if IsZero( M ) then
return true;
fi;
S := HomalgRing( M );
R := UnderlyingNonGradedRing( S );
K := CoefficientsRing( R );
if not ( HasIsFieldForHomalg( K ) and IsFieldForHomalg( K ) ) then
TryNextMethod( );
fi;
RP := homalgTable( R );
if not IsBound( RP!.AffineDimension ) then
TryNextMethod( );
fi;
return AffineDimension( M ) <= 0;
end );
##
InstallMethod( IsCohenMacaulay,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local S, m;
S := HomalgRing( M );
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
m := MaximalGradedLeftIdeal( S );
else
m := MaximalGradedRightIdeal( S );
fi;
return AffineDimension( M ) = Grade( m, M );
end );
####################################
#
# methods for attributes:
#
####################################
##
InstallMethod( Annihilator,
"for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
return GradedModule( Annihilator( UnderlyingModule( M ) ), HomalgRing( M ) );
end );
##
InstallMethod( BettiTable,
"LIGrMOD: for homalg graded modules",
[ IsHomalgGradedModule ],
function( M )
local C, degrees, min, C_degrees, l, ll, r, beta;
## M = coker( F_0 <-- F_1 )
C := Resolution( 1, M );
## [ F_0, F_1 ];
C := ObjectsOfComplex( C ){[ 1 .. 2 ]};
## the list of generators degrees of F_0 and F_1
degrees := List( C, DegreesOfGenerators );
degrees := List( degrees, i -> List( i, HomalgElementToInteger ) );
## the homological degrees of the resolution complex C: F_0 <- F_1
C_degrees := [ 0 .. 1 ];
## a counting list
l := [ 1 .. Length( C_degrees ) ];
## the non-empty list
ll := Filtered( l, j -> degrees[j] <> [ ] );
## the degree of the lowest row in the Betti diagram
if ll <> [ ] then
r := MaximumList( List( ll, j -> MaximumList( degrees[j] ) - ( j - 1 ) ) );
else
r := 0;
fi;
## the lowest generator degree of F_0
if degrees[1] <> [ ] then
min := MinimumList( degrees[1] );
else
min := r;
fi;
## the row range of the Betti diagram
r := [ min .. r ];
## the Betti table
beta := List( r, i -> List( l, j -> Length( Filtered( degrees[j], a -> a = i + ( j - 1 ) ) ) ) );
return HomalgBettiTable( beta, r, C_degrees, M );
end );
##
InstallMethod( CastelnuovoMumfordRegularity,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local S, B, nS, nB, max, B_S, B2, l;
S := HomalgRing( M );
B := BaseRing( S );
nS := Length( Indeterminates( S ) );
nB := Length( Indeterminates( B ) );
## FIXME: use IrrelevantIdeal( M )
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
max := CertainRows( MaximalIdealAsColumnMatrix( S ), [ nB+1 .. nS ] );
B_S := LeftPresentationWithDegrees( max );
else
max := CertainColumns( MaximalIdealAsRowMatrix( S ), [ nB+1 .. nS ] );
B_S := RightPresentationWithDegrees( max );
fi;
# Computations with the residue class rings are inefficient
B2 := S / max;
SetWeightsOfIndeterminates( B2, WeightsOfIndeterminates( B ) );
l := List( [ 0 .. nS ], i-> HomalgElementToInteger( CastelnuovoMumfordRegularity( B2 * Tor( i, B_S, M ) ) ) - i );
return Maximum( l );
end );
##
InstallMethod( CastelnuovoMumfordRegularity,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local S, minus_infinity, betti, degrees, B, nS, nB, max, B_S, B2, l;
S := HomalgRing( M );
minus_infinity := HOMALG_TOOLS.minus_infinity;
## TODO: Every ring should have a base ring
if HasBaseRing( S ) and not IsIdenticalObj( BaseRing( S ), CoefficientsRing( S ) ) then
TryNextMethod( );
fi;
if IsZero( M ) then
return minus_infinity;
## do not use IsQuasiZero unless it does not fall back to CastelnuovoMumfordRegularity
elif AffineDimension( M ) = 0 then
return Degree( HilbertPoincareSeries( M ) );
fi;
betti := BettiTable( Resolution( M ) );
degrees := RowDegreesOfBettiTable( betti );
return degrees[Length(degrees)];
end );
## FIXME: knowledge propagation suggests the use of IsFree in the list of conditions
InstallMethod( CastelnuovoMumfordRegularity,
"LIGrMOD: for homalg graded free modules",
[ IsGradedModuleRep ],10,
function( M )
local UM, minus_infinity, deg;
UM := UnderlyingModule( M );
minus_infinity := HOMALG_TOOLS.minus_infinity;
if HasIsFree( UM ) and IsFree( UM ) then
if HasIsZero( M ) and IsZero( M ) then
# todo: -infinity
return minus_infinity;
fi;
deg := DegreesOfGenerators( M );
if IsList( deg ) and ( IsInt( deg[1] ) or IsHomalgElement( deg[ 1 ] ) ) then
return Maximum( deg );
fi;
fi;
TryNextMethod( );
end );
##
InstallMethod( CastelnuovoMumfordRegularityOfSheafification,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local min_deg, CMreg;
## we cannot expect this to be less or equal to the
## Castelnuovo-Mumford regularity of the sheafification
min_deg := Minimum( DegreesOfGenerators( M ) );
CMreg := CastelnuovoMumfordRegularity( M );
TateResolution( M, min_deg, CMreg );
if HasCastelnuovoMumfordRegularityOfSheafification( M ) then
return CastelnuovoMumfordRegularityOfSheafification( M );
fi;
TryNextMethod( );
end );
##
InstallGlobalFunction( LinearRegularityIntervalViaMinimalResolution,
function( M )
local S, minus_infinity, dim, betti, cols, degrees, col0, col1, mat, rows, d, d0, d1;
S := HomalgRing( M );
## TODO: Every ring should have a base ring
if HasBaseRing( S ) and not IsIdenticalObj( BaseRing( S ), CoefficientsRing( S ) ) then
TryNextMethod( );
fi;
minus_infinity := HOMALG_TOOLS.minus_infinity;
if IsZero( M ) then
return [ minus_infinity ];
## do not use IsQuasiZero unless it does not fall back to CastelnuovoMumfordRegularity
elif AffineDimension( M ) = 0 then
return [ Degree( HilbertPoincareSeries( M ) ) ];
fi;
if HasRelativeIndeterminatesOfPolynomialRing( S ) then
dim := Length( RelativeIndeterminatesOfPolynomialRing( S ) );
else
dim := Length( IndeterminatesOfPolynomialRing( S ) );
fi;
betti := BettiTable( Resolution( M ) );
cols := ColumnDegreesOfBettiTable( betti );
cols := Intersection2( cols, [ dim - 1, dim ] );
if IsEmpty( cols ) then
return [ minus_infinity ];
fi;
degrees := RowDegreesOfBettiTable( betti );
## 0 stands for Ext^0
col0 := Intersection2( cols, [ dim ] );
col0 := col0 + 1;
d0 := minus_infinity;
if not IsEmpty( col0 ) then
mat := List( betti!.matrix, b -> b{col0} );
rows := Filtered( [ 1 .. Length( mat ) ], a -> not IsZero( mat[a] ) );
if not IsEmpty( rows ) then
d := degrees{rows};
d0 := d[Length( rows )];
fi;
fi;
## 1 stand for Ext^1
col1 := Intersection2( cols, [ dim - 1 ] );
col1 := col1 + 1;
d1 := minus_infinity;
if not IsEmpty( col1 ) then
mat := List( betti!.matrix, b -> b{col1} );
rows := Filtered( [ 1 .. Length( mat ) ], a -> not IsZero( mat[a] ) );
if not IsEmpty( rows ) then
d := degrees{rows};
d1 := d[Length( rows )] - 1;
fi;
fi;
return [ d0 .. Maximum( d0, d1 ) ];
end );
##
InstallGlobalFunction( LinearRegularityIntervalViaExt01OverBaseField,
function( M )
local S, minus_infinity, m, k, d0, d1, linreg;
S := HomalgRing( M );
## TODO: Every ring should have a base ring
if HasBaseRing( S ) and not IsIdenticalObj( BaseRing( S ), CoefficientsRing( S ) ) then
TryNextMethod( );
fi;
minus_infinity := HOMALG_TOOLS.minus_infinity;
if IsZero( M ) then
return [ minus_infinity ];
## do not use IsQuasiZero unless it does not fall back to CastelnuovoMumfordRegularity
elif AffineDimension( M ) = 0 then
return [ Degree( HilbertPoincareSeries( M ) ) ];
fi;
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
m := MaximalGradedLeftIdeal( S );
else
m := MaximalGradedRightIdeal( S );
fi;
k := FactorObject( m );
d0 := Degree( HilbertPoincareSeries( GradedHom( k, M ) ) );
d1 := Degree( HilbertPoincareSeries( GradedExt( 1, k, M ) ) );
## FIXME
if d0 = -infinity then
d0 := minus_infinity;
fi;
if d1 = -infinity then
d1 := minus_infinity;
fi;
linreg := [ d0 .. Maximum( d0, d1 ) ];
SetLinearRegularityInterval( M, linreg );
return linreg;
end );
##
InstallMethod( LinearRegularityInterval,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ],
LinearRegularityIntervalViaMinimalResolution );
##
InstallMethod( LinearRegularity,
"LIGrMOD: for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local linreg;
linreg := LinearRegularityInterval( M );
return linreg[Length( linreg )];
end );
##
InstallMethod( Depth,
"LIMOD: for two homalg modules",
[ IsGradedModuleRep, IsGradedModuleRep ],
function( M, N )
return Depth( UnderlyingModule( M ), UnderlyingModule( N ) );
end );
##
InstallMethod( ResidueClassRing,
"for homalg ideals",
[ IsGradedSubmoduleRep and ConstructedAsAnIdeal ],
function( J )
local S, R, RR, result, A;
S := HomalgRing( J );
R := UnderlyingNonGradedRing( S );
Assert( 3, not J = S );
RR := ResidueClassRing( UnderlyingModule( J ) );
## do not do this, use the given J
#J := GradedModule( DefiningIdeal( RR ), S );
result := GradedRing( RR );
if HasContainsAField( S ) and ContainsAField( S ) then
SetContainsAField( result, true );
if HasCoefficientsRing( S ) then
SetCoefficientsRing( result, CoefficientsRing( S ) );
fi;
fi;
SetDefiningIdeal( result, J );
if HasAmbientRing( S ) then
A := AmbientRing( S );
elif HasAmbientRing( R ) then
A := GradedRing( AmbientRing( R ) );
else
A := S;
fi;
SetAmbientRing( result, A );
SetRingRelations( result, A * RingRelations( RR ) );
return result;
end );
##
InstallMethod( FullSubobject,
"for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local subobject;
if HasIsFree( UnderlyingModule( M ) ) and IsFree( UnderlyingModule( M ) ) then
subobject := ImageSubobject( TheIdentityMorphism( M ) );
else
subobject := ImageSubobject( GradedMap( FullSubobject( UnderlyingModule( M ) )!.map_having_subobject_as_its_image, "create", M ) );
fi;
SetEmbeddingInSuperObject( subobject, TheIdentityMorphism( M ) );
return subobject;
end );
##
InstallMethod( ZeroSubobject,
"for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local alpha;
alpha := ZeroSubobject( UnderlyingModule( M ) )!.map_having_subobject_as_its_image;
return UnderlyingSubobject( ImageObject( GradedMap( alpha, "create", M ) ) );
end );
##
InstallMethod( ZerothRegularity,
"for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local B, r_min, r_max, c, last_column, reg, i, j;
B := BettiTable( Resolution( M ) );
r_min := HomalgElementToInteger( RowDegreesOfBettiTable( B )[ 1 ] );
r_max := HomalgElementToInteger( RowDegreesOfBettiTable( B )[ Length( RowDegreesOfBettiTable( B ) ) ] );
c := Length( ColumnDegreesOfBettiTable( B ) );
last_column := List( MatrixOfDiagram( B ), function( a ) return a[c]; end );
reg := r_min;
for i in [ r_min + 1 .. r_max ] do
j := i - r_min + 1;
if not IsZero( last_column[j] ) then
reg := i;
fi;
od;
return reg;
end );
##
InstallMethod( TrivialArtinianSubmodule,
"for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
local S, k;
S := HomalgRing( M );
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
k := ResidueClassRingAsGradedLeftModule( S );
else
k := ResidueClassRingAsGradedRightModule( S );
fi;
return IsZero( GradedHom( k, M ) );
end );
##
InstallMethod( CoefficientsOfUnreducedNumeratorOfHilbertPoincareSeries,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
local R, weights, degrees;
R := HomalgRing( M );
weights := WeightsOfIndeterminates( R );
weights := List( weights, HomalgElementToInteger );
degrees := DegreesOfGenerators( M );
degrees := List( degrees, HomalgElementToInteger );
return CoefficientsOfUnreducedNumeratorOfHilbertPoincareSeries( UnderlyingModule( M ), weights, degrees );
end );
##
InstallMethod( CoefficientsOfNumeratorOfHilbertPoincareSeries,
"for a homalg graded module",
[ IsGradedModuleRep ],
CoefficientsOfNumeratorOfHilbertPoincareSeries_ViaBettiTableOfMinimalFreeResolution );
##
InstallMethod( CoefficientsOfNumeratorOfHilbertPoincareSeries,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
local R, weights, degrees, coeffs;
R := HomalgRing( M );
weights := List( WeightsOfIndeterminates( R ), HomalgElementToInteger );
degrees := List( DegreesOfGenerators( M ), HomalgElementToInteger );
coeffs := CoefficientsOfNumeratorOfHilbertPoincareSeries( UnderlyingModule( M ), weights, degrees );
if coeffs = fail then
TryNextMethod( );
fi;
return coeffs;
end );
##
InstallMethod( UnreducedNumeratorOfHilbertPoincareSeries,
"for a homalg graded module and a ring element",
[ IsGradedModuleRep, IsRingElement ],
function( M, lambda )
local R, weights, degrees;
R := HomalgRing( M );
weights := WeightsOfIndeterminates( R );
weights := List( weights, HomalgElementToInteger );
degrees := DegreesOfGenerators( M );
degrees := List( degrees, HomalgElementToInteger );
return UnreducedNumeratorOfHilbertPoincareSeries( UnderlyingModule( M ), weights, degrees, lambda );
end );
##
InstallMethod( UnreducedNumeratorOfHilbertPoincareSeries,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
return UnreducedNumeratorOfHilbertPoincareSeries( M, VariableForHilbertPoincareSeries( ) );
end );
##
InstallMethod( NumeratorOfHilbertPoincareSeries,
"for a homalg graded module and a ring element",
[ IsGradedModuleRep, IsRingElement ],
function( M, lambda )
local R, weights, degrees;
R := HomalgRing( M );
weights := List( WeightsOfIndeterminates( R ), HomalgElementToInteger );
degrees := List( DegreesOfGenerators( M ), HomalgElementToInteger );
return NumeratorOfHilbertPoincareSeries( UnderlyingModule( M ), weights, degrees, lambda );
end );
##
InstallMethod( NumeratorOfHilbertPoincareSeries,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
return NumeratorOfHilbertPoincareSeries( M, VariableForHilbertPoincareSeries( ) );
end );
##
InstallMethod( HilbertPoincareSeries,
"for a homalg graded module",
[ IsGradedModuleRep, IsRingElement ],
HilbertPoincareSeries_ViaBettiTableOfMinimalFreeResolution );
##
InstallMethod( HilbertPoincareSeries,
"for a homalg graded module",
[ IsGradedModuleRep, IsRingElement ],
function( M, lambda )
local R, weights, degrees, series;
R := HomalgRing( M );
weights := List( WeightsOfIndeterminates( R ), HomalgElementToInteger );
degrees := List( DegreesOfGenerators( M ), HomalgElementToInteger );
series := HilbertPoincareSeries( UnderlyingModule( M ), weights, degrees, lambda );
if series = fail then
TryNextMethod( );
fi;
return series;
end );
##
InstallMethod( HilbertPoincareSeries,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
return HilbertPoincareSeries( M, VariableForHilbertPoincareSeries( ) );
end );
##
InstallMethod( HilbertPoincareSeries,
"for a Betti diagram, an integer, and a ring element",
[ IsBettiTable, IsInt, IsRingElement ],
function( betti, n, s )
local row_range, col_range, r, hilb;
row_range := RowDegreesOfBettiTable( betti );
col_range := ColumnDegreesOfBettiTable( betti );
r := Length( row_range );
betti := MatrixOfDiagram( betti );
hilb := 1 / ( 1 - s )^n *
Sum( col_range, i ->
(-1)^i *
Sum( [ 1 .. r ], k ->
betti[k][i + 1] * s^(i + row_range[k])
)
);
return hilb;
end );
##
InstallMethod( HilbertPoincareSeries,
[ IsBettiTable, IsHomalgElement, IsRingElement ],
function( betti, n, s )
return HilbertPoincareSeries( betti, HomalgElementToInteger( n ), s );
end );
##
InstallMethod( HilbertPoincareSeries,
"for a Betti diagram and an integer",
[ IsBettiTable, IsInt ],
function( betti, n )
local s;
s := VariableForHilbertPoincareSeries( );
return HilbertPoincareSeries( betti, n, s );
end );
##
InstallMethod( HilbertPoincareSeries,
[ IsBettiTable, IsHomalgElement ],
function( betti, n )
return HilbertPoincareSeries( betti, HomalgElementToInteger( n ) );
end );
##
InstallMethod( HilbertPolynomial,
"for a homalg graded module",
[ IsGradedModuleRep, IsRingElement ],
HilbertPolynomial_ViaBettiTableOfMinimalFreeResolution );
##
InstallMethod( HilbertPolynomial,
"for a homalg graded module",
[ IsGradedModuleRep, IsRingElement ],
function( M, lambda )
local R, weights, degrees, hilb;
R := HomalgRing( M );
weights := List( WeightsOfIndeterminates( R ), HomalgElementToInteger );
degrees := List( DegreesOfGenerators( M ), HomalgElementToInteger );
hilb := HilbertPolynomial( UnderlyingModule( M ), weights, degrees, lambda );
if hilb = fail then
TryNextMethod( );
fi;
return hilb;
end );
##
InstallMethod( HilbertPolynomial,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
return HilbertPolynomial( M, VariableForHilbertPolynomial( ) );
end );
##
InstallMethod( HilbertPolynomial,
"for a Betti diagram, an integer, and a ring element",
[ IsBettiTable, IsInt, IsRingElement ],
function( betti, n, s )
local series;
series := HilbertPoincareSeries( betti, n, s );
return HilbertPolynomialOfHilbertPoincareSeries( series );
end );
##
InstallMethod( HilbertPolynomial,
"for a Betti diagram and an integer",
[ IsBettiTable, IsInt ],
function( betti, n )
local t;
t := VariableForHilbertPolynomial( );
return HilbertPolynomial( betti, n, t );
end );
##
InstallMethod( HilbertPolynomial,
[ IsBettiTable, IsHomalgElement, IsRingElement ],
function( betti, n, s )
return HilbertPolynomial( betti, HomalgElementToInteger( n ), s );
end );
##
InstallMethod( HilbertPolynomial,
[ IsBettiTable, IsHomalgElement ],
function( betti, n )
return HilbertPolynomial( betti, HomalgElementToInteger( n ) );
end );
## for CASs which do not support Hilbert* for non-graded modules
InstallMethod( AffineDimension,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
local R, weights, degrees;
R := HomalgRing( M );
weights := List( WeightsOfIndeterminates( R ), HomalgElementToInteger );
degrees := List( DegreesOfGenerators( M ), HomalgElementToInteger );
return AffineDimension( UnderlyingModule( M ), weights, degrees );
end );
##
InstallMethod( AffineDegree,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
local R, weights, degrees;
R := HomalgRing( M );
weights := List( WeightsOfIndeterminates( R ), HomalgElementToInteger );
degrees := List( DegreesOfGenerators( M ), HomalgElementToInteger );
return AffineDegree( UnderlyingModule( M ), weights, degrees );
end );
##
InstallMethod( ProjectiveDegree,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
local R, weights, degrees;
R := HomalgRing( M );
weights := List( WeightsOfIndeterminates( R ), HomalgElementToInteger );
degrees := List( DegreesOfGenerators( M ), HomalgElementToInteger );
return ProjectiveDegree( UnderlyingModule( M ), weights, degrees );
end );
##
InstallMethod( ConstantTermOfHilbertPolynomial,
"for a homalg graded module",
[ IsGradedModuleRep ],
function( M )
local R, weights, degrees;
R := HomalgRing( M );
weights := List( WeightsOfIndeterminates( R ), HomalgElementToInteger );
degrees := List( DegreesOfGenerators( M ), HomalgElementToInteger );
return ConstantTermOfHilbertPolynomial( UnderlyingModule( M ), weights, degrees );
end );
##
InstallGlobalFunction( HilbertPoincareSeries_ViaBettiTableOfMinimalFreeResolution,
function( arg )
local M, s, betti, n;
if Length( arg ) > 0 then
M := arg[1];
else
Error( "empty arguments\n" );
fi;
if Length( arg ) > 1 and IsRingElement( arg[2] ) then
s := arg[2];
else
s := VariableForHilbertPoincareSeries( );
fi;
if IsZero( M ) then
return 0 * s;
fi;
betti := BettiTable( Resolution( M ) );
n := Length( IndeterminatesOfPolynomialRing( HomalgRing( M ) ) );
return HilbertPoincareSeries( betti, n, s );
end );
##
InstallGlobalFunction( CoefficientsOfNumeratorOfHilbertPoincareSeries_ViaBettiTableOfMinimalFreeResolution,
function( M )
local series;
series := HilbertPoincareSeries_ViaBettiTableOfMinimalFreeResolution( M );
return CoefficientsOfNumeratorOfHilbertPoincareSeries( series );
end );
##
InstallGlobalFunction( HilbertPolynomial_ViaBettiTableOfMinimalFreeResolution,
function( arg )
local series;
series := CallFuncList( HilbertPoincareSeries_ViaBettiTableOfMinimalFreeResolution, arg );
return HilbertPolynomialOfHilbertPoincareSeries( series );
end );
##
InstallMethod( PrimaryDecomposition,
"for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
return
List( PrimaryDecomposition( UnderlyingModule( M ) ),
function( pp )
local primary, prime;
##FIXME: fix the degrees
primary := ImageSubobject( GradedMap( pp[1]!.map_having_subobject_as_its_image, "create", "create", HomalgRing( M ) ) );
prime := ImageSubobject( GradedMap( pp[2]!.map_having_subobject_as_its_image, "create", "create", HomalgRing( M ) ) );
return [ primary, prime ];
end
);
end );
##
InstallMethod( RadicalDecomposition,
"for homalg graded modules",
[ IsGradedModuleRep ],
function( M )
return
List( RadicalDecomposition( UnderlyingModule( M ) ),
function( pp )
##FIXME: fix the degrees
return ImageSubobject( GradedMap( pp!.map_having_subobject_as_its_image, "create", "create", HomalgRing( M ) ) );
end
);
end );
##
InstallMethod( ModuleOfKaehlerDifferentials,
"for homalg rings",
[ IsHomalgRing and HasRingRelations ],
function( R )
local A, var, I, jac;
A := AmbientRing( R );
if not ( HasIsFreePolynomialRing( A ) and IsFreePolynomialRing( A ) ) then
TryNextMethod( );
fi;
var := Indeterminates( A );
var := HomalgMatrix( var, 1, Length( var ), A );
I := MatrixOfRelations( R );
jac := R * Diff( var, I );
return LeftPresentation( jac );
end );
##
InstallMethod( ModuleOfKaehlerDifferentials,
"for homalg rings",
[ IsHomalgGradedRingRep and HasRingRelations ],
function( S )
local R, K;
R := UnderlyingNonGradedRing( S );
K := ModuleOfKaehlerDifferentials( R );
return GradedModule( K, S );
end );
##
InstallMethod( SymmetricAlgebra,
"for a homalg matrix",
[ IsHomalgMatrixOverGradedRingRep, IsList ],
function( M, gvar )
local n, R, Sym, weights, rel;
n := NrColumns( 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;
R := HomalgRing( M );
Sym := R * gvar;
weights := Concatenation(
ListWithIdenticalEntries( Length( Indeterminates( R ) ), 0 ),
ListWithIdenticalEntries( Length( gvar ), 1 ) );
SetWeightsOfIndeterminates( Sym, weights );
gvar := RelativeIndeterminatesOfPolynomialRing( Sym );
gvar := HomalgMatrix( gvar, Length( gvar ), 1, Sym );
rel := GradedLeftSubmodule( ( Sym * M ) * gvar );
Sym := Sym / rel;
SetDefiningIdeal( Sym, rel );
return Sym;
end );
##
InstallMethod( ExteriorAlgebra,
"for a homalg matrix",
[ IsHomalgMatrixOverGradedRingRep, IsList ],
function( M, gvar )
local n, R, S, weights, A, rel;
n := NrColumns( 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;
R := HomalgRing( M );
S := R * List( gvar, v -> Concatenation( "XX", v ) );
weights := Concatenation(
ListWithIdenticalEntries( Length( Indeterminates( R ) ), 0 ),
ListWithIdenticalEntries( Length( gvar ), -1 ) );
SetWeightsOfIndeterminates( S, weights );
A := KoszulDualRing( S, gvar );
gvar := IndeterminateAntiCommutingVariablesOfExteriorRing( A );
gvar := HomalgMatrix( gvar, Length( gvar ), 1, A );
rel := GradedLeftSubmodule( ( A * M ) * gvar );
A := A / rel;
SetDefiningIdeal( A, rel );
return A;
end );
##
InstallMethod( SymmetricPower,
"for free modules",
[ IsInt, IsGradedModuleRep and IsFree ],
function( k, M )
local R, r, degrees, l, P, powers;
if HasSymmetricPowers( M ) then
powers := SymmetricPowers( M );
else
powers := rec( );
fi;
if IsBound( powers!.( k ) ) then
return powers!.( k );
fi;
R := HomalgRing( M );
r := Rank( M );
degrees := DegreesOfGenerators( M );
l := Length( degrees );
if k in [ 0 .. l ] then
degrees := List( UnorderedTuples( [ 1 .. l ], k ),
i -> Sum( degrees{i} ) );
else
degrees := [ ];
fi;
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
P := FreeLeftModuleWithDegrees( R, degrees );
else
P := FreeRightModuleWithDegrees( R, degrees );
fi;
SetIsSymmetricPower( P, true );
SetSymmetricPowerExponent( P, k );
SetSymmetricPowerBaseModule( P, M );
powers!.( k ) := P;
SetSymmetricPowers( M, powers );
return P;
end );
##
InstallMethod( SymmetricPower,
"for graded modules",
[ IsInt, IsGradedModuleRep ],
function( k, M )
local phi, T;
if k = 0 then
return One( M );
elif k = 1 then
return M;
elif not k in [ 2 .. NrGenerators( M ) ] then
return Zero( M );
fi;
phi := PresentationMorphism( M );
T := SymmetricPower( k, Range( phi ) );
phi := SymmetricPowerOfPresentationMorphism( k, phi );
phi := GradedMap( phi, "free", T );
return Cokernel( phi );
end );
##
InstallMethod( ExteriorPower,
"for free modules",
[ IsInt, IsGradedModuleRep and IsFree ],
function( k, M )
local R, r, degrees, l, P, powers;
if HasExteriorPowers( M ) then
powers := ExteriorPowers( M );
else
powers := rec( );
fi;
if IsBound( powers!.( k ) ) then
return powers!.( k );
fi;
R := HomalgRing( M );
r := Rank( M );
degrees := DegreesOfGenerators( M );
l := Length( degrees );
if k in [ 0 .. l ] then
degrees := List( Combinations( [ 1 .. l ], k ),
i -> Sum( degrees{i} ) );
else
degrees := [ ];
fi;
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
P := FreeLeftModuleWithDegrees( R, degrees );
else
P := FreeRightModuleWithDegrees( R, degrees );
fi;
SetIsExteriorPower( P, true );
SetExteriorPowerExponent( P, k );
SetExteriorPowerBaseModule( P, M );
powers!.( k ) := P;
SetExteriorPowers( M, powers );
return P;
end );
##
InstallMethod( ExteriorPower,
"for a graded map",
[ IsInt, IsMapOfGradedModulesRep ],
function( k, phi )
local S, T, mat;
S := Source( phi );
T := Range( phi );
mat := MatrixOfMap( phi );
S := ExteriorPower( k, S );
T := ExteriorPower( k, T );
mat := ExteriorPower( k, mat );
return GradedMap( mat, S, T );
end );
##
InstallMethod( ExteriorPower,
"for graded modules",
[ IsInt, IsGradedModuleRep ],
function( k, M )
local phi, T;
if k = 0 then
return One( M );
elif k = 1 then
return M;
elif not k in [ 2 .. NrGenerators( M ) ] then
return Zero( M );
fi;
phi := PresentationMorphism( M );
T := ExteriorPower( k, Range( phi ) );
phi := ExteriorPowerOfPresentationMorphism( k, phi );
phi := GradedMap( phi, "free", T );
return Cokernel( phi );
end );
##
InstallMethod( GradedTorsionFreeFactor,
"for graded modules",
[ IsGradedModuleRep ],
function( M )
local S, m, k, N, pi;
S := HomalgRing( M );
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
m := MaximalGradedLeftIdeal( S );
else
m := MaximalGradedRightIdeal( S );
fi;
k := FactorObject( m );
N := GradedHom( k, M );
if IsZero( N ) then
return M;
fi;
pi := CokernelEpi( EmbeddingInSuperObject( m ) );
while not IsZero( N ) do
M := Cokernel( GradedHom( S, GradedHom( pi, M ) ) );
N := GradedHom( k, M );
od;
return M;
end );
##
InstallMethod( SaturateToDegreeZero,
"for graded modules",
[ IsGradedModuleRep ],
function( M )
local S, m, iota, phi;
S := HomalgRing( M );
if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
m := MaximalGradedLeftIdeal( S );
else
m := MaximalGradedRightIdeal( S );
fi;
M := GradedTorsionFreeFactor( M );
iota := EmbeddingInSuperObject( m );
while LinearRegularity( M ) >= 0 do
phi := GradedHom( S, GradedHom( iota, M ) );
M := Range( phi );
od;
return M;
end );