GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
## LIMOD.gi LIMOD subpackage Mohamed Barakat
##
## LIMOD = Logical Implications for homalg MODules
##
## Copyright 2007-2008 Lehrstuhl B für Mathematik, RWTH Aachen
##
## Implementation stuff for the LIMOD subpackage.
##
#############################################################################
####################################
#
# 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_MODULES.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 NrColumns( m ) - NrRows( m );
fi;
else
if HasIsRightRegular( m ) and IsRightRegular( m ) then
return NrRows( m ) - NrColumns( 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_MODULES.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 := NrRows( img ) <= 1;
else
img := BasisOfColumns( img );
free := NrColumns( 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 NrColumns( m ) - NrRows( m );
fi;
else
if IsRightRegular( m ) then
return NrRows( m ) - NrColumns( 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
ResetFilterObj( M, AFiniteFreeResolution );
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( HilbertPolynomial,
"for a homalg module",
[ IsHomalgModule ],
function( M )
return HilbertPolynomial( M, VariableForHilbertPolynomial( ) );
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;
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 := 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;
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 := 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;
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 );