From 1a8ec62767695a942febf4e5fd6f7fef85170f74 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Tue, 24 Sep 2024 20:57:44 +0200 Subject: [PATCH 1/4] fix too restrictive method installations In many situations, we cannot expect that compatible groups have the same type. --- src/Groups/homomorphisms.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Groups/homomorphisms.jl b/src/Groups/homomorphisms.jl index 09988d5fc05d..e02ac23f684e 100644 --- a/src/Groups/homomorphisms.jl +++ b/src/Groups/homomorphisms.jl @@ -1298,7 +1298,7 @@ end Base.:^(x::GAPGroupElem{T},f::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = apply_automorphism(f, x, true) #Base.:^(f::GAPGroupElem{AutomorphismGroup{T}},g::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = g^-1*f*g -function (A::AutomorphismGroup{T})(f::GAPGroupHomomorphism{T,T}) where T <: GAPGroup +function (A::AutomorphismGroup{<: GAPGroup})(f::GAPGroupHomomorphism{T,T}) where T <: GAPGroup @assert domain(f)==A.G && codomain(f)==A.G "f not in A" @assert is_bijective(f) "f not in A" return group_element(A, GapObj(f)) @@ -1351,11 +1351,11 @@ function inner_automorphism_group(A::AutomorphismGroup{T}) where T <: GAPGroup end """ - is_invariant(f::GAPGroupElem{AutomorphismGroup{T}}, H::T) + is_invariant(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) Return whether `f`(`H`) == `H`. """ -function is_invariant(f::GAPGroupElem{AutomorphismGroup{T}}, H::T) where T<:GAPGroup +function is_invariant(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) @assert GAPWrap.IsSubset(GapObj(parent(f).G), GapObj(H)) "Not a subgroup of the domain" return GAPWrap.Image(GapObj(f), GapObj(H)) == GapObj(H) end @@ -1379,18 +1379,18 @@ end induced_automorphism(f::GAPGroupHomomorphism, mH::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = induced_automorphism(f,hom(mH)) """ - restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::T) + restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) Return the restriction of `f` to `H` as an automorphism of `H`. An exception is thrown if `H` is not invariant under `f`. """ -function restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::T, A=automorphism_group(H)) where T <: GAPGroup +function restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup, A=automorphism_group(H)) @assert is_invariant(f,H) "H is not invariant under f!" fh = hom(H, H, gens(H), [f(x) for x in gens(H)], check = false) return A(fh) end -function restrict_homomorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::T) where T <: GAPGroup +function restrict_homomorphism(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) return restrict_homomorphism(hom(f),H) end From 2e4b49881a21b8adbe3aa6ed8b333e96d007940a Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Tue, 24 Sep 2024 23:10:08 +0200 Subject: [PATCH 2/4] fix signatures --- src/Groups/homomorphisms.jl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Groups/homomorphisms.jl b/src/Groups/homomorphisms.jl index e02ac23f684e..42932c8cd368 100644 --- a/src/Groups/homomorphisms.jl +++ b/src/Groups/homomorphisms.jl @@ -231,8 +231,7 @@ end """ - is_invariant(f::GAPGroupHomomorphism, H::Group) - is_invariant(f::GAPGroupElem{AutomorphismGroup{T}}, H::T) + is_invariant(f::GAPGroupHomomorphism, H::GAPGroup) Return whether `f(H) == H` holds. An exception is thrown if `domain(f)` and `codomain(f)` are not equal @@ -1351,11 +1350,11 @@ function inner_automorphism_group(A::AutomorphismGroup{T}) where T <: GAPGroup end """ - is_invariant(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) + is_invariant(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) Return whether `f`(`H`) == `H`. """ -function is_invariant(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) +function is_invariant(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) @assert GAPWrap.IsSubset(GapObj(parent(f).G), GapObj(H)) "Not a subgroup of the domain" return GAPWrap.Image(GapObj(f), GapObj(H)) == GapObj(H) end @@ -1379,18 +1378,18 @@ end induced_automorphism(f::GAPGroupHomomorphism, mH::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = induced_automorphism(f,hom(mH)) """ - restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) + restrict_automorphism(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) Return the restriction of `f` to `H` as an automorphism of `H`. An exception is thrown if `H` is not invariant under `f`. """ -function restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup, A=automorphism_group(H)) +function restrict_automorphism(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup, A=automorphism_group(H)) @assert is_invariant(f,H) "H is not invariant under f!" fh = hom(H, H, gens(H), [f(x) for x in gens(H)], check = false) return A(fh) end -function restrict_homomorphism(f::GAPGroupElem{AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) +function restrict_homomorphism(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) return restrict_homomorphism(hom(f),H) end From cab15f22adea0c4b9eb7825fd705ca9b7cbc4a93 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Wed, 25 Sep 2024 13:14:14 +0200 Subject: [PATCH 3/4] next round - adjust reference in .md file - change more types in signatures - extend tests - fix `small_group` with given type: apply it to an Oscar group not a GAP group - fix `sub`: the type check was wrong, and the compatibility is checked anyhow --- docs/src/Groups/autgroup.md | 4 +- src/Groups/homomorphisms.jl | 12 +-- src/Groups/libraries/smallgroups.jl | 2 +- src/Groups/sub.jl | 1 - test/Groups/homomorphisms.jl | 129 +++++++++++++++------------- 5 files changed, 77 insertions(+), 71 deletions(-) diff --git a/docs/src/Groups/autgroup.md b/docs/src/Groups/autgroup.md index 1a103ce7b643..d12ff0404262 100644 --- a/docs/src/Groups/autgroup.md +++ b/docs/src/Groups/autgroup.md @@ -11,8 +11,8 @@ automorphism_group(G::GAPGroup) The following functions are available for automorphisms, some of them similar to the corresponding functions for homomorphisms of groups. ```@docs -is_invariant(f::GAPGroupElem{AutomorphismGroup{T}}, H::T) where T<:GAPGroup -restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::T, A=automorphism_group(H)) where T <: GAPGroup +is_invariant(f::GAPGroupElem{AutomorphismGroup{T}}, H::GAPGroup) where T <: GAPGroup +restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::GAPGroup, A=automorphism_group(H)) where T <: GAPGroup induced_automorphism(f::GAPGroupHomomorphism, mH::GAPGroupHomomorphism) hom(x::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup ``` diff --git a/src/Groups/homomorphisms.jl b/src/Groups/homomorphisms.jl index 42932c8cd368..2cbe48f55bbb 100644 --- a/src/Groups/homomorphisms.jl +++ b/src/Groups/homomorphisms.jl @@ -1297,7 +1297,7 @@ end Base.:^(x::GAPGroupElem{T},f::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = apply_automorphism(f, x, true) #Base.:^(f::GAPGroupElem{AutomorphismGroup{T}},g::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = g^-1*f*g -function (A::AutomorphismGroup{<: GAPGroup})(f::GAPGroupHomomorphism{T,T}) where T <: GAPGroup +function (A::AutomorphismGroup{S})(f::GAPGroupHomomorphism{T,T}) where S <: GAPGroup where T <: GAPGroup @assert domain(f)==A.G && codomain(f)==A.G "f not in A" @assert is_bijective(f) "f not in A" return group_element(A, GapObj(f)) @@ -1350,11 +1350,11 @@ function inner_automorphism_group(A::AutomorphismGroup{T}) where T <: GAPGroup end """ - is_invariant(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) + is_invariant(f::GAPGroupElem{AutomorphismGroup{T}}, H::GAPGroup) where T <: GAPGroup Return whether `f`(`H`) == `H`. """ -function is_invariant(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) +function is_invariant(f::GAPGroupElem{AutomorphismGroup{T}}, H::GAPGroup) where T <: GAPGroup @assert GAPWrap.IsSubset(GapObj(parent(f).G), GapObj(H)) "Not a subgroup of the domain" return GAPWrap.Image(GapObj(f), GapObj(H)) == GapObj(H) end @@ -1378,18 +1378,18 @@ end induced_automorphism(f::GAPGroupHomomorphism, mH::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = induced_automorphism(f,hom(mH)) """ - restrict_automorphism(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) + restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::GAPGroup) where T <: GAPGroup Return the restriction of `f` to `H` as an automorphism of `H`. An exception is thrown if `H` is not invariant under `f`. """ -function restrict_automorphism(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup, A=automorphism_group(H)) +function restrict_automorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::GAPGroup, A=automorphism_group(H)) where T <: GAPGroup @assert is_invariant(f,H) "H is not invariant under f!" fh = hom(H, H, gens(H), [f(x) for x in gens(H)], check = false) return A(fh) end -function restrict_homomorphism(f::GAPGroupElem{<: AutomorphismGroup{<: GAPGroup}}, H::GAPGroup) +function restrict_homomorphism(f::GAPGroupElem{AutomorphismGroup{T}}, H::GAPGroup) where T <: GAPGroup return restrict_homomorphism(hom(f),H) end diff --git a/src/Groups/libraries/smallgroups.jl b/src/Groups/libraries/smallgroups.jl index 182cb9e325b1..a0efb72672f6 100644 --- a/src/Groups/libraries/smallgroups.jl +++ b/src/Groups/libraries/smallgroups.jl @@ -83,7 +83,7 @@ Pc group of order 60 ``` """ function small_group(::Type{T}, n::IntegerUnion, m::IntegerUnion) where T - G = _small_group(n, m) + G = small_group(n, m) return T(G) end diff --git a/src/Groups/sub.jl b/src/Groups/sub.jl index e50a0e7396d9..b9baf736aa1a 100644 --- a/src/Groups/sub.jl +++ b/src/Groups/sub.jl @@ -34,7 +34,6 @@ true ``` """ function sub(G::GAPGroup, gens::AbstractVector{S}; check::Bool = true) where S <: GAPGroupElem - @assert elem_type(G) == S if check @req all(x -> parent(x) === G || x in G, gens) "not all elements of gens lie in G" end diff --git a/test/Groups/homomorphisms.jl b/test/Groups/homomorphisms.jl index 6e1a7848b98d..1889233e1202 100644 --- a/test/Groups/homomorphisms.jl +++ b/test/Groups/homomorphisms.jl @@ -656,69 +656,76 @@ end test_kernel(G,H,f) end -@testset "Automorphism group of Sym(n)" begin - G=symmetric_group(4) - A=automorphism_group(G) - - @test A isa AutomorphismGroup - @test A isa AutomorphismGroup{PermGroup} - @test A.G == G - @test is_isomorphic(G,A) - @test order(A) == 24 - @test A==inner_automorphism_group(A)[1] - - f = rand(A) - g = rand(A) - x = rand(G) - o = order(f) - fh = hom(f) - @test f isa Oscar.GAPGroupElem{typeof(A)} - @test fh isa Oscar.GAPGroupHomomorphism{PermGroup,PermGroup} - @test A(fh)==f - @test f(x)==x^f - @test f^o == one(A) - @test f*f^-1 == one(A) - @test (f*g)(x) == g(f(x)) - @test comm(f,g) == f^-1*g^-1*f*g - @test f(G[1])==fh(G[1]) - @test f(G[2])==fh(G[2]) - alt = alternating_group(4) - N,e = sub(G,[alt[1],alt[2]]) - @test e*f==e*fh +@testset "Automorphism group of a perm. group or a (sub) pc group" begin + for T in [PermGroup, PcGroup, SubPcGroup] + G = small_group(T, 24, 12) + A = automorphism_group(G) + + @test A isa AutomorphismGroup + @test A isa AutomorphismGroup{T} + @test A.G === G + @test is_isomorphic(G, A) + @test order(A) == 24 + @test A == inner_automorphism_group(A)[1] + + f = rand(A) + g = rand(A) + x = rand(G) + o = order(f) + fh = hom(f) + @test f isa Oscar.GAPGroupElem{typeof(A)} + @test fh isa Oscar.GAPGroupHomomorphism{T, T} + @test A(fh) == f + @test f(x) == x^f + @test f^o == one(A) + @test f*f^-1 == one(A) + @test (f*g)(x) == g(f(x)) + @test comm(f, g) == f^-1*g^-1*f*g + @test f(G[1]) == fh(G[1]) + @test f(G[2]) == fh(G[2]) + H = derived_subgroup(G)[1] + N, e = sub(G, [H[1], H[2]]) + @test e*f == e*fh + + C = cyclic_group(2) # type is independent of `T` + oC = one(C) + gC = gen(C, 1) + g = hom(G, C, x -> x in H ? oC : gC) + @test f*g == fh*g + @test kernel(f*g) == kernel(g) + @test induced_automorphism(g, f) == induced_automorphism(g, fh) + + @test is_inner_automorphism(f) + g1 = inner_automorphism(G(H[1])) + @test !(g in A) + g1 = A(g1) + @test g1 in A + g2 = A(inner_automorphism(G(H[2]))) + AA, phi = sub(A, [g1, g2]) + @test is_isomorphic(AA, H) + @test index(A, AA) == 2 + @test is_normal_subgroup(AA, A) + @test is_normalized_by(AA, A) + @test phi(AA[1]) == AA[1] + @test phi(AA[2]) == AA[2] + @test order(quo(A, AA)[1]) == 2 + @test is_invariant(f, H) + + S = sylow_subgroup(G, 3)[1] + x = gen(S, 1) + f = A(hom(G, G, y -> y^x)) + fHa = restrict_automorphism(f, H) + fHh = restrict_homomorphism(f, H) + @test parent(fHa) == automorphism_group(H) + @testset for g in gens(H) + @test fHa(g) == H(f(g)) + @test fHh(g) == H(f(g)) + end - C=cyclic_group(2) - g = hom(G,C,x -> C[1]^((1-sign(x))รท2) ) - @test f*g == fh*g - @test kernel(f*g)==kernel(g) - - @test is_inner_automorphism(f) - g1 = inner_automorphism(G(alt[1])) - @test !(g in A) - g1 = A(g1) - @test g1 in A - g2 = A(inner_automorphism(G(alt[2]))) - AA,phi = sub(A,[g1,g2]) - @test is_isomorphic(AA,alt) - @test index(A,AA)==2 - @test is_normal_subgroup(AA, A) - @test is_normalized_by(AA, A) - @test phi(AA[1])==AA[1] - @test phi(AA[2])==AA[2] - @test order(quo(A,AA)[1])==2 - @test is_invariant(f,alt) - - H = alternating_group(4) - x = cperm(G,[1,2,3]) - f = A(hom(G,G,y->y^x)) - fa = restrict_automorphism(f,H) - @test parent(fa)==automorphism_group(H) - @testset for g in gens(H) - @test fa(g)==H(f(g)) + V, _ = pcore(G, 2) + S, g = quo(G, V) + @test induced_automorphism(g, f) == automorphism_group(S)(inner_automorphism(g(x))) end - - S = symmetric_group(3) - g = hom(G,S,[cperm([1,2,3,4]), cperm([1,2])], [cperm([1,3]), cperm([1,2])]) - @test induced_automorphism(g,f)==automorphism_group(S)(inner_automorphism(cperm(S,[1,2,3]))) end @testset "Other automorphisms groups" begin From c8451b90eda8e538c5840e8775212a531c4f3cc2 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Thu, 26 Sep 2024 13:40:54 +0200 Subject: [PATCH 4/4] address comments (improve syntax) --- src/Groups/homomorphisms.jl | 2 +- src/Groups/sub.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Groups/homomorphisms.jl b/src/Groups/homomorphisms.jl index 2cbe48f55bbb..40a0a68e4732 100644 --- a/src/Groups/homomorphisms.jl +++ b/src/Groups/homomorphisms.jl @@ -1297,7 +1297,7 @@ end Base.:^(x::GAPGroupElem{T},f::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = apply_automorphism(f, x, true) #Base.:^(f::GAPGroupElem{AutomorphismGroup{T}},g::GAPGroupElem{AutomorphismGroup{T}}) where T <: GAPGroup = g^-1*f*g -function (A::AutomorphismGroup{S})(f::GAPGroupHomomorphism{T,T}) where S <: GAPGroup where T <: GAPGroup +function (A::AutomorphismGroup{<: GAPGroup})(f::GAPGroupHomomorphism{T,T}) where T <: GAPGroup @assert domain(f)==A.G && codomain(f)==A.G "f not in A" @assert is_bijective(f) "f not in A" return group_element(A, GapObj(f)) diff --git a/src/Groups/sub.jl b/src/Groups/sub.jl index b9baf736aa1a..b107a3062912 100644 --- a/src/Groups/sub.jl +++ b/src/Groups/sub.jl @@ -33,7 +33,7 @@ julia> H == alternating_group(4) true ``` """ -function sub(G::GAPGroup, gens::AbstractVector{S}; check::Bool = true) where S <: GAPGroupElem +function sub(G::GAPGroup, gens::AbstractVector{<: GAPGroupElem}; check::Bool = true) if check @req all(x -> parent(x) === G || x in G, gens) "not all elements of gens lie in G" end