####################################################################### ## #F Cat( <identity>, <properties> ) ## ## Constructs a category object from two pieces of data: ## -- <identity>, a list with information identifying the category, ## f.ex. a name and some object the cat is constructed from. ## -- <properties>, a record with the following entries: ## name (will be used for printing a categeory), zeroObj (the zero ## object of the cat), isZeroObj (a test function), zeroMap (an ## operation on two objects of the cat), isZeroMapping (a test ## function), composeMaps (an operation on two maps of the cat), ## ker (an operation on the maps of the cat), im (an operation on ## the maps of the cat), isExact (an operation on two maps of the ## cat) and objStr (a function printing the objects of the cat). ##
InstallGlobalFunction( Cat, function( identity, properties )
return Objectify( NewType( NewFamily( "CatFamily", IsCat ),
IsCat and IsCatDefaultRep ),
rec( identity := identity,
properties := properties ) ); end );
####################################################################### ## #M \.( <cat>, <propName> ) ## ## Method for retrieving properties from a category, where <propName> ## is one of the properties listed in the Cat() documentation above. ##
InstallMethod( \.,
[ IsCat, IsPosInt ], function( cat, propName )
return cat!.properties.( NameRNam( propName ) ); end );
####################################################################### ## #M \=( <cat1>, <cat2> ) ## ## Equality test for two categories. Two categories are equal if ## and only if their identity are the same. ##
InstallMethod( \=,
[ IsCat, IsCat ], function( cat1, cat2 )
return cat1!.identity = cat2!.identity; end );
####################################################################### ## #M PrintObj( <cat> ) ## ## Printing a category, using its name. ##
InstallMethod( PrintObj,
[ IsCat ], function( cat )
Print( "<cat: ", cat.name, ">" ); end );
####################################################################### ## #M ViewObj( <cat> ) ## ## Viewing a cateory, adding no more information than the PrintObj. ##
InstallMethod( ViewObj,
[ IsCat ], function( cat )
Print( cat ); end );
####################################################################### ## #M CatOfRightAlgebraModules( <A> ) ## ## Returns the category of right modules over some (quotient of a) ## path algebra <A>. ##
InstallMethod( CatOfRightAlgebraModules,
[ IsAlgebra ], function( A )
local isZeroObj, composeMaps, isExact, objStr;
isZeroObj := function( M )
return Dimension( M ) = 0; end;
composeMaps := function( g, f )
return f * g; end;
isExact := function( g, f )
return Dimension( Kernel( g ) ) = Dimension( Image( f ) ); end;
objStr := function( M )
local dims;
dims := JoinStringsWithSeparator( DimensionVector( M ), "," );
return Concatenation( "(", dims, ")" ); end;
return Cat( [ "right modules", A ],
rec( name := "right modules over algebra",
zeroObj := ZeroModule( A ),
isZeroObj := isZeroObj,
zeroMap := ZeroMapping,
isZeroMapping := IsZero,
composeMaps := composeMaps,
ker := Kernel,
im := Image,
isExact := isExact,
objStr := objStr ) ); end );
####################################################################### ## #F FiniteComplex( <cat>, <basePosition>, <differentials> ) ## ## This function returns a finite complex with objects in <cat>. The ## differentials are given in the list <differentials> = [d1, ..., dN], ## an <basePosition> is some integer i. The returned complex has the ## map d1 from degree (i) to degree (i-1). ##
InstallGlobalFunction( FiniteComplex, function( cat, basePosition, differentials )
return Complex( cat, basePosition, differentials, "zero", "zero" ); end );
####################################################################### ## #F ZeroComplex( <cat> ) ## ## Returns the complex in which all objects are the zero object in ## <cat>. ##
InstallGlobalFunction( ZeroComplex, function( cat )
local fam, C;
fam := NewFamily( "ComplexesFamily", IsQPAComplex );
fam!.cat := cat;
C := Objectify( NewType( fam, IsZeroComplex and IsQPAComplexDefaultRep ),
rec( ) );
SetCatOfComplex( C, cat );
SetDifferentialsOfComplex( C, ConstantInfList( cat.zeroMap( cat.zeroObj, cat.zeroObj ) ) );
return C; end );
####################################################################### ## #F StalkComplex( <cat>, <obj>, <degree> ) ## ## Returns the stalk complex with the object <obj> from <cat> in ## degree <degree>. ##
InstallGlobalFunction( StalkComplex, function( cat, obj, degree )
return FiniteComplex( cat, degree,
[ cat.zeroMap( obj, cat.zeroObj ), cat.zeroMap( cat.zeroObj, obj ) ] ); end );
####################################################################### ## #F ShortExactSequence( <cat>, <f>, <g> ) ## ## Returns a complex with three non-zero consecutive objects, and zero ## objects elsewhere, such that the complex is exact: The image of <f> ## should be the kernel of <g>, and <f> should be injective, and <g> ## should be surjective. The function checks that this is the case, ## and returns an error otherwise. ##
InstallGlobalFunction( ShortExactSequence, function( cat, f, g )
local SES;
SES := FiniteComplex( cat, 0, [ g, f ] ); if not IsShortExactSequence( SES ) then
Error( "not exact\n" ); fi;
return SES; end );
####################################################################### ## #F Complex( <cat>, <basePosition>, <middle>, <positive>, <negative> ) ## ## Constructs a complex, not necessarily finite, from the given data. ## See the QPA manual for detailed information on the input data. ##
InstallGlobalFunction( Complex, function( cat, basePosition, middle, positive, negative )
local checkDifferentials, checkDifferentialList, checkDifferentialListWithRepeat,
positiveRepeat, negativeRepeat,
fam, C, basePositionL, middleL, positiveL, negativeL,
firstMiddleObj, lastMiddleObj, checkNewDifferential,
firstMap, next, secondMap;
# check that all consecutive differentials compose to zero
checkDifferentials := function( topDegree, indices, lists, listNames )
local degrees, diffs, diffNames;
degrees := [ topDegree, topDegree - 1 ];
diffs := List( [1,2], i -> lists[ i ][ indices[ i ] ] );
diffNames := List( [1,2], i -> Concatenation( "differential ", String( degrees[ i ] ), " (element ", String( indices[ i ] ), " in ", String( listNames[ i ] ), " list)" ) ); if Range( diffs[ 1 ] ) <> Source( diffs[ 2 ] ) then
Error( "range of ", diffNames[ 1 ], " is not the same as source of ",
diffNames[ 2 ], ".\n" ); fi; if not cat.isZeroMapping( cat.composeMaps( diffs[ 2 ], diffs[ 1 ] ) ) then
Error( "non-zero composition of ", diffNames[ 2 ], " and ", diffNames[ 1 ], ".\n" ); fi; end;
checkDifferentialList := function( list, startDegree, listName )
local i; for i in [ 2 .. Length( list ) ] do
checkDifferentials( startDegree + i - 1,
[ i, i - 1 ],
[ list, list ],
[ listName, listName ] );
od; end;
checkNewDifferential := function( i, dir, type )
local degrees, diffs; if dir = 1then
degrees := [ i - 1, i ]; else
degrees := [ i, i + 1 ]; fi;
diffs := [ DifferentialOfComplex( C, degrees[ 1 ] ),
DifferentialOfComplex( C, degrees[ 2 ] ) ]; if Source( diffs[ 1 ] ) <> Range( diffs[ 2 ] ) then
Error( "source of differential ", degrees[ 1 ], " is not the same as range of differential ",
degrees[ 2 ], " in complex\n ", C, "\n" ); fi; if not cat.isZeroMapping( cat.composeMaps( diffs[ 1 ], diffs[ 2 ] ) ) then
Error( "nonzero composition of differentials ", degrees[ 1 ], " and ", degrees[ 2 ], " in complex\n ", C, "\n" ); fi; end;
####################################################################### ## #M DifferentialOfComplex( <C>, <i> ) ## ## Returns the differential in degree <i> of the complex <C>. ##
InstallMethod( DifferentialOfComplex,
[ IsQPAComplex, IsInt ], function( C, i )
return DifferentialsOfComplex( C )^i; end );
####################################################################### ## #M ObjectOfComplex( <C>, <i> ) ## ## Returns the object in degree <i> of the complex <C>. ##
InstallMethod( ObjectOfComplex,
[ IsQPAComplex, IsInt ], function( C, i )
return Source( DifferentialOfComplex( C, i ) ); end );
####################################################################### ## #M \^( <C>, <i> ) ## ## Is this in use?? ##
InstallMethod( \^,
[ IsQPAComplex, IsInt ], function( C, i )
return DifferentialOfComplex( C, i ); end );
####################################################################### ## #M CyclesOfComplex( <C>, <i> ) ## ## For a complex <C> and an integer <i>. Returns the i-cycle of the ## complex, that is the subobject Ker(d_i) of the object in degree i. ##
InstallMethod( CyclesOfComplex,
[ IsQPAComplex, IsInt ], function( C, i )
return Kernel( DifferentialOfComplex( C, i ) ); end );
####################################################################### ## #M BoundariesOfComplex( <C>, <i> ) ## ## For a complex <C> and an integer <i>. Returns the i-boundary of the ## complex, that is the subobject Im(d_{i+1}) of the object in degree i. ##
InstallMethod( BoundariesOfComplex,
[ IsQPAComplex, IsInt ], function( C, i )
return Image( DifferentialOfComplex( C, i + 1 ) ); end );
####################################################################### ## #M HomologyOfComplex( <C>, <i> ) ## ## For a complex <C> and an integer <i>. Returns the ith homology of ## the complex. ## ## TODO: Does not currently work (see the documentation). ##
InstallMethod( HomologyOfComplex, # TODO: this does not work
[ IsQPAComplex, IsInt ], function( C, i )
return CyclesOfComplex( C, i ) / BoundariesOfComplex( C, i ); end );
####################################################################### ## #M IsFiniteComplex( <C> ) ## ## Returns true if the complex <C> is a finite complex, false otherwise. ##
InstallMethod( IsFiniteComplex,
[ IsQPAComplex ], function( C )
local upbound, lowbound;
upbound := UpperBound( C );
lowbound := LowerBound( C );
if IsZeroComplex( C ) then
return true; elif IsInt( upbound ) and IsInt( lowbound ) then
return true; elif ( upbound in [ -infinity, infinity ] ) or ( lowbound in [ -infinity, infinity ] ) then
return false; else
return fail; fi; end );
####################################################################### ## #M LengthOfComplex( <C> ) ## ## Returns the length of the complex <C>. If C is a zero complex, then ## the length is zero. If C is a finite complex, the length is the ## upper bound - the lower bound + 1. If C is an infinite complex, the ## length is infinity. ##
InstallMethod( LengthOfComplex,
[ IsQPAComplex ], function( C )
local finiteness;
finiteness := IsFiniteComplex( C ); if IsZeroComplex( C ) then
return 0; elif finiteness = true then
return UpperBound( C ) - LowerBound( C ) + 1; elif finiteness = false then
return infinity; else
return fail; fi; end );
####################################################################### ## #M HighestKnownDegree( <C> ) ## ## Returns the greatest integer i such that the object at position i ## is known (or computed). For a finite complex, this will be infinity. ##
InstallMethod( HighestKnownDegree,
[ IsQPAComplex ], function( C )
return HighestKnownPosition( DifferentialsOfComplex( C ) ); end );
####################################################################### ## #M LowestKnownDegree( <C> ) ## ## Returns the smallest integer i such that the object at position i ## is known (or computed). For a finite complex, this will be negative ## infinity. ##
InstallMethod( LowestKnownDegree,
[ IsQPAComplex ], function( C )
return LowestKnownPosition( DifferentialsOfComplex( C ) ); end );
####################################################################### ## #M IsExactSequence( <C> ) ## ## True if the complex <C> is exact in every degree. If the complex ## is not finite and not repeating, the function fails. ##
InstallMethod( IsExactSequence,
[ IsQPAComplex ], function( C )
return ForEveryDegree( C, CatOfComplex( C ).isExact ); end );
####################################################################### ## #M IsExactInDegree( <C>, <i> ) ## ## Returns true if the complex <C> is exact in degree <i>. ##
InstallMethod( IsExactInDegree,
[ IsQPAComplex, IsInt ], function( C, i )
return CatOfComplex( C ).isExact( DifferentialOfComplex( C, i ),
DifferentialOfComplex( C, i + 1 ) ); end );
####################################################################### ## #M IsShortExactSequence( <C> ) ## ## Returns true if the complex <C> is exact and has only three non-zero ## objects, which are consecutive. ##
InstallMethod( IsShortExactSequence,
[ IsQPAComplex ], function( C )
local length;
length := LengthOfComplex( C ); if length = fail then return fail; fi; if length = 3then
return IsExactSequence( C ); else
return false; fi; end );
####################################################################### ## #M ForEveryDegree( <C>, <func> ) ## ## <C> is a complex, and <func> is a function operating on two conse- ## cutive differentials, returning either true or false. ## ## Returns true if func(d_i, d_{i+1}) is true for all i. Fails if this ## is unknown, i.e. if the complex is infinite and not repeating. ##
InstallMethod( ForEveryDegree, # TODO: misleading name?
[ IsQPAComplex, IsFunction ], function( C, func )
local diffs, pos, neg, i;
diffs := DifferentialsOfComplex( C );
pos := PositivePart( diffs );
neg := NegativePart( diffs ); if not (IsRepeating( PositivePart( diffs ) ) and
IsRepeating( NegativePart( diffs ) ) ) then
return fail; fi; for i in [ StartPosition( neg ) - Length( RepeatingList( neg ) )
.. StartPosition( pos ) + Length( RepeatingList( pos ) ) ] do if not func( diffs^i, diffs^(i+1) ) then
return false; fi;
od;
return true; end );
####################################################################### ## #M UpperBound( <C> ) ## ## Returns: ## If it exists: The smallest integer i such that the object at ## position i is non-zero, but for all j > i the object at position j ## is zero. If C is not a finite complex, the operation will return ## fail or infinity, depending on how C was defined. ##
InstallMethod( UpperBound,
[ IsQPAComplex ], function( C )
local cat, diffs, positive, i;
cat := CatOfComplex( C );
diffs := DifferentialsOfComplex( C );
positive := PositivePart( diffs );
if IsZeroComplex( C ) then
return -infinity; elif IsRepeating( positive ) and Length( RepeatingList( positive ) ) = 1
and cat.isZeroObj( ObjectOfComplex( C, StartPosition( positive ) ) ) then
i := MiddleEnd( diffs ) - 1; whilecat.isZeroObj( ObjectOfComplex( C, i ) ) do
i := i - 1; if i < MiddleStart( diffs ) then
return fail; fi;
od;
return i; elif IsRepeating( positive ) then
return infinity; else
return fail; fi; end );
####################################################################### ## #M LowerBound( <C> ) ## ## Returns: ## If it exists: The greatest integer i such that the object at ## position i is non-zero, but for all j < i the object at position j ## is zero. If C is not a finite complex, the operation will return ## fail or negative infinity, depending on how C was defined. ##
InstallMethod( LowerBound,
[ IsQPAComplex ], function( C )
local cat, diffs, negative, i;
cat := CatOfComplex( C );
diffs := DifferentialsOfComplex( C );
negative := NegativePart( diffs );
if IsZeroComplex( C ) then
return infinity; elif IsRepeating( negative ) and Length( RepeatingList( negative ) ) = 1
and cat.isZeroObj( ObjectOfComplex( C, StartPosition( negative ) ) ) then
i := MiddleStart( diffs ); whilecat.isZeroObj( ObjectOfComplex( C, i ) ) do
i := i + 1; if i > MiddleEnd( diffs ) then
return fail; fi;
od;
return i; elif IsRepeating( negative ) then
return -infinity; else
return fail; fi; end );
####################################################################### ## #M IsPositiveRepeating( <C> ) ## ## Returns true if the positive part of the differential list of the ## complex <C> is repeating. ##
InstallMethod( IsPositiveRepeating,
[ IsQPAComplex ], function( C )
return IsRepeating( PositivePart( DifferentialsOfComplex( C ) ) ); end );
####################################################################### ## #M IsNegativeRepeating( <C> ) ## ## Returns true if the negative part of the differential list of the ## complex <C> is repeating. ##
InstallMethod( IsNegativeRepeating,
[ IsQPAComplex ], function( C )
return IsRepeating( NegativePart( DifferentialsOfComplex( C ) ) ); end );
####################################################################### ## #M PositiveRepeatDegrees( <C> ) ## ## Returns a list describing the positions of the positive repeating ## differentials. The returned list is of the form [first .. last], ## where 'first' is the smallest degree such that the differential ## ending there is in the positive repeating part. After the degree ## 'last', the same differentials start repeating. Fails if ## IsPositiveRepeating(C) is false. ##
InstallMethod( PositiveRepeatDegrees,
[ IsQPAComplex ], function( C )
local positive, first, last;
positive := PositivePart( DifferentialsOfComplex( C ) ); if not IsRepeating( positive ) then
return fail; fi;
first := StartPosition( positive );
last := first + Length( RepeatingList( positive ) ) - 1;
return [ first .. last ]; end );
####################################################################### ## #M NegativeRepeatDegrees( <C> ) ## ## Returns a list describing the positions of the negative repeating ## differentials. The returned list is of the form [last .. first], ## where 'last' is the greatest degree such that the differential ## starting there is in the negative repeating part. After the degree ## 'first', the same differentials start repeating. Fails if ## IsNegativeRepeating(C) is false. ##
InstallMethod( NegativeRepeatDegrees,
[ IsQPAComplex ], function( C )
local negative, first, last;
negative := NegativePart( DifferentialsOfComplex( C ) ); if not IsRepeating( negative ) then
return fail; fi;
first := StartPosition( negative );
last := first - Length( RepeatingList( negative ) ) + 1;
return [ last .. first ]; end );
####################################################################### ## #M Shift( <C>, <i> ) ## ## Returns the complex C[i]. Note that the signs of the differentials ## change if i is odd. ##
InstallMethod( Shift,
[ IsQPAComplex, IsInt ], function( C, shift )
local newDifferentials;
newDifferentials := Shift( DifferentialsOfComplex( C ), shift ); if shift mod 2 = 1then
newDifferentials := InfList( newDifferentials, d -> -d ); fi;
return ComplexByDifferentialList( CatOfComplex( C ), newDifferentials );
end );
####################################################################### ## #M ShiftUnsigned( <C>, <i> ) ## ## Returns a complex with the same objects as C[i], but with the ## differentials of C shifted without changing the signs. A 'non- ## algebraic' operation, but useful for manipulating complexes. ##
InstallMethod( ShiftUnsigned,
[ IsQPAComplex, IsInt ], function( C, shift )
local newDifferentials;
newDifferentials := Shift( DifferentialsOfComplex( C ), shift );
return ComplexByDifferentialList( CatOfComplex( C ), newDifferentials );
end );
####################################################################### ## #M YonedaProduct( <C1>, <C2> ) ## ## <C1> and <C2> are complexes such that the object in degree LowerBound(C) ## equals the object in degree UpperBound(D). The returned complex ## is the Yoneda product of <C1> and <C2> (see the QPA documentation ## for a more precise definition). ##
InstallMethod( YonedaProduct,
[ IsQPAComplex, IsQPAComplex ], function( C1, C2 )
local cat, lowbound1, upbound2, diff1, diff2, connection, diffs;
if not IsInt( lowbound1 ) then
Error( "first argument in Yoneda product must be bounded below" ); fi; if not IsInt( upbound2 ) then
Error( "second argument in Yoneda product must be bounded above" ); fi; if ObjectOfComplex( C1, lowbound1 ) <> ObjectOfComplex( C2, upbound2 ) then
Error( "non-compatible complexes for Yoneda product" ); fi;
####################################################################### ## #M GoodTruncationBelow( <C>, <i> ) ## ## Not working at the moment. Suppose that C is a complex ## ... --> C_{i+1} --> C_i --> C_{i-1} --> ... ## ## then the function should return the complex ## ... --> C_{i+1} --> Z_i --> 0 --> 0 --> ... ## ## where Z_i is the i-cycle of C. ##
InstallMethod( GoodTruncationBelow,
[ IsQPAComplex, IsInt ], function( C, i )
local cat, difflist, truncpart, newpart, zeropart, newdifflist, kerinc;
####################################################################### ## #M GoodTruncationAbove( <C>, <i> ) ## ## Not working at the moment. Suppose that C is a complex ## ... --> C_{i+1} --> C_i --> C_{i-1} --> ... ## ## then the function should return the complex ## ... --> 0 --> C_i/Z_i --> C_{i-1} --> 0 --> ... ## ## where Z_i is the i-cycle of C. ##
InstallMethod( GoodTruncationAbove,
[ IsQPAComplex, IsInt ], function( C, i )
local cat, difflist, truncpart, newpart, zeropart, newdifflist, factor, factorinclusion,
kerinc, factorproj;
####################################################################### ## #O CutComplexAbove( <C> ) ## ## For a bounded below complex C which is stored as an infinite complex, ## but is known to be finite. Returns the same complex, but represented ## as a finite complex. ##
InstallMethod( CutComplexAbove,
[ IsQPAComplex ], function( C )
local i, obj; if (IsInt(UpperBound(C))) then
return C; else
i := LowerBound(C); while true do
obj := ObjectOfComplex(C, i); if (IsZero(DimensionVector(obj))) then
return BrutalTruncationAbove(C, i-1); fi;
i := i+1;
od; fi;
end );
####################################################################### ## #O CutComplexBelow( <C> ) ## ## For a bounded above complex C which is stored as an infinite complex, ## but is known to be finite. Returns the same complex, but represented ## as a finite complex. ##
InstallMethod( CutComplexBelow,
[ IsQPAComplex ], function( C )
local i, obj; if (IsInt(LowerBound(C))) then
return C; else
i := UpperBound(C); while true do
obj := ObjectOfComplex(C, i); if (IsZero(DimensionVector(obj))) then
return BrutalTruncationBelow(C, i+1); fi;
i := i-1;
od; fi;
end );
####################################################################### ## #O ComplexByDifferentialList( <cat>, <differentials> ) ## ## <cat> is a category, and <differentials> is an InfList of ## differentials. ##
InstallMethod( ComplexByDifferentialList,
[ IsCat, IsInfList ], function( cat, differentials )
local C, fam;
####################################################################### ## #O PrintObj( <C> ) ## ## Prints the zero complex ##
InstallMethod( PrintObj,
[ IsZeroComplex ], function( C )
Print( "0 -> 0" ); end );
####################################################################### ## #O PrintObj( <C> ) ## ## Prints a non-zero complex ##
InstallMethod( PrintObj,
[ IsQPAComplex ], function( C )
local cat, diffs, i, upbound, lowbound, top, bottom;
cat := CatOfComplex( C );
diffs := DifferentialsOfComplex( C );
upbound := UpperBound( C );
lowbound := LowerBound( C ); if IsInt( upbound ) then
top := MiddleEnd( diffs ) - 1; elif IsPositiveRepeating( C ) then
top := MiddleEnd( diffs ); else
top := HighestKnownDegree( C ); fi; if IsNegativeRepeating( C ) then
bottom := MiddleStart( diffs ); else
bottom := LowestKnownDegree( C ); fi;
if IsInt( upbound ) then
Print( "0 -> " ); else
Print( "--- -> " ); fi;
if IsPositiveRepeating( C ) and upbound = infinity then
Print( "[ " ); for i in Reversed( PositiveRepeatDegrees( C ) ) do
Print( i, ":", cat.objStr( ObjectOfComplex( C, i ) ), " -> " );
od;
Print( "] " ); fi;
if IsInt( top ) and IsInt( bottom ) then for i in [ top, top - 1 .. bottom ] do
Print( i, ":", cat.objStr( ObjectOfComplex( C, i ) ), " -> " );
od; fi;
if IsNegativeRepeating( C ) and lowbound = -infinity then
Print( "[ " ); for i in Reversed( NegativeRepeatDegrees( C ) ) do
Print( i, ":", cat.objStr( ObjectOfComplex( C, i ) ), " -> " );
od;
Print( "] " ); fi;
if IsInt( lowbound ) then
Print( "0" ); else
Print( "---" ); fi; end );
####################################################################### ## #O ProjectiveResolution( <M> ) ## ## Returns the projective resolution of M, including M in degree -1. ##
InstallMethod( ProjectiveResolution,
[ IsPathAlgebraMatModule ], function( M )
local nextDifferential, cover;
nextDifferential := function( d )
return ProjectiveCover( Kernel( d ) ) * KernelInclusion( d ); end;
cover := ProjectiveCover( M );
return Complex( CatOfRightAlgebraModules( ActingAlgebra( M ) ), 0,
[ cover ],
[ "next/repeat", nextDifferential, cover ], "zero" ); end );
####################################################################### ## #O InjectiveResolution( < M > ) ## ## Returns the minimal injective resolution of M, including M in degree -1. ##
InstallMethod( InjectiveResolution,
[ IsPathAlgebraMatModule ], function( M )
local nextDifferential, envelope;
nextDifferential := function( d )
return CoKernelProjection( d )*InjectiveEnvelope( CoKernel( d ) ); end;
envelope := InjectiveEnvelope( M );
return Complex( CatOfRightAlgebraModules( ActingAlgebra( M ) ), 0,
[ envelope ], "zero",
[ "next/repeat", nextDifferential, envelope ]
); end
);
####################################################################### ## #F ChainMap( <M>, <v> ) ## ## TODO: documentation for all chain map-functions ##
InstallMethod( ChainMap, "for complexes, int and lists",
[ IsQPAComplex, IsQPAComplex, IsInt, IsList, IsList, IsList ], function( source, range, basePosition, middle, positive, negative )
local cat, fam, map, positiveL, negativeL, numZeroMaps, i,
correctDomainAt, correctCodomainAt, commutesAt,
checkDomainAndCodomain, checkCommutes, checkNewMorphism,
morphisms, firstCheckDegree, lastCheckDegree;
cat := CatOfComplex( source ); ifcat <> CatOfComplex( range ) then
Error( "source and range of chain map must be complexes over the same cat" ); fi;
checkDomainAndCodomain := function( i ) if not correctDomainAt( i ) then
Error( "incorrect source of chain map morphism in degree ", i, "\n" ); fi; if not correctCodomainAt( i ) then
Error( "incorrect range of chain map morphism in degree ", i, "\n" ); fi; end;
checkCommutes := function( i ) if not commutesAt( i ) then
Error( "chain map morphisms at degrees (", i, ",", i-1, ") ", "do not commute with complex differentials\n" ); fi; end;
checkNewMorphism := function( i, dir, type )
local topDegreeOfNewSquare; if dir = 1then
topDegreeOfNewSquare := i; else
topDegreeOfNewSquare := i + 1; fi;
checkDomainAndCodomain( i );
checkCommutes( topDegreeOfNewSquare ); end;
# for i in [ LowestKnownDegree( map ) .. HighestKnownDegree( map ) ] do # checkDomainAndCodomain( i ); # od; # for i in [ LowestKnownDegree( map ) + 1 .. HighestKnownDegree( map ) ] do # checkCommutes( i ); # od;
# TODO: hvor mye som må sjekkes (må se på kompleksene) if IsRepeating( NegativePart( morphisms ) ) then
firstCheckDegree := StartPosition( NegativePart( morphisms ) )
- Length( RepeatingList( NegativePart( morphisms ) ) ); else
firstCheckDegree := MiddleStart( morphisms ); fi; if IsRepeating( PositivePart( morphisms ) ) then
lastCheckDegree := StartPosition( PositivePart( morphisms ) )
+ Length( RepeatingList( PositivePart( morphisms ) ) ); else
lastCheckDegree := MiddleEnd( morphisms ); fi; for i in [ firstCheckDegree .. lastCheckDegree ] do
checkDomainAndCodomain( i );
od; for i in [ firstCheckDegree + 1 .. lastCheckDegree ] do
checkCommutes( i );
od;
return map;
end );
####################################################################### ## #O HighestKnownDegree( <map> ) ## ## Returns the highest degree that has been computed (or is otherwise ## known) of the chain map <map>. ##
InstallMethod( HighestKnownDegree,
[ IsChainMap ], function( map )
return HighestKnownPosition( MorphismsOfChainMap( map ) ); end );
####################################################################### ## #O LowestKnownDegree( <map> ) ## ## Returns the lowest degree that has been computed (or is otherwise) ## known) of the chain map <map>. ##
InstallMethod( LowestKnownDegree,
[ IsChainMap ], function( map )
return LowestKnownPosition( MorphismsOfChainMap( map ) ); end );
####################################################################### ## #O MorphismOfChainMap( <map>, <i> ) ## ## Returns the morhpism in degree <i> of the map <map>. ##
InstallMethod( MorphismOfChainMap,
[ IsChainMap, IsInt ], function( map, i )
return MorphismsOfChainMap( map )^i; end );
####################################################################### ## #O \^( <map>, <i> ) ## ## Returns the morphism in degree <i> of the map <map>. ##
InstallMethod( \^,
[ IsChainMap, IsInt ], function( map, i )
return MorphismsOfChainMap( map )^i; end );
####################################################################### ## #O PrintObj( <map> ) ## ## Prints the chain map <map>. ##
InstallMethod( PrintObj,
[ IsChainMap ], function( map )
Print( "<chain map>" ); end );
####################################################################### ## #F ComplexAndChainMAps( <sourceComplexes>, <rangeComplexes>, ## <basePosition>, <middle>, <positive>, ## <negative> ) ## ## Returns a list consisting of a newly created complex, togeher with ## one or more newly created chain maps. The new complex is either ## source or range for the new chain map(s). ## ## <sourceComplexes> is a list of the complexes to be sources of the ## chain maps which will have the new complex as range. Similarly, ## <rangeComplexes> is a list of the complexes to be ranges of the new ## chain maps which will have the new complex as source. ##
InstallGlobalFunction( ComplexAndChainMaps, function( sourceComplexes, rangeComplexes,
basePosition, middle, positive, negative )
if positive = "zero"then
positiveDiffs := "zero";
positiveInMaps := List( [ 1 .. numInMaps ], i -> "zero" );
positiveOutMaps := List( [ 1 .. numOutMaps ], i -> "zero" ); else
positiveDiffs := [ "pos", function( C, i ) return \^(list, i)[ 1 ]; end ];
positiveInMaps :=
List( [ 1 .. numInMaps ],
i -> [ "pos", function( map, pos ) return \^(list, pos)[ 1 + i ]; end ] );
positiveOutMaps :=
List( [ 1 .. numOutMaps ],
i -> [ "pos", function( map, pos )
return \^(list, pos)[ 1 + numInMaps + i ]; end ] ); fi; if negative = "zero"then
negativeDiffs := "zero";
negativeInMaps := List( [ 1 .. numInMaps ], i -> "zero" );
negativeOutMaps := List( [ 1 .. numOutMaps ], i -> "zero" ); else
negativeDiffs := [ "pos", function( C, i ) return \^(list, i)[ 1 ]; end ];
negativeInMaps :=
List( [ 1 .. numInMaps ],
i -> [ "pos", function( map, pos ) return \^(list, pos)[ 1 + i ]; end ] );
negativeOutMaps :=
List( [ 1 .. numOutMaps ],
i -> [ "pos", function( map, pos )
return \^(list, pos)[ 1 + numInMaps + i ]; end ] ); fi;
middleDiffs := List( middle, L -> L[ 1 ] );
middleInMaps := List( [ 1 .. numInMaps ],
i -> List( middle, L -> L[ 1 + i ] ) );
middleOutMaps := List( [ 1 .. numOutMaps ],
i -> List( middle, L -> L[ 1 + numInMaps + i ] ) );
C := Complex( cat, basePosition, middleDiffs, positiveDiffs, negativeDiffs );
inMaps := List( [ 1 .. numInMaps ],
i -> ChainMap( sourceComplexes[ i ],
C,
basePosition,
middleInMaps[ i ],
positiveInMaps[ i ],
negativeInMaps[ i ] ) );
outMaps := List( [ 1 .. numOutMaps ],
i -> ChainMap( C,
rangeComplexes[ i ],
basePosition,
middleOutMaps[ i ],
positiveOutMaps[ i ],
negativeOutMaps[ i ] ) );
return Concatenation( [ C ], inMaps, outMaps );
end );
####################################################################### ## #F FiniteChainMap( <source>, <range>, <baseDegree>, <morphisms> ) ## ## This function returns a finite chain map between two finite ## complexes <source> and <range>. ##
InstallMethod( FiniteChainMap,
[ IsQPAComplex, IsQPAComplex, IsInt, IsList ], function( source, range, baseDegree, morphisms )
return ChainMap( source, range, baseDegree, morphisms, "zero", "zero" ); end );
####################################################################### ## #F ZeroChainMap( <source>, <range> ) ## ## This function returns the zero chain map between two ## complexes <source> and <range>. ##
InstallMethod( ZeroChainMap,
[ IsQPAComplex, IsQPAComplex ], function( source, range )
return ChainMap( source, range, 0, [], "zero", "zero" ); end );
####################################################################### ## #O ComparisonLifting( <f>, <PC>, <EC> ) ## ## <f> is a morphism between two modules M and N. <PC> is a complex ## with M in degree i, zero in degrees j < i and projective modules ## in degrees j > i. <EC> is an exact complex with N in degree i ## and zero in degrees j < i. The function returns a chain map from ## <PC> to <EC> which lifts the map <f> (it has <f> in degree i). ##
InstallMethod( ComparisonLifting,
[ IsPathAlgebraMatModuleHomomorphism, IsQPAComplex, IsQPAComplex ], function( f, PC, EC )
local lbound, surjection, middle, nextLifting, nextLiftingFunction, i, j, chainmap;
if ( LowerBound(PC) <> LowerBound(EC) ) then
Error("The complexes must have the same lower bound"); fi;
lbound := LowerBound(PC);
if (ObjectOfComplex(PC,lbound) <> Source( f ) or
ObjectOfComplex(EC,lbound) <> Range( f ) ) then
Error("The map has wrong source and/or range"); fi;
surjection := DifferentialOfComplex( PC , lbound + 1 )*f;
if IsInt( UpperBound( PC ) ) and IsInt( UpperBound ( EC )) then for i in [ lbound+2..UpperBound( PC ) ] do
Append( middle, [ nextLifting( middle[i-lbound], i ) ] );
od; for j in [ i+1..UpperBound( EC ) ] do
Append( middle, [ ZeroMapping( ObjectOfComplex( PC, j ), ObjectOfComplex( EC, j ) ) ] );
od;
return FiniteChainMap( PC, EC, lbound, middle ); else
nextLiftingFunction := function( M, i ) return nextLifting( MorphismOfChainMap( M, i-1 ), i ); end;
return ChainMap( PC, EC, lbound, middle, [ "pos", nextLiftingFunction, true ], "zero" ); fi; end );
####################################################################### ## #O ComparisonLiftingToProjectiveResolution( <f> ) ## ## <f> is a morphism between two modules M and N. The function ## returns the lifting of <f> to a chain map between the projective ## resolutions of M and N. The modules M and N are in degree -1 of ## the resolutions, and the map in degree -1 is <f>. ##
InstallMethod( ComparisonLiftingToProjectiveResolution,
[ IsPathAlgebraMatModuleHomomorphism ], function( f )
return ComparisonLifting( f, ProjectiveResolution( Source(f) ), ProjectiveResolution( Range(f) ) ); end );
####################################################################### ## #O MappingCone( <f> ) ## ## <f> is a chain map between two complexes A and B. ## This method returns a list [ C, i, p ] where C is the mapping cone ## of <f>, i is the (chain map) inclusion of B into the cone and ## p is the projection from the cone onto A[-1]. ##
InstallMethod( MappingCone,
[ IsChainMap ], function( f )
local C, i, A, B, dirsum, dirsum2, diff, middle, positiveFunction, negativeFunction;
A := Source(f);
B := Range(f);
# # Consider where to "start" the cone complex. # if (IsInt(LowerBound(A))) then
i := LowerBound(A); elif (IsInt(LowerBound(B))) then
i := LowerBound(B); elif (IsInt(UpperBound(A))) then
i := UpperBound(A); elif (IsInt(UpperBound(B))) then
i := UpperBound(B); else
i := 0; fi;
# # Construct the first differential of the cone, and the first projection/inclusion morphisms #
# # Returns the cone (as a complex) together with the projection and the inclusion #
C := ComplexAndChainMaps( [B], [Shift(A,-1)], i, middle,
["pos", positiveFunction, true],
["pos", negativeFunction, true] );
return C; end );
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.61 Sekunden
(vorverarbeitet am 2026-10-13)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.