From 317c3b6ecc66dedf413a5e5c0f4e26d8641a0845 Mon Sep 17 00:00:00 2001 From: Katharine Hyatt Date: Mon, 8 Jun 2026 07:13:38 +0200 Subject: [PATCH 1/2] Update Project.toml Bump VI and TK deps and patch version --- Project.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index ee8ccda..3b9c176 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "BlockTensorKit" uuid = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" -version = "0.3.13" +version = "0.3.14" authors = ["Lukas Devos and contributors"] [deps] @@ -36,12 +36,12 @@ MatrixAlgebraKit = "0.6" Random = "1" SafeTestsets = "0.1" Strided = "2.3.3" -TensorKit = "0.16.4" +TensorKit = "0.16.4, 0.17" TensorOperations = "5" Test = "1" TestExtras = "0.2, 0.3" TupleTools = "1" -VectorInterface = "0.4.8, 0.5" +VectorInterface = "0.4.8, 0.5, 0.6" julia = "1.10" [extras] From 7611a62d7337b787329c9a12e42ba3ca7e50af83 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 8 Jun 2026 11:09:42 -0400 Subject: [PATCH 2/2] update for indexmanipulation API changes --- Project.toml | 2 +- src/tensors/indexmanipulations.jl | 272 ++++++++++++------------------ 2 files changed, 112 insertions(+), 162 deletions(-) diff --git a/Project.toml b/Project.toml index 3b9c176..dcb6c4c 100644 --- a/Project.toml +++ b/Project.toml @@ -36,7 +36,7 @@ MatrixAlgebraKit = "0.6" Random = "1" SafeTestsets = "0.1" Strided = "2.3.3" -TensorKit = "0.16.4, 0.17" +TensorKit = "0.17" TensorOperations = "5" Test = "1" TestExtras = "0.2, 0.3" diff --git a/src/tensors/indexmanipulations.jl b/src/tensors/indexmanipulations.jl index 58e3cd7..1194120 100644 --- a/src/tensors/indexmanipulations.jl +++ b/src/tensors/indexmanipulations.jl @@ -1,233 +1,183 @@ -function TK.add_transform!( - tdst::BlockTensorMap, tsrc::BlockTensorMap, (p₁, p₂)::Index2Tuple{N₁, N₂}, - fusiontreetransform, - α::Number, β::Number, - backend::AbstractBackend..., - ) where {N₁, N₂} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) - end +@propagate_inbounds function TK.add_transform!( + tdst::BlockTensorMap, tsrc::BlockTensorMap, p::Index2Tuple, transformer, + α::Number, β::Number, backend, allocator + ) + @boundscheck TK.spacecheck_transform(permute, tdst, tsrc, p) + dstdata = parent(tdst) - srcdata = permutedims(StridedView(parent(tsrc)), (p₁..., p₂...)) + srcdata = permutedims(StridedView(parent(tsrc)), (p[1]..., p[2]...)) @inbounds for I in eachindex(dstdata, srcdata) dstdata[I] = TK.add_transform!( - dstdata[I], srcdata[I], (p₁, p₂), fusiontreetransform, α, β, backend... + dstdata[I], srcdata[I], p, transformer, α, β, backend, allocator ) end return tdst end -function TK.add_transform!( +@propagate_inbounds function TK.add_transform!( tdst::AbstractBlockTensorMap, tsrc::AbstractBlockTensorMap, - (p₁, p₂)::Index2Tuple{N₁, N₂}, - fusiontreetransform, - α::Number, β::Number, - backend::AbstractBackend..., - ) where {N₁, N₂} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) - end + p::Index2Tuple, transformer, α::Number, β::Number, backend, allocator + ) + @boundscheck TK.spacecheck_transform(permute, tdst, tsrc, p) scale!(tdst, β) - p = (p₁..., p₂...) + p_lin = (p[1]..., p[2]...) @inbounds for (I, v) in nonzero_pairs(tsrc) - I′ = CartesianIndex(TT.getindices(I.I, p)) + I′ = CartesianIndex(TT.getindices(I.I, p_lin)) tdst[I′] = TK.add_transform!( - tdst[I′], v, (p₁, p₂), fusiontreetransform, α, One(), backend... + tdst[I′], v, p_lin, transformer, α, One(), backend, allocator ) end return tdst end function TK.add_transform!( tdst::AbstractBlockTensorMap, tsrc::AdjointTensorMap{T, S, N₁, N₂, TT}, - (p₁, p₂)::Index2Tuple, - fusiontreetransform, - α::Number, β::Number, - backend::AbstractBackend..., + p::Index2Tuple, transformer, α::Number, β::Number, backend, allocator ) where {T, S, N₁, N₂, TT <: AbstractBlockTensorMap} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) - end + @boundscheck TK.spacecheck_transform(permute, tdst, tsrc, p) scale!(tdst, β) - p = (p₁..., p₂...) + p_lin = (p[1]..., p[2]...) @inbounds for (I, v) in nonzero_pairs(tsrc) - I′ = CartesianIndex(TT.getindices(I.I, p)) + I′ = CartesianIndex(TT.getindices(I.I, p_lin)) tdst[I′] = TK.add_transform!( - tdst[I′], v, (p₁, p₂), fusiontreetransform, α, One(), backend... + tdst[I′], v, p, transformer, α, One(), backend, allocator ) end return tdst end function TK.add_transform!( - tdst::TensorMap, tsrc::BlockTensorMap, (p₁, p₂)::Index2Tuple, - fusiontreetransform, - α::Number, β::Number, - backend::AbstractBackend..., + tdst::TensorMap, tsrc::BlockTensorMap, p::Index2Tuple, transformer, + α::Number, β::Number, backend, allocator ) - @assert length(tsrc) == 1 "source tensor must be a single tensor" return TK.add_transform!( - tdst, only(tsrc), (p₁, p₂), fusiontreetransform, α, β, backend... + tdst, only(tsrc), p, transformer, α, β, backend, allocator ) end function TK.add_transform!( - tdst::BlockTensorMap, tsrc::TensorMap, - (p₁, p₂)::Index2Tuple, - fusiontreetransform, - α::Number, β::Number, - backend::AbstractBackend..., + tdst::BlockTensorMap, tsrc::TensorMap, p::Index2Tuple, transformer, + α::Number, β::Number, backend, allocator ) - # @assert length(tsrc) == 1 "source tensor must be a single tensor" return TK.add_transform!( - only(tdst), tsrc, (p₁, p₂), fusiontreetransform, α, β, backend... + only(tdst), tsrc, p, transformer, α, β, backend, allocator ) end # we need to capture the other functions earlier to enjoy the fast transformers... -for f! in (:add_permute!, :add_transpose!) - @eval function TK.$f!( - tdst::BlockTensorMap, tsrc::BlockTensorMap, - (p₁, p₂)::Index2Tuple{N₁, N₂}, - α::Number, β::Number, - backend::AbstractBackend..., - ) where {N₁, N₂} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) - end - dstdata = parent(tdst) - srcdata = permutedims(StridedView(parent(tsrc)), (p₁..., p₂...)) +for f in (:permute, :transpose) + f! = Symbol(f, :!) + @eval begin + function TK.$f!( + tdst::BlockTensorMap, tsrc::BlockTensorMap, p::Index2Tuple, + α::Number, β::Number, backend::AbstractBackend, allocator + ) + @boundscheck TK.spacecheck_transform(TK.$f, tdst, tsrc, p) - @inbounds for I in eachindex(dstdata, srcdata) - dstdata[I] = TK.$f!(dstdata[I], srcdata[I], (p₁, p₂), α, β, backend...) + dstdata = parent(tdst) + srcdata = permutedims(StridedView(parent(tsrc)), (p[1]..., p[2]...)) + + @inbounds for I in eachindex(dstdata, srcdata) + dstdata[I] = TK.$f!(dstdata[I], srcdata[I], p, α, β, backend, allocator) + end + return tdst end - return tdst - end - @eval function TK.$f!( - tdst::AbstractBlockTensorMap, tsrc::AbstractBlockTensorMap, - (p₁, p₂)::Index2Tuple{N₁, N₂}, - α::Number, β::Number, - backend::AbstractBackend..., - ) where {N₁, N₂} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) + function TK.$f!( + tdst::AbstractBlockTensorMap, tsrc::AbstractBlockTensorMap, + p::Index2Tuple, α::Number, β::Number, backend::AbstractBackend, allocator + ) + @boundscheck TK.spacecheck_transform(TK.$f, tdst, tsrc, p) + scale!(tdst, β) + p_lin = (p[1]..., p[2]...) + @inbounds for (I, v) in nonzero_pairs(tsrc) + I′ = CartesianIndex(TT.getindices(I.I, p_lin)) + tdst[I′] = TK.$f!(tdst[I′], v, p, α, One(), backend, allocator) + end + return tdst end - scale!(tdst, β) - p = (p₁..., p₂...) - @inbounds for (I, v) in nonzero_pairs(tsrc) - I′ = CartesianIndex(TT.getindices(I.I, p)) - tdst[I′] = TK.$f!(tdst[I′], v, (p₁, p₂), α, One(), backend...) + function TK.$f!( + tdst::AbstractBlockTensorMap, tsrc::AdjointTensorMap{T, S, N₁, N₂, TT}, + p::Index2Tuple, α::Number, β::Number, backend::AbstractBackend, allocator + ) where {T, S, N₁, N₂, TT <: AbstractBlockTensorMap} + @boundscheck TK.spacecheck_transform(TK.$f, tdst, tsrc, p) + scale!(tdst, β) + p_lin = (p[1]..., p[2]...) + @inbounds for (I, v) in nonzero_pairs(tsrc) + I′ = CartesianIndex(TT.getindices(I.I, p)) + tdst[I′] = TK.$f!(tdst[I′], v, (p₁, p₂), α, One(), backend, allocator) + end + return tdst end - return tdst - end - @eval function TK.$f!( - tdst::AbstractBlockTensorMap, tsrc::AdjointTensorMap{T, S, N₁, N₂, TT}, - (p₁, p₂)::Index2Tuple, - α::Number, β::Number, - backend::AbstractBackend..., - ) where {T, S, N₁, N₂, TT <: AbstractBlockTensorMap} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) + function TK.$f!( + tdst::TensorMap, tsrc::BlockTensorMap, p::Index2Tuple, + α::Number, β::Number, backend::AbstractBackend, allocator + ) + return TK.$f!(tdst, only(tsrc), p, α, β, backend, allocator) end - scale!(tdst, β) - p = (p₁..., p₂...) - @inbounds for (I, v) in nonzero_pairs(tsrc) - I′ = CartesianIndex(TT.getindices(I.I, p)) - tdst[I′] = TK.$f!(tdst[I′], v, (p₁, p₂), α, One(), backend...) + function TK.$f!( + tdst::BlockTensorMap, tsrc::TensorMap, p::Index2Tuple, + α::Number, β::Number, backend::AbstractBackend, allocator + ) + TK.$f!(only(tdst), tsrc, p, α, β, backend, allocator) + return tdst end - return tdst - end - @eval function TK.$f!( - tdst::TensorMap, tsrc::BlockTensorMap, - (p₁, p₂)::Index2Tuple, - α::Number, β::Number, - backend::AbstractBackend..., - ) - @assert length(tsrc) == 1 "source tensor must be a single tensor" - return TK.$f!(tdst, only(tsrc), (p₁, p₂), α, β, backend...) end end -function TK.add_braid!( - tdst::BlockTensorMap, tsrc::BlockTensorMap, - (p₁, p₂)::Index2Tuple{N₁, N₂}, - levels::IndexTuple, - α::Number, β::Number, - backend::AbstractBackend..., - ) where {N₁, N₂} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) - end +@propagate_inbounds function TK.braid!( + tdst::BlockTensorMap, tsrc::BlockTensorMap, p::Index2Tuple, levels::IndexTuple, + α::Number, β::Number, backend::AbstractBackend, allocator + ) + @boundscheck TK.spacecheck_transform(braid, tdst, tsrc, p, levels) + dstdata = parent(tdst) - srcdata = permutedims(StridedView(parent(tsrc)), (p₁..., p₂...)) + srcdata = permutedims(StridedView(parent(tsrc)), (p[1]..., p[2]...)) @inbounds for I in eachindex(dstdata, srcdata) - dstdata[I] = TK.add_braid!( - dstdata[I], srcdata[I], (p₁, p₂), levels, α, β, backend... + dstdata[I] = TK.braid!( + dstdata[I], srcdata[I], p, levels, α, β, backend, allocator ) end return tdst end -function TK.add_braid!( +@propagate_inbounds function TK.braid!( tdst::AbstractBlockTensorMap, tsrc::AbstractBlockTensorMap, - (p₁, p₂)::Index2Tuple{N₁, N₂}, - levels::IndexTuple, - α::Number, β::Number, - backend::AbstractBackend..., - ) where {N₁, N₂} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) - end + p::Index2Tuple, levels::IndexTuple, + α::Number, β::Number, backend::AbstractBackend, allocator + ) + @boundscheck TK.spacecheck_transform(braid, tdst, tsrc, p, levels) scale!(tdst, β) - p = (p₁..., p₂...) + p_lin = (p[1]..., p[2]...) @inbounds for (I, v) in nonzero_pairs(tsrc) - I′ = CartesianIndex(TT.getindices(I.I, p)) - tdst[I′] = TK.add_braid!(tdst[I′], v, (p₁, p₂), levels, α, One(), backend...) + I′ = CartesianIndex(TT.getindices(I.I, p_lin)) + tdst[I′] = TK.braid!(tdst[I′], v, p, levels, α, One(), backend, allocator) end return tdst end -function TK.add_braid!( +function TK.braid!( tdst::AbstractBlockTensorMap, tsrc::AdjointTensorMap{T, S, N₁, N₂, TT}, - (p₁, p₂)::Index2Tuple, - levels::IndexTuple, - α::Number, β::Number, - backend::AbstractBackend..., + p::Index2Tuple, levels::IndexTuple, α::Number, β::Number, backend::AbstractBackend, allocator ) where {T, S, N₁, N₂, TT <: AbstractBlockTensorMap} - @boundscheck begin - permute(space(tsrc), (p₁, p₂)) == space(tdst) || - throw(SpaceMismatch("source = $(codomain(tsrc))←$(domain(tsrc)), - dest = $(codomain(tdst))←$(domain(tdst)), p₁ = $(p₁), p₂ = $(p₂)")) - end + @boundscheck TK.spacecheck_transform(braid, tdst, tsrc, p, levels) scale!(tdst, β) - p = (p₁..., p₂...) + p_lin = (p[1]..., p[2]...) @inbounds for (I, v) in nonzero_pairs(tsrc) - I′ = CartesianIndex(TT.getindices(I.I, p)) - tdst[I′] = TK.add_braid!(tdst[I′], v, (p₁, p₂), levels, α, One(), backend...) + I′ = CartesianIndex(TT.getindices(I.I, p_lin)) + tdst[I′] = TK.braid!(tdst[I′], v, p, levels, α, One(), backend, allocator) end return tdst end -function TK.add_braid!( +function TK.braid!( tdst::TensorMap, tsrc::BlockTensorMap, - (p₁, p₂)::Index2Tuple, - levels::IndexTuple, - α::Number, β::Number, - backend::AbstractBackend..., + p::Index2Tuple, levels::IndexTuple, + α::Number, β::Number, backend::AbstractBackend, allocator + ) + return TK.add_braid!(tdst, only(tsrc), p, levels, α, β, backend, allocator) +end +function TK.braid!( + tdst::BlockTensorMap, tsrc::TensorMap, + p::Index2Tuple, levels::IndexTuple, + α::Number, β::Number, backend::AbstractBackend, allocator ) - @assert length(tsrc) == 1 "source tensor must be a single tensor" - return TK.add_braid!(tdst, only(tsrc), (p₁, p₂), levels, α, β, backend...) + TK.braid!(only(tdst), tsrc, p, levels, α, β, backend, allocator) + return tdst end Base.@constprop :aggressive function TK.insertleftunit(