|
#############################################################################
##
#W itc.gi XGAP library Volkmar Felsch
#W Ludger Hippe
#W Joachim Neubueser
##
#Y Copyright 1999, Volkmar Felsch, Aachen, Germany
##
## This file contains the implementations for the Interactive Todd-Coxeter
## coset enumeration routines.
##
## *Note* that the comments may be partially outdated!
##
## This is Version 1.1 of March 2001
##
#############################################################################
##
## Declarations of representations:
##
#############################################################################
##
#R IsItcClassSheet . . . . . . . . representation for a list of gap classes
##
DeclareRepresentation( "IsItcClassSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"boxes",
"class",
"ctSheet" ],
IsGraphicSheet );
#############################################################################
##
#R IsItcCoincSheet . . . . . . . representation for a list of coincidences
##
DeclareRepresentation( "IsItcCoincSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"boxes",
"ctSheet",
"repSheets" ],
IsGraphicSheet );
#############################################################################
##
#R IsItcCosetTableSheet . . . . . . representation for graphic coset table
##
DeclareRepresentation( "IsItcCosetTableSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"alives",
"app",
"app1",
"backto",
"clear",
"coincSwitch",
"coincs",
"coiSheet",
"deducs",
"defaultLimit",
"defs",
"defSheet",
"digits",
"digitString1",
"digitString2",
"echo",
"felsch",
"fgens",
"fillgaps",
"fillrows",
"first",
"firstCol",
"firstDef",
"firstFree",
"fsgens",
"gaps",
"gapsStrategy",
"genNames",
"graphicTable",
"hlt",
"hltRow",
"infoLine",
"invcol",
"involutory",
"isActual",
"lastDef",
"lastFree",
"limit",
"line",
"mark",
"markDefs",
"marked",
"message",
"messageText",
"ncols",
"ndefs",
"newtab",
"next",
"nlines",
"normal",
"nrdel",
"oldtab",
"prev",
"quitt",
"relColumnNums",
"rels",
"relsGen",
"relSheet",
"relText",
"renumbered",
"repLists",
"reset",
"rtSheets",
"scroll",
"scrollby",
"scrollto",
"settingsSheet",
"shortCut",
"shortcut",
"showcoincs",
"showdefs",
"showgaps",
"showrels",
"showsubgrp",
"small",
"sortdefs",
"sorted",
"stSheets",
"subColumnNums",
"subgrp",
"subSheet",
"subText",
"table" ],
IsGraphicSheet );
#############################################################################
##
#R IsItcDefinitionsSheet . . . . . representation for a list of definitions
##
DeclareRepresentation( "IsItcDefinitionsSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"boxes",
"ctSheet" ],
IsGraphicSheet );
#############################################################################
##
#R IsItcGapSheet . . . . . . . representation for a list of gap class reps
##
DeclareRepresentation( "IsItcGapSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"boxes",
"ctSheet" ],
IsGraphicSheet );
#############################################################################
##
#R IsItcRelationTableSheet . . . . . . . representation for a relator table
##
DeclareRepresentation( "IsItcRelationTableSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"ctSheet",
"graphicTable",
"newtab",
"number",
"oldtab",
"vertical" ],
IsGraphicSheet );
#############################################################################
##
#R IsItcRelatorsSheet . . . . . . . . . representation for a relators sheet
##
DeclareRepresentation( "IsItcRelatorsSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"boxes",
"ctSheet" ],
IsGraphicSheet );
#############################################################################
##
#R IsItcSubgroupGeneratorsSheet . . representation for a subgroup gens sheet
##
DeclareRepresentation( "IsItcSubgroupGeneratorsSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"boxes",
"ctSheet" ],
IsGraphicSheet );
#############################################################################
##
#R IsItcSubgroupTableSheet . . representation for a subgroup generator table
##
DeclareRepresentation( "IsItcSubgroupTableSheet",
IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
IsGraphicSheetRep,
# we inherit those components from the sheet:
[ "name", "width", "height", "WindowId", "callbackName", "callbackFunc",
"menus", "gapMenu", "objects", "free", "DefaultsForGraphicObject",
"filenamePS",
# now our own components:
"ctSheet",
"graphicTable",
"newtab",
"number",
"oldtab",
"vertical" ],
IsGraphicSheet );
#############################################################################
#
# ItcClassSheetLeftPBDown( <classSheet>, <x>, <y> )
#
# installs the methods for the left pointer button in table of gaps of length
# one.
#
InstallGlobalFunction( ItcClassSheetLeftPBDown, function( classSheet, x, y )
local class, classSheets, coset, gaps, gen, i, ctSheet, ndefs;
# get some local variables
ctSheet := classSheet!.ctSheet;
gaps := ctSheet!.gaps;
classSheets := gaps[4];
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. Length( classSheet!.boxes ) ] do
if [x,y] in classSheet!.boxes[i] then
coset := classSheet!.class[i][1];
gen := classSheet!.class[i][2];
# echo the command
if ctSheet!.echo then
class := Position( classSheets, classSheet );
Print( ">> CLICK class ", class, " gap [ ", coset, ", ",
ctSheet!.genNames[gen], " ]\n" );
fi;
# get some local variables
ndefs := ctSheet!.ndefs;
# define a new coset
ItcFillCosetTableEntry( ctSheet, coset, gen );
# check for a fail because of insufficient table size
if ctSheet!.ndefs > ndefs then
# save the current state.
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
fi;
return;
fi;
od;
end );
#############################################################################
#
# ItcCoincSheetLeftPBDown( <coiSheet>, <x>, <y> )
#
# installs the methods for the left pointer button in the list of pending
# coincidences.
#
InstallGlobalFunction( ItcCoincSheetLeftPBDown, function( coiSheet, x, y )
local boxes, coincs, cos1, cos2, ctSheet, i, length, newtab, oldtab;
# get some local variables
ctSheet := coiSheet!.ctSheet;
boxes := coiSheet!.boxes;
length := Length( boxes );
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. length ] do
if [x,y] in boxes[i] then
# echo the command
if ctSheet!.echo then
coincs := ctSheet!.coincs;
cos1 := coincs[i][1];
cos2 := coincs[i][2];
Print( ">> CLICK coincidence ", cos1, " = ", cos2, "\n" );
fi;
# work off the i-th pending coincidence
ItcHandlePendingCoincidence( ctSheet, i );
# save the old state as new state
newtab := ctSheet!.oldtab;
oldtab := ctSheet!.newtab;
ctSheet!.newtab := newtab;
ctSheet!.oldtab := oldtab;
# make the current state the new state
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
return;
fi;
od;
end );
#############################################################################
#
# ItcCoincSheetRightPBDown( <coiSheet>, <x>, <y> )
#
# installs the methods for the right pointer button in the list of pending
# coincidences.
#
InstallGlobalFunction( ItcCoincSheetRightPBDown, function( coiSheet, x, y )
local boxes, charWidth, coincs, cos1, cos2, ctSheet, distance, height, i,
length, lineHeight, name, sheet, string, width;
# get some local variables
ctSheet := coiSheet!.ctSheet;
distance := ctSheet!.normal.distance;
lineHeight := ctSheet!.normal.lineHeight;
charWidth := ctSheet!.normal.charWidth;
boxes := coiSheet!.boxes;
length := Length( boxes );
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. length ] do
if [x,y] in boxes[i] then
# get some local variables
coincs := ctSheet!.coincs;
cos1 := coincs[i][1];
cos2 := coincs[i][2];
# echo the command
if ctSheet!.echo then
Print( ">> RIGHT CLICK coincidence ", cos1, " = ", cos2, "\n" );
fi;
# check if there is already a window for the rep of this coincidence
if IsBound( coiSheet!.repSheets[i] ) and
IsAlive( coiSheet!.repSheets[i] ) then
Close( coiSheet!.repSheets[i] );
else
# get the word string to be displayed
string := String( ItcRepresentativeCoset( ctSheet, cos1 ) *
ItcRepresentativeCoset( ctSheet, cos2 )^-1 );
# open a new graphic sheet
name := Concatenation( "Coinidence ", String( cos1 ), " = ",
String( cos2 ) );
width := Maximum( ( Length( string ) + 2 ) * charWidth,
WidthOfSheetName( name ) );
height := 3 * distance + lineHeight;
sheet := GraphicSheet( name, width, height );
# get the representative of cos1 * cos2^-1 and display it
sheet!.word := Text( sheet, FONTS.normal, charWidth, lineHeight,
string );
sheet!.ctSheet := ctSheet;
coiSheet!.repSheets[i] := sheet;
fi;
return;
fi;
od;
end );
#############################################################################
#
# ItcCosetTableSheetLeftPBDown( <ctSheet>, <x>, <y> )
#
# installs the callback for the left pointer button in the window
# 'Interactive Todd-Coxeter'.
#
InstallGlobalFunction( ItcCosetTableSheetLeftPBDown,
function( ctSheet, x, y )
local alives, coset, done, firstCol, graphicTable, i, j, line0, ncols,
newtab, ndefs, ndefs2, nlines, renumbered;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
if [x,y] in ctSheet!.felsch then
ItcFelsch( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.fillgaps then
ItcFillGaps( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.fillrows then
ItcFillRows( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.hlt then
ItcHLT( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.showdefs then
ItcShowDefs( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.showgaps then
ItcShowGaps( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.showrels then
ItcShowRels( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.showsubgrp then
ItcShowSubgrp( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.backto then
ItcBackTo( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.clear then
ItcClear( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.reset then
ItcReset( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.shortcut then
ItcShortCut( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.sortdefs then
ItcSortDefinitions( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.scrollto then
ItcScrollTo( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.scrollby then
ItcScrollBy( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.showcoincs then
ItcShowCoincs( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.mark then
ItcMarkCosets( ctSheet, 0, 0 );
elif [x,y] in ctSheet!.quitt then
ItcQuit( ctSheet, 0, 0 );
else
# get some local variables
firstCol := ctSheet!.firstCol;
graphicTable := ctSheet!.graphicTable;
newtab := ctSheet!.newtab;
ndefs := ctSheet!.ndefs;
ncols := ctSheet!.ncols;
nlines := ctSheet!.nlines;
renumbered := ctSheet!.renumbered;
alives := ctSheet!.alives;
line0 := renumbered[ctSheet!.first] - 1;
done := false;
for i in [ 1 .. nlines ] do
coset := alives[line0 + i];
for j in [ 1 .. ncols ] do
if [x,y] in graphicTable[i][j] and newtab[coset][j] <= 0 then
# echo the command
if ctSheet!.echo then
Print( ">> CLICK coset table entry [ ", coset, ", ",
ctSheet!.genNames[j], " ]\n" );
fi;
done := true;
# define a new coset in the specified coset table entry
ItcFillCosetTableEntry( ctSheet, coset, j );
# check for a fail because of insufficient table size
if ctSheet!.ndefs > ndefs then
# save the current state.
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
fi;
return;
fi;
od;
od;
if not done then
i := 0;
while i < nlines do
i := i + 1;
if [x,y] in firstCol[i] then
# echo the command
coset := alives[line0 + i];
if ctSheet!.echo then
Print( ">> CLICK coset table row ", coset, "\n" );
fi;
# loop over the entries of the row
j := 0;
while j < ncols do
j := j + 1;
if ctSheet!.table[j][coset] <= 0 then
# define a new coset
ndefs2 := ctSheet!.ndefs;
ItcFillCosetTableEntry( ctSheet, coset, j );
# check for a fail because of insufficient table size
if ctSheet!.ndefs = ndefs2 then
j := ncols;
else
# save the current state.
ItcExtractTable( ctSheet );
newtab := ctSheet!.newtab;
renumbered := ctSheet!.renumbered;
if ctSheet!.renumbered[coset] = 0 then
j := ncols;
fi;
fi;
fi;
od;
# check for a fail because of insufficient table size
if ctSheet!.ndefs > ndefs then
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
fi;
i := nlines;
fi;
od;
fi;
fi;
end );
#############################################################################
#
# ItcCosetTableSheetRightPBDown( <ctSheet>, <x>, <y> )
#
# installs the callback for the right pointer button in the window
# 'Interactive Todd-Coxeter'.
#
InstallGlobalFunction( ItcCosetTableSheetRightPBDown,
function( ctSheet, x, y )
local alives, classSheets, coset, firstCol, gaps, graphicTable, i, j, k,
line0, newtab, nlines, renumbered;
# get some local variables
renumbered := ctSheet!.renumbered;
line0 := renumbered[ctSheet!.first] - 1;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
if [x,y] in ctSheet!.showdefs then
ctSheet!.markDefs := not ctSheet!.markDefs;
if ctSheet!.markDefs then
# mark the definitions in the coset table
ItcRecolorDefs( ctSheet );
else
# recolor all table entries to unmark the definitons
ItcRecolorTableEntries( ctSheet );
fi;
return;
fi;
# get some local variables
firstCol := ctSheet!.firstCol;
graphicTable := ctSheet!.graphicTable;
newtab := ctSheet!.newtab;
nlines := ctSheet!.nlines;
alives := ctSheet!.alives;
# run througth the lines in the coset table sheet
for i in [ 1 .. nlines ] do
coset := alives[line0 + i];
# check if the line number has been clicked
if [x,y] in firstCol[i] then
# echo the command
if ctSheet!.echo then
Print( ">> RIGHT CLICK coset table row ", coset, "\n" );
fi;
# display the representative of thecorrespondingcoset and return
ItcDisplayDefinition( ctSheet, coset );
return;
fi;
# check if a proper entry in the line has been clicked
for j in [ 1 .. Length( graphicTable[i] ) ] do
if [x,y] in graphicTable[i][j] then
# echo the command
if ctSheet!.echo then
Print( ">> RIGHT CLICK coset table entry [ ", alives[line0 + i],
", ", ctSheet!.genNames[j], " ]\n" );
fi;
# check if the entry is a coset number
if newtab[coset][j] > 0 then
# display the representative of the corresponding coset
ItcDisplayDefinition( ctSheet, newtab[coset][j] );
# check if the entry represents a gap of length 1
elif newtab[coset][j] < 0 then
# get the class number of the gap of length 1
k := ItcNumberClassOfGaps( ctSheet, coset, j );
# update the correponding class sheet
gaps := ctSheet!.gaps;
classSheets := gaps[4];
if classSheets[k] <> 0 and IsAlive( classSheets[k] ) then
Close( classSheets[k] );
fi;
ItcOpenClassSheet( ctSheet, k );
fi;
return;
fi;
od;
od;
end );
#############################################################################
#
# ItcDefinitionsSheetPBDown( <defSheet>, <x>, <y> )
#
# installs the methods for the left or right pointer button in the Table of
# Definitions.
#
InstallGlobalFunction( ItcDefinitionsSheetPBDown, function( defSheet, x, y )
local alives, boxes, coset, ctSheet, def, defs, gen, i, inv, j, length,
line0, names, newtab, string;
# get some local variables
ctSheet := defSheet!.ctSheet;
boxes := defSheet!.boxes;
length := Length( boxes );
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. length ] do
if [x,y] in boxes[i] then
# get some local variables
names := ctSheet!.genNames;
defs := ctSheet!.defs;
alives := ctSheet!.alives;
newtab := ctSheet!.newtab;
line0 := ctSheet!.renumbered[ctSheet!.first] - 1;
coset := alives[line0 + i];
if coset = 1 then
string := "1 = 1";
else
def := defs[coset - 1];
gen := def[2];
inv := gen + 1 - 2 * ( ( gen + 1 ) mod 2 );
j := newtab[coset][inv];
string := Concatenation( String( coset ), " = ", String( j ),
" * ", names[gen] );
fi;
# echo the command
if ctSheet!.echo then
Print( ">> RIGHT CLICK definition ", string, "\n" );
fi;
# open (or close) a definition sheet and return
ItcDisplayDefinition( ctSheet, coset );
return;
fi;
od;
end );
#############################################################################
#
# ItcGapSheetLeftPBDown( <gapSheet>, <x>, <y> )
#
# installs the methods for the left pointer button in table of gaps of length
# one.
#
InstallGlobalFunction( ItcGapSheetLeftPBDown, function( gapSheet, x, y )
local coset, ctSheet, gen, i, ndefs, rep, reps;
# get some local variables
ctSheet := gapSheet!.ctSheet;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. Length( gapSheet!.boxes ) ] do
if [x,y] in gapSheet!.boxes[i] then
# echo the command
if ctSheet!.echo then
Print( ">> CLICK gaps class ", i, "\n" );
fi;
# get some local variables
reps := ctSheet!.gaps[1];
rep := reps[i];
coset := rep[2];
gen := rep[3];
ndefs := ctSheet!.ndefs;
# define a new coset
ItcFillCosetTableEntry( ctSheet, coset, gen );
# check for a fail because of insufficient table size
if ctSheet!.ndefs > ndefs then
# save the current state.
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
fi;
return;
fi;
od;
end );
#############################################################################
#
# ItcGapSheetRightPBDown( <gapSheet>, <x>, <y> )
#
# installs the methods for the left pointer button in table of gaps of length
# one.
#
InstallGlobalFunction( ItcGapSheetRightPBDown, function( gapSheet, x, y )
local classSheets, ctSheet, gaps, i;
# get some local variables
ctSheet := gapSheet!.ctSheet;
gaps := ctSheet!.gaps;
classSheets := gaps[4];
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. Length( gapSheet!.boxes ) ] do
if [x,y] in gapSheet!.boxes[i] then
# echo the command
if ctSheet!.echo then
Print( ">> RIGHT CLICK gaps class ", i, "\n" );
fi;
if classSheets[i] <> 0 and IsAlive( classSheets[i] ) then
Close( classSheets[i] );
else
ItcOpenClassSheet( ctSheet, i );
fi;
fi;
od;
end );
#############################################################################
#
# ItcRelationTableSheetLeftPBDown( <rtSheet>, <x>, <y> )
#
# installs the methods for the left pointer button in a relation table.
#
InstallGlobalFunction( ItcRelationTableSheetLeftPBDown, function(
rtSheet, x, y )
local alives, columns, coset, ctSheet, gen, graphicTable, i, invcol, j,
length, line0, ndefs, number, table;
# get some local variables
ctSheet := rtSheet!.ctSheet;
table := rtSheet!.newtab;
number := rtSheet!.number;
graphicTable := rtSheet!.graphicTable;
invcol := ctSheet!.invcol;
alives := ctSheet!.alives;
line0 := ctSheet!.renumbered[ctSheet!.first] - 1;
columns := ctSheet!.relColumnNums[number];
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. Length( graphicTable ) ] do
if IsBound( graphicTable[i] ) then
length := Length( graphicTable[i] );
for j in [ 1 .. length ] do
if [x,y] in graphicTable[i][j] then
if j = 1 or j = length then
# echo the command
coset := alives[line0 + i];
if ctSheet!.echo then
Print( ">> CLICK relation table ", number, " row ", coset,
"\n" );
fi;
# new definitions are not allowed if there are pending
# coincidences
if not ctSheet!.coincs = [] then
Relabel( ctSheet!.messageText,
"There are pending coincidences" );
ctSheet!.message := true;
return;
fi;
# fill the row
ItcFillTrace( ctSheet, coset, columns );
ItcDisplayCosetTable( ctSheet );
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
return;
elif table[i][j] > 0 then
return;
elif table[i][j-1] > 0 then
coset := table[i][j-1];
gen := columns[j-1];
elif table[i][j+1] <= 0 then
Relabel( ctSheet!.messageText, "This command has no effect" );
ctSheet!.message := true;
return;
else
coset := table[i][j+1];
gen := invcol[columns[j]];
fi;
# echo the command
if ctSheet!.echo then
Print( ">> CLICK relation table ", number, " row ",
alives[line0 + i], " entry [ ", coset, ", ",
ctSheet!.genNames[gen], " ]\n" );
fi;
ndefs := ctSheet!.ndefs;
ItcFillCosetTableEntry( ctSheet, coset, gen );
# check for a fail because of insufficient table size
if ctSheet!.ndefs > ndefs then
# save the current state.
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
fi;
return;
fi;
od;
fi;
od;
end );
#############################################################################
#
# ItcRelatorsSheetLeftPBDown( <relSheet>, <x>, <y> )
#
# installs the methods for the left pointer button in the window 'Relators'.
#
InstallGlobalFunction( ItcRelatorsSheetLeftPBDown, function( relSheet, x, y )
local boxes, ctSheet, i, rtSheets;
# get some local variables
boxes := relSheet!.boxes;
ctSheet := relSheet!.ctSheet;
rtSheets := ctSheet!.rtSheets;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. Length( boxes ) ] do
if [x,y] in boxes[i] then
# echo the command
if ctSheet!.echo then
Print( ">> CLICK relator ", i, "\n" );
fi;
if IsBound( rtSheets[i] ) and IsAlive( rtSheets[i] ) then
Close( rtSheets[i] );
else
ItcDisplayRelationTable( ctSheet, i );
fi;
fi;
od;
end );
#############################################################################
#
# ItcSubgroupGeneratorsSheetLeftPBDown( <subSheet>, <x>, <y> )
#
# installs the methods for the left pointer button in the window 'Subgroup
# gens'.
#
InstallGlobalFunction( ItcSubgroupGeneratorsSheetLeftPBDown,
function( subSheet, x, y )
local boxes, ctSheet, i, stSheets;
# get some local variables
boxes := subSheet!.boxes;
ctSheet := subSheet!.ctSheet;
stSheets := ctSheet!.stSheets;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. Length( boxes ) ] do
if [x,y] in boxes[i] then
# echo the command
if ctSheet!.echo then
Print( ">> CLICK subgroup generator ", i, "\n" );
fi;
if IsBound( stSheets[i] ) and IsAlive( stSheets[i] ) then
Close( stSheets[i] );
else
ItcDisplaySubgroupTable( ctSheet, i );
fi;
fi;
od;
end );
#############################################################################
#
# ItcSubgroupTableSheetLeftPBDown( <stSheet>, <x>, <y> )
#
# installs the methods for the left pointer button in a subgroup table.
#
InstallGlobalFunction( ItcSubgroupTableSheetLeftPBDown,
function( stSheet, x, y )
local alives, columns, coset, ctSheet, gen, graphicTable, i,invcol, j,
length, ndefs, number, table;
# get some local variables
ctSheet := stSheet!.ctSheet;
table := stSheet!.newtab;
number := stSheet!.number;
graphicTable := stSheet!.graphicTable;
invcol := ctSheet!.invcol;
alives := ctSheet!.alives;
columns := ctSheet!.subColumnNums[number];
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
for i in [ 1 .. Length( graphicTable ) ] do
if IsBound( graphicTable[i] ) then
length := Length( graphicTable[i] );
for j in [ 1 .. length ] do
if [x,y] in graphicTable[i][j] then
if j = 1 or j = length then
coset := alives[i];
if ctSheet!.echo then
Print( ">> CLICK subgroup table ", number, " row ", coset,
"\n" );
fi;
# new definitions are not allowed if there are pending
# coincidences
if not ctSheet!.coincs = [] then
Relabel( ctSheet!.messageText,
"There are pending coincidences" );
ctSheet!.message := true;
return;
fi;
# fill the row
ItcFillTrace( ctSheet, coset, columns );
ItcDisplayCosetTable( ctSheet );
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
return;
elif table[i][j] > 0 then
Relabel( ctSheet!.messageText, "This command has no effect" );
ctSheet!.message := true;
return;
elif table[i][j-1] > 0 then
coset := table[i][j-1];
gen := columns[j-1];
elif table[i][j+1] <= 0 then
return;
else
coset := table[i][j+1];
gen := invcol[columns[j]];
fi;
# echo the command
if ctSheet!.echo then
Print( ">> CLICK subgroup table ", number, " row ", alives[i],
" entry [ ", coset, ", ", ctSheet!.genNames[gen], " ]\n" );
fi;
ndefs := ctSheet!.ndefs;
ItcFillCosetTableEntry( ctSheet, coset, gen );
# check for a fail because of insufficient table size
if ctSheet!.ndefs > ndefs then
# save the current state.
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
fi;
return;
fi;
od;
fi;
od;
end );
#############################################################################
#
# ItcBackTo( <ctSheet>, <menu>, <entry> )
#
# is called by selecting the menu entry 'back to definition' or by clicking
# on the button 'back to'.
#
InstallGlobalFunction( ItcBackTo, function( ctSheet, menu, entry )
local coincSwitch, coset, defs, defSheet, echo, first, i, nargs, ndefs,
query, repLists, showDefs, steps, table;
# get some local variables
ndefs := ctSheet!.ndefs;
if ndefs = 1 then
return;
fi;
# select the number of steps to be canceled and select the definitions to
# be made
query := Query( Dialog( "OKcancel", "back to ..." ), String( ndefs - 1 ) );
# echo the command
if ctSheet!.echo then
Print( ">> BACK TO ", query, "\n" );
fi;
# return if the query has been canceled
if query = false then
return;
fi;
# evaluate the query string and check the arguments
query := ItcQuery( query );
nargs := Length( query );
if nargs = 0 or query = [ ndefs ] then
Relabel( ctSheet!.messageText, "This command has no effect" );
ctSheet!.message := true;
return;
fi;
steps := query[1];
if not IsInt( steps ) or steps > ndefs or steps <= -ndefs or nargs > 1
then
Relabel( ctSheet!.messageText, "Illegal argument" );
ctSheet!.message := true;
return;
fi;
if steps < 0 then
steps := ndefs + steps;
fi;
if steps = 1 then
# clear the coset table
ItcClearTable( ctSheet );
ctSheet!.hltRow := 1;
ctSheet!.marked := [];
ctSheet!.scroll := 20;
# display the coset table
ItcDisplayCosetTable( ctSheet );
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
return;
fi;
# save the current scroll position
first := ctSheet!.first;
# save the definitions and clear the table
defs := ctSheet!.defs{ [ 1 .. steps - 1 ] };
ndefs := Length( defs );
# save the coset representative sheets and the definitions table
repLists := ctSheet!.repLists;
ctSheet!.repLists := [ [], [] ];
showDefs := IsBound( ctSheet!.defSheet ) and IsAlive( ctSheet!.defSheet );
if showDefs then
defSheet := ctSheet!.defSheet;
Unbind( ctSheet!.defSheet );
fi;
# clear the coset table
ItcClearTable( ctSheet );
ctSheet!.hltRow := 1;
# switch on the automatic handling of coinicidences, if necessary
coincSwitch := ctSheet!.coincSwitch;
ctSheet!.coincSwitch := true;
# reconstruct and extract the table preceding the requested one
for i in [ 1 .. ndefs - 1 ] do
ItcFastCosetStepFill( ctSheet, defs[i][1], defs[i][2] );
od;
ItcExtractTable( ctSheet );
# reconstruct the requested table
i := ndefs;
ItcCosetStepFill( ctSheet, defs[i][1], defs[i][2] );
# reset the coincidences switch
ctSheet!.coincSwitch := coincSwitch;
# save the current state
ItcExtractTable( ctSheet );
ctSheet!.first := first;
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# reset the coset representative sheets and the definitions table
ctSheet!.repLists := repLists;
if showDefs then
ctSheet!.defSheet := defSheet;
ItcDisplayDefinitionsTable( ctSheet );
fi;
# update all active relator and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
end );
#############################################################################
#
# ItcChangeDefaultTableSize( <ctSheet>, <menu>, <entry> )
#
InstallGlobalFunction( ItcChangeDefaultTableSize,
function( ctSheet, menu, entry )
local defaultLimit, limit, nargs, ndefs, query, settingsSheet, string,
suggest;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
# find a suitable default value for the query
defaultLimit := ctSheet!.defaultLimit;
if defaultLimit = 1000 then
suggest := 2000;
else
suggest := 1000;
fi;
# initialize the default coset table size
query := Query( Dialog( "OKcancel", Concatenation(
"change default table size from ", String( defaultLimit ), " to" ) ),
String( suggest ) );
# echo the command
if ctSheet!.echo then
Print( ">> CHANGE DEFAULT TABLE SIZE TO ", query, "\n" );
fi;
# return if the query has been canceled
if query = false then
return;
fi;
# evaluate the query string and check the arguments
query := ItcQuery( query );
nargs := Length( query );
if nargs = 0 then
defaultLimit := 0;
else
defaultLimit := query[1];
if not IsInt( defaultLimit ) or defaultLimit <= 0 or nargs > 1 then
Relabel( ctSheet!.messageText, "Illegal argument" );
ctSheet!.message := true;
return;
fi;
fi;
# reset the default table size
ctSheet!.defaultLimit := defaultLimit;
# get some local variables
ndefs := ctSheet!.ndefs;
# if no enumeration has been started yet reinitialize the coset table
if ndefs = 1 then
limit := defaultLimit;
ctSheet!.limit := limit;
ctSheet!.defs := [];
ctSheet!.ndefs := 1;
ctSheet!.renumbered := [1];
ctSheet!.alives := [ [1], [1], [1] ];
ItcMakeDigitStrings( ctSheet );
ctSheet!.oldtab := ListWithIdenticalEntries( limit, 0 );
ctSheet!.newtab := ListWithIdenticalEntries( limit, 0 );
ItcInitializeParameters( ctSheet );
ItcEnableMenu( ctSheet );
fi;
# update the sheet of current settings
if IsBound( ctSheet!.settingsSheet ) and IsAlive( ctSheet!.settingsSheet )
then
settingsSheet := ctSheet!.settingsSheet;
FastUpdate( ctSheet, true );
string := Concatenation( "default table size ", String( defaultLimit ) );
Relabel( settingsSheet!.boxes[1], string );
string := Concatenation( "table size ", String( ctSheet!.limit ) );
Relabel( settingsSheet!.boxes[2], string );
FastUpdate( ctSheet, false );
fi;
end );
#############################################################################
#
# ItcChangeSettings( <ctSheet>, <menu>, <entry> )
#
# changes the settings.
#
InstallGlobalFunction( ItcChangeSettings, function( ctSheet, menu, entry )
local i, num, settingsSheet, showSettings, strategy, string;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
# get the entry
num := Position( menu!.entries, entry );
if num < 3 or num > 10 then
Error( "illegal arguments" );
fi;
showSettings := IsBound( ctSheet!.settingsSheet ) and
IsAlive( ctSheet!.settingsSheet );
if num = 3 then
# entry "coincidence handling off"
# --------------------------------
# echo the command
if ctSheet!.echo then
Print( ">> COINCIDENCE HANDLING OFF\n" );
fi;
# switch off the automatic handling of coincidences
ctSheet!.coincSwitch := false;
if showSettings then
i := 3;
string := "coincidence handling OFF";
fi;
ItcRelabelInfoLine( ctSheet );
elif num = 4 then
# entry "coincidence handling on"
# -------------------------------
# echo the command
if ctSheet!.echo then
Print( ">> COINCIDENCE HANDLING ON\n" );
fi;
# if there is a window 'pending coincidenes' close it
if IsBound( ctSheet!.coiSheet ) and IsAlive( ctSheet!.coiSheet ) then
ItcCloseSheets( ctSheet!.coiSheet!.repSheets );
Close( ctSheet!.coiSheet );
fi;
# switch on the automatic handling of coincidences
ctSheet!.coincSwitch := true;
if showSettings then
i := 3;
string := "coincidence handling ON";
fi;
ItcRelabelInfoLine( ctSheet );
# if there are pending coincidences reconstruct the table
if ctSheet!.coincs <> [] then
# reconstruct the preceding state
ItcExtractPrecedingTable( ctSheet );
# make the current state the new state
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
ItcEnableMenu( ctSheet );
fi;
elif num = 5 then
# entry "echo on"
# ---------------
# switch on the echo
ctSheet!.echo := true;
# echo the command
Print( ">> ECHO ON\n" );
if showSettings then
i := 4;
string := "echo ON";
fi;
elif num = 6 then
# entry "echo off"
# ----------------
# echo the command
if ctSheet!.echo then
Print( ">> ECHO OFF\n" );
fi;
# switch off the echo
ctSheet!.echo := false;
if showSettings then
i := 4;
string := "echo OFF";
fi;
else
# echo the command
strategy := num - 6;
if ctSheet!.echo then
Print( ">> GAPS STRATEGY ", strategy, "\n" );
fi;
# set the gaps strategy
ctSheet!.gapsStrategy := strategy;
if showSettings then
i := 5;
if strategy = 1 then
string := "gaps strategy 1 (first gap)";
elif strategy = 2 then
string := "gaps strategy 2 (first rep of max weight)";
elif strategy = 3 then
string := "gaps strategy 3 (last rep of max weight)";
fi;
fi;
fi;
# update the sheet of current settings
if showSettings then
settingsSheet := ctSheet!.settingsSheet;
FastUpdate( ctSheet, true );
Relabel( settingsSheet!.boxes[i], string );
FastUpdate( ctSheet, false );
fi;
ItcEnableMenu( ctSheet );
end );
#############################################################################
#
# ItcClassOfGaps( <ctSheet>, <n> )
#
# compute the n-th class of gaps of length 1.
#
InstallGlobalFunction( ItcClassOfGaps, function( ctSheet, n )
local class, classes, c, cos, entry, gaps, gen, i, involutory, j, length,
ncols, next, null, rep, reps, table;
# get the list of all classes of gaps of length 1
gaps := ItcGaps( ctSheet );
classes := gaps[2];
# check if the class is already available
if classes[n] <> 0 then
class := classes[n];
else
# get some local variables
involutory := ctSheet!.involutory;
next := ctSheet!.next;
table := ctSheet!.table;
ncols := ctSheet!.ncols;
null := ncols * Length( table[1] );
reps := gaps[1];
rep := reps[n];
length := rep[1];
cos := rep[2];
gen := rep[3];
# initialize the class
class := ListWithIdenticalEntries( length, 0 );
i := 1;
class[1] := [ cos, gen ];
if involutory[gen] = 2 then
gen := gen + 1;
i := 2;
class[2] := [ cos, gen ];
fi;
rep := ( cos -1 ) * ncols + gen;
# loop over the coset table and find all gaps of the class
while cos <> 0 do
while gen < ncols do
gen := gen + 1;
entry := - table[gen][cos];
if entry > 0 then
while entry < null and entry <> rep do
if entry <= 0 then
Error( "THIS IS A BUG (ITC 01), YOU SHOULD NEVER GET HERE" );
fi;
j := ( entry - 1 ) mod ncols + 1;
c := ( entry - j ) / ncols + 1;
entry := - table[j][c];
od;
if entry = rep then
# add the gap to the class
i := i + 1;
class[i] := [ cos, gen ];
fi;
fi;
od;
gen := 0;
cos := next[cos];
od;
if i <> length then
Error( "THIS IS A BUG (ITC 02), YOU SHOULD NEVER GET HERE" );
fi;
fi;
return class;
end );
#############################################################################
#
# ItcClear( <ctSheet>, <menu>, <entry> )
#
#
InstallGlobalFunction( ItcClear, function( ctSheet, menu, entry )
local i, limit, nsgens, nrels;
# get some local variables
nrels := Length( ctSheet!.rels );
nsgens := Length( ctSheet!.fsgens );
# echo the command
if ctSheet!.echo then
Print( ">> CLEAR\n" );
fi;
# reset the table size
limit := ctSheet!.defaultLimit;
ctSheet!.limit := limit;
# reinitialize some auxiliary lists
ItcMakeDigitStrings( ctSheet );
ctSheet!.newtab := ListWithIdenticalEntries( limit, 0 );
ctSheet!.oldtab := ListWithIdenticalEntries( limit, 0 );
# clear the coset table
ItcClearTable( ctSheet );
# close the definitions table
if IsBound( ctSheet!.defSheet ) and IsAlive( ctSheet!.defSheet ) then
ItcCloseSheets( ctSheet!.repLists[2] );
Close( ctSheet!.defSheet );
fi;
# close the relator tables
if IsBound( ctSheet!.rtSheets ) then
for i in [ 1 .. nrels ] do
if IsBound( ctSheet!.rtSheets[i] ) and
IsAlive( ctSheet!.rtSheets[i] ) then
Close( ctSheet!.rtSheets[i] );
fi;
od;
fi;
# close the subgroup generator tables
if IsBound( ctSheet!.stSheets ) then
if IsBound( ctSheet!.subSheet ) then
for i in [ 1 .. nsgens ] do
if IsBound( ctSheet!.stSheets[i] ) and
IsAlive( ctSheet!.stSheets[i] ) then
Close( ctSheet!.stSheets[i] );
fi;
od;
fi;
fi;
# reinitialize some parameters
ctSheet!.hltRow := 1;
ctSheet!.marked := [];
ctSheet!.scroll := 20;
ctSheet!.repLists := [ [], [] ];
# display the coset table
ItcDisplayCosetTable( ctSheet );
ItcEnableMenu( ctSheet );
end );
#############################################################################
#
# ItcClearTable( <ctSheet> )
#
InstallGlobalFunction( ItcClearTable, function( ctSheet )
local def, definitions, fsgens, nsgens, steps;
# get some local variables
fsgens := ctSheet!.fsgens;
nsgens := Length( fsgens );
# close the gaps of length 1 sheets if there are any
ItcCloseGapSheets( ctSheet );
# close the window 'pending coincidenes'
if IsBound( ctSheet!.coiSheet ) and IsAlive( ctSheet!.coiSheet ) then
ItcCloseSheets( ctSheet!.coiSheet!.repSheets );
Close( ctSheet!.coiSheet );
fi;
# set back the variables for the coset enumerations
ctSheet!.sorted := false;
ctSheet!.markDefs := false;
ctSheet!.coincs := [];
ctSheet!.deducs := [];
ctSheet!.defs := [];
ctSheet!.ndefs := 1;
ctSheet!.renumbered := [1];
ctSheet!.alives := [ [1], [1], [1] ];
ItcInitializeParameters( ctSheet );
end );
#############################################################################
#
# ItcCloseGapSheets( <ctSheet> )
#
# close the gaps of length 1 sheets if there are any
#
InstallGlobalFunction( ItcCloseGapSheets, function( ctSheet )
local i, classSheets, gaps, gapSheet, sheet;
gaps := ctSheet!.gaps;
if gaps <> 0 then
classSheets := gaps[4];
for sheet in classSheets do
if sheet <> 0 and IsAlive( sheet ) then
Close( sheet );
fi;
od;
gapSheet := gaps[3];
if gapSheet <> 0 and IsAlive( gapSheet ) then
Close( gapSheet );
fi;
fi;
end );
#############################################################################
#
# ItcCloseSheets( <list> )
#
# close all sheets in the given list.
#
InstallGlobalFunction( ItcCloseSheets, function( list )
local sheet;
for sheet in list do
if IsAlive( sheet ) then
Close( sheet );
fi;
od;
end );
#############################################################################
#
# ItcCloseTableFelsch( <ctSheet>, <menu>, <entry> )
#
# is called by selecting the menu entry 'close table By Felsch'.
#
InstallGlobalFunction( ItcCloseTableFelsch, function( ctSheet, menu, entry )
local count, limit, ndefs;
# if the coset table is already closed return
if ctSheet!.firstDef = 0 then
Relabel( ctSheet!.messageText, "The tables are closed" );
ctSheet!.message := true;
return;
fi;
# new definitions are not allowed if there are pending coincidences
if not ctSheet!.coincs = [] then
Relabel( ctSheet!.messageText, "There are pending coincidences" );
ctSheet!.message := true;
return;
fi;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
# echo the command
if ctSheet!.echo then
Print( ">> CLOSE Felsch\n" );
fi;
# initialize some local variables
limit := ctSheet!.limit;
count := 0;
# do the enumeration.
while ctSheet!.firstDef <> 0 and ctSheet!.coincs = [] do
# extend the table is necessary
ndefs := ctSheet!.ndefs;
if ndefs = limit then
ItcExtendTableSize( ctSheet, 0, 0 );
limit := ctSheet!.limit;
if ndefs = limit then
# insufficient table size: display a message and return
Relabel( ctSheet!.messageText, "Insufficient table size" );
ctSheet!.message := true;
return;
fi;
count := 0;
fi;
count := count + 1;
ItcFastCosetStepFelsch( ctSheet );
ItcRelabelInfoLine( ctSheet );
# check for a fail because of insufficient table size
if ctSheet!.ndefs = ndefs then
Error( "THIS IS A BUG (ITC 03), YOU SHOULD NEVER GET HERE" );
fi;
# if table has closed reconstruct the last preceding state.
if ctSheet!.firstDef = 0 and count > 1 or not ctSheet!.coincs = [] then
ItcExtractPrecedingTable( ctSheet );
fi;
od;
# save the current state.
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists(ctSheet);
# if there are pending coincidences display them
if not ctSheet!.coincs = [] then
ItcDisplayPendingCoincidences( ctSheet );
fi;
ItcEnableMenu( ctSheet );
end );
#############################################################################
#
# ItcCloseTableGaps( <ctSheet>, <menu>, <entry> )
#
# is called by selecting the menu entry 'close table using gaps'.
#
InstallGlobalFunction( ItcCloseTableGaps, function( ctSheet, menu, entry )
local count, first, limit, ndefs, pos, strategy;
# if the coset table is already closed return
if ctSheet!.firstDef = 0 then
Relabel( ctSheet!.messageText, "The tables are closed" );
ctSheet!.message := true;
return;
fi;
# new definitions are not allowed if there are pending coincidences
if not ctSheet!.coincs = [] then
Relabel( ctSheet!.messageText, "There are pending coincidences" );
ctSheet!.message := true;
return;
fi;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
# get the strategy
pos := Position( menu!.entries, entry );
if pos < 2 or pos > 5 then
Error( "illegal arguments" );
fi;
strategy := pos - 1;
# echo the command
if ctSheet!.echo then
Print( ">> CLOSE gaps ", strategy, "\n" );
fi;
# save the current scroll position
first := ctSheet!.first;
# initialize some local variables
limit := ctSheet!.limit;
count := 0;
# do the enumeration.
while ctSheet!.firstDef <> 0 and ctSheet!.coincs = [] do
# extend the table is necessary
ndefs := ctSheet!.ndefs;
if ndefs = limit then
ItcExtendTableSize( ctSheet, 0, 0 );
limit := ctSheet!.limit;
if ndefs = limit then
# insufficient table size: display a message and return
Relabel( ctSheet!.messageText, "Insufficient table size" );
ctSheet!.message := true;
return;
fi;
count := 0;
fi;
# define the next coset
count := count + 1;
pos := ItcFirstGapOfLengthOne( ctSheet, strategy );
if pos = fail then
ItcFastCosetStepFelsch( ctSheet );
else
ItcFastCosetStepFill( ctSheet, pos[1], pos[2] );
fi;
ItcRelabelInfoLine( ctSheet );
# check for a fail because of insufficient table size
if ctSheet!.ndefs = ndefs then
Error( "THIS IS A BUG (ITC 04), YOU SHOULD NEVER GET HERE" );
fi;
# if table has closed reconstruct the last preceding state.
if ctSheet!.firstDef = 0 and count > 1 or not ctSheet!.coincs = [] then
ItcExtractPrecedingTable( ctSheet );
fi;
od;
ctSheet!.first := first;
# save the current state.
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists(ctSheet);
# if there are pending coincidences display them
if not ctSheet!.coincs = [] then
ItcDisplayPendingCoincidences( ctSheet );
fi;
ItcEnableMenu( ctSheet );
end );
#############################################################################
#
# ItcCloseTableHLT( <ctSheet>, <menu>, <entry> )
#
# is called by selecting the menu entry 'close table by HLT'.
#
InstallGlobalFunction( ItcCloseTableHLT, function( ctSheet, menu, entry )
local coset, first, hlt, i, limit, maxdef, ndefs, nrels, nsgens, overflow,
relColumnNums, subColumnNums, subgrp;
# if the coset table is already closed return
if ctSheet!.firstDef = 0 then
Relabel( ctSheet!.messageText, "The tables are closed" );
ctSheet!.message := true;
return;
fi;
# new definitions are not allowed if there are pending coincidences
if not ctSheet!.coincs = [] then
Relabel( ctSheet!.messageText, "There are pending coincidences" );
ctSheet!.message := true;
return;
fi;
# if there is an actual message line, clear it
if ctSheet!.message then
Relabel( ctSheet!.messageText, "" );
ctSheet!.message := false;
fi;
# echo the command
if ctSheet!.echo then
Print( ">> CLOSE HLT\n" );
fi;
# get some local variables
subColumnNums := ctSheet!.subColumnNums;
relColumnNums := ctSheet!.relColumnNums;
subgrp := ctSheet!.subgrp;
ndefs := ctSheet!.ndefs;
nrels := Length( ctSheet!.rels );
nsgens := Length( ctSheet!.fsgens );
maxdef := 0;
coset := ctSheet!.hltRow;
overflow := false;
hlt := [ coset, maxdef, overflow ];
# fill the subgroup tables
if not subgrp = [] then
if coset <> 1 then
Error( "THIS IS A BUG (ITC 05), YOU SHOULD NEVER GET HERE" );
fi;
i := 0;
while i < nsgens do
i := i + 1;
ItcFillTraceHLT( ctSheet, hlt, subColumnNums[i] );
overflow := hlt[3];
if ctSheet!.firstDef = 0 or overflow or not ctSheet!.coincs = [] then
# break the loop if the tables closed or in case of insufficient
# table size or if there are pending coincidences
i := nsgens;
maxdef := ctSheet!.ndefs;
fi;
od;
fi;
coset := ctSheet!.hltRow;
hlt[1] := coset;
while maxdef <> ctSheet!.ndefs and coset <> 0 do
ctSheet!.hltRow := coset;
# fill the corresponding row in each relation table
i := 0;
while i < nrels do
i := i + 1;
ItcFillTraceHLT( ctSheet, hlt, relColumnNums[i] );
overflow := hlt[3];
# break the loops if the tables closed or in case of insufficient table
# size or if there are pending coincidences
if ctSheet!.firstDef = 0 or overflow or not ctSheet!.coincs = [] then
maxdef := ctSheet!.ndefs;
fi;
# break the inner loop if the coset is not alive any more
if ctSheet!.ndefs = maxdef or hlt[1] <> coset then
i := nrels;
fi;
od;
if hlt[1] = coset then
coset := ctSheet!.next[coset];
hlt[1] := coset;
else
coset := hlt[1];
fi;
od;
if ctSheet!.ndefs > ndefs and not overflow then
if ctSheet!.ndefs - ndefs > 1 then
ItcExtractPrecedingTable( ctSheet );
fi;
# save the current state
ItcExtractTable( ctSheet );
# display the coset tables and set all variables
ItcDisplayCosetTable( ctSheet );
# update all active relator tables and subgroup generator tables
ItcUpdateDisplayedLists( ctSheet );
# if there are pending coincidences display them
if not ctSheet!.coincs = [] then
ItcDisplayPendingCoincidences( ctSheet );
fi;
ItcEnableMenu( ctSheet );
fi;
end );
#############################################################################
#
# ItcCosetStepFelsch( <ctSheet> )
#
# defines a new coset (applying the Felsch strategy), computes all
# consequences, and displays the resulting tables.
#
InstallGlobalFunction( ItcCosetStepFelsch, function( ctSheet )
if ctSheet!.firstDef <> 0 then
# define a new coset
ItcFastCosetStepFelsch( ctSheet );
# give some information
ItcRelabelInfoLine( ctSheet );
fi;
end );
#############################################################################
#
# ItcCosetStepFill( <ctSheet>, <coset>, <gen> )
#
# defines a new coset to fill the given coset table position, computes all
# consequences, and displays the resulting tables.
#
InstallGlobalFunction( ItcCosetStepFill, function( ctSheet, coset, gen )
# define the new coset
ItcFastCosetStepFill( ctSheet, coset, gen );
# give some information
ItcRelabelInfoLine( ctSheet );
end );
#############################################################################
#
# ItcDisplayButtons( <ctSheet>, <y> )
#
# display the headers and buttons in the window 'Interactive Todd-Coxeter'.
#
InstallGlobalFunction( ItcDisplayButtons, function( ctSheet, y )
local bar, blue, charWidth, distance, gap, green, height, infoLine,
ItcButton, lineHeight, red, width1, width4, width6, white, x, x1, x2,
x3, x4, x5, x6, y1, y2, y3;
ItcButton := function( x, y, width, string, color )
local button;
# get the four colored bars
button := Box( ctSheet, x, y, width, bar, color );
button := Box( ctSheet, x, y + height - bar, width, bar, color );
button := Box( ctSheet, x, y, bar, height, color );
button := Box( ctSheet, x + width - bar, y, bar, height, color );
# get the black inner rectangle
button := Rectangle( ctSheet, x + bar + 1, y + bar + 1,
width - 2 * ( bar + 1 ), height - 2 * ( bar + 1 ) );
# get the black outer rectangle
button := Rectangle( ctSheet, x - 1, y - 1, width + 2, height + 2 );
# insert the text string
x := x + QuoInt( width - Length( string ) * charWidth + 1, 2 );
y := y + lineHeight - QuoInt( distance - 1, 2 );
Text( ctSheet, FONTS.normal, x, y, string );
return button;
end;
# get some local variables
distance := ctSheet!.normal.distance;
lineHeight := ctSheet!.normal.lineHeight;
charWidth := ctSheet!.normal.charWidth;
gap := ctSheet!.normal.gap;
if distance < 3 then
bar := distance - 2;
else
bar := distance - 1;
fi;
blue := rec( color := COLORS.blue );
green := rec( color := COLORS.green );
red := rec( color := COLORS.red );
white := rec( color := COLORS.white );
# define size and position of the buttons
width1 := 10 * charWidth + 2 * distance;
width4 := 12 * charWidth + 2 * distance;
width6 := 7 * charWidth + 2 * distance;
height := lineHeight + 2 * distance;
x1 := gap;
x2 := x1 + width1 + gap;
x3 := x2 + width1 + gap;
x4 := x3 + width1 + gap;
x5 := x4 + width4 + gap;
x6 := x5 + width4 + gap;
y1 := y + gap;
y2 := y1 + height + gap;
y3 := y2 + height + gap;
# define the buttons in the first column
ctSheet!.scrollto := ItcButton( x1, y1, width1, "scroll to", blue );
ctSheet!.scrollby := ItcButton( x1, y2, width1, "scroll by", blue );
ctSheet!.backto := ItcButton( x1, y3, width1, "back to", green );
# define the buttons in the second column
ctSheet!.felsch := ItcButton( x2, y1, width1, "Felsch", green );
ctSheet!.hlt := ItcButton( x2, y2, width1, "HLT", green );
ctSheet!.sortdefs := ItcButton( x2, y3, width1, "sort defs", green );
# define the buttons in the third column
ctSheet!.fillgaps := ItcButton( x3, y1, width1, "fill gaps", green );
ctSheet!.fillrows := ItcButton( x3, y2, width1, "fill rows", green );
ctSheet!.shortcut := ItcButton( x3, y3, width1, "short-cut", green );
# define the buttons in the fourth column
ctSheet!.showrels := ItcButton( x4, y1, width4, "show rels", white );
ctSheet!.showdefs := ItcButton( x4, y2, width4, "show defs", white );
ctSheet!.showcoincs := ItcButton( x4, y3, width4, "show coincs", white );
# define the buttons in the fifth column
ctSheet!.showsubgrp := ItcButton( x5, y1, width4, "show subgrp", white );
ctSheet!.showgaps := ItcButton( x5, y2, width4, "show gaps", white );
ctSheet!.mark := ItcButton( x5, y3, width4, "mark cosets", white );
# define the buttons in the sixth column
ctSheet!.clear := ItcButton( x6, y1, width6, "clear", red );
ctSheet!.reset := ItcButton( x6, y2, width6, "reset", red );
ctSheet!.quitt := ItcButton( x6, y3, width6, "quit", red );
end );
#############################################################################
#
# ItcDisplayCosetTable( <ctSheet> )
#
# displays the coset tables in the window 'Interactive Todd-Coxeter'.
#
InstallGlobalFunction( ItcDisplayCosetTable, function( ctSheet )
local alives, black, c, charWidth, color, coset, digits, distance, entry,
first, green, i, j, lastline, line0, line1, lineHeight, marked,
nalive, ncols, newtab, nlines, ndefs, oldrow, oldtab, px, py, red,
renumbered, row, str, t, w, y;
# get some local variables
ncols := ctSheet!.ncols;
newtab := ctSheet!.newtab;
oldtab := ctSheet!.oldtab;
ndefs := ctSheet!.ndefs;
marked := ctSheet!.marked;
renumbered := ctSheet!.renumbered;
alives := ctSheet!.alives;
nalive := Length( alives );
first := ctSheet!.first;
str := ctSheet!.digitString2;
black := rec( color := COLORS.black );
green := rec( color := COLORS.green );
red := rec( color := COLORS.red );
# get the character width and some other variables to display the table
digits := ctSheet!.digits;
distance := ctSheet!.small.distance;
lineHeight := ctSheet!.small.lineHeight;
charWidth := ctSheet!.small.charWidth;
y := 3 * distance;
w := ( digits + 2 ) * charWidth;
# check the first line to be printed for being in range
while first > ndefs or renumbered[first] = 0 do
first := first - 1;
od;
line1 := Minimum( renumbered[first], nalive );
if line1 < 1 then
line1 := 1;
fi;
first := alives[line1];
lastline := Minimum( line1 + 29, nalive );
line0 := line1 - 1;
# get the table and delete the old values
t := Flat( ctSheet!.graphicTable );
for i in [ 1 .. Length( t ) ] do
Delete ( t[i] );
od;
if IsBound( ctSheet!.line ) then
Delete( ctSheet!.line );
fi;
# delete the first column
c := Flat( ctSheet!.firstCol );
for i in [ 1 .. Length( c ) ] do
Delete( c[i] );
od;
# display a vertical line
nlines := lastline - line1 + 1;
ctSheet!.line := Line( ctSheet, w + charWidth, y, 0,
distance + ( nlines + 1 ) * lineHeight );
# display the numbers in the first column
FastUpdate( ctSheet, true );
ctSheet!.firstCol := [];
px := - charWidth;
if nalive <> 1 then
for i in [ line1 .. lastline ] do
py := y + (i - line0 + 1) * lineHeight;
ctSheet!.firstCol[i - line0] :=
Text( ctSheet, FONTS.small, px, py, str[alives[i]+2] );
od;
elif ctSheet!.first = 1 then
py := y + 2 * lineHeight;
ctSheet!.firstCol[1] := Text( ctSheet, FONTS.small, px, py, str[3] );
fi;
# display the numbers
t := [];
for i in [ 1 .. nlines ] do
coset := alives[line0 + i];
row := newtab[coset];
oldrow := oldtab[coset];
t[i] := [];
px := 0;
for j in [ 1 .. ncols ] do
px := px + w;
py := y + (i + 1) * lineHeight;
color := black;
entry := row[j];
if entry > 0 then
if entry in marked then
color := green;
elif entry <> oldrow[j] then
color := red;
fi;
elif entry < 0 and entry <> oldrow[j] then
color := red;
fi;
t[i][j] := Text( ctSheet, FONTS.small, px, py, str[entry+2], color );
od;
od;
FastUpdate( ctSheet, false );
# save the table
ctSheet!.first := first;
ctSheet!.nlines := nlines;
ctSheet!.graphicTable := t;
# recolor the rows which belong to pending cosets
ItcRecolorPendingCosets( ctSheet );
# mark definitions in the coset table
ItcRecolorDefs( ctSheet );
# update the info line
ItcRelabelInfoLine( ctSheet );
ctSheet!.isActual := true;
end );
#############################################################################
#
# ItcDisplayDefinition( <ctSheet>, <coset> )
#
# installs the methods for the right pointer button in the definitions list.
#
InstallGlobalFunction( ItcDisplayDefinition, function( ctSheet, coset )
local charWidth, distance, height, length, lineHeight, name, pos, repLists,
repNums, repSheets, sheet, string, width;
# get some local variables
distance := ctSheet!.normal.distance;
lineHeight := ctSheet!.normal.lineHeight;
charWidth := ctSheet!.normal.charWidth;
repLists := ctSheet!.repLists;
repNums := repLists[1];
--> --------------------
--> maximum size reached
--> --------------------
[ Dauer der Verarbeitung: 0.44 Sekunden
(vorverarbeitet)
]
|