From 1b69e3d8fc2528d51dbf341b6ab1023a9cee38e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Tue, 19 Nov 2024 17:34:51 +0100 Subject: [PATCH] fix: group algebras of additive groups with sparse rep (#1685) * fix: group algebra operation redirection * fix: order for finite dim group algebras with sparse rep * fix: construct group algebras for `AdditiveGroup` that is not `FinGenAbGroup` * fix: `is_commutative` for group algebras with sparse rep * Add test for additive group with sparse rep * fix: add warning to `StructureConstantAlgebra` constructor * fix: show for infinite dim group algebras * Add some printing tests * fix: unary minus for sparse group algebra elems --- src/AlgAss/AlgGrp.jl | 57 +++++++++++++++++++++++++++++++------------ src/AlgAss/Elem.jl | 8 ++++-- src/AlgAss/Types.jl | 8 ++---- test/AlgAss/AlgGrp.jl | 39 ++++++++++++++++++++++++++++- 4 files changed, 88 insertions(+), 24 deletions(-) diff --git a/src/AlgAss/AlgGrp.jl b/src/AlgAss/AlgGrp.jl index abeeaa10e4..f977a7675a 100644 --- a/src/AlgAss/AlgGrp.jl +++ b/src/AlgAss/AlgGrp.jl @@ -12,7 +12,7 @@ base_ring(A::GroupAlgebra{T}) where {T} = A.base_ring::parent_type(T) base_ring_type(::Type{GroupAlgebra{T, S, R}}) where {T, S, R} = parent_type(T) -Generic.dim(A::GroupAlgebra) = size(multiplication_table(A, copy = false), 1) +Generic.dim(A::GroupAlgebra) = order(Int, group(A)) elem_type(::Type{GroupAlgebra{T, S, R}}) where {T, S, R} = GroupAlgebraElem{T, GroupAlgebra{T, S, R}} @@ -55,11 +55,15 @@ end # get the underyling group operation, I wish this was part of the group interface _op(G::AbstractAlgebra.AdditiveGroup) = + - _op(G::Group) = * - _op(A::GroupAlgebra) = _op(group(A)) +_is_identity_elem(x::AbstractAlgebra.AdditiveGroupElem) = iszero(x) +_is_identity_elem(x::GroupElem) = isone(x) + +_identity_elem(G::AbstractAlgebra.AdditiveGroup) = zero(G) +_identity_elem(G::Group) = one(G) + ################################################################################ # # Construction @@ -81,12 +85,12 @@ Group algebra over rational field ``` """ -group_algebra(K::Ring, G; cached = true) = _group_algebra(K, G; op = *, cached) +group_algebra(K::Ring, G; cached = true) = _group_algebra(K, G; cached) # one additional level of indirection to hide the non-user facing options # `op` and `sparse`. -function _group_algebra(K::Ring, G; op = *, sparse = _use_sparse_group_algebra(G), cached::Bool = true) - A = GroupAlgebra(K, G; op = _op(G) , sparse = sparse, cached = cached) +function _group_algebra(K::Ring, G; op = _op(G), sparse = _use_sparse_group_algebra(G), cached::Bool = true) + A = GroupAlgebra(K, G; op = op , sparse = sparse, cached = cached) if !(K isa Field) return A end @@ -128,16 +132,26 @@ function is_commutative(A::GroupAlgebra) if is_commutative_known(A) return A.is_commutative == 1 end - for i in 1:dim(A) - for j in 1:dim(A) - if multiplication_table(A, copy = false)[i, j] != multiplication_table(A, copy = false)[j, i] - A.is_commutative = 2 - return false + if _is_sparse(A) + if is_abelian(group(A)) + A.is_commutative = 1 + return true + else + A.is_commutative = 2 + return false + end + else + for i in 1:dim(A) + for j in 1:dim(A) + if multiplication_table(A, copy = false)[i, j] != multiplication_table(A, copy = false)[j, i] + A.is_commutative = 2 + return false + end end end + A.is_commutative = 1 + return true end - A.is_commutative = 1 - return true end ################################################################################ @@ -157,9 +171,21 @@ end function show(io::IO, A::GroupAlgebra) if is_terse(io) - print(io, "Group algebra of dimension ", dim(A), " over ", base_ring(A)) + print(io, "Group algebra of ") + if is_finite(group(A)) + print(io, "dimension ", order(group(A))) + else + print(io, "infinite dimension ") + end + print(io, " over ", base_ring(A)) else - print(io, "Group algebra of group of order ", order(group(A)), " over ") + print(io, "Group algebra of group ") + if is_finite(group(A)) + print(io, "of order ", order(group(A))) + else + print(io, "of infinite order ") + end + print(io, "over ") print(terse(io), base_ring(A)) end end @@ -236,6 +262,7 @@ end ################################################################################ function StructureConstantAlgebra(A::GroupAlgebra{T, S, R}) where {T, S, R} + @req _is_dense(A) "StructureConstantAlgebra only works for dense group algebras" K = base_ring(A) mult = Array{T, 3}(undef, dim(A), dim(A), dim(A)) B = basis(A) diff --git a/src/AlgAss/Elem.jl b/src/AlgAss/Elem.jl index 46e8d75b69..6f7970a8a5 100644 --- a/src/AlgAss/Elem.jl +++ b/src/AlgAss/Elem.jl @@ -147,8 +147,12 @@ end ################################################################################ function -(a::AbstractAssociativeAlgebraElem{T}) where {T} - v = T[ -coefficients(a, copy = false)[i] for i = 1:dim(parent(a)) ] - return parent(a)(v) + if _is_sparse(a) + return parent(a)(-a.coeffs_sparse) + else + v = T[ -coefficients(a, copy = false)[i] for i = 1:dim(parent(a)) ] + return parent(a)(v) + end end ################################################################################ diff --git a/src/AlgAss/Types.jl b/src/AlgAss/Types.jl index 1da1e9a9a6..207ff9385a 100644 --- a/src/AlgAss/Types.jl +++ b/src/AlgAss/Types.jl @@ -186,11 +186,7 @@ end end if A.sparse - if G isa FinGenAbGroup - el = zero(G) - else - el = one(G) - end + el = _identity_elem(G) A.group_to_base[el] = 1 A.base_to_group[1] = el A.sparse_one = sparse_row(K, [1], [one(K)]) @@ -199,7 +195,7 @@ end A.mult_table = zeros(Int, d, d) i = 2 for g in collect(G) - if isone(g) + if _is_identity_elem(g) A.group_to_base[deepcopy(g)] = 1 A.base_to_group[1] = deepcopy(g) continue diff --git a/test/AlgAss/AlgGrp.jl b/test/AlgAss/AlgGrp.jl index 20c3dde96e..7ee39d22ca 100644 --- a/test/AlgAss/AlgGrp.jl +++ b/test/AlgAss/AlgGrp.jl @@ -1,7 +1,8 @@ @testset "Group algebras" begin G = small_group(8, 4) A = GroupAlgebra(QQ, G) - + @test sprint(show, MIME"text/plain"(), A) isa String + @test sprint(show, A) isa String @testset "Regular matrix algebra" begin B, BtoA = Hecke.regular_matrix_algebra(A) @@ -90,6 +91,10 @@ let G = SymmetricGroup(10) QG = Hecke._group_algebra(QQ, G; sparse = true, cached = false) + @test dim(QG) == factorial(10) + #@test !is_commutative(QG) # needs https://github.com/Nemocas/AbstractAlgebra.jl/pull/1907 + @test sprint(show, MIME"text/plain"(), QG) isa String + @test sprint(show, QG) isa String for i in 1:10 a = rand(G) b = rand(G) @@ -102,6 +107,38 @@ @test aa * bb == cc @test bb * aa == dd @test (aa + bb)^2 == QG(a)^2 + cc + dd + QG(b)^2 + @test aa - bb == aa + (-bb) + end + end + + let + G = abelian_group([2, 3, 5000]) + QG = Hecke._group_algebra(QQ, G; sparse = true, cached = false) + @test dim(QG) == 2 * 3 * 5000 + @test is_commutative(QG) + @test sprint(show, MIME"text/plain"(), QG) isa String + @test sprint(show, QG) isa String + for i in 1:10 + a = rand(G) + b = rand(G) + c = a + b + d = b + a + aa = QG(a) + bb = QG(b) + cc = QG(c) + dd = QG(d) + @test aa * bb == cc + @test bb * aa == dd + @test (aa + bb)^2 == QG(a)^2 + cc + dd + QG(b)^2 + @test aa - bb == aa + (-bb) end end + + let + G = abelian_group([2, 3, 0]) + QG = Hecke._group_algebra(QQ, G; sparse = true, cached = false) + @test is_commutative(QG) + @test sprint(show, MIME"text/plain"(), QG) isa String + @test sprint(show, QG) isa String + end end