/usr/share/gap/doc/tut/chap8.html is in gap-doc 4r8p8-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>GAP (tut) - Chapter 8: Operations and Methods</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="generator" content="GAPDoc2HTML" />
<link rel="stylesheet" type="text/css" href="manual.css" />
<script src="manual.js" type="text/javascript"></script>
<script type="text/javascript">overwriteStyle();</script>
</head>
<body class="chap8" onload="jscontent()">
<div class="chlinktop"><span class="chlink1">Goto Chapter: </span><a href="chap0.html">Top</a> <a href="chap1.html">1</a> <a href="chap2.html">2</a> <a href="chap3.html">3</a> <a href="chap4.html">4</a> <a href="chap5.html">5</a> <a href="chap6.html">6</a> <a href="chap7.html">7</a> <a href="chap8.html">8</a> <a href="chapBib.html">Bib</a> <a href="chapInd.html">Ind</a> </div>
<div class="chlinkprevnexttop"> <a href="chap0.html">[Top of Book]</a> <a href="chap0.html#contents">[Contents]</a> <a href="chap7.html">[Previous Chapter]</a> <a href="chapBib.html">[Next Chapter]</a> </div>
<p id="mathjaxlink" class="pcenter"><a href="chap8_mj.html">[MathJax on]</a></p>
<p><a id="X7AEED9AB824CD4DA" name="X7AEED9AB824CD4DA"></a></p>
<div class="ChapSects"><a href="chap8.html#X7AEED9AB824CD4DA">8 <span class="Heading">Operations and Methods</span></a>
<div class="ContSect"><span class="tocline"><span class="nocss"> </span><a href="chap8.html#X7C701DBF7BAE649A">8.1 <span class="Heading">Attributes</span></a>
</span>
</div>
<div class="ContSect"><span class="tocline"><span class="nocss"> </span><a href="chap8.html#X81C430C37B2F16D8">8.2 <span class="Heading">Properties and Filters</span></a>
</span>
</div>
<div class="ContSect"><span class="tocline"><span class="nocss"> </span><a href="chap8.html#X85CC8C167A280043">8.3 <span class="Heading">Immediate and True Methods</span></a>
</span>
</div>
<div class="ContSect"><span class="tocline"><span class="nocss"> </span><a href="chap8.html#X7DF5DBF9868B02C0">8.4 <span class="Heading">Operations and Method Selection</span></a>
</span>
</div>
</div>
<h3>8 <span class="Heading">Operations and Methods</span></h3>
<p><a id="X7C701DBF7BAE649A" name="X7C701DBF7BAE649A"></a></p>
<h4>8.1 <span class="Heading">Attributes</span></h4>
<p>In the preceding chapters, we have seen how to obtain information about mathematical objects in <strong class="pkg">GAP</strong>: We have to pass the object as an argument to a function. For example, if <var class="Arg">G</var> is a group one can call <code class="code">Size( <var class="Arg">G</var> )</code>, and the function will return a value, in our example an integer which is the size of <var class="Arg">G</var>. Computing the size of a group generally requires a substantial amount of work, therefore it seems desirable to store the size somewhere once it has been calculated. You should imagine that <strong class="pkg">GAP</strong> stores the size in some place associated with the object <var class="Arg">G</var> when <code class="code">Size( <var class="Arg">G</var> )</code> is executed for the first time, and if this function call is executed again later, the size is simply looked up and returned, without further computation.</p>
<p>This means that the behavior of the function <code class="func">Size</code> (<a href="../../doc/ref/chap30.html#X858ADA3B7A684421"><span class="RefLink">Reference: Size</span></a>) has to depend on whether the size for the argument <var class="Arg">G</var> is already known, and if not, that the size must be stored after it has been calculated. These two extra tasks are done by two other functions that accompany <code class="code">Size( <var class="Arg">G</var> )</code>, namely the <em>tester</em> <code class="code">HasSize( <var class="Arg">G</var> )</code> and the <em>setter</em> <code class="code">SetSize( <var class="Arg">G</var>, <var class="Arg">size</var> )</code>. The tester returns <code class="keyw">true</code> or <code class="keyw">false</code> according to whether <var class="Arg">G</var> has already stored its size, and the setter puts <var class="Arg">size</var> into a place from where <var class="Arg">G</var> can directly look it up. The function <code class="func">Size</code> (<a href="../../doc/ref/chap30.html#X858ADA3B7A684421"><span class="RefLink">Reference: Size</span></a>) itself is called the <em>getter</em>, and from the preceding discussion we see that there must really be at least two <em>methods</em> for the getter: One method is used when the tester returns <code class="keyw">false</code>; it is the method which first does the real computation and then executes the setter with the computed value. A second method is used when the tester returns <code class="keyw">true</code>; it simply returns the stored value. This second method is also called the <em>system getter</em>. <strong class="pkg">GAP</strong> functions for which several methods can be available are called <em>operations</em>, so <code class="func">Size</code> (<a href="../../doc/ref/chap30.html#X858ADA3B7A684421"><span class="RefLink">Reference: Size</span></a>) is an example of an operation.</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput">G := Group(List([1..3], i-> Random(SymmetricGroup(53))));;</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">Size( G ); time > 0; # the time may of course vary on your machine</span>
4274883284060025564298013753389399649690343788366813724672000000000000
true
<span class="GAPprompt">gap></span> <span class="GAPinput">Size( G ); time;</span>
4274883284060025564298013753389399649690343788366813724672000000000000
0
</pre></div>
<p>The convenient thing for the user is that <strong class="pkg">GAP</strong> automatically chooses the right method for the getter, i.e., it calls a real-work getter at most once and the system getter in all subsequent occurrences. <em>At most once</em> because the value of a function call like <code class="code">Size( <var class="Arg">G</var> )</code> can also be set for <var class="Arg">G</var> before the getter is called at all; for example, one can call the setter directly if one knows the size.</p>
<p>The size of a group is an example of a class of things which in <strong class="pkg">GAP</strong> are called <em>attributes</em>. Every attribute in <strong class="pkg">GAP</strong> is represented by a triple of a getter, a setter and a tester. When a new attribute is declared, all three functions are created together and the getter contains references to the other two. This is necessary because when the getter is called, it must first consult the tester, and perhaps execute the setter in the end. Therefore the getter could be implemented as follows:</p>
<div class="example"><pre>
getter := function( obj )
local value;
if tester( obj ) then
value := system_getter( obj );
else
value := real_work_getter( obj );
setter( obj, value );
fi;
return value;
end;
</pre></div>
<p>The only function which depends on the mathematical nature of the attribute is the real-work getter, and this is of course what the programmer of an attribute has to install. In both cases, the getter returns the same value, which we also call the value of the attribute (properly: the value of the attribute for the object <code class="code">obj</code>). By the way: The names for setter and tester of an attribute are always composed from the prefix <code class="code">Set</code> resp. <code class="code">Has</code> and the name of the getter.</p>
<p>As a (not typical) example, note that the <strong class="pkg">GAP</strong> function <code class="func">Random</code> (<a href="../../doc/ref/chap30.html#X7FF906E57D6936F8"><span class="RefLink">Reference: Random</span></a>), although it takes only one argument, is of course <em>not</em> an attribute, because otherwise the first random element of a group would be stored by the setter and returned over and over again by the system getter every time <code class="func">Random</code> (<a href="../../doc/ref/chap30.html#X7FF906E57D6936F8"><span class="RefLink">Reference: Random</span></a>) is called in the sequel.</p>
<p>There is a general important rule about attributes: <em>Once the value of an attribute for an object has been set, it cannot be reset, i.e., it cannot be changed any more.</em> This is achieved by having two methods not only for the getter but also for the setter: If an object already has an attribute value stored, i.e., if the tester returns <code class="keyw">true</code>, the setter simply does nothing.</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput">G := SymmetricGroup(8);; Size(G);</span>
40320
<span class="GAPprompt">gap></span> <span class="GAPinput">SetSize( G, 0 ); Size( G );</span>
40320
</pre></div>
<p><em>Summary.</em> In this section we have introduced attributes as triples of getter, setter and tester and we have explained how these three functions work together behind the scene to provide automatic storage and look-up of values that have once been calculated. We have seen that there can be several methods for the same function among which <strong class="pkg">GAP</strong> automatically selects an appropriate one.</p>
<p><a id="X81C430C37B2F16D8" name="X81C430C37B2F16D8"></a></p>
<h4>8.2 <span class="Heading">Properties and Filters</span></h4>
<p>Certain attributes, like <code class="func">IsAbelian</code> (<a href="../../doc/ref/chap35.html#X830A4A4C795FBC2D"><span class="RefLink">Reference: IsAbelian</span></a>), are boolean-valued. Such attributes are known to <strong class="pkg">GAP</strong> as <em>properties</em>, because their values are stored in a slightly different way. A property also has a getter, a setter and a tester, but in this case, the getter as well as the tester returns a boolean value. Therefore <strong class="pkg">GAP</strong> stores both values in the same way, namely as bits in a boolean list, thereby treating property getters and all testers (of attributes or properties) uniformly. These boolean-valued functions are called <em>filters</em>. You can imagine a filter as a switch which is set either to <code class="keyw">true</code> or to <code class="keyw">false</code>. For every <strong class="pkg">GAP</strong> object there is a boolean list which has reserved a bit for every filter <strong class="pkg">GAP</strong> knows about. Strictly speaking, there is one bit for every <em>simple filter</em>, and these simple filters can be combined with <code class="code">and</code> to form other filters (which are then <code class="keyw">true</code> if and only if all the corresponding bits are set to <code class="keyw">true</code>). For example, the filter <code class="code">IsPermGroup and IsSolvableGroup</code> is made up from several simple filters.</p>
<p>Since they allow only two values, the bits which represent filters can be compared very quickly, and the scheme by which <strong class="pkg">GAP</strong> chooses the method, e.g., for a getter or a setter (as we have seen in the previous section), is mostly based on the examination of filters, not on the examination of other attribute values. Details of this <em>method selection</em> are described in chapter <a href="../../doc/ref/chap78.html#X8058CC8187162644"><span class="RefLink">Reference: Method Selection</span></a>.</p>
<p>We only present the following rule of thumb here: Each installed method for an attribute, say <code class="func">Size</code> (<a href="../../doc/ref/chap30.html#X858ADA3B7A684421"><span class="RefLink">Reference: Size</span></a>), has a "required filter", which is made up from certain simple filters which must yield <code class="keyw">true</code> for the argument <var class="Arg">obj</var> for this method to be applicable. To execute a call of <code class="code">Size( <var class="Arg">obj</var> )</code>, <strong class="pkg">GAP</strong> selects among all applicable methods the one whose required filter combines the most simple filters; the idea behind is that the more an algorithm requires of <var class="Arg">obj</var>, the more efficient it is expected to be. For example, if <var class="Arg">obj</var> is a permutation group that is not (known to be) solvable, a method with required filter <code class="code">IsPermGroup and IsSolvableGroup</code> is not applicable, whereas a method with required filter <code class="func">IsPermGroup</code> (<a href="../../doc/ref/chap43.html#X7879877482F59676"><span class="RefLink">Reference: IsPermGroup</span></a>) can be chosen. On the other hand, if <var class="Arg">obj</var> was known to be solvable, the method with required filter <code class="code">IsPermGroup and IsSolvableGroup</code> would be preferred to the one with required filter <code class="func">IsPermGroup</code> (<a href="../../doc/ref/chap43.html#X7879877482F59676"><span class="RefLink">Reference: IsPermGroup</span></a>).</p>
<p>It may happen that a method is applicable for a given argument but cannot compute the desired value. In such cases, the method will execute the statement <code class="code">TryNextMethod();</code>, and <strong class="pkg">GAP</strong> calls the next applicable method. For example, <a href="chapBib.html#biBSims90b">[Sim90]</a> describes an algorithm to compute the size of a solvable permutation group, which can be used also to decide whether or not a permutation group is solvable. Suppose that the function <code class="code">size_solvable</code> implements this algorithm, and that is returns the order of the group if it is solvable and <code class="keyw">fail</code> otherwise. Then we can install the following method for <code class="func">Size</code> (<a href="../../doc/ref/chap30.html#X858ADA3B7A684421"><span class="RefLink">Reference: Size</span></a>) with required filter <code class="func">IsPermGroup</code> (<a href="../../doc/ref/chap43.html#X7879877482F59676"><span class="RefLink">Reference: IsPermGroup</span></a>).</p>
<div class="example"><pre>
function( G )
local value;
value := size_solvable( G );
if value <> fail then return value;
else TryNextMethod(); fi;
end;
</pre></div>
<p>This method can then be tried on every permutation group (whether known to be solvable or not), and it would include a mandatory solvability test.</p>
<p>If no applicable method (or no next applicable method) is found, <strong class="pkg">GAP</strong> stops with an error message of the form</p>
<div class="example"><pre>
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
Error, no 1st choice method found for `Size' on 1 arguments called from
... lines deleted here ...
</pre></div>
<p>You would get an error message as above if you asked for <code class="code">Size( 1 )</code>. The message simply says that there is no method installed for calculating the size of <code class="code">1</code>. Section <a href="../../doc/ref/chap7.html#X83C45B0A797AAF96"><span class="RefLink">Reference: Recovery from NoMethodFound-Errors</span></a> contains more information on how to deal with these messages.</p>
<p><em>Summary.</em> In this section we have introduced properties as special attributes, and filters as the general concept behind property getters and attribute testers. The values of the filters of an object govern how the object is treated in the selection of methods for operations.</p>
<p><a id="X85CC8C167A280043" name="X85CC8C167A280043"></a></p>
<h4>8.3 <span class="Heading">Immediate and True Methods</span></h4>
<p>In the example in Section <a href="chap8.html#X81C430C37B2F16D8"><span class="RefLink">8.2</span></a>, we have mentioned that the operation <code class="func">Size</code> (<a href="../../doc/ref/chap30.html#X858ADA3B7A684421"><span class="RefLink">Reference: Size</span></a>) has a method for solvable permutation groups that is so far superior to the method for general permutation groups that it seems worthwhile to try it even if nothing is known about solvability of the group of which the <code class="func">Size</code> (<a href="../../doc/ref/chap30.html#X858ADA3B7A684421"><span class="RefLink">Reference: Size</span></a>) is to be calculated. There are other examples where certain methods are even "cheaper" to execute. For example, if the size of a group is known it is easy to check whether it is odd, and if so, the Feit-Thompson theorem allows us to set <code class="func">IsSolvableGroup</code> (<a href="../../doc/ref/chap39.html#X809C78D5877D31DF"><span class="RefLink">Reference: IsSolvableGroup</span></a>) to <code class="keyw">true</code> for this group. <strong class="pkg">GAP</strong> utilizes this celebrated theorem by having an <em>immediate method</em> for <code class="func">IsSolvableGroup</code> (<a href="../../doc/ref/chap39.html#X809C78D5877D31DF"><span class="RefLink">Reference: IsSolvableGroup</span></a>) with required filter <code class="code">HasSize</code> which checks parity of the size and either sets <code class="func">IsSolvableGroup</code> (<a href="../../doc/ref/chap39.html#X809C78D5877D31DF"><span class="RefLink">Reference: IsSolvableGroup</span></a>) or does nothing, i.e., calls <code class="code">TryNextMethod()</code>. These immediate methods are executed automatically for an object whenever the value of a filter changes, so solvability of a group will automatically be detected when an odd size has been calculated for it (and therefore the value of <code class="code">HasSize</code> for that group has changed to <code class="keyw">true</code>).</p>
<p>Some methods are even more immediate, because they do not require any calculation at all: They allow a filter to be set if another filter is also set. In other words, they model a mathematical implication like <code class="code">IsGroup and IsCyclic</code> implies <code class="code">IsSolvableGroup</code> and such implications can be installed in <strong class="pkg">GAP</strong> as <em>true methods</em>. To execute true methods, <strong class="pkg">GAP</strong> only needs to do some bookkeeping with its filters, therefore true methods are much faster than immediate methods.</p>
<p>How immediate and true methods are installed is described in <a href="../../doc/ref/chap78.html#X87D38D2584D0A8AF"><span class="RefLink">Reference: Immediate Methods</span></a> and <a href="../../doc/ref/chap78.html#X7FB5016E83DB4349"><span class="RefLink">Reference: Logical Implications</span></a>.</p>
<p><a id="X7DF5DBF9868B02C0" name="X7DF5DBF9868B02C0"></a></p>
<h4>8.4 <span class="Heading">Operations and Method Selection</span></h4>
<p>The method selection is not only used to select methods for attribute getters but also for arbitrary <em>operations</em>, which can have more than one argument. In this case, there is a required filter for each argument (which must yield <code class="keyw">true</code> for the corresponding arguments).</p>
<p>Additionally, a method with at least two arguments may require a certain relation between the arguments, which is expressed in terms of the <em>families</em> of the arguments. For example, the methods for <code class="code">ConjugateGroup( <var class="Arg">grp</var>, <var class="Arg">elm</var> )</code> require that <var class="Arg">elm</var> lies in the family of elements from which <var class="Arg">grp</var> is made, i.e., that the family of <var class="Arg">elm</var> equals the "elements family" of <var class="Arg">grp</var>.</p>
<p>For permutation groups, the situation is quite easy: all permutations form one family, <code class="func">PermutationsFamily</code> (<a href="../../doc/ref/chap42.html#X819628B083B3939B"><span class="RefLink">Reference: PermutationsFamily</span></a>), and each collection of permutations, for example each permutation group, each coset of a permutation group, or each dense list of permutations, lies in <code class="code">CollectionsFamily( PermutationsFamily )</code>.</p>
<p>For other kinds of group elements, the situation can be different. Every call of <code class="func">FreeGroup</code> (<a href="../../doc/ref/chap37.html#X8215999E835290F0"><span class="RefLink">Reference: FreeGroup</span></a>) constructs a new family of free group elements. <strong class="pkg">GAP</strong> refuses to compute <code class="code">One( FreeGroup( 1 ) ) * One( FreeGroup( 1 ) )</code> because the two operands of the multiplication lie in different families and no method is installed for this case.</p>
<p>For further information on family relations, see <a href="../../doc/ref/chap13.html#X846063757EC05986"><span class="RefLink">Reference: Families</span></a>.</p>
<p>If you want to know which properties are already known for an object <var class="Arg">obj</var>, or which properties are known to be true, you can use the functions <code class="code">KnownPropertiesOfObject( <var class="Arg">obj</var> )</code> resp. <code class="code">KnownTruePropertiesOfObject( <var class="Arg">obj</var> )</code>. This will print a list of names of properties. These names are also the identifiers of the property getters, by which you can retrieve the value of the properties (and confirm that they are really <code class="keyw">true</code>). Analogously, there is the function <code class="func">KnownAttributesOfObject</code> (<a href="../../doc/ref/chap13.html#X7F7960338163AA88"><span class="RefLink">Reference: KnownAttributesOfObject</span></a>) which lists the names of the known attributes, leaving out the properties.</p>
<p>Since <strong class="pkg">GAP</strong> lets you know what it already knows about an object, it is only natural that it also lets you know what methods it considers applicable for a certain method, and in what order it will try them (in case <code class="code">TryNextMethod()</code> occurs). <code class="code">ApplicableMethod( <var class="Arg">opr</var>, [ arg_1, arg_2, ... ] )</code> returns the first applicable method for the call <code class="code"><var class="Arg">opr</var>( arg_1, arg_2, ... )</code>. More generally, <code class="code">ApplicableMethod( <var class="Arg">opr</var>, [ ... ], 0, <var class="Arg">nr</var> )</code> returns the <var class="Arg">nr</var>th applicable method (i.e., the one that would be chosen after <span class="SimpleMath"><var class="Arg">nr</var>-1</span> calls of <code class="code">TryNextMethod</code>) and if <var class="Arg">nr</var><code class="code"> = "all"</code>, the sorted list of all applicable methods is returned. For details, see <a href="../../doc/ref/chap78.html#X851FC6387CA2B241"><span class="RefLink">Reference: Applicable Methods and Method Selection</span></a>.</p>
<p>If you want to see which methods are chosen for certain operations while <strong class="pkg">GAP</strong> code is being executed, you can call the function <code class="func">TraceMethods</code> (<a href="../../doc/ref/chap7.html#X80B044017C9E4137"><span class="RefLink">Reference: TraceMethods for a list of operations</span></a>) with a list of these operations as arguments.</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput">TraceMethods( [ Size ] );</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">g:= Group( (1,2,3), (1,2) );; Size( g );</span>
#I Size: for a permutation group
#I Setter(Size): system setter
#I Size: system getter
#I Size: system getter
6
</pre></div>
<p>The system getter is called once to fetch the freshly computed value for returning to the user. The second call is triggered by an immediate method. To find out by which, we can trace the immediate methods by saying <code class="code">TraceImmediateMethods( true )</code>.</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput">TraceImmediateMethods( true );</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">g:= Group( (1,2,3), (1,2) );;</span>
#I immediate: Size
#I immediate: IsCyclic
#I immediate: IsCommutative
#I immediate: IsTrivial
<span class="GAPprompt">gap></span> <span class="GAPinput">Size( g );</span>
#I Size: for a permutation group
#I immediate: IsNonTrivial
#I immediate: Size
#I immediate: IsFreeAbelian
#I immediate: IsTorsionFree
#I immediate: IsNonTrivial
#I immediate: GeneralizedPcgs
#I Setter(Size): system setter
#I Size: system getter
#I immediate: IsPerfectGroup
#I Size: system getter
#I immediate: IsEmpty
6
<span class="GAPprompt">gap></span> <span class="GAPinput">TraceImmediateMethods( false );</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">UntraceMethods( [ Size ] );</span>
</pre></div>
<p>The last two lines switch off tracing again. We now see that the system getter was called by the immediate method for <code class="func">IsPerfectGroup</code> (<a href="../../doc/ref/chap39.html#X8755147280C84DBB"><span class="RefLink">Reference: IsPerfectGroup</span></a>). Also the above-mentioned immediate method for <code class="func">IsSolvableGroup</code> (<a href="../../doc/ref/chap39.html#X809C78D5877D31DF"><span class="RefLink">Reference: IsSolvableGroup</span></a>) was not used because the solvability of <code class="code">g</code> was already found out during the size calculation (cf. the example in Section <a href="chap8.html#X81C430C37B2F16D8"><span class="RefLink">8.2</span></a>).</p>
<p><em>Summary.</em> In this section and the last we have looked some more behind the scenes and seen that <strong class="pkg">GAP</strong> automatically executes immediate and true methods to deduce information about objects that is cheaply available. We have seen how this can be supervised by tracing the methods.</p>
<div class="chlinkprevnextbot"> <a href="chap0.html">[Top of Book]</a> <a href="chap0.html#contents">[Contents]</a> <a href="chap7.html">[Previous Chapter]</a> <a href="chapBib.html">[Next Chapter]</a> </div>
<div class="chlinkbot"><span class="chlink1">Goto Chapter: </span><a href="chap0.html">Top</a> <a href="chap1.html">1</a> <a href="chap2.html">2</a> <a href="chap3.html">3</a> <a href="chap4.html">4</a> <a href="chap5.html">5</a> <a href="chap6.html">6</a> <a href="chap7.html">7</a> <a href="chap8.html">8</a> <a href="chapBib.html">Bib</a> <a href="chapInd.html">Ind</a> </div>
<hr />
<p class="foot">generated by <a href="http://www.math.rwth-aachen.de/~Frank.Luebeck/GAPDoc">GAPDoc2HTML</a></p>
</body>
</html>
|