Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
65ea338
FusionTreePair
lkdvos Jul 30, 2025
ba97ca1
implement "vectorized" fusiontree manipulations
lkdvos Jul 31, 2025
74b323a
Refactor treetransformer to make use of vectorized implementation
lkdvos Jul 31, 2025
610e195
fix arg order `braid`
lkdvos Jul 31, 2025
42fa59b
refactor in terms of FusionTreeBlock
lkdvos Jul 31, 2025
7cd9fbc
Fix unbound type parameter
lkdvos Jul 31, 2025
59f8188
refactor repartition to unroll loop
lkdvos Jul 31, 2025
260688b
dont depend on intricate scoping rules
lkdvos Aug 13, 2025
cb8ab0d
Refactor bendright to avoid extra dictionary
lkdvos Aug 13, 2025
1ae2608
Refactor bendleft to avoid extra dictionaries
lkdvos Aug 13, 2025
6edf83c
Refactor foldright to avoid extra dictionaries
lkdvos Aug 13, 2025
10c04ae
Refactor foldleft to avoid extra dictionaries
lkdvos Aug 13, 2025
2cfe587
remove unused variable
lkdvos Aug 13, 2025
cf52331
some docs fixes
lkdvos Aug 14, 2025
47cbe11
Avoid using `one(I)`
lkdvos Aug 14, 2025
83d9a2a
format
lkdvos Aug 14, 2025
ecdaa94
Move independent computations out of loop
lkdvos Aug 15, 2025
fdcaddc
add utility fusiontreetype
lkdvos Aug 15, 2025
fb8d815
add multithreaded treetransformer implementation
lkdvos Aug 15, 2025
f303050
refactor treeindex_map
lkdvos Aug 15, 2025
77e484c
Refactor artin_braid to avoid extra dicts
lkdvos Aug 16, 2025
cea4e1c
type stability improvements
lkdvos Aug 16, 2025
a77dde5
fix multithreaded implementation
lkdvos Aug 17, 2025
f70405c
speed up hashing by hashing less things
lkdvos Aug 17, 2025
6210d04
Slight refactor of artin_braid
lkdvos Aug 17, 2025
bf9e6d9
reduce allocations with sizehints
lkdvos Aug 17, 2025
f5292d1
separate treemanipulation threads
lkdvos Aug 17, 2025
bc48a05
update `leftunit` and `rightunit`
lkdvos Nov 12, 2025
68cef16
add missing `treeindex_data`
lkdvos Nov 12, 2025
c3ded84
update `frobeniusschur` to `frobenius_schur_phase`
lkdvos Nov 12, 2025
02c0a05
remove stray file
lkdvos Nov 14, 2025
9dc27c4
some QOL additions
lkdvos Nov 16, 2025
ed00524
some reorganization
lkdvos Nov 16, 2025
364a1d7
rework indexmanipulations to use fusionblocks
lkdvos Nov 18, 2025
37622f7
update implementation to remove code duplication
lkdvos Nov 19, 2025
d5301ee
update fusiontensor overload
lkdvos Nov 19, 2025
c31bc93
temporary trace fix
lkdvos Nov 19, 2025
8f35e73
start tackling tests
lkdvos Nov 19, 2025
dd19c4d
Merge branch 'main' into ld-outer
lkdvos Dec 19, 2025
23c3994
attempts at cleanup
lkdvos Dec 21, 2025
c2ea490
fix argument order
lkdvos Jan 3, 2026
60348dd
handle empty case
lkdvos Jan 3, 2026
7866948
correctly import times
lkdvos Jan 3, 2026
5ac0d42
reorganize tests
lkdvos Jan 3, 2026
00c4a81
account for complex frobenius schur factors
lkdvos Jan 3, 2026
691f8e7
Merge branch 'main' into ld-outer
lkdvos Jan 3, 2026
b7dc600
resolve ambiguities
lkdvos Jan 3, 2026
10b2777
fix braidingtensor subblock
lkdvos Jan 5, 2026
411a423
fix braidingtensor block
lkdvos Jan 5, 2026
72d0df1
refactor braidingtensor access
lkdvos Jan 5, 2026
da8e939
fix planarcontract for braidingtensor
lkdvos Jan 5, 2026
58bedb6
code suggestions
lkdvos Jan 5, 2026
5f71cf1
docs fixes
lkdvos Jan 5, 2026
b44a9c5
Merge branch 'ld-outer' of https://github.com/QuantumKitHub/TensorKit…
lkdvos Jan 5, 2026
c518988
more docs fixes
lkdvos Jan 5, 2026
db772b0
(0, 0) FusionTreeBlock
lkdvos Jan 5, 2026
dff1193
correct for multifusion
lkdvos Jan 5, 2026
720580a
Merge branch 'main' into ld-outer
lkdvos Jan 5, 2026
cf504cf
fix missing innerlines
lkdvos Jan 6, 2026
f07586f
fix foldright for UniqueFusion with non-trivial Fsymbols
lkdvos Jan 6, 2026
ea5d346
Merge branch 'main' into ld-outer
lkdvos Jan 6, 2026
90751dd
actually use BLAS
lkdvos Jan 6, 2026
22e6fdc
isunit
lkdvos Jan 6, 2026
3126378
Apply suggestions from code review
lkdvos Jan 8, 2026
aa1f859
special case braiding with unit
lkdvos Jan 8, 2026
b48d2f8
Merge branch 'main' into ld-outer
lkdvos Jan 8, 2026
b5f0dd3
correctly handle stridedviews with `conj` flag
lkdvos Jan 8, 2026
67010a7
careful with reshapes and adjoints
lkdvos Jan 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Documenter
using Random
using TensorKit
using TensorKit: FusionTreePair, Index2Tuple
using TensorKit.TensorKitSectors
using TensorKit.MatrixAlgebraKit
using DocumenterInterLinks
Expand Down
23 changes: 10 additions & 13 deletions docs/src/lib/fusiontrees.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ FusionTree
## Methods for defining and generating fusion trees

```@docs
fusiontrees(uncoupled::NTuple{N,I}, coupled::I,
isdual::NTuple{N,Bool}) where {N,I<:Sector}
fusiontrees(uncoupled::NTuple{N, I}, coupled::I, isdual::NTuple{N, Bool}) where {N, I<:Sector}
```

## Methods for manipulating fusion trees
Expand All @@ -25,31 +24,29 @@ insertat
split
merge
elementary_trace
planar_trace(f::FusionTree{I,N}, q1::IndexTuple{N₃}, q2::IndexTuple{N₃}) where {I<:Sector,N,N₃}
planar_trace(f::FusionTree{I, N}, q::Index2Tuple{N₃, N₃}) where {I, N, N₃}
artin_braid
braid(f::FusionTree{I,N}, levels::NTuple{N,Int}, p::NTuple{N,Int}) where {I<:Sector,N}
permute(f::FusionTree{I,N}, p::NTuple{N,Int}) where {I<:Sector,N}
braid(f::FusionTree{I, N}, p::IndexTuple{N}, levels::IndexTuple{N}) where {I, N}
permute(f::FusionTree{I, N}, p::IndexTuple{N}) where {I, N}
```

These can be composed to implement elementary manipulations of fusion-splitting tree pairs,
according to the following methods

```julia
# TODO: add documentation for the following methods
```@docs
TensorKit.bendright
TensorKit.bendleft
TensorKit.foldright
TensorKit.foldleft
TensorKit.cycleclockwise
TensorKit.cycleanticlockwise
```

Finally, these are used to define large manipulations of fusion-splitting tree pairs, which
are then used in the index manipulation of `AbstractTensorMap` objects. The following methods
defined on fusion splitting tree pairs have an associated definition for tensors.

```@docs
repartition(::FusionTree{I,N₁}, ::FusionTree{I,N₂}, ::Int) where {I<:Sector,N₁,N₂}
transpose(::FusionTree{I}, ::FusionTree{I}, ::IndexTuple{N₁}, ::IndexTuple{N₂}) where {I<:Sector,N₁,N₂}
braid(::FusionTree{I}, ::FusionTree{I}, ::IndexTuple, ::IndexTuple, ::IndexTuple{N₁}, ::IndexTuple{N₂}) where {I<:Sector,N₁,N₂}
permute(::FusionTree{I}, ::FusionTree{I}, ::IndexTuple{N₁}, ::IndexTuple{N₂}) where {I<:Sector,N₁,N₂}
repartition(src::Union{FusionTreePair, FusionTreeBlock}, N::Int)
Base.transpose(src::Union{FusionTreePair, FusionTreeBlock}, p::Index2Tuple)
braid(src::Union{FusionTreePair, FusionTreeBlock}, p::Index2Tuple, levels::Index2Tuple)
permute(src::Union{FusionTreePair, FusionTreeBlock}, p::Index2Tuple)
```
11 changes: 6 additions & 5 deletions docs/src/man/sectors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,7 @@ value pair.
With the elementary `artin_braid`, we can then compute a more general braid. For this, we
provide an interface

[`braid(f::FusionTree{I,N}, levels::NTuple{N,Int}, permutation::NTuple{N,Int})`](@ref braid(f::FusionTree{I,N}, levels::NTuple{N,Int}, p::NTuple{N,Int}) where {I<:Sector,N})
[`braid(f::FusionTree{I, N}, permutation::IndexTuple{N}, levels::NTuple{N,Int})`](@ref braid(::FusionTree{I, N}, ::IndexTuple{N}, ::IndexTuple{N}) where {I, N})

where the braid is specified as a permutation, such that the new sector at position `i` was
originally at position `permutation[i]`, and where every uncoupled sector is also assigned
Expand All @@ -1065,7 +1065,7 @@ the braiding or its inverse (i.e. lines crossing over or under each other in the
notation) and the whole operation simplifies down to a permutation. We then also support
the interface

[`permute(f::FusionTree{I,N}, permutation::NTuple{N,Int})`](@ref permute(f::FusionTree{I,N}, p::NTuple{N,Int}) where {I<:Sector,N})
[`permute(f::FusionTree{I, N}, permutation::IndexTuple{N})`](@ref permute(::FusionTree{I, N}, ::IndexTuple{N}) where {I, N})

Other manipulations which are sometimes needed are

Expand Down Expand Up @@ -1159,7 +1159,8 @@ the splitting tree.

The `FusionTree` interface to duality and line bending is given by

[`repartition(f1::FusionTree{I,N₁}, f2::FusionTree{I,N₂}, N::Int)`](@ref repartition)
[`repartition(f::FusionTreePair{I,N₁,N₂}, N::Int)`](@ref repartition(::Union{FusionTreePair,
FusionTreeBlock}, ::Int))

which takes a splitting tree `f1` with `N₁` outgoing sectors, a fusion tree `f2` with `N₂`
incoming sectors, and applies line bending such that the resulting splitting and fusion
Expand All @@ -1184,7 +1185,7 @@ With this basic function, we can now perform arbitrary combinations of braids or
permutations with line bendings, to completely reshuffle where sectors appear. The
interface provided for this is given by

[`braid(f1::FusionTree{I,N₁}, f2::FusionTree{I,N₂}, levels1::NTuple{N₁,Int}, levels2::NTuple{N₂,Int}, p1::NTuple{N₁′,Int}, p2::NTuple{N₂′,Int})`](@ref braid(::FusionTree{I}, ::FusionTree{I}, ::IndexTuple, ::IndexTuple, ::IndexTuple{N₁}, ::IndexTuple{N₂}) where {I<:Sector,N₁,N₂})
[`braid((f₁, f₂)::FusionTreePair, (p1, p2)::Index2Tuple, (levels1, levels2)::Index2Tuple)`](@ref braid(::TensorKit.FusionTreePair, ::Index2Tuple, ::Index2Tuple))

where we now have splitting tree `f1` with `N₁` outgoing sectors, a fusion tree `f2` with
`N₂` incoming sectors, `levels1` and `levels2` assign a level or depth to the corresponding
Expand All @@ -1211,7 +1212,7 @@ As before, there is a simplified interface for the case where
`BraidingStyle(I) isa SymmetricBraiding` and the levels are not needed. This is simply
given by

[`permute(f1::FusionTree{I,N₁}, f2::FusionTree{I,N₂}, p1::NTuple{N₁′,Int}, p2::NTuple{N₂′,Int})`](@ref permute(::FusionTree{I}, ::FusionTree{I}, ::IndexTuple{N₁}, ::IndexTuple{N₂}) where {I<:Sector,N₁,N₂})
[`permute((f₁, f₂)::FusionTreePair, (p1, p2)::Index2Tuple)`](@ref permute(::Union{FusionTreePair, FusionTreeBlock}, ::Index2Tuple))

The `braid` and `permute` routines for double fusion trees will be the main access point for
corresponding manipulations on tensors. As a consequence, results from this routine are
Expand Down
17 changes: 15 additions & 2 deletions src/TensorKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ using OhMyThreads
using ScopedValues

using TensorKitSectors
import TensorKitSectors: dim, BraidingStyle, FusionStyle, ⊠, ⊗
import TensorKitSectors: dual, type_repr
import TensorKitSectors: dim, BraidingStyle, FusionStyle, ⊠, ⊗, ×
import TensorKitSectors: dual, type_repr, fusiontensor
import TensorKitSectors: twist

using Base: @boundscheck, @propagate_inbounds, @constprop,
Expand Down Expand Up @@ -215,6 +215,19 @@ function set_num_transformer_threads(n::Int)
return TRANSFORMER_THREADS[] = n
end

const TREEMANIPULATION_THREADS = Ref(1)

get_num_manipulation_threads() = TREEMANIPULATION_THREADS[]

function set_num_manipulation_threads(n::Int)
N = Base.Threads.nthreads()
if n > N
n = N
Strided._set_num_threads_warn(n)
end
return TREEMANIPULATION_THREADS[] = n
end

# Definitions and methods for tensors
#-------------------------------------
# general definitions
Expand Down
17 changes: 16 additions & 1 deletion src/auxiliary/auxiliary.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ function permutation2swaps(perm)
return swaps
end

# one-argument version: check whether `p` is a cyclic permutation (of `1:length(p)`)
function iscyclicpermutation(p)
N = length(p)
@inbounds for i in 1:N
p[mod1(i + 1, N)] == mod1(p[i] + 1, N) || return false
end
return true
end
# two-argument version: check whether `v1` is a cyclic permutation of `v2`
function iscyclicpermutation(v1, v2)
length(v1) == length(v2) || return false
return iscyclicpermutation(indexin(v1, v2))
end

_kron(A, B, C, D...) = _kron(_kron(A, B), C, D...)
function _kron(A, B)
sA = size(A)
Expand Down Expand Up @@ -61,6 +75,7 @@ end
# used in indexmanipulations: avoids the overhead of Strided.jl
function _copyto!(A::StridedView{<:Any, 1}, B::StridedView{<:Any, 2})
length(A) == length(B) || throw(DimensionMismatch())
@assert A.op === identity

Adata = parent(A)
Astr = stride(A, 1)
Expand All @@ -73,7 +88,7 @@ function _copyto!(A::StridedView{<:Any, 1}, B::StridedView{<:Any, 2})
@inbounds for _ in axes(B, 2)
IB = IB_1
for _ in axes(B, 1)
Adata[IA += Astr] = Bdata[IB += Bstr[1]]
Adata[IA += Astr] = B.op(Bdata[IB += Bstr[1]])
end
IB_1 += Bstr[2]
end
Expand Down
Loading
Loading