Skip to content

Commit

Permalink
add G-set functionality for conjugacy classes
Browse files Browse the repository at this point in the history
and changed the `show` methods for conjugacy classes
  • Loading branch information
ThomasBreuer committed Jan 30, 2024
1 parent 5857e99 commit d3eafa9
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 37 deletions.
130 changes: 94 additions & 36 deletions src/Groups/GAPGroups.jl
Original file line number Diff line number Diff line change
Expand Up @@ -531,29 +531,84 @@ end
#
################################################################################

struct GAPGroupConjClass{T<:GAPGroup, S<:Union{GAPGroupElem,GAPGroup}} <: GroupConjClass{T, S}
@attributes mutable struct GAPGroupConjClass{T<:GAPGroup, S<:Union{GAPGroupElem,GAPGroup}} <: GroupConjClass{T, S}
X::T
repr::S
CC::GapObj

function GAPGroupConjClass(G::T, obj::S, C::GapObj) where T<:GAPGroup where S<:Union{GAPGroupElem, GAPGroup}
return new{T, S}(G, obj, C, Dict{Symbol,Any}())
end
end

Base.eltype(::Type{GAPGroupConjClass{T,S}}) where {T,S} = S

Base.hash(x::GAPGroupConjClass, h::UInt) = h # FIXME

function Base.show(io::IO, x::GAPGroupConjClass)
print(io, String(GAPWrap.StringViewObj(x.repr.X)),
" ^ ",
String(GAPWrap.StringViewObj(x.X.X)))
function Base.show(io::IO, ::MIME"text/plain", x::GAPGroupConjClass)
println(io, "Conjugacy class of")
io = pretty(io)
print(io, Indent())
println(io, Lowercase(), x.repr, " in")
print(io, Lowercase(), x.X)
print(io, Dedent())
end

function Base.show(io::IO, x::GAPGroupConjClass{T, S}) where T where S
if get(io, :supercompact, false)
if S <: GAPGroupElem
print(io, "Conjugacy class of group elements")

Check warning on line 560 in src/Groups/GAPGroups.jl

View check run for this annotation

Codecov / codecov/patch

src/Groups/GAPGroups.jl#L559-L560

Added lines #L559 - L560 were not covered by tests
else
print(io, "Conjugacy class of subgroups")

Check warning on line 562 in src/Groups/GAPGroups.jl

View check run for this annotation

Codecov / codecov/patch

src/Groups/GAPGroups.jl#L562

Added line #L562 was not covered by tests
end
else
print(io, "Conjugacy class of ")
io = pretty(io)
print(IOContext(io, :supercompact => true), Lowercase(), x.repr, " in ", Lowercase(), x.X)
end
end

action_function(C::GAPGroupConjClass) = ^

Check warning on line 571 in src/Groups/GAPGroups.jl

View check run for this annotation

Codecov / codecov/patch

src/Groups/GAPGroups.jl#L571

Added line #L571 was not covered by tests

==(a::GAPGroupConjClass{T, S}, b::GAPGroupConjClass{T, S}) where S where T = a.CC == b.CC

function Base.length(::Type{T}, C::GAPGroupConjClass) where T <: IntegerUnion
return T(GAPWrap.Size(C.CC))
end

Base.length(C::GroupConjClass) = length(ZZRingElem, C)
Base.lastindex(C::GroupConjClass) = length(C)

Check warning on line 580 in src/Groups/GAPGroups.jl

View check run for this annotation

Codecov / codecov/patch

src/Groups/GAPGroups.jl#L580

Added line #L580 was not covered by tests

Base.keys(C::GroupConjClass) = keys(1:length(C))

Check warning on line 582 in src/Groups/GAPGroups.jl

View check run for this annotation

Codecov / codecov/patch

src/Groups/GAPGroups.jl#L582

Added line #L582 was not covered by tests

is_transitive(C::GroupConjClass) = true

Check warning on line 584 in src/Groups/GAPGroups.jl

View check run for this annotation

Codecov / codecov/patch

src/Groups/GAPGroups.jl#L584

Added line #L584 was not covered by tests

orbit(G::GAPGroup, g::T) where T<: Union{GAPGroupElem, GAPGroup} = conjugacy_class(G, g)

orbits(C::GAPGroupConjClass) = [C]

function permutation(C::GAPGroupConjClass, g::GAPGroupElem)
pi = GAP.Globals.Permutation(g.X, C.CC, GAP.Globals.OnPoints)::GapObj
sym = get_attribute!(C, :action_range) do
return symmetric_group(length(Int, C))

Check warning on line 593 in src/Groups/GAPGroups.jl

View check run for this annotation

Codecov / codecov/patch

src/Groups/GAPGroups.jl#L593

Added line #L593 was not covered by tests
end
return group_element(sym, pi)
end

@attr GAPGroupHomomorphism{T, PermGroup} function action_homomorphism(C::GAPGroupConjClass{T, S}) where T where S
G = C.X
acthom = GAP.Globals.ActionHomomorphism(G.X, C.CC, GAP.Globals.OnPoints)::GapObj

# See the comment about `SetJuliaData` in the `action_homomorphism` method
# for `GSetByElements`.
GAP.Globals.SetJuliaData(acthom, GAP.Obj([C, G]))

sym = get_attribute!(C, :action_range) do
return symmetric_group(length(Int, C))
end
return GAPGroupHomomorphism(G, sym, acthom)
end


"""
representative(C::GroupConjClass)
Expand All @@ -565,11 +620,12 @@ Return a representative of the conjugacy class `C`.
julia> G = symmetric_group(4);
julia> C = conjugacy_class(G, G([2, 1, 3, 4]))
(1,2) ^ Sym( [ 1 .. 4 ] )
Conjugacy class of
(1,2) in
Sym(4)
julia> representative(C)
(1,2)
```
"""
representative(C::GroupConjClass) = C.repr
Expand All @@ -584,11 +640,12 @@ Return the acting group of `C`.
julia> G = symmetric_group(4);
julia> C = conjugacy_class(G, G([2, 1, 3, 4]))
(1,2) ^ Sym( [ 1 .. 4 ] )
Conjugacy class of
(1,2) in
Sym(4)
julia> acting_group(C) === G
true
```
"""
acting_group(C::GroupConjClass) = C.X
Expand All @@ -605,8 +662,9 @@ Return the conjugacy class `cc` of `g` in `G`, where `g` = `representative`(`cc`
julia> G = symmetric_group(4);
julia> C = conjugacy_class(G, G([2, 1, 3, 4]))
(1,2) ^ Sym( [ 1 .. 4 ] )
Conjugacy class of
(1,2) in
Sym(4)
```
"""
function conjugacy_class(G::GAPGroup, g::GAPGroupElem)
Expand All @@ -621,6 +679,25 @@ function Base.rand(rng::Random.AbstractRNG, C::GAPGroupConjClass{S,T}) where S w
return group_element(C.X, GAP.Globals.Random(GAP.wrap_rng(rng), C.CC)::GapObj)
end

Base.in(g::GAPGroupElem, C::GAPGroupConjClass) = GapObj(g) in C.CC
Base.in(G::GAPGroup, C::GAPGroupConjClass) = GapObj(G) in C.CC

Base.IteratorSize(::Type{<:GAPGroupConjClass}) = Base.SizeUnknown()

Base.iterate(cc::GAPGroupConjClass) = iterate(cc, GAPWrap.Iterator(cc.CC))

function Base.iterate(cc::GAPGroupConjClass{S,T}, state::GapObj) where {S,T}
if GAPWrap.IsDoneIterator(state)
return nothing
end
i = GAPWrap.NextIterator(state)::GapObj
if T <: GAPGroupElem
return group_element(cc.X, i), state
else
return _as_subgroup(cc.X, i)[1], state
end
end


"""
number_conjugacy_classes(G::GAPGroup)
Expand Down Expand Up @@ -705,11 +782,10 @@ Sym(3)
julia> conjugacy_classes_subgroups(G)
4-element Vector{GAPGroupConjClass{PermGroup, PermGroup}}:
Group(()) ^ Sym( [ 1 .. 3 ] )
Group([ (2,3) ]) ^ Sym( [ 1 .. 3 ] )
Group([ (1,2,3) ]) ^ Sym( [ 1 .. 3 ] )
Group([ (1,2,3), (2,3) ]) ^ Sym( [ 1 .. 3 ] )
Conjugacy class of permutation group in Sym(3)
Conjugacy class of permutation group in Sym(3)
Conjugacy class of permutation group in Sym(3)
Conjugacy class of permutation group in Sym(3)
```
"""
function conjugacy_classes_subgroups(G::GAPGroup)
Expand Down Expand Up @@ -760,9 +836,8 @@ julia> G = symmetric_group(3);
julia> conjugacy_classes_maximal_subgroups(G)
2-element Vector{GAPGroupConjClass{PermGroup, PermGroup}}:
Group([ (1,2,3) ]) ^ Sym( [ 1 .. 3 ] )
Group([ (2,3) ]) ^ Sym( [ 1 .. 3 ] )
Conjugacy class of permutation group in Sym(3)
Conjugacy class of permutation group in Sym(3)
```
"""
function conjugacy_classes_maximal_subgroups(G::GAPGroup)
Expand Down Expand Up @@ -1009,23 +1084,6 @@ end
# END subgroups conjugation


# START iterator
Base.IteratorSize(::Type{<:GAPGroupConjClass}) = Base.SizeUnknown()

Base.iterate(cc::GAPGroupConjClass) = iterate(cc, GAPWrap.Iterator(cc.CC))

function Base.iterate(cc::GAPGroupConjClass{S,T}, state::GapObj) where {S,T}
if GAPWrap.IsDoneIterator(state)
return nothing
end
i = GAPWrap.NextIterator(state)::GapObj
if T <: GAPGroupElem
return group_element(cc.X, i), state
else
return _as_subgroup(cc.X, i)[1], state
end
end

################################################################################
#
# Normal Structure
Expand Down
2 changes: 1 addition & 1 deletion src/Groups/gsets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ abstract type GSet{T} end
function GSetByElements(G::T, fun::Function, seeds; closed::Bool = false) where T<:GAPGroup
@assert ! isempty(seeds)
Omega = new{T}(G, fun, seeds, Dict{Symbol,Any}())
closed && set_attribute!(Omega, :elements => collect(seeds))
closed && set_attribute!(Omega, :elements => unique!(collect(seeds)))
return Omega
end
end
Expand Down
14 changes: 14 additions & 0 deletions test/Groups/conjugation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,20 @@

end

@testset "Conjugacy classes as G-sets" begin
G = symmetric_group(4)
x = G(cperm([3, 4]))
y = G(cperm([1, 4, 2]))
C = conjugacy_class(G, x)
@test x in C
@test orbits(C) == [C]
@test C == orbit(G, x)
mp = action_homomorphism(C)
@test permutation(C, y) == mp(y)
@test length(C) == 6
@test order(image(mp)[1]) == 24
end

function TestConjCentr(G,x)
Cx = centralizer(G,x)[1]
cc = conjugacy_class(G,x)
Expand Down

0 comments on commit d3eafa9

Please sign in to comment.