Domains and their Elements
<#Include Label="[1]{domain}">

An introduction to the most important facts about domains is given in Chapter .

There are only few operations especially for domains (see ), operations such as and are defined for the more general situation of collections (see Chapter ).

Operational Structure of Domains

Domains have an operational structure, that is, a collection of operations under which the domain is closed. For example, a group is closed under multiplication, taking the zeroth power of elements, and taking inverses of elements. The operational structure may be empty, examples of domains without additional structure are the underlying relations of general mappings (see ).

The operations under which a domain is closed are a subset of the operations that the elements of a domain admit. It is possible that the elements admit more operations. For example, matrices can be multiplied and added. But addition plays no role in a group of matrices, and multiplication plays no role in a vector space of matrices. In particular, a matrix group is not closed under addition.

Note that the elements of a domain exist independently of this domain, usually they existed already before the domain was created. So it makes sense to say that a domain is generated by some elements with respect to certain operations.

Of course, different sets of operations yield different notions of generation. For example, the group generated by some matrices is different from the ring generated by these matrices, and these two will in general be different from the vector space generated by the same matrices, over a suitable field.

The other way round, the same set of elements may be obtained by generation w.r.t. different notions of generation. For example, one can get the group generated by two elements g and h also as the monoid generated by the elements g, g^{{-1}}, h, h^{{-1}}; if both g and h have finite order then of course the group generated by g and h coincides with the monoid generated by g and h.

Additionally to the operational structure, a domain can have properties. For example, the multiplication of a group is associative, and the multiplication in a field is commutative.

Note that associativity and commutativity depend on the set of elements for which one considers the multiplication, i.e., it depends on the domain. For example, the multiplication in a full matrix ring over a field is not commutative, whereas its restriction to the set of diagonal matrices is commutative.

One important difference between the operational structure and the properties of a domain is that the operational structure is fixed when the domain is constructed, whereas properties can be discovered later. For example, take a domain whose operational structure is given by closure under multiplication. If it is discovered that the inverses of all its elements also do (by chance) lie in this domain, being closed under taking inverses is not added to the operational structure. But a domain with operational structure of multiplication, taking the identity, and taking inverses will be treated as a group as soon as the multiplication is found out to be associative for this domain.

The operational structures available in &GAP; form a hierarchy, which is explicitly formulated in terms of domain categories, see .

Equality and Comparison of Domains
<#Include Label="[2]{domain}">

Constructing Domains

For several operational structures (see ), &GAP; provides functions to construct domains with this structure (note that such functions do not exist for all operational structures). For example, returns groups, returns vector spaces etc.:

Struct
Struct( arg1, arg2, ... )

The syntax of these functions may vary, dependent on the structure in question. Usually a domain is constructed as the closure of some elements under the given operations, that is, the domain is given by its generators. For example, a group can be constructed from a list of generating permutations or matrices or whatever is admissible as group elements, and a vector space over a given field F can be constructed from F and a list of appropriate vectors.

The idea of generation and generators in &GAP; is that the domain returned by a function such as Group, Algebra, or FreeLeftModule contains the given generators. This implies that the generators of a group must know how they are multiplied and inverted, the generators of a module must know how they are added and how scalar multiplication works, and so on. Thus one cannot use for example permutations as generators of a vector space.

The function Struct first checks whether the arguments admit the construction of a domain with the desired structure. This is done by calling the operation

IsGeneratorsOfStruct( [info, ]gens )

IsGeneratorsOfStruct

where arglist is the list of given generators and info an argument of Struct, for example the field of scalars in the case that a vector space shall be constructed. If the check failed then Struct returns fail, otherwise it returns the result of StructByGenerators (see below). (So if one wants to omit the check then one should call StructByGenerators directly.)

GeneratorsOfStruct
GeneratorsOfStruct( D)

For a domain D with operational structure corresponding to Struct, the attribute GeneratorsOfStruct returns a list of corresponding generators of D. If these generators were not yet stored in D then D must know some generators if GeneratorsOfStruct shall have a chance to compute the desired result; for example, monoid generators of a group can be computed from known group generators (and vice versa). Note that several notions of generation may be meaningful for a given domain, so it makes no sense to ask for the generators of a domain. Further note that the generators may depend on other information about D. For example the generators of a vector space depend on the underlying field of scalars; the vector space generators of a vector space over the field with four elements need not generate the same vector space when this is viewed as a space over the field with two elements.

StructByGenerators
StructByGenerators( [info, ]gens )

Domain construction from generators gens is implemented by operations StructByGenerators, which are called by the simple functions Struct; methods can be installed only for the operations. Note that additional information info may be necessary to construct the domain; for example, a vector space needs the underlying field of scalars in addition to the list of vector space generators. The GeneratorsOfStruct value of the returned domain need not be equal to gens. But if a domain D is printed as Struct([a, b, ...]) and if there is an attribute GeneratorsOfStruct then the list GeneratorsOfStruct( D ) is guaranteed to be equal to [ a, b, ... ].

StructWithGenerators
StructWithGenerators( [info, ]gens )

The only difference between StructByGenerators and StructWithGenerators is that the latter guarantees that the GeneratorsOfStruct value of the result is equal to the given generators gens.

ClosureStruct
ClosureStruct( D, obj )

For constructing a domain as the closure of a given domain with an element or another domain, one can use the operation ClosureStruct. It returns the smallest domain with operational structure corresponding to Struct that contains D as a subset and obj as an element.

Changing the Structure

The same set of elements can have different operational structures. For example, it may happen that a monoid M does in fact contain the inverses of all of its elements; if M has not been constructed as a group (see ) then it is reasonable to ask for the group that is equal to M.

AsStruct
AsStruct( [info, ]D )

If D is a domain that is closed under the operational structure given by Struct then AsStruct returns a domain E that consists of the same elements (that is, D = E) and that has this operational structure (that is, IsStruct( E ) is true); if D is not closed under the structure given by Struct then AsStruct returns fail.

If additional information besides generators are necessary to define D then the argument info describes the value of this information for the desired domain. For example, if we want to view D as a vector space over the field with two elements then we may call AsVectorSpace( GF(2), D ); this allows us to change the underlying field of scalars, for example if D is a vector space over the field with four elements. Again, if D is not equal to a domain with the desired structure and additional information then fail is returned.

In the case that no additional information info is related to the structure given by Struct, the operation AsStruct is in fact an attribute (see ).

See the index of the &GAP; Reference Manual for an overview of the available AsStruct functions.

Changing the Representation

Often it is useful to answer questions about a domain via computations in a different but isomorphic domain. In the sense that this approach keeps the structure and changes the underlying set of elements, it can be viewed as a counterpart of keeping the set of elements and changing its structure (see ).

One reason for doing so can be that computations with the elements in the given domain are not very efficient. For example, if one is given a solvable matrix group (see Chapter ) then one can compute an isomorphism to a polycyclicly presented group G, say (see Chapter ); the multiplication of two matrices –which is essentially determined by the dimension of the matrices– is much more expensive than the multiplication of two elements in G –which is essentially determined by the composition length of G.

IsomorphismRep Struct
IsomorphismRep Struct( D )

If D is a domain that is closed under the operational structure given by Struct then IsomorphismRep Struct returns a mapping hom from D to a domain E having structure given by Struct, such that hom respects the structure Struct and Rep describes the representation of the elements in E. If no domain E with the required properties exists then fail is returned.

For example, takes a group as its argument and returns a group homomorphism (see ) onto an isomorphic permutation group (see Chapter ) provided the original group is finite; for infinite groups, returns fail. Similarly, returns a group homomorphism from its argument to a polycyclicly presented group (see ) if the argument is polycyclic, and fail otherwise.

See the index of the &GAP; Reference Manual for an overview of the available IsomorphismRep Struct functions.

Domain Categories

As mentioned in , the operational structure of a domain is fixed when the domain is constructed. For example, if D was constructed by then D is in general not regarded as a group in &GAP;, even if D is in fact closed under taking inverses. In this case, returns false for D. The operational structure determines which operations are applicable for a domain, so for example is not defined for D and therefore will signal an error.

IsStruct
IsStruct( D )

The functions IsStruct implement the tests whether a domain D has the respective operational structure (upon construction). IsStruct is a filter (see ) that involves certain categories (see ) and usually also certain properties (see ). For example, is equivalent to IsMagmaWithInverses and IsAssociative, the first being a category and the second being a property.

Implications between domain categories describe the hierarchy of operational structures available in &GAP;. Here are some typical examples.

is implied by each domain category,
is implied by each category that describes the closure under multiplication *,
is implied by each category that describes the closure under addition +,
implies ; a magma-with-one is a magma such that each element (and thus also the magma itself) can be asked for its zeroth power,
implies ; a magma-with-inverses is a magma such that each element can be asked for its inverse; important special cases are groups, which in addition are associative,
a ring is a magma that is also an additive group,
a ring-with-one is a ring that is also a magma-with-one,
a division ring is a ring-with-one that is also closed under taking inverses of nonzero elements,
a field is a commutative division ring.

Each operational structure Struct has associated with it a domain category IsStruct, and operations StructByGenerators for constructing a domain from generators, GeneratorsOfStruct for storing and accessing generators w.r.t. this structure, ClosureStruct for forming the closure, and AsStruct for getting a domain with the desired structure from one with weaker operational structure and for testing whether a given domain can be regarded as a domain with Struct.

The functions applicable to domains with the various structures are described in the corresponding chapters of the Reference Manual. For example, functions for rings, fields, groups, and vector spaces are described in Chapters , , , and , respectively. More general functions for arbitrary collections can be found in Chapter .

Parents
<#Include Label="Parent">

Constructing Subdomains
Subdomains
For many domains D, there are functions that construct certain subsets S of D as domains with parent (see ) already set to D. For example, if G is a group that contains the elements in the list gens then Subgroup( G, gens ) returns a group S that is generated by the elements in gens and with Parent( S ) = G.

Substruct
Substruct( D, gens )

More general, if D is a domain whose algebraic structure is given by the function Struct (for example Group, Algebra, Field) then the function Substruct (for example Subgroup, Subalgebra, Subfield) returns domains with structure Struct and parent set to the first argument.

SubstructNC
SubstructNC( D, gens )

Each function Substruct checks that the Struct generated by gens is in fact a subset of D. If one wants to omit this check then one can call SubstructNC instead; the suffix NC stands for no check.

AsSubstruct
AsSubstruct( D, S )

first constructs AsStruct( [info, ]S ), where info depends on D and S, and then sets the parent (see ) of this new domain to D.

IsSubstruct
IsSubstruct( D, S )

There is no real need for functions that check whether a domain S is a Substruct of a domain D, since this is equivalent to the checks whether S is a Struct and S is a subset of D. Note that in many cases, only the subset relation is what one really wants to check, and that appropriate methods for the operation are available for many special situations, such as the test whether a group is contained in another group, where only generators need to be checked.

If a function IsSubstruct is available in &GAP; then it is implemented as first a call to IsStruct for the second argument and then a call to for the two arguments.

Operations for Domains

For the meaning of the attributes , , in the case of a domain argument, see .

<#Include Label="IsGeneralizedDomain"> <#Include Label="GeneratorsOfDomain"> <#Include Label="Domain">

Attributes and Properties of Elements

The following attributes and properties for elements and domains correspond to the operational structure.

<#Include Label="Characteristic"> <#Include Label="OneImmutable"> <#Include Label="ZeroImmutable"> <#Include Label="MultiplicativeZeroOp"> <#Include Label="IsOne"> <#Include Label="IsZero"> <#Include Label="IsIdempotent"> <#Include Label="InverseImmutable"> <#Include Label="AdditiveInverseImmutable"> <#Include Label="Order">

Comparison Operations for Elements

Binary comparison operations have been introduced already in . The underlying operations for which methods can be installed are the following.

\= and \<
equality
comparison
Note that the comparisons via <>, <=, >, and >= are delegated to the operations and .

In general, objects in different families cannot be compared with . For the reason and for exceptions from this rule, see .
<#Include Label="CanEasilyCompareElements">

Arithmetic Operations for Elements
Binary
arithmetic operations have been introduced already in . The underlying operations for which methods can be installed are the following.

\+, \*, \/, \^, \mod
addition
multiplication
division
exponentiation
remainder
For details about special methods for , , and , consult the appropriate index entries for them.
<#Include Label="LeftQuotient"> <#Include Label="Comm"> <#Include Label="LieBracket"> <#Include Label="Sqrt">

Relations Between Domains

Domains are often constructed relative to other domains. The probably most usual case is to form a subset of a domain, for example the intersection (see ) of two domains, or a Sylow subgroup of a given group (see ).

In such a situation, the new domain can gain knowledge by exploiting that several attributes are maintained under taking subsets. For example, the intersection of an arbitrary domain with a finite domain is clearly finite, a Sylow subgroup of an abelian group is abelian, too, and so on.

Since usually the new domain has access to the knowledge of the old domain(s) only when it is created (see for the exception), this is the right moment to take advantage of the subset relation, using .

Analogous relations occur when a factor structure is created from a domain and a subset (see ), and when a domain isomorphic to a given one is created (see ).

The functions , , and are used to tell &GAP; under what conditions an attribute is maintained under taking subsets, or forming factor structures or isomorphic domains. This is used only when a new attribute is created, see . For the attributes already available, such as and , the maintenances are already notified.

<#Include Label="UseSubsetRelation"> <#Include Label="UseFactorRelation"> <#Include Label="UseIsomorphismRelation">

<#Include Label="InstallSubsetMaintenance"> <#Include Label="InstallFactorMaintenance"> <#Include Label="InstallIsomorphismMaintenance">

Useful Categories of Elements

This section and the following one are rather technical, and may be interesting only for those &GAP; users who want to implement new kinds of elements.

It deals with certain categories of elements that are useful mainly for the design of elements, from the viewpoint that one wants to form certain domains of these elements. For example, a domain closed under multiplication * (a so-called magma, see Chapter ) makes sense only if its elements can be multiplied, and the latter is indicated by the category for each element. Again note that the underlying idea is that a domain is regarded as generated by given elements, and that these elements carry information about the desired domain. For general information on categories and their hierarchies, see .

More special categories of this kind are described in the contexts where they arise, they are , , , and .

<#Include Label="IsExtAElement"> <#Include Label="IsNearAdditiveElement"> <#Include Label="IsAdditiveElement"> <#Include Label="IsNearAdditiveElementWithZero"> <#Include Label="IsAdditiveElementWithZero"> <#Include Label="IsNearAdditiveElementWithInverse"> <#Include Label="IsAdditiveElementWithInverse"> <#Include Label="IsExtLElement"> <#Include Label="IsExtRElement"> <#Include Label="IsMultiplicativeElement"> <#Include Label="IsMultiplicativeElementWithOne"> <#Include Label="IsMultiplicativeElementWithZero"> <#Include Label="IsMultiplicativeElementWithInverse"> <#Include Label="IsVector"> <#Include Label="IsNearRingElement"> <#Include Label="IsRingElement"> <#Include Label="IsNearRingElementWithOne"> <#Include Label="IsRingElementWithOne"> <#Include Label="IsNearRingElementWithInverse"> <#Include Label="IsRingElementWithInverse">

Useful Categories for all Elements of a Family

The following categories of elements are to be understood mainly as categories for all objects in a family, they are usually used as third argument of NewFamily (see ). The purpose of each of the following categories is then to guarantee that each collection of its elements automatically lies in its collections category (see ).

For example, the multiplication of permutations is associative, and it is stored in the family of permutations that each permutation lies in . As a consequence, each magma consisting of permutations (more precisely: each collection that lies in the family CollectionsFamily( PermutationsFamily ), see ) automatically lies in CategoryCollections( IsAssociativeElement ). A magma in this category is always known to be associative, via a logical implication (see ).

Similarly, if a family knows that all its elements are in the categories and , then each algebra of these elements is automatically known to be a Lie algebra (see Chapter ).

<#Include Label="IsAssociativeElement"> <#Include Label="IsAdditivelyCommutativeElement"> <#Include Label="IsCommutativeElement"> <#Include Label="IsFiniteOrderElement"> <#Include Label="IsJacobianElement"> <#Include Label="IsZeroSquaredElement">