Skip to content

Commit

Permalink
Group coset changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Giovanni De Franceschi authored and fingolfin committed Jul 21, 2020
1 parent 5170aa2 commit 730d3ce
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 6 deletions.
63 changes: 57 additions & 6 deletions src/Groups/cosets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export
double_cosets,
elements,
isbicoset,
isleft,
isright,
left_acting_group,
left_coset,
left_cosets,
Expand All @@ -17,9 +19,9 @@ export
# T=type of the group, S=type of the element
"""
GroupCoset{T<: Group, S <: GAPGroupElem}
Group coset. It is displayed as `H * x` (right cosets) or `x * H` (left cosets), where `H` is a subgroup of a group `G` and `x` is an element of `G`. Two cosets are equal if, and only if, they are both left (resp. right) and they contain the same elements.
Type of group cosets. It is displayed as `H * x` (right cosets) or `x * H` (left cosets), where `H` is a subgroup of a group `G` and `x` is an element of `G`. Two cosets are equal if, and only if, they are both left (resp. right) and they contain the same elements.
"""
mutable struct GroupCoset{T<: GAPGroup, S <: GAPGroupElem}
struct GroupCoset{T<: GAPGroup, S <: GAPGroupElem}
G::T # big group containing the subgroup and the element
H::T # subgroup
repr::S # element
Expand All @@ -37,8 +39,10 @@ function ==(x::GroupCoset, y::GroupCoset)
return x.X == y.X && x.side == y.side
end


"""
right_coset(H::Group, g::GAPGroupElem)
*(H::Group, g::GAPGroupElem)
Return the coset `Hg`.
"""
function right_coset(H::GAPGroup, g::GAPGroupElem)
Expand All @@ -50,8 +54,11 @@ function right_coset(H::GAPGroup, g::GAPGroupElem)
end

"""
right_coset(H::Group, g::GAPGroupElem)
left_coset(H::Group, g::GAPGroupElem)
*(g::GAPGroupElem, H::Group)
Return the coset `gH`.
!!! note
Since GAP supports right cosets only, the underlying GAP object of `left_coset(H,g)` is the right coset `H^(g^-1) * g`.
"""
function left_coset(H::GAPGroup, g::GAPGroupElem)
@assert elem_type(H) == typeof(g)
Expand All @@ -65,13 +72,53 @@ function show(io::IO, x::GroupCoset)
a = GAP.gap_to_julia(GAP.Globals.StringViewObj(x.H.X))
b = GAP.gap_to_julia(GAP.Globals.StringViewObj(x.repr.X))
if x.side == :right
print(io, a, " * ", b)
print(io, "Right coset ", a, " * ", b)
else
print(io, b, " * ", a)
print(io, "Left coset ", b, " * ", a)
end
return nothing
end

"""
isleft(c::GroupCoset)
Return whether the coset `c` is a left coset of its acting domain.
"""
isleft(c::GroupCoset) = c.side == :left

"""
isright(c::GroupCoset)
Return whether the coset `c` is a right coset of its acting domain.
"""
isright(c::GroupCoset) = c.side == :right

Base.:*(H::GAPGroup, g::GAPGroupElem) = right_coset(H,g)
Base.:*(g::GAPGroupElem, H::GAPGroup) = left_coset(H,g)

function Base.:*(c::GroupCoset, y::GAPGroupElem)
@assert y in c.G "element not in the group"
if c.side == :right
return right_coset(c.H, c.repr*y)
else
return left_coset(c.H^y, c.repr*y)
end
end

function Base.:*(y::GAPGroupElem, c::GroupCoset)
@assert y in c.G "element not in the group"
if c.side == :left
return left_coset(c.H, y*c.repr)
else
return right_coset(c.H^(y^-1), y*c.repr)
end
end

function Base.:*(c::GroupCoset, d::GroupCoset)
if c.side != :right || d.side != :left
throw(ArgumentError("Wrong input"))
end
return double_coset(c.H, c.repr*d.repr, d.H)
end

"""
acting_domain(C::GroupCoset)
If `C` = `Hx` or `xH`, return `H`.
Expand Down Expand Up @@ -173,7 +220,7 @@ end
Group double coset. It is displayed as `H * x * K`, where `H` and `K` are subgroups of a group `G` and `x` is an element of `G`. Two double cosets are equal if, and only if, they contain the same elements.
"""
# T=type of the group, S=type of the element
mutable struct GroupDoubleCoset{T <: GAPGroup, S <: GAPGroupElem}
struct GroupDoubleCoset{T <: GAPGroup, S <: GAPGroupElem}
G::T
H::T
K::T
Expand All @@ -195,8 +242,10 @@ function Base.show(io::IO, x::GroupDoubleCoset)
GAP.gap_to_julia(GAP.Globals.StringViewObj(x.K.X)))
end


"""
double_coset(H::Group, x::GAPGroupElem, K::Group)
*(H::Group, x::GAPGroupElem, K::Group)
returns the double coset `HxK`.
"""
function double_coset(G::T, g::GAPGroupElem{T}, H::T) where T<: GAPGroup
Expand All @@ -211,6 +260,8 @@ function double_coset(G::T, g::GAPGroupElem{T}, H::T) where T<: GAPGroup
return GroupDoubleCoset(parent(g),G,H,g,GAP.Globals.DoubleCoset(G.X,g.X,H.X))
end

Base.:*(H::GAPGroup, g::GAPGroupElem, K::GAPGroup) = double_coset(H,g,K)

"""
double_cosets(G::T, H::T, K::T; NC=false) where T<: GAPGroup
Return the array of all the double cosets `HxK` for `x` in `G`. If `NC` = `true`, do not check whether `H` and `K` are subgroups of `G`.
Expand Down
13 changes: 13 additions & 0 deletions test/Groups/subgroups_and_cosets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ end
@test index(G, H) == 4

C = right_coset(H, G[1])
@test isright(C)
@test order(C) == length(elements(C))

@test length(right_transversal(G, H)) == index(G, H)
Expand All @@ -154,6 +155,9 @@ end
rc = right_coset(H,x)
lc = left_coset(H,x)
dc = double_coset(H,x,K)
@test rc==H*x
@test lc==x*H
@test dc==H*x*K
@test acting_domain(rc) == H
@test acting_domain(lc) == H
@test left_acting_group(dc) == H
Expand All @@ -176,6 +180,15 @@ end
@test issubset(rc,dc)
@test issubset(left_coset(K,x),dc)
@test !isbicoset(rc)

@test rc == H*x
@test lc == x*H
@test dc == H*x*K
@test rc*y == H*(x*y)
@test lc*y == (x*y)*H^y
@test y*rc == H^(y^-1)*(y*x)
@test y*lc == (y*x)*H
@test rc*lc == double_coset(H,x^2,H)
end

H = sub(G, [cperm(G,[1,2,3]), cperm(G,[2,3,4])])[1]
Expand Down

0 comments on commit 730d3ce

Please sign in to comment.