From 082be7a72512baea1c6a8c632b6cc7d5efcf254f Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Tue, 12 Dec 2023 23:48:29 +0000 Subject: [PATCH] build based on 24a7335 --- dev/extensions/index.html | 2 +- dev/group_elements/index.html | 6 +++--- dev/groups/index.html | 2 +- dev/index.html | 2 +- dev/search/index.html | 2 +- dev/search_index.js | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev/extensions/index.html b/dev/extensions/index.html index 75d70da..c27ddce 100644 --- a/dev/extensions/index.html +++ b/dev/extensions/index.html @@ -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 ≤ 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
+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 ba19362..f2bb85b 100644 --- a/dev/group_elements/index.html +++ b/dev/group_elements/index.html @@ -1,7 +1,7 @@ -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)
+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)
+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
+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 7d8a31c..e79f437 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 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
+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 05a799c..4eb178d 100644 --- a/dev/index.html +++ b/dev/index.html @@ -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 | 91 91 0.0s

Users

The Oscar.jl project no longer supports GroupsCore.jl interface at version 0.5. See these comments.

diff --git a/dev/search/index.html b/dev/search/index.html index 8f25460..9937bac 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 7a8bfb2..9d3c340 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 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"}] +[{"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":"","page":"GroupsCore","title":"GroupsCore","text":"The Oscar.jl project no longer supports GroupsCore.jl interface at version 0.5. See these comments.","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"}] }