diff --git a/dev/extensions/index.html b/dev/extensions/index.html index b557892..75d70da 100644 --- a/dev/extensions/index.html +++ b/dev/extensions/index.html @@ -1,5 +1,5 @@ -Extensions · GroupsCore.jl

Extensions

The following functions are defined in GroupsCore only to be extended externally:

isabelian
+Extensions · GroupsCore.jl

Extensions

The following (empty) functions are defined in GroupsCore only to be extended externally:

isabelian
 issolvable
 isnilpotent
 isperfect
@@ -10,4 +10,4 @@
 centralizer
 normalizer
 stabilizer
-right_coset_representatives
GroupsCore.indexFunction
index(H::Gr, G::Gr) where {Gr <: Group}

Return the index $|G : H|$, where $H \subseteq G$. If $H$ is not contained in $G$, an error is thrown.

source
GroupsCore.left_coset_representativesFunction
left_coset_representatives(H::Gr, G::Gr) where {Gr <: Group}

Return representatives of the left cosets $h G$ where $h$ are elements of $H$. If $H$ is not contained in $G$, an error is thrown.

source
+right_coset_representatives
GroupsCore.indexFunction
index(H::Gr, G::Gr) where {Gr <: Group}

Return the index |G : H|, where H ≤ G is a subgroup. If H is not contained in G, an error is thrown.

source
GroupsCore.left_coset_representativesFunction
left_coset_representatives(H::Gr, G::Gr) where {Gr <: Group}

Return representatives of the left cosets h G where h are elements of H. If H is not contained in G, an error is thrown.

source
diff --git a/dev/group_elements/index.html b/dev/group_elements/index.html index df23735..ba19362 100644 --- a/dev/group_elements/index.html +++ b/dev/group_elements/index.html @@ -1,3 +1,7 @@ -Group elements · GroupsCore.jl

Group elements

GroupsCore defines abstract type GroupElement, which all implementations of group elements should subtype.

Obligatory methods

The elements which are not of isbitstype should extend

Base.deepcopy_internal(g::GroupElement, ::IdDict)

according to Base.deepcopy docstring. Due to our assumption on parents of group elements (acting as local singleton objects), a group element and its deepcopy should have identical (i.e. ===) parents.

The remaining obligatory methods are:

Base.parentMethod
parent(g::GroupElement)

Return the parent object of the group element.

source
Base.:==Method
==(g::GEl, h::GEl) where {GEl <: GroupElement}

Return true if and only if the mathematical equality $g = h$ holds.

Note

This function may not return, due to unsolvable word problem.

source
Base.invMethod
inv(g::GroupElement)

Return $g^{-1}$, the group inverse.

source
Base.:*Method
*(g::GEl, h::GEl) where {GEl <: GroupElement}

Return $g h$, the result of group binary operation.

source
Note

If finiteness of a group can be decided based on its type there is no need to extend isfiniteorder.

Implemented methods

Using the obligatory methods we implement the rest of the functions in GroupsCore. For starters, the first of these are:

:(^)(::GroupElement, ::Integer)
-:(/)(::GEl, ::GEl) where {GEl <: GroupElement}

and

Base.oneMethod
one(g::GroupElement)

Return the identity element in the group of $g$.

source
Base.isequalMethod
isequal(g::GEl, h::GEl) where {GEl <: GroupElement}

Return the "best effort" equality for group elements.

The implication isequal(g, h)$g = h$, must be always satisfied, i.e. isequal(g, h) might return false even if g == h holds (i.e. $g$ and $h$ are mathematically equal).

For example, in a finitely presented group, isequal may return the equality of words.

source
GroupsCore.orderMethod
order(::Type{T} = BigInt, g::GroupElement) where T

Return the order of $g$ as an instance of I. If $g$ is of infinite order GroupsCore.InfiniteOrder exception will be thrown.

Warning

Only arbitrary sized integers are required to return a mathematically correct answer.

source
Base.conjFunction
conj(g::GEl, h::GEl) where {GEl <: GroupElement}

Return conjugation of $g$ by $h$, i.e. $h^{-1} g h$.

source
GroupsCore.commutatorFunction
commutator(g::GEl, h::GEl, k::GEl...) where {GEl <: GroupElement}

Return the left associative iterated commutator $[[g, h], ...]$, where $[g, h] = g^{-1} h^{-1} g h$.

source

Performance modifications

Some of the mentioned implemented methods may be altered for performance reasons:

Base.similarMethod
similar(g::GroupElement)

Return a group element sharing the parent with $g$. Might be arbitrary and possibly uninitialized.

source
Base.isoneMethod
isone(g::GroupElement)

Return true if $g$ is the identity element.

source

Mutable API

Warning

Work-in-progress.

Mutable API is considered private and hence may change between versions without warning.

For the purpose of mutable arithmetic the following methods may be overloaded to provide more tailored versions for a given type and reduce the allocations. These functions should be used when writing libraries, in performance critical sections. However one should only use the returned value and there are no guarantees on in-place modifications actually happening.

All of these functions (possibly) alter only the first argument, and must unalias their arguments when necessary.

GroupsCore.inv!Function
inv!(out::GEl, g::GEl) where {GEl <: GroupElement}

Return inv(g), possibly modifying out. Aliasing of g with out is allowed.

source
GroupsCore.mul!Function
mul!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return $g h$, possibly modifying out. Aliasing of g or h with out is allowed.

source
GroupsCore.div_left!Function
div_left!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return $h^{-1} g$, possibly modifying out. Aliasing of g or h with out is allowed.

source
GroupsCore.div_right!Function
div_right!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return $g h^{-1}$, possibly modifying out. Aliasing of g or h with out is allowed.

source
GroupsCore.conj!Function
conj!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return $h^{-1} g h$, possibly modifying out. Aliasing of g or h with out is allowed.

source
GroupsCore.commutator!Function
commutator!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return $g^{-1} h^{-1} g h$, possibly modifying out. Aliasing of g or h with out is allowed.

source
+Group elements · GroupsCore.jl

Group elements

GroupsCore defines abstract type GroupElement, which all implementations of group elements should subtype.

Obligatory methods

Base.parentMethod
parent(g::GroupElement)

Return the parent object of the group element.

source
Base.:==Method
==(g::GEl, h::GEl) where {GEl <: GroupElement}

Return the best effort equality for group elements.

If ==(g, h) returns truethen the mathematical equalityg == hholds. However==(g, h)may returnfalseeven ifgandh` represent mathematically equal group elements.

For example, in a finitely presented group, == may return the equality of words.

Note

This function may not return due to unsolvable word problem.

source
GroupsCore.isfiniteorderMethod
isfiniteorder(g::GroupElement)

Return true if g is of finite order, possibly without computing it.

Note

If finiteness of a group can be decided based on its type there is no need to extend isfiniteorder for its elements.

source

As well as the two arithmetic operations:

Base.inv(::GroupElement)
+Base.:(*)(::GEl, ::GEl) where {GEl <: GroupElement}

A note on deepcopy

The elements which are not of isbitstype should extend

Base.deepcopy_internal(g::GroupElement, ::IdDict)

according to Base.deepcopy docstring. Due to our assumption on parents of group elements (acting as local singleton objects), a group element and its deepcopy should have identical (i.e. ===) parents.

Implemented methods

Using the obligatory methods we implement the rest of the functions in GroupsCore. For starters, the first of these are:

Base.:(^)(::GroupElement, ::Integer)
+Base.:(/)(::GEl, ::GEl) where {GEl <: GroupElement}
+Base.one(::GroupElement)

and

GroupsCore.orderMethod
order([::Type{T} = BigInt, ]g::GroupElement) where T

Return the order of g as an instance of T. If g is of infinite order GroupsCore.InfiniteOrder exception will be thrown.

Warning

Only arbitrary sized integers are required to return a mathematically correct answer.

source
Base.conjFunction
conj(g::GEl, h::GEl) where {GEl <: GroupElement}

Return the conjugation of g by h, i.e. inv(h)*g*h.

source
GroupsCore.commutatorFunction
commutator(g::GEl, h::GEl, k::GEl...) where {GEl <: GroupElement}

Return the left associative iterated commutator $[[g, h], ...]$, where $[g, h] = g^{-1} h^{-1} g h$.

source

Moreover we provide basic implementation which should be altered for performance reasons:

Base.:(^)(g::GroupElement, n::Integer)
+Groups.Core.order([::Type{T}], g::GroupElement) where T
+Base.hash(::GroupElement, ::UInt)

Mutable API

Warning

Work-in-progress. Mutable API is considered private and hence may change between versions without warning.

For the purpose of mutable arithmetic the following methods may be overloaded to provide more tailored versions for a given type and reduce the allocations. These functions should be used when writing libraries, in performance critical sections. However one should only use the returned value and there are no guarantees on in-place modifications actually happening.

All of these functions (possibly) alter only the first argument, and must unalias their arguments when necessary.

GroupsCore.inv!Function
inv!(out::GEl, g::GEl) where {GEl <: GroupElement}

Return inv(g), possibly modifying out. Aliasing of g with out is allowed.

source
GroupsCore.mul!Function
mul!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return g*h, possibly modifying out. Aliasing of g or h with out is allowed.

source
GroupsCore.div_left!Function
div_left!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return inv(h)*g, possibly modifying out. Aliasing of g or h with out is allowed.

source
GroupsCore.div_right!Function
div_right!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return g*inv(h), possibly modifying out. Aliasing of g or h with out is allowed.

source
GroupsCore.conj!Function
conj!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return inv(h)*g*h, possibly modifying out. Aliasing of g or h with out is allowed.

source
GroupsCore.commutator!Function
commutator!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}

Return inv(g)*inv(h)*g*h, possibly modifying out. Aliasing of g or h with out is allowed.

source
diff --git a/dev/groups/index.html b/dev/groups/index.html index 3969cb8..7d8a31c 100644 --- a/dev/groups/index.html +++ b/dev/groups/index.html @@ -1,2 +1,2 @@ -Groups · GroupsCore.jl

Groups

The abstract type Group encompasses all groups. Since these are already abstract, we skip the Abstract prefix.

Assumptions

GroupsCore implements some methods with default values, which may not be generally true for all groups. The intent is to limit the extent of the required interface. This require special care when implementing groups that need to override these default methods.

The methods we currently predefine are:

  • GroupsCore.hasgens(::Group) = true

This is based on the assumption that reasonably generic functions manipulating groups can be implemented only with access to a generating set.

  • For finite groups only we define Base.length(G) = order(Int, G)
Danger

In general length is used for iteration purposes only. If you are interested in the number of distinct elements of a group, use order(::Type{<:Integer}, ::Group). For more information see Iteration.

Obligatory methods

Here we list the minimal set of functions that a group object must extend to implement the Group interface.

Base.oneMethod
one(G::Group)

Return the identity element of the group $G$.

source
GroupsCore.orderMethod
order(::Type{T} = BigInt, G::Group) where T

Return the order of $G$ as an instance of T. If $G$ is of infinite order, GroupsCore.InfiniteOrder exception will be thrown.

Warning

Only arbitrary sized integers are required to return a mathematically correct answer.

source
GroupsCore.gensMethod
gens(G::Group)

Return a random-access collection of generators of $G$.

The result of this function is undefined unless GroupsCore.hasgens(G) return true.

source
Missing docstring.

Missing docstring for rand. Check Documenter's build log for details.

Iteration

If a group is defined by generators (i.e. hasgens(G) returns true) an important aspect of this interface is the iteration over a group.

Iteration over infinite objects seem to be useful only when the returned elements explore the whole group. To be precise, for the free group $F_2 = ⟨a,b⟩$, one could implement iteration by sequence

\[a, a^2, a^3, \ldots,\]

which is arguably less useful than

\[a, b, a^{-1}, b^{-1}, ab, \ldots.\]

Therefore we put the following assumptions on iteration.

  • Iteration is mandatory only if hasgens(G) returns true.
  • The first element of the iteration (e.g. given by Base.first) is the group identity.
  • Iteration over a finitely generated group should exhaust every fixed radius ball around the identity (in word-length metric associated to gens(G)) in finite time.

These are just the conventions, the iteration interface consists of standard julia methods:

Base.IteratorSizeMethod
IteratorSize(::Type{Gr}) where {Gr <: Group}

Given the type of a group, return one of the following values:

  • Base.IsInfinite() if all instances of groups of type Gr are infinite.
  • Base.HasLength() or Base.HasShape{N}() if all instances are finite.
  • Base.SizeUnknown() otherwise, [the default].
source

In contrast to julia we default to Base.SizeUnknown() to provide a mathematically correct fallback. If your group is finite by definition, implementing the correct IteratorSize (i.e. Base.HasLength(), or Base.HasShape{N}()) will simplify several other methods, which will be then optimized to work only based on the type of the group. In particular when the information is derivable from the type, there is no need to extend Base.isfinite.

Note

In the case that IteratorSize(Gr) == IsInfinite(), one should define Base.length(Gr) to be a "best effort", length of the group iterator.

For practical reasons the largest group you could iterate over in your lifetime is of order that fits into an Int. For example, $2^{63}$ nanoseconds comes to 290 years.

Additional methods

Base.isfiniteMethod
isfinite(G::Group)

Test whether group $G$ is finite.

The default implementation is based on Base.IteratorSize. Only groups of returning Base.SizeUnknown() should extend this method.

source
GroupsCore.istrivialMethod
istrivial(G::Group)

Test whether group $G$ is trivial.

The default implementation is based on isfinite and order.

source
+Groups · GroupsCore.jl

Groups

The abstract type Group encompasses all multiplicative groups. Since these are already abstract, we skip the Abstract prefix.

Assumptions

GroupsCore implements some methods with default values, which may not be generally true for all groups. The intent is to limit the extent of the required interface. This require special care when implementing groups that need to override these default methods.

The methods we currently predefine are:

  • GroupsCore.hasgens(::Group) = true This is based on the assumption that reasonably generic functions manipulating groups can be implemented only with access to a generating set.

  • For finite groups only we define Base.length(G) = order(Int, G)

Danger

In general length is used for iteration purposes only. If you are interested in the number of distinct elements of a group, use order(::Type{<:Integer}, ::Group). For more information see Iteration.

Obligatory methods

Here we list the minimal set of functions that a group object must extend to implement the Group interface:

  • Base.one(::Group) and
GroupsCore.orderMethod
order([::Type{T} = BigInt, ]G::Group) where T

Return the order of G as an instance of T. If G is of infinite order, GroupsCore.InfiniteOrder exception will be thrown.

Warning

Only arbitrary sized integers are required to return a mathematically correct answer.

source

Iteration

If a group is defined by generators (i.e. hasgens(G) returns true) an important aspect of this interface is the iteration over a group.

Iteration over infinite objects seem to be useful only when the returned elements explore the whole group. To be precise, for the free group $F_2 = ⟨a,b⟩$, one could implement iteration by sequence

\[a, a^2, a^3, \ldots,\]

which is arguably less useful than

\[a, b, a^{-1}, b^{-1}, ab, \ldots.\]

Therefore we put the following assumptions on iteration.

  • Iteration is mandatory only if hasgens(G) returns true.
  • The first element of the iteration (e.g. given by Base.first) is the group identity.
  • Iteration over a finitely generated group should exhaust every fixed radius ball around the identity (in word-length metric associated to gens(G)) in finite time.
  • There is no requirement that in the iteration sequence elements are returned only once.

These are just the conventions, the iteration interface consists of standard julia methods:

Base.IteratorSizeMethod
IteratorSize(::Type{Gr}) where {Gr <: Group}

Given the type of a group, return one of the following values:

  • Base.IsInfinite() if all instances of groups of type Gr are infinite.
  • Base.HasLength() or Base.HasShape{N}() if all instances are finite.
  • Base.SizeUnknown() otherwise, [the default].
source

In contrast to julia we default to Base.SizeUnknown() to provide a mathematically correct fallback. If your group is finite by definition, implementing the correct IteratorSize (i.e. Base.HasLength(), or Base.HasShape{N}()) will simplify several other methods, which will be then optimized to work only based on the type of the group. In particular when the information is derivable from the type, there is no need to extend Base.isfinite.

Note

In the case that IteratorSize(Gr) == IsInfinite(), one should define Base.length(Gr) to be a "best effort", length of the group iterator. For practical reasons the largest group you could iterate over in your lifetime is of order that fits into an Int. For example, $2^{63}$ nanoseconds comes to 290 years.

Additional methods

Base.isfiniteMethod
isfinite(G::Group)

Test whether group G is finite.

The default implementation is based on Base.IteratorSize. Only groups of returning Base.SizeUnknown() should extend this method.

source
GroupsCore.istrivialMethod
istrivial(G::Group)

Test whether group G is trivial.

The default implementation is based on isfinite and order.

source
diff --git a/dev/index.html b/dev/index.html index 7e640ce..05a799c 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,5 +1,5 @@ -GroupsCore · GroupsCore.jl

GroupsCore

The aim of this package is to standardize the common assumptions and functions on group i.e. to create Group interface.

The protocol consists of two parts:

This is due to the fact that hardly any information can be encoded in Type, we rely on parent objects that represent groups, as well as ordinary group elements. It is assumed that all elements of a group have identical parent (i.e. ===) so that parent objects behave locally as singletons. More on this can be read under AbstractAlgebra.jl.

Examples and Conformance testing

For an implemented interface please have a look at /test folder, where several example implementations are tested against the conformance test suite:

To test the conformance of e.g. CyclicGroup defined above one can run

julia> using GroupsCore
+GroupsCore · GroupsCore.jl

GroupsCore

The aim of this package is to standardize the common assumptions and functions on group i.e. to create Group interface.

The protocol consists of two parts:

This is due to the fact that hardly any information can be encoded in Type, we rely on parent objects that represent groups, as well as ordinary group elements. It is assumed that all elements of a group have identical parent (i.e. ===) so that parent objects behave locally as singletons.

Examples and Conformance testing

For an implemented interface please have a look at /test folder, where several example implementations are tested against the conformance test suite:

To test the conformance of e.g. CyclicGroup defined above one can run

julia> using GroupsCore
 
 julia> include(joinpath(pathof(GroupsCore), "..", "..", "test", "conformance_test.jl"))
 test_GroupElement_interface (generic function with 1 method)
@@ -14,4 +14,4 @@
 Test Summary:   | Pass  Total  Time
 Group interface |   21     21  0.0s
 Test Summary:          | Pass  Total  Time
-GroupElement interface |   95     95  0.0s

Users

+GroupElement interface | 95 95 0.0s

Users

diff --git a/dev/search/index.html b/dev/search/index.html index c3540cc..8f25460 100644 --- a/dev/search/index.html +++ b/dev/search/index.html @@ -1,2 +1,2 @@ -Search · GroupsCore.jl

Loading search...

    +Search · GroupsCore.jl

    Loading search...

      diff --git a/dev/search_index.js b/dev/search_index.js index c778b61..7a8bfb2 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"groups/#H1_groups","page":"Groups","title":"Groups","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"The abstract type Group encompasses all groups. Since these are already abstract, we skip the Abstract prefix.","category":"page"},{"location":"groups/#Assumptions","page":"Groups","title":"Assumptions","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"GroupsCore implements some methods with default values, which may not be generally true for all groups. The intent is to limit the extent of the required interface. This require special care when implementing groups that need to override these default methods.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"The methods we currently predefine are:","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"GroupsCore.hasgens(::Group) = true","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"This is based on the assumption that reasonably generic functions manipulating groups can be implemented only with access to a generating set.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"For finite groups only we define Base.length(G) = order(Int, G)","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"danger: Danger\nIn general length is used for iteration purposes only. If you are interested in the number of distinct elements of a group, use order(::Type{<:Integer}, ::Group). For more information see Iteration.","category":"page"},{"location":"groups/#Obligatory-methods","page":"Groups","title":"Obligatory methods","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"Here we list the minimal set of functions that a group object must extend to implement the Group interface.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"one(::Group)\norder(::Type{T}, ::Group) where T\ngens(::Group)\nrand","category":"page"},{"location":"groups/#Base.one-Tuple{Group}","page":"Groups","title":"Base.one","text":"one(G::Group)\n\nReturn the identity element of the group G.\n\n\n\n","category":"method"},{"location":"groups/#GroupsCore.order-Union{Tuple{T}, Tuple{Type{T}, Group}} where T","page":"Groups","title":"GroupsCore.order","text":"order(::Type{T} = BigInt, G::Group) where T\n\nReturn the order of G as an instance of T. If G is of infinite order, GroupsCore.InfiniteOrder exception will be thrown.\n\nwarning: Warning\nOnly arbitrary sized integers are required to return a mathematically correct answer.\n\n\n\n","category":"method"},{"location":"groups/#GroupsCore.gens-Tuple{Group}","page":"Groups","title":"GroupsCore.gens","text":"gens(G::Group)\n\nReturn a random-access collection of generators of G.\n\nThe result of this function is undefined unless GroupsCore.hasgens(G) return true.\n\n\n\n","category":"method"},{"location":"groups/#Iteration","page":"Groups","title":"Iteration","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"If a group is defined by generators (i.e. hasgens(G) returns true) an important aspect of this interface is the iteration over a group.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Iteration over infinite objects seem to be useful only when the returned elements explore the whole group. To be precise, for the free group F_2 = ab, one could implement iteration by sequence","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"a a^2 a^3 ldots","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"which is arguably less useful than","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"a b a^-1 b^-1 ab ldots","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Therefore we put the following assumptions on iteration.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Iteration is mandatory only if hasgens(G) returns true.\nThe first element of the iteration (e.g. given by Base.first) is the group identity.\nIteration over a finitely generated group should exhaust every fixed radius ball around the identity (in word-length metric associated to gens(G)) in finite time.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"These are just the conventions, the iteration interface consists of standard julia methods:","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Base.iterate\nBase.eltype","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Base.IteratorSize(::Type{<:Group})","category":"page"},{"location":"groups/#Base.IteratorSize-Tuple{Type{<:Group}}","page":"Groups","title":"Base.IteratorSize","text":"IteratorSize(::Type{Gr}) where {Gr <: Group}\n\nGiven the type of a group, return one of the following values:\n\nBase.IsInfinite() if all instances of groups of type Gr are infinite.\nBase.HasLength() or Base.HasShape{N}() if all instances are finite.\nBase.SizeUnknown() otherwise, [the default].\n\n\n\n","category":"method"},{"location":"groups/","page":"Groups","title":"Groups","text":"In contrast to julia we default to Base.SizeUnknown() to provide a mathematically correct fallback. If your group is finite by definition, implementing the correct IteratorSize (i.e. Base.HasLength(), or Base.HasShape{N}()) will simplify several other methods, which will be then optimized to work only based on the type of the group. In particular when the information is derivable from the type, there is no need to extend Base.isfinite.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"note: Note\nIn the case that IteratorSize(Gr) == IsInfinite(), one should define Base.length(Gr) to be a \"best effort\", length of the group iterator.For practical reasons the largest group you could iterate over in your lifetime is of order that fits into an Int. For example, 2^63 nanoseconds comes to 290 years.","category":"page"},{"location":"groups/#Additional-methods","page":"Groups","title":"Additional methods","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"Base.isfinite(G::Group)\nistrivial(G::Group)","category":"page"},{"location":"groups/#Base.isfinite-Tuple{Group}","page":"Groups","title":"Base.isfinite","text":"isfinite(G::Group)\n\nTest whether group G is finite.\n\nThe default implementation is based on Base.IteratorSize. Only groups of returning Base.SizeUnknown() should extend this method.\n\n\n\n","category":"method"},{"location":"groups/#GroupsCore.istrivial-Tuple{Group}","page":"Groups","title":"GroupsCore.istrivial","text":"istrivial(G::Group)\n\nTest whether group G is trivial.\n\nThe default implementation is based on isfinite and order.\n\n\n\n","category":"method"},{"location":"group_elements/#H1_group_elements","page":"Group elements","title":"Group elements","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"GroupsCore defines abstract type GroupElement, which all implementations of group elements should subtype.","category":"page"},{"location":"group_elements/#Obligatory-methods","page":"Group elements","title":"Obligatory methods","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"The elements which are not of isbitstype should extend","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Base.deepcopy_internal(g::GroupElement, ::IdDict)","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"according to Base.deepcopy docstring. Due to our assumption on parents of group elements (acting as local singleton objects), a group element and its deepcopy should have identical (i.e. ===) parents.","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"The remaining obligatory methods are:","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"parent(::GroupElement)\n:(==)(::GEl, ::GEl) where {GEl <: GroupElement}\nisfiniteorder(::GroupElement)\ninv(::GroupElement)\n:(*)(::GEl, ::GEl) where {GEl <: GroupElement}","category":"page"},{"location":"group_elements/#Base.parent-Tuple{GroupElement}","page":"Group elements","title":"Base.parent","text":"parent(g::GroupElement)\n\nReturn the parent object of the group element.\n\n\n\n","category":"method"},{"location":"group_elements/#Base.:==-Union{Tuple{GEl}, Tuple{GEl, GEl}} where GEl<:GroupElement","page":"Group elements","title":"Base.:==","text":"==(g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn true if and only if the mathematical equality g = h holds.\n\nnote: Note\nThis function may not return, due to unsolvable word problem.\n\n\n\n","category":"method"},{"location":"group_elements/#GroupsCore.isfiniteorder-Tuple{GroupElement}","page":"Group elements","title":"GroupsCore.isfiniteorder","text":"isfiniteorder(g::GroupElement)\n\nReturn true if g is of finite order, possibly without computing it.\n\n\n\n","category":"method"},{"location":"group_elements/#Base.inv-Tuple{GroupElement}","page":"Group elements","title":"Base.inv","text":"inv(g::GroupElement)\n\nReturn g^-1, the group inverse.\n\n\n\n","category":"method"},{"location":"group_elements/#Base.:*-Union{Tuple{GEl}, Tuple{GEl, GEl}} where GEl<:GroupElement","page":"Group elements","title":"Base.:*","text":"*(g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn g h, the result of group binary operation.\n\n\n\n","category":"method"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"note: Note\nIf finiteness of a group can be decided based on its type there is no need to extend isfiniteorder.","category":"page"},{"location":"group_elements/#Implemented-methods","page":"Group elements","title":"Implemented methods","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Using the obligatory methods we implement the rest of the functions in GroupsCore. For starters, the first of these are:","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":":(^)(::GroupElement, ::Integer)\n:(/)(::GEl, ::GEl) where {GEl <: GroupElement}","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"and","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"one(::GroupElement)\nisequal(::GEl, ::GEl) where {GEl <: GroupElement}\norder(::Type{T}, ::GroupElement) where T\nconj\n:(^)(::GEl, ::GEl) where {GEl <: GroupElement}\ncommutator","category":"page"},{"location":"group_elements/#Base.one-Tuple{GroupElement}","page":"Group elements","title":"Base.one","text":"one(g::GroupElement)\n\nReturn the identity element in the group of g.\n\n\n\n","category":"method"},{"location":"group_elements/#Base.isequal-Union{Tuple{GEl}, Tuple{GEl, GEl}} where GEl<:GroupElement","page":"Group elements","title":"Base.isequal","text":"isequal(g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn the \"best effort\" equality for group elements.\n\nThe implication isequal(g, h) → g = h, must be always satisfied, i.e. isequal(g, h) might return false even if g == h holds (i.e. g and h are mathematically equal).\n\nFor example, in a finitely presented group, isequal may return the equality of words.\n\n\n\n","category":"method"},{"location":"group_elements/#GroupsCore.order-Union{Tuple{T}, Tuple{Type{T}, GroupElement}} where T","page":"Group elements","title":"GroupsCore.order","text":"order(::Type{T} = BigInt, g::GroupElement) where T\n\nReturn the order of g as an instance of I. If g is of infinite order GroupsCore.InfiniteOrder exception will be thrown.\n\nwarning: Warning\nOnly arbitrary sized integers are required to return a mathematically correct answer.\n\n\n\n","category":"method"},{"location":"group_elements/#Base.conj","page":"Group elements","title":"Base.conj","text":"conj(g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn conjugation of g by h, i.e. h^-1 g h.\n\n\n\n","category":"function"},{"location":"group_elements/#Base.:^-Union{Tuple{GEl}, Tuple{GEl, GEl}} where GEl<:GroupElement","page":"Group elements","title":"Base.:^","text":"^(g::GEl, h::GEl) where {GEl <: GroupElement}\n\nAlias for conj.\n\n\n\n","category":"method"},{"location":"group_elements/#GroupsCore.commutator","page":"Group elements","title":"GroupsCore.commutator","text":"commutator(g::GEl, h::GEl, k::GEl...) where {GEl <: GroupElement}\n\nReturn the left associative iterated commutator g h , where g h = g^-1 h^-1 g h.\n\n\n\n","category":"function"},{"location":"group_elements/#Performance-modifications","page":"Group elements","title":"Performance modifications","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Some of the mentioned implemented methods may be altered for performance reasons:","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"isequal\nBase.:(^)(g::GroupElement, n::Integer)\norder(::Type{T}, g::GroupElement) where T\nBase.hash(::GroupElement, ::UInt)","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"similar(::GroupElement)\nisone(::GroupElement)","category":"page"},{"location":"group_elements/#Base.similar-Tuple{GroupElement}","page":"Group elements","title":"Base.similar","text":"similar(g::GroupElement)\n\nReturn a group element sharing the parent with g. Might be arbitrary and possibly uninitialized.\n\n\n\n","category":"method"},{"location":"group_elements/#Base.isone-Tuple{GroupElement}","page":"Group elements","title":"Base.isone","text":"isone(g::GroupElement)\n\nReturn true if g is the identity element.\n\n\n\n","category":"method"},{"location":"group_elements/#Mutable-API","page":"Group elements","title":"Mutable API","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"warning: Warning\nWork-in-progress.Mutable API is considered private and hence may change between versions without warning.","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"For the purpose of mutable arithmetic the following methods may be overloaded to provide more tailored versions for a given type and reduce the allocations. These functions should be used when writing libraries, in performance critical sections. However one should only use the returned value and there are no guarantees on in-place modifications actually happening.","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"All of these functions (possibly) alter only the first argument, and must unalias their arguments when necessary.","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"GroupsCore.one!\nGroupsCore.inv!\nGroupsCore.mul!\nGroupsCore.div_left!\nGroupsCore.div_right!\nGroupsCore.conj!\nGroupsCore.commutator!","category":"page"},{"location":"group_elements/#GroupsCore.one!","page":"Group elements","title":"GroupsCore.one!","text":"one!(g::GroupElement)\n\nReturn one(g), possibly modifying g.\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.inv!","page":"Group elements","title":"GroupsCore.inv!","text":"inv!(out::GEl, g::GEl) where {GEl <: GroupElement}\n\nReturn inv(g), possibly modifying out. Aliasing of g with out is allowed.\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.mul!","page":"Group elements","title":"GroupsCore.mul!","text":"mul!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn g h, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.div_left!","page":"Group elements","title":"GroupsCore.div_left!","text":"div_left!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn h^-1 g, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.div_right!","page":"Group elements","title":"GroupsCore.div_right!","text":"div_right!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn g h^-1, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.conj!","page":"Group elements","title":"GroupsCore.conj!","text":"conj!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn h^-1 g h, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.commutator!","page":"Group elements","title":"GroupsCore.commutator!","text":"commutator!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn g^-1 h^-1 g h, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n","category":"function"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"CurrentModule = GroupsCore","category":"page"},{"location":"#GroupsCore","page":"GroupsCore","title":"GroupsCore","text":"","category":"section"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"The aim of this package is to standardize the common assumptions and functions on group i.e. to create Group interface.","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"The protocol consists of two parts:","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"Group (parent object) methods,\nGroupElement methods.","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"This is due to the fact that hardly any information can be encoded in Type, we rely on parent objects that represent groups, as well as ordinary group elements. It is assumed that all elements of a group have identical parent (i.e. ===) so that parent objects behave locally as singletons. More on this can be read under AbstractAlgebra.jl.","category":"page"},{"location":"#Examples-and-Conformance-testing","page":"GroupsCore","title":"Examples and Conformance testing","text":"","category":"section"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"For an implemented interface please have a look at /test folder, where several example implementations are tested against the conformance test suite:","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"CyclicGroup","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"To test the conformance of e.g. CyclicGroup defined above one can run","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"using GroupsCore\ninclude(joinpath(pathof(GroupsCore), \"..\", \"..\", \"test\", \"conformance_test.jl\"))\ninclude(joinpath(pathof(GroupsCore), \"..\", \"..\", \"test\", \"cyclic.jl\"))\nlet C = CyclicGroup(15)\n test_Group_interface(C)\n test_GroupElement_interface(rand(C, 2)...)\n nothing\nend","category":"page"},{"location":"#Users","page":"GroupsCore","title":"Users","text":"","category":"section"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"Groups.jl,\nSymbolicWedderburn.jl,\nOscar project.","category":"page"},{"location":"extensions/#Extensions","page":"Extensions","title":"Extensions","text":"","category":"section"},{"location":"extensions/","page":"Extensions","title":"Extensions","text":"The following functions are defined in GroupsCore only to be extended externally:","category":"page"},{"location":"extensions/","page":"Extensions","title":"Extensions","text":"isabelian\nissolvable\nisnilpotent\nisperfect\nderivedsubgroup\ncenter\nsocle\nsylowsubgroup\ncentralizer\nnormalizer\nstabilizer\nright_coset_representatives","category":"page"},{"location":"extensions/","page":"Extensions","title":"Extensions","text":"GroupsCore.index\nGroupsCore.left_coset_representatives","category":"page"},{"location":"extensions/#GroupsCore.index","page":"Extensions","title":"GroupsCore.index","text":"index(H::Gr, G::Gr) where {Gr <: Group}\n\nReturn the index G H, where H subseteq G. If H is not contained in G, an error is thrown.\n\n\n\n","category":"function"},{"location":"extensions/#GroupsCore.left_coset_representatives","page":"Extensions","title":"GroupsCore.left_coset_representatives","text":"left_coset_representatives(H::Gr, G::Gr) where {Gr <: Group}\n\nReturn representatives of the left cosets h G where h are elements of H. If H is not contained in G, an error is thrown.\n\n\n\n","category":"function"}] +[{"location":"groups/#H1_groups","page":"Groups","title":"Groups","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"The abstract type Group encompasses all multiplicative groups. Since these are already abstract, we skip the Abstract prefix.","category":"page"},{"location":"groups/#Assumptions","page":"Groups","title":"Assumptions","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"GroupsCore implements some methods with default values, which may not be generally true for all groups. The intent is to limit the extent of the required interface. This require special care when implementing groups that need to override these default methods.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"The methods we currently predefine are:","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"GroupsCore.hasgens(::Group) = true This is based on the assumption that reasonably generic functions manipulating groups can be implemented only with access to a generating set.\nFor finite groups only we define Base.length(G) = order(Int, G)","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"danger: Danger\nIn general length is used for iteration purposes only. If you are interested in the number of distinct elements of a group, use order(::Type{<:Integer}, ::Group). For more information see Iteration.","category":"page"},{"location":"groups/#Obligatory-methods","page":"Groups","title":"Obligatory methods","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"Here we list the minimal set of functions that a group object must extend to implement the Group interface:","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Base.one(::Group) and","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"order(::Type{T}, ::Group) where T\ngens(::Group)","category":"page"},{"location":"groups/#GroupsCore.order-Union{Tuple{T}, Tuple{Type{T}, Group}} where T","page":"Groups","title":"GroupsCore.order","text":"order([::Type{T} = BigInt, ]G::Group) where T\n\nReturn the order of G as an instance of T. If G is of infinite order, GroupsCore.InfiniteOrder exception will be thrown.\n\nwarning: Warning\nOnly arbitrary sized integers are required to return a mathematically correct answer.\n\n\n\n\n\n","category":"method"},{"location":"groups/#GroupsCore.gens-Tuple{Group}","page":"Groups","title":"GroupsCore.gens","text":"gens(G::Group)\n\nReturn a random-access collection of generators of G.\n\n\n\n\n\n","category":"method"},{"location":"groups/#Iteration","page":"Groups","title":"Iteration","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"If a group is defined by generators (i.e. hasgens(G) returns true) an important aspect of this interface is the iteration over a group.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Iteration over infinite objects seem to be useful only when the returned elements explore the whole group. To be precise, for the free group F_2 = ab, one could implement iteration by sequence","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"a a^2 a^3 ldots","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"which is arguably less useful than","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"a b a^-1 b^-1 ab ldots","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Therefore we put the following assumptions on iteration.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Iteration is mandatory only if hasgens(G) returns true.\nThe first element of the iteration (e.g. given by Base.first) is the group identity.\nIteration over a finitely generated group should exhaust every fixed radius ball around the identity (in word-length metric associated to gens(G)) in finite time.\nThere is no requirement that in the iteration sequence elements are returned only once.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"These are just the conventions, the iteration interface consists of standard julia methods:","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Base.iterate\nBase.eltype","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"Base.IteratorSize(::Type{<:Group})","category":"page"},{"location":"groups/#Base.IteratorSize-Tuple{Type{<:Group}}","page":"Groups","title":"Base.IteratorSize","text":"IteratorSize(::Type{Gr}) where {Gr <: Group}\n\nGiven the type of a group, return one of the following values:\n\nBase.IsInfinite() if all instances of groups of type Gr are infinite.\nBase.HasLength() or Base.HasShape{N}() if all instances are finite.\nBase.SizeUnknown() otherwise, [the default].\n\n\n\n\n\n","category":"method"},{"location":"groups/","page":"Groups","title":"Groups","text":"In contrast to julia we default to Base.SizeUnknown() to provide a mathematically correct fallback. If your group is finite by definition, implementing the correct IteratorSize (i.e. Base.HasLength(), or Base.HasShape{N}()) will simplify several other methods, which will be then optimized to work only based on the type of the group. In particular when the information is derivable from the type, there is no need to extend Base.isfinite.","category":"page"},{"location":"groups/","page":"Groups","title":"Groups","text":"note: Note\nIn the case that IteratorSize(Gr) == IsInfinite(), one should define Base.length(Gr) to be a \"best effort\", length of the group iterator. For practical reasons the largest group you could iterate over in your lifetime is of order that fits into an Int. For example, 2^63 nanoseconds comes to 290 years.","category":"page"},{"location":"groups/#Additional-methods","page":"Groups","title":"Additional methods","text":"","category":"section"},{"location":"groups/","page":"Groups","title":"Groups","text":"Base.isfinite(G::Group)\nistrivial(G::Group)","category":"page"},{"location":"groups/#Base.isfinite-Tuple{Group}","page":"Groups","title":"Base.isfinite","text":"isfinite(G::Group)\n\nTest whether group G is finite.\n\nThe default implementation is based on Base.IteratorSize. Only groups of returning Base.SizeUnknown() should extend this method.\n\n\n\n\n\n","category":"method"},{"location":"groups/#GroupsCore.istrivial-Tuple{Group}","page":"Groups","title":"GroupsCore.istrivial","text":"istrivial(G::Group)\n\nTest whether group G is trivial.\n\nThe default implementation is based on isfinite and order.\n\n\n\n\n\n","category":"method"},{"location":"group_elements/#H1_group_elements","page":"Group elements","title":"Group elements","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"GroupsCore defines abstract type GroupElement, which all implementations of group elements should subtype.","category":"page"},{"location":"group_elements/#Obligatory-methods","page":"Group elements","title":"Obligatory methods","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"parent(::GroupElement)\n:(==)(::GEl, ::GEl) where {GEl <: GroupElement}\nisfiniteorder(::GroupElement)","category":"page"},{"location":"group_elements/#Base.parent-Tuple{GroupElement}","page":"Group elements","title":"Base.parent","text":"parent(g::GroupElement)\n\nReturn the parent object of the group element.\n\n\n\n\n\n","category":"method"},{"location":"group_elements/#Base.:==-Union{Tuple{GEl}, Tuple{GEl, GEl}} where GEl<:GroupElement","page":"Group elements","title":"Base.:==","text":"==(g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn the best effort equality for group elements.\n\nIf ==(g, h) returns truethen the mathematical equalityg == hholds. However==(g, h)may returnfalseeven ifgandh` represent mathematically equal group elements.\n\nFor example, in a finitely presented group, == may return the equality of words.\n\nnote: Note\nThis function may not return due to unsolvable word problem.\n\n\n\n\n\n","category":"method"},{"location":"group_elements/#GroupsCore.isfiniteorder-Tuple{GroupElement}","page":"Group elements","title":"GroupsCore.isfiniteorder","text":"isfiniteorder(g::GroupElement)\n\nReturn true if g is of finite order, possibly without computing it.\n\nnote: Note\nIf finiteness of a group can be decided based on its type there is no need to extend isfiniteorder for its elements.\n\n\n\n\n\n","category":"method"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"As well as the two arithmetic operations:","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Base.inv(::GroupElement)\nBase.:(*)(::GEl, ::GEl) where {GEl <: GroupElement}","category":"page"},{"location":"group_elements/#A-note-on-deepcopy","page":"Group elements","title":"A note on deepcopy","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"The elements which are not of isbitstype should extend","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Base.deepcopy_internal(g::GroupElement, ::IdDict)","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"according to Base.deepcopy docstring. Due to our assumption on parents of group elements (acting as local singleton objects), a group element and its deepcopy should have identical (i.e. ===) parents.","category":"page"},{"location":"group_elements/#Implemented-methods","page":"Group elements","title":"Implemented methods","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Using the obligatory methods we implement the rest of the functions in GroupsCore. For starters, the first of these are:","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Base.:(^)(::GroupElement, ::Integer)\nBase.:(/)(::GEl, ::GEl) where {GEl <: GroupElement}\nBase.one(::GroupElement)","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"and","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"order(::Type{T}, ::GroupElement) where T\nconj\n:(^)(::GEl, ::GEl) where {GEl <: GroupElement}\ncommutator","category":"page"},{"location":"group_elements/#GroupsCore.order-Union{Tuple{T}, Tuple{Type{T}, GroupElement}} where T","page":"Group elements","title":"GroupsCore.order","text":"order([::Type{T} = BigInt, ]g::GroupElement) where T\n\nReturn the order of g as an instance of T. If g is of infinite order GroupsCore.InfiniteOrder exception will be thrown.\n\nwarning: Warning\nOnly arbitrary sized integers are required to return a mathematically correct answer.\n\n\n\n\n\n","category":"method"},{"location":"group_elements/#Base.conj","page":"Group elements","title":"Base.conj","text":"conj(g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn the conjugation of g by h, i.e. inv(h)*g*h.\n\n\n\n\n\n","category":"function"},{"location":"group_elements/#Base.:^-Union{Tuple{GEl}, Tuple{GEl, GEl}} where GEl<:GroupElement","page":"Group elements","title":"Base.:^","text":"^(g::GEl, h::GEl) where {GEl <: GroupElement}\n\nAlias for conj.\n\n\n\n\n\n","category":"method"},{"location":"group_elements/#GroupsCore.commutator","page":"Group elements","title":"GroupsCore.commutator","text":"commutator(g::GEl, h::GEl, k::GEl...) where {GEl <: GroupElement}\n\nReturn the left associative iterated commutator g h , where g h = g^-1 h^-1 g h.\n\n\n\n\n\n","category":"function"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Moreover we provide basic implementation which should be altered for performance reasons:","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"Base.:(^)(g::GroupElement, n::Integer)\nGroups.Core.order([::Type{T}], g::GroupElement) where T\nBase.hash(::GroupElement, ::UInt)","category":"page"},{"location":"group_elements/#Mutable-API","page":"Group elements","title":"Mutable API","text":"","category":"section"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"warning: Warning\nWork-in-progress. Mutable API is considered private and hence may change between versions without warning.","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"For the purpose of mutable arithmetic the following methods may be overloaded to provide more tailored versions for a given type and reduce the allocations. These functions should be used when writing libraries, in performance critical sections. However one should only use the returned value and there are no guarantees on in-place modifications actually happening.","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"All of these functions (possibly) alter only the first argument, and must unalias their arguments when necessary.","category":"page"},{"location":"group_elements/","page":"Group elements","title":"Group elements","text":"GroupsCore.one!\nGroupsCore.inv!\nGroupsCore.mul!\nGroupsCore.div_left!\nGroupsCore.div_right!\nGroupsCore.conj!\nGroupsCore.commutator!","category":"page"},{"location":"group_elements/#GroupsCore.one!","page":"Group elements","title":"GroupsCore.one!","text":"one!(g::GroupElement)\n\nReturn one(g), possibly modifying g.\n\n\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.inv!","page":"Group elements","title":"GroupsCore.inv!","text":"inv!(out::GEl, g::GEl) where {GEl <: GroupElement}\n\nReturn inv(g), possibly modifying out. Aliasing of g with out is allowed.\n\n\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.mul!","page":"Group elements","title":"GroupsCore.mul!","text":"mul!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn g*h, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.div_left!","page":"Group elements","title":"GroupsCore.div_left!","text":"div_left!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn inv(h)*g, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.div_right!","page":"Group elements","title":"GroupsCore.div_right!","text":"div_right!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn g*inv(h), possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.conj!","page":"Group elements","title":"GroupsCore.conj!","text":"conj!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn inv(h)*g*h, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n\n\n","category":"function"},{"location":"group_elements/#GroupsCore.commutator!","page":"Group elements","title":"GroupsCore.commutator!","text":"commutator!(out::GEl, g::GEl, h::GEl) where {GEl <: GroupElement}\n\nReturn inv(g)*inv(h)*g*h, possibly modifying out. Aliasing of g or h with out is allowed.\n\n\n\n\n\n","category":"function"},{"location":"#GroupsCore","page":"GroupsCore","title":"GroupsCore","text":"","category":"section"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"CurrentModule = GroupsCore","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"The aim of this package is to standardize the common assumptions and functions on group i.e. to create Group interface.","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"The protocol consists of two parts:","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"Group (parent object) methods,\nGroupElement methods.","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"This is due to the fact that hardly any information can be encoded in Type, we rely on parent objects that represent groups, as well as ordinary group elements. It is assumed that all elements of a group have identical parent (i.e. ===) so that parent objects behave locally as singletons.","category":"page"},{"location":"#Examples-and-Conformance-testing","page":"GroupsCore","title":"Examples and Conformance testing","text":"","category":"section"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"For an implemented interface please have a look at /test folder, where several example implementations are tested against the conformance test suite:","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"CyclicGroup","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"To test the conformance of e.g. CyclicGroup defined above one can run","category":"page"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"using GroupsCore\ninclude(joinpath(pathof(GroupsCore), \"..\", \"..\", \"test\", \"conformance_test.jl\"))\ninclude(joinpath(pathof(GroupsCore), \"..\", \"..\", \"test\", \"cyclic.jl\"))\nlet C = CyclicGroup(15)\n test_Group_interface(C)\n test_GroupElement_interface(rand(C, 2)...)\n nothing\nend","category":"page"},{"location":"#Users","page":"GroupsCore","title":"Users","text":"","category":"section"},{"location":"","page":"GroupsCore","title":"GroupsCore","text":"PermutationGroups.jl\nGroups.jl,\nSymbolicWedderburn.jl.","category":"page"},{"location":"extensions/#Extensions","page":"Extensions","title":"Extensions","text":"","category":"section"},{"location":"extensions/","page":"Extensions","title":"Extensions","text":"The following (empty) functions are defined in GroupsCore only to be extended externally:","category":"page"},{"location":"extensions/","page":"Extensions","title":"Extensions","text":"isabelian\nissolvable\nisnilpotent\nisperfect\nderivedsubgroup\ncenter\nsocle\nsylowsubgroup\ncentralizer\nnormalizer\nstabilizer\nright_coset_representatives","category":"page"},{"location":"extensions/","page":"Extensions","title":"Extensions","text":"GroupsCore.index\nGroupsCore.left_coset_representatives","category":"page"},{"location":"extensions/#GroupsCore.index","page":"Extensions","title":"GroupsCore.index","text":"index(H::Gr, G::Gr) where {Gr <: Group}\n\nReturn the index |G : H|, where H ≤ G is a subgroup. If H is not contained in G, an error is thrown.\n\n\n\n\n\n","category":"function"},{"location":"extensions/#GroupsCore.left_coset_representatives","page":"Extensions","title":"GroupsCore.left_coset_representatives","text":"left_coset_representatives(H::Gr, G::Gr) where {Gr <: Group}\n\nReturn representatives of the left cosets h G where h are elements of H. If H is not contained in G, an error is thrown.\n\n\n\n\n\n","category":"function"}] }