############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Martin Schönert. ## ## Copyright of GAP belongs to its developers, whose names are too numerous ## to list here. Please refer to the COPYRIGHT file for details. ## ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This declares the operations for domains. ##
############################################################################# ## ## <#GAPDoc Label="[1]{domain}"> ## <E>Domain</E> is &GAP;'s name for structured sets. ## The ring of Gaussian integers <M>&ZZ;[\sqrt{{-1}}]</M> is an example of a ## domain, ## the group <M>D_{12}</M> of symmetries of a regular hexahedron is another. ## <P/> ## The &GAP; library predefines some domains. ## For example the ring of Gaussian integers is predefined as ## <Ref Var="GaussianIntegers"/> (see <Ref Chap="Gaussians"/>) ## and the field of rationals is predefined as <Ref Var="Rationals"/> ## (see <Ref Chap="Rational Numbers"/>). ## Most domains are constructed by functions, ## which are called <E>domain constructors</E> ## (see <Ref Sect="Constructing Domains"/>). ## For example the group <M>D_{12}</M> is constructed by the construction ## <C>Group( (1,2,3,4,5,6), (2,6)(3,5) )</C> ## (see <Ref Func="Group" Label="for several generators"/>) ## and the finite field with 16 elements is constructed by ## <C>GaloisField( 16 )</C> ## (see <Ref Func="GaloisField" Label="for field size"/>). ## <P/> ## The first place where you need domains in &GAP; is the obvious one. ## Sometimes you simply want to deal with a domain. ## For example if you want to compute the size of the group <M>D_{12}</M>, ## you had better be able to represent this group in a way that the ## <Ref Attr="Size"/> function can understand. ## <P/> ## The second place where you need domains in &GAP; is when you want to ## be able to specify that an operation or computation takes place in a ## certain domain. ## For example suppose you want to factor 10 in the ring of Gaussian ## integers. ## Saying <C>Factors( 10 )</C> will not do, because this will return the ## factorization <C>[ 2, 5 ]</C> in the ring of integers. ## To allow operations and computations to happen in a specific domain, ## <Ref Oper="Factors"/>, and many other functions as well, ## accept this domain as optional first argument. ## Thus <C>Factors( GaussianIntegers, 10 )</C> yields the desired result ## <C>[ 1+E(4), 1-E(4), 2+E(4), 2-E(4) ]</C>. ## (The imaginary unit <M>\sqrt{{-1}}</M> is written as <C>E(4)</C> ## in &GAP;, see <Ref Oper="E"/>.) ## <#/GAPDoc> ## ## <#GAPDoc Label="[2]{domain}"> ## <E>Equality</E> and <E>comparison</E> of domains are defined as follows. ## <P/> ## Two domains are considered <E>equal</E> if and only if the sets of their ## elements as computed by <Ref Attr="AsSSortedList"/>) are equal. ## Thus, in general <C>=</C> behaves as if each domain operand were replaced ## by its set of elements. ## Except that <C>=</C> will also sometimes, but not always, ## work for infinite domains, for which of course &GAP; cannot compute ## the set of elements. ## Note that this implies that domains with different algebraic structure ## may well be equal. ## As a special case of this, either operand of <C>=</C> may also be a ## proper set (see <Ref Sect="Sorted Lists and Sets"/>), ## i.e., a sorted list without holes or duplicates ## (see <Ref Attr="AsSSortedList"/>), ## and <C>=</C> will return <K>true</K> if and only if this proper set is ## equal to the set of elements of the argument that is a domain. ## <P/> ## <!-- #T These statements imply that <C><</C> and <C>=</C> --> ## <!-- #T comparisons of <E>elements</E> in a domain are always --> ## <!-- #T defined. Do we really want to guarantee this? --> ## <E>No</E> general <E>ordering</E> of arbitrary domains via <C><</C> ## is defined in &GAP; 4. ## This is because a well-defined <C><</C> for domains or, more general, ## for collections, would have to be compatible with <C>=</C> and would need ## to be transitive and antisymmetric in order to be used to form ordered ## sets. ## In particular, <C><</C> would have to be independent of the algebraic ## structure of its arguments because this holds for <C>=</C>, ## and thus there would be hardly a situation where one could implement ## an efficient comparison method. ## (Note that in the case that two domains are comparable with <C><</C>, ## the result is in general <E>not</E> compatible with the set theoretical ## subset relation, which can be decided with <Ref Oper="IsSubset"/>.) ## <#/GAPDoc> ##
############################################################################# ## #C IsGeneralizedDomain( <D> ) . . . . . . . . . test for generalized domain #C IsDomain( <D> ) . . . . . . . . . . . . . . . . . . . . . test for domain ## ## <#GAPDoc Label="IsGeneralizedDomain"> ## <ManSection> ## <Filt Name="IsGeneralizedDomain" Arg='obj' Type='Category'/> ## <Filt Name="IsDomain" Arg='obj' Type='Category'/> ## ## <Description> ## For some purposes, it is useful to deal with objects that are similar to ## domains but that are not collections in the sense of &GAP; ## because their elements may lie in different families; ## such objects are called <E>generalized domains</E>. ## An instance of generalized domains are <Q>operation domains</Q>, ## for example any <M>G</M>-set for a permutation group <M>G</M> ## consisting of some union of points, sets of points, sets of sets of ## points etc., under a suitable action. ## <P/> ## <Ref Filt="IsDomain"/> is a synonym for ## <C>IsGeneralizedDomain and IsCollection</C>. ## </Description> ## </ManSection> ## <#/GAPDoc> ##
DeclareCategory( "IsGeneralizedDomain", IsObject );
DeclareSynonym( "IsDomain", IsGeneralizedDomain and IsCollection );
InstallTrueMethod( IsDuplicateFree, IsDomain );
############################################################################# ## #A GeneratorsOfDomain( <D> ) ## ## <#GAPDoc Label="GeneratorsOfDomain"> ## <ManSection> ## <Attr Name="GeneratorsOfDomain" Arg='D'/> ## ## <Description> ## For a domain <A>D</A>, <Ref Attr="GeneratorsOfDomain"/> returns a list ## containing generators of <A>D</A> with respect to the trivial operational ## structure, that is interpreting <A>D</A> as a set. ## The returned list may contain repetitions. ## <P/> ## See <Ref Sect="Constructing Domains"/> and for ## <C>GeneratorsOf<A>Struct</A></C> methods with respect to other available ## operational structures. ## <P/> ## For many domains that have <E>natural generators by construction</E> ## (for example, the natural generators of a free group of rank two ## are the two generators stored as value of the attribute ## <Ref Attr="GeneratorsOfGroup"/>, and the natural generators of ## a free associative algebra are those generators stored as value of ## the attribute <Ref Attr="GeneratorsOfAlgebra"/>), each <E>natural</E> ## generator can be accessed using the <C>.</C> operator. For a domain ## <A>D</A>, <C><A>D</A>.i</C> returns the <M>i</M>-th generator if ## <M>i</M> is a positive integer, and if <C>name</C> is the name of a ## generator of <A>D</A> then <C><A>D</A>.name</C> returns this generator. ## <P/> ## <Example><![CDATA[ ## gap> G := DihedralGroup(IsPermGroup, 4);; ## gap> GeneratorsOfGroup(G); ## [ (1,2), (3,4) ] ## gap> GeneratorsOfDomain(G); ## [ (), (3,4), (1,2), (1,2)(3,4) ] ## gap> F := FreeGroup("x"); ## <free group on the generators [ x ]> ## gap> GeneratorsOfGroup(F); ## [ x ] ## gap> GeneratorsOfDomain(F); ## Error, resulting list would be too large (length infinity) ## ]]></Example> ## </Description> ## </ManSection> ## <#/GAPDoc> ##
DeclareAttribute( "GeneratorsOfDomain", IsDomain );
############################################################################# ## #F Domain( [<Fam>, ]<generators> ) #O DomainByGenerators( <Fam>, <generators> ) ## ## <#GAPDoc Label="Domain"> ## <ManSection> ## <Func Name="Domain" Arg='[Fam, ]generators'/> ## <Oper Name="DomainByGenerators" Arg='Fam, generators'/> ## ## <Description> ## <Ref Func="Domain"/> returns the domain consisting of the elements ## in the homogeneous list <A>generators</A>. ## If <A>generators</A> is empty then a family <A>Fam</A> must be entered ## as the first argument, and the returned (empty) domain lies in the ## collections family of <A>Fam</A>. ## <P/> ## <Ref Oper="DomainByGenerators"/> is the operation called by ## <Ref Func="Domain"/>. ## </Description> ## </ManSection> ## <#/GAPDoc> ##
DeclareGlobalFunction( "Domain" );
DeclareOperation( "DomainByGenerators", [ IsFamily, IsList ] );
############################################################################# ## #F Parent( <D> ) #O SetParent( <D>, <P> ) #F HasParent( <D> ) ## ## <#GAPDoc Label="Parent"> ## <ManSection> ## <Func Name="Parent" Arg='D'/> ## <Oper Name="SetParent" Arg='D, P'/> ## <Filt Name="HasParent" Arg='D'/> ## ## <Description> ## It is possible to assign to a domain <A>D</A> one other domain <A>P</A> ## containing <A>D</A> as a subset, ## in order to exploit this subset relation between <A>D</A> and <A>P</A>. ## Note that <A>P</A> need not have the same operational structure as <A>D</A>, ## for example <A>P</A> may be a magma and <A>D</A> a field. ## <P/> ## The assignment is done by calling <Ref Oper="SetParent"/>, ## and <A>P</A> is called the <E>parent</E> of <A>D</A>. ## If <A>D</A> has already a parent, ## calls to <Ref Oper="SetParent"/> will be ignored. ## <P/> ## If <A>D</A> has a parent <A>P</A> ## –this can be checked with <Ref Filt="HasParent"/>– ## then <A>P</A> can be used to gain information about <A>D</A>. ## First, the call of <Ref Oper="SetParent"/> causes ## <Ref Oper="UseSubsetRelation"/> to be called. ## Second, for a domain <A>D</A> with parent, ## information relative to the parent can be stored in <A>D</A>; ## for example, there is an attribute <C>NormalizerInParent</C> for storing ## <C>Normalizer( <A>P</A>, <A>D</A> )</C> in the case that <A>D</A> is a ## group. ## (More about such parent dependent attributes can be found in ## <Ref Sect="In Parent Attributes"/>.) ## <!-- better make this part of the Reference Manual?--> ## Note that because of this relative information, ## one cannot change the parent; ## that is, one can set the parent only once, ## subsequent calls to <Ref Oper="SetParent"/> for the same domain <A>D</A> ## are ignored. ## <!-- better raise a warning/error?--> ## Further note that contrary to <Ref Oper="UseSubsetRelation"/>, ## also knowledge about the parent <A>P</A> might be used ## that is discovered after the <Ref Oper="SetParent"/> call. ## <P/> ## A stored parent can be accessed using <Ref Func="Parent"/>. ## If <A>D</A> has no parent then <Ref Func="Parent"/> returns <A>D</A> ## itself, and <Ref Filt="HasParent"/> will return <K>false</K> ## also after a call to <Ref Func="Parent"/>. ## So <Ref Func="Parent"/> is <E>not</E> an attribute, ## the underlying attribute to store the parent is <C>ParentAttr</C>. ## <!-- add a cross-ref. to section about attributes --> ## <P/> ## Certain functions that return domains with parent already set, ## for example <Ref Func="Subgroup"/>, ## are described in Section <Ref Sect="Constructing Subdomains"/>. ## Whenever a function has this property, ## the &GAP; Reference Manual states this explicitly. ## Note that these functions <E>do not guarantee</E> a certain parent, ## for example <Ref Attr="DerivedSubgroup"/> for a perfect ## group <M>G</M> may return <M>G</M> itself, and if <M>G</M> had already a ## parent then this is not replaced by <M>G</M>. ## As a rule of thumb, &GAP; avoids to set a domain as its own parent, ## which is consistent with the behaviour of <Ref Func="Parent"/>, ## at least until a parent is set explicitly with <Ref Oper="SetParent"/>. ## <P/> ## <Example><![CDATA[ ## gap> g:= Group( (1,2,3), (1,2) );; h:= Group( (1,2) );; ## gap> HasParent( g ); HasParent( h ); ## false ## false ## gap> SetParent( h, g ); ## gap> Parent( g ); Parent( h ); ## Group([ (1,2,3), (1,2) ]) ## Group([ (1,2,3), (1,2) ]) ## gap> HasParent( g ); HasParent( h ); ## false ## true ## ]]></Example> ## </Description> ## </ManSection> ## <#/GAPDoc> ##
DeclareAttribute( "ParentAttr", IsDomain );
DeclareSynonym( "SetParent", SetParentAttr );
DeclareSynonym( "HasParent", HasParentAttr );
BIND_GLOBAL( "Parent", function( S ) if HasParent( S ) then
return ParentAttr( S ); else
return S; fi; end );
############################################################################# ## #F InstallAccessToGenerators( <required>, <infotext>, <generators> ) ## ## <ManSection> ## <Func Name="InstallAccessToGenerators" Arg='required, infotext, generators'/> ## ## <Description> ## A free structure <M>F</M> has natural generators by construction. ## For example, the natural generators of a free group of rank two are the ## two generators stored as value of the attribute <C>GeneratorsOfGroup</C>, ## and the natural generators of a free associative algebra are those ## generators stored as value of the attribute <C>GeneratorsOfAlgebra</C>. ## Note that semigroup generators are <E>not</E> considered as natural. ## <P/> ## Each natural generator of <M>F</M> can be accessed using the <C>.</C> operator. ## <M>F.i</M> returns the <M>i</M>-th generator if <M>i</M> is a positive integer, ## and if <A>name</A> is the name of a generator of <M>F</M> then <M>F.<A>name</A></M> returns ## this generator. ## </Description> ## </ManSection> ##
DeclareGlobalFunction( "InstallAccessToGenerators" );
############################################################################# ## #F InParentFOA( <name>, <super>, <sub>, <AorP> ) . dispatcher, oper and attr ## ## <#GAPDoc Label="InParentFOA"> ## <ManSection> ## <Func Name="InParentFOA" Arg='name, super, sub, AorP'/> ## ## <Description> ## This section describes how you can add new <Q>in parent attributes</Q> ## (see <Ref Sect="Constructing Subdomains"/> ## and <Ref Sect="Parents"/>). ## As an example, we describe how ## <Ref Oper="Index" Label="for a group and its subgroup"/> ## and its related functions are implemented. ## <P/> ## There are two operations ## <Ref Oper="Index" Label="for a group and its subgroup"/> and ## <C>IndexOp</C>, ## and an attribute <C>IndexInParent</C>. ## They are created together as shown below, ## and after they have been created, ## methods need be installed only for <C>IndexOp</C>. ## In the creation process, <C>IndexInParent</C> ## already gets one default method installed ## (in addition to the usual system getter of each attribute, ## see <Ref Sect="Attributes"/>), ## namely <C>D -> IndexOp( Parent( D ), D )</C>. ## <P/> ## The operation <Ref Oper="Index" Label="for a group and its subgroup"/> ## proceeds as follows. ## <List> ## <Item> ## If it is called with the two arguments <A>super</A> and <A>sub</A>, ## and if <C>HasParent( <A>sub</A> )</C> and ## <C>IsIdenticalObj( <A>super</A>, Parent( <A>sub</A> ) )</C> ## are <K>true</K>, <C>IndexInParent</C> is called ## with argument <A>sub</A>, and the result is returned. ## </Item> ## <Item> ## Otherwise, <C>IndexOp</C> is called with the same arguments that ## <Ref Oper="Index" Label="for a group and its subgroup"/> was called with, ## and the result is returned. ## </Item> ## </List> ## (Note that it is in principle possible to install even ## <Ref Oper="Index" Label="for a group and its subgroup"/> ## and <C>IndexOp</C> methods ## for a number of arguments different from two, ## with <Ref Func="InstallOtherMethod"/>, see <Ref Sect="Attributes"/>). ## <P/> ## The call of <Ref Func="InParentFOA"/> declares the operations and the ## attribute as described above, ## with names <A>name</A>, <A>name</A><C>Op</C>, ## and <A>name</A><C>InParent</C>. ## <A>super-req</A> and <A>sub-req</A> specify the required filters for the ## first and second argument of the operation <A>name</A><C>Op</C>, ## which are needed to create this operation with ## <Ref Func="DeclareOperation"/>. ## <A>sub-req</A> is also the required filter for the corresponding ## attribute <A>name</A><C>InParent</C>; ## note that <Ref Filt="HasParent"/> is <E>not</E> required ## for the argument <A>U</A> of <A>name</A><C>InParent</C>, ## because even without a parent stored, ## <C>Parent( <A>U</A> )</C> is legal, meaning <A>U</A> itself ## (see <Ref Sect="Parents"/>). ## The fourth argument must be <Ref Func="DeclareProperty"/> ## if <A>name</A><C>InParent</C> takes only boolean values (for example in ## the case <C>IsNormalInParent</C>), ## and <Ref Func="DeclareAttribute"/> otherwise. ## <P/> ## For example, to set up the three objects ## <Ref Oper="Index" Label="for a group and its subgroup"/>, <C>IndexOp</C>, ## and <C>IndexInParent</C> together, ## the declaration file <F>lib/domain.gd</F> contains the following line of ## code. ## <Log><![CDATA[ ## InParentFOA( "Index", IsGroup, IsGroup, DeclareAttribute ); ## ]]></Log> ## <P/> ## Note that no methods need be installed for ## <Ref Oper="Index" Label="for a group and its subgroup"/> ## and <C>IndexInParent</C>. ## </Description> ## </ManSection> ## <#/GAPDoc> ##
BIND_GLOBAL( "InParentFOA", function( name, superreq, subreq, DeclareAorP )
local str, oper, attr, func;
# Declare the attribute or property # (for cases where the first argument is the parent of the second).
str:= SHALLOW_COPY_OBJ( name );
APPEND_LIST_INTR( str, "InParent" );
DeclareAorP( str, subreq );
attr:= VALUE_GLOBAL( str );
# Create the wrapper operation that mainly calls the operation, # but also checks resp. sets the attribute if the first argument # is identical with the parent of the second.
DeclareOperation( name, [ superreq, subreq ] );
func:= VALUE_GLOBAL( name );
# Install the methods for the wrapper that calls the operation.
str:= "try to exploit the in-parent attribute ";
APPEND_LIST_INTR( str, name );
APPEND_LIST_INTR( str, "InParent" );
InstallMethod( func,
str,
[ superreq, subreq ], function( super, sub )
local value; if HasParent( sub ) and IsIdenticalObj( super, Parent( sub ) ) then
value:= attr( sub ); else
value:= oper( super, sub ); fi;
return value; end );
# Install the method for the attribute that calls the operation.
str:= "method that calls the two-argument operation ";
APPEND_LIST_INTR( str, name );
APPEND_LIST_INTR( str, "Op" );
InstallMethod( attr, str, [ subreq and HasParent ],
D -> oper( Parent( D ), D ) ); end );
############################################################################# ## #F RepresentativeFromGenerators( <GeneratorsOfStruct> ) ## ## <ManSection> ## <Func Name="RepresentativeFromGenerators" Arg='GeneratorsOfStruct'/> ## ## <Description> ## We can get a representative of a domain by taking an element of a ## suitable generators list, so the problem is to specify the generators. ## </Description> ## </ManSection> ##
BIND_GLOBAL( "RepresentativeFromGenerators", function( GeneratorsOfStruct )
return function( D )
D:= GeneratorsOfStruct( D ); if IsEmpty( D ) then
TryNextMethod(); fi;
return Representative( D ); end; end );
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.26 Sekunden
(vorverarbeitet am 2026-10-13)
¤
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 und die Messung sind noch experimentell.