[GAP Forum] Displaying character table with different conjugacy class labels
Thomas Breuer
sam at Math.RWTH-Aachen.De
Wed Aug 14 09:18:19 BST 2019
Dear GAP Forum,
David Madore asked
> I'm not sure whether my question concerns GAP proper or the character
> table library: I'm using GAP from Debian stretch (now oldstable) which
> identifies as follows (although I can easily switch to a different
> version if this is relevant):
>
> [...]
>
> Anyway, I'd like to display a character table (tbl, say, computed by
> something like tbl := CharacterTable("W(E8)")) but with a different
> labeling of the conjugacy classes. It turns out that the function
> AtlasClassNames(tbl) gives the labels I want, but I couldn't figure
> out a way to either get Display(tbl) to use this set of labels or
> modify tbl so as to replace the origina labels.
>
> This is merely a display issue. I'm not trying to change anything in
> the computation or even in the order of the classes.
Currently the relevant function does not support prescribed class names,
but I think it is a good idea to add such an option to the 'Display'
and 'Browse' methods for character tables.
For the moment, reading the GAP code appended below into a GAP session
yields the desired functionality.
One can then enter
gap> tbl:= CharacterTable( "W(E8)" );;
gap> Display( tbl, rec( classnames:= AtlasClassNames( tbl ) ) );
and gets the given class names as labels of the columns.
Thanks for the suggestion.
All the best,
Thomas
#############################################################################
##
#F CharacterTableDisplayDefault( <tbl>, <options> )
##
## changed: admit component "classnames" in <options>
##
if not IsBound( CambridgeMaps ) then
CambridgeMaps:= "dummy"; # the function is in the character table library
fi;
MakeReadWriteGVar( "REREADING" );
REREADING:= true;
InstallGlobalFunction( CharacterTableDisplayDefault,
function( tbl, options )
local i, j, # loop variables
colWidth, # local function
record, # loop over options records
printLegend, # local function
legend, # local function
cletter, # character name
chars_from_irr, # are the characters contained in `Irr( tbl )'?
chars, # list of characters
cnr, # list of character numbers
classes, # list of classes
powermap, # list of primes
centralizers, # boolean
cen, # factorized centralizers
fak, # factorization
prime, # loop over primes
primes, # prime factors of order
prin, # column widths
nam, # classnames
col, # number of columns already printed
acol, # nuber of columns on next page
len, # width of next page
ncols, # total number of columns
linelen, # line length
q, # quadratic cyc / powermap entry
indicator, # list of primes
indic, # indicators
iw, # width of indicator column
stringEntry, # local function
stringEntryData, # data accessed by `stringEntry'
cc, # column number
charnames, # list of character names
charvals, # matrix of strings of character values
tbl_powermap,
tbl_centralizers;
# compute the width of column `col'
colWidth:= function( col )
local len, width;
if IsRecord( powermap ) then
# the three components should fit into the column
width:= Length( powermap.power[ col ] );
len:= Length( powermap.prime[ col ] );
if len > width then
width:= len;
fi;
len:= Length( powermap.names[ col ] );
if len > width then
width:= len;
fi;
else
# the class name should fit into the column
width:= Length( nam[col] );
# the class names of power classes should fit into the column
for i in powermap do
len:= tbl_powermap[i][ col ];
if IsInt( len ) then
len:= Length( nam[ len ] );
if len > width then
width:= len;
fi;
fi;
od;
fi;
if centralizers = "ATLAS" then
# The centralizer orders should fit into the column.
len:= Length( String( tbl_centralizers[ col ] ) );
if len > width then
width:= len;
fi;
fi;
# each character value should fit into the column
for i in [ 1 .. Length( cnr ) ] do
len:= Length( charvals[i][ col ] );
if len > width then
width:= len;
fi;
od;
# at least one blank should separate the column entries
return width + 1;
end;
# Prepare a list of the available options records.
options:= [ options ];
if HasDisplayOptions( tbl ) and
not IsIdenticalObj( options[1], DisplayOptions( tbl ) ) then
Add( options, DisplayOptions( tbl ) );
fi;
if IsBound( CharacterTableDisplayDefaults.User ) and
not IsIdenticalObj( options[1],
CharacterTableDisplayDefaults.User ) then
Add( options, CharacterTableDisplayDefaults.User );
fi;
if not IsIdenticalObj( options[1],
CharacterTableDisplayDefaults.Global ) then
Add( options, CharacterTableDisplayDefaults.Global );
fi;
# Get the options that are in at least one record.
for record in options do
if IsBound( record.StringEntry ) then
stringEntry:= record.StringEntry;
break;
fi;
od;
for record in options do
if IsBound( record.StringEntryData ) then
stringEntryData:= record.StringEntryData( tbl );
break;
fi;
od;
for record in options do
if IsBound( record.PrintLegend ) then
# for backwards compatibility with GAP 4.4 ...
printLegend:= record.PrintLegend;
break;
elif IsBound( record.Legend ) then
legend:= record.Legend;
printLegend:= function( data ) Print( legend( data ) ); end;
break;
fi;
od;
for record in options do
if IsBound( record.letter ) and Length( record.letter ) = 1 then
cletter:= record.letter;
break;
fi;
od;
for record in options do
if IsBound( record.centralizers ) then
centralizers:= record.centralizers;
break;
fi;
od;
# Get the options that have no global default.
# choice of characters and character names
chars_from_irr:= true;
for record in options do
if IsBound( record.chars ) then
if IsList( record.chars ) and ForAll( record.chars, IsPosInt ) then
cnr:= record.chars;
chars:= List( Irr( tbl ){ cnr }, ValuesOfClassFunction );
elif IsInt( record.chars ) then
cnr:= [ record.chars ];
chars:= List( Irr( tbl ){ cnr }, ValuesOfClassFunction );
elif IsHomogeneousList( record.chars ) then
chars:= record.chars;
cnr:= [ 1 .. Length( chars ) ];
chars_from_irr:= false;
if not IsBound( cletter ) then
cletter:= "Y";
fi;
else
cnr:= [];
chars:= [];
fi;
break;
fi;
od;
if not IsBound( chars ) then
# Perhaps the irreducibles have to be computed here,
# so we do not use this before evaluating the options.
chars:= List( Irr( tbl ), ValuesOfClassFunction );
cnr:= [ 1 .. Length( chars ) ];
if HasCharacterNames( tbl ) then
charnames:= CharacterNames( tbl );
fi;
fi;
if not IsBound( cletter ) then
cletter:= "X";
fi;
if not IsBound( charnames ) then
charnames:= List( cnr,
i -> Concatenation( cletter, ".", String( i ) ) );
fi;
# choice of classes
classes:= [ 1 .. NrConjugacyClasses( tbl ) ];
for record in options do
if IsBound( record.classes ) then
if IsInt( record.classes ) then
classes:= [ record.classes ];
else
classes:= record.classes;
fi;
break;
fi;
od;
# choice of power maps
tbl_powermap:= ComputedPowerMaps( tbl );
powermap:= Filtered( [ 2 .. Length( tbl_powermap ) ],
x -> IsBound( tbl_powermap[x] ) );
for record in options do
if IsBound( record.powermap ) then
if IsInt( record.powermap ) then
IntersectSet( powermap, [ record.powermap ] );
elif record.powermap = "ATLAS" and IsBound( CambridgeMaps ) then
powermap:= "ATLAS";
powermap:= CambridgeMaps( tbl );
elif IsList( record.powermap ) then
IntersectSet( powermap, record.powermap );
elif record.powermap = false then
powermap:= [];
fi;
break;
fi;
od;
# print Frobenius-Schur indicators?
indicator:= [];
for record in options do
if IsBound( record.indicator ) then
if record.indicator = true then
indicator:= [ 2 ];
elif IsList( record.indicator ) then
indicator:= Set( Filtered( record.indicator, IsPosInt ) );
fi;
break;
fi;
od;
# (end of options handling)
# line length
linelen:= SizeScreen()[1] - 1;
# prepare centralizers
if centralizers = "ATLAS" then
tbl_centralizers:= SizesCentralizers( tbl );
elif centralizers = true then
tbl_centralizers:= SizesCentralizers( tbl );
primes:= PrimeDivisors( Size( tbl ) );
cen:= [];
for prime in primes do
cen[ prime ]:= [];
od;
fi;
# prepare class names
if IsRecord( powermap ) then
nam:= ClassNames( tbl, "ATLAS" );
else
nam:= ClassNames( tbl );
for record in options do
if IsBound( record.classnames ) and IsList( record.classnames ) then
nam:= record.classnames;
break;
fi;
od;
fi;
# prepare indicator
# (compute the values if they are not stored but use stored values)
iw:= [ 0 ];
if indicator <> [] then
indic:= [];
for i in indicator do
if chars_from_irr and IsBound( ComputedIndicators( tbl )[i] ) then
indic[i]:= ComputedIndicators( tbl )[i]{ cnr };
else
indic[i]:= Indicator( tbl, Irr( tbl ){ cnr }, i );
fi;
if i = 2 then
iw[i]:= 2;
else
iw[i]:= Maximum( Length( String( Maximum( Set( indic[i] ) ) ) ),
Length( String( Minimum( Set( indic[i] ) ) ) ),
Length( String( i ) ) ) + 1;
fi;
iw[1]:= iw[1] + iw[i];
od;
iw[1]:= iw[1] + 1;
fi;
if Length( cnr ) = 0 then
prin:= [ 3 ];
else
prin:= [ Maximum( List( charnames, Length ) ) + 3 ];
fi;
# prepare list for strings of character values
charvals:= List( chars, x -> [] );
# total number of columns
ncols:= Length(classes) + 1;
# number of columns already displayed
col:= 1;
# A character table has a name.
Print( Identifier( tbl ), "\n" );
while col < ncols do
# determine number of cols for next page
acol:= 0;
if indicator <> [] then
prin[1]:= prin[1] + iw[1];
fi;
len:= prin[1];
while col+acol < ncols and len < linelen do
acol:= acol + 1;
if Length(prin) < col + acol then
cc:= classes[ col + acol - 1 ];
for i in [ 1 .. Length( cnr ) ] do
charvals[i][ cc ]:= stringEntry( chars[i][ cc ],
stringEntryData );
od;
prin[ col + acol ]:= colWidth( cc );
fi;
len:= len + prin[col+acol];
od;
if len >= linelen then
acol:= acol-1;
fi;
# Check whether we are able to print at least one column.
if acol = 0 then
Error( "line length too small (perhaps resize with `SizeScreen')" );
fi;
# centralizers
if centralizers = "ATLAS" then
#T Admit splitting into two lines,
#T admit that the first centralizer starts in the character names' area.
Print( "\n" );
Print( String( "", prin[1] ) );
for j in [ col + 1 .. col + acol ] do
Print( String( tbl_centralizers[ j-1 ], prin[j] ) );
od;
Print( "\n" );
elif centralizers = true then
Print( "\n" );
for i in [col..col+acol-1] do
fak:= Factors( Integers, tbl_centralizers[ classes[i] ] );
for prime in Set( fak ) do
if prime <> 1 then
cen[prime][i]:= Number( fak, x -> x = prime );
fi;
od;
od;
for j in [1..Length(cen)] do
if IsBound(cen[j]) then
for i in [col..col+acol-1] do
if not IsBound(cen[j][i]) then
cen[j][i]:= ".";
fi;
od;
fi;
od;
for prime in primes do
Print( String( prime, prin[1] ) );
for j in [1..acol] do
Print( String( cen[prime][col+j-1], prin[col+j] ) );
od;
Print( "\n" );
od;
fi;
# class names and power maps
if IsRecord( powermap ) then
# three lines: power maps, p' part, and class names
Print( "\n" );
Print( String( "p ", prin[1] ) );
for j in [ 1 .. acol ] do
Print( String( powermap.power[classes[col+j-1]],
prin[col+j] ) );
od;
Print( "\n" );
Print( String( "p'", prin[1] ) );
for j in [ 1 .. acol ] do
Print( String( powermap.prime[classes[col+j-1]],
prin[col+j] ) );
od;
Print( "\n" );
Print( String( "", prin[1] ) );
for j in [ 1 .. acol ] do
Print( String( powermap.names[classes[col+j-1]],
prin[col+j] ) );
od;
else
# first class names, then a line for each power map
Print( "\n" );
Print( String( "", prin[1] ) );
for i in [ 1 .. acol ] do
Print( String( nam[classes[col+i-1]], prin[col+i] ) );
od;
for i in powermap do
Print( "\n" );
Print( String( Concatenation( String(i), "P" ),
prin[1] ) );
for j in [ 1 .. acol ] do
q:= tbl_powermap[i][classes[col+j-1]];
if IsInt( q ) then
Print( String( nam[q], prin[col+j] ) );
else
Print( String( "?", prin[col+j] ) );
fi;
od;
od;
fi;
# empty column resp. indicators
Print( "\n" );
if indicator <> [] then
prin[1]:= prin[1] - iw[1];
Print( String( "", prin[1] ) );
for i in indicator do
Print( String( i, iw[i] ) );
od;
fi;
# the characters
for i in [1..Length(chars)] do
Print( "\n" );
# character name
Print( String( charnames[i], -prin[1] ) );
# indicators
for j in indicator do
if j = 2 then
if indic[j][i] = 0 then
Print( String( "o", iw[j] ) );
elif indic[j][i] = 1 then
Print( String( "+", iw[j] ) );
elif indic[j][i] = -1 then
Print( String( "-", iw[j] ) );
fi;
else
if indic[j][i] = 0 then
Print( String( "0", iw[j] ) );
else
Print( String( stringEntry( indic[j][i],
stringEntryData ),
iw[j]) );
fi;
fi;
od;
if indicator <> [] then
Print(" ");
fi;
for j in [ 1 .. acol ] do
Print( String( charvals[i][ classes[col+j-1] ],
prin[ col+j ] ) );
od;
od;
col:= col + acol;
Print("\n");
# Indicators are printed only with the first portion of columns.
indicator:= [];
od;
# print legend for cyclos
printLegend( stringEntryData );
end );
REREADING:= false;
MakeReadOnlyGVar( "REREADING" );
if IsString( CambridgeMaps ) then
Unbind( CambridgeMaps );
fi;
More information about the Forum
mailing list