From 803ecaa5dbf29fb4b38779416cf7d2b9b12eff89 Mon Sep 17 00:00:00 2001 From: ThomasBreuer Date: Wed, 28 Feb 2024 11:50:04 +0100 Subject: [PATCH] support group properties for character tables and character value access by class names --- docs/src/Groups/basics.md | 18 +-- docs/src/Groups/group_characters.md | 18 +++ src/Groups/group_characters.jl | 215 +++++++++++++++++++++++++++- test/Groups/group_characters.jl | 16 +++ 4 files changed, 257 insertions(+), 10 deletions(-) diff --git a/docs/src/Groups/basics.md b/docs/src/Groups/basics.md index d088222e052e..e63004cd2fb6 100644 --- a/docs/src/Groups/basics.md +++ b/docs/src/Groups/basics.md @@ -70,17 +70,17 @@ is_finite(G::GAPGroup) is_trivial(G::GAPGroup) is_cyclic(G::GAPGroup) is_abelian(G::GAPGroup) -is_elementary_abelian -is_pgroup -is_pgroup_with_prime -is_nilpotent -is_supersolvable -is_solvable -is_perfect +is_elementary_abelian(G::GAPGroup) +is_pgroup(G::GAPGroup) +is_pgroup_with_prime(::Type{T}, G::GAPGroup) where T <: IntegerUnion +is_nilpotent(G::GAPGroup) +is_supersolvable(G::GAPGroup) +is_solvable(G::GAPGroup) +is_perfect(G::GAPGroup) is_simple(G::GAPGroup) is_almost_simple(G::GAPGroup) -is_quasisimple -is_sporadic_simple +is_quasisimple(G::GAPGroup) +is_sporadic_simple(G::GAPGroup) is_finitely_generated(G::GAPGroup) ``` diff --git a/docs/src/Groups/group_characters.md b/docs/src/Groups/group_characters.md index 5f0f6dcafd23..ec48a13605f1 100644 --- a/docs/src/Groups/group_characters.md +++ b/docs/src/Groups/group_characters.md @@ -143,6 +143,24 @@ trivial_character(tbl::GAPGroupCharacterTable) regular_character(tbl::GAPGroupCharacterTable) ``` +The following properties of a group can be read off from its +character table. +Therefore it is supported to call these functions with a character table. + +```@docs +is_abelian(tbl::GAPGroupCharacterTable) +is_almost_simple(tbl::GAPGroupCharacterTable) +is_cyclic(tbl::GAPGroupCharacterTable) +is_elementary_abelian(tbl::GAPGroupCharacterTable) +is_nilpotent(tbl::GAPGroupCharacterTable) +is_perfect(tbl::GAPGroupCharacterTable) +is_quasisimple(tbl::GAPGroupCharacterTable) +is_simple(tbl::GAPGroupCharacterTable) +is_solvable(tbl::GAPGroupCharacterTable) +is_sporadic_simple(tbl::GAPGroupCharacterTable) +is_supersolvable(tbl::GAPGroupCharacterTable) +``` + ## Construct group characters from groups ```@docs diff --git a/src/Groups/group_characters.jl b/src/Groups/group_characters.jl index 0a442126ad7b..3423563bd544 100644 --- a/src/Groups/group_characters.jl +++ b/src/Groups/group_characters.jl @@ -1642,6 +1642,212 @@ function known_class_fusions(tbl::GAPGroupCharacterTable) end +############################################################################## +## +## mathematical properties of a group that can be read off from its +## character table +## + +""" + is_abelian(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of an abelian group, +see [`is_abelian(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_abelian(character_table("A5")) +false + +julia> is_abelian(character_table("C2")) +true +``` +""" +@gapattribute is_abelian(tbl::GAPGroupCharacterTable) = GAP.Globals.IsAbelian(GAPTable(tbl))::Bool + + +""" + is_almost_simple(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of an almost simple group, +see [`is_almost_simple(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_almost_simple(character_table("S5")) +true + +julia> is_almost_simple(character_table("S4")) +false +``` +""" +@gapattribute is_almost_simple(tbl::GAPGroupCharacterTable) = GAP.Globals.IsAlmostSimple(GAPTable(tbl))::Bool + + +""" + is_cyclic(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of a cyclic group, +see [`is_cyclic(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_cyclic(character_table("C2")) +true + +julia> is_cyclic(character_table("S4")) +false +``` +""" +@gapattribute is_cyclic(tbl::GAPGroupCharacterTable) = GAP.Globals.IsCyclic(GAPTable(tbl))::Bool + + +""" + is_elementary_abelian(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of +an elementary abelian group, +see [`is_elementary_abelian(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_elementary_abelian(character_table("C2")) +true + +julia> is_elementary_abelian(character_table("S4")) +false +``` +""" +@gapattribute is_elementary_abelian(tbl::GAPGroupCharacterTable) = GAP.Globals.IsElementaryAbelian(GAPTable(tbl))::Bool + + +""" + is_nilpotent(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of a nilpotent group, +see [`is_nilpotent(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_nilpotent(character_table("C2")) +true + +julia> is_nilpotent(character_table("S4")) +false +``` +""" +@gapattribute is_nilpotent(tbl::GAPGroupCharacterTable) = GAP.Globals.IsNilpotent(GAPTable(tbl))::Bool + + +""" + is_perfect(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of a perfect group, +see [`is_perfect(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_perfect(character_table("A5")) +true + +julia> is_perfect(character_table("S4")) +false +``` +""" +@gapattribute is_perfect(tbl::GAPGroupCharacterTable) = GAP.Globals.IsPerfect(GAPTable(tbl))::Bool + + +""" + is_quasisimple(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of a quasisimple group, +see [`is_quasisimple(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_quasisimple(character_table("A5")) +true + +julia> is_quasisimple(character_table("S4")) +false +``` +""" +@gapattribute is_quasisimple(tbl::GAPGroupCharacterTable) = GAP.Globals.IsQuasisimple(GAPTable(tbl))::Bool + + +""" + is_simple(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of a simple group, +see [`is_simple(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_simple(character_table("A5")) +true + +julia> is_simple(character_table("S4")) +false +``` +""" +@gapattribute is_simple(tbl::GAPGroupCharacterTable) = GAP.Globals.IsSimple(GAPTable(tbl))::Bool + + +""" + is_solvable(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of a solvable group, +see [`is_solvable(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_solvable(character_table("A5")) +false + +julia> is_solvable(character_table("S4")) +true +``` +""" +@gapattribute is_solvable(tbl::GAPGroupCharacterTable) = GAP.Globals.IsSolvable(GAPTable(tbl))::Bool + + +""" + is_sporadic_simple(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of +a sporadic simple group, +see [`is_sporadic_simple(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_sporadic_simple(character_table("A5")) +false + +julia> is_sporadic_simple(character_table("M11")) +true +``` +""" +@gapattribute is_sporadic_simple(tbl::GAPGroupCharacterTable) = GAP.Globals.IsSporadicSimple(GAPTable(tbl))::Bool + + +""" + is_supersolvable(tbl::GAPGroupCharacterTable) + +Return whether `tbl` is the ordinary character table of a supersolvable group, +see [`is_supersolvable(G::GAPGroup)`](@ref). + +# Examples +```jldoctest +julia> is_supersolvable(character_table("A5")) +false + +julia> is_supersolvable(character_table("S3")) +true +``` +""" +@gapattribute is_supersolvable(tbl::GAPGroupCharacterTable) = GAP.Globals.IsSupersolvable(GAPTable(tbl))::Bool + + ############################################################################# ## ## class functions (and characters) @@ -2061,12 +2267,19 @@ Nemo.degree(::Type{QQAbElem}, chi::GAPGroupClassFunction) = values(chi)[1]::QQAb Nemo.degree(::Type{T}, chi::GAPGroupClassFunction) where T <: IntegerUnion = T(Nemo.degree(ZZRingElem, chi))::T -# access character values +# access character values by position function Base.getindex(chi::GAPGroupClassFunction, i::Int) vals = GAPWrap.ValuesOfClassFunction(chi.values) return QQAbElem(vals[i]) end +# access character values by class name +function Base.getindex(chi::GAPGroupClassFunction, nam::String) + i = findfirst(is_equal(nam), class_names(parent(chi))) + @req i != nothing "$nam is not a class name" + return chi[i] +end + # arithmetic with class functions function Base.:(==)(chi::GAPGroupClassFunction, psi::GAPGroupClassFunction) @req parent(chi) === parent(psi) "character tables must be identical" diff --git a/test/Groups/group_characters.jl b/test/Groups/group_characters.jl index a14c037dd8c5..45462bcab5b4 100644 --- a/test/Groups/group_characters.jl +++ b/test/Groups/group_characters.jl @@ -852,6 +852,7 @@ end @test chi isa Oscar.GAPGroupClassFunction @test chi[4] == t[2,4] @test [chi[i] for i in 1:5] == values(chi) + @test [chi[nam] for nam in class_names(t)] == values(chi) @test [2*chi[i] for i in 1:5] == values(chi + chi) @test [chi[i]^2 for i in 1:5] == values(chi * chi) @test [chi[i]^2 for i in 1:5] == values(chi^2) @@ -1281,3 +1282,18 @@ end end end end + +@testset "read off group properties from character tables" begin + t = character_table("A5") + @test ! is_abelian(t) + @test is_almost_simple(t) + @test ! is_cyclic(t) + @test ! is_elementary_abelian(t) + @test ! is_nilpotent(t) + @test is_perfect(t) + @test is_quasisimple(t) + @test is_simple(t) + @test ! is_solvable(t) + @test ! is_sporadic_simple(t) + @test ! is_supersolvable(t) +end