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

provide automorphism groups that do not consist of automorphisms #4237

Open
ThomasBreuer opened this issue Oct 23, 2024 · 8 comments
Open

provide automorphism groups that do not consist of automorphisms #4237

ThomasBreuer opened this issue Oct 23, 2024 · 8 comments
Labels
enhancement New feature or request topic: groups

Comments

@ThomasBreuer
Copy link
Member

@fieker had mentioned in the discussion of #4191 that he would like to get an implementation of "abstract" automorphism groups in the sense that their elements are not "concrete" automorphisms of the given object; instead one should ask for the corresponding map of an element if one wants to compute images and preimages under this map.

For that, we could for example define that for a group G, automorphism_group(G; abstract = false) returns A, mp where A is some group isomorphic with the full automorphism group of G, and mp is a map that takes an element of A and returns the group isomorphism on G that corresponds to this element.

For finite groups with underlying GAP group, this can be implemented via GAP's NiceMonomorphism mechanism that delegates computations with the automorphism maps on the GAP side to another (isomorphic) group, typically (always?) a permutation group. We can choose A as this permutation group, and implement mp via the data that are already used by GAP.

  • What kind of object should mp be? A natural type would be a map with domain A, but then what is its codomain?
  • Is it perhaps desirable to prescribe a type for A, similar to the situation with quo? If yes then we could use the syntax automorphism_group(PermGroup, G) for the new implementation, and one could also get the current automorphism groups by choosing the type AutomorphismGroup. The only problem with the old and the new implementation is then that the return values of automorphism_group are different. Or should we perhaps omit the return value mp, and provide a function that can be applied to the group A in order to create the map in question?

Once the questions about the syntax have been decided, I will provide a pull request for the implementation.

@thofma
Copy link
Collaborator

thofma commented Oct 23, 2024

I touched upon these points 3 years ago in #920 and back then we seemed to be happy with AutomorphismGroup etc. What has changed?

As far as I understand, our design for the automorphism groups means that one should do A = automorphism_group(G); mp = isomorphism(PermGroup, A)?

Having different behavior for automorphism_group(PermGroup, G) and automorphism_group(G) seems undesirable from a user point of view.

@fieker
Copy link
Contributor

fieker commented Oct 23, 2024 via email

@ThomasBreuer
Copy link
Member Author

@fieker Concerning the plan you mention, one solution would be an interface like the following.

function Hecke.automorphism_group(::Type{PermGroup}, G::Oscar.GAPGroup)
    A = GAP.Globals.AutomorphismGroup(GapObj(G))
    nice = GAP.Globals.NiceMonomorphism(A)
    img = GAP.Globals.ImagesSource(nice)  # this gets computed here!
    res = Oscar._oscar_group(img)
    Oscar.set_attribute!(res, :interpret_as_automorphism => (G, nice))
    return res
end

function interpretation_map(P::PermGroup)
    att = Oscar.get_attribute(P, :interpret_as_automorphism)
    @req att !== nothing "the group was not created with `automorphism_group`"
    (G, nice) = att
    range = GAP.Globals.Range(nice)

    f = function(x::PermGroupElem)
      xx = GapObj(x)
      xx in range || error("x has no preimage")  
      pre = GAP.Globals.PreImagesRepresentative(nice, xx)
      pre === GAP.Globals.fail && error("x has no preimage")
      return GAPGroupHomomorphism(G, G, pre)
    end

    g = function(x::GAPGroupHomomorphism)
      img = GAP.Globals.ImagesRepresentative(nice, GapObj(x))
      return Oscar.group_element(P, img)
    end

#   return MapFromFunc(P, ?, f, g)
    return (f, g)
end

(It would be more elegant to return a Map object, but what should be its codomain?)

Then the following would work.

julia> G = symmetric_group(6)
Sym(6)

julia> P = automorphism_group(PermGroup, G)
Permutation group of degree 30

julia> f, g = interpretation_map(P);

julia> x = gens(P)[1]
(1,27,11,7,4,2)(3,23,10,15,8,5)(6,19,9)(12,28)(13,24,26,18,16,29)(14,20,30)(17,25,22)

julia> y = f(x)
Group homomorphism
  from Sym(6)
  to Sym(6)

julia> x == g(y)
true

This would even be compatible with the current automorphism_group.

@thofma
Copy link
Collaborator

thofma commented Oct 25, 2024

The codomain could just be some artificial object "Set of automorphisms of blabla" without mathematical structure. This is done for example for number fields:

julia> K, a = cyclotomic_field(7, :a);

julia> A, m = automorphism_group(PermGroup, K);

julia> codomain(m)
Set of automorphisms of Cyclotomic field of order 7

julia> m(one(A))
Map
  from cyclotomic field of order 7
  to cyclotomic field of order 7

julia> parent(ans)
Set of automorphisms of Cyclotomic field of order 7

It could be the same object we would use to make the following work:

julia> id_hom(A)
Group homomorphism
  from permutation group of degree 6
  to permutation group of degree 6

julia> parent(ans)
ERROR: MethodError: no method matching parent(::GAPGroupHomomorphism{PermGroup, PermGroup})

I am skeptical about the interpretation_map approach.

@fieker
Copy link
Contributor

fieker commented Oct 25, 2024 via email

@ThomasBreuer
Copy link
Member Author

My idea was that this way, the syntax for the new automorphism groups is the same as for the old ones.
That is, one asks for automorphism_group([T, ]G), and the default for T is the old AutomorphismGroup type.

Do we want that automorphism_group(G) returns only the group, as it is now, and automorphism_group(T, G) returns also the map, or do we choose another function name for the "new" automorphism groups, or do we want to drop backwards compatibility?

@fingolfin
Copy link
Member

Since we don't want to break backwards compatibility, automorphism_group(G) must (for the time being) stay as it is and only return a single value. At least until we make a breaking release (but that shouldn't be too soon, the book is not even out and it uses

I like the idea of having A, m = automorphism_group(PermGroup, K) with two return values. That allows people to "upgrade" their code to the new system incrementally. If one day we want to make a break here (for Oscar 2.0, 3.0, ... whatever) it would then still be possible to have code that works before and after, too.

There are other automorphism_group which fact a similar issue. E.g. from the book:

julia> X = matrix(GF(2), [1 0 1 0 1 0 1; 0 1 1 0 0 1 1; 0 0 0 1 1 1 1])
[1   0   1   0   1   0   1]
[0   1   1   0   0   1   1]
[0   0   0   1   1   1   1]

julia> F = matroid_from_matrix_columns(X)
Matroid of rank 3 on 7 elements

julia> is_isomorphic(F, fano_matroid())
true

julia> G = automorphism_group(F);

julia> describe(G)
"PSL(3,2)"

But that's fine, we can also add a two-arguments-two-return-values variant of that down the road.

@fingolfin
Copy link
Member

One operation I sometimes down with automorphism groups is to compute "centralizers" of group elements (i.e. a stabilizer) so I need a way to efficiently construct a G-set from this -- but the new setup still allows for that quite nicely (we may make it even nice by allowing a G-set construction API that takes a group plus an "action morphism", but that can be done down the road)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request topic: groups
Projects
None yet
Development

No branches or pull requests

4 participants