StarAlgebras (+their elements) based on Basis and MStructures

This commit is contained in:
Marek Kaluba 2021-06-19 00:59:35 +02:00
parent 781e26299f
commit 1151ac7bd3
No known key found for this signature in database
GPG Key ID: 8BF1A3855328FC15
7 changed files with 279 additions and 0 deletions

View File

@ -565,12 +565,18 @@ end
module New
using SparseArrays
import LinearAlgebra
include("bases.jl")
include("mstructures.jl")
include("mtables.jl")
include("types.jl")
include("algebra_elts.jl")
include("show.jl")
end
end # of module GroupRings

44
src/algebra_elts.jl Normal file
View File

@ -0,0 +1,44 @@
function Base.hash(a::AlgebraElement, h::UInt)
return hash(coeffs(a), hash(parent(a), hash(typeof(a), h)))
end
function Base.:(==)(X::AlgebraElement, Y::AlgebraElement)
parent(X) === parent(Y) || return false
return coeffs(X) == coeffs(Y)
end
Base.getindex(a::AlgebraElement, i::Integer) = coeffs(a)[i]
Base.getindex(a::AlgebraElement{<:StarAlgebra{O,T}}, x::T) where {O,T} =
(b = basis(parent(a)); a[b[x]])
# call overload:
(a::AlgebraElement)(x) = a[x]
Base.setindex!(a::AlgebraElement, v, i::Integer) = a.coeffs[i] = v
function Base.setindex!(a::AlgebraElement{<:StarAlgebra{O,T}}, v, t::T) where {O,T}
b = basis(parent(a))
return a[b[t]] = v
end
# AlgebraElement specific functions
supp_ind(a::AlgebraElement) = findall(!iszero, coeffs(a))
supp_ind(a::AlgebraElement{A,T,<:SparseVector}) where {A,T} = coeffs(a).nzind
supp(a::AlgebraElement) = (b = basis(parent(a)); [b[i] for i in supp_ind(a)])
function star(X::AlgebraElement)
A = parent(X)
b = basis(A)
supp_X = supp_ind(X)
idcs = similar(supp_X)
vals = similar(idcs, eltype(X))
for (i, idx) in enumerate(supp_X)
idcs[i] = b[star(b[idx])]
vals[i] = X[idx]
end
return AlgebraElement(sparsevec(idcs, vals, length(b)), A)
end
LinearAlgebra.norm(a::AlgebraElement, p) = LinearAlgebra.norm(coeffs(a), p)
aug(a::AlgebraElement) = sum(coeffs(a))

35
src/show.jl Normal file
View File

@ -0,0 +1,35 @@
Base.show(io::IO, A::AbstractStarAlgebra) = print(io, "*-Algebra of $(object(A))")
__prints_with_minus(x) = false
__prints_with_minus(x::Real) = x < 0
function Base.show(io::IO, a::AlgebraElement)
A = parent(a)
if iszero(a)
T = eltype(a)
print(io, "$(zero(T))*$(one(object(A)))")
elseif hasbasis(A)
elts = String[]
nzeros = findall(!iszero, coeffs(a))
for (counter, idx) in enumerate(nzeros)
c, elt = coeffs(a)[idx], basis(A)[idx]
if counter == 1
print(io, c, '·', elt)
length(nzeros) > 1 && print(io, ' ')
else
__prints_with_minus(c) || print(io, '+')
print(io, c, '·', elt)
counter == length(nzeros) || print(io, ' ')
end
end
else
println(io, "Algebra element without defined basis")
show(io, MIME("text/plain"), a.coeffs)
end
end
function Base.show(io::IO, ::MIME"text/plain", mstr::TrivialMStructure)
Tw = _istwisted(mstr)
l = length(basis(mstr))
print(io, "TrivialMStructure{$Tw} over basis with $l elements")
end

116
src/types.jl Normal file
View File

@ -0,0 +1,116 @@
abstract type AbstractStarAlgebra end
struct StarAlgebra{O,T,M<:MultiplicativeStructure,B<:AbstractBasis{T}} <:
AbstractStarAlgebra
object::O
mstructure::M
basis::B
function StarAlgebra(obj, basis::AbstractBasis, mstr::MultiplicativeStructure)
O = typeof(obj)
T = eltype(basis)
M = typeof(mstr)
B = typeof(basis)
return new{O,T,M,B}(obj, mstr, basis)
end
function StarAlgebra(obj, mstr::MultiplicativeStructure)
O = typeof(obj)
T = Symbol
M = typeof(mstr)
B = Basis{T,Int}
return new{O,T,M,B}(obj, mstr)
end
end
# TrivialMStructure:
StarAlgebra(obj, basis::AbstractBasis) = StarAlgebra{false}(obj, basis)
function StarAlgebra{Tw}(obj, basis::AbstractBasis) where {Tw}
mstr = TrivialMStructure{Tw}(basis)
return StarAlgebra(obj, basis, mstr)
end
# CachedMStructure:
StarAlgebra(obj, basis::AbstractBasis, cache_size::Tuple{<:Integer,Integer}) =
StarAlgebra{false}(obj, basis, cache_size)
function StarAlgebra{Tw}(
obj,
basis::AbstractBasis,
cache_size::Tuple{<:Integer,Integer},
) where {Tw}
mstr = CachedMTable{Tw}(basis, table_size = cache_size)
return StarAlgebra(obj, basis, mstr)
end
hasbasis(A::StarAlgebra) = isdefined(A, :basis)
basis(A::StarAlgebra) = A.basis
object(A::StarAlgebra) = A.object
# Base.eltype(A::StarAlgebra{O,B}) where {O,B} = eltype(B)
struct AlgebraElement{A,T,V<:AbstractVector{T}}
coeffs::V
parent::A
function AlgebraElement(coeffs::AbstractVector, A::AbstractStarAlgebra)
if hasbasis(A)
@assert length(coeffs) == length(basis(A))
end
return new{typeof(A),eltype(coeffs),typeof(coeffs)}(coeffs, A)
end
end
coeffs(a::AlgebraElement) = a.coeffs
Base.parent(a::AlgebraElement) = a.parent
Base.eltype(a::AlgebraElement) = eltype(coeffs(a))
### constructing elements
function Base.zero(A::AbstractStarAlgebra, T = Int)
if hasbasis(A)
return AlgebraElement(spzeros(T, length(basis(A))), A)
else
return AlgebraElement(spzeros(T, maximum(A.mstructure)))
end
end
Base.one(A::AbstractStarAlgebra, T = Int) = A(one(object(A)), T)
Base.zero(a::AlgebraElement) = zero(parent(a))
Base.one(a::AlgebraElement) = one(parent(a))
Base.iszero(a::AlgebraElement) = iszero(coeffs(a))
function Base.isone(a::AlgebraElement, T = Int)
b = basis(parent(a))
k = findfirst(!iszero, coeffs(a))
k === nothing && return false
isone(a[k]) || return false
return isone(b[k])
end
function (A::AbstractStarAlgebra)(elt, T = Int)
if hasbasis(A)
b = basis(A)
i = b[elt]
return AlgebraElement(sparsevec([i], [one(T)], length(b)), A)
else
throw("Cannot coerce $elt to an algebra without defined basis")
end
end
function (A::AbstractStarAlgebra)(x::Number)
g = one(object(A))
res = A(g, typeof(x))
res = mul!(res, res, x)
return res
end
Base.similar(X::AlgebraElement, ::Type{T} = eltype(X)) where {T} =
AlgebraElement(similar(coeffs(X), T), parent(X))

View File

@ -30,3 +30,33 @@
@test tmstr[3, 2] == b[inv(b[3])*b[2]]
end
@testset "Group Algebra caching" begin
G = SymmetricGroup(3)
b = New.Basis{UInt8}(collect(G))
l = length(b)
RG = New.StarAlgebra(G, b, (l, l))
@test RG isa New.StarAlgebra
D = ((l + 1) * one(RG) - sum(RG(g) for g in b)) // 6
@test D isa New.AlgebraElement
g = RG(b[1])
@test isone(g)
@test one(RG) == g
@test iszero(zero(RG))
@test 0 * g == zero(RG)
@test iszero(0 * g)
h = RG(b[3])
@test D * one(RG) == D
@test all(New.supp(D) .== b)
@test one(RG) * D == D
@test any(iszero, RG.mstructure.table)
@test D * D isa New.AlgebraElement
@test all(!iszero, RG.mstructure.table)
end

47
test/constructors.jl Normal file
View File

@ -0,0 +1,47 @@
@testset "Algebra and Elements Constructors" begin
G = SymmetricGroup(3)
b = New.Basis{UInt8}(collect(G))
l = length(b)
RG = New.StarAlgebra(G, b, (l, l))
a = rand(6)
@test New.AlgebraElement(a, RG) isa New.AlgebraElement
@test all(RG(g) isa New.AlgebraElement{typeof(RG)} for g in G)
@test_throws AssertionError New.AlgebraElement([1,2,3], RG)
@test New.AlgebraElement([1,2,3,0,0,0], RG) isa New.AlgebraElement
p = G([2,3,1])
a = RG(p)
@test New.coeffs(a) isa SparseVector
@test New.coeffs(a)[5] == 1
@test all(New.coeffs(a)[i] == 0 for i in 1:6 if i 5)
@test a(p) == 1
@test all(a(g) == 0 for g in G if g != p)
@test sprint(show, a) == "1·(1,2,3)"
@test sprint(show, -a) == "-1·(1,2,3)"
@test New.AlgebraElement([0,0,0,0,1,0], RG) == a
@test New.supp(a) == [p]
@test New.supp_ind(a) == [5]
s = one(G)
@test a(s) == 0
a[s] = 2
@test New.coeffs(a)[1] == 2
@test a[1] == 2
@test a(s) == 2
@test New.supp(a) == [s, p]
@test New.supp_ind(a) == [1, 5]
@test sprint(show, a) == "2·() +1·(1,2,3)"
@test sprint(show, -a) == "-2·() -1·(1,2,3)"
@test sprint(show, New.AlgebraElement([2,0,0,0,-1,0], RG)) == "2·() -1·(1,2,3)"
end

View File

@ -10,6 +10,7 @@ using GroupRings.New
New.star(p::Generic.Perm) = inv(p)
include("constructors.jl")
include("cachedmtables.jl")
end