Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
Project: cocalc-sagemath-dev-slelievre
Views: 418346############################################################################# ## #W interfac.gi GAP 4 package AtlasRep Thomas Breuer ## #Y Copyright (C) 2001, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany ## ## This file contains the implementation part of the ``high level'' GAP ## interface to the ATLAS of Group Representations. ## ############################################################################# ## #F AGR.Pager( <string> ) ## ## Simply calling `Pager' is not good enough, because GAP introduces ## line breaks in too long lines, and GAP does not compute the printable ## length of the line but the length as a string. ## ## If <string> is empty then the builtin pager runs into an error, ## therefore we catch this case. ## AGR.Pager:= function( string ) if string <> "" then Pager( rec( lines:= string, formatted:= true ) ); fi; end; ############################################################################# ## #F AGR.ShowOnlyASCII() ## ## Show nicer grids and symbols such as ℤ if the terminal admits this. ## Currently we do not do this if `Print' is used to show the data, ## because of the automatically inserted line breaks. ## AGR.ShowOnlyASCII:= function() return IsIdenticalObj( AtlasOfGroupRepresentationsInfo.displayFunction, Print ) or GAPInfo.TermEncoding <> "UTF-8"; end; ############################################################################# ## #F AGR.StringAtlasInfoOverview( <gapnames>, <conditions> ) ## AGR.StringAtlasInfoOverview:= function( gapnames, conditions ) local columns, type, i, widths, width, fstring, result, mid; # Consider only those names for which actually information is available. # (The ordering shall be the same as in the input.) if gapnames = "all" then gapnames:= AtlasOfGroupRepresentationsInfo.GAPnamesSortDisp; else gapnames:= Filtered( List( gapnames, AGR.InfoForName ), x -> x <> fail ); fi; if IsEmpty( gapnames ) then return; fi; # Compute the data of the columns. columns:= [ [ "group", "l", List( gapnames, x -> [ x[1], false ] ) ] ]; for type in AGR.DataTypes( "rep", "prg" ) do if type[2].DisplayOverviewInfo <> fail then Add( columns, [ type[2].DisplayOverviewInfo[1], type[2].DisplayOverviewInfo[2], List( gapnames, n -> type[2].DisplayOverviewInfo[3]( Concatenation( [ n ], conditions ) ) ) ] ); fi; od; # Evaluate the privacy flag. for i in [ 1 .. Length( gapnames ) ] do if ForAny( columns, x -> x[3][i][2] ) then columns[1][3][i][1]:= Concatenation( columns[1][3][i][1], AtlasOfGroupRepresentationsInfo.markprivate ); fi; od; # Compute the appropriate column widths. widths:= []; for i in columns do width:= Maximum( Length( i[1] ), # the header string shall fit Maximum( List( i[3], y -> Length( y[1] ) ) ) ); Add( widths, [ width, i[2] ] ); od; fstring:= function( string, width ) local strwidth, n, n1, n2; strwidth:= WidthUTF8String( string ); if width[1] <= strwidth then return string; elif width[2] = "l" then return Concatenation( string, RepeatedString( ' ', width[1] - strwidth ) ); elif width[2] = "r" then return Concatenation( RepeatedString( ' ', width[1] - strwidth ), string ); else n:= RepeatedString( ' ', width[1] - strwidth ); n1:= n{ [ QuoInt( Length( n ), 2 ) + 1 .. Length( n ) ] }; n2:= n{ [ 1 .. QuoInt( Length( n ), 2 ) ] }; return Concatenation( n1, string, n2 ); fi; end; result:= []; # Add the header line. if AGR.ShowOnlyASCII() then mid:= " | "; else mid:= " │ "; fi; Add( result, JoinStringsWithSeparator( List( [ 1 .. Length( columns ) ], j -> fstring( columns[j][1], widths[j] ) ), mid ) ); if AGR.ShowOnlyASCII() then Add( result, JoinStringsWithSeparator( List( [ 1 .. Length( columns ) ], j -> RepeatedString( "-", widths[j][1] ) ), "-+-" ) ); else Add( result, JoinStringsWithSeparator( List( [ 1 .. Length( columns ) ], j -> RepeatedUTF8String( "─", widths[j][1] ) ), "─┼─" ) ); fi; # Add the information for each group. for i in [ 1 .. Length( gapnames ) ] do if ForAny( [ 2 .. Length( columns ) ], j -> columns[j][3][i][1] <> "" ) then Add( result, JoinStringsWithSeparator( List( [ 1 .. Length( columns ) ], j -> fstring( columns[j][3][i][1], widths[j] ) ), mid ) ); fi; od; return result; end; ############################################################################# ## #F AGR.InfoPrgs( <conditions> ) ## AGR.InfoPrgs:= function( conditions ) local groupname, name, tocs, std, argpos, stdavail, toc, record, type, list, header, nams, sort, info, pi; groupname:= AGR.InfoForName( conditions[1] ); if groupname = fail then return rec( list:= [] ); fi; conditions:= conditions{ [ 2 .. Length( conditions ) ] }; name:= groupname[2]; tocs:= AGR.TablesOfContents( conditions ); if Length( conditions ) = 0 or not ( IsInt( conditions[1] ) or IsList( conditions[1] ) ) then std:= true; argpos:= 1; else std:= conditions[1]; if IsInt( std ) then std:= [ std ]; fi; argpos:= 2; fi; # If the standardization is prescribed then do not mention it. # Otherwise if all information refers to the same standardization then # print just one line. # Otherwise print the standardization for each entry. stdavail:= []; if std = true or 1 < Length( std ) then for toc in tocs do if IsBound( toc.( name ) ) then record:= toc.( name ); for type in AGR.DataTypes( "prg" ) do if IsBound( record.( type[1] ) ) then for list in record.( type[1] ) do if std = true or list[1] in std then AddSet( stdavail, list[1] ); fi; od; fi; od; fi; od; fi; # Create the header line. # (Because of `AtlasRepCreateHTMLInfoForGroup', # `gapname' must occur as an entry of its own .) header:= [ "Programs for G = ", groupname[1], ":" ]; if Length( stdavail ) = 1 then Append( header, [ " (all refer to std. generators ", String( stdavail[1] ), ")" ] ); fi; # Collect the info lines for the scripts. list:= []; nams:= []; sort:= []; if ( Length( conditions ) = argpos and conditions[ argpos ] = IsStraightLineProgram ) or ( Length( conditions ) = argpos + 1 and conditions[ argpos ] = IsStraightLineProgram and conditions[ argpos + 1 ] = true ) or Length( conditions ) < argpos then for type in AGR.DataTypes( "prg" ) do info:= type[2].DisplayPRG( tocs, name, std, stdavail ); Add( list, info ); if IsEmpty( info ) then Add( sort, [ 0 ] ); elif Length( info ) = 1 then Add( sort, [ 0, info[1] ] ); else Add( sort, [ 1, info[1] ] ); fi; Add( nams, type[1] ); od; fi; # Sort the information such that those come first for which a single # line is given. # (This is because `BrowseAtlasInfo' turns the parts with more than # one line into a subcategory which is created from the first line.) # Inside this ordering of entries, sort the information alphabetically. pi:= Sortex( sort ); return rec( header := header, list := Permuted( list, pi ), nams := Permuted( nams, pi ) ); end; ############################################################################# ## #F AGR.EvaluateMinimalityCondition( <gapname>, <conditions> ) ## ## Evaluate conditions involving `"minimal"': ## Replace the string `"minimal"' by the number in question if known, ## return `true' in this case and `false' otherwise. ## (In the `false' case, an info message is printed.) ## AGR.EvaluateMinimalityCondition:= function( gapname, conditions ) local pos, info, pos2; pos:= Position( conditions, "minimal" ); if pos <> fail and pos <> 1 then if IsIdenticalObj( conditions[ pos-1 ], NrMovedPoints ) then # ..., NrMovedPoints, "minimal", ... info:= MinimalRepresentationInfo( gapname, NrMovedPoints ); if info = fail then Info( InfoAtlasRep, 1, "minimal perm. repr. of `", gapname, "' not known" ); return false; fi; conditions[ pos ]:= info.value; elif IsIdenticalObj( conditions[ pos-1 ], Dimension ) then pos2:= Position( conditions, Characteristic ); if pos2 <> fail and pos2 < Length( conditions ) then # ..., Characteristic, <p>, ..., Dimension, "minimal", ... info:= MinimalRepresentationInfo( gapname, Characteristic, conditions[ pos2+1 ] ); if info = fail then Info( InfoAtlasRep, 1, "minimal matrix repr. of `", gapname, "' in characteristic ", conditions[ pos2+1 ], " not known" ); return false; fi; conditions[ pos ]:= info.value; else pos2:= Position( conditions, Ring ); if pos2 <> fail and pos2 < Length( conditions ) and IsField( conditions[ pos2+1 ] ) and IsFinite( conditions[ pos2+1 ] ) then # ..., Ring, <R>, ..., Dimension, "minimal", ... info:= MinimalRepresentationInfo( gapname, Size, Size( conditions[ pos2+1 ] ) ); if info = fail then Info( InfoAtlasRep, 1, "minimal matrix repr. of `", gapname, "' over `", conditions[ pos2+1 ], "' not known" ); return false; fi; conditions[ pos ]:= info.value; fi; fi; fi; fi; return true; end; ############################################################################# ## #F AGR.InfoReps( <conditions> ) ## ## This function is used by `AGR.DisplayAtlasInfoGroup' and ## `BrowseData.AtlasRepGroupInfoTable'. ## AGR.InfoReps:= function( conditions ) local info, stdavail, header, list, types, r, type, entry; info:= CallFuncList( AllAtlasGeneratingSetInfos, conditions ); # If all information refers to the same standardization then # print just one line. # Otherwise print the standardization for each entry. stdavail:= Set( List( info, x -> x.standardization ) ); # Construct the header line. # (Because of `AtlasRepCreateHTMLInfoForGroup', # `gapname' must occur as an entry of its own .) header:= [ "Representations for G = ", AGR.GAPName( conditions[1] ), ":" ]; if Length( stdavail ) = 1 then Add( header, Concatenation( " (all refer to std. generators ", String( stdavail[1] ), ")" ) ); fi; list:= []; types:= AGR.DataTypes( "rep" ); for r in info do type:= First( types, t -> t[1] = r.type ); entry:= type[2].DisplayGroup( r ); if IsString( entry ) then entry:= [ entry ]; fi; entry:= [ [ String( r.repnr ), ":" ], [ entry[1], "" ], entry{ [ 2 .. Length( entry ) ] } ]; if not IsString( r.identifier[1] ) then entry[2][2]:= AtlasOfGroupRepresentationsInfo.markprivate; fi; if 1 < Length( stdavail ) then Add( entry, [ ", w.r.t. std. gen. ", String( r.standardization ) ] ); fi; Add( list, entry ); od; return rec( header := header, list := list ); end; ############################################################################# ## #F AGR.StringAtlasInfoGroup( <conditions> ) ## ## Deal with the detailed overview for one group. ## AGR.StringAtlasInfoGroup:= function( conditions ) local result, screenwidth, inforeps, list, line, len1, len2, indent, underline, i, prefix, entry, infoprgs, j; result:= []; screenwidth:= SizeScreen()[1] - 1; # `DisplayAtlasInfo( <gapname>[, <std>][, <conditions>] )' inforeps:= AGR.InfoReps( conditions ); if not IsEmpty( inforeps.list ) then list:= List( inforeps.list, line -> Concatenation( [ Concatenation( line[1] ), Concatenation( line[2] ) ], Concatenation( line{ [ 3 .. Length( line ) ] } ) ) ); len1:= Maximum( List( list, x -> WidthUTF8String( x[1] ) ) ); len2:= Maximum( List( list, x -> WidthUTF8String( x[2] ) ) ); indent:= 0; line:= Concatenation( inforeps.header{ [ 1 .. 3 ] } ); if AGR.ShowOnlyASCII() then underline:= RepeatedString( "-", Sum( List( inforeps.header{ [ 1 .. 3 ] }, Length ) ) ); else underline:= RepeatedUTF8String( "─", Sum( List( inforeps.header{ [ 1 .. 3 ] }, Length ) ) ); fi; for i in [ 4 .. Length( inforeps.header ) ] do if WidthUTF8String( line ) + WidthUTF8String( inforeps.header[i] ) >= screenwidth and WidthUTF8String( line ) <> indent then Add( result, line ); Add( result, underline ); underline:= ""; line:= ""; fi; Append( line, inforeps.header[i] ); od; if line <> "" then Add( result, line ); fi; if underline <> "" then Add( result, underline ); fi; indent:= len1 + len2 + 2; if indent >= screenwidth then indent:= 1; fi; prefix:= RepeatedString( " ", indent ); for entry in list do # right-aligned number, left-aligned description line:= Concatenation( String( entry[1], len1 ), " ", entry[2], RepeatedString( " ", len2 - WidthUTF8String( entry[2] ) ), " " ); for i in [ 3 .. Length( entry ) ] do if WidthUTF8String( line ) + WidthUTF8String( entry[i] ) >= screenwidth and Length( line ) <> indent then Add( result, line ); line:= ShallowCopy( prefix ); fi; Append( line, entry[i] ); od; Add( result, line ); od; fi; # `DisplayAtlasInfo( <gapname>[, <std>][, IsStraightLineProgram] )' infoprgs:= AGR.InfoPrgs( conditions ); if ForAny( infoprgs.list, x -> not IsEmpty( x ) ) then if IsBound( inforeps ) and not IsEmpty( inforeps.list ) then Add( result, "" ); fi; indent:= 0; line:= Concatenation( infoprgs.header{ [ 1 .. 3 ] } ); if AGR.ShowOnlyASCII() then underline:= RepeatedString( "-", Sum( List( infoprgs.header{ [ 1 .. 3 ] }, Length ) ) ); else underline:= RepeatedUTF8String( "─", Sum( List( infoprgs.header{ [ 1 .. 3 ] }, Length ) ) ); fi; for i in [ 4 .. Length( infoprgs.header ) ] do if WidthUTF8String( line ) + WidthUTF8String( infoprgs.header[i] ) >= screenwidth and WidthUTF8String( line ) <> indent then Add( result, line ); Add( result, underline ); underline:= ""; line:= ""; fi; Append( line, infoprgs.header[i] ); od; if line <> "" then Add( result, line ); fi; if underline <> "" then Add( result, underline ); fi; for i in infoprgs.list do if not IsEmpty( i ) then if Length( i ) = 1 then Add( result, i[1] ); else Add( result, Concatenation( i[1], ":" ) ); for j in [ 2 .. Length( i ) ] do Add( result, Concatenation( " ", i[j] ) ); od; fi; fi; od; fi; return result; end; ############################################################################# ## #F DisplayAtlasInfo( [<listofnames>][,][<std>][,]["contents", <sourcesid>] #F [, IsPermGroup[, true]] #F [, NrMovedPoints, <n>] #F [, IsMatrixGroup[, true]] #F [, Characteristic, <p>][, Dimension, <n>] #F [, Position, <n>] #F [, Character, <chi>] #F [, Identifier, <id>] ) #F DisplayAtlasInfo( <gapname>[, <std>][, "contents", <sourcesid>] #F [, IsPermGroup[, true]] #F [, NrMovedPoints, <n>] #F [, IsMatrixGroup[, true]] #F [, Characteristic, <p>][, Dimension, <n>] #F [, Position, <n>] #F [, Character, <chi>] #F [, Identifier, <id>] #F [, IsStraightLineProgram[, true]] ) ## InstallGlobalFunction( DisplayAtlasInfo, function( arg ) local result, width; # Distinguish the summary overview for at least one group # from the detailed overview for exactly one group. if Length( arg ) = 0 then result:= AGR.StringAtlasInfoOverview( "all", arg ); elif IsList( arg[1] ) and ForAll( arg[1], IsString ) then result:= AGR.StringAtlasInfoOverview( arg[1], arg{ [ 2 .. Length( arg ) ] } ); elif not IsString( arg[1] ) or arg[1] = "contents" then result:= AGR.StringAtlasInfoOverview( "all", arg ); else result:= AGR.StringAtlasInfoGroup( arg ); fi; width:= SizeScreen()[1] - 2; result:= List( result, l -> InitialSubstringUTF8StringWithSuffix( l, width, "*" ) ); Add( result, "" ); AtlasOfGroupRepresentationsInfo.displayFunction( JoinStringsWithSeparator( result, "\n" ) ); end ); ############################################################################# ## #F AtlasGenerators( <gapname>, <repnr>[, <maxnr>] ) #F AtlasGenerators( <identifier> ) ## ## <identifier> is a list containing at the first position the string ## <gapname>, ## at the second position a string or a list of strings ## (describing filenames), ## at the third position a positive integer denoting the standardization of ## the representation, ## at the fourth position a positive integer describing the common ring of ## the generators, ## and at the fifth position, if bound, a positive integer denoting the ## number of the maximal subgroup to which the representation is restricted. ## InstallGlobalFunction( AtlasGenerators, function( arg ) local tocs, identifier, gapname, prefix, groupname, maxnr, file, repnr, res, type, j, toc, record, pos, try, gens, name, gen, result, prog, repname; tocs:= AGR.TablesOfContents( "all" ); if Length( arg ) = 1 then # `AtlasGenerators( <identifier> )' identifier:= arg[1]; if IsRecord( identifier ) and IsBound( identifier.identifier ) then identifier:= identifier.identifier; fi; gapname:= identifier[1]; if Length( gapname ) = 2 and IsString( gapname[1] ) then # file in a private directory prefix:= gapname[1]; gapname:= gapname[2]; else prefix:= "datagens"; fi; groupname:= AGR.InfoForName( gapname ); if IsBound( identifier[5] ) then maxnr:= identifier[5]; fi; file:= identifier[2]; if not IsString( file ) then file:= file[1]; fi; # Compute the type, and the current number of the representation. repnr:= 0; res:= false; for type in AGR.DataTypes( "rep" ) do for toc in tocs do if IsBound( toc.( groupname[2] ) ) then record:= toc.( groupname[2] ); if IsBound( record.( type[1] ) ) then pos:= PositionProperty( record.( type[1] ), entry -> entry[ Length( entry ) ] = identifier[2] ); if pos = fail then repnr:= repnr + Length( record.( type[1] ) ); else repnr:= repnr + pos; res:= true; break; fi; fi; fi; od; if res then break; fi; od; if not res then return fail; fi; elif ( Length( arg ) = 2 and IsString( arg[1] ) and IsPosInt( arg[2] ) ) or ( Length( arg ) = 3 and IsString( arg[1] ) and IsPosInt( arg[2] ) and IsPosInt( arg[3] ) ) then # `AtlasGenerators( <gapname>, <repnr>[, <maxnr>] )' gapname:= arg[1]; groupname:= AGR.InfoForName( gapname ); if groupname = fail then Info( InfoAtlasRep, 1, "AtlasGenerators: no group with GAP name `", gapname, "'" ); return fail; fi; try:= function( repnr, type ) local j, toc, record; for j in [ 1 .. Length( tocs ) ] do toc:= tocs[j]; if IsBound( toc.( groupname[2] ) ) then record:= toc.( groupname[2] ); if IsBound( record.( type ) ) then if repnr <= Length( record.( type ) ) then return [ j, record.( type )[ repnr ] ]; fi; repnr:= repnr - Length( record.( type ) ); fi; fi; od; return repnr; end; repnr:= arg[2]; res:= repnr; for type in AGR.DataTypes( "rep" ) do res:= try( res, type[1] ); if not IsInt( res ) then break; fi; od; if IsInt( res ) then return fail; fi; if res[1] = 1 then prefix:= "datagens"; else prefix:= AtlasOfGroupRepresentationsInfo.private[ res[1]-1 ][2]; fi; res:= res[2]; identifier:= [ gapname, res[ Length( res) ], res[1], res[2] ]; if prefix <> "datagens" then identifier[1]:= [ prefix, gapname ]; fi; if IsBound( arg[3] ) then maxnr:= arg[3]; identifier[5]:= maxnr; fi; else Error( "usage: AtlasGenerators( <gapname>,<repnr>[,<maxnr>] ) or\n", " AtlasGenerators( <identifier> )" ); fi; # Access the data file(s). gens:= AGR.FileContents( prefix, groupname[2], identifier[2], type ); if gens = fail then return fail; fi; result:= rec( generators := gens, standardization := identifier[3], repnr := repnr, identifier := identifier ); if IsBound( maxnr ) then # Compute the straight line program for the restriction # (w.r.t. the correct standardization). prog:= AtlasProgram( gapname, identifier[3], maxnr ); if prog = fail then return fail; fi; # Evaluate the straight line program. result.generators:= ResultOfStraightLineProgram( prog.program, gens ); # Add info. if IsBound( groupname[3].sizesMaxes ) and IsBound( groupname[3].sizesMaxes[ maxnr ] ) then result.size:= groupname[3].sizesMaxes[ maxnr ]; fi; if IsBound( groupname[3].structureMaxes ) and IsBound( groupname[3].structureMaxes[ maxnr ] ) then result.groupname:= groupname[3].structureMaxes[ maxnr ]; fi; else # Add info. repname:= identifier[2]; if not IsString( repname ) then repname:= repname[1]; fi; repname:= repname{ [ 1 .. Position( repname, '.' )-1 ] }; result.groupname:= gapname; result.repname:= repname; result.type:= type[1]; type[2].AddDescribingComponents( result, type ); if IsBound( groupname[3].size ) then result.size:= groupname[3].size; fi; fi; # Return the result. return Immutable( result ); end ); ############################################################################# ## #F AGR.MergedTableOfContents( <tocid>, <gapname> ) ## ## `AGR.MergedTableOfContents' returns a list of the known representations ## for the group with name <gapname>. ## This list is sorted by types and for each type by its `SortTOCEntries' ## function. ## The list is cached in the component <gapname> of the global record ## `AtlasOfGroupRepresentationsInfo.TableOfContents.merged'. ## When a new table of contents is notified with ## `AtlasOfGroupRepresentationsNotifyPrivateDirectory' then the cache is ## cleared. ## AGR.MergedTableOfContents:= function( tocid, gapname ) local merged, label, groupname, result, tocs, type, typeresult, sortkeys, toc, record, id, i, repname, oneresult; merged:= AtlasOfGroupRepresentationsInfo.TableOfContents.merged; label:= Concatenation( tocid, "|", gapname ); if not IsBound( merged.( label ) ) then groupname:= AGR.InfoForName( gapname ); if groupname = fail then return []; fi; result:= []; # Loop over the relevant representations, sort them for each type. tocs:= AGR.TablesOfContents( [ "contents", tocid ] ); for type in AGR.DataTypes( "rep" ) do typeresult:= []; sortkeys:= []; for toc in tocs do if IsBound( toc.( groupname[2] ) ) then record:= toc.( groupname[2] ); if IsBound( record.( type[1] ) ) then if not IsBound( toc.diridPrivate ) then id:= gapname; else id:= [ toc.diridPrivate, gapname ]; fi; for i in record.( type[1] ) do repname:= i[ Length(i) ]; if not IsString( repname ) then repname:= repname[1]; fi; repname:= repname{ [ 1 .. Position( repname, '.' )-1 ] }; oneresult:= rec( groupname := gapname, identifier := [ id, i[ Length(i) ], i[1], i[2] ], repname := repname, standardization := i[1], type := type[1] ); type[2].AddDescribingComponents( oneresult, type ); Add( typeresult, oneresult ); Add( sortkeys, type[2].SortTOCEntries( i ) ); od; fi; fi; od; SortParallel( sortkeys, typeresult ); Append( result, typeresult ); od; if IsBound( groupname[3].size ) then for i in result do i.size:= groupname[3].size; od; fi; for i in [ 1 .. Length( result ) ] do result[i].repnr:= i; od; merged.( label ):= result; fi; return merged.( label ); end; ############################################################################# ## #F AGR.EvaluateCharacterCondition( <gapname>, <conditions>, <reps> ) ## ## Evaluate conditions involving `Character'. ## The list <conditions> is changed in place. ## The return value is a copy of <conditions> in which one occurrence of ## `Character' is replaced by the corresponding `Identifier' condition ## if this is known, ## or a nonempty string describing an info message otherwise. ## AGR.EvaluateCharacterCondition:= function( gapname, conditions, reps ) local pos, chi, len, i, map, tbl, p, dec, list, j, repname, newreps; # If `Character' does not occur then we need not work. pos:= Position( conditions, Character ); if pos = fail then return reps; elif pos = Length( conditions ) then return []; fi; map:= AtlasOfGroupRepresentationsInfo.characterinfo; if not IsBound( map.( gapname ) ) then Info( InfoAtlasRep, 1, "no character information for ", gapname, " known" ); return []; fi; map:= map.( gapname ); tbl:= CharacterTable( gapname ); if tbl = fail then Info( InfoAtlasRep, 1, "no character table for ", gapname, " known" ); return []; fi; chi:= conditions[ pos+1 ]; # Remove the entries from `conditions'. len:= Length( conditions ); for i in [ pos .. Length( conditions )-2 ] do conditions[i]:= conditions[ i+2 ]; od; Unbind( conditions[ len ] ); Unbind( conditions[ len-1 ] ); # Check whether `Characteristic' is specified. pos:= Position( conditions, Characteristic ); if pos = fail then p:= "?"; elif pos = Length( conditions ) then return []; else p:= conditions[ pos+1 ]; if not ( p = 0 or IsPosInt( p ) ) then return []; fi; fi; # Interpret the character. if IsClassFunction( chi ) then # the character is explicitly given if p = "?" then p:= UnderlyingCharacteristic( UnderlyingCharacterTable( chi ) ); elif p <> UnderlyingCharacteristic( UnderlyingCharacterTable( chi ) ) then return []; elif p <> 0 then tbl:= tbl mod p; fi; else if p = "?" then p:= 0; elif p <> 0 then tbl:= tbl mod p; fi; if IsPosInt( chi ) and chi <= NrConjugacyClasses( tbl ) then # the `chi'-th irreducible character in characteristic `p' chi:= Irr( tbl )[ chi ]; elif IsString( chi ) then # the character is irreducible and specified by its name, # as defined by `AtlasCharacterNames'. chi:= Position( AtlasCharacterNames( tbl ), chi ); if chi = fail then return []; fi; chi:= Irr( tbl )[ chi ]; else return []; fi; fi; if Identifier( UnderlyingCharacterTable( chi ) ) <> Identifier( tbl ) then return []; fi; # Check whether character information for the given type is stored. if p = 0 and IsBound( map[1] ) then map:= map[1]; elif IsPosInt( p ) and IsBound( map[p] ) then if tbl = fail then Info( InfoAtlasRep, 1, "no ", p, "-modular character table for ", gapname, " known" ); return []; fi; map:= map[p]; else Info( InfoAtlasRep, 1, "no character information for ", gapname, " in characteristic ", p, " known" ); return []; fi; # Look for the character. if p = 0 then dec:= MatScalarProducts( tbl, Irr( tbl ), [ chi ] )[1]; else dec:= Decomposition( Irr( tbl ), [ chi ], "nonnegative" )[1]; fi; if dec = fail or not ForAll( dec, x -> IsInt( x ) and 0 <= x ) then Info( InfoAtlasRep, 1, "character does not decompose properly" ); return []; fi; list:= []; for i in [ 1 .. Length( dec ) ] do if dec[i] = 1 then Add( list, i ); elif 1 < dec[i] then Add( list, [ i, dec[i] ] ); fi; od; if Length( list ) = 1 then list:= list[1]; fi; pos:= Position( map[1], list ); if pos = fail then Info( InfoAtlasRep, 1, "character not found" ); return []; fi; # We have found the character. repname:= map[2][ pos ]; return Filtered( reps, r -> r.repname = repname ); end; ############################################################################# ## #F AGR.AtlasGeneratingSetInfo( <conditions>, "one" ) #F AGR.AtlasGeneratingSetInfo( <conditions>, "all" ) #F AGR.AtlasGeneratingSetInfo( <conditions>, <types> ) ## ## This function does the work for `OneAtlasGeneratingSetInfo', ## `AllAtlasGeneratingSetInfos', and `AGR.InfoReps'. ## The first entry in <conditions> can be a group name ## or a list of group names. ## AGR.AtlasGeneratingSetInfo:= function( conditions, mode ) local pos, tocid, gapnames, types, std, position, result, gapname, reps, cond, info, type; pos:= Position( conditions, "contents" ); if pos <> fail then tocid:= conditions[ pos+1 ]; conditions:= Concatenation( conditions{ [ 1 .. pos-1 ] }, conditions{ [ pos+2 .. Length( conditions ) ] } ); else tocid:= "all"; fi; # The first argument (if there is one) is a group name, # or a list of group names, # or an integer (denoting a standardization), # or a function (denoting the first condition). if Length( conditions ) = 0 or IsInt( conditions[1] ) or IsFunction( conditions[1] ) then # The group is not restricted. gapnames:= List( AtlasOfGroupRepresentationsInfo.GAPnamesSortDisp, pair -> pair[1] ); elif IsString( conditions[1] ) then # Only one group is considered. gapnames:= [ AGR.GAPName( conditions[1] ) ]; conditions:= conditions{ [ 2 .. Length( conditions ) ] }; elif IsList( conditions[1] ) and ForAll( conditions[1], IsString ) then # A list of group names is prescribed. gapnames:= List( conditions[1], AGR.GAPName ); conditions:= conditions{ [ 2 .. Length( conditions ) ] }; else Error( "invalid first argument ", conditions[1] ); fi; types:= AGR.DataTypes( "rep" ); # Deal with a prescribed standardization. if 1 <= Length( conditions ) and ( IsPosInt( conditions[1] ) or IsList( conditions[1] ) ) then std:= conditions[1]; if IsPosInt( std ) then std:= [ std ]; fi; conditions:= conditions{ [ 2 .. Length( conditions ) ] }; else std:= true; fi; # Deal with a prescribed representation number. pos:= Position( conditions, Position ); if pos <> fail then if pos = Length( conditions ) or not IsPosInt( conditions[ pos+1 ] ) then Error( "condition `Position' must be followed by a pos. integer" ); fi; position:= conditions[ pos+1 ]; conditions:= Concatenation( conditions{ [ 1 .. pos-1 ] }, conditions{ [ pos+2 .. Length( conditions ) ] } ); fi; result:= []; for gapname in gapnames do reps:= AGR.MergedTableOfContents( tocid, gapname ); # Evaluate the `Position' condition. if pos <> fail then if position <= Length( reps ) then reps:= [ reps[ position ] ]; else reps:= []; fi; fi; cond:= ShallowCopy( conditions ); # Evaluate conditions involving `"minimal"' (modify `cond' in place). if AGR.EvaluateMinimalityCondition( gapname, cond ) then # Evaluate the `Character' condition. if Character in cond then reps:= AGR.EvaluateCharacterCondition( gapname, cond, reps ); fi; # Loop over the relevant representations. for info in reps do type:= First( types, t -> t[1] = info.type ); if ( std = true or info.standardization in std ) and type[2].AccessGroupCondition( info, ShallowCopy( cond ) ) then if mode = "one" then return info; else Add( result, info ); fi; fi; od; fi; od; # We have checked all available representations. if mode = "one" then return fail; else return result; fi; end; ############################################################################# ## #F OneAtlasGeneratingSetInfo( [<gapname>][, <std>] ) #F OneAtlasGeneratingSetInfo( [<gapname>][, <std>], IsPermGroup[, true] ) #F OneAtlasGeneratingSetInfo( [<gapname>][, <std>], NrMovedPoints, <n> ) #F OneAtlasGeneratingSetInfo( [<gapname>][, <std>], IsMatrixGroup[, true] ) #F OneAtlasGeneratingSetInfo( [<gapname>][, <std>][, Characteristic, <p>] #F [, Dimension, <m>] ) #F OneAtlasGeneratingSetInfo( [<gapname>][, <std>][, Ring, <R>] #F [, Dimension, <m>] ) #F OneAtlasGeneratingSetInfo( [<gapname>,][ <std>,] Position, <n> ) ## InstallGlobalFunction( OneAtlasGeneratingSetInfo, function( arg ) return AGR.AtlasGeneratingSetInfo( arg, "one" ); end ); ############################################################################# ## #F AllAtlasGeneratingSetInfos( [<gapname>][, <std>] ) #F AllAtlasGeneratingSetInfos( [<gapname>][, <std>], IsPermGroup[, true] ) #F AllAtlasGeneratingSetInfos( [<gapname>][, <std>], NrMovedPoints, <n> ) #F AllAtlasGeneratingSetInfos( [<gapname>][, <std>], IsMatrixGroup[, true] ) #F AllAtlasGeneratingSetInfos( [<gapname>][, <std>][, Characteristic, <p>] #F [, Dimension, <m>] ) #F AllAtlasGeneratingSetInfos( [<gapname>][, <std>][, Ring, <R>] #F [, Dimension, <m>] ) ## InstallGlobalFunction( AllAtlasGeneratingSetInfos, function( arg ) return AGR.AtlasGeneratingSetInfo( arg, "all" ); end ); ############################################################################# ## #F AtlasGroup( [<gapname>[, <std>]] ) #F AtlasGroup( [<gapname>[, <std>]], IsPermGroup[, true] ) #F AtlasGroup( [<gapname>[, <std>]], NrMovedPoints, <n> ) #F AtlasGroup( [<gapname>[, <std>]], IsMatrixGroup[, true] ) #F AtlasGroup( [<gapname>[, <std>]][, Characteristic, <p>] #F [, Dimension, <m>] ) #F AtlasGroup( [<gapname>[, <std>]][, Ring, <R>][, Dimension, <m>] ) #F AtlasGroup( [<gapname>[, <std>]], Position, <n> ) #F AtlasGroup( <identifier> ) ## InstallGlobalFunction( AtlasGroup, function( arg ) local info, gens, result; if Length( arg ) = 1 and IsRecord( arg[1] ) then info:= arg[1]; elif Length( arg ) = 1 and IsList( arg[1] ) and not IsString( arg[1] ) then info:= rec( identifier:= arg[1] ); else info:= CallFuncList( OneAtlasGeneratingSetInfo, arg ); fi; if info <> fail then gens:= AtlasGenerators( info.identifier ); if gens <> fail then result:= GroupWithGenerators( gens.generators ); if IsBound( gens.size ) then SetSize( result, gens.size ); SetAtlasRepInfoRecord( result, info ); fi; return result; fi; fi; return fail; end ); ############################################################################# ## #F AtlasSubgroup( <gapname>[, <std>], <maxnr> ) #F AtlasSubgroup( <gapname>[, <std>], IsPermGroup[, true], <maxnr> ) #F AtlasSubgroup( <gapname>[, <std>], NrMovedPoints, <n>, <maxnr> ) #F AtlasSubgroup( <gapname>[, <std>], IsMatrixGroup[, true], <maxnr> ) #F AtlasSubgroup( <gapname>[, <std>][, Characteristic, <p>] #F [, Dimension, <m>], <maxnr> ) #F AtlasSubgroup( <gapname>[, <std>][, Ring, <R>] #F [, Dimension, <m>], <maxnr> ) #F AtlasSubgroup( <gapname>[, <std>], Position, <n>, <maxnr> ) #F AtlasSubgroup( <G>, <maxnr> ) #F AtlasSubgroup( <identifier>, <maxnr> ) ## InstallGlobalFunction( AtlasSubgroup, function( arg ) local maxnr, info, groupname, std, prog, result, inforec; maxnr:= arg[ Length( arg ) ]; if not IsPosInt( maxnr ) then Error( "<maxnr> must be a positive integer" ); fi; if Length( arg ) = 2 and IsRecord( arg[1] ) then info:= arg[1]; groupname:= info.groupname; elif Length( arg ) = 2 and IsGroup( arg[1] ) then if not HasAtlasRepInfoRecord( arg[1] ) then Error( "the `AtlasRepInfoRecord' value is not set for the group" ); fi; info:= AtlasRepInfoRecord( arg[1] ); groupname:= info.groupname; elif Length( arg ) = 2 and IsList( arg[1] ) and not IsString( arg[1] ) then info:= rec( identifier:= arg[1], standardization:= arg[1][3] ); groupname:= arg[1][1]; elif 1 < Length( arg ) then info:= CallFuncList( OneAtlasGeneratingSetInfo, arg{ [ 1 .. Length( arg ) - 1 ] } ); groupname:= arg[1]; else info:= fail; fi; if info = fail then return fail; fi; std:= info.standardization; prog:= AtlasProgram( groupname, std, "maxes", maxnr ); if prog = fail then return fail; fi; if Length( arg ) = 2 and IsGroup( arg[1] ) then # We need not load the generators from files. result:= GroupWithGenerators( ResultOfStraightLineProgram( prog.program, GeneratorsOfGroup( arg[1] ) ) ); else result:= AtlasGenerators( info.identifier ); if result = fail then return fail; fi; result:= GroupWithGenerators( ResultOfStraightLineProgram( prog.program, result.generators ) ); fi; if IsBound( prog.size ) then SetSize( result, prog.size ); fi; inforec:= rec( identifier:= Concatenation( info.identifier, [ maxnr ] ), standardization:= info.standardization ); if IsBound( info.repnr ) then inforec.repnr:= info.repnr; fi; if IsBound( prog.subgroupname ) then inforec.groupname:= prog.subgroupname; fi; if IsBound( prog.size ) then inforec.size:= prog.size; fi; SetAtlasRepInfoRecord( result, inforec ); return result; end ); ############################################################################# ## #F AtlasProgramInfo( <gapname>[, <std>][, "maxes"], <maxnr> ) #F AtlasProgramInfo( <gapname>[, <std>], "classes" ) #F AtlasProgramInfo( <gapname>[, <std>], "cyclic" ) #F AtlasProgramInfo( <gapname>[, <std>], "automorphism", <autname> ) #F AtlasProgramInfo( <gapname>[, <std>], "check" ) #F AtlasProgramInfo( <gapname>[, <std>], "pres" ) #F AtlasProgramInfo( <gapname>[, <std>], "find" ) #F AtlasProgramInfo( <gapname>, <std>, "restandardize", <std2> ) #F AtlasProgramInfo( <gapname>[, <std>], "other", <descr> ) ## ## (Also the argument pair [, "contents", <sources> ] is supported.) ## InstallGlobalFunction( AtlasProgramInfo, function( arg ) local identifier, gapname, prefix, groupname, type, result, std, argpos, conditions, tocs, toc, record, id; if Length( arg ) = 1 then # `AtlasProgramInfo( <identifier> )' identifier:= arg[1]; gapname:= identifier[1]; if Length( gapname ) = 2 and IsString( gapname[1] ) then prefix:= gapname[1]; gapname:= gapname[2]; else prefix:= "dataword"; fi; groupname:= AGR.InfoForName( gapname ); if groupname = fail then return fail; fi; for type in AGR.DataTypes( "prg" ) do result:= type[2].AtlasProgramInfo( type, identifier, prefix, groupname[2] ); if result <> fail then result.groupname:= gapname; return Immutable( result ); fi; od; return fail; elif Length( arg ) = 0 or not IsString( arg[1] ) then Error( "the first argument must be the GAP name of a group" ); fi; # Now handle the cases of more than one argument. gapname:= arg[1]; groupname:= AGR.InfoForName( gapname ); if groupname = fail then Info( InfoAtlasRep, 1, "AtlasProgramInfo: no group with GAP name `", gapname, "'" ); return fail; fi; if IsInt( arg[2] ) and 2 < Length( arg ) then std:= [ arg[2] ]; argpos:= 3; else std:= true; argpos:= 2; fi; conditions:= arg{ [ argpos .. Length( arg ) ] }; # Restrict to a prescribed selection of tables of contents. tocs:= AGR.TablesOfContents( conditions ); # `AtlasProgramInfo( <gapname>[, <std>][, "maxes"], <maxnr> )' if Length( conditions ) = 1 and IsInt( conditions[1] ) then conditions:= [ "maxes", conditions[1] ]; fi; for toc in tocs do if IsBound( toc.( groupname[2] ) ) then record:= toc.( groupname[2] ); for type in AGR.DataTypes( "prg" ) do id:= type[2].AccessPRG( record, std, conditions ); if id <> fail then # The table of contents provides a program as is required. if not IsBound( toc.diridPrivate ) then id:= Concatenation( [ groupname[1] ], id ); else id:= Concatenation( [ [ toc.diridPrivate, groupname[1] ] ], id ); fi; return AtlasProgramInfo( id ); fi; od; fi; od; # No program was found. Info( InfoAtlasRep, 2, "no program for conditions ", conditions, "\n", "#I of the group with GAP name `", groupname[1], "'" ); return fail; end ); ############################################################################# ## #F AtlasProgram( <gapname>[, <std>][, "maxes"], <maxnr> ) #F AtlasProgram( <gapname>[, <std>], "classes" ) #F AtlasProgram( <gapname>[, <std>], "cyclic" ) #F AtlasProgram( <gapname>[, <std>], "automorphism", <autname> ) #F AtlasProgram( <gapname>[, <std>], "check" ) #F AtlasProgram( <gapname>[, <std>], "pres" ) #F AtlasProgram( <gapname>[, <std>], "find" ) #F AtlasProgram( <gapname>, <std>, "restandardize", <std2> ) #F AtlasProgram( <gapname>[, <std>], "other", <descr> ) #F AtlasProgram( <identifier> ) ## ## <identifier> is a list containing at the first position the string ## <gapname>, ## at the second position a string or a list of strings ## (describing the filenames involved), ## and at the third position a positive integer denoting the standardization ## of the program. ## InstallGlobalFunction( AtlasProgram, function( arg ) local identifier, gapname, prefix, groupname, type, result, info; if Length( arg ) = 1 then # `AtlasProgram( <identifier> )' identifier:= arg[1]; gapname:= identifier[1]; if Length( gapname ) = 2 and IsString( gapname[1] ) then prefix:= gapname[1]; gapname:= gapname[2]; else prefix:= "dataword"; fi; groupname:= AGR.InfoForName( gapname ); if groupname = fail then return fail; fi; for type in AGR.DataTypes( "prg" ) do result:= type[2].AtlasProgram( type, identifier, prefix, groupname[2] ); if result <> fail then result.groupname:= groupname[1]; return Immutable( result ); fi; od; return fail; elif Length( arg ) = 0 or not IsString( arg[1] ) then Error( "the first argument must be the GAP name of a group" ); fi; # Now handle the cases of more than one argument. info:= CallFuncList( AtlasProgramInfo, arg ); if info = fail then return fail; fi; return AtlasProgram( info.identifier ); end ); ############################################################################# ## #F AtlasOfGroupRepresentationsUserParameters() ## InstallGlobalFunction( AtlasOfGroupRepresentationsUserParameters, function() local str, prefix, pair, r; str:= "access to remote data: "; if AtlasOfGroupRepresentationsInfo.remote then Append( str, "yes\n" ); else Append( str, "no\n" ); fi; prefix:= "servers: "; for pair in AtlasOfGroupRepresentationsInfo.servers do Append( str, prefix ); prefix:= " "; Append( str, pair[1] ); Append( str, "/" ); Append( str, pair[2] ); Append( str, "\n" ); od; Append( str, "access remote data: " ); if not IsBound( AtlasOfGroupRepresentationsInfo.wget ) or not AtlasOfGroupRepresentationsInfo.wget in [ true, false ] then Append( str, "via the IO package (preferred) or wget\n" ); elif AtlasOfGroupRepresentationsInfo.wget = true then Append( str, "only via wget\n" ); else Append( str, "only via the IO package\n" ); fi; Append( str, "compress data files: " ); if AtlasOfGroupRepresentationsInfo.compress then Append( str, "yes\n" ); else Append( str, "no\n" ); fi; Append( str, "display overviews via: " ); Append( str, NameFunction( AtlasOfGroupRepresentationsInfo.displayFunction ) ); Append( str, "\n" ); prefix:= "access functions: "; for r in Reversed( AtlasOfGroupRepresentationsInfo.accessFunctions ) do Append( str, prefix ); prefix:= " "; Append( str, r.description ); if r.active = true then Append( str, " [enabled]\n" ); else Append( str, " [disabled]\n" ); fi; od; Append( str, "read MeatAxe text files: " ); if IsBound( CMeatAxe.FastRead ) and CMeatAxe.FastRead = true then Append( str, "fast\n" ); else Append( str, "minimizing the space\n" ); fi; return str; end ); ############################################################################# ## #E