Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual groups #116

Merged
merged 1 commit into from
Jul 21, 2020
Merged

Manual groups #116

merged 1 commit into from
Jul 21, 2020

Conversation

GDeFranceschi
Copy link
Contributor

This branch has been created to write the manual for Groups (just another .md file in docs/src). But I just started.

@codecov
Copy link

codecov bot commented Jun 25, 2020

Codecov Report

Merging #116 into master will decrease coverage by 0.03%.
The diff coverage is 33.33%.

@@            Coverage Diff             @@
##           master     #116      +/-   ##
==========================================
- Coverage   27.89%   27.85%   -0.04%     
==========================================
  Files          19       19              
  Lines        2811     2815       +4     
==========================================
  Hits          784      784              
- Misses       2027     2031       +4     
Impacted Files Coverage Δ
src/Groups/homomorphisms.jl 80.18% <0.00%> (-2.23%) ⬇️
src/Groups/sub.jl 72.86% <0.00%> (-0.57%) ⬇️
src/Groups/GAPGroups.jl 78.60% <50.00%> (ø)
src/Groups/group_constructors.jl 88.57% <100.00%> (ø)

* `sub(G, [x,y,...])` ;
* `sub(x,y,...)`.

This function returns two objects: a group `H`, that is the subgroup of `G` generated by the elements `x,y,...`, and the embedding homomorphism of `H` into `G`. The object `H` has the same type of `G`, and it has no memory of the "parent" group `G`: it is an independent group.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has no memory of a parent? Does that make sense? Why is it called sub then, and not e.g. group?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it returns the embedding.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking to create also a function called simply group, that works in a similar way to the GAP function Group.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thofma I was only referring to the second variant (sorry, I failed to state that), which only takes a bunch of elements, not an existing group

@GDeFranceschi sounds good, that could replace the second sub variant

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but even for the second variant it returns the new group H together with the embedding into G. Without the embedding, I would not call it subgroup, but just group.

Comment on lines 34 to 53
* `one(G)` = the identity element of `G`.
```@repl oscar
one(symmetric_group(4))
one(GL(2,3))
```

* `rand(G)`: returns a random element of the group `G`.

For very large groups, the algorithm to ensure a uniform probability could be expensive, so there exists also the function `rand_pseudo`: this is much faster than `rand`, but the elements of `G` are not necessarily equally distributed.

* `gens(G)`: returns a list of generators for the group `G`. To have access to the ``n``-th generator of the list, it is sufficient to type `G[n]` instead of `gens(G)[n]`.
```@repl oscar
G = symmetric_group(4);
gens(G)
G[1]
```
If the group `G` has been created as the subgroup of another group generated by a list of elements `L`, then the generating set returned by the function `gens` corresponds to `L`.

!!! note
The output of `gens(G)` is not, in general, the minimal list of generators for `G`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.. I think this should be done differently: this text and the example should be part of the docstring for our methods for one, rand, gens. Then here, we should just "include" that documentation via @docs`

Suggested change
* `one(G)` = the identity element of `G`.
```@repl oscar
one(symmetric_group(4))
one(GL(2,3))
```
* `rand(G)`: returns a random element of the group `G`.
For very large groups, the algorithm to ensure a uniform probability could be expensive, so there exists also the function `rand_pseudo`: this is much faster than `rand`, but the elements of `G` are not necessarily equally distributed.
* `gens(G)`: returns a list of generators for the group `G`. To have access to the ``n``-th generator of the list, it is sufficient to type `G[n]` instead of `gens(G)[n]`.
```@repl oscar
G = symmetric_group(4);
gens(G)
G[1]
```
If the group `G` has been created as the subgroup of another group generated by a list of elements `L`, then the generating set returned by the function `gens` corresponds to `L`.
!!! note
The output of `gens(G)` is not, in general, the minimal list of generators for `G`.
```@docs
one
rand
gens
```

Actually, that's probably not quite right yet, as Oscar.jl will include many one methods eventually, so we probably ought to tell it which one is meant here. Please carefully read https://juliadocs.github.io/Documenter.jl/stable/man/syntax/ it explains how to do this.

Perhaps also look at how some of our other packages do this; here are some select examples (you can easily find plenty more)

Comment on lines 86 to 88
```@repl oscar
degree(symmetric_group(4))
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not very fond of the @repl feature:

  • it requires Julia to process all @repl examples just to be able to render the documentation, which means building the manual takes longer
  • it misses an opportunity for further testing, as we never notice if Julia's output changes

Instead, please use @jldoctest (specifically, the REPL variant) as I suggested before; read https://juliadocs.github.io/Documenter.jl/stable/man/doctests/ for details

alternating_group
```

Every permutation group `G` is identified by a degree, that corresponds ideally to the size of the set on which `G` is acting.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think every permutation group is "identified" by a degree! Rather, every permutation group in Oscar has an associated degree.

The use of "ideally" renders this sentences rather vague. It implies that this "ideal" may not be always reached, but gives the reader no clue at all about when that is and so on. Also, is this really "ideal"? Perhaps you meant "usually"? What exactly do you want to convey here?

Perhaps more something like:

Suggested change
Every permutation group `G` is identified by a degree, that corresponds ideally to the size of the set on which `G` is acting.
In Oscar, every group has a parent (see section XYZ for details). For permutation groups, the parent currently always is a symmetric group. The degree `d` of a permutation group `G` then is the degree of its parent symmetric group. That is, `G` acts on the set `1..d`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't parent defined only for group elements? The symmetric group is only a kind of "sup-group" for the permutation group G. Maybe we should say something like:
" Every permutation group G has a degree n, that is the cardinality of the set on which G acts."
Then add the note about deg(G) != largest moved point of G in general.

Every permutation group `G` is identified by a degree, that corresponds ideally to the size of the set on which `G` is acting.

!!! note
The degree of a group of permutations is not necessarily the highest moved point of the group `G`. For example, if `G` is defined as a subgroup of `Sym(n)`, its degree is `n` even if every element of `G` fixes `n`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The degree of a group of permutations is not necessarily the highest moved point of the group `G`. For example, if `G` is defined as a subgroup of `Sym(n)`, its degree is `n` even if every element of `G` fixes `n`.
The degree of a permutation group is not necessarily equal to the largest moved point of the group `G`. For example, the trivial subgroup of `symmetric_group(d)` has degree `d` even tough it fixes `n`.

```

**Example:**
```jldoctest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be inside the perm resp. cperm doc strings

(1,3,2)
```

At the moment, the input vectors of the function `cperm` need not to be disjoint.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds like it should be inside the docstring of cperm, not here. Also, it is a bit unclear what the significance of this statement is? Should this behavior be surprising? If so, perhaps it should explained what happens in this case? Or perhaps it all works fine?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It simply means that when the function gets in input non-disjoint cycles, it multiplies them instead of returning an error, like GAP and Magma do.
I just felt to write this line just because the behaviour is different from GAP.

docs/src/Groups/groups.md Outdated Show resolved Hide resolved
This works also if the argument is not in the range `1:n`; in such a case, the output coincides with the input.

!!! note
The multiplication between permutations works from the left to the right. So, if `x` and `y` are permutations and `n` is an integer, then `(x*y)(n) = (y(x(n))`, NOT `x(y(n))`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I guess I'd move this warning before the example, and also augment it by mentioning that this is why instead we recommend the notation n^x, as then (n^x)^y == n^(x*y)

And at that point we might also want to warn that in Julia a^b^c is evaluated as a^(b^c) (while in GAP it thankfully gives an error).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the notation x(n) instead of n^x because x(n) is the syntax. Now I was thinking about it: do I also implement the function ^(n::Int)(x::Perm) having the same output as x(n)?

quaternion_group
```
!!! warning
The type need to be specified in the input of the function `abelian_group`, otherwise a group of type `GrpAbFinGen` is returned.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The type need to be specified in the input of the function `abelian_group`, otherwise a group of type `GrpAbFinGen` is returned.
The type need to be specified in the input of the function `abelian_group`, otherwise a group of type `GrpAbFinGen` is returned, which is not a GAP group type. In future versions of Oscar, this may change.

julia> G[2]*G[1]
f1*f2
```
Anyway, recall that variables named `f1`, `f2`, etc. are not initialized! To get the generators of the group `G`, one has to refer to them as `G[1]`, `G[2]`, etc.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Anyway, recall that variables named `f1`, `f2`, etc. are not initialized! To get the generators of the group `G`, one has to refer to them as `G[1]`, `G[2]`, etc.
Note that this does not define Julia variables named `f1`, `f2`, etc.! To get the generators of the group `G`, use `gens(G)`; for convenience they can also be accessed as `G[1]`, `G[2]`, etc.

"Anyway" is colloquial. And "recall" doesn't seem to apply (from where should this be recalled?). Also note that the point about "there are no Julia variables with those names by default" also applies to free groups and in general all finitely presented groups (of which pc groups in a sense are a special case).

At the same time, access to the generators is something that really concerns all groups, so perhaps it would be better to move that into its own section, and then just insert a reference link here. (Please look into the Documenter.jl documentation to learn how to insert cross links to other section)

Finally, you could also mention the possibility of writing f1, f2 = gens(G).

Return the permutation `x` sending `i` into `L[i]` for every `i`. `L` must contain exactly one time every integer from 1 to n for n = length(`L`).
The parent of `x` is `G`. If `x` is not in `G`, return ERROR.
Return the permutation `x` sending `i` into `L[i]` for every `i`. `L` must contain exactly one time every integer from 1 to `n` for `n` = length(`L`).
The parent of `x` is `G`. If `x` is not contained in `G`, an ERROR is returned. For `gap_perm`, the parent group of `x` is set as Sym(`n`), where `n` is the largest moved point of `x`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that an "ERROR is returned"? Isn't rather a exception thrown? Same for other sections with similar text

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the permutation groups, an ArgumentError is returned. I'll check for similar parts.

# FIXME: clashes with AbstractAlgebra.perm method
#function perm(L::AbstractVector{<:Base.Integer})
# return PermGroupElem(symmetric_group(length(L)), GAP.Globals.PermList(GAP.julia_to_gap(L)))
#end
# FIXME: use name gap_perm for now
"""
gap_perm(L::AbstractVector{<:Integer})
Return the permutation `x` sending `i` into `L[i]` for every `i`. `L` must contain exactly one time every integer from 1 to `n` for `n` = length(`L`).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Return the permutation `x` sending `i` into `L[i]` for every `i`. `L` must contain exactly one time every integer from 1 to `n` for `n` = length(`L`).
Return the permutation `x` which maps every `i` from `1` to `length(L)` to `L[i]`. `L` must contain every integer from 1 to `length(L)` exactly, otherwise an exception is thrown.

@fingolfin fingolfin merged commit f482cc8 into oscar-system:master Jul 21, 2020
```

!!! warning
Do not confuse `haspreimage` with the function `has_preimage`, which works on variable of type `GrpGenToGrpGenMor`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't these two functions be merged? It looks indeed confusing to have both in the same system.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two functions called haspreimage and has_preimage already exist in Hecke. The first one is defined on variables of types GrpAbFinGenMap and GrpAbFinGenElem, while the second is defined on variables of type GrpGenToGrpGenMor and GrpGenElem, and they do essentially the same thing. If we want to merge these two functions, this has to be done in the Hecke package first. Then, in Oscar, we can simply import the function we decide to preserve and extend it to GAPGroups.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just an oversight/inconsistency in Hecke. We should not replicate this here :)

We just need to decide for one convention and follow it through. There is no need to change it in Hecke first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants