Skip to content

Commit 7dbe071

Browse files
borisdevoslkdvos
andauthored
Representations of alternating group A4 (#43)
* alternating group * start of ANIrrep * rename file * get fusion working * show and export * fusion tensor * start of hardcoding fusion tensors * remove trace in Fsymbol * bosonic braiding * fix show * keep product iterator to unique outputs * remove aliases for N < 4 * remove show method for `ANIrrep` * fix length of product iterator * make `Fsymbol` type-stable * fix length of iterator * fix rsymbol * minor code suggestions * fix some things to be clear N < 5 isn't available * fix Rsymbol * rename fusion tensor help functions * format * generalise orthogonality of fusion tensor check for `GenericFusion` * add to sectorlist in tests * clean up and shorten code * add docstring for `fusiontensor` * code suggestions * fix counting number of irreps of A_N * replace more partitions by irreps * bring back sectorscalartype * minor cleanup * some more cleanup * remove stray ANIrrep * add source to motivate choice of basis * reduce allocations * Update src/irreps/irreps.jl Co-authored-by: Lukas Devos <[email protected]> * intertwiner check * move intertwiner test to run it --------- Co-authored-by: Lukas Devos <[email protected]>
1 parent e045378 commit 7dbe071

File tree

5 files changed

+202
-2
lines changed

5 files changed

+202
-2
lines changed

src/TensorKitSectors.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export triangle_equation, pentagon_equation, hexagon_equation
2121
export Trivial
2222
export Z2Irrep, Z3Irrep, Z4Irrep, ZNIrrep, LargeZNIrrep, U1Irrep
2323
export D3Irrep, D4Irrep, DNIrrep, CU1Irrep
24+
export A4Irrep
2425
export SU2Irrep
2526
export ZNElement, Z2Element, Z3Element, Z4Element
2627
export ProductSector, TimeReversed
@@ -35,6 +36,7 @@ export charge, modulus
3536
# ---------------
3637
export , , ×
3738
export Cyclic, ℤ, ℤ₂, ℤ₃, ℤ₄, U₁, SU, SU₂, Dihedral, D₃, D₄, CU₁
39+
export Alternating, A₄
3840
export fℤ₂, fU₁, fSU₂
3941

4042
# public

src/groups.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ group.
3838
"""
3939
abstract type Dihedral{N} <: Group end
4040

41+
"""
42+
abstract type Alternating{N} <: Group
43+
44+
Type to represent the alternating group of order `N!/2`, which is the group
45+
of even permutations on `N` elements.
46+
"""
47+
abstract type Alternating{N} <: Group end
48+
4149

4250
"""
4351
abstract type U₁ <: AbelianGroup
@@ -72,6 +80,7 @@ const ℤ₃ = ℤ{3}
7280
const ℤ₄ = ℤ{4}
7381
const D₃ = Dihedral{3}
7482
const D₄ = Dihedral{4}
83+
const A₄ = Alternating{4}
7584
const SU₂ = SU{2}
7685

7786
type_repr(::Type{ℤ₂}) = "ℤ₂"
@@ -80,6 +89,7 @@ type_repr(::Type{ℤ₄}) = "ℤ₄"
8089
type_repr(::Type{ℤ{N}}) where {N} = "ℤ{$N}"
8190
type_repr(::Type{D₃}) = "D₃"
8291
type_repr(::Type{D₄}) = "D₄"
92+
type_repr(::Type{A₄}) = "A₄"
8393
type_repr(::Type{SU₂}) = "SU₂"
8494
type_repr(::Type{U₁}) = "U₁"
8595
type_repr(::Type{CU₁}) = "CU₁"

src/irreps/a4irrep.jl

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
"""
2+
struct A4Irrep <: AbstractIrrep{A₄}
3+
A4Irrep(n::Integer)
4+
Irrep[A₄](n::Integer)
5+
6+
Represents irreps of the alternating group ``A₄``.
7+
8+
## Fields
9+
10+
- `n::Int8`: the label of the irrep, corresponding to ``1``, ``1′``, ``1″`` and ``3``.
11+
"""
12+
struct A4Irrep <: AbstractIrrep{A₄}
13+
n::Int8
14+
function A4Irrep(n::Integer)
15+
0 n < 4 || throw(ArgumentError("A4Irrep only has irrep labels in `0:3`"))
16+
return new(n)
17+
end
18+
end
19+
20+
FusionStyle(::Type{A4Irrep}) = GenericFusion()
21+
sectorscalartype(::Type{A4Irrep}) = Float64
22+
23+
unit(::Type{A4Irrep}) = A4Irrep(0)
24+
dual(a::A4Irrep) = a.n == 3 ? a : A4Irrep((3 - a.n) % 3)
25+
26+
Base.hash(a::A4Irrep, h::UInt) = hash(a.n, h)
27+
Base.convert(::Type{A4Irrep}, n::Integer) = A4Irrep(n)
28+
29+
Base.getindex(::IrrepTable, ::Type{A₄}) = A4Irrep
30+
31+
32+
# Sector iterator
33+
# ---------------
34+
Base.isless(a::A4Irrep, b::A4Irrep) = isless(a.n, b.n)
35+
Base.IteratorSize(::Type{SectorValues{A4Irrep}}) = Base.HasLength()
36+
Base.length(::SectorValues{A4Irrep}) = 4
37+
38+
Base.iterate(v::SectorValues{A4Irrep}, i = 1) = i > length(v) ? nothing : (v[i], i + 1)
39+
40+
@inline function Base.getindex(v::SectorValues{A4Irrep}, i::Int)
41+
@boundscheck 1 <= i <= length(v) || throw(BoundsError(v, i))
42+
return A4Irrep(i - 1)
43+
end
44+
45+
findindex(::SectorValues{A4Irrep}, a::A4Irrep) = a.n + 1
46+
47+
# Product iterator
48+
# ----------------
49+
50+
const A4IrrepProdIterator = SectorProductIterator{A4Irrep}
51+
(a::A4Irrep, b::A4Irrep) = SectorProductIterator((a <= b ? (a, b) : (b, a))...)
52+
53+
Base.IteratorSize(::Type{A4IrrepProdIterator}) = Base.HasLength()
54+
Base.length(x::A4IrrepProdIterator) = (x.a == x.b == A4Irrep(3)) ? 4 : 1
55+
56+
function Base.iterate(p::A4IrrepProdIterator, state::Int = 1)
57+
a, b = p.a, p.b
58+
if state == 1
59+
a.n == b.n == 3 && return (A4Irrep(state - 1), state + 1) # 3 ⊗ 3
60+
b.n == 3 && return (b, 5) # x ⊗ 3 = 3
61+
return (A4Irrep((a.n + b.n) % 3), 5) # 1d irreps ≡ Z3
62+
elseif state < 5 # a == b == 3
63+
return (A4Irrep(state - 1), state + 1)
64+
else
65+
return nothing
66+
end
67+
end
68+
69+
# Topological data
70+
# ----------------
71+
dim(a::A4Irrep) = a.n == 3 ? 3 : 1
72+
73+
function Nsymbol(a::A4Irrep, b::A4Irrep, c::A4Irrep)
74+
# 3d irreps
75+
a.n == b.n == 3 && return 1 + (c.n == 3)
76+
(a.n == 3 || b.n == 3) && return Int(c.n == 3)
77+
# 1d irreps
78+
return Int((a.n + b.n) % 3 == c.n)
79+
end
80+
81+
82+
function Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I <: A4Irrep}
83+
T = sectorscalartype(I)
84+
Nabe = Nsymbol(a, b, e)
85+
Necd = Nsymbol(e, c, d)
86+
Nbcf = Nsymbol(b, c, f)
87+
Nafd = Nsymbol(a, f, d)
88+
89+
Nabe > 0 && Necd > 0 && Nbcf > 0 && Nafd > 0 ||
90+
return zeros(T, Nabe, Necd, Nbcf, Nafd)
91+
92+
# fallback through fusiontensor for A4Irrep
93+
A = fusiontensor(a, b, e)
94+
B = fusiontensor(e, c, d)[:, :, 1, :]
95+
C = fusiontensor(b, c, f)
96+
D = fusiontensor(a, f, d)[:, :, 1, :]
97+
@tensor F[-1, -2, -3, -4] := conj(D[1, 5, -4]) * conj(C[2, 4, 5, -3]) *
98+
A[1, 2, 3, -1] * B[3, 4, -2]
99+
100+
return F
101+
end
102+
103+
# bosonic
104+
function Rsymbol(a::I, b::I, c::I) where {I <: A4Irrep}
105+
Nabc = Nsymbol(a, b, c)
106+
R = zeros(sectorscalartype(I), Nabc, Nabc)
107+
Nabc == 0 && return R
108+
if a == b == c == A4Irrep(3)
109+
R[1, 1] = -1
110+
R[2, 2] = 1
111+
else
112+
R[1, 1] = 1
113+
end
114+
return R
115+
end
116+
117+
# choice of basis: https://journals.aps.org/rmp/pdf/10.1103/RevModPhys.82.2701
118+
# triplet is a real representation -> can make all representation matrices real
119+
function fusiontensor(a::I, b::I, c::I) where {I <: A4Irrep}
120+
T = sectorscalartype(I)
121+
Nabc = Nsymbol(a, b, c)
122+
C = zeros(T, dim(a), dim(b), dim(c), Nabc)
123+
isempty(C) && return C
124+
125+
ω = cis(2π / 3)
126+
127+
if a.n == b.n == 3 # 3 ⊗ 3
128+
if c.n != 3 # singlets
129+
invsqrt3 = 1 / sqrt(3.0)
130+
for i in 1:3
131+
j = 4 - mod1(i - c.n - 1, 3)
132+
C[i, j, 1, 1] = invsqrt3
133+
end
134+
else # triplet: eq 38 in above reference
135+
s2 = 1 / sqrt(2.0)
136+
s6 = 1 / sqrt(6.0)
137+
138+
# antisymmetric channel
139+
C[:, :, 1, 1] .= [0 0 0; 0 0 s2; 0 -s2 0]
140+
C[:, :, 2, 1] .= [0 s2 0; -s2 0 0; 0 0 0]
141+
C[:, :, 3, 1] .= [0 0 -s2; 0 0 0; s2 0 0]
142+
143+
# symmetric channel
144+
C[:, :, 1, 2] .= [-2 * s6 0 0; 0 0 s6; 0 s6 0]
145+
C[:, :, 2, 2] .= [0 s6 0; s6 0 0; 0 0 -2 * s6]
146+
C[:, :, 3, 2] .= [0 0 s6; 0 -2 * s6 0; s6 0 0]
147+
end
148+
else
149+
if a.n != 3 && b.n != 3 # 1d x 1d
150+
C[1, 1, 1] = one(T)
151+
elseif a.n == 3 && b.n != 3 # 3 x 1d
152+
for i in 1:3
153+
j = mod1(i - b.n, 3)
154+
C[j, 1, i, 1] = one(T)
155+
end
156+
else # 1d x 3: reshape of 3 x 1d
157+
for i in 1:3
158+
j = mod1(i - a.n, 3)
159+
C[1, j, i, 1] = one(T)
160+
end
161+
end
162+
end
163+
return C
164+
end

src/irreps/irreps.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,4 @@ include("u1irrep.jl")
6868
include("dnirrep.jl")
6969
include("cu1irrep.jl")
7070
include("su2irrep.jl")
71+
include("a4irrep.jl")

test/runtests.jl

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,21 @@ const sectorlist = (
99
Trivial, PlanarTrivial,
1010
Z2Irrep, Z3Irrep, Z4Irrep, Irrep[ℤ{200}], U1Irrep,
1111
DNIrrep{3}, DNIrrep{4}, DNIrrep{5}, CU1Irrep,
12-
SU2Irrep, NewSU2Irrep,
12+
A4Irrep, SU2Irrep, NewSU2Irrep,
1313
FibonacciAnyon, IsingAnyon, FermionParity,
1414
FermionParity FermionParity,
1515
Z3Irrep Z4Irrep, FermionParity U1Irrep SU2Irrep,
1616
FermionParity SU2Irrep SU2Irrep, NewSU2Irrep NewSU2Irrep,
1717
NewSU2Irrep SU2Irrep, FermionParity SU2Irrep NewSU2Irrep,
1818
FibonacciAnyon FibonacciAnyon Z2Irrep,
19+
A4Irrep Z2Irrep, A4Irrep SU2Irrep,
1920
Z2Element{0}, Z2Element{1},
2021
Z3Element{0}, Z3Element{1}, Z3Element{2},
2122
Z4Element{0}, Z4Element{1}, Z4Element{2},
2223
Z3Element{1} SU2Irrep,
2324
FibonacciAnyon Z4Element{3},
2425
TimeReversed{Z2Irrep},
25-
TimeReversed{Z3Irrep}, TimeReversed{Z4Irrep},
26+
TimeReversed{Z3Irrep}, TimeReversed{Z4Irrep}, TimeReversed{A4Irrep},
2627
TimeReversed{U1Irrep}, TimeReversed{CU1Irrep}, TimeReversed{SU2Irrep},
2728
TimeReversed{FibonacciAnyon}, TimeReversed{IsingAnyon},
2829
TimeReversed{FermionParity},
@@ -46,6 +47,28 @@ using .SectorTestSuite
4647
end
4748
end
4849

50+
@testset "Intertwiner relation for A4Irrep" begin
51+
ω = cis(2π / 3)
52+
T3 = [1 0 0; 0 ω 0; 0 0 ω^2]
53+
T(a::Int8) = (a == 3) ? T3 : hcat^(a))
54+
S3 = 1 / 3 * [-1 2 2; 2 -1 2; 2 2 -1]
55+
S(a::Int8) = (a == 3) ? S3 : hcat(1)
56+
for a in smallset(A4Irrep), b in smallset(A4Irrep)
57+
for c in (a, b)
58+
C = fusiontensor(a, b, c)
59+
Ta, Tb, Tc = T(a.n), T(b.n), T(c.n)
60+
Sa, Sb, Sc = S(a.n), S(b.n), S(c.n)
61+
for μ in 1:Nsymbol(a, b, c)
62+
Cmat = reshape(view(C, :, :, :, μ), (dim(a) * dim(b), dim(c)))
63+
L_T = Cmat' * kron(Ta, Tb) * Cmat
64+
L_S = Cmat' * kron(Sa, Sb) * Cmat
65+
@test isapprox(L_T, Tc; atol = 1.0e-12)
66+
@test isapprox(L_S, Sc; atol = 1.0e-12)
67+
end
68+
end
69+
end
70+
end
71+
4972
@testset "Deligne product" begin
5073
sectorlist′ = (Trivial, sectorlist...)
5174
for I1 in sectorlist′, I2 in sectorlist′

0 commit comments

Comments
 (0)