GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
## HomalgDiagram.gi GradedModules package
##
## Copyright 2007-2010, Mohamed Barakat, University of Kaiserslautern
##
## Declarations for Betti diagrams.
##
#############################################################################
####################################
#
# families and types:
#
####################################
# a new type:
BindGlobal( "TheTypeBettiTable",
NewType( TheFamilyOfHomalgDiagrams,
IsHomalgDiagramRep and
IsBettiTable ) );
####################################
#
# global variables:
#
####################################
HOMALG.SpectralSequenceConventionForBettiTablesOfComplexes := false;
HOMALG.SpectralSequenceConventionForBettiTablesOfCocomplexes := true;
####################################
#
# methods for operations:
#
####################################
##
InstallMethod( RowDegreesOfBettiTable,
"for Betti diagrams",
[ IsBettiTable ],
function( diag )
return diag!.row_range;
end );
##
InstallMethod( ColumnDegreesOfBettiTable,
"for Betti diagrams",
[ IsBettiTable ],
function( diag )
return diag!.column_range;
end );
####################################
#
# constructor functions and methods:
#
####################################
##
InstallGlobalFunction( HomalgBettiTable,
function( arg )
local betti, row_range, column_range, object, ar, nr_rows, nr_cols, diagram;
betti := arg[1];
row_range := arg[2];
column_range := arg[3];
object := arg[4];
nr_rows := Length( row_range );
nr_cols := Length( column_range );
if nr_rows <> Length( betti ) then
Error( "the Betti table and the row range are incompatible\n" );
elif Length( betti ) > 0 and nr_cols <> Length( betti[1] ) then
Error( "the Betti table and the column range are incompatible\n" );
fi;
diagram := rec(
object := object,
matrix := betti,
row_range := row_range,
column_range := column_range,
reverse := false ## read the row range upside down?: default value is false (might get reset below)
);
## search for options
for ar in arg{[ 5 .. Length( arg ) ]} do
if IsString( ar ) then
diagram.( ar ) := true;
elif IsList( ar ) and Length( ar ) = 2 and IsString( ar[1] ) then
diagram.( ar[1] ) := ar[2];
fi;
od;
## Objectify:
ObjectifyWithAttributes(
diagram, TheTypeBettiTable,
NrRows, nr_rows,
NrColumns, nr_cols
);
return diagram;
end );
####################################
#
# View, Print, and Display methods:
#
####################################
##
InstallMethod( ViewObj,
"for Betti diagrams",
[ IsBettiTable ],
function( o )
Print( "<A Betti diagram of " );
if HasBettiTable ( o!.object ) and IsIdenticalObj( o, BettiTable ( o!.object ) ) then
ViewObj( o!.object );
Print( ">" );
else
Print( "a homalg " );
if IsBound( o!.object!.string ) then
Print( o!.object!.string );
else
Print( "object" );
fi;
Print( ">" );
fi;
end );
##
InstallMethod( homalgCreateDisplayString,
"for Betti diagrams",
[ IsBettiTable ],
function( o )
local SpectralSequenceConvention, betti, row_range, column_range,
higher_vanish, twist, EulerCharacteristic, reverse,
nr_rows, nr_cols, total, max, twist_range, chi,
MAX, display, ar, i, pos, marker;
## the spectral sequence convention for Betti diagrams
SpectralSequenceConvention := o!.SpectralSequenceConvention;
## collect the relevant data from the diagram
betti := MatrixOfDiagram( o );
row_range := RowDegreesOfBettiTable( o );
column_range := ColumnDegreesOfBettiTable( o );
if IsBound( o!.higher_vanish ) then
higher_vanish := o!.higher_vanish;
fi;
if IsBound( o!.twist ) then
twist := o!.twist;
fi;
if IsBound( o!.EulerCharacteristic ) and
IsUnivariatePolynomial( o!.EulerCharacteristic ) then
EulerCharacteristic := o!.EulerCharacteristic;
fi;
## read the row range upside down?
reverse := o!.reverse;
nr_rows := NrRows( o );
nr_cols := NrColumns( o );
## now prepare constructing the display string
## the list of total dimensions
total := ListWithIdenticalEntries( nr_rows, 1 ) * betti;
## save it
o!.total := total;
## get the maximum width in the matrix
max := MaximumList( List( betti, r -> MaximumList( List( r, a -> Length( String( a ) ) ) ) ) );
max := Maximum( MaximumList( List( column_range, a -> Length( String( a ) ) ) ), max );
max := Maximum( MaximumList( List( total, a -> Length( String( a ) ) ) ), max );
if SpectralSequenceConvention then
ar := column_range[1];
if nr_rows > 1 then
max := Maximum( MaximumList( List( [ ar - ( nr_rows - 1 ) .. ar - 1 ], a -> Length( String( a ) ) ) ), max );
fi;
fi;
if IsBound( twist ) then
twist_range := column_range - ( nr_rows - 1 );
max := Maximum( MaximumList( List( twist_range, a -> Length( String( a ) ) ) ), max );
if IsBound( EulerCharacteristic ) then
if SpectralSequenceConvention then
twist_range := [ twist_range[1] .. twist_range[nr_cols] + ( nr_rows - 1 ) ];
chi := List( twist_range, i -> Value( EulerCharacteristic, i ) );
else
chi := List( twist_range + ( nr_rows - 1 ), i -> Value( EulerCharacteristic, i ) );
fi;
## save it
o!.Euler := chi;
max := Maximum( MaximumList( List( chi, a -> Length( String( a ) ) ) ), max );
elif twist = row_range[nr_rows] then ## we might have computed the syzygies up to some degree bound only
chi := List( [ 1 .. nr_cols - twist ], j -> Sum( [ 0 .. nr_rows - 1 ], i -> (-1)^i * betti[nr_rows-i][i+j] ) );
## save it
o!.Euler := chi;
if IsBound( higher_vanish ) and column_range[Length( column_range )] >= higher_vanish - 1 then
Append( chi, List( [ Maximum( nr_cols - twist + 1, 1 ) .. nr_cols ],
j -> Sum( [ 0 .. nr_rows - 1 ],
function( i )
if IsBound( betti[nr_rows-i][i+j] ) then
return (-1)^i * betti[nr_rows-i][i+j];
else
return 0;
fi; end ) ) );
## save it
o!.Euler := chi;
else
Append( chi, ListWithIdenticalEntries( twist, "?" ) );
fi;
max := Maximum( MaximumList( List( chi, a -> Length( String( a ) ) ) ), max );
fi;
fi;
## finally add a space
max := max + 1;
## the maximum of the legend column
MAX := MaximumList( List( row_range, a -> Length( String( a ) ) ) );
if IsBound( twist ) then
MAX := Maximum( MAX, Length( "twist" ) );
else
MAX := Maximum( MAX, Length( "degree" ) );
fi;
## create the display string:
display := "";
if SpectralSequenceConvention then
nr_cols := nr_cols + nr_rows - 1;
fi;
## total:
if nr_rows > 1 then
Append( display, String( "total", MAX ) );
Append( display, ": " );
Perform( total, function( i ) Append( display, String( i, max ) ); end );
if SpectralSequenceConvention then
Perform( [ 1 .. nr_rows - 1 ], function( i ) Append( display, String( "?", max ) ); end );
fi;
Append( display, "\n" );
if SpectralSequenceConvention then
Append( display, ListWithIdenticalEntries( MAX + 2, '-' ) );
Append( display, Flat( ListWithIdenticalEntries( nr_cols, Concatenation( ListWithIdenticalEntries( max - 1, '-' ), "|" ) ) ) );
else
Append( display, ListWithIdenticalEntries( MAX + 2 + nr_cols * max, '-' ) );
fi;
Append( display, "\n" );
fi;
## twist:
if IsBound( twist ) and nr_rows > 1 and not SpectralSequenceConvention then
Append( display, String( "twist", MAX ) );
Append( display, ": " );
Perform( twist_range, function( i ) Append( display, String( i, max ) ); end );
Append( display, "\n" );
Append( display, ListWithIdenticalEntries( MAX + 2, '-' ) );
Append( display, Flat( ListWithIdenticalEntries( nr_cols, Concatenation( ListWithIdenticalEntries( max - 1, '-' ), "|" ) ) ) );
Append( display, "\n" );
fi;
if reverse then
row_range := Reversed( row_range );
fi;
## betti:
if SpectralSequenceConvention then
for ar in [ 1 .. nr_rows ] do
Append( display, String( String( row_range[ar] ), MAX ) );
Append( display, ": " );
Perform( [ 1 .. ar - 1 ], function( i ) Append( display, String( "*", max ) ); end );
for i in [ 1 .. nr_cols - ( nr_rows - 1 ) ] do
if IsZero( betti[ar][i] ) then
Append( display, String( ".", max ) );
else
Append( display, String( String( betti[ar][i] ), max ) );
fi;
od;
if IsBound( higher_vanish ) and column_range[Length( column_range )] >= higher_vanish - 1 then
Perform( [ 1 .. nr_rows - ar ], function( i ) Append( display, String( "0", max ) ); end );
else
Perform( [ 1 .. nr_rows - ar ], function( i ) Append( display, String( "*", max ) ); end );
fi;
Append( display, "\n" );
od;
else
for ar in [ 1 .. nr_rows ] do
Append( display, String( String( row_range[ar] ), MAX ) );
Append( display, ": " );
for i in [ 1 .. nr_cols ] do
if IsZero( betti[ar][i] ) then
Append( display, String( ".", max ) );
else
Append( display, String( String( betti[ar][i] ), max ) );
fi;
od;
Append( display, "\n" );
od;
fi;
## degree/twist:
if IsBound( twist ) then
Append( display, ListWithIdenticalEntries( MAX + 2, '-' ) );
if IsBound( higher_vanish ) then
pos := Position( column_range, higher_vanish );
if IsBound( o!.markers ) and IsList( o!.markers ) then
marker := First( o!.markers, i -> i[1] = higher_vanish );
if IsList( marker ) then
marker := marker[2];
fi;
fi;
fi;
if IsBound( pos ) and IsPosInt( pos ) then
pos := pos + nr_cols - Length( column_range );
Append( display, Flat( ListWithIdenticalEntries( pos - 1, Concatenation( ListWithIdenticalEntries( max - 1, '-' ), "|" ) ) ) );
if not IsString( marker ) then
marker := "V";
fi;
Append( display, Concatenation( ListWithIdenticalEntries( max - 1, '-' ), marker ) );
Append( display, Flat( ListWithIdenticalEntries( nr_cols - pos, Concatenation( ListWithIdenticalEntries( max - 1, '-' ), "|" ) ) ) );
else
Append( display, Flat( ListWithIdenticalEntries( nr_cols, Concatenation( ListWithIdenticalEntries( max - 1, '-' ), "|" ) ) ) );
fi;
Append( display, "\n" );
Append( display, String( "twist", MAX ) );
else
Append( display, ListWithIdenticalEntries( MAX + 2 + nr_cols * max, '-' ) );
Append( display, "\n" );
Append( display, String( "degree", MAX ) );
fi;
Append( display, ": " );
if SpectralSequenceConvention then
ar := column_range[1];
Perform( [ ar - ( nr_rows - 1 ) .. ar - 1 ], function( i ) Append( display, String( i, max ) ); end );
fi;
Perform( column_range, function( i ) Append( display, String( i, max ) ); end );
Append( display, "\n" );
## Euler characteristic:
if IsBound( chi ) then
Append( display, ListWithIdenticalEntries( MAX + 2 + nr_cols * max, '-' ) );
Append( display, "\n" );
Append( display, String( "Euler", MAX ) );
Append( display, ": " );
if SpectralSequenceConvention and not IsBound( EulerCharacteristic ) then
Perform( [ 1 .. nr_rows - 1 ], function( i ) Append( display, String( "?", max ) ); end );
fi;
Perform( chi, function( i ) Append( display, String( i, max ) ); end );
Append( display, "\n" );
fi;
return display;
end );
##
InstallMethod( Display,
"for Betti diagrams",
[ IsBettiTable ],
function( o )
local SpectralSequenceConvention;
## the spectral sequence convention for Betti diagrams
if IsBound( HOMALG.SpectralSequenceConventionForBettiTables ) then
SpectralSequenceConvention := HOMALG.SpectralSequenceConventionForBettiTables = true;
elif IsComplexOfFinitelyPresentedObjectsRep( o!.object ) and
IsBound( HOMALG.SpectralSequenceConventionForBettiTablesOfComplexes ) then
SpectralSequenceConvention := HOMALG.SpectralSequenceConventionForBettiTablesOfComplexes = true;
elif IsCocomplexOfFinitelyPresentedObjectsRep( o!.object ) and
IsBound( HOMALG.SpectralSequenceConventionForBettiTablesOfCocomplexes ) then
SpectralSequenceConvention := HOMALG.SpectralSequenceConventionForBettiTablesOfCocomplexes = true;
else
SpectralSequenceConvention := false;
fi;
if not IsBound( o!.display ) or
o!.SpectralSequenceConvention <> SpectralSequenceConvention then
o!.SpectralSequenceConvention := SpectralSequenceConvention;
o!.display := homalgCreateDisplayString( o );
fi;
Print( o!.display );
end );