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; _______________________________________________ Forum mailing list Forum@gap-system.org https://mail.gap-system.org/mailman/listinfo/forum