diff --git a/Project.toml b/Project.toml index 379300a..903dfc7 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "BlockTensorKit" uuid = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" -version = "0.3.18" +version = "0.3.19" authors = ["Lukas Devos and contributors"] [deps] @@ -36,7 +36,7 @@ MatrixAlgebraKit = "0.6" Random = "1" SafeTestsets = "0.1" Strided = "2.3.3" -TensorKit = "0.17" +TensorKit = "0.17.2" TensorOperations = "5" Test = "1" TestExtras = "0.2, 0.3" diff --git a/src/vectorspaces/sumspace.jl b/src/vectorspaces/sumspace.jl index 8415b62..1375e69 100644 --- a/src/vectorspaces/sumspace.jl +++ b/src/vectorspaces/sumspace.jl @@ -180,6 +180,18 @@ function TensorKit.rightunitspace(S::SumSpace) end TensorKit.isunitspace(S::SumSpace) = !isempty(S) && all(isunitspace, S.spaces) +# a `SumSpace` must, as a whole, be homogeneously colored: all of its sectors (across all +# components) share a single left and right unit, exactly like a plain `GradedSpace`. +function TK._leftrightunit(S::SumSpace) + s = sectors(S) + isempty(s) && return (nothing, nothing) + c = first(s) + l, r = TK.leftunit(c), TK.rightunit(c) + all(x -> TK.leftunit(x) == l && TK.rightunit(x) == r, s) || + throw(SpaceMismatch(lazy"components of $S do not share a single left and right unit")) + return (l, r) +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 1c877ba..0e9eb0c 100644 --- a/test/vectorspaces/sumspace.jl +++ b/test/vectorspaces/sumspace.jl @@ -160,7 +160,6 @@ end using Test, TestExtras using TensorKit: hassector - using BlockTensorKit: ⊕ I = IsingBimodule @@ -186,7 +185,9 @@ end @test @constinferred(dual(V)) == @constinferred(conj(V)) == @constinferred(adjoint(V)) @test field(V) == ℂ - @test unitspace(V) == unitspace(V1) + @test_throws ArgumentError unitspace(V1) + @test_throws ArgumentError unitspace(V) + @test_throws ArgumentError unitspace(SumSpace(V1)) @test @constinferred(sectortype(V)) == sectortype(V1) @test ((@constinferred sectors(V))...,) == (C0, C1, M, D0, D1) # sorted order @@ -208,20 +209,26 @@ end 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)) + @test_throws ArgumentError unitspace(typeof(W)) end - @test_throws ArgumentError leftunitspace(V) - @test_throws ArgumentError rightunitspace(V) - @test leftunitspace(SumSpace(V1, V3)) == WC - @test rightunitspace(SumSpace(V2, V3)) == WD + # a `SumSpace` is only well-defined as a single left/right unit when ALL of its + # components, taken together, are homogeneously colored -- exactly like a plain + # `GradedSpace`. Combinations that mix components with different left and/or right + # units are rejected, even if they happen to agree on one side. + @test_throws SpaceMismatch leftunitspace(V) + @test_throws SpaceMismatch rightunitspace(V) + @test_throws SpaceMismatch leftunitspace(SumSpace(V1, V3)) + @test_throws SpaceMismatch rightunitspace(SumSpace(V2, V3)) @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)) + @test_throws ArgumentError unitspace(WM) + @test_throws ArgumentError unitspace(WMop) Wempty = SumSpace(Vect[I]()) Wzero = zerospace(V) - @test unitspace(Wempty) == unitspace(Wzero) + @test_throws ArgumentError unitspace(Wempty) + @test_throws ArgumentError unitspace(Wzero) for f in (leftunitspace, rightunitspace) @test_throws ArgumentError f(Wempty) end @@ -231,9 +238,9 @@ end VMD = SumSpace(V2, V3) @test @constinferred(⊞(V, V)) == SumSpace(vcat(V.spaces, V.spaces)) - @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_throws ArgumentError unitspace(VCM) + @test_throws SpaceMismatch leftunitspace(VCM) + @test_throws SpaceMismatch rightunitspace(VMD) @test @constinferred(⊞(V, V, V, V)) == SumSpace(repeat(V.spaces, 4)) @test @constinferred(fuse(VC, VC)) ≅ SumSpace(Vect[I](C0 => 8, C1 => 8)) @@ -243,18 +250,19 @@ end @test flip(V) ≅ V @test flip(V) ≾ V @test flip(V) ≿ V - @test V ≺ ⊕(V, V) - @test !(V ≻ ⊕(V, V)) + @test V ≺ ⊞(V, V) + @test !(V ≻ ⊞(V, V)) # blocksectors tests @test issetequal(@constinferred(blocksectors(one(V) ← one(V))), (C0, D0)) - @test issetequal(@constinferred(blocksectors(V ← V)), sectors(V)) + @test_throws SpaceMismatch V ← V # `V` itself is not homogeneously colored @test @constinferred(blocksectors(one(V))) == [C0, D0] - for v in [VC, VCM, VMD] - @test issetequal(@constinferred(blocksectors(v^2)), blocksectors(v ← v)) + @test issetequal(@constinferred(blocksectors(VC^2)), blocksectors(VC ← VC)) + for v in [VCM, VMD] + @test_throws SpaceMismatch v^2 # not homogeneously colored end for v in [WM, WMop] - @test isempty(@constinferred(blocksectors(v^2))) + @test_throws SpaceMismatch v^2 @test issetequal(@constinferred(blocksectors(v ← v)), blocksectors(v)) end end