<p>The main features of the library can be summarized in three points: it provides a complete set of semigroups up to isomorphism and anti-isomorphism of sizes up to 8; it carries a vast amount of precomputed information about these semigroups; and there is an identification function which takes a semigroup with at most 8 elements and returns a map to the equivalent one from the library.</p>
<p>These features lead to different ways of using the library. It is impossible to describe - or even to anticipate - all possible types of usage. Most problems will admit multiple solutions. We find it difficult to predict which will be most effective. The examples in this chapter should give an idea of the differences in the various functions and help you to find an alternative if a computation uses more time or memory than you have available.</p>
<p>Let us go step by step through some ways to use the library showing which tools are provided.</p>
<h4>3.1 <span class="Heading">Lists, Enumerators and Iterators of Semigroups</span></h4>
<p>At first one could want to search through the stored semigroups for one or all semigroups with a certain property. Going through all the semigroups can take a long time. Just to create all the 1.8 billion semigroups as objects in <strong class="pkg">GAP</strong> takes around a day on a modern PC. Doing a simple test on all the semigroups in the library might take another day. Performing complicated tests easily takes weeks. To avoid this, many properties of the semigroups were precomputed. Semigroups with or without a precomputed property can be accessed as quickly as simply creating the same number of semigroups. (Note that timings of two calls to the same command may vary and, of course, heavily depend on your machine.)</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput"># obtain a list of all semigroups with 6 elements</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">AllSmallSemigroups(6);;</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">time;</span>
2636
<span class="GAPprompt">gap></span> <span class="GAPinput"># obtain a list of all commutative semigroups with 7 elements</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">AllSmallSemigroups(7, IsCommutative, true);;</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">time;</span>
2957
<span class="GAPprompt">gap></span> <span class="GAPinput"># compare the numbers of semigroups in the two lists</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">NrSmallSemigroups(6); NrSmallSemigroups(7, IsCommutative, true);</span>
15973
17291
</pre></div>
<p>(In all the examples in this section the info messages which are given by default when data is loaded are turned off via <code class="code">SetInfoLevel(InfoSmallSemi,0)</code>.)</p>
<p>We provide three commands that can be used if one is interested in all semigroups with some properties. These are <code class="func">AllSmallSemigroups</code> (<a href="chap4.html#X81DC0FE28043C9B0"><span class="RefLink">4.5-1</span></a>), <code class="func">EnumeratorOfSmallSemigroups</code> (<a href="chap4.html#X831E543E83DDFDEA"><span class="RefLink">4.5-2</span></a>), and <code class="func">IteratorOfSmallSemigroups</code> (<a href="chap4.html#X7D6BFDE17A9BEEC3"><span class="RefLink">4.5-9</span></a>). Which one is best to use depends a lot on the situation. Here we attempt to provide some insight about the essential differences.</p>
<p>We start with examples using only precomputed information. In this case there is essentially no advantage of calling an iterator instead of an enumerator. Thus only <code class="func">AllSmallSemigroups</code> (<a href="chap4.html#X81DC0FE28043C9B0"><span class="RefLink">4.5-1</span></a>) and <code class="func">EnumeratorOfSmallSemigroups</code> (<a href="chap4.html#X831E543E83DDFDEA"><span class="RefLink">4.5-2</span></a>) will be considered.</p>
<p>We first compare the memory usage and the setup time. Assume we are interested in the commutative semigroups with at most 7 elements.</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput">list := AllSmallSemigroups([1 .. 7], IsCommutativeSemigroup, true);;</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">time; # the time needed will always depend on your machine</span>
3180
<span class="GAPprompt">gap></span> <span class="GAPinput">enum := EnumeratorOfSmallSemigroups([1 .. 7], IsCommutativeSemigroup, true);</span>
<enumerator of semigroups of sizes [ 1 .. 7 ]>
<span class="GAPprompt">gap></span> <span class="GAPinput">time;</span>
8
</pre></div>
<p>The enumerator stores the information, which semigroups it contains, but only creates the semigroups when asked for them explicitly.</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput"># now the semigroups have to be created ...</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">for sg in enum do</span>
<span class="GAPprompt">></span> <span class="GAPinput"># do nothing, the semigroup will be created anyway</span>
<span class="GAPprompt">></span> <span class="GAPinput">od;</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">time;</span>
3428
<span class="GAPprompt">gap></span> <span class="GAPinput"># ... and again if you want to look through them another time ...</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">for sg in enum do od;</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">time;</span>
3437
<span class="GAPprompt">gap></span> <span class="GAPinput"># ... not so for the list of semigroups though</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">for sg in list do od;</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">time;</span>
4
</pre></div>
<p>There are several reasons why one would nevertheless prefer an enumerator, one is the smaller need for memory. While the number of semigroups in this example is rather moderate (compared with all the semigroups in the library) the difference is remarkable:</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput">nr := Length(enum);</span>
17291
<span class="GAPprompt">gap></span> <span class="GAPinput">MemoryUsage(enum);</span>
70507
<span class="GAPprompt">gap></span> <span class="GAPinput">MemoryUsage(list); # this will take a while .. .</span>
19089280
<span class="GAPprompt">gap></span> <span class="GAPinput"># ... but you can get a close approximation much faster</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">sg := OneSmallSemigroup(7, IsCommutativeSemigroup, true);</span>
<small semigroup of size 7>
<span class="GAPprompt">gap></span> <span class="GAPinput">nr * MemoryUsage(sg);</span>
19020100
</pre></div>
<p>As said before the advantage of the enumerator comes from the fact that the members of it are created anew every time they are called. This means on the other hand that information that is computed is not stored.</p>
<div class="example"><pre>
<span class="GAPprompt">gap></span> <span class="GAPinput">IsZeroSemigroup(list[3]); # a semigroup from the list .. .</span>
false
<span class="GAPprompt">gap></span> <span class="GAPinput">KnownPropertiesOfObject(list[3]); # .. . can store new information</span>
[ "IsEmpty", "IsTrivial", "IsNonTrivial", "IsFinite", "IsDuplicateFree", "IsAssociative", "IsCommutativeSemigroup", "IsZeroSemigroup" ]
<span class="GAPprompt">gap></span> <span class="GAPinput">IsZeroSemigroup(enum[3]); # semigroups in the enumerator .. .</span>
false
<span class="GAPprompt">gap></span> <span class="GAPinput">KnownPropertiesOfObject(enum[3]); # .. . are created anew in every call</span>
[ "IsEmpty", "IsTrivial", "IsNonTrivial", "IsFinite", "IsDuplicateFree", "IsAssociative", "IsCommutativeSemigroup" ]
<span class="GAPprompt">gap></span> <span class="GAPinput"># but if it turns out this is the semigroup you want to analyse, just do</span>
<span class="GAPprompt">gap></span> <span class="GAPinput">sg := enum[3];</span>
</pre></div>
<p>Observe that in the last example the semigroup from the enumerator knew about the property that was used to create the enumerator. The enumerator stores this knowledge and passes it on whenever a member is called.</p>
<p>Another reason to prefer an enumerator is that one might only be interested in some of the elements it contains. This could become clear after analysing some of the elements and then there is no time wasted in creating all semigroups in the enumerator. Or possibly creating the enumerator involving precomputed properties was just the first step. As described in Section <a href="chap4.html#X82F9C36C86006857"><span class="RefLink">4.5</span></a> enumerators themselves can be given as argument to get to a more restricted class of semigroups. This leads us to the next part of this section.</p>
<p>We now come to examples dealing with properties that are not precomputed - including user defined functions. This makes <code class="func">IteratorOfSmallSemigroups</code> (<a href="chap4.html#X7D6BFDE17A9BEEC3"><span class="RefLink">4.5-9</span></a>) interesting again. Assume you want to work with bands (<code class="func">IsBand</code> (<a href="chap4.html#X7C8DB14587D1B55A"><span class="RefLink">4.2-5</span></a>)) of order 8 having 1 Green's D-class (see Reference: Green's Relations</span></a>). You might feel tempted to implement a function testing a semigroup for this combination of properties.</p>
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.