Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f829452
bump compat TKS
borisdevos Dec 15, 2025
a509cca
export more sectors + fusiontensor
borisdevos Dec 15, 2025
4c96418
more exports
borisdevos Dec 15, 2025
7890266
expand diagonal space list
borisdevos Dec 19, 2025
ae3939f
expand sectorlist and spacelist
borisdevos Dec 19, 2025
615226e
change A4 V1 space for factorization tests (hermitian and posdef check)
borisdevos Dec 19, 2025
3cb49d4
add A4 spaces to tensors spacelist
borisdevos Dec 19, 2025
8cc3bd1
Merge branch 'main' of https://github.com/Jutho/TensorKit.jl into bd/…
borisdevos Mar 13, 2026
02ea357
edit sectors and spaces
borisdevos Mar 13, 2026
1e1296f
fix foldright
borisdevos Mar 13, 2026
5d62645
remove `target` and `source`
borisdevos Mar 13, 2026
095b089
add spaces to cuda tests
borisdevos Mar 13, 2026
91c44fd
add braiding condition to insertat test
borisdevos Mar 13, 2026
e82683c
add spaces to diagonal and factorisation tests
borisdevos Mar 13, 2026
52e7772
add spaces to tensor tests + additional tests + make costly tests les…
borisdevos Mar 13, 2026
7ee5345
remove `VectorDict`
borisdevos Mar 13, 2026
62a0342
format
borisdevos Mar 13, 2026
d5498c4
Merge branch 'main' of https://github.com/Jutho/TensorKit.jl into bd/…
borisdevos Apr 1, 2026
8c84bbf
small change
borisdevos Apr 1, 2026
e8f245c
missing variables
borisdevos Apr 1, 2026
dd747ff
more missing exports
borisdevos Apr 2, 2026
2eba537
Merge branch 'main' of https://github.com/Jutho/TensorKit.jl into bd/…
borisdevos Apr 20, 2026
78f427d
exports
borisdevos Apr 20, 2026
455cffc
deal with bad merge
borisdevos Apr 20, 2026
d6c6309
Merge branch 'main' into bd/codecoverage
lkdvos Apr 20, 2026
a742745
move around export + add another missing one
borisdevos Apr 21, 2026
82f7645
Merge branch 'bd/codecoverage' of https://github.com/Jutho/TensorKit.…
borisdevos Apr 21, 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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Random = "1"
SafeTestsets = "0.1"
ScopedValues = "1.3.0"
Strided = "2"
TensorKitSectors = "0.3.5"
TensorKitSectors = "0.3.7"
TensorOperations = "5.1"
Test = "1"
TestExtras = "0.2,0.3"
Expand Down
10 changes: 6 additions & 4 deletions src/TensorKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ module TensorKit
# Exports
#---------
# Reexport common sector types:
export Sector, AbstractIrrep, Irrep
export Sector, AbstractIrrep, Irrep, GroupElement, TimeReversed
export FusionStyle, UniqueFusion, MultipleFusion, MultiplicityFreeFusion, SimpleFusion, GenericFusion
export UnitStyle, SimpleUnit, GenericUnit
export BraidingStyle, SymmetricBraiding, Bosonic, Fermionic, Anyonic, NoBraiding, HasBraiding
export Trivial, Z2Irrep, Z3Irrep, Z4Irrep, ZNIrrep, U1Irrep, SU2Irrep, CU1Irrep
export Trivial, Z2Irrep, Z3Irrep, Z4Irrep, ZNIrrep, LargeZNIrrep
export ZNElement, Z2Element, Z3Element, Z4Element, DNIrrep, A4Irrep, U1Irrep, SU2Irrep, CU1Irrep
export ProductSector, TimeReversed
export FermionParity, FermionNumber, FermionSpin
export FibonacciAnyon, IsingAnyon, IsingBimodule
Expand Down Expand Up @@ -42,7 +43,8 @@ export infimum, supremum, isisomorphic, ismonomorphic, isepimorphic
# Reexport methods for sectors and properties thereof
export sectortype, sectors, hassector
export unit, rightunit, leftunit, allunits, isunit, otimes
export Nsymbol, Fsymbol, Rsymbol, Bsymbol, frobenius_schur_phase, frobenius_schur_indicator, twist, sectorscalartype, deligneproduct
export Nsymbol, Fsymbol, Rsymbol, Bsymbol, frobenius_schur_phase, frobenius_schur_indicator, twist, fusiontensor
export sectorscalartype, deligneproduct

# Export methods for fusion trees
export fusiontrees, braid, permute, transpose
Expand All @@ -52,7 +54,7 @@ export fusiontrees, braid, permute, transpose

# some unicode
export ⊕, ⊗, ⊖, ×, ⊠, ℂ, ℝ, ℤ, ←, →, ≾, ≿, ≅, ≺, ≻
export ℤ₂, ℤ₃, ℤ₄, U₁, SU, SU₂, CU₁
export ℤ₂, ℤ₃, ℤ₄, D₃, D₄, A₄, U₁, SU, SU₂, CU₁
export fℤ₂, fU₁, fSU₂
export ℤ₂Space, ℤ₃Space, ℤ₄Space, U₁Space, CU₁Space, SU₂Space

Expand Down
78 changes: 0 additions & 78 deletions src/auxiliary/dicts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,84 +21,6 @@ Base.get(d::SingletonDict, key, default) = isequal(d.key, key) ? d.value : defau

Base.iterate(d::SingletonDict, s = true) = s ? ((d.key => d.value), false) : nothing

struct VectorDict{K, V} <: AbstractDict{K, V}
keys::Vector{K}
values::Vector{V}
end
VectorDict{K, V}() where {K, V} = VectorDict{K, V}(Vector{K}(), Vector{V}())
VectorDict() = VectorDict{Any, Any}()

function VectorDict{K, V}(kvs) where {K, V}
keys = Vector{K}()
values = Vector{V}()
if Base.IteratorSize(kv) !== SizeUnknown()
sizehint!(keys, length(kvs))
sizehint!(values, length(kvs))
end
for (k, v) in kvs
push!(keys, k)
push!(values, v)
end
return VectorDict{K, V}(keys, values)
end
VectorDict(kv1::Pair{K, V}, kvs::Pair{K, V}...) where {K, V} = VectorDict{K, V}((kv1, kvs...))
VectorDict(g::Base.Generator) = VectorDict(g...)

Base.length(d::VectorDict) = length(d.keys)
function Base.sizehint!(d::VectorDict, newsz)
(sizehint!(d.keys, newsz); sizehint!(d.values, newsz); return d)
end

@propagate_inbounds getpair(d::VectorDict, i::Integer) = d.keys[i] => d.values[i]

Base.copy(d::VectorDict) = VectorDict(copy(d.keys), copy(d.values))
Base.empty(::VectorDict, ::Type{K}, ::Type{V}) where {K, V} = VectorDict{K, V}()
Base.empty!(d::VectorDict) = (empty!(d.keys); empty!(d.values); return d)

function Base.delete!(d::VectorDict, key)
i = findfirst(isequal(key), d.keys)
if !(i === nothing || i == 0)
deleteat!(d.keys, i)
deleteat!(d.values, i)
end
return d
end

Base.keys(d::VectorDict) = d.keys
Base.values(d::VectorDict) = d.values
Base.haskey(d::VectorDict, key) = key in d.keys
function Base.getindex(d::VectorDict, key)
i = findfirst(isequal(key), d.keys)
@inbounds begin
return i !== nothing ? d.values[i] : throw(KeyError(key))
end
end
function Base.setindex!(d::VectorDict, v, key)
i = findfirst(isequal(key), d.keys)
if i === nothing
push!(d.keys, key)
push!(d.values, v)
else
d.values[i] = v
end
return d
end

function Base.get(d::VectorDict, key, default)
i = findfirst(isequal(key), d.keys)
@inbounds begin
return i !== nothing ? d.values[i] : default
end
end

function Base.iterate(d::VectorDict, s = 1)
@inbounds if s > length(d)
return nothing
else
return (d.keys[s] => d.values[s]), s + 1
end
end

struct SortedVectorDict{K, V} <: AbstractDict{K, V}
keys::Vector{K}
values::Vector{V}
Expand Down
18 changes: 15 additions & 3 deletions src/fusiontrees/manipulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,21 @@ function foldright(f₁::FusionTree{I, N₁}, f₂::FusionTree{I, N₂}) where {
isdual = Base.tail(f₁.isdual)
if FusionStyle(I) isa UniqueFusion
c = first(c1 ⊗ c2)
fl = FusionTree{I}(Base.tail(f₁.uncoupled), c, Base.tail(f₁.isdual))
fr = FusionTree{I}((c1, f₂.uncoupled...), c, (!isduala, f₂.isdual...))
return fusiontreedict(I)((fl, fr) => factor)
cvalid = N₁ == 1 ? leftunit(c1) : only(⊗(uncoupled...))
@assert c == cvalid
fc = FusionTree((c1, c2), c, (!isduala, false))
fl′, coeff1 = only(insertat(fc, 2, f₁)) # this coeff is not always 1
N₁ > 1 && @assert isunit(fl′.innerlines[1])

coupled = fl′.coupled
uncoupled = Base.tail(Base.tail(fl′.uncoupled))
isdual = Base.tail(Base.tail(fl′.isdual))
inner = N₁ <= 3 ? () : Base.tail(Base.tail(fl′.innerlines))
vertices = N₁ <= 2 ? () : Base.tail(Base.tail(fl′.vertices))
fl = FusionTree{I}(uncoupled, coupled, isdual, inner, vertices)
fr, coeff2 = only(insertat(fc, 2, f₂)) # same here
coeff = factor * coeff1 * conj(coeff2)
return fusiontreedict(I)((fl, fr) => coeff)
else
hasmultiplicities = FusionStyle(a) isa GenericFusion
local newtrees
Expand Down
2 changes: 0 additions & 2 deletions src/tensors/abstracttensor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ See also [`domain`](@ref) and [`space`](@ref).

codomain(t::AbstractTensorMap) = codomain(space(t))
codomain(t::AbstractTensorMap, i) = codomain(t)[i]
target(t::AbstractTensorMap) = codomain(t) # categorical terminology

@doc """
domain(t::AbstractTensorMap{T,S,N₁,N₂}) -> ProductSpace{S,N₂}
Expand All @@ -226,7 +225,6 @@ See also [`codomain`](@ref) and [`space`](@ref).

domain(t::AbstractTensorMap) = domain(space(t))
domain(t::AbstractTensorMap, i) = domain(t)[i]
source(t::AbstractTensorMap) = domain(t) # categorical terminology

@doc """
numout(x) -> Int
Expand Down
8 changes: 4 additions & 4 deletions test/cuda/factorizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ using .TestSetup
spacelist = if get(ENV, "CI", "false") == "true"
println("Detected running on CI")
if Sys.iswindows()
(Vtr, Vℤ₃, VU₁, VfU₁, VCU₁, VSU₂, VIB_diag)
(Vtr, Vℤ₃, VA₄, Vfib, VU₁, VfU₁, VCU₁, VSU₂, VIB_diag)
elseif Sys.isapple()
(Vtr, Vℤ₃, VfU₁, VfSU₂, VIB_M)
(Vtr, Vℤ₃, VA₄, Vfib, VfU₁, VfSU₂, VIB_M)
else
(Vtr, VU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
(Vtr, VA₄, VU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
end
else
(Vtr, Vℤ₃, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
(Vtr, Vℤ₃, VA₄, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
end

eltypes = (Float32, ComplexF64)
Expand Down
12 changes: 6 additions & 6 deletions test/cuda/tensors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ using CUDA: rand as curand, rand! as curand!, randn as curandn, randn! as curand
@isdefined(TestSetup) || include("../setup.jl")
using .TestSetup

for V in (Vtr, Vℤ₂, Vfℤ₂, Vℤ₃, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂) #, VSU₃)
for V in (Vtr, Vℤ₂, Vfℤ₂, Vℤ₃, VA₄, Vfib, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂) #, VSU₃)
V1, V2, V3, V4, V5 = V
@assert V3 * V4 * V2 ≿ V1' * V5' # necessary for leftorth tests
@assert V3 * V4 ≾ V1' * V2' * V5' # necessary for rightorth tests
Expand All @@ -23,17 +23,17 @@ spacelist = try
if ENV["CI"] == "true"
println("Detected running on CI")
if Sys.iswindows()
(Vtr, Vℤ₂, Vfℤ₂, Vℤ₃, VU₁, VfU₁, VCU₁, VSU₂)
(Vtr, Vℤ₂, Vfℤ₂, Vℤ₃, VA₄, VU₁, VfU₁, VCU₁, VSU₂)
elseif Sys.isapple()
(Vtr, Vℤ₂, Vfℤ₂, Vℤ₃, VfU₁, VfSU₂) #, VSU₃)
(Vtr, Vℤ₂, Vfℤ₂, Vℤ₃, VA₄, Vfib, VfU₁, VfSU₂) #, VSU₃)
else
(Vtr, Vℤ₂, Vfℤ₂, VU₁, VCU₁, VSU₂, VfSU₂) #, VSU₃)
(Vtr, Vℤ₂, Vfℤ₂, VA₄, Vfib, VU₁, VCU₁, VSU₂, VfSU₂) #, VSU₃)
end
else
(Vtr, VU₁, VSU₂, Vfℤ₂)
(Vtr, VU₁, VSU₂, Vfℤ₂, VA₄)
end
catch
(Vtr, Vℤ₂, Vfℤ₂, Vℤ₃, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂) #, VSU₃)
(Vtr, Vℤ₂, Vfℤ₂, Vℤ₃, VA₄, Vfib, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂) #, VSU₃)
end

for V in spacelist
Expand Down
48 changes: 39 additions & 9 deletions test/setup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ function randsector(::Type{I}) where {I <: Sector}
return a
end
function hasfusiontensor(I::Type{<:Sector})
isa(UnitStyle(I), GenericUnit) && return false
try
TensorKit.fusiontensor(unit(I), unit(I), unit(I))
u = first(allunits(I))
TensorKit.fusiontensor(u, u, u)
return true
catch e
if e isa MethodError
Expand Down Expand Up @@ -145,14 +145,30 @@ function test_dim_isapprox(V::ProductSpace, d::Int)
return @test max(0, d - dim_c_max) ≤ dim(V) ≤ d + dim_c_max
end

sectorlist = (
uniquefusionsectorlist = (
Z2Irrep, Z3Irrep, Z4Irrep, Z3Irrep ⊠ Z4Irrep,
U1Irrep, CU1Irrep, SU2Irrep,
FermionParity, FermionParity ⊠ FermionParity,
FermionParity ⊠ U1Irrep ⊠ SU2Irrep, FermionParity ⊠ SU2Irrep ⊠ SU2Irrep, # Hubbard-like
FibonacciAnyon, IsingAnyon,
Z2Irrep ⊠ FibonacciAnyon ⊠ FibonacciAnyon,
U1Irrep, FermionParity, FermionParity ⊠ FermionParity, FermionNumber,
Z3Element{1}, Z4Element{2}, ZNElement{5, 2},
)
simplefusionsectorlist = (
CU1Irrep, SU2Irrep, FibonacciAnyon, IsingAnyon,
FermionParity ⊠ U1Irrep ⊠ SU2Irrep, FermionParity ⊠ SU2Irrep ⊠ SU2Irrep,
Z3Element{1} ⊠ FibonacciAnyon ⊠ FibonacciAnyon,
)
genericfusionsectorlist = (
A4Irrep, A4Irrep ⊠ FermionParity, A4Irrep ⊠ SU2Irrep,
A4Irrep ⊠ Z3Element{2}, A4Irrep ⊠ A4Irrep,
)
multifusionsectorlist = (
IsingBimodule, IsingBimodule ⊠ SU2Irrep, IsingBimodule ⊠ IsingBimodule,
IsingBimodule ⊠ Z3Element{1}, IsingBimodule ⊠ FibonacciAnyon ⊠ A4Irrep,
)

sectorlist = (
uniquefusionsectorlist...,
simplefusionsectorlist...,
genericfusionsectorlist...,
multifusionsectorlist...,
Comment thread
lkdvos marked this conversation as resolved.
)

# spaces
Expand All @@ -178,6 +194,20 @@ Vℤ₃ = (
Vect[Z3Irrep](0 => 1, 1 => 2, 2 => 3),
Vect[Z3Irrep](0 => 1, 1 => 3, 2 => 3)',
)
VZ2ω = (
Vect[Z2Element{1}](0 => 2, 1 => 1),
Vect[Z2Element{1}](0 => 1, 1 => 2)',
Vect[Z2Element{1}](0 => 2, 1 => 1)',
Vect[Z2Element{1}](0 => 2, 1 => 3),
Vect[Z2Element{1}](0 => 2, 1 => 5),
)
VA₄ = (
Vect[A4Irrep](0 => 1, 1 => 1, 2 => 1, 3 => 3), # dim large enough for truncated factorization tests
Vect[A4Irrep](0 => 1, 1 => 2, 2 => 1, 3 => 1),
Vect[A4Irrep](0 => 1, 1 => 1, 2 => 2, 3 => 1)',
Vect[A4Irrep](0 => 1, 1 => 2, 2 => 2, 3 => 2),
Vect[A4Irrep](0 => 1, 1 => 2, 2 => 2, 3 => 3)',
)
VU₁ = (
Vect[U1Irrep](0 => 1, 1 => 2, -1 => 2),
Vect[U1Irrep](0 => 3, 1 => 1, -1 => 1),
Expand Down Expand Up @@ -224,7 +254,7 @@ VSU₂U₁ = (
Vect[SU2Irrep ⊠ U1Irrep]((0, 0) => 1, (1 // 2, 1) => 1)',
)
Vfib = (
Vect[FibonacciAnyon](:I => 1, :τ => 1),
Vect[FibonacciAnyon](:I => 2, :τ => 1),
Vect[FibonacciAnyon](:I => 1, :τ => 2)',
Vect[FibonacciAnyon](:I => 3, :τ => 2)',
Vect[FibonacciAnyon](:I => 2, :τ => 3),
Expand Down
2 changes: 1 addition & 1 deletion test/symmetries/fusiontrees.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ using .TestSetup
@test length(TK.insertat(f1b, 1, f1a)) == 1
@test first(TK.insertat(f1b, 1, f1a)) == (f1 => 1)

if UnitStyle(I) isa SimpleUnit
if UnitStyle(I) isa SimpleUnit && BraidingStyle(I) isa HasBraiding
levels = ntuple(identity, N)
function _reinsert_partial_tree(t, f)
(t′, c′) = first(TK.insertat(t, 1, f))
Expand Down
4 changes: 4 additions & 0 deletions test/tensors/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ using TensorKit
diagspacelist = (
(ℂ^4)',
Vect[Z2Irrep](0 => 2, 1 => 3),
Vect[Z3Element{1}](0 => 2, 1 => 3, 2 => 1),
Vect[A4Irrep](0 => 1, 1 => 2, 2 => 2, 3 => 2),
Vect[FermionNumber](0 => 2, 1 => 2, -1 => 1),
Vect[SU2Irrep](0 => 2, 1 => 1)',
Vect[FibonacciAnyon](:I => 2, :τ => 2),
Vect[Z3Element{1}](0 => 2, 1 => 2, 2 => 1),
Vect[IsingBimodule](C0 => 2, C1 => 3),
)

@testset "DiagonalTensor with domain $V" for V in diagspacelist
Expand Down
10 changes: 5 additions & 5 deletions test/tensors/factorizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ spacelist = try
if ENV["CI"] == "true"
println("Detected running on CI")
if Sys.iswindows()
(Vtr, Vℤ₃, VU₁, VfU₁, VCU₁, VSU₂, VIB_diag)
(Vtr, Vℤ₃, VA₄, VU₁, VfU₁, VZ2ω, VCU₁, VSU₂, VIB_diag)
elseif Sys.isapple()
(Vtr, Vℤ₃, VfU₁, VfSU₂, VIB_M)
(Vtr, Vℤ₃, VA₄, Vfib, VZ2ω, VfU₁, VfSU₂, VIB_M)
else
(Vtr, VU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
(Vtr, VA₄, Vfib, VU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
end
else
(Vtr, Vℤ₃, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
(Vtr, Vℤ₃, VA₄, Vfib, VZ2ω, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
end
catch
(Vtr, Vℤ₃, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
(Vtr, Vℤ₃, VA₄, Vfib, VZ2ω, VU₁, VfU₁, VCU₁, VSU₂, VfSU₂, VIB_diag, VIB_M)
end

eltypes = (Float32, ComplexF64)
Expand Down
Loading
Loading