From b0bdc9d8ba69bfbf2693efade48770fbf3cedef7 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 25 Aug 2025 17:13:18 +0200 Subject: [PATCH 01/25] custom `(left/right)oneunit` and `blocksectors` for `SumSpace` of `IsingBimodule` spaces --- src/vectorspaces/multifusionsumspace.jl | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/vectorspaces/multifusionsumspace.jl diff --git a/src/vectorspaces/multifusionsumspace.jl b/src/vectorspaces/multifusionsumspace.jl new file mode 100644 index 0000000..f580662 --- /dev/null +++ b/src/vectorspaces/multifusionsumspace.jl @@ -0,0 +1,39 @@ +# custom methods for SumSpaces + +function Base.oneunit(S::SumSpace{Vect[IsingBimodule]}) + @assert !isempty(S) "Cannot determine type of empty space" + allequal(a.row for a in sectors(S)) && allequal(a.col for a in sectors(S)) || + throw(ArgumentError("sectors of $S are not all equal")) + first(sectors(S)).row == first(sectors(S)).col || throw(ArgumentError("non-diagonal SumSpace $S")) + return SumSpace(oneunit(first(S.spaces))) +end + +function TensorKit.rightoneunit(S::SumSpace{Vect[IsingBimodule]}) + @assert !isempty(S) "Cannot determine type of empty space" + allequal(a.col for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same rightone")) + return SumSpace(TensorKit.rightoneunit(first(S.spaces))) +end + +function TensorKit.leftoneunit(S::SumSpace{Vect[IsingBimodule]}) + @assert !isempty(S) "Cannot determine type of empty space" + allequal(a.row for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same leftone")) + return SumSpace(TensorKit.leftoneunit(first(S.spaces))) +end + +function TensorKit.blocksectors(W::TensorMapSpace{SumSpace{Vect[IsingBimodule]},N₁,N₂}) where {N₁,N₂} + codom = codomain(W) + dom = domain(W) + if N₁ == 0 && N₂ == 0 + return (IsingBimodule(1, 1, 0), IsingBimodule(2, 2, 0)) # should this be a vector? + elseif N₁ == 0 + @assert N₂ != 0 "one of Type IsingBimodule doesn't exist" + return filter!(isone, collect(blocksectors(dom))) + elseif N₂ == 0 + @assert N₁ != 0 "one of Type IsingBimodule doesn't exist" + return filter!(isone, collect(blocksectors(codom))) + elseif N₂ <= N₁ # keep intersection + return filter!(c -> TK.hasblock(codom, c), collect(blocksectors(dom))) + else + return filter!(c -> TK.hasblock(dom, c), collect(blocksectors(codom))) + end +end \ No newline at end of file From e5bb078491def9882654673252077779886774ea Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 25 Aug 2025 17:13:59 +0200 Subject: [PATCH 02/25] start of `IsingBimodule` `SumSpace` tests --- test/vectorspaces/sumspace.jl | 68 ++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index 1f6524d..aec140d 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -103,7 +103,7 @@ end @test !(V ≻ ⊕(V, V)) end -@testset"GradedSpace" begin +@testset "GradedSpace" begin using TensorKit, BlockTensorKit using Test, TestExtras @@ -156,3 +156,69 @@ end @test V ≺ ⊕(V, V) @test !(V ≻ ⊕(V, V)) end + +@testset "MultFusion" begin + using TensorKit, BlockTensorKit + using Test, TestExtras + + using TensorKit: hassector + using BlockTensorKit: ⊕ + + I = IsingBimodule + + C0, C1, D0, D1, M, Mop = I(1, 1, 0), I(1, 1, 1), I(2, 2, 0), I(2, 2, 1), I(1, 2, 0), I(2, 1, 0) + + V1 = Vect[I](C0 => 1, C1 => 1) + V2 = Vect[I](D0 => 1, D1 => 1) + V3 = Vect[I](M => 1) # no Mop + d = dim(V1) + dim(V2) + dim(V3) + V = SumSpace(V1, V2, V3) + + @test isa(V, VectorSpace) + @test isa(V, ElementarySpace) + + @test isa(InnerProductStyle(V), HasInnerProduct) + @test isa(InnerProductStyle(V), EuclideanInnerProduct) + @test isa(V, SumSpace) + + @test !isdual(V) + @test isdual(V') + + @test @constinferred(hash(V)) == hash(deepcopy(V)) + @test @constinferred(dual(V)) == @constinferred(conj(V)) == @constinferred(adjoint(V)) + @test field(V) == ℂ + + @test_throws ArgumentError("one of Type IsingBimodule doesn't exist") oneunit(V) + # TODO: get left/rightoneunit working + + @test @constinferred(sectortype(V)) == sectortype(V1) + @test ((@constinferred sectors(V))...,) == (C1, C0, D1, D0, M) # why does ordering matter? + @test length(sectors(V)) == 5 + @test @constinferred(hassector(V, M)) + @test !@constinferred(hassector(V, Mop)) + @test @constinferred(dim(V)) == + d == + @constinferred(sum(dim(s) for s in sectors(V))) + @test dim(@constinferred(typeof(V)())) == 0 + @test (sectors(typeof(V)())...,) == () + + W = @constinferred SumSpace(Vect[I](M => 1)) + @test @constinferred(oneunit(V)) == W == @constinferred(oneunit(typeof(V))) + + VC = SumSpace(V1, V1) # TODO: finish tests with these + VCM = SumSpace(V1, V3) + VMD = SumSpace(V2, V3) + + @test @constinferred(⊕(V, V)) == SumSpace(vcat(V.spaces, V.spaces)) + @test @constinferred(⊕(V, oneunit(V))) == SumSpace(vcat(V.spaces, oneunit(V1))) + @test @constinferred(⊕(V, V, V, V)) == SumSpace(repeat(V.spaces, 4)) + @test @constinferred(fuse(VC, VC)) ≅ SumSpace(Vect[I](C0 => 8, C1 => 8)) + @test @constinferred(fuse(VC, VC', VC, VC')) ≅ + SumSpace(Vect[I](C0 => 128, C1 => 128)) + @test @constinferred(flip(V)) ≅ SumSpace(flip.(V.spaces)...) + @test flip(V) ≅ V + @test flip(V) ≾ V + @test flip(V) ≿ V + @test V ≺ ⊕(V, V) + @test !(V ≻ ⊕(V, V)) +end \ No newline at end of file From 84b5ef618d116ad1c1cec9366501794c16ed5dbb Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 25 Aug 2025 17:14:07 +0200 Subject: [PATCH 03/25] import `hasblock` --- src/BlockTensorKit.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/BlockTensorKit.jl b/src/BlockTensorKit.jl index bdc4042..fc7e82b 100644 --- a/src/BlockTensorKit.jl +++ b/src/BlockTensorKit.jl @@ -23,7 +23,8 @@ using TensorKit: AdjointTensorMap, adjointtensorindices, compose, - sectorscalartype + sectorscalartype, + hasblock using VectorInterface using TensorOperations using TensorOperations: @@ -52,6 +53,7 @@ import TupleTools as TT # Spaces include("vectorspaces/sumspace.jl") include("vectorspaces/sumspaceindices.jl") +include("vectorspaces/multifusionsumspace.jl") # Tensors include("tensors/abstractblocktensor/abstractblocktensor.jl") From ed522adf8bfc24ef904996652dc5b9e74a5f12b4 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 26 Aug 2025 09:23:43 +0200 Subject: [PATCH 04/25] finish multifusion tests --- test/vectorspaces/sumspace.jl | 44 ++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index aec140d..856fb0f 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -157,7 +157,7 @@ end @test !(V ≻ ⊕(V, V)) end -@testset "MultFusion" begin +@testset "Multifusion" begin using TensorKit, BlockTensorKit using Test, TestExtras @@ -188,11 +188,10 @@ end @test @constinferred(dual(V)) == @constinferred(conj(V)) == @constinferred(adjoint(V)) @test field(V) == ℂ - @test_throws ArgumentError("one of Type IsingBimodule doesn't exist") oneunit(V) - # TODO: get left/rightoneunit working + @test_throws ArgumentError("sectors of $V are not all equal") oneunit(V) @test @constinferred(sectortype(V)) == sectortype(V1) - @test ((@constinferred sectors(V))...,) == (C1, C0, D1, D0, M) # why does ordering matter? + @test ((@constinferred sectors(V))...,) == (C1, C0, D1, D0, M) # ordering matters @test length(sectors(V)) == 5 @test @constinferred(hassector(V, M)) @test !@constinferred(hassector(V, Mop)) @@ -202,15 +201,30 @@ end @test dim(@constinferred(typeof(V)())) == 0 @test (sectors(typeof(V)())...,) == () - W = @constinferred SumSpace(Vect[I](M => 1)) - @test @constinferred(oneunit(V)) == W == @constinferred(oneunit(typeof(V))) - - VC = SumSpace(V1, V1) # TODO: finish tests with these + # (left/right)oneunit tests + WC = @constinferred SumSpace(Vect[I](C0 => 1)) + WD = @constinferred SumSpace(Vect[I](D0 => 1)) + WM = @constinferred SumSpace(V3) + WMop = @constinferred SumSpace(Vect[I](Mop => 1)) + for W in [WC, WD] + @test @constinferred(oneunit(W)) == W == @constinferred(leftoneunit(W)) == @constinferred(rightoneunit(W)) + @test_throws ArgumentError("one of Type IsingBimodule doesn't exist") oneunit(typeof(W)) + end + + @test leftoneunit(WMop) == WD && rightoneunit(WMop) == WC + @test leftoneunit(WM) == WC && rightoneunit(WM) == WD + @test_throws ArgumentError("non-diagonal SumSpace $WM") oneunit(WM) + @test_throws ArgumentError("non-diagonal SumSpace $WMop") oneunit(WMop) + + VC = SumSpace(V1, V1) VCM = SumSpace(V1, V3) VMD = SumSpace(V2, V3) @test @constinferred(⊕(V, V)) == SumSpace(vcat(V.spaces, V.spaces)) - @test @constinferred(⊕(V, oneunit(V))) == SumSpace(vcat(V.spaces, oneunit(V1))) + @test @constinferred(⊕(VC, oneunit(VC))) == SumSpace(vcat(VC.spaces, oneunit(VC))) + @test @constinferred(⊕(VCM, leftoneunit(VCM))) == SumSpace(vcat(VCM.spaces, leftoneunit(VCM))) + @test @constinferred(⊕(VMD, rightoneunit(VMD))) == SumSpace(vcat(VMD.spaces, rightoneunit(VMD))) + @test @constinferred(⊕(V, V, V, V)) == SumSpace(repeat(V.spaces, 4)) @test @constinferred(fuse(VC, VC)) ≅ SumSpace(Vect[I](C0 => 8, C1 => 8)) @test @constinferred(fuse(VC, VC', VC, VC')) ≅ @@ -221,4 +235,16 @@ end @test flip(V) ≿ V @test V ≺ ⊕(V, V) @test !(V ≻ ⊕(V, V)) + + # blocksectors tests + @test @constinferred(blocksectors(one(V) ← one(V))) == [C0, D0] + @test @constinferred(blocksectors(V ← V)) == sort(collect(sectors(V))) # convert set to vector + @test @constinferred(blocksectors(one(V))) == [C0, D0] + for v in [VC, VCM, VMD] + @test @constinferred(blocksectors(v^2)) == blocksectors(v ← v) + end + for v in [WM, WMop] + @test isempty(@constinferred(blocksectors(v^2))) + @test @constinferred(blocksectors(v ← v)) == blocksectors(v) + end end \ No newline at end of file From f033921cc26d2f4f3323f167627e48a1981031f9 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 26 Aug 2025 09:24:33 +0200 Subject: [PATCH 05/25] add `blocksectors` for `ProductSpace` for `IsingBimodule` --- src/vectorspaces/multifusionsumspace.jl | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/vectorspaces/multifusionsumspace.jl b/src/vectorspaces/multifusionsumspace.jl index f580662..93f732b 100644 --- a/src/vectorspaces/multifusionsumspace.jl +++ b/src/vectorspaces/multifusionsumspace.jl @@ -24,7 +24,7 @@ function TensorKit.blocksectors(W::TensorMapSpace{SumSpace{Vect[IsingBimodule]}, codom = codomain(W) dom = domain(W) if N₁ == 0 && N₂ == 0 - return (IsingBimodule(1, 1, 0), IsingBimodule(2, 2, 0)) # should this be a vector? + return [IsingBimodule(1, 1, 0), IsingBimodule(2, 2, 0)] elseif N₁ == 0 @assert N₂ != 0 "one of Type IsingBimodule doesn't exist" return filter!(isone, collect(blocksectors(dom))) @@ -36,4 +36,25 @@ function TensorKit.blocksectors(W::TensorMapSpace{SumSpace{Vect[IsingBimodule]}, else return filter!(c -> TK.hasblock(dom, c), collect(blocksectors(codom))) end +end + +function TensorKit.blocksectors(P::ProductSpace{SumSpace{Vect[IsingBimodule]},N}) where {N} + I = sectortype(P) # IsingBimodule + bs = Vector{I}() + if N == 0 + return [IsingBimodule(1, 1, 0), IsingBimodule(2, 2, 0)] + elseif N == 1 + for s in sectors(P) + push!(bs, first(s)) + end + else + for s in sectors(P) + for c in ⊗(s...) + if !(c in bs) + push!(bs, c) + end + end + end + end + return sort!(bs) end \ No newline at end of file From 36f6413469a2c99538fb6eee523223b9c009867e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 26 Aug 2025 10:01:17 +0200 Subject: [PATCH 06/25] `left/rightoneunit` for `SumSpace` of `GradedSpace` + test --- src/vectorspaces/sumspace.jl | 8 ++++++++ test/vectorspaces/sumspace.jl | 1 + 2 files changed, 9 insertions(+) diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index 21bf105..4b84541 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -152,6 +152,14 @@ end Base.oneunit(S::Type{<:SumSpace}) = SumSpace(oneunit(eltype(S))) +function TensorKit.leftoneunit(S::SumSpace{<:GradedSpace}) + return SumSpace(leftoneunit(first(S))) +end + +function TensorKit.rightoneunit(S::SumSpace{<:GradedSpace}) + return SumSpace(rightoneunit(first(S))) +end + # Promotion and conversion # ------------------------ Base.promote_rule(::Type{S}, ::Type{SumSpace{S}}) where {S <: ElementarySpace} = SumSpace{S} diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index 856fb0f..3ceb7eb 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -143,6 +143,7 @@ end @test @constinferred(axes(V)) == Base.OneTo(d) W = @constinferred SumSpace(U1Space(0 => 1)) @test @constinferred(oneunit(V)) == W == @constinferred(oneunit(typeof(V))) + @test @constinferred(leftoneunit(V)) == W == @constinferred(rightoneunit(V)) @test @constinferred(⊕(V, V)) == SumSpace(vcat(V.spaces, V.spaces)) @test @constinferred(⊕(V, oneunit(V))) == SumSpace(vcat(V.spaces, oneunit(V1))) @test @constinferred(⊕(V, V, V, V)) == SumSpace(repeat(V.spaces, 4)) From 70e0cccfbfa8acf0081f83ec77f3698469b4cf19 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 26 Aug 2025 11:50:08 +0200 Subject: [PATCH 07/25] redefine `left/rightoneunit` for usual `GradedSpace`s --- src/vectorspaces/sumspace.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index 4b84541..0c20f03 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -152,13 +152,9 @@ end Base.oneunit(S::Type{<:SumSpace}) = SumSpace(oneunit(eltype(S))) -function TensorKit.leftoneunit(S::SumSpace{<:GradedSpace}) - return SumSpace(leftoneunit(first(S))) -end +TensorKit.leftoneunit(S::SumSpace{<:GradedSpace}) = SumSpace(leftoneunit(first(S))) -function TensorKit.rightoneunit(S::SumSpace{<:GradedSpace}) - return SumSpace(rightoneunit(first(S))) -end +TensorKit.rightoneunit(S::SumSpace{<:GradedSpace}) = SumSpace(rightoneunit(first(S))) # Promotion and conversion # ------------------------ From 76184b65178861a86612b982cdbc27f747b32b63 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 26 Aug 2025 11:51:11 +0200 Subject: [PATCH 08/25] extra check to `IsingBimodule` `SumSpace`s when empty --- src/vectorspaces/multifusionsumspace.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vectorspaces/multifusionsumspace.jl b/src/vectorspaces/multifusionsumspace.jl index 93f732b..0bd17e6 100644 --- a/src/vectorspaces/multifusionsumspace.jl +++ b/src/vectorspaces/multifusionsumspace.jl @@ -1,7 +1,7 @@ # custom methods for SumSpaces function Base.oneunit(S::SumSpace{Vect[IsingBimodule]}) - @assert !isempty(S) "Cannot determine type of empty space" + @assert !isempty(sectors(S)) "Cannot determine type of empty space" allequal(a.row for a in sectors(S)) && allequal(a.col for a in sectors(S)) || throw(ArgumentError("sectors of $S are not all equal")) first(sectors(S)).row == first(sectors(S)).col || throw(ArgumentError("non-diagonal SumSpace $S")) @@ -9,13 +9,13 @@ function Base.oneunit(S::SumSpace{Vect[IsingBimodule]}) end function TensorKit.rightoneunit(S::SumSpace{Vect[IsingBimodule]}) - @assert !isempty(S) "Cannot determine type of empty space" + @assert !isempty(sectors(S)) "Cannot determine type of empty space" allequal(a.col for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same rightone")) return SumSpace(TensorKit.rightoneunit(first(S.spaces))) end function TensorKit.leftoneunit(S::SumSpace{Vect[IsingBimodule]}) - @assert !isempty(S) "Cannot determine type of empty space" + @assert !isempty(sectors(S)) "Cannot determine type of empty space" allequal(a.row for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same leftone")) return SumSpace(TensorKit.leftoneunit(first(S.spaces))) end From 1f12902c38747837135aadab5afad236cc9811a5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 26 Aug 2025 11:51:48 +0200 Subject: [PATCH 09/25] `left/rightoneunit` tests on empty `SumSpace`s --- test/vectorspaces/sumspace.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index 3ceb7eb..1546d2e 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -144,6 +144,8 @@ end W = @constinferred SumSpace(U1Space(0 => 1)) @test @constinferred(oneunit(V)) == W == @constinferred(oneunit(typeof(V))) @test @constinferred(leftoneunit(V)) == W == @constinferred(rightoneunit(V)) + Vempty = @constinferred(SumSpace(zero(U1Space))) + @test oneunit(Vempty) == leftoneunit(Vempty) == rightoneunit(Vempty) == SumSpace(U1Space(0 => 1)) @test @constinferred(⊕(V, V)) == SumSpace(vcat(V.spaces, V.spaces)) @test @constinferred(⊕(V, oneunit(V))) == SumSpace(vcat(V.spaces, oneunit(V1))) @test @constinferred(⊕(V, V, V, V)) == SumSpace(repeat(V.spaces, 4)) @@ -217,6 +219,11 @@ end @test_throws ArgumentError("non-diagonal SumSpace $WM") oneunit(WM) @test_throws ArgumentError("non-diagonal SumSpace $WMop") oneunit(WMop) + Wempty = SumSpace(Vect[I]()) + for f in (oneunit, leftoneunit, rightoneunit) + @test_throws ArgumentError("Cannot determine type of empty space") f(Wempty) + end + VC = SumSpace(V1, V1) VCM = SumSpace(V1, V3) VMD = SumSpace(V2, V3) From 1e928d33e604b7291fa9b6c48924d96afdc3a364 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 14:34:14 +0100 Subject: [PATCH 10/25] delete specialisations to IsingBimodule --- src/vectorspaces/multifusionsumspace.jl | 60 ------------------------- 1 file changed, 60 deletions(-) delete mode 100644 src/vectorspaces/multifusionsumspace.jl diff --git a/src/vectorspaces/multifusionsumspace.jl b/src/vectorspaces/multifusionsumspace.jl deleted file mode 100644 index 0bd17e6..0000000 --- a/src/vectorspaces/multifusionsumspace.jl +++ /dev/null @@ -1,60 +0,0 @@ -# custom methods for SumSpaces - -function Base.oneunit(S::SumSpace{Vect[IsingBimodule]}) - @assert !isempty(sectors(S)) "Cannot determine type of empty space" - allequal(a.row for a in sectors(S)) && allequal(a.col for a in sectors(S)) || - throw(ArgumentError("sectors of $S are not all equal")) - first(sectors(S)).row == first(sectors(S)).col || throw(ArgumentError("non-diagonal SumSpace $S")) - return SumSpace(oneunit(first(S.spaces))) -end - -function TensorKit.rightoneunit(S::SumSpace{Vect[IsingBimodule]}) - @assert !isempty(sectors(S)) "Cannot determine type of empty space" - allequal(a.col for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same rightone")) - return SumSpace(TensorKit.rightoneunit(first(S.spaces))) -end - -function TensorKit.leftoneunit(S::SumSpace{Vect[IsingBimodule]}) - @assert !isempty(sectors(S)) "Cannot determine type of empty space" - allequal(a.row for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same leftone")) - return SumSpace(TensorKit.leftoneunit(first(S.spaces))) -end - -function TensorKit.blocksectors(W::TensorMapSpace{SumSpace{Vect[IsingBimodule]},N₁,N₂}) where {N₁,N₂} - codom = codomain(W) - dom = domain(W) - if N₁ == 0 && N₂ == 0 - return [IsingBimodule(1, 1, 0), IsingBimodule(2, 2, 0)] - elseif N₁ == 0 - @assert N₂ != 0 "one of Type IsingBimodule doesn't exist" - return filter!(isone, collect(blocksectors(dom))) - elseif N₂ == 0 - @assert N₁ != 0 "one of Type IsingBimodule doesn't exist" - return filter!(isone, collect(blocksectors(codom))) - elseif N₂ <= N₁ # keep intersection - return filter!(c -> TK.hasblock(codom, c), collect(blocksectors(dom))) - else - return filter!(c -> TK.hasblock(dom, c), collect(blocksectors(codom))) - end -end - -function TensorKit.blocksectors(P::ProductSpace{SumSpace{Vect[IsingBimodule]},N}) where {N} - I = sectortype(P) # IsingBimodule - bs = Vector{I}() - if N == 0 - return [IsingBimodule(1, 1, 0), IsingBimodule(2, 2, 0)] - elseif N == 1 - for s in sectors(P) - push!(bs, first(s)) - end - else - for s in sectors(P) - for c in ⊗(s...) - if !(c in bs) - push!(bs, c) - end - end - end - end - return sort!(bs) -end \ No newline at end of file From 92dfef0f39d0042eead42570e8ff4d23fadf9069 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 14:39:37 +0100 Subject: [PATCH 11/25] remove include --- src/BlockTensorKit.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/BlockTensorKit.jl b/src/BlockTensorKit.jl index 07ef4d8..e2bf9fb 100644 --- a/src/BlockTensorKit.jl +++ b/src/BlockTensorKit.jl @@ -40,7 +40,6 @@ import MatrixAlgebraKit as MAK # Spaces include("vectorspaces/sumspace.jl") include("vectorspaces/sumspaceindices.jl") -include("vectorspaces/multifusionsumspace.jl") # Tensors include("tensors/abstractblocktensor/abstractblocktensor.jl") From cc9e53db4274102c562f67eafd3d563e68e61241 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 14:39:55 +0100 Subject: [PATCH 12/25] renaming from TK v0.15 + incoming renamings --- src/tensors/indexmanipulations.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tensors/indexmanipulations.jl b/src/tensors/indexmanipulations.jl index 0b2d2df..85f1ce9 100644 --- a/src/tensors/indexmanipulations.jl +++ b/src/tensors/indexmanipulations.jl @@ -230,38 +230,38 @@ function TK.add_braid!( return TK.add_braid!(tdst, only(tsrc), (p₁, p₂), levels, α, β, backend...) end -Base.@constprop :aggressive function TK.insertleftunit( +Base.@constprop :aggressive function TK.insertleftunitspace( t::AbstractBlockTensorMap, i::Int = numind(t) + 1; kwargs... ) - W = TK.insertleftunit(space(t), i; kwargs...) + W = TK.insertleftunitspace(space(t), i; kwargs...) tdst = similar(t, W) for (I, v) in nonzero_pairs(t) I′ = CartesianIndex(TT.insertafter(I.I, i - 1, (1,))) - tdst[I′] = TK.insertleftunit(v, i; kwargs...) + tdst[I′] = TK.insertleftunitspace(v, i; kwargs...) end return tdst end -Base.@constprop :aggressive function TK.insertrightunit( +Base.@constprop :aggressive function TK.insertrightunitspace( t::AbstractBlockTensorMap, i::Int = numind(t) + 1; kwargs... ) - W = TK.insertrightunit(space(t), i; kwargs...) + W = TK.insertrightunitspace(space(t), i; kwargs...) tdst = similar(t, W) for (I, v) in nonzero_pairs(t) I′ = CartesianIndex(TT.insertafter(I.I, i, (1,))) - tdst[I′] = TK.insertrightunit(v, i; kwargs...) + tdst[I′] = TK.insertrightunitspace(v, i; kwargs...) end return tdst end -Base.@constprop :aggressive function TK.removeunit( +Base.@constprop :aggressive function TK.removeunitspace( t::AbstractBlockTensorMap, i::Int; kwargs... ) - W = TK.removeunit(space(t), i) + W = TK.removeunitspace(space(t), i) tdst = similar(t, W) for (I, v) in nonzero_pairs(t) I′ = CartesianIndex(TT.deleteat(I.I, i)) - tdst[I′] = TK.removeunit(v, i) + tdst[I′] = TK.removeunitspace(v, i) end return tdst end From 05199695205e2dcd8e1db2fcb664c56dc12c5909 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 14:40:10 +0100 Subject: [PATCH 13/25] more renamings --- src/vectorspaces/sumspace.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index 237ec78..2026dae 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -171,9 +171,9 @@ end TensorKit.unitspace(S::Type{<:SumSpace}) = SumSpace(TensorKit.unitspace(eltype(S))) TensorKit.zerospace(::Type{SumSpace{S}}) where {S} = SumSpace{S}() -TensorKit.leftoneunit(S::SumSpace{<:GradedSpace}) = SumSpace(leftoneunit(first(S))) +TensorKit.leftunitspace(S::SumSpace{<:GradedSpace}) = SumSpace(leftunitspace(first(S))) -TensorKit.rightoneunit(S::SumSpace{<:GradedSpace}) = SumSpace(rightoneunit(first(S))) +TensorKit.rightunitspace(S::SumSpace{<:GradedSpace}) = SumSpace(rightunitspace(first(S))) # Promotion and conversion # ------------------------ From 00c069b53b5e9fb2727542fab9c785fdf9a17bb7 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 15:53:58 +0100 Subject: [PATCH 14/25] go back to `insertleft/rightunit` and `removeunit` --- src/tensors/indexmanipulations.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tensors/indexmanipulations.jl b/src/tensors/indexmanipulations.jl index 85f1ce9..0b2d2df 100644 --- a/src/tensors/indexmanipulations.jl +++ b/src/tensors/indexmanipulations.jl @@ -230,38 +230,38 @@ function TK.add_braid!( return TK.add_braid!(tdst, only(tsrc), (p₁, p₂), levels, α, β, backend...) end -Base.@constprop :aggressive function TK.insertleftunitspace( +Base.@constprop :aggressive function TK.insertleftunit( t::AbstractBlockTensorMap, i::Int = numind(t) + 1; kwargs... ) - W = TK.insertleftunitspace(space(t), i; kwargs...) + W = TK.insertleftunit(space(t), i; kwargs...) tdst = similar(t, W) for (I, v) in nonzero_pairs(t) I′ = CartesianIndex(TT.insertafter(I.I, i - 1, (1,))) - tdst[I′] = TK.insertleftunitspace(v, i; kwargs...) + tdst[I′] = TK.insertleftunit(v, i; kwargs...) end return tdst end -Base.@constprop :aggressive function TK.insertrightunitspace( +Base.@constprop :aggressive function TK.insertrightunit( t::AbstractBlockTensorMap, i::Int = numind(t) + 1; kwargs... ) - W = TK.insertrightunitspace(space(t), i; kwargs...) + W = TK.insertrightunit(space(t), i; kwargs...) tdst = similar(t, W) for (I, v) in nonzero_pairs(t) I′ = CartesianIndex(TT.insertafter(I.I, i, (1,))) - tdst[I′] = TK.insertrightunitspace(v, i; kwargs...) + tdst[I′] = TK.insertrightunit(v, i; kwargs...) end return tdst end -Base.@constprop :aggressive function TK.removeunitspace( +Base.@constprop :aggressive function TK.removeunit( t::AbstractBlockTensorMap, i::Int; kwargs... ) - W = TK.removeunitspace(space(t), i) + W = TK.removeunit(space(t), i) tdst = similar(t, W) for (I, v) in nonzero_pairs(t) I′ = CartesianIndex(TT.deleteat(I.I, i)) - tdst[I′] = TK.removeunitspace(v, i) + tdst[I′] = TK.removeunit(v, i) end return tdst end From e54130432f52397197d743550e11abf8da48d34f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 16:26:33 +0100 Subject: [PATCH 15/25] edit tests --- test/vectorspaces/sumspace.jl | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index baa1505..6a8755a 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -185,7 +185,7 @@ end @test @constinferred(dual(V)) == @constinferred(conj(V)) == @constinferred(adjoint(V)) @test field(V) == ℂ - @test_throws ArgumentError("sectors of $V are not all equal") oneunit(V) + @test unitspace(V) == unitspace(V1) @test @constinferred(sectortype(V)) == sectortype(V1) @test ((@constinferred sectors(V))...,) == (C1, C0, D1, D0, M) # ordering matters @@ -198,23 +198,24 @@ end @test dim(@constinferred(typeof(V)())) == 0 @test (sectors(typeof(V)())...,) == () - # (left/right)oneunit tests + # (left/right)unitspace tests WC = @constinferred SumSpace(Vect[I](C0 => 1)) WD = @constinferred SumSpace(Vect[I](D0 => 1)) WM = @constinferred SumSpace(V3) WMop = @constinferred SumSpace(Vect[I](Mop => 1)) for W in [WC, WD] - @test @constinferred(oneunit(W)) == W == @constinferred(leftoneunit(W)) == @constinferred(rightoneunit(W)) - @test_throws ArgumentError("one of Type IsingBimodule doesn't exist") oneunit(typeof(W)) + @test W == @constinferred(leftunitspace(W)) == @constinferred(rightunitspace(W)) + @test unitspace(typeof(W)) == ⊞(Vect[IsingBimodule]((1, 1, 0) => 1, (2, 2, 0) => 1)) end - @test leftoneunit(WMop) == WD && rightoneunit(WMop) == WC - @test leftoneunit(WM) == WC && rightoneunit(WM) == WD - @test_throws ArgumentError("non-diagonal SumSpace $WM") oneunit(WM) - @test_throws ArgumentError("non-diagonal SumSpace $WMop") oneunit(WMop) + @test leftunitspace(WMop) == WD && rightunitspace(WMop) == WC + @test leftunitspace(WM) == WC && rightunitspace(WM) == WD + @test unitspace(WM) == unitspace(WMop) == ⊞(Vect[IsingBimodule]((1, 1, 0) => 1, (2, 2, 0) => 1)) Wempty = SumSpace(Vect[I]()) - for f in (oneunit, leftoneunit, rightoneunit) + Wzero = zerospace(V) + @test unitspace(Wempty) == unitspace(Wzero) + for f in (leftunitspace, rightunitspace) @test_throws ArgumentError("Cannot determine type of empty space") f(Wempty) end @@ -222,12 +223,12 @@ end VCM = SumSpace(V1, V3) VMD = SumSpace(V2, V3) - @test @constinferred(⊕(V, V)) == SumSpace(vcat(V.spaces, V.spaces)) - @test @constinferred(⊕(VC, oneunit(VC))) == SumSpace(vcat(VC.spaces, oneunit(VC))) - @test @constinferred(⊕(VCM, leftoneunit(VCM))) == SumSpace(vcat(VCM.spaces, leftoneunit(VCM))) - @test @constinferred(⊕(VMD, rightoneunit(VMD))) == SumSpace(vcat(VMD.spaces, rightoneunit(VMD))) + @test @constinferred(⊞(V, V)) == SumSpace(vcat(V.spaces, V.spaces)) + @test @constinferred(⊞(VC, unitspace(VC))) == SumSpace(vcat(VC.spaces, unitspace(VC))) + @test @constinferred(⊞(VCM, leftunitspace(VCM))) == SumSpace(vcat(VCM.spaces, leftunitspace(VCM))) + @test @constinferred(⊞(VMD, rightunitspace(VMD))) == SumSpace(vcat(VMD.spaces, rightunitspace(VMD))) - @test @constinferred(⊕(V, V, V, V)) == SumSpace(repeat(V.spaces, 4)) + @test @constinferred(⊞(V, V, V, V)) == SumSpace(repeat(V.spaces, 4)) @test @constinferred(fuse(VC, VC)) ≅ SumSpace(Vect[I](C0 => 8, C1 => 8)) @test @constinferred(fuse(VC, VC', VC, VC')) ≅ SumSpace(Vect[I](C0 => 128, C1 => 128)) @@ -239,9 +240,9 @@ end @test !(V ≻ ⊕(V, V)) # blocksectors tests - @test @constinferred(blocksectors(one(V) ← one(V))) == [C0, D0] + @test @constinferred(blocksectors(one(V) ← one(V))) == (C0, D0) @test @constinferred(blocksectors(V ← V)) == sort(collect(sectors(V))) # convert set to vector - @test @constinferred(blocksectors(one(V))) == [C0, D0] + @test @constinferred(blocksectors(one(V))) == (C0, D0) for v in [VC, VCM, VMD] @test @constinferred(blocksectors(v^2)) == blocksectors(v ← v) end From 5a7ea725fc1c7b275b7863bddf67e660b014b931 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 1 Dec 2025 17:40:56 +0100 Subject: [PATCH 16/25] add `isunitspace` --- src/vectorspaces/sumspace.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index 2026dae..4116aa5 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -172,8 +172,8 @@ TensorKit.unitspace(S::Type{<:SumSpace}) = SumSpace(TensorKit.unitspace(eltype(S TensorKit.zerospace(::Type{SumSpace{S}}) where {S} = SumSpace{S}() TensorKit.leftunitspace(S::SumSpace{<:GradedSpace}) = SumSpace(leftunitspace(first(S))) - TensorKit.rightunitspace(S::SumSpace{<:GradedSpace}) = SumSpace(rightunitspace(first(S))) +TensorKit.isunitspace(S::SumSpace{<:GradedSpace}) = all(isunitspace, S.spaces) # Promotion and conversion # ------------------------ From f97c6a7bff5b00fbc153caf413a80ee88ee6fede Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 1 Dec 2025 17:41:06 +0100 Subject: [PATCH 17/25] more tests --- test/vectorspaces/sumspace.jl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index 6a8755a..2ac4743 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -204,10 +204,13 @@ end WM = @constinferred SumSpace(V3) WMop = @constinferred SumSpace(Vect[I](Mop => 1)) for W in [WC, WD] + @test isunitspace(W) @test W == @constinferred(leftunitspace(W)) == @constinferred(rightunitspace(W)) @test unitspace(typeof(W)) == ⊞(Vect[IsingBimodule]((1, 1, 0) => 1, (2, 2, 0) => 1)) end + @test leftunitspace(V) == ⊞(WC, WD, WC) + @test rightunitspace(V) == ⊞(WC, WD, WD) @test leftunitspace(WMop) == WD && rightunitspace(WMop) == WC @test leftunitspace(WM) == WC && rightunitspace(WM) == WD @test unitspace(WM) == unitspace(WMop) == ⊞(Vect[IsingBimodule]((1, 1, 0) => 1, (2, 2, 0) => 1)) @@ -216,7 +219,7 @@ end Wzero = zerospace(V) @test unitspace(Wempty) == unitspace(Wzero) for f in (leftunitspace, rightunitspace) - @test_throws ArgumentError("Cannot determine type of empty space") f(Wempty) + @test_throws ArgumentError f(Wempty) end VC = SumSpace(V1, V1) @@ -224,9 +227,9 @@ end VMD = SumSpace(V2, V3) @test @constinferred(⊞(V, V)) == SumSpace(vcat(V.spaces, V.spaces)) - @test @constinferred(⊞(VC, unitspace(VC))) == SumSpace(vcat(VC.spaces, unitspace(VC))) - @test @constinferred(⊞(VCM, leftunitspace(VCM))) == SumSpace(vcat(VCM.spaces, leftunitspace(VCM))) - @test @constinferred(⊞(VMD, rightunitspace(VMD))) == SumSpace(vcat(VMD.spaces, rightunitspace(VMD))) + @test @constinferred(⊞(VCM, unitspace(VCM))) == SumSpace(vcat(VCM.spaces, unitspace(VCM).spaces)) + @test @constinferred(⊞(VCM, leftunitspace(VCM))) == SumSpace(vcat(VCM.spaces, leftunitspace(VCM).spaces)) + @test @constinferred(⊞(VMD, rightunitspace(VMD))) == SumSpace(vcat(VMD.spaces, rightunitspace(VMD).spaces)) @test @constinferred(⊞(V, V, V, V)) == SumSpace(repeat(V.spaces, 4)) @test @constinferred(fuse(VC, VC)) ≅ SumSpace(Vect[I](C0 => 8, C1 => 8)) @@ -242,7 +245,7 @@ end # blocksectors tests @test @constinferred(blocksectors(one(V) ← one(V))) == (C0, D0) @test @constinferred(blocksectors(V ← V)) == sort(collect(sectors(V))) # convert set to vector - @test @constinferred(blocksectors(one(V))) == (C0, D0) + @test @constinferred(blocksectors(one(V))) == [C0, D0] for v in [VC, VCM, VMD] @test @constinferred(blocksectors(v^2)) == blocksectors(v ← v) end From e3ab406faec2b55817f1f55ac983e7b6cf436926 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 1 Dec 2025 17:43:21 +0100 Subject: [PATCH 18/25] format --- test/vectorspaces/sumspace.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index 2ac4743..a22a938 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -253,4 +253,4 @@ end @test isempty(@constinferred(blocksectors(v^2))) @test @constinferred(blocksectors(v ← v)) == blocksectors(v) end -end \ No newline at end of file +end From 4f07d8ba609446d0f5512d54c0013088a0523343 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 15 Dec 2025 11:29:43 +0100 Subject: [PATCH 19/25] check coloring of all component spaces + fix tests --- src/vectorspaces/sumspace.jl | 23 +++++++++++++++++++++-- test/vectorspaces/sumspace.jl | 6 ++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index 4116aa5..810d398 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -171,8 +171,27 @@ end TensorKit.unitspace(S::Type{<:SumSpace}) = SumSpace(TensorKit.unitspace(eltype(S))) TensorKit.zerospace(::Type{SumSpace{S}}) where {S} = SumSpace{S}() -TensorKit.leftunitspace(S::SumSpace{<:GradedSpace}) = SumSpace(leftunitspace(first(S))) -TensorKit.rightunitspace(S::SumSpace{<:GradedSpace}) = SumSpace(rightunitspace(first(S))) +function TensorKit.leftunitspace(S::SumSpace{<:GradedSpace}) + I = sectortype(S) + if UnitStyle(I) isa GenericUnit + !isempty(sectors(S)) || throw(ArgumentError("Cannot determine the left unit of an empty SumSpace")) + TensorKit._allequal(leftunit, sectors(S)) || + throw(ArgumentError("sectors of $S do not have the same left unit")) + end + + return SumSpace(leftunitspace(first(S))) +end + +function TensorKit.rightunitspace(S::SumSpace{<:GradedSpace}) + I = sectortype(S) + if UnitStyle(I) isa GenericUnit + !isempty(sectors(S)) || throw(ArgumentError("Cannot determine the right unit of an empty SumSpace")) + TensorKit._allequal(rightunit, sectors(S)) || + throw(ArgumentError("sectors of $S do not have the same right unit")) + end + + return SumSpace(rightunitspace(first(S))) +end TensorKit.isunitspace(S::SumSpace{<:GradedSpace}) = all(isunitspace, S.spaces) # Promotion and conversion diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index a22a938..29f47d2 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -209,8 +209,10 @@ end @test unitspace(typeof(W)) == ⊞(Vect[IsingBimodule]((1, 1, 0) => 1, (2, 2, 0) => 1)) end - @test leftunitspace(V) == ⊞(WC, WD, WC) - @test rightunitspace(V) == ⊞(WC, WD, WD) + @test_throws ArgumentError leftunitspace(V) + @test_throws ArgumentError rightunitspace(V) + @test leftunitspace(SumSpace(V1, V3)) == WC + @test rightunitspace(SumSpace(V2, V3)) == WD @test leftunitspace(WMop) == WD && rightunitspace(WMop) == WC @test leftunitspace(WM) == WC && rightunitspace(WM) == WD @test unitspace(WM) == unitspace(WMop) == ⊞(Vect[IsingBimodule]((1, 1, 0) => 1, (2, 2, 0) => 1)) From f7f1ac4e9d28c0442dd826f54ff7688d626cbe3d Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 16 Dec 2025 09:15:55 +0100 Subject: [PATCH 20/25] relax `isunitspace` dispatch but check zero spaces --- src/vectorspaces/sumspace.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index 810d398..fe6b1da 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -192,7 +192,7 @@ function TensorKit.rightunitspace(S::SumSpace{<:GradedSpace}) return SumSpace(rightunitspace(first(S))) end -TensorKit.isunitspace(S::SumSpace{<:GradedSpace}) = all(isunitspace, S.spaces) +TensorKit.isunitspace(S::SumSpace) = !isempty(S) && all(isunitspace, S.spaces) # Promotion and conversion # ------------------------ From 1cf8e715beee084a15783ea36cac8fae92674d68 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 16 Dec 2025 09:18:12 +0100 Subject: [PATCH 21/25] use `oplus` instead of `sectors` --- src/vectorspaces/sumspace.jl | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index fe6b1da..9f658f6 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -172,25 +172,10 @@ TensorKit.unitspace(S::Type{<:SumSpace}) = SumSpace(TensorKit.unitspace(eltype(S TensorKit.zerospace(::Type{SumSpace{S}}) where {S} = SumSpace{S}() function TensorKit.leftunitspace(S::SumSpace{<:GradedSpace}) - I = sectortype(S) - if UnitStyle(I) isa GenericUnit - !isempty(sectors(S)) || throw(ArgumentError("Cannot determine the left unit of an empty SumSpace")) - TensorKit._allequal(leftunit, sectors(S)) || - throw(ArgumentError("sectors of $S do not have the same left unit")) - end - - return SumSpace(leftunitspace(first(S))) + return SumSpace(leftunitspace(oplus(S))) end - function TensorKit.rightunitspace(S::SumSpace{<:GradedSpace}) - I = sectortype(S) - if UnitStyle(I) isa GenericUnit - !isempty(sectors(S)) || throw(ArgumentError("Cannot determine the right unit of an empty SumSpace")) - TensorKit._allequal(rightunit, sectors(S)) || - throw(ArgumentError("sectors of $S do not have the same right unit")) - end - - return SumSpace(rightunitspace(first(S))) + return SumSpace(rightunitspace(oplus(S))) end TensorKit.isunitspace(S::SumSpace) = !isempty(S) && all(isunitspace, S.spaces) From 885b42db42000aa3d127e3852c2ff63f1e5a86ea Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 16 Dec 2025 09:20:04 +0100 Subject: [PATCH 22/25] relax more --- src/vectorspaces/sumspace.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index 9f658f6..b4d97a4 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -171,10 +171,10 @@ end TensorKit.unitspace(S::Type{<:SumSpace}) = SumSpace(TensorKit.unitspace(eltype(S))) TensorKit.zerospace(::Type{SumSpace{S}}) where {S} = SumSpace{S}() -function TensorKit.leftunitspace(S::SumSpace{<:GradedSpace}) +function TensorKit.leftunitspace(S::SumSpace) return SumSpace(leftunitspace(oplus(S))) end -function TensorKit.rightunitspace(S::SumSpace{<:GradedSpace}) +function TensorKit.rightunitspace(S::SumSpace) return SumSpace(rightunitspace(oplus(S))) end TensorKit.isunitspace(S::SumSpace) = !isempty(S) && all(isunitspace, S.spaces) From 23d3fa42e13475c1b07415356f8e5b34a1595912 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 16 Dec 2025 09:22:48 +0100 Subject: [PATCH 23/25] use `issetequal` --- test/vectorspaces/sumspace.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index 29f47d2..1a609e4 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -246,7 +246,7 @@ end # blocksectors tests @test @constinferred(blocksectors(one(V) ← one(V))) == (C0, D0) - @test @constinferred(blocksectors(V ← V)) == sort(collect(sectors(V))) # convert set to vector + @test issetequal(@constinferred(blocksectors(V ← V)), sectors(V)) @test @constinferred(blocksectors(one(V))) == [C0, D0] for v in [VC, VCM, VMD] @test @constinferred(blocksectors(v^2)) == blocksectors(v ← v) From 3e5940fde621ad51b809ae033ba5bfd971e9b940 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 16 Dec 2025 09:24:28 +0100 Subject: [PATCH 24/25] another issetequal --- test/vectorspaces/sumspace.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vectorspaces/sumspace.jl b/test/vectorspaces/sumspace.jl index 1a609e4..7770ce1 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -245,7 +245,7 @@ end @test !(V ≻ ⊕(V, V)) # blocksectors tests - @test @constinferred(blocksectors(one(V) ← one(V))) == (C0, D0) + @test issetequal(@constinferred(blocksectors(one(V) ← one(V))), (C0, D0)) @test issetequal(@constinferred(blocksectors(V ← V)), sectors(V)) @test @constinferred(blocksectors(one(V))) == [C0, D0] for v in [VC, VCM, VMD] From 333a3224609b5253979a332d71c1a5007f6d8a38 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 10:08:39 +0100 Subject: [PATCH 25/25] bump version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 3ee008e..efa63b2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "BlockTensorKit" uuid = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" -version = "0.3.4" +version = "0.3.5" authors = ["Lukas Devos and contributors"] [deps]