|
| 1 | +I = IsingBimod |
| 2 | +Istr = TensorKitSectors.type_repr(I) |
| 3 | +@testset "$Istr sector" begin |
| 4 | + @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 | + end |
| 8 | + |
| 9 | + M = IsingBimod(1, 2, 0) |
| 10 | + Mop = IsingBimod(2, 1, 0) |
| 11 | + C0 = IsingBimod(1, 1, 0) |
| 12 | + C1 = IsingBimod(1, 1, 1) |
| 13 | + D0 = IsingBimod(2, 2, 0) |
| 14 | + D1 = IsingBimod(2, 2, 1) |
| 15 | + C = rand([C0, C1]) |
| 16 | + D = rand([D0, D1]) |
| 17 | + s = rand((M, Mop, C, D)) |
| 18 | + |
| 19 | + @testset "Basic properties" begin |
| 20 | + @test @constinferred(one(C1)) == @constinferred(leftone(C1)) == |
| 21 | + @constinferred(rightone(C1)) |
| 22 | + @test one(D1) == leftone(D1) == rightone(D1) |
| 23 | + @test one(C1) == leftone(M) == rightone(Mop) |
| 24 | + @test one(D1) == rightone(M) == leftone(Mop) |
| 25 | + |
| 26 | + @test eval(Meta.parse(sprint(show, s))) == s |
| 27 | + @test @constinferred(hash(s)) == hash(deepcopy(s)) |
| 28 | + @constinferred dual(s) |
| 29 | + @test dual(dual(s)) == s |
| 30 | + @constinferred dim(s) |
| 31 | + @constinferred frobeniusschur(s) |
| 32 | + @constinferred convert(IsingAnyon, s) |
| 33 | + |
| 34 | + @constinferred Bsymbol(C, C, C) |
| 35 | + @constinferred Fsymbol(D, D, D, D, D, D) |
| 36 | + end |
| 37 | + |
| 38 | + @testset "$Istr: Value iterator" begin |
| 39 | + @test eltype(values(I)) == I |
| 40 | + @test_throws ArgumentError one(I) |
| 41 | + sprev = C0 # first in SectorValues |
| 42 | + for (i, s) in enumerate(values(I)) |
| 43 | + @test !isless(s, sprev) # confirm compatibility with sort order |
| 44 | + @test s == @constinferred (values(I)[i]) |
| 45 | + @test findindex(values(I), s) == i |
| 46 | + sprev = s |
| 47 | + i >= 10 && break |
| 48 | + end |
| 49 | + @test C0 == first(values(I)) |
| 50 | + @test (@constinferred findindex(values(I), C0)) == 1 |
| 51 | + for s in collect(values(I)) |
| 52 | + @test (@constinferred values(I)[findindex(values(I), s)]) == s |
| 53 | + end |
| 54 | + end |
| 55 | + |
| 56 | + @testset "$Istr: Printing and errors" begin |
| 57 | + @test eval(Meta.parse(sprint(show, C))) == C |
| 58 | + @test eval(Meta.parse(sprint(show, M))) == M |
| 59 | + @test eval(Meta.parse(sprint(show, Mop))) == Mop |
| 60 | + @test eval(Meta.parse(sprint(show, D))) == D |
| 61 | + @test_throws DomainError one(M) |
| 62 | + @test_throws DomainError one(Mop) |
| 63 | + end |
| 64 | + |
| 65 | + @testset "$Istr Fusion rules and F-symbols" begin |
| 66 | + argerr = ArgumentError("invalid fusion channel") |
| 67 | + # forbidden fusions |
| 68 | + for obs in [(C, D), (D, C), (M, M), (Mop, Mop), (D, M), (M, C), (Mop, D), (C, Mop)] |
| 69 | + @test isempty(⊗(obs...)) |
| 70 | + @test_throws argerr Nsymbol(obs..., s) |
| 71 | + end |
| 72 | + |
| 73 | + # allowed fusions |
| 74 | + for obs in [(C, C), (D, D), (M, Mop), (Mop, M), (C, M), (Mop, C), (M, D), (D, Mop)] |
| 75 | + @test !isempty(⊗(obs...)) |
| 76 | + end |
| 77 | + |
| 78 | + @test Nsymbol(C, C, one(C)) == Nsymbol(D, D, one(D)) == 1 |
| 79 | + @test Nsymbol(C, M, M) == Nsymbol(Mop, C, Mop) == 1 |
| 80 | + @test Nsymbol(M, D, M) == Nsymbol(D, Mop, Mop) == 1 |
| 81 | + |
| 82 | + @test_throws argerr Nsymbol(M, Mop, D) |
| 83 | + @test_throws argerr Nsymbol(Mop, M, C) |
| 84 | + @test Nsymbol(M, Mop, C) == Nsymbol(Mop, M, D) == 1 |
| 85 | + |
| 86 | + # non-trivial F-symbol checks |
| 87 | + @test Fsymbol(Mop, M, D1, D0, D0, M) == 0 # ℳᵒᵖ x ℳ x 𝒟 → ℳ allowed, but 𝒟-labels mismatch |
| 88 | + @test Fsymbol(Mop, M, D1, D0, D1, M) == 1 |
| 89 | + @test Fsymbol(M, Mop, C1, C0, C0, Mop) == 0 |
| 90 | + @test Fsymbol(M, Mop, C1, C0, C1, Mop) == 1 |
| 91 | + |
| 92 | + @test Fsymbol(C, M, D, M, M, M) == (C.label * D.label == 0 ? 1 : -1) # 𝒞 x ℳ x 𝒟 → ℳ allowed |
| 93 | + @test_throws argerr Fsymbol(M, Mop, M, Mop, C, D) == 0 # IsingAnyon conversion would give non-zero |
| 94 | + @test_throws argerr Fsymbol(Mop, M, Mop, M, D, C) == 0 |
| 95 | + |
| 96 | + @test Fsymbol(M, Mop, M, M, C, D) == |
| 97 | + (C.label * D.label == 0 ? inv(sqrt(2)) : -inv(sqrt(2))) # ℳ x ℳᵒᵖ x ℳ → ℳ allowed |
| 98 | + @test Fsymbol(Mop, M, Mop, Mop, D, C) == |
| 99 | + (C.label * D.label == 0 ? inv(sqrt(2)) : -inv(sqrt(2))) # ℳᵒᵖ x ℳ x ℳᵒᵖ → ℳᵒᵖ allowed |
| 100 | + |
| 101 | + @test_throws argerr Fsymbol(M, Mop, M, Mop, C, D) |
| 102 | + end |
| 103 | + |
| 104 | + @testset "$Istr: Unitarity of F-move" begin |
| 105 | + objects = collect(values(I)) |
| 106 | + for a in objects, b in objects, c in objects |
| 107 | + for d in ⊗(a, b, c) |
| 108 | + es = collect(intersect(⊗(a, b), map(dual, ⊗(c, dual(d))))) |
| 109 | + fs = collect(intersect(⊗(b, c), map(dual, ⊗(dual(d), a)))) |
| 110 | + @test length(es) == length(fs) |
| 111 | + F = [Fsymbol(a, b, c, d, e, f) for e in es, f in fs] |
| 112 | + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) |
| 113 | + end |
| 114 | + end |
| 115 | + end |
| 116 | + |
| 117 | + @testset "$Istr: Pentagon equation" begin |
| 118 | + objects = collect(values(I)) |
| 119 | + for a in objects, b in objects, c in objects, d in objects |
| 120 | + # compatibility checks built in Fsymbol |
| 121 | + @test pentagon_equation(a, b, c, d; atol=1e-12, rtol=1e-12) |
| 122 | + end |
| 123 | + end |
| 124 | +end |
0 commit comments