Skip to content

Commit dc045b3

Browse files
authored
fix productsector symbols for invalid fusion vertices (#12)
1 parent ec8c50b commit dc045b3

File tree

6 files changed

+90
-31
lines changed

6 files changed

+90
-31
lines changed

src/TensorKitSectors.jl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
# Superselection sectors (quantum numbers):
2-
# for defining graded vector spaces and invariant subspaces of tensor products
3-
#==========================================================================================#
4-
51
module TensorKitSectors
62

73
# exports

src/anyons.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Sectors corresponding to simplest fusion categories that are not group representations.
2+
#---------------------------------------------------------------------------------------#
3+
14
# PlanarTrivial
25
"""
36
struct PlanarTrivial <: Sector

src/fermions.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ See also: [`SU2Irrep`](@ref), [`FermionParity`](@ref)
9797
"""
9898
const FermionSpin = SU2Irrep FermionParity
9999
const fSU₂ = FermionSpin
100-
FermionSpin(j::Real) = (s = SU2Irrep(j);
101-
s FermionParity(isodd(twice(s.j))))
100+
FermionSpin(j::Real) = (s=SU2Irrep(j); s FermionParity(isodd(twice(s.j))))
102101
type_repr(::Type{FermionSpin}) = "FermionSpin"
103102

104103
# convenience default converter -> allows Vect[FermionSpin](1 => 1)

src/irreps.jl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
# Sectors corresponding to irreducible representations of compact groups
2-
#==============================================================================#
3-
# Irreps of groups
42
#------------------------------------------------------------------------------#
53
"""
64
abstract type AbstractIrrep{G<:Group} <: Sector end
@@ -143,7 +141,7 @@ function Base.getindex(::SectorValues{U1Irrep}, i::Int)
143141
return U1Irrep(iseven(i) ? half(i >> 1) : -half(i >> 1))
144142
end
145143
function findindex(::SectorValues{U1Irrep}, c::U1Irrep)
146-
return (n = twice(c.charge); 2 * abs(n) + (n <= 0))
144+
return (n=twice(c.charge); 2 * abs(n) + (n <= 0))
147145
end
148146

149147
Base.hash(c::U1Irrep, h::UInt) = hash(c.charge, h)

src/product.jl

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Deligne tensor product of different sectors: ⊠
2-
#==============================================================================#
2+
#------------------------------------------------------------------------------#
33
const SectorTuple = Tuple{Vararg{Sector}}
44

55
"""
@@ -79,12 +79,24 @@ _tailsector(x::ProductSector) = ProductSector(Base.tail(x.sectors))
7979
function Fsymbol(a::P, b::P, c::P, d::P, e::P, f::P) where {P<:ProductSector}
8080
heads = map(_firstsector, (a, b, c, d, e, f))
8181
tails = map(_tailsector, (a, b, c, d, e, f))
82-
f₁ = Fsymbol(heads...)
83-
f₂ = Fsymbol(tails...)
84-
if f₁ isa Number || f₂ isa Number
85-
f₁ * f₂
82+
F₁ = Fsymbol(heads...)
83+
F₂ = Fsymbol(tails...)
84+
if F₁ isa Number && F₂ isa Number
85+
return F₁ * F₂
86+
elseif F₁ isa Number
87+
a₁, b₁, c₁, d₁, e₁, f₁ = heads
88+
sz₁ = (Nsymbol(a₁, b₁, e₁), Nsymbol(e₁, c₁, d₁), Nsymbol(b₁, c₁, f₁),
89+
Nsymbol(a₁, f₁, d₁))
90+
F₁′ = fill(F₁, sz₁)
91+
return _kron(F₁′, F₂)
92+
elseif F₂ isa Number
93+
a₂, b₂, c₂, d₂, e₂, f₂ = tails
94+
sz₂ = (Nsymbol(a₂, b₂, e₂), Nsymbol(e₂, c₂, d₂), Nsymbol(b₂, c₂, f₂),
95+
Nsymbol(a₂, f₂, d₂))
96+
F₂′ = fill(F₂, sz₂)
97+
return _kron(F₁, F₂′)
8698
else
87-
_kron(f₁, f₂)
99+
return _kron(F₁, F₂)
88100
end
89101
end
90102
function Fsymbol(a::P, b::P, c::P, d::P, e::P,
@@ -95,12 +107,22 @@ end
95107
function Rsymbol(a::P, b::P, c::P) where {P<:ProductSector}
96108
heads = map(_firstsector, (a, b, c))
97109
tails = map(_tailsector, (a, b, c))
98-
r1 = Rsymbol(heads...)
99-
r2 = Rsymbol(tails...)
100-
if r1 isa Number || r2 isa Number
101-
r1 * r2
110+
R₁ = Rsymbol(heads...)
111+
R₂ = Rsymbol(tails...)
112+
if R₁ isa Number && R₂ isa Number
113+
R₁ * R₂
114+
elseif R₁ isa Number
115+
a₁, b₁, c₁ = heads
116+
sz₁ = (Nsymbol(a₁, b₁, c₁), Nsymbol(b₁, a₁, c₁)) # 0 x 0 or 1 x 1
117+
R₁′ = fill(R₁, sz₁)
118+
return _kron(R₁′, R₂)
119+
elseif R₂ isa Number
120+
a₂, b₂, c₂ = tails
121+
sz₂ = (Nsymbol(a₂, b₂, c₂), Nsymbol(b₂, a₂, c₂)) # 0 x 0 or 1 x 1
122+
R₂′ = fill(R₂, sz₂)
123+
return _kron(R₁, R₂′)
102124
else
103-
_kron(r1, r2)
125+
return _kron(R₁, R₂)
104126
end
105127
end
106128
function Rsymbol(a::P, b::P, c::P) where {P<:ProductSector{<:Tuple{Sector}}}
@@ -110,12 +132,22 @@ end
110132
function Bsymbol(a::P, b::P, c::P) where {P<:ProductSector}
111133
heads = map(_firstsector, (a, b, c))
112134
tails = map(_tailsector, (a, b, c))
113-
b1 = Bsymbol(heads...)
114-
b2 = Bsymbol(tails...)
115-
if b1 isa Number || b2 isa Number
116-
b1 * b2
135+
B₁ = Bsymbol(heads...)
136+
B₂ = Bsymbol(tails...)
137+
if B₁ isa Number && B₂ isa Number
138+
B₁ * B₂
139+
elseif B₁ isa Number
140+
a₁, b₁, c₁ = heads
141+
sz₁ = (Nsymbol(a₁, b₁, c₁), Nsymbol(c₁, dual(b₁), a₁)) # 0 x 0 or 1 x 1
142+
B₁′ = fill(B₁, sz₁)
143+
return _kron(B₁′, B₂)
144+
elseif B₂ isa Number
145+
a₂, b₂, c₂ = tails
146+
sz₂ = (Nsymbol(a₂, b₂, c₂), Nsymbol(c₂, dual(b₂), a₂)) # 0 x 0 or 1 x 1
147+
B₂′ = fill(B₂, sz₂)
148+
return _kron(B₁, B₂′)
117149
else
118-
_kron(b1, b2)
150+
return _kron(B₁, B₂)
119151
end
120152
end
121153
function Bsymbol(a::P, b::P, c::P) where {P<:ProductSector{<:Tuple{Sector}}}
@@ -125,12 +157,22 @@ end
125157
function Asymbol(a::P, b::P, c::P) where {P<:ProductSector}
126158
heads = map(_firstsector, (a, b, c))
127159
tails = map(_tailsector, (a, b, c))
128-
a1 = Asymbol(heads...)
129-
a2 = Asymbol(tails...)
130-
if a1 isa Number || a2 isa Number
131-
a1 * a2
160+
A₁ = Asymbol(heads...)
161+
A₂ = Asymbol(tails...)
162+
if A₁ isa Number && A₂ isa Number
163+
A₁ * A₂
164+
elseif A₁ isa Number
165+
a₁, b₁, c₁ = heads
166+
sz₁ = (Nsymbol(a₁, b₁, c₁), Nsymbol(dual(a₁), c₁, b₁)) # 0 x 0 or 1 x 1
167+
A₁′ = fill(A₁, sz₁)
168+
return _kron(A₁′, A₂)
169+
elseif A₂ isa Number
170+
a₂, b₂, c₂ = tails
171+
sz₂ = (Nsymbol(a₂, b₂, c₂), Nsymbol(dual(a₂), c₂, b₂)) # 0 x 0 or 1 x 1
172+
A₂′ = fill(A₂, sz₂)
173+
return _kron(A₁, A₂′)
132174
else
133-
_kron(a1, a2)
175+
return _kron(A₁, A₂)
134176
end
135177
end
136178
function Asymbol(a::P, b::P, c::P) where {P<:ProductSector{<:Tuple{Sector}}}

test/runtests.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const sectorlist = (Z2Irrep, Z3Irrep, Z4Irrep, U1Irrep, CU1Irrep, SU2Irrep, NewS
2020
Z3Irrep Z4Irrep, FermionParity U1Irrep SU2Irrep,
2121
FermionParity SU2Irrep SU2Irrep, NewSU2Irrep NewSU2Irrep,
2222
NewSU2Irrep SU2Irrep, FermionParity SU2Irrep NewSU2Irrep,
23-
Z2Irrep FibonacciAnyon FibonacciAnyon)
23+
FibonacciAnyon FibonacciAnyon Z2Irrep)
2424

2525
@testset "$(TensorKitSectors.type_repr(I))" for I in sectorlist
2626
@include("sectors.jl")
@@ -40,6 +40,27 @@ end
4040
end
4141
end
4242

43+
@testset "Issue that came up in #11" begin
44+
a = Z2Irrep(1) NewSU2Irrep(1)
45+
b = Z2Irrep(0) NewSU2Irrep(1)
46+
c = Z2Irrep(0) NewSU2Irrep(1)
47+
d = Z2Irrep(0) NewSU2Irrep(1)
48+
e = Z2Irrep(0) NewSU2Irrep(1)
49+
f = Z2Irrep(0) NewSU2Irrep(1)
50+
@test size(Fsymbol(a, b, c, d, e, f)) == (0, 1, 1, 0)
51+
@test size(Bsymbol(a, b, c)) == (0, 0)
52+
@test size(Rsymbol(a, b, c)) == (0, 0)
53+
a = NewSU2Irrep(1) Z2Irrep(1)
54+
b = NewSU2Irrep(1) Z2Irrep(0)
55+
c = NewSU2Irrep(1) Z2Irrep(0)
56+
d = NewSU2Irrep(1) Z2Irrep(0)
57+
e = NewSU2Irrep(1) Z2Irrep(0)
58+
f = NewSU2Irrep(1) Z2Irrep(0)
59+
@test size(Fsymbol(a, b, c, d, e, f)) == (0, 1, 1, 0)
60+
@test size(Bsymbol(a, b, c)) == (0, 0)
61+
@test size(Rsymbol(a, b, c)) == (0, 0)
62+
end
63+
4364
@testset "Aqua" begin
4465
using Aqua: Aqua
4566
Aqua.test_all(TensorKitSectors)

0 commit comments

Comments
 (0)