From 383f2664f63ff4c3d927b8207d85f13ab4229eff Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:15:23 +0100 Subject: [PATCH 01/15] rewrite TrivialMstructure without twisted --- src/mstructures.jl | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/mstructures.jl b/src/mstructures.jl index c17a213..e74219a 100644 --- a/src/mstructures.jl +++ b/src/mstructures.jl @@ -1,10 +1,4 @@ -abstract type MultiplicativeStructure{Twisted,I} <: AbstractMatrix{I} end - -_istwisted(::MultiplicativeStructure{T}) where {T} = T -_product(ms::MultiplicativeStructure, g, h) = _product(Val(_istwisted(ms)), g, h) - -_product(::Val{false}, g, h) = g * h -_product(::Val{true}, g, h) = star(g) * h +abstract type MultiplicativeStructure{I} <: AbstractMatrix{I} end struct ProductNotDefined <: Exception i::Any @@ -21,12 +15,12 @@ function Base.showerror(io::IO, ex::ProductNotDefined) print(io, ".") end -struct TrivialMStructure{Tw,I,B<:AbstractBasis} <: MultiplicativeStructure{Tw,I} +struct TrivialMStructure{I,B<:AbstractBasis} <: MultiplicativeStructure{I} basis::B end -TrivialMStructure{Tw}(basis::AbstractBasis{T,I}) where {Tw,T,I} = - TrivialMStructure{Tw,I,typeof(basis)}(basis) +TrivialMStructure(basis::AbstractBasis{T,I}) where {T,I} = + TrivialMStructure{I,typeof(basis)}(basis) basis(mstr::TrivialMStructure) = mstr.basis Base.size(mstr::TrivialMStructure) = (l = length(basis(mstr)); (l, l)) @@ -36,10 +30,10 @@ Base.@propagate_inbounds function Base.getindex( i::Integer, j::Integer, ) - @boundscheck checkbounds(mstr, i, j) b = basis(mstr) - g, h = b[i], b[j] - gh = _product(mstr, g, h) + g = i ≥ 0 ? b[i] : star(b[-i]) + h = j ≥ 0 ? b[j] : star(b[-j]) + gh = g * h gh in b || throw(ProductNotDefined(i, j, "$g · $h = $gh")) - return b[gh] + return basis(mstr)[gh] end From 2387f45c567ee86896bbabee3469a0cea8bb9a76 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:17:28 +0100 Subject: [PATCH 02/15] rewrite mtables without twisted --- src/mtables.jl | 79 ++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/mtables.jl b/src/mtables.jl index a29b7f0..193a569 100644 --- a/src/mtables.jl +++ b/src/mtables.jl @@ -1,73 +1,84 @@ -abstract type AbstractMTable{I,Tw} <: MultiplicativeStructure{Tw,I} end +abstract type AbstractMTable{I} <: MultiplicativeStructure{I} end -Base.size(mt::AbstractMTable) = size(mt.table) - -_check(mt::AbstractMTable) = _check(mt.table, basis(mt), _istwisted(mt)) - -function _check(product_matrix, basis, twisted::Bool) +function _check(product_matrix::AbstractMatrix, basis::AbstractVector) idx = findfirst(iszero, product_matrix) - if idx != nothing + if idx !== nothing i, j = Tuple(idx) - x = (twisted ? star(basis[i]) : basis[i]) + x, y = basis[i], basis[j] throw( ProductNotDefined( i, j, - "$x · $(basis[j]) = $(_product(Val(twisted), x, basis[j]))", + "$x · $y = $(x * y)", ), ) end return true end +Base.size(mt::AbstractMTable) = size(mt.table) -_iscached(mt::AbstractMTable, i, j) = !iszero(mt.table[i, j]) - +function _star_of(basis::AbstractBasis, len::Integer) + return [basis[star(basis[i])] for i in 1:len] +end ## MTables - -struct MTable{I,Twisted,M<:AbstractMatrix{I}} <: AbstractMTable{I,Twisted} +struct MTable{I,M<:AbstractMatrix{I}} <: AbstractMTable{I} table::M + star_of::Vector{I} end -MTable{Tw}(mt::AbstractMatrix{<:Integer}) where {Tw} = MTable{eltype(mt),Tw,typeof(mt)}(mt) - -MTable(b::AbstractBasis; table_size) = MTable{false}(b; table_size=table_size) - -function MTable{Tw}(basis::AbstractBasis; table_size) where {Tw} +function MTable(basis::AbstractBasis; table_size) @assert length(table_size) == 2 + @assert 1 <= first(table_size) <= length(basis) @assert 1 <= last(table_size) <= length(basis) table = zeros(SparseArrays.indtype(basis), table_size) - complete!(table, basis, Val(Tw)) - - _check(table, basis, Tw) + complete!(table, basis) + _check(table, basis) - return MTable{Tw}(table) + return MTable(table, _star_of(basis, max(table_size...))) end -for twisted in (:true, :false) - @eval begin - function complete!(table, basis, v::Val{$twisted}) - Threads.@threads for j in 1:size(table, 2) - y = basis[j] - for i in 1:size(table, 1) - table[i, j] = basis[_product(v, basis[i], y)] - end +function complete!(table::AbstractMatrix, basis::AbstractBasis, lck=Threads.SpinLock()) + Threads.@threads for j in axes(table, 2) + y = basis[j] + for i in axes(table, 1) + xy = basis[i] * y + lock(lck) do + table[i, j] = xy end - return table end end + return table +end + +function complete!(table::Matrix, basis::AbstractBasis, lck=Threads.SpinLock()) + Threads.@threads for j in axes(table, 2) + y = basis[j] + for i in axes(table, 1) + x = basis[i] + table[i, j] = basis[x*y] + end + end + return table end basis(mt::MTable) = throw("No basis is defined for a simple $(typeof(mt))") +Base.@propagate_inbounds _iscached(mt::MTable, i, j) = !iszero(mt.table[i, j]) +Base.@propagate_inbounds _get(cmt::MTable, i::Integer) = ifelse(i ≥ 0, i, cmt.star_of[abs(i)]) Base.@propagate_inbounds function Base.getindex(m::MTable, i::Integer, j::Integer) - @boundscheck checkbounds(Bool, m, i, j) || + @boundscheck checkbounds(Bool, m, abs(i), abs(j)) || throw(ProductNotDefined(i, j, "out of Mtable bounds")) - @boundscheck iszero(m.table[i, j]) && throw(ProductNotDefined(i, j)) - return m.table[i, j] + @boundscheck !_iscached(m, abs(i), abs(j)) && throw(ProductNotDefined(i, j, "product not stored")) + @inbounds begin + i = _get(m, i) + j = _get(m, j) + + return m.table[i, j] + end end ## CachedMTables From fcf3ca9a6db516d21cfb079631d12240f17f6aca Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:18:22 +0100 Subject: [PATCH 03/15] base CachedMTable on MTable + make it thread-safe --- src/mtables.jl | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/mtables.jl b/src/mtables.jl index 193a569..c823803 100644 --- a/src/mtables.jl +++ b/src/mtables.jl @@ -83,44 +83,49 @@ end ## CachedMTables -struct CachedMTable{T,I,B<:Basis{T,I},M,Twisted} <: AbstractMTable{I,Twisted} +struct CachedMTable{I,T,B<:AbstractBasis{T,I},M<:MTable} <: AbstractMTable{I} basis::B table::M + lock::Threads.SpinLock end -CachedMTable(basis::AbstractBasis; table_size) = - CachedMTable{false}(basis; table_size=table_size) - -function CachedMTable{Tw}(basis::AbstractBasis{T,I}; table_size) where {Tw,T,I} - return CachedMTable{Tw}(basis, zeros(I, table_size)) +function CachedMTable(basis::AbstractBasis{T,I}; table_size) where {T,I} + return CachedMTable(basis, zeros(I, table_size)) end -CachedMTable(basis::AbstractBasis, mt::AbstractMatrix{<:Integer}) = - CachedMTable{false}(basis, mt) - -function CachedMTable{Tw}( +function CachedMTable( basis::AbstractBasis{T,I}, mt::AbstractMatrix{<:Integer}, -) where {Tw,T,I} - return CachedMTable{T,I,typeof(basis),typeof(mt),Tw}(basis, mt) +) where {T,I} + star_of = _star_of(basis, max(size(mt)...)) + mtable = MTable(mt, star_of) + return CachedMTable(basis, mtable, Threads.SpinLock()) end basis(m::CachedMTable) = m.basis +Base.@propagate_inbounds _iscached(cmt::CachedMTable, i, j) = _iscached(cmt.table, i, j) +Base.@propagate_inbounds _get(cmt::CachedMTable, i::Integer) = _get(cmt.table, i) Base.@propagate_inbounds function Base.getindex(cmt::CachedMTable, i::Integer, j::Integer) - cache!(cmt, i, j) - return cmt.table[i, j] + @boundscheck checkbounds(Bool, cmt, abs(i), abs(j)) || + throw(ProductNotDefined(i, j, "out of Mtable bounds")) + @inbounds begin + i = _get(cmt, i) + j = _get(cmt, j) + if !_iscached(cmt, i, j) + cache!(cmt, i, j) + end + return cmt.table[i, j] + end end Base.@propagate_inbounds function cache!(cmt::CachedMTable, i::Integer, j::Integer) - @boundscheck checkbounds(Bool, cmt, i, j) || - throw(ProductNotDefined(i, j, "out of Mtable bounds")) - if !_iscached(cmt, i, j) - b = basis(cmt) - g, h = b[i], b[j] - gh = _product(cmt, g, h) - gh in b || throw(ProductNotDefined(i, j, "$g · $h = $gh")) - cmt.table[i, j] = b[gh] + b = basis(cmt) + g, h = b[i], b[j] + gh = g * h + gh in b || throw(ProductNotDefined(i, j, "$g · $h = $gh")) + lock(cmt.lock) do + cmt.table.table[i, j] = b[gh] end return cmt end From df9b5c96dad43d4abbbfef9a846711c6cd130074 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:19:17 +0100 Subject: [PATCH 04/15] fix: call deepcopy_internal recursively --- src/algebra_elts.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algebra_elts.jl b/src/algebra_elts.jl index 248e31a..e01af51 100644 --- a/src/algebra_elts.jl +++ b/src/algebra_elts.jl @@ -54,5 +54,5 @@ LinearAlgebra.dot(v::AbstractVector, a::AlgebraElement) = LinearAlgebra.dot(a, v Base.copy(a::AlgebraElement) = AlgebraElement(copy(coeffs(a)), parent(a)) function Base.deepcopy_internal(a::AlgebraElement, stackdict::IdDict) haskey(stackdict, a) && return stackdict[a] - return AlgebraElement(deepcopy(coeffs(a)), parent(a)) + return AlgebraElement(Base.deepcopy_internal(coeffs(a), stackdict), parent(a)) end From 7cf0c78fc0d512c21e30ef4f9a1b5fc5bea6764a Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:20:39 +0100 Subject: [PATCH 05/15] StarAlgebras no longer need Tw type parameter --- src/types.jl | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/types.jl b/src/types.jl index 6daff1d..3f52559 100644 --- a/src/types.jl +++ b/src/types.jl @@ -26,24 +26,19 @@ struct StarAlgebra{O,T,M<:MultiplicativeStructure,B<:AbstractBasis{T}} <: end # TrivialMStructure: -StarAlgebra(obj, basis::AbstractBasis) = StarAlgebra{false}(obj, basis) - -function StarAlgebra{Tw}(obj, basis::AbstractBasis) where {Tw} - mstr = TrivialMStructure{Tw}(basis) +function StarAlgebra(obj, basis::AbstractBasis) + mstr = TrivialMStructure(basis) return StarAlgebra(obj, basis, mstr) end # CachedMStructure: -StarAlgebra(obj, basis::AbstractBasis, cache_size::Tuple{<:Integer,Integer}; precompute=false) = - StarAlgebra{false}(obj, basis, cache_size, precompute=precompute) - -function StarAlgebra{Tw}( +function StarAlgebra( obj, basis::AbstractBasis, cache_size::Tuple{<:Integer,Integer}; precompute=false -) where {Tw} - mstr = CachedMTable{Tw}(basis, table_size=cache_size) +) + mstr = CachedMTable(basis, table_size=cache_size) precompute && complete!(mstr) return StarAlgebra(obj, basis, mstr) end @@ -54,7 +49,6 @@ 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 From 32169d76b54a730f845154794dbf9975ec7a2967 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:27:56 +0100 Subject: [PATCH 06/15] use _get for faster star --- src/algebra_elts.jl | 12 +++++++++++- src/mstructures.jl | 5 +++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/algebra_elts.jl b/src/algebra_elts.jl index e01af51..f3fb050 100644 --- a/src/algebra_elts.jl +++ b/src/algebra_elts.jl @@ -30,6 +30,16 @@ supp_ind(a::AlgebraElement{A,T,<:SparseVector}) where {A,T} = (dropzeros!(coeffs(a)); SparseArrays.nonzeroinds(coeffs(a))) supp(a::AlgebraElement) = (b = basis(parent(a)); [b[i] for i in supp_ind(a)]) +function star(A::StarAlgebra, i::Integer) + @assert i > 0 + if i < max(size(A.mstructure)...) + return _get(A.mstructure, -signed(i)) + else + b = basis(A) + return b[star(b[i])] + end +end + function star(X::AlgebraElement) A = parent(X) b = basis(A) @@ -37,7 +47,7 @@ function star(X::AlgebraElement) idcs = similar(supp_X) vals = similar(idcs, eltype(X)) for (i, idx) in enumerate(supp_X) - idcs[i] = b[star(b[idx])] + idcs[i] = star(parent(X), idx) vals[i] = X[idx] end return AlgebraElement(sparsevec(idcs, vals, length(b)), A) diff --git a/src/mstructures.jl b/src/mstructures.jl index e74219a..c8e4532 100644 --- a/src/mstructures.jl +++ b/src/mstructures.jl @@ -24,6 +24,7 @@ TrivialMStructure(basis::AbstractBasis{T,I}) where {T,I} = basis(mstr::TrivialMStructure) = mstr.basis Base.size(mstr::TrivialMStructure) = (l = length(basis(mstr)); (l, l)) +_get(mstr::TrivialMStructure, i) = i ≥ 0 ? i : (b = basis(mstr); b[star(b[-i])]) Base.@propagate_inbounds function Base.getindex( mstr::TrivialMStructure, @@ -31,8 +32,8 @@ Base.@propagate_inbounds function Base.getindex( j::Integer, ) b = basis(mstr) - g = i ≥ 0 ? b[i] : star(b[-i]) - h = j ≥ 0 ? b[j] : star(b[-j]) + i, j = _get(mstr, i), _get(mstr, j) + g, h = b[i], b[j] gh = g * h gh in b || throw(ProductNotDefined(i, j, "$g · $h = $gh")) return basis(mstr)[gh] From 36420217f0237fec5c4c6f192d6235f18c29437a Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:30:42 +0100 Subject: [PATCH 07/15] make zero/one/similar/coercion more consistent --- src/types.jl | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/types.jl b/src/types.jl index 3f52559..27aae8c 100644 --- a/src/types.jl +++ b/src/types.jl @@ -66,21 +66,26 @@ Base.parent(a::AlgebraElement) = a.parent Base.eltype(a::AlgebraElement) = eltype(coeffs(a)) ### constructing elements - -function Base.zero(A::AbstractStarAlgebra, T=Int) +Base.zero(A::AbstractStarAlgebra) = zero(Int, A) +function Base.zero(T::Type, A::AbstractStarAlgebra) if hasbasis(A) I = SparseArrays.indtype(basis(A)) return AlgebraElement(sparsevec(I[], T[], length(basis(A))), A) end throw( - "Algebra without basis; to construct zero use the `AlgebraElement` constructor directly.", + "Algebra without basis; use the `AlgebraElement` constructor directly.", ) end -function Base.one(A::AbstractStarAlgebra, T=Int) - hasbasis(A) && return A(one(object(A)), T) +Base.one(A::AbstractStarAlgebra) = one(Int, A) +function Base.one(T::Type, A::AbstractStarAlgebra) + if hasbasis(A) + b = basis(A) + i = b[one(object(A))] + return AlgebraElement(sparsevec([i], [one(T)], length(b)), A) + end throw( - "Algebra without basis; to construct one use the `AlgebraElement` constructor directly.", + "Algebra without basis; use the `AlgebraElement` constructor directly.", ) end @@ -95,27 +100,28 @@ function Base.isone(a::AlgebraElement) isone(a[k]) || return false return isone(b[k]) end -@eval begin - function (A::AbstractStarAlgebra{O,T})(elt::T, S=Int) where {O,T} - if hasbasis(A) - b = basis(A) - i = b[elt] - return AlgebraElement(sparsevec([i], [one(S)], length(b)), A) - else - throw("Algebra without basis: cannot coerce $elt.") - end + +function (A::AbstractStarAlgebra{O,T})(elt::T) where {O,T} + if hasbasis(A) + b = basis(A) + i = b[elt] + return AlgebraElement(sparsevec([i], [1], length(b)), A) + else + throw("Algebra without basis: cannot coerce $elt.") end +end - function (A::AbstractStarAlgebra)(x::Number) - g = one(object(A)) - res = A(g, typeof(x)) - res[g] *= x - return res +function (A::AbstractStarAlgebra)(x::Number) + if hasbasis(A) + b = basis(A) + i = b[one(object(A))] + return AlgebraElement(sparsevec([i], [x], length(b)), A) + else + throw("Algebra without basis: cannot coerce $elt.") end end -Base.similar(X::AlgebraElement, ::Type{T}=eltype(X)) where {T} = - AlgebraElement(similar(coeffs(X), T), parent(X)) +Base.similar(X::AlgebraElement, T=eltype(X)) = AlgebraElement(similar(coeffs(X), T), parent(X)) function AlgebraElement{T}(X::AlgebraElement) where {T} v = coeffs(X) From ac1ab35eab07caad99237ef4aa33d77df4dc9cfd Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:31:30 +0100 Subject: [PATCH 08/15] fix: error in isone --- src/types.jl | 3 ++- test/constructors.jl | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types.jl b/src/types.jl index 27aae8c..0a926ad 100644 --- a/src/types.jl +++ b/src/types.jl @@ -98,7 +98,8 @@ function Base.isone(a::AlgebraElement) k = findfirst(!iszero, coeffs(a)) k === nothing && return false isone(a[k]) || return false - return isone(b[k]) + isone(b[k]) || return false + return isnothing(findnext(!iszero, coeffs(a), k + 1)) end function (A::AbstractStarAlgebra{O,T})(elt::T) where {O,T} diff --git a/test/constructors.jl b/test/constructors.jl index edc9a50..0f5eb96 100644 --- a/test/constructors.jl +++ b/test/constructors.jl @@ -33,6 +33,7 @@ @test sprint(show, zero(RG)) == "0·(id)" @test sprint(show, one(RG)) == "1·(id)" @test isone(one(a)) + @test !isone(x) @test iszero(zero(a)) @test sprint(show, a) == "1·b·c" @test sprint(show, -a) == "-1·b·c" From bcdf5792b3b13bc50e61fdb1243b027be2a5156f Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:32:05 +0100 Subject: [PATCH 09/15] removed unused variables --- src/show.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/show.jl b/src/show.jl index f22be43..1ae427e 100644 --- a/src/show.jl +++ b/src/show.jl @@ -26,7 +26,6 @@ function Base.show(io::IO, a::AlgebraElement) print(io, zero(T)) end elseif hasbasis(A) - elts = String[] nzeros = findall(!iszero, coeffs(a)) for (counter, idx) in enumerate(nzeros) c, elt = coeffs(a)[idx], basis(A)[idx] @@ -48,9 +47,7 @@ function Base.show(io::IO, a::AlgebraElement) end function Base.show(io::IO, ::MIME"text/plain", mstr::TrivialMStructure) - Tw = _istwisted(mstr) l = length(basis(mstr)) - Tw && print(io, "twisted ") print(io, "TrivialMStructure over basis with $l elements") return end From ccd627c597541c507faf065bcbff3b233c1bbb01 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:39:50 +0100 Subject: [PATCH 10/15] update mtables tests to reflect removal of twisted --- test/mtables.jl | 134 +++++++++++++++++++++--------------------------- 1 file changed, 58 insertions(+), 76 deletions(-) diff --git a/test/mtables.jl b/test/mtables.jl index 21378ca..e7b2175 100644 --- a/test/mtables.jl +++ b/test/mtables.jl @@ -1,32 +1,33 @@ @testset "TrivialMStructure" begin b = StarAlgebras.Basis{UInt8}(words([:a, :b, :c], radius=4)) - k = findfirst(w -> length(w) == 3, b) - 1 - mstr = StarAlgebras.TrivialMStructure{false}(b) + mstr = StarAlgebras.TrivialMStructure(b) @test mstr[1, 1] == 1 @test mstr[1, 2] == 2 + @test mstr[-1, 2] == 2 @test mstr[2, 1] == 2 + @test mstr[-2, 1] == 3 @test mstr[3, 1] == 3 + @test mstr[-3, 1] == 2 idx = b[b[2]*b[3]] # == 8 @test mstr[2, 3] == idx idx = b[b[3]*b[2]] @test mstr[3, 2] == idx + @test mstr[-2, 3] == b[star(b[2])*b[3]] + @test mstr[-3, 2] == b[star(b[3])*b[2]] - tmstr = StarAlgebras.TrivialMStructure{true}(b) - @test tmstr[1, 2] == 2 - @test tmstr[2, 3] == b[star(b[2])*b[3]] - @test tmstr[3, 2] == b[star(b[3])*b[2]] - - @test sprint(show, MIME"text/plain"(), tmstr) == - "twisted TrivialMStructure over basis with $(length(basis(tmstr))) elements" + @test sprint(show, MIME"text/plain"(), mstr) == + "TrivialMStructure over basis with $(length(basis(mstr))) elements" - @test_throws StarAlgebras.ProductNotDefined mstr[k+1, k] + k = findfirst(w -> length(w) == 3, b) + @test_throws StarAlgebras.ProductNotDefined mstr[k, k-1] + @test_throws StarAlgebras.ProductNotDefined mstr[k-1, k] try - w = mstr[k+1, k] + w = mstr[k, k-1] catch ex @test ex isa StarAlgebras.ProductNotDefined @test sprint(Base.showerror, ex) == @@ -37,79 +38,60 @@ end @testset "MTable" begin b = StarAlgebras.Basis{UInt16}(words([:a, :b, :c, :d], radius=4)) k = findfirst(w -> length(w) == 3, b) - 1 - mstr = StarAlgebras.MTable(b, table_size=(k, k)) - @test mstr isa StarAlgebras.MTable{UInt16,false} - - @test all(mstr[i, i] ≠ 1 for i in 2:size(mstr, 1)) - @test all(mstr[1, i] == i for i in 1:size(mstr, 2)) - @test all(mstr[i, 1] == i for i in 1:size(mstr, 1)) - - tmstr = StarAlgebras.MTable{true}(b, table_size=(k, k)) - - @test tmstr isa StarAlgebras.MTable{UInt16,true} - @test all(tmstr[i, i] != 1 for i in 2:size(tmstr, 1)) - @test all(tmstr[1, i] == i for i in 1:size(tmstr, 2)) - @test all(tmstr[i, 1] ≠ i for i in 1:size(tmstr, 1) if b[i] != star(b[i])) + @test mstr isa StarAlgebras.MTable{UInt16} + @test all( + mstr[i, j] == b[b[i]*b[j]] for i in axes(mstr, 1) for j in axes(mstr, 2) + ) + @test all( + mstr[-i, j] == b[star(b[i])*b[j]] for i in axes(mstr, 1) for j in axes(mstr, 2) + ) + @test all( + mstr[i, -j] == b[b[i]*star(b[j])] for i in axes(mstr, 1) for j in axes(mstr, 2) + ) + @test all( + mstr[-i, -j] == b[star(b[i])*star(b[j])] for i in axes(mstr, 1) for j in axes(mstr, 2) + ) end @testset "CachedMTable" begin b = StarAlgebras.Basis{UInt8}(words([:a, :b, :c], radius=4)) k = findfirst(w -> length(w) == 3, b) - 1 - @test StarAlgebras.CachedMTable(b, table_size=(k, k)) isa - StarAlgebras.CachedMTable{Word{Symbol},UInt8,typeof(b),Matrix{UInt8},false} - - @test StarAlgebras.CachedMTable{true}(b, table_size=(k, k)) isa - StarAlgebras.CachedMTable{Word{Symbol},UInt8,typeof(b),Matrix{UInt8},true} - - @test StarAlgebras.CachedMTable(b, spzeros(UInt8, k, k)) isa StarAlgebras.CachedMTable{ - Word{Symbol}, - UInt8, - typeof(b), - SparseMatrixCSC{UInt8,Int64}, - false, - } - - @test StarAlgebras.CachedMTable{true}(b, spzeros(UInt8, k, k)) isa - StarAlgebras.CachedMTable{ - Word{Symbol}, - UInt8, - typeof(b), - SparseMatrixCSC{UInt8,Int64}, - true, - } - - for mstr in [ - StarAlgebras.CachedMTable{false}(b, table_size=(k, k)), - StarAlgebras.CachedMTable{true}(b, spzeros(UInt8, k, k)), - ] - - @test all(iszero, mstr.table) - StarAlgebras.cache!(mstr, 1, 2) - @test mstr.table[1, 2] == 2 - @test mstr.table[1, 1] == 0 - - idx = StarAlgebras._istwisted(mstr) ? b[star(b[2])*b[3]] : b[b[2]*b[3]] - - @test mstr.table[2, 3] == 0 - @test mstr[2, 3] == idx - @test mstr.table[2, 3] == idx - - @test mstr.table[1, 3] == 0 - @test mstr.table[1, 4] == 0 - StarAlgebras.cache!(mstr, [1], [3, 4]) - @test mstr.table[1, 3] == 3 - @test mstr.table[1, 4] == 4 - - @test_throws StarAlgebras.ProductNotDefined mstr[k+1, k] - end + mstr = StarAlgebras.CachedMTable(b, table_size=(k, k)) + @test mstr isa StarAlgebras.CachedMTable{UInt8,Word{Symbol}} + @test mstr.table.table isa Matrix{UInt8} - tmstr = StarAlgebras.CachedMTable{true}(b, table_size=(k, k)) + mstr_sparse = StarAlgebras.CachedMTable(b, spzeros(UInt8, k, k)) + @test issparse(mstr_sparse.table.table) + + mstr = StarAlgebras.CachedMTable(b, table_size=(k, k)) + + @test all(iszero, mstr.table.table) + StarAlgebras.cache!(mstr, 1, 2) + @test mstr.table.table[1, 2] == 2 + @test mstr.table.table[1, 1] == 0 + + idx = b[b[2]*b[3]] + @test mstr.table.table[2, 3] == 0 + @test_throws StarAlgebras.ProductNotDefined mstr.table[2, 3] + @test mstr[2, 3] == idx + @test mstr.table[2, 3] == idx + @test mstr.table.table[2, 3] == idx + + @test mstr.table.table[1, 3] == 0 + @test mstr.table.table[1, 4] == 0 + StarAlgebras.cache!(mstr, [1], [3, 4]) + @test mstr.table[1, 3] == 3 + @test mstr.table[1, 4] == 4 + + @test_throws StarAlgebras.ProductNotDefined mstr[k+1, k] - @test all(iszero, tmstr.table) - @test tmstr[1, 2] == 2 - @test tmstr[2, 3] == b[star(b[2])*b[3]] - @test tmstr[3, 2] == b[star(b[3])*b[2]] + mstr = StarAlgebras.CachedMTable(b, table_size=(k, k)) + @test all(iszero, mstr.table.table) + @test mstr[-1, 2] == 2 + @test mstr[-2, 3] == b[star(b[2])*b[3]] + @test mstr[3, -2] == b[b[3]*star(b[2])] + @test mstr[-3, -2] == b[star(b[3])*star(b[2])] end From a6d60ebca0972cb79c3d33ee42325459a7fcf5f6 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:40:58 +0100 Subject: [PATCH 11/15] fix tests for cached algebra mtable --- test/arithmetic.jl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/arithmetic.jl b/test/arithmetic.jl index 7a9157f..24fe89e 100644 --- a/test/arithmetic.jl +++ b/test/arithmetic.jl @@ -300,14 +300,10 @@ end @test supp(D) == b[1:k] - @test_throws StarAlgebras.ProductNotDefined StarAlgebras._check( - RG.mstructure, - ) + @test_throws StarAlgebras.ProductNotDefined all(!iszero, RG.mstructure.table) @test D * D isa AlgebraElement - @test StarAlgebras._check(RG.mstructure) - @test all(!iszero, RG.mstructure.table) RG = StarAlgebra(Word(A, Int[]), b, (k, k), precompute=true) From 7557ec68f32dc94a167eb4cc6174154b6e24d0cb Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 02:39:17 +0100 Subject: [PATCH 12/15] alias star with Base.adjoint This makes writing sums of hermition squares less painful --- src/algebra_elts.jl | 2 + test/sum_of_squares.jl | 198 ++++++++++++++++++++--------------------- 2 files changed, 100 insertions(+), 100 deletions(-) diff --git a/src/algebra_elts.jl b/src/algebra_elts.jl index f3fb050..467b470 100644 --- a/src/algebra_elts.jl +++ b/src/algebra_elts.jl @@ -53,6 +53,8 @@ function star(X::AlgebraElement) return AlgebraElement(sparsevec(idcs, vals, length(b)), A) end +Base.adjoint(a::AlgebraElement) = star(a) + LinearAlgebra.norm(a::AlgebraElement, p::Real) = LinearAlgebra.norm(coeffs(a), p) aug(a::AlgebraElement) = sum(coeffs(a)) diff --git a/test/sum_of_squares.jl b/test/sum_of_squares.jl index 3512a6d..80ef114 100644 --- a/test/sum_of_squares.jl +++ b/test/sum_of_squares.jl @@ -1,104 +1,102 @@ using Groups @testset "sum of squares in FreeGroup *-algebra" begin - StarAlgebras.star(g::Groups.GroupElement) = inv(g) - F = Groups.FreeGroup(4) - S = [Groups.gens(F); inv.(Groups.gens(F))] - - ID = one(F) - RADIUS = 3 - @time E_R, sizes = Groups.wlmetric_ball(S, ID, radius=2 * RADIUS) - @test sizes == [9, 65, 457, 3201, 22409, 156865] - - b = StarAlgebras.Basis{UInt32}(E_R) - - tmstr = StarAlgebras.MTable{true}(b, table_size=(sizes[RADIUS], sizes[RADIUS])) - - RG = StarAlgebra(F, b, tmstr) - - g, h, k, l = S[1:4] - - length(b) - - G = (one(RG) - RG(g)) - @test G^2 == StarAlgebras.mul!(zero(G), G, G) == 2one(RG) - RG(g) - star(RG(g)) - @test star(G * G) == G * G - - @testset "Sums of hermitian squares" begin - 𝕀 = one(RG) - - G = (𝕀 - RG(g)) - H = (𝕀 - RG(h)) - K = (𝕀 - RG(k)) - L = (𝕀 - RG(l)) - GH = (𝕀 - RG(g * h)) - KL = (𝕀 - RG(k * l)) - - X = (2𝕀 - star(RG(g)) - RG(h)) - Y = (2𝕀 - star(RG(g * h)) - RG(k)) - - - @test -(2𝕀 - RG(g * h) - star(RG(g * h))) + 2G^2 + 2H^2 == X^2 - @test (2𝕀 - RG(g * h) - star(RG(g * h))) == GH^2 - @test -(2𝕀 - RG(g * h * k) - star(RG(g * h * k))) + 2GH^2 + 2K^2 == Y^2 - @test -(2𝕀 - RG(g * h * k) - star(RG(g * h * k))) + - 2(GH^2 - 2G^2 - 2H^2) + - 4G^2 + - 4H^2 + - 2K^2 == Y^2 - - @test GH^2 - 2G^2 - 2H^2 == -X^2 - @test -(2𝕀 - RG(g * h * k) - star(RG(g * h * k))) + 4G^2 + 4H^2 + 2K^2 == 2X^2 + Y^2 - - @test GH^2 == 2G^2 + 2H^2 - (2𝕀 - star(RG(g)) - RG(h))^2 - @test KL^2 == 2K^2 + 2L^2 - (2𝕀 - star(RG(k)) - RG(l))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + 2 * GH^2 + 2 * KL^2 == - (2𝕀 - star(RG(g * h)) - RG(k * l))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + - 2(2G^2 + 2H^2 - (2𝕀 - star(RG(g)) - RG(h))^2) + - 2(2K^2 + 2L^2 - (2𝕀 - star(RG(k)) - RG(l))^2) == - (2𝕀 - star(RG(g * h)) - RG(k * l))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + - 2(2G^2 + 2H^2) + - 2(2K^2 + 2L^2) == - (2𝕀 - star(RG(g * h)) - RG(k * l))^2 + - 2(2𝕀 - star(RG(g)) - RG(h))^2 + - 2(2𝕀 - star(RG(k)) - RG(l))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + - 2(2𝕀 - star(RG(g * h * k)) - RG(g * h * k)) + - 2L^2 == (2𝕀 - star(RG(g * h * k)) - RG(l))^2 - - @test 2𝕀 - star(RG(g * h * k)) - RG(g * h * k) == - 2GH^2 + 2K^2 - (2𝕀 - star(RG(g * h)) - RG(k))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + - 2(2GH^2 + 2K^2 - (2𝕀 - star(RG(g * h)) - RG(k))^2) + - 2L^2 == (2𝕀 - star(RG(g * h * k)) - RG(l))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + 2(2GH^2 + 2K^2) + 2L^2 == - (2𝕀 - star(RG(g * h * k)) - RG(l))^2 + 2(2𝕀 - star(RG(g * h)) - RG(k))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + - 8G^2 + - 8H^2 + - 4K^2 + - 2L^2 == - (2𝕀 - star(RG(g * h * k)) - RG(l))^2 + - 2(2𝕀 - star(RG(g * h)) - RG(k))^2 + - 4(2𝕀 - star(RG(g)) - RG(h))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + 2GH^2 + 2KL^2 == - (2𝕀 - star(RG(g * h)) - RG(k * l))^2 - - @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + - 2(2G^2 + 2H^2) + - 2(2K^2 + 2L^2) == - (2𝕀 - star(RG(g * h)) - RG(k * l))^2 + - 2(2𝕀 - star(RG(k)) - RG(l))^2 + - 2(2𝕀 - star(RG(g)) - RG(h))^2 - end + StarAlgebras.star(g::Groups.GroupElement) = inv(g) + F = Groups.FreeGroup(4) + S = [Groups.gens(F); inv.(Groups.gens(F))] + + ID = one(F) + RADIUS = 3 + @time E_R, sizes = Groups.wlmetric_ball(S, ID, radius=2 * RADIUS) + @test sizes == [9, 65, 457, 3201, 22409, 156865] + + b = StarAlgebras.Basis{UInt32}(E_R) + + mstr = StarAlgebras.MTable(b, table_size=(sizes[RADIUS], sizes[RADIUS])) + + RG = StarAlgebra(F, b, mstr) + + g, h, k, l = S[1:4] + + G = (one(RG) - RG(g)) + @test G' == one(RG) - RG(inv(g)) + @test G' * G == StarAlgebras.mul!(zero(G), G', G) == 2one(RG) - RG(g) - RG(g)' + @test star(G * G) == G' * G' + + @testset "Sums of hermitian squares" begin + 𝕀 = one(RG) + + G = (𝕀 - RG(g)) + H = (𝕀 - RG(h)) + K = (𝕀 - RG(k)) + L = (𝕀 - RG(l)) + GH = (𝕀 - RG(g * h)) + KL = (𝕀 - RG(k * l)) + + X = (2𝕀 - star(RG(g)) - RG(h)) + Y = (2𝕀 - star(RG(g * h)) - RG(k)) + + @test -(2𝕀 - RG(g * h) - RG(g * h)') + 2G' * G + 2H' * H == X' * X + @test (2𝕀 - RG(g * h) - RG(g * h)') == GH' * GH + @test -(2𝕀 - RG(g * h * k) - RG(g * h * k)') + 2GH' * GH + 2K' * K == Y' * Y + @test -(2𝕀 - RG(g * h * k) - RG(g * h * k)') + + 2(GH' * GH - 2G' * G - 2H' * H) + + 4G' * G + + 4H' * H + + 2K' * K == Y' * Y + + @test GH' * GH - 2G' * G - 2H' * H == -X' * X + @test -(2𝕀 - RG(g * h * k) - RG(g * h * k)') + 4G' * G + 4H' * H + 2K' * K == 2X' * X + Y' * Y + + @test GH' * GH == 2G' * G + 2H' * H - (2𝕀 - RG(g)' - RG(h))' * (2𝕀 - RG(g)' - RG(h)) + @test KL' * KL == 2K' * K + 2L' * L - (2𝕀 - RG(k)' - RG(l))' * (2𝕀 - RG(k)' - RG(l)) + + @test -(2𝕀 - RG(g * h * k * l)' - RG(g * h * k * l)) + 2 * GH' * GH + 2 * KL' * KL == + (2𝕀 - RG(g * h)' - RG(k * l))' * (2𝕀 - RG(g * h)' - RG(k * l)) + + @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + + 2(2G' * G + 2H' * H - (2𝕀 - RG(g)' - RG(h))' * (2𝕀 - RG(g)' - RG(h))) + + 2(2K' * K + 2L' * L - (2𝕀 - RG(k)' - RG(l))' * (2𝕀 - RG(k)' - RG(l))) == + (2𝕀 - RG(g * h)' - RG(k * l))' * (2𝕀 - RG(g * h)' - RG(k * l)) + + @test -(2𝕀 - star(RG(g * h * k * l)) - RG(g * h * k * l)) + + 2(2G' * G + 2H' * H) + + 2(2K' * K + 2L' * L) == + (2𝕀 - RG(g * h)' - RG(k * l))' * (2𝕀 - RG(g * h)' - RG(k * l)) + + 2(2𝕀 - RG(g)' - RG(h))' * (2𝕀 - RG(g)' - RG(h)) + + 2(2𝕀 - RG(k)' - RG(l))' * (2𝕀 - RG(k)' - RG(l)) + + @test -(2𝕀 - RG(g * h * k * l)' - RG(g * h * k * l)) + + 2(2𝕀 - RG(g * h * k)' - RG(g * h * k)) + 2L' * L == + (2𝕀 - RG(g * h * k)' - RG(l))' * (2𝕀 - RG(g * h * k)' - RG(l)) + + @test 2𝕀 - RG(g * h * k)' - RG(g * h * k) == + 2GH' * GH + 2K' * K - (2𝕀 - star(RG(g * h)) - RG(k))' * (2𝕀 - star(RG(g * h)) - RG(k)) + + @test -(2𝕀 - RG(g * h * k * l)' - RG(g * h * k * l)) + + 2( + 2GH' * GH + 2K' * K - (2𝕀 - RG(g * h)' - RG(k))' * (2𝕀 - RG(g * h)' - RG(k)) + ) + 2L' * L == + (2𝕀 - RG(g * h * k)' - RG(l))' * (2𝕀 - RG(g * h * k)' - RG(l)) + + @test -(2𝕀 - RG(g * h * k * l)' - RG(g * h * k * l)) + 2(2GH' * GH + 2K' * K) + 2L' * L == + (2𝕀 - RG(g * h * k)' - RG(l))' * (2𝕀 - RG(g * h * k)' - RG(l)) + + 2(2𝕀 - RG(g * h)' - RG(k))' * (2𝕀 - RG(g * h)' - RG(k)) + + @test -(2𝕀 - RG(g * h * k * l)' - RG(g * h * k * l)) + + 8G' * G + 8H' * H + 4K' * K + 2L' * L == + (2𝕀 - RG(g * h * k)' - RG(l))' * (2𝕀 - RG(g * h * k)' - RG(l)) + + 2(2𝕀 - RG(g * h)' - RG(k))' * (2𝕀 - RG(g * h)' - RG(k)) + + 4(2𝕀 - RG(g)' - RG(h))' * (2𝕀 - RG(g)' - RG(h)) + + @test -(2𝕀 - RG(g * h * k * l)' - RG(g * h * k * l)) + 2GH' * GH + 2KL' * KL == + (2𝕀 - RG(g * h)' - RG(k * l))' * (2𝕀 - RG(g * h)' - RG(k * l)) + + @test -(2𝕀 - RG(g * h * k * l)' - RG(g * h * k * l)) + + 2(2G' * G + 2H' * H) + + 2(2K' * K + 2L' * L) == + (2𝕀 - RG(g * h)' - RG(k * l))' * (2𝕀 - RG(g * h)' - RG(k * l)) + + 2(2𝕀 - RG(k)' - RG(l))' * (2𝕀 - RG(k)' - RG(l)) + + 2(2𝕀 - RG(g)' - RG(h))' * (2𝕀 - RG(g)' - RG(h)) + end end From 2d7707608764d0dfbf88dc782b8f0ff4fb8eb738 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 03:03:08 +0100 Subject: [PATCH 13/15] remove mentions of twisted from README --- README.md | 72 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index e3ed008..74ed129 100644 --- a/README.md +++ b/README.md @@ -15,19 +15,21 @@ julia> using StarAlgebras julia> using PermutationGroups julia> G = PermGroup(perm"(1,2)", perm"(1,2,3)") -Full symmetric group over 3 elements +Permutation group on 2 generators generated by + (1,2) + (1,2,3) julia> b = StarAlgebras.Basis{UInt8}(collect(G)) -6-element StarAlgebras.Basis{Permutation{...}, UInt8, Vector{...}}: +6-element StarAlgebras.Basis{Permutation{Int64, …}, UInt8, Vector{Permutation{Int64, …}}}: () + (2,3) (1,2) (1,3,2) - (2,3) - (1,2,3) (1,3) + (1,2,3) - julia> RG = StarAlgebra(G, b) - *-algebra of Permutation group on 2 generators of order 6 +julia> RG = StarAlgebra(G, b) +*-algebra of Permutation group on 2 generators of order 6 ``` @@ -66,6 +68,9 @@ julia> StarAlgebras.coeffs(f) julia> StarAlgebras.star(p::PermutationGroups.AbstractPerm) = inv(p); star(f) # the star involution 1·() -1·(2,3) +3·(1,2) +3·(1,3,2) -3·(1,3) -1·(1,2,3) +julia> f' # the same +1·() -1·(2,3) +3·(1,2) +3·(1,3,2) -3·(1,3) -1·(1,2,3) + julia> g = rand(G); g (1,2,3) @@ -132,6 +137,24 @@ Test Passed ``` +This package originated as a tool to compute sum of hermitian squares in `*`-algebras. These consist not of standard `f*f` summands, but rather `star(f)*f`. You may think of semi-definite matrices: their Cholesky decomposition determines `P = Q'·Q`, where `Q'` denotes transpose. Algebra of matrices with transpose is an (the?) example of a `*`-algebra. To compute such sums of squares one may either sprinkle the code with `star`s, or `'` (aka `Base.adjoint` postfix symbol): +```julia +julia> x = RG(G(perm"(1,2,3)")) +1·(1,2,3) + +julia> X = one(RG) - x +1·() -1·(1,2,3) + +julia> X' +1·() -1·(1,3,2) + +julia> X'*X +2·() -1·(1,3,2) -1·(1,2,3) + +julia> @test X'*X == star(X)*X == 2one(X) - x - star(x) +Test Passed + +``` ### More advanced use @@ -194,53 +217,30 @@ Finally, if the group is infinite (or just too large), but we need specific prod ### Even more advanced use (for experts only) -This package originated as a tool to compute sum of (hermitian) squares in `*`-algebras. These consist not of standard `f*f` summands, but rather `star(f)*f`. You may think of semi-definite matrices: their Cholesky decomposition determines `P = Q'·Q`, where `Q'` denotes transpose. Algebra of matrices with transpose is an (the?) example of `*`-algebra. - -To compute such sums of squares one may either sprinkle the code with `star`s, or define +For low-level usage `MultiplicativeStructures` follow the sign convention: ```julia -julia> tcmt = StarAlgebras.CachedMTable{true}(b, table_size=(length(b), length(b))); +julia> mt = StarAlgebras.CachedMTable(b, table_size=(length(b), length(b))); -``` -This multiplicative structure is **twisted** in the sense that `tcmt[i,j]` does not compute the product of `i`-th and `j`-th elements of the basis, but rather the `star` of `i`-th and `j`-th. An example ```julia -julia> k = tcmt[i,j] -0x03 +julia> k = mt[-i,j] +0x06 julia> @test star(b[i])*b[j] == b[k] Test Passed ``` -you should only use it with extreme care, as this "product" is no longer associative! Observe: +Note that this (minus-twisted) "product" is no longer associative! Observe: ```julia julia> @test mt[mt[3, 5], 4] == mt[3, mt[5, 4]] # (b[3]*b[4])*b[5] == b[3]*(b[4]*b[5]) Test Passed -julia> @test tcmt[tcmt[3, 5], 4] == 0x06 # star(star(b[3])*b[5])*b[4] = star(b[5])*b[3]*b[4] -Test Passed - -julia> @test tcmt[3, tcmt[5, 4]] == 0x01 # star(b[3])*star(b[5])*b[4] +julia> @test mt[-signed(mt[-3, 5]), 4] == 0x06 # star(star(b[3])*b[5])*b[4] = star(b[5])*b[3]*b[4] Test Passed -``` -However, writing sums of heritian squares is a breeze: -```julia -julia> tRG = StarAlgebra(G, b, tcmt) -*-Algebra of Full symmetric group over 3 elements - -julia> x = tRG(G(perm"(1,2,3)")) -1·(1,2,3) - -julia> X = one(tRG) - x -1·() -1·(1,2,3) - -julia> @test X^2 == X*X == 2one(tRG) - x - star(x) +julia> @test mt[-3, mt[-5, 4]] == 0x01 # star(b[3])*star(b[5])*b[4] Test Passed - ``` -#### WARNING! - -Before using this mode you should consult the code (and potentially its author :) and understand very precisely what and where is happening! ----- From 3c26c9adec4ec36ecf5f0770f87e156f29b73055 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 03:03:33 +0100 Subject: [PATCH 14/15] increment verion to 0.2 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index dd5f943..90de204 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "StarAlgebras" uuid = "0c0c59c1-dc5f-42e9-9a8b-b5dc384a6cd1" authors = ["Marek Kaluba "] -version = "0.1.8" +version = "0.2.0" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" From 7acd7a8cbacbb1a2352f21fe17e3e062437f2264 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Wed, 1 Mar 2023 03:41:24 +0100 Subject: [PATCH 15/15] fix base-less algebras & rise coverage --- src/mtables.jl | 2 +- src/types.jl | 8 ++++---- test/constructors.jl | 12 ++++++++++++ test/mtables.jl | 12 ++++++++++++ 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/mtables.jl b/src/mtables.jl index c823803..9410dd6 100644 --- a/src/mtables.jl +++ b/src/mtables.jl @@ -47,7 +47,7 @@ function complete!(table::AbstractMatrix, basis::AbstractBasis, lck=Threads.Spin for i in axes(table, 1) xy = basis[i] * y lock(lck) do - table[i, j] = xy + table[i, j] = basis[xy] end end end diff --git a/src/types.jl b/src/types.jl index 0a926ad..1fc0039 100644 --- a/src/types.jl +++ b/src/types.jl @@ -17,9 +17,9 @@ struct StarAlgebra{O,T,M<:MultiplicativeStructure,B<:AbstractBasis{T}} <: function StarAlgebra(obj, mstr::MultiplicativeStructure) O = typeof(obj) - T = Symbol + T = eltype(obj) M = typeof(mstr) - B = Basis{T,Int} + B = Basis{T,eltype(mstr)} return new{O,T,M,B}(obj, mstr) end @@ -108,7 +108,7 @@ function (A::AbstractStarAlgebra{O,T})(elt::T) where {O,T} i = b[elt] return AlgebraElement(sparsevec([i], [1], length(b)), A) else - throw("Algebra without basis: cannot coerce $elt.") + throw("Algebra without basis: cannot coerce $elt") end end @@ -118,7 +118,7 @@ function (A::AbstractStarAlgebra)(x::Number) i = b[one(object(A))] return AlgebraElement(sparsevec([i], [x], length(b)), A) else - throw("Algebra without basis: cannot coerce $elt.") + throw("Algebra without basis: cannot coerce $x") end end diff --git a/test/constructors.jl b/test/constructors.jl index 0f5eb96..ed019ee 100644 --- a/test/constructors.jl +++ b/test/constructors.jl @@ -86,4 +86,16 @@ @test deepcopy(a) !== a @test coeffs(deepcopy(a)) !== coeffs(a) @test parent(deepcopy(a)) === parent(a) + + @testset "without basis" begin + O = one(first(b)) + RG2 = StarAlgebra(O, RG.mstructure) + @test_throws String zero(RG2) + @test_throws String one(RG2) + @test_throws String RG2(one(O)) + @test_throws String RG2(-5) + + @test sprint(show, AlgebraElement(rand(-2:2, 6), RG2)) isa String + @test sprint(show, AlgebraElement(zeros(Int, 6), RG2)) isa String + end end diff --git a/test/mtables.jl b/test/mtables.jl index e7b2175..97cc111 100644 --- a/test/mtables.jl +++ b/test/mtables.jl @@ -40,6 +40,8 @@ end k = findfirst(w -> length(w) == 3, b) - 1 mstr = StarAlgebras.MTable(b, table_size=(k, k)) + @test_throws String StarAlgebras.basis(mstr) + @test mstr isa StarAlgebras.MTable{UInt16} @test all( mstr[i, j] == b[b[i]*b[j]] for i in axes(mstr, 1) for j in axes(mstr, 2) @@ -63,9 +65,19 @@ end @test mstr isa StarAlgebras.CachedMTable{UInt8,Word{Symbol}} @test mstr.table.table isa Matrix{UInt8} + @test_throws StarAlgebras.ProductNotDefined StarAlgebras._check(mstr.table.table, StarAlgebras.basis(mstr)) + + StarAlgebras.complete!(mstr) + @test all(!iszero, mstr.table) + mstr_sparse = StarAlgebras.CachedMTable(b, spzeros(UInt8, k, k)) @test issparse(mstr_sparse.table.table) + StarAlgebras.complete!(mstr_sparse.table.table, basis(mstr)) + @test all(!iszero, mstr.table.table) + + @test mstr == mstr_sparse + mstr = StarAlgebras.CachedMTable(b, table_size=(k, k)) @test all(iszero, mstr.table.table)