Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/src/Groups/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ is_finitely_generated(G::GAPGroup)
order(::Type{T}, x::Union{GAPGroupElem, GAPGroup}) where T <: IntegerUnion
abelian_invariants(G::GAPGroup)
abelian_invariants_schur_multiplier(G::GAPGroup)
abelian_invariants(v::Vector{S}) where S <: IntegerUnion
elementary_divisors(v::Vector{S}) where S <: IntegerUnion
cyclic_generator(G::GAPGroup)
exponent(G::GAPGroup)
describe(G::GAPGroup)
Expand Down
69 changes: 54 additions & 15 deletions src/Groups/GrpAb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -346,12 +346,33 @@

is_pgroup_with_prime(G::FinGenAbGroup) = is_pgroup_with_prime(ZZRingElem, G)

# Let `v` be a vector of integers.
# This function returns the unique sorted vector `w` of zeros and prime powers
# such that `v` and `w` describe the same abelian group in the sense that
# the direct product of the groups `ZZ /(v[i]*ZZ)` is isomorphic to
# the direct product of the groups `ZZ /(w[i]*ZZ)`.
function abelian_invariants_of_vector(::Type{T}, v::Vector) where T <: IntegerUnion
# convert between "abelian invariants format" and "elementary divisors format"

"""

Check warning on line 351 in src/Groups/GrpAb.jl

View check run for this annotation

Codecov / codecov/patch

src/Groups/GrpAb.jl#L351

Added line #L351 was not covered by tests
abelian_invariants(::Type{T} = S, v::Vector{S}) where {T <: IntegerUnion, S <: IntegerUnion}

Return the unique sorted vector `w` of zeros and prime powers of type `T`
such that `v` and `w` describe the same abelian group in the sense that
the direct product of the groups of order `v[i]` is isomorphic to
the direct product of the groups of order `w[i]`.

For example, if `v` was computed with
[`elementary_divisors(G::FinGenAbGroup)`](@ref)
then `w` is equal to the vector computed with
[`abelian_invariants(G::FinGenAbGroup)`](@ref).

# Examples
```jldoctest
julia> abelian_invariants(ZZRingElem, [1, 0, 12])
3-element Vector{ZZRingElem}:
0
3
4
```
"""
abelian_invariants(v::Vector{S}) where S <: IntegerUnion = abelian_invariants(S, v)

function abelian_invariants(::Type{T}, v::Vector{S}) where {T <: IntegerUnion, S <: IntegerUnion}
invs = T[]
for elm in v
if elm == 0
Expand All @@ -365,13 +386,31 @@
return sort!(invs)
end

# Let `v` be a vector of integers.
# This function returns the unique vector `w` of nonnegative integers
# such that `w[1] != 1`, `w[i]` divides `w[i+1]` for `1 < i < length(w)-1`
# and such that `v` and `w` describe the same abelian group in the sense that
# the direct product of the groups `ZZ /(v[i]*ZZ)` is isomorphic to
# the direct product of the groups `ZZ /(w[i]*ZZ)`.
function elementary_divisors_of_vector(::Type{T}, v::Vector) where T <: IntegerUnion
"""
elementary_divisors(::Type{T} = S, v::Vector{S}) where {T <: IntegerUnion, S <: IntegerUnion}

Return the unique vector `w` of nonnegative integers of type `T`
such that `w[1] != 1`, `w[i]` divides `w[i+1]` for `1 <= i < length(w)`
and such that `v` and `w` describe the same abelian group in the sense that
the direct product of cyclic groups of order `v[i]` is isomorphic to
the direct product of cyclic groups of order `w[i]`.

For example, if `v` was computed with
[`abelian_invariants(G::FinGenAbGroup)`](@ref)
then `w` is equal to the vector computed with
[`elementary_divisors(G::FinGenAbGroup)`](@ref).

# Examples
```jldoctest
julia> elementary_divisors(ZZRingElem, [1, 0, 3, 4])
2-element Vector{ZZRingElem}:
12
0
```
"""
elementary_divisors(v::Vector{S}) where S <: IntegerUnion = elementary_divisors(S, v)

function elementary_divisors(::Type{T}, v::Vector{S}) where {T <: IntegerUnion, S <: IntegerUnion}
invs = T[]
d = Dict{T, Vector{T}}()
for elm in v
Expand Down Expand Up @@ -414,7 +453,7 @@
end

abelian_invariants(::Type{T}, G::FinGenAbGroup) where T <: IntegerUnion =
abelian_invariants_of_vector(T, elementary_divisors(G))
abelian_invariants(T, elementary_divisors(G))

abelian_invariants(G::FinGenAbGroup) = abelian_invariants(ZZRingElem, G)

Expand All @@ -429,7 +468,7 @@
for i in 1:(k-1)
append!(res, repeat(T[invs[i]], k-i))
end
return abelian_invariants_of_vector(T, res)
return abelian_invariants(T, res)
end

abelian_invariants_schur_multiplier(G::FinGenAbGroup) = abelian_invariants_schur_multiplier(ZZRingElem, G)
Expand Down
14 changes: 10 additions & 4 deletions src/Groups/sub.jl
Original file line number Diff line number Diff line change
Expand Up @@ -928,12 +928,17 @@ end
"""
abelian_invariants(::Type{T} = ZZRingElem, G::Union{GAPGroup, FinGenAbGroup}) where T <: IntegerUnion

Return the sorted vector of abelian invariants of the commutator factor group
of `G` (see [`maximal_abelian_quotient`](@ref)).
Return the sorted vector `v` of abelian invariants of the commutator factor
group `Q` of `G` (see [`maximal_abelian_quotient`](@ref)).
The entries are prime powers or zeroes and have the type `T`.
They describe the structure of the commutator factor group of `G`
as a direct product of cyclic groups of prime power (or infinite) order.

In order to convert between the formats defined for `abelian_invariants`
and [`elementary_divisors(::FinGenAbGroup)`](@ref) for `Q`,
one can apply [`elementary_divisors(::Vector)`](@ref) to `v`
and [`abelian_invariants(::Vector{S}) where S <: Oscar.IntegerUnion`](@ref) to the result of that call.

# Examples
```jldoctest
julia> abelian_invariants(symmetric_group(4))
Expand Down Expand Up @@ -963,7 +968,8 @@ abelian_invariants(::Type{T}, G::GAPGroup) where T <: IntegerUnion =
abelian_invariants_schur_multiplier(::Type{T} = ZZRingElem, G::Union{GAPGroup, FinGenAbGroup}) where T <: IntegerUnion

Return the sorted vector of abelian invariants
(see [`abelian_invariants`](@ref)) of the Schur multiplier of `G`.
(see [`abelian_invariants(::Union{GAPGroup, FinGenAbGroup})`](@ref))
of the Schur multiplier of `G`.
The entries are prime powers or zeroes and have the type `T`.
They describe the structure of the Schur multiplier of `G`
as a direct product of cyclic groups of prime power (or infinite) order.
Expand Down Expand Up @@ -1018,7 +1024,7 @@ Z/1
schur_multiplier(G::Union{GAPGroup, FinGenAbGroup}) = schur_multiplier(FinGenAbGroup, G)

function schur_multiplier(::Type{T}, G::Union{GAPGroup, FinGenAbGroup}) where T <: Union{GAPGroup, FinGenAbGroup}
eldiv = elementary_divisors_of_vector(ZZRingElem, abelian_invariants_schur_multiplier(G))
eldiv = elementary_divisors(ZZRingElem, abelian_invariants_schur_multiplier(G))
M = abelian_group(eldiv)
(M isa T) && return M
return codomain(isomorphism(T, M))
Expand Down
20 changes: 11 additions & 9 deletions test/Groups/GrpAb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,19 @@ end
end

@testset "conversions between formats of abelian invariants" begin
@test Oscar.elementary_divisors_of_vector(Int, []) == []
@test Oscar.elementary_divisors_of_vector(Int, [0, 3, 2]) == [6, 0]
@test Oscar.abelian_invariants_of_vector(Int, []) == []
@test Oscar.abelian_invariants_of_vector(Int, [0, 6]) == [0, 2, 3]
@test elementary_divisors(Int, Int[]) == []
@test elementary_divisors(Int, [0, 3, 2]) == [6, 0]
@test abelian_invariants(Int, Int[]) == []
@test abelian_invariants(Int, [0, 6]) == [0, 2, 3]
for i in 1:100
v = rand(-5:30, 10)
elab = Oscar.elementary_divisors_of_vector(Int, v)
abinv = Oscar.abelian_invariants_of_vector(Int, v)
@test Oscar.elementary_divisors_of_vector(Int, abinv) == elab
@test Oscar.abelian_invariants_of_vector(Int, elab) == abinv
@test elementary_divisors(abelian_group([abs(x) for x in v])) == elab
elab = elementary_divisors(Int, v)
abinv = abelian_invariants(Int, v)
@test elementary_divisors(abinv) == elab
@test abelian_invariants(elab) == abinv
G = abelian_group([abs(x) for x in v])
@test elementary_divisors(G) == elab
@test abelian_invariants(G) == abinv
end
end

Expand Down
Loading