From a42800eb4e5a5114a04f42204f3f8644c371da3c Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Thu, 7 Nov 2024 12:16:04 +0100 Subject: [PATCH 1/5] implement SubBasis and SubMStructure --- src/bases_fixed.jl | 82 +++++++++++++++++++++++++++++++++------- test/monoid_algebra.jl | 2 +- test/perm_grp_algebra.jl | 28 ++++++++++++++ 3 files changed, 97 insertions(+), 15 deletions(-) diff --git a/src/bases_fixed.jl b/src/bases_fixed.jl index ce302b7..03ab5f2 100644 --- a/src/bases_fixed.jl +++ b/src/bases_fixed.jl @@ -1,6 +1,33 @@ +abstract type FiniteSupportBasis{T,I} <: ExplicitBasis{T,I} end + +""" + supp(fb::FiniteSupportBasis) +Return the supporting elements of `fb` as an indexable vector +""" +function supp end + +Base.IteratorSize(::Type{<:FiniteSupportBasis}) = Base.HasLength() +Base.IteratorEltype(::Type{<:FiniteSupportBasis{T}}) where {T} = T +Base.length(b::FiniteSupportBasis) = length(supp(b)) + +Base.iterate(b::FiniteSupportBasis) = iterate(supp(b)) +Base.iterate(b::FiniteSupportBasis, state) = iterate(supp(b), state) +# function Base.IndexStyle(::Type{<:FiniteSupportBasis{T,I,V}}) where {T,I,V} +# return Base.IndexStyle(V) +# end + +# To break ambiguity +# ?? +Base.@propagate_inbounds function Base.getindex( + b::FiniteSupportBasis, + i::Integer, +) + return supp(b)[i] +end + mutable struct FixedBasis{T,I,V<:AbstractVector{T},M<:MTable{T,I}} <: - ExplicitBasis{T,I} - elts::V + FiniteSupportBasis{T,I} + supporting_elts::V table::M end @@ -21,21 +48,48 @@ function FixedBasis( return FixedBasis(elts, MTable(elts, mstr, dims)) end +supp(fb::FiniteSupportBasis) = fb.supporting_elts mstructure(fb::FixedBasis) = fb.table - Base.in(x, b::FixedBasis) = haskey(mstructure(b), x) Base.getindex(b::FixedBasis{T}, x::T) where {T} = mstructure(b)[x] -Base.getindex(b::FixedBasis, i::Integer) = mstructure(b)[i] -Base.IteratorSize(::Type{<:FixedBasis}) = Base.HasLength() -Base.length(b::FixedBasis) = length(b.elts) +struct SubBasis{T,I,V,B<:AbstractBasis{T,I}} <: FiniteSupportBasis{T,I} + supporting_elts::V + parent_basis::B +end -Base.iterate(b::FixedBasis) = iterate(b.elts) -Base.iterate(b::FixedBasis, state) = iterate(b.elts, state) -Base.IndexStyle(::Type{<:FixedBasis{T,I,V}}) where {T,I,V} = Base.IndexStyle(V) +supp(sb::SubBasis) = sb.supporting_elts +Base.parent(sub::SubBasis) = sub.parent_basis -# To break ambiguity -Base.@propagate_inbounds Base.getindex( - b::FixedBasis{T,I}, - i::I, -) where {T,I<:Integer} = b.elts[i] +Base.in(x, b::SubBasis) = x in supp(b) +function Base.getindex(b::SubBasis{T,I}, x::T) where {T,I<:Integer} + k = findfirst(==(x), supp(b)) + isnothing(k) && throw("x=$x is not supported on SubBasis") + @info T I + return convert(I, k) +end + +function Base.getindex(b::SubBasis{T,T}, x::T) where {T} + x in supp(b) && return x + throw("x=$x is not supported on SubBasis") +end + +struct SubMStructure{SB<:SubBasis,MS} <: MultiplicativeStructure + basis::SB + mstructure::MS +end + +function mstructure(b::SubBasis) + pb = b.parent_basis + return SubMStructure(b, mstructure(pb)) +end + +function (mstr::SubMStructure)(x::T, y::T) where {T} + b = mstr.basis + xy = mstr.mstructure(b[x], b[y]) + return xy +end + +# this is used for key-lookup in mstructures.jl +# MA.operate!(op::UnsafeAddMul, …) +_key(mstr::SubMStructure, k) = findfirst(==(k), supp(mstr.basis)) diff --git a/test/monoid_algebra.jl b/test/monoid_algebra.jl index 8be47ca..402f6b3 100644 --- a/test/monoid_algebra.jl +++ b/test/monoid_algebra.jl @@ -7,7 +7,7 @@ # no caching fB = SA.FixedBasis(basis(RG); n = nwords(A★, 0, 8), mt = 0) - @test fB.table.elts === fB.elts + @test fB.table.elts === SA.supp(fB) fRG = StarAlgebra(A★, fB) diff --git a/test/perm_grp_algebra.jl b/test/perm_grp_algebra.jl index 8090e48..2f85b86 100644 --- a/test/perm_grp_algebra.jl +++ b/test/perm_grp_algebra.jl @@ -96,4 +96,32 @@ end @test a ≤ b end + + @testset "FiniteSupportBasis" begin + S1 = unique!(rand(G, 7)) + S = unique!([S1; [a * b for a in S1 for b in S1]]) + subb = SA.SubBasis(S, db) + smstr = SA.mstructure(subb) + @test smstr(1, 2).basis_elements[1] == subb[1] * subb[2] + + sbRG = SA.StarAlgebra(G, subb) + + x = let z = zeros(Int, length(SA.basis(sbRG))) + z[1:length(S1)] .= rand(-1:1, length(S1)) + SA.AlgebraElement(z, sbRG) + end + + y = let z = zeros(Int, length(SA.basis(sbRG))) + z[1:length(S1)] .= rand(-1:1, length(S1)) + SA.AlgebraElement(z, sbRG) + end + + dx = SA.AlgebraElement(SA.coeffs(x, basis(RG)), RG) + dy = SA.AlgebraElement(SA.coeffs(y, basis(RG)), RG) + + @test dx + dy == SA.AlgebraElement(SA.coeffs(x + y, basis(RG)), RG) + + @test dx * dy == SA.AlgebraElement(SA.coeffs(x * y, basis(RG)), RG) + end end + From baf65a20d21ffe87800e00872af9ff502f6a632a Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Thu, 7 Nov 2024 12:22:38 +0100 Subject: [PATCH 2/5] test broken: scalar mul @allocated --- test/monoid_algebra.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/monoid_algebra.jl b/test/monoid_algebra.jl index 402f6b3..d735671 100644 --- a/test/monoid_algebra.jl +++ b/test/monoid_algebra.jl @@ -130,7 +130,7 @@ @test @allocated(MA.operate_to!(d, *, 2, d)) == 0 @test d == 2a - @test @allocated(MA.operate_to!(d, *, 2, a)) == 0 + @test_broken @allocated(MA.operate_to!(d, *, 2, a)) == 0 @test d == 2a MA.operate!(zero, d) From d023e28acb8dcc76848ea6abb372dd98bdd790c1 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Thu, 7 Nov 2024 12:23:18 +0100 Subject: [PATCH 3/5] rm StarAlgebra from test/Project.toml --- test/Project.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Project.toml b/test/Project.toml index cc6317b..aa75afe 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -6,7 +6,6 @@ MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" PermutationGroups = "8bc5a954-2dfc-11e9-10e6-cd969bffa420" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -StarAlgebras = "0c0c59c1-dc5f-42e9-9a8b-b5dc384a6cd1" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] From ad67331a4c92f25adb1e32e30be0101356f7094d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 7 Nov 2024 17:05:00 +0100 Subject: [PATCH 4/5] Add broken tests --- test/perm_grp_algebra.jl | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/test/perm_grp_algebra.jl b/test/perm_grp_algebra.jl index 2f85b86..66217f9 100644 --- a/test/perm_grp_algebra.jl +++ b/test/perm_grp_algebra.jl @@ -1,3 +1,6 @@ +using Test +using PermutationGroups +import StarAlgebras as SA @testset "POC: group algebra" begin G = PermGroup(perm"(1,2,3,4,5,6)", perm"(1,2)") g = Permutation(perm"(1,4,3,6)(2,5)", G) @@ -17,7 +20,7 @@ zcfs = SA.SparseCoefficients([one(G), h], [1, -1]) xzcfs = SA.SparseCoefficients([one(G), g, h, g * h], [1, -1, -1, 1]) - RG = SA.StarAlgebra(G, db) + RG = SA.StarAlgebra(G, db) x = SA.AlgebraElement(xcfs, RG) y = SA.AlgebraElement(ycfs, RG) @@ -116,12 +119,27 @@ SA.AlgebraElement(z, sbRG) end - dx = SA.AlgebraElement(SA.coeffs(x, basis(RG)), RG) - dy = SA.AlgebraElement(SA.coeffs(y, basis(RG)), RG) - - @test dx + dy == SA.AlgebraElement(SA.coeffs(x + y, basis(RG)), RG) - - @test dx * dy == SA.AlgebraElement(SA.coeffs(x * y, basis(RG)), RG) + dx = SA.AlgebraElement(SA.coeffs(x, SA.basis(RG)), RG) + dy = SA.AlgebraElement(SA.coeffs(y, SA.basis(RG)), RG) + + @test dx + dy == SA.AlgebraElement(SA.coeffs(x + y, SA.basis(RG)), RG) + + @test dx * dy == SA.AlgebraElement(SA.coeffs(x * y, SA.basis(RG)), RG) + + a = SA.AlgebraElement([2], SA.StarAlgebra(G, SA.SubBasis([g], db))) + b = SA.AlgebraElement([-3], SA.StarAlgebra(G, SA.SubBasis([h], db))) + # `Base.+` assumes that using the basis of the first argument will suffice + # We should redefine `Base.:+(a::SubBasis, b::SubBasis)` to first + # convert `a` and `b` to their implicit basis equivalent and then + # do `+` and then convert the result back + # `MultivariateBases` defines an `implicit` function. + # Why not having an `explicit` as well ? + # My dream implementation would be + # Base.:+(a::SubBasis, b::SubBasis) = explicit(implicit(a) + implicit(b)) + # so we just need to implement `implicit` and `explicit` 👼 + @test_broken SA.explicit(SA.implicit(a)) == a + @test_broken SA.explicit(SA.implicit(b)) == b + @test_broken a + b == SA.explicit(SA.implicit(a) + SA.implicit(b)) + @test_broken a * b == SA.explicit(SA.implicit(a) * SA.implicit(b)) end end - From f0a91dd4e2c27caeda1f1196a9cf0d85c2116683 Mon Sep 17 00:00:00 2001 From: Marek Kaluba Date: Sun, 1 Dec 2024 23:07:09 +0100 Subject: [PATCH 5/5] store indicies instead of elts But this makes the abstraction useless... --- src/bases_fixed.jl | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/bases_fixed.jl b/src/bases_fixed.jl index 03ab5f2..cefb558 100644 --- a/src/bases_fixed.jl +++ b/src/bases_fixed.jl @@ -16,8 +16,6 @@ Base.iterate(b::FiniteSupportBasis, state) = iterate(supp(b), state) # return Base.IndexStyle(V) # end -# To break ambiguity -# ?? Base.@propagate_inbounds function Base.getindex( b::FiniteSupportBasis, i::Integer, @@ -53,25 +51,22 @@ mstructure(fb::FixedBasis) = fb.table Base.in(x, b::FixedBasis) = haskey(mstructure(b), x) Base.getindex(b::FixedBasis{T}, x::T) where {T} = mstructure(b)[x] -struct SubBasis{T,I,V,B<:AbstractBasis{T,I}} <: FiniteSupportBasis{T,I} - supporting_elts::V +struct SubBasis{T,I,V<:AbstractVector{I},B<:AbstractBasis{T,I}} <: + FiniteSupportBasis{T,I} + supporting_idcs::V parent_basis::B end -supp(sb::SubBasis) = sb.supporting_elts +supp(sb::SubBasis) = sb.supporting_idcs Base.parent(sub::SubBasis) = sub.parent_basis Base.in(x, b::SubBasis) = x in supp(b) function Base.getindex(b::SubBasis{T,I}, x::T) where {T,I<:Integer} - k = findfirst(==(x), supp(b)) - isnothing(k) && throw("x=$x is not supported on SubBasis") - @info T I - return convert(I, k) + return convert(I, parent(b)[supp(b)[x]]) end function Base.getindex(b::SubBasis{T,T}, x::T) where {T} - x in supp(b) && return x - throw("x=$x is not supported on SubBasis") + parent(b)[x] in supp(b) && return x end struct SubMStructure{SB<:SubBasis,MS} <: MultiplicativeStructure