Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ RationalRoots = "0.1 - 0.2"
Scratch = "1"
SparseArrayKit = "0.4"
TensorKit = "0.16.4"
TensorKitSectors = "0.3.5"
TensorKitSectors = "0.3.7"
TensorOperations = "5"
Test = "1"
TestExtras = "0.3"
Expand All @@ -54,3 +54,6 @@ TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6"

[targets]
test = ["Test", "Random", "Combinatorics", "TestExtras", "TensorKit", "TupleTools", "Latexify", "Aqua"]

[sources]
TensorKitSectors = {url = "https://github.com/QuantumKitHub/TensorKitSectors.jl", rev = "main"}
4 changes: 2 additions & 2 deletions src/clebschgordan.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ end
end

function _CGC(T::Type{<:Real}, s1::I, s2::I, s3::I) where {I <: SUNIrrep}
if isone(s1)
if isunit(s1)
@assert s2 == s3
CGC = trivial_CGC(T, s2, true)
elseif isone(s2)
elseif isunit(s2)
@assert s1 == s3
CGC = trivial_CGC(T, s1, false)
else
Expand Down
47 changes: 32 additions & 15 deletions src/sector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,14 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I <
return LRU{K, V}(; maxsize = 10^5)
end
return get!(cache, key) do
return _Fsymbol(a, b, c, d, e, f)
return TensorKitSectors.Fsymbol_from_fusiontensor(a, b, c, d, e, f)
end
end
function _Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I <: SUNIrrep}
N1 = Nsymbol(a, b, e)
N2 = Nsymbol(e, c, d)
N3 = Nsymbol(b, c, f)
N4 = Nsymbol(a, f, d)

(N1 == 0 || N2 == 0 || N3 == 0 || N4 == 0) &&
return fill(zero(fusionscalartype(I)), N1, N2, N3, N4)
function TensorKitSectors.Fsymbol_from_fusiontensor(
a::I, b::I, c::I, d::I, e::I, f::I
) where {I <: SUNIrrep}
Nabe, Necd, Nbcd, Nafd = Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)
iszero(Nabe * Necd * Nbcd * Nafd) && return zeros(fusionscalartype(I), Nabe, Necd, Nbcd, Nafd)

# computing first diagonal element
A = fusiontensor(a, b, e)
Expand All @@ -86,6 +83,28 @@ function _Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I <: SUNIrrep}
return Array(F)
end

# remove the view calls
function TensorKitSectors.Asymbol_from_fusiontensor(a::I, b::I, c::I) where {I <: SUNIrrep}
Nabc = Nsymbol(a, b, c)
iszero(Nabc) && return zeros(fusionscalartype(typeof(a)), Nabc, Nabc)

C1 = fusiontensor(a, b, c)[:, 1, :, :]
C2 = fusiontensor(dual(a), c, b)[:, :, 1, :]
Za = sqrtdim(a) * fusiontensor(a, dual(a), leftunit(a))[:, :, 1, 1]
@tensor A[-1, -2] := sqrtdim(b) / sqrtdim(c) * conj(Za[1, 2]) * C1[1, 3, -1] * C2[2, 3, -2]
return Array(A)
end
function TensorKitSectors.Bsymbol_from_fusiontensor(a::I, b::I, c::I) where {I <: SUNIrrep}
Nabc = Nsymbol(a, b, c)
iszero(Nabc) && return zeros(fusionscalartype(typeof(a)), Nabc, Nabc)

C1 = fusiontensor(a, b, c)[1, :, :, :]
C2 = fusiontensor(c, dual(b), a)[:, :, 1, :]
Zb = sqrtdim(b) * fusiontensor(b, dual(b), leftunit(b))[:, :, 1, 1]
@tensor B[-1, -2] := sqrtdim(a) / sqrtdim(c) * conj(Zb[1, 2]) * C1[1, 3, -1] * C2[3, 2, -2]
return Array(B)
end

const RCACHE = LRU{Int, Any}(; maxsize = 10)
TensorKitSectors.braidingscalartype(::Type{<:SUNIrrep}) = Float64
function TensorKitSectors.Rsymbol(a::I, b::I, c::I) where {I <: SUNIrrep}
Expand All @@ -96,14 +115,12 @@ function TensorKitSectors.Rsymbol(a::I, b::I, c::I) where {I <: SUNIrrep}
return LRU{K, V}(; maxsize = 10^5)
end
return get!(cache, key) do
return _Rsymbol(a, b, c)
return TensorKitSectors.Rsymbol_from_fusiontensor(a, b, c)
end
end
function _Rsymbol(a::I, b::I, c::I) where {I <: SUNIrrep}
N1 = Nsymbol(a, b, c)
N2 = Nsymbol(b, a, c)

(N1 == 0 || N2 == 0) && return fill(zero(braidingscalartype(I)), N1, N2)
function TensorKitSectors.Rsymbol_from_fusiontensor(a::I, b::I, c::I) where {I <: SUNIrrep}
Nabc = Nsymbol(a, b, c)
iszero(Nabc) && return fill(zero(braidingscalartype(I)), Nabc, Nabc)

A = fusiontensor(a, b, c)[:, :, 1, :]
B = fusiontensor(b, a, c)[:, :, 1, :]
Expand Down
1 change: 0 additions & 1 deletion test/clebschgordan.jl

This file was deleted.

2 changes: 1 addition & 1 deletion test/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ using Latexify: latexify, @L_str
@test I1.I == @constinferred weight(I1)

@test inv(cartanmatrix(I1)) ≈ inverse_cartanmatrix(I1)
@test SUNIrrep{N}("1") === one(SUNIrrep{N})
@test SUNIrrep{N}("1") === unit(SUNIrrep{N})
end

@timedtestset "Illegal constructors" begin
Expand Down
51 changes: 30 additions & 21 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
using Test
using TestExtras
using Aqua
using Random
using TensorKitSectors
using TensorKit
using SUNRepresentations
using Combinatorics
using TensorKit
using TensorKit: ProductSector, fusiontensor, pentagon_equation, hexagon_equation,
FusionTreeBlock
using TensorOperations
using Base.Iterators: take, product
using Base.Iterators: take
using SparseArrayKit: SparseArray
using LinearAlgebra: LinearAlgebra

Expand All @@ -18,44 +18,53 @@ const TK = TensorKit
_isone(x; kwargs...) = isapprox(x, one(x); kwargs...)

Random.seed!(1234)
Ti = time()

# sector tests
testsuite_path = joinpath(
dirname(dirname(pathof(TensorKitSectors))), # TensorKitSectors root
"test", "testsuite.jl"
)
include(testsuite_path)
using .SectorTestSuite: randsector, smallset

smallset(::Type{I}) where {I <: Sector} = take(values(I), 5)
function smallset(::Type{ProductSector{Tuple{I1, I2}}}) where {I1, I2}
iter = product(smallset(I1), smallset(I2))
s = collect(i ⊠ j for (i, j) in iter if dim(i) * dim(j) <= 6)
return length(s) > 6 ? rand(s, 6) : s
function SectorTestSuite.smallset(::Type{I}) where {I <: SUNIrrep}
N = SUNRepresentations.rank(I)
return smallset(I, 5, 5 * N)
end
function smallset(::Type{ProductSector{Tuple{I1, I2, I3}}}) where {I1, I2, I3}
iter = product(smallset(I1), smallset(I2), smallset(I3))
s = collect(i ⊠ j ⊠ k for (i, j, k) in iter if dim(i) * dim(j) * dim(k) <= 6)
return length(s) > 6 ? rand(s, 6) : s
function SectorTestSuite.smallset(::Type{ProductSector{Tuple{I1, I2}}}) where {I1 <: SUNIrrep, I2 <: SUNIrrep}
s1 = smallset(I1)
s2 = smallset(I2)
N = SUNRepresentations.rank(I1)
return resize!(shuffle!([a ⊠ b for a in s1 for b in s2 if dim(a) * dim(b) <= 50 * N]), 5)
end
function randsector(::Type{I}) where {I <: Sector}
s = collect(smallset(I))
a = rand(s)
while a == one(a) # don't use trivial label
a = rand(s)

sectorlist = (SU3Irrep, SU4Irrep, SU5Irrep, SU3Irrep ⊠ SU3Irrep)
@testset "Sector tests" begin
for sector in sectorlist
SectorTestSuite.test_sector(sector)
end
return a
include("sectors.jl")
end

Ti = time()
module GenericTests
using Test
using TestExtras
using Random
using SUNRepresentations
using TensorKitSectors
include("generic.jl")
end

include("caching.jl")
@testset "Caching tests" begin
include("caching.jl")
end
include("casimir.jl")
sectorlist = (SU3Irrep, SU4Irrep, SU5Irrep, SU3Irrep ⊠ SU3Irrep)
include("sectors.jl")
sectorlist = (SU3Irrep, SU4Irrep, SU5Irrep)
include("fusiontrees.jl")

@testset "Aqua" verbose = true begin
using Aqua
# RationalRoots has ambiguities with Base/Core, so only test SUNRepresentations ambiguities
# Intentional piracy of Rep[SU{N}] etc
Aqua.test_all(SUNRepresentations; ambiguities = false, piracies = (; treat_as_own = [SU]))
Expand Down
95 changes: 2 additions & 93 deletions test/sectors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,109 +2,18 @@ for I in sectorlist
println("------------------------------------")
println("Sector $I")
println("------------------------------------")
ti = time()
@testset "Sector $I: Basic properties" begin
@testset "Sector $I: Additional basic properties" begin
s = (randsector(I), randsector(I), randsector(I))

mode_old = SUNRepresentations.display_mode("dimension")
for mode in ["dimension", "dynkin", "weight"]
SUNRepresentations.display_mode(mode)
@test eval(Meta.parse(sprint(show, s[1]))) == s[1]
end
SUNRepresentations.display_mode(mode_old)

@test @constinferred(hash(s[1])) == hash(deepcopy(s[1]))
@test @constinferred(one(s[1])) == @constinferred(one(I))
@constinferred dual(s[1])
@constinferred dim(s[1])
@constinferred frobenius_schur_phase(s[1])
@constinferred frobenius_schur_indicator(s[1])
@constinferred Nsymbol(s...)
@constinferred Rsymbol(s...)
@constinferred Bsymbol(s...)
@constinferred Fsymbol(s..., s...)
it = @constinferred s[1] ⊗ s[2]
@constinferred ⊗(s..., s...)
for i in 1:3
@test 1 == @constinferred Nsymbol(s[i], conj(s[i]), one(s[i]))
end
end
@timedtestset "Sector $I: Value iterator" begin
@test eltype(values(I)) == I
sprev = one(I)
for (i, s) in enumerate(values(I))
@test !isless(s, sprev) # confirm compatibility with sort order
@test s == @constinferred (values(I)[i])
@test TensorKit.findindex(values(I), s) == i
sprev = s
i >= 10 && break
end
@test one(I) == first(values(I))
@test (@constinferred TensorKit.findindex(values(I), one(I))) == 1
for s in smallset(I)
@test (@constinferred values(I)[TensorKit.findindex(values(I), s)]) == s
end
end
@timedtestset "Sector $I: fusion tensor and F-move and R-move" begin
for a in smallset(I), b in smallset(I)
for c in ⊗(a, b)
X1 = permutedims(fusiontensor(a, b, c), (2, 1, 3, 4))
X2 = fusiontensor(b, a, c)
l = dim(a) * dim(b) * dim(c)
R = LinearAlgebra.transpose(Rsymbol(a, b, c))
sz = (l, convert(Int, Nsymbol(a, b, c)))
@test reshape(X1, sz) ≈ reshape(X2, sz) * R
end
end
for a in smallset(I), b in smallset(I), c in smallset(I)
for e in ⊗(a, b), f in ⊗(b, c)
for d in intersect(⊗(e, c), ⊗(a, f))
X1 = fusiontensor(a, b, e)
X2 = fusiontensor(e, c, d)
Y1 = fusiontensor(b, c, f)
Y2 = fusiontensor(a, f, d)
@tensor f1[-1, -2, -3, -4] := conj(Y2[a, f, d, -4]) *
conj(Y1[b, c, f, -3]) *
X1[a, b, e, -1] * X2[e, c, d, -2]
f2 = Fsymbol(a, b, c, d, e, f) * dim(d)
@test isapprox(f1, f2; atol = 1000 * eps(), rtol = 1000 * eps())
end
end
end
end
@timedtestset "Sector $I: Unitarity of F-move" begin
for a in smallset(I), b in smallset(I), c in smallset(I), d in ⊗(a, b, c)
es = collect(intersect(⊗(a, b), map(dual, ⊗(c, dual(d)))))
fs = collect(intersect(⊗(b, c), map(dual, ⊗(dual(d), a))))
Fblocks = Vector{Any}()
for e in es, f in fs
Fs = Fsymbol(a, b, c, d, e, f)
push!(
Fblocks,
reshape(Fs, (size(Fs, 1) * size(Fs, 2), size(Fs, 3) * size(Fs, 4)))
)
end
F = hvcat(length(fs), Fblocks...)
@test F' * F ≈ one(F)
end
end
@testset "Sector $I: Pentagon equation" begin
for a in smallset(I), b in smallset(I), c in smallset(I), d in smallset(I)
@test pentagon_equation(a, b, c, d; atol = 1.0e-12, rtol = 1.0e-12)
end
end
@testset "Sector $I: Hexagon equation" begin
for a in smallset(I), b in smallset(I), c in smallset(I)
@test hexagon_equation(a, b, c; atol = 1.0e-12, rtol = 1.0e-12)
@test 1 == @constinferred Nsymbol(s[i], dual(s[i]), unit(s[i]))
end
end
tf = time()
printstyled(
"Finished sector $I tests in ",
string(round(tf - ti; sigdigits = 3)),
" seconds."; bold = true, color = Base.info_color()
)
println()

try
s = sprint(SUNRepresentations.cache_info)
Expand Down
Loading