Skip to content

Commit 876cbd6

Browse files
borisdevoslkdvos
andauthored
Make testsuite compatible with multifusion categories (#71)
* make testsuite compatible with multifusion cats * add unitarity test * change test to assert * clean up additional multifusion tests * typo * fix timereversed product sector values iteration * edit deligne product test * isingbimodule is not in base * fix `sectorscalartype` of product sector + bring back relevant test * remove `allunits` condition * edit iterating over time-reversed product scetor * make `smallset` type-stable * `random_fusion` vector output * relax default size for smallset * check colorings where relevant * rename unitarity test * fusiontensor edit * `eval_module` function for parse-show tests * format * remove commented code * remove eval_module * `can_fuse` for readability * value iterator suggestion * export `can_fuse` and remove unused import * bump version --------- Co-authored-by: Lukas Devos <ldevos98@gmail.com>
1 parent 0a6995d commit 876cbd6

5 files changed

Lines changed: 91 additions & 91 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "TensorKitSectors"
22
uuid = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f"
33
authors = ["Lukas Devos", "Jutho Haegeman"]
4-
version = "0.3.6"
4+
version = "0.3.7"
55

66
[deps]
77
HalfIntegers = "f0d1745a-41c9-11e9-1dd9-e5d34d218721"

test/multifusion.jl

Lines changed: 4 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ I = IsingBimodule
22
Istr = TensorKitSectors.type_repr(I)
33
@testset "$Istr sector" begin
44
@testset "Basic type properties" begin
5-
@test eval(Meta.parse(sprint(show, I))) == I
6-
@test eval(Meta.parse(TensorKitSectors.type_repr(I))) == I
7-
85
prodsec = I Z2Irrep
96
@test UnitStyle(prodsec) isa GenericUnit
107
@test FusionStyle(prodsec) isa SimpleFusion
@@ -23,13 +20,13 @@ Istr = TensorKitSectors.type_repr(I)
2320
s = rand((M, Mop, C, D))
2421

2522
@testset "Basic properties" begin
26-
@test @constinferred(unit(C1)) == @constinferred(leftunit(C1)) ==
27-
@constinferred(rightunit(C1))
23+
@test @testinferred(unit(C1)) == @testinferred(leftunit(C1)) ==
24+
@testinferred(rightunit(C1))
2825
@test unit(D1) == leftunit(D1) == rightunit(D1)
2926
@test unit(C1) == leftunit(M) == rightunit(Mop)
3027
@test unit(D1) == rightunit(M) == leftunit(Mop)
3128

32-
@test @constinferred(isunit(C0))
29+
@test @testinferred(isunit(C0))
3330
@test isunit(D0)
3431
@test !isunit(C1) && !isunit(D1) && !isunit(M) && !isunit(Mop)
3532

@@ -44,35 +41,7 @@ Istr = TensorKitSectors.type_repr(I)
4441
@test length(allunits(I I)) == 4
4542

4643
@test leftunit(M Mop) == C0 D0 == rightunit(Mop M)
47-
48-
@test eval(Meta.parse(sprint(show, s))) == s
49-
@test @constinferred(hash(s)) == hash(deepcopy(s))
50-
@constinferred dual(s)
51-
@test dual(dual(s)) == s
52-
@constinferred dim(s)
53-
@constinferred frobenius_schur_phase(s)
54-
@constinferred convert(IsingAnyon, s)
55-
56-
@constinferred Bsymbol(C, C, C)
57-
@constinferred Fsymbol(D, D, D, D, D, D)
58-
end
59-
60-
@testset "$Istr: Value iterator" begin
61-
@test eltype(values(I)) == I
62-
@test_throws ArgumentError unit(I)
63-
sprev = C0 # first in SectorValues
64-
for (i, s) in enumerate(values(I))
65-
@test !isless(s, sprev) # confirm compatibility with sort order
66-
@test s == @constinferred (values(I)[i])
67-
@test findindex(values(I), s) == i
68-
sprev = s
69-
i >= 10 && break
70-
end
71-
@test C0 == first(values(I))
72-
@test (@constinferred findindex(values(I), C0)) == 1
73-
for s in collect(values(I))
74-
@test (@constinferred values(I)[findindex(values(I), s)]) == s
75-
end
44+
@testinferred convert(IsingAnyon, s)
7645
end
7746

7847
@testset "$Istr: Printing and errors" begin
@@ -122,31 +91,4 @@ Istr = TensorKitSectors.type_repr(I)
12291

12392
@test_throws argerr Fsymbol(M, Mop, M, Mop, C, D)
12493
end
125-
126-
@testset "$Istr: Unitarity of F-move" begin
127-
objects = collect(values(I))
128-
for a in objects, b in objects, c in objects
129-
for d in (a, b, c)
130-
es = collect(intersect((a, b), map(dual, (c, dual(d)))))
131-
fs = collect(intersect((b, c), map(dual, (dual(d), a))))
132-
@test length(es) == length(fs)
133-
F = [Fsymbol(a, b, c, d, e, f) for e in es, f in fs]
134-
@test isapprox(F' * F, one(F); atol = 1.0e-12, rtol = 1.0e-12)
135-
end
136-
end
137-
end
138-
139-
@testset "$Istr: Triangle equation" begin
140-
for a in smallset(I), b in smallset(I)
141-
@test triangle_equation(a, b; atol = 1.0e-12, rtol = 1.0e-12)
142-
end
143-
end
144-
145-
@testset "$Istr: Pentagon equation" begin
146-
objects = collect(values(I))
147-
for a in objects, b in objects, c in objects, d in objects
148-
# compatibility checks built in Fsymbol
149-
@test pentagon_equation(a, b, c, d; atol = 1.0e-12, rtol = 1.0e-12)
150-
end
151-
end
15294
end

test/runtests.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const sectorlist = (
2323
ZNElement{6, 0}, ZNElement{6, 1}, ZNElement{6, 3},
2424
Z3Element{1} SU2Irrep,
2525
FibonacciAnyon Z4Element{3},
26+
IsingBimodule, IsingBimodule IsingBimodule, IsingBimodule Z2Irrep,
27+
IsingBimodule SU2Irrep, IsingBimodule FibonacciAnyon,
2628
TimeReversed{Z2Irrep},
2729
TimeReversed{Z3Irrep}, TimeReversed{Z4Irrep}, TimeReversed{A4Irrep},
2830
TimeReversed{U1Irrep}, TimeReversed{CU1Irrep}, TimeReversed{SU2Irrep},
@@ -85,8 +87,10 @@ end
8587
@testinferred I1 I2
8688
@test typeof(a b) == I1 I2
8789

88-
@test @testinferred(length(allunits(I1 I2))) == 1
89-
@test @testinferred(unit(I1 I2)) == leftunit(a b) == rightunit(a b)
90+
if UnitStyle(I1 I2) isa SimpleUnit
91+
@test @testinferred(length(allunits(I1 I2))) == 1
92+
@test @testinferred(unit(I1 I2)) == leftunit(a b) == rightunit(a b)
93+
end
9094
end
9195
@test @testinferred(Tuple(SU2Irrep(1) U1Irrep(0))) == (SU2Irrep(1), U1Irrep(0))
9296
@test @testinferred(length(FermionParity(1) SU2Irrep(1 // 2) U1Irrep(1))) == 3

test/sectors.jl

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,27 @@ using LinearAlgebra
33
using TensorKitSectors: TensorKitSectors as TKS
44

55
@testsuite "Basic properties" I -> begin
6-
s = (randsector(I), randsector(I), randsector(I))
7-
@test @testinferred(hash(s[1])) == hash(deepcopy(s[1]))
8-
@test @testinferred(unit(s[1])) == @testinferred(unit(I))
9-
@testinferred dual(s[1])
10-
@testinferred dim(s[1])
11-
@testinferred frobenius_schur_phase(s[1])
12-
@testinferred frobenius_schur_indicator(s[1])
13-
@testinferred Nsymbol(s...)
14-
@testinferred Asymbol(s...)
15-
B = @testinferred Bsymbol(s...)
16-
F = @testinferred Fsymbol(s..., s...)
6+
s = random_fusion(I, 2)
7+
sc = @testinferred(first((s...)))
8+
@test @testinferred(hash(sc)) == hash(deepcopy(sc))
9+
if UnitStyle(I) isa SimpleUnit
10+
@test @testinferred(unit(sc)) == @testinferred(unit(I))
11+
end
12+
@testinferred dual(sc)
13+
@testinferred dim(sc)
14+
@testinferred frobenius_schur_phase(sc)
15+
@testinferred frobenius_schur_indicator(sc)
16+
@testinferred((s..., s...))
17+
@testinferred Nsymbol(s..., sc)
18+
@testinferred Asymbol(s..., sc)
19+
B = @testinferred Bsymbol(s..., sc)
20+
s2 = random_fusion(I, 3)
21+
s2c = first((s2...))
22+
e, f = first((s2[1], s2[2])), first((s2[2], s2[3]))
23+
F = @testinferred Fsymbol(s2..., s2c, e, f)
1724
@test eltype(F) === @testinferred fusionscalartype(I)
1825
if BraidingStyle(I) isa HasBraiding
19-
R = @testinferred Rsymbol(s...)
26+
R = @testinferred Rsymbol(s..., sc)
2027
@test eltype(R) === @testinferred braidingscalartype(I)
2128
if FusionStyle(I) === SimpleFusion()
2229
@test typeof(R * F) <: @testinferred sectorscalartype(I)
@@ -30,8 +37,6 @@ using TensorKitSectors: TensorKitSectors as TKS
3037
@test eltype(F) <: @testinferred sectorscalartype(I)
3138
end
3239
end
33-
@testinferred(s[1] s[2])
34-
@testinferred((s..., s...))
3540
end
3641

3742
@testsuite "Show and parse" I -> begin
@@ -48,24 +53,25 @@ end
4853

4954
@testsuite "Value iterator" I -> begin
5055
@test eltype(values(I)) == I
51-
sprev = unit(I)
52-
for (i, s) in enumerate(values(I))
56+
sprev, rest = Iterators.peel(values(I))
57+
i = 1
58+
@test (@testinferred findindex(values(I), sprev)) == i
59+
for s in rest
60+
i += 1
5361
@test !isless(s, sprev)
5462
@test s == @testinferred(values(I)[i])
5563
@test findindex(values(I), s) == i
5664
sprev = s
5765
i >= 10 && break
5866
end
59-
@test unit(I) == first(values(I))
60-
@test length(allunits(I)) == 1
61-
@test (@testinferred findindex(values(I), unit(I))) == 1
6267
for s in smallset(I)
6368
@test (@testinferred values(I)[findindex(values(I), s)]) == s
6469
end
6570
end
6671

6772
@testsuite "Fusion and dimensions" I -> begin
6873
for a in smallset(I), b in smallset(I)
74+
can_fuse(a, b) || continue
6975
da = dim(a)
7076
db = dim(b)
7177
dc = sum(c -> dim(c) * Nsymbol(a, b, c), a b)
@@ -178,8 +184,12 @@ end
178184
end
179185

180186
@testsuite "Unitarity of F-move" I -> begin
181-
for a in smallset(I), b in smallset(I), c in smallset(I)
182-
@test F_unitarity_test(a, b, c; atol = 1.0e-12, rtol = 1.0e-12)
187+
for a in smallset(I), b in smallset(I)
188+
can_fuse(a, b) || continue
189+
for c in smallset(I)
190+
can_fuse(b, c) || continue
191+
@test F_unitarity_test(a, b, c; atol = 1.0e-12, rtol = 1.0e-12)
192+
end
183193
end
184194
end
185195

@@ -192,13 +202,21 @@ end
192202

193203
@testsuite "Triangle equation" I -> begin
194204
for a in smallset(I), b in smallset(I)
205+
can_fuse(a, b) || continue
195206
@test triangle_equation(a, b; atol = 1.0e-12, rtol = 1.0e-12)
196207
end
197208
end
198209

199210
@testsuite "Pentagon equation" I -> begin
200-
for a in smallset(I), b in smallset(I), c in smallset(I), d in smallset(I)
201-
@test pentagon_equation(a, b, c, d; atol = 1.0e-12, rtol = 1.0e-12)
211+
for a in smallset(I), b in smallset(I)
212+
can_fuse(a, b) || continue
213+
for c in smallset(I)
214+
can_fuse(b, c) || continue
215+
for d in smallset(I)
216+
can_fuse(c, d) || continue
217+
@test pentagon_equation(a, b, c, d; atol = 1.0e-12, rtol = 1.0e-12)
218+
end
219+
end
202220
end
203221
end
204222

test/testsuite.jl

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,23 @@ SectorTestSuite.test_sector(MySectorType)
2020
Additionally, this test suite exports the following convenience testing utilities:
2121
* [`smallset`](@ref)
2222
* [`randsector`](@ref)
23+
* [`random_fusion`](@ref)
2324
* [`hasfusiontensor`](@ref)
25+
* [`F_unitarity_test`](@ref)
2426
* [`R_unitarity_test`](@ref)
27+
* [`can_fuse`](@ref)
2528
"""
2629
module SectorTestSuite
2730

28-
export smallset, randsector, hasfusiontensor, F_unitarity_test, R_unitarity_test
31+
export smallset, randsector, random_fusion, hasfusiontensor, can_fuse
32+
export F_unitarity_test, R_unitarity_test
2933

3034
using Test
3135
using TestExtras
3236
using TensorKitSectors
3337
using TensorKitSectors: type_repr
3438
using Random
35-
using Base.Iterators: take, product
39+
using Base.Iterators: take
3640

3741
const tests = Dict()
3842

@@ -86,9 +90,41 @@ function randsector(::Type{I}) where {I <: Sector}
8690
end
8791
randsector(::Type{I}) where {I <: Union{Trivial, PlanarTrivial}} = unit(I)
8892

93+
"""
94+
can_fuse(a::I, b::I) where {I <: Sector}
95+
96+
Returns a boolean indicating whether the fusion of `a` and `b` is allowed,
97+
i.e. whether there exists a sector `c` such that `c ∈ ⊗(a, b)`.
98+
"""
99+
can_fuse(a::I, b::I) where {I <: Sector} = !isempty((a, b))
100+
101+
"""
102+
random_fusion(I::Type, N::Int)
103+
104+
Returns a vector of `N` random sectors from `I` that have a non-empty coupled sector.
105+
Compatible with any `Sector` type, including those with `UnitStyle(I) == GenericUnit()`.
106+
"""
107+
function random_fusion(I::Type{<:Sector}, N::Int)
108+
vec = Vector{I}(undef, N)
109+
vec[1] = randsector(I)
110+
N == 1 && return vec
111+
for i in 2:N
112+
s = randsector(I)
113+
sprev = vec[i - 1]
114+
counter = 0
115+
while !can_fuse(sprev, s) && counter < 20
116+
counter += 1
117+
s = (counter < 20) ? randsector(I) : rightunit(sprev)
118+
end
119+
vec[i] = s
120+
end
121+
return vec
122+
end
123+
89124
function hasfusiontensor(I::Type{<:Sector})
90125
try
91-
fusiontensor(unit(I), unit(I), unit(I))
126+
u = first(allunits(I))
127+
fusiontensor(u, u, u)
92128
return true
93129
catch e
94130
if e isa MethodError

0 commit comments

Comments
 (0)