Skip to content
Merged
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
9 changes: 4 additions & 5 deletions src/TensorKitSectors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ export Sector, Group, AbstractIrrep, AbstractGroupElement
export Irrep, GroupElement

export Nsymbol, Fsymbol, Rsymbol, Asymbol, Bsymbol
export sectorscalartype
export sectorscalartype, fusionscalartype, braidingscalartype, dimscalartype
export dim, sqrtdim, invsqrtdim, frobenius_schur_indicator, frobenius_schur_phase, twist, fusiontensor, dual
export otimes, deligneproduct, times
export FusionStyle, UniqueFusion, MultipleFusion, SimpleFusion, GenericFusion,
MultiplicityFreeFusion
export UnitStyle, SimpleUnit, GenericUnit
export FusionStyle, UniqueFusion, MultipleFusion, SimpleFusion, GenericFusion, MultiplicityFreeFusion
export BraidingStyle, NoBraiding, HasBraiding, SymmetricBraiding, Bosonic, Fermionic, Anyonic
export UnitStyle, SimpleUnit, GenericUnit
export SectorSet, SectorValues, findindex
export unit, rightunit, leftunit, allunits, isunit

Expand Down Expand Up @@ -50,7 +49,7 @@ end
using Base: SizeUnknown, HasLength, IsInfinite
using Base: HasEltype, EltypeUnknown
using Base.Iterators: product, filter
using Base: tuple_type_head, tuple_type_tail
using Base: @assume_effects

using LinearAlgebra: tr
using TensorOperations
Expand Down
5 changes: 5 additions & 0 deletions src/anyons.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dual(::PlanarTrivial) = PlanarTrivial()

FusionStyle(::Type{PlanarTrivial}) = UniqueFusion()
BraidingStyle(::Type{PlanarTrivial}) = NoBraiding()
fusionscalartype(::Type{PlanarTrivial}) = Int
sectorscalartype(::Type{PlanarTrivial}) = Int

Nsymbol(::Vararg{PlanarTrivial, 3}) = 1
Expand Down Expand Up @@ -82,7 +83,9 @@ const _goldenratio = Float64(MathConstants.golden)
dim(a::FibonacciAnyon) = isunit(a) ? one(_goldenratio) : _goldenratio

FusionStyle(::Type{FibonacciAnyon}) = SimpleFusion()
fusionscalartype(::Type{FibonacciAnyon}) = Float64
BraidingStyle(::Type{FibonacciAnyon}) = Anyonic()
braidingscalartype(::Type{FibonacciAnyon}) = ComplexF64
sectorscalartype(::Type{FibonacciAnyon}) = ComplexF64

const FibonacciAnyonProdIterator = SectorProductIterator{FibonacciAnyon}
Expand Down Expand Up @@ -198,7 +201,9 @@ dual(s::IsingAnyon) = s
dim(a::IsingAnyon) = a.s == :σ ? sqrt(2) : 1.0

FusionStyle(::Type{IsingAnyon}) = SimpleFusion()
fusionscalartype(::Type{IsingAnyon}) = Float64
BraidingStyle(::Type{IsingAnyon}) = Anyonic()
braidingscalartype(::Type{IsingAnyon}) = ComplexF64
sectorscalartype(::Type{IsingAnyon}) = ComplexF64

const IsingAnyonProdIterator = SectorProductIterator{IsingAnyon}
Expand Down
2 changes: 2 additions & 0 deletions src/fermions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ dual(f::FermionParity) = f
dim(f::FermionParity) = 1

FusionStyle(::Type{FermionParity}) = UniqueFusion()
fusionscalartype(::Type{FermionParity}) = Int
BraidingStyle(::Type{FermionParity}) = Fermionic()
braidingscalartype(::Type{FermionParity}) = Int
sectorscalartype(::Type{FermionParity}) = Int

⊗(a::FermionParity, b::FermionParity) = (FermionParity(a.isodd ⊻ b.isodd),)
Expand Down
2 changes: 1 addition & 1 deletion src/groups.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const times = ×
function ×(
G1::Type{ProductGroup{T1}}, G2::Type{ProductGroup{T2}}
) where {T1 <: GroupTuple, T2 <: GroupTuple}
return tuple_type_head(T1) × (ProductGroup{tuple_type_tail(T1)} × G2)
return Base.tuple_type_head(T1) × (ProductGroup{Base.tuple_type_tail(T1)} × G2)
end
×(G1::Type{ProductGroup{Tuple{}}}, G2::Type{<:Group}) = ProductGroup{Tuple{G2}}
function ×(G1::Type{ProductGroup{T}}, G2::Type{<:Group}) where {T <: GroupTuple}
Expand Down
6 changes: 4 additions & 2 deletions src/irreps/a4irrep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ struct A4Irrep <: AbstractIrrep{A₄}
end

FusionStyle(::Type{A4Irrep}) = GenericFusion()
fusionscalartype(::Type{A4Irrep}) = Float64
braidingscalartype(::Type{A4Irrep}) = Float64
sectorscalartype(::Type{A4Irrep}) = Float64

unit(::Type{A4Irrep}) = A4Irrep(0)
Expand Down Expand Up @@ -80,7 +82,7 @@ end


function Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I <: A4Irrep}
T = sectorscalartype(I)
T = fusionscalartype(I)
Nabe = Nsymbol(a, b, e)
Necd = Nsymbol(e, c, d)
Nbcf = Nsymbol(b, c, f)
Expand All @@ -103,7 +105,7 @@ end
# bosonic
function Rsymbol(a::I, b::I, c::I) where {I <: A4Irrep}
Nabc = Nsymbol(a, b, c)
R = zeros(sectorscalartype(I), Nabc, Nabc)
R = zeros(braidingscalartype(I), Nabc, Nabc)
Nabc == 0 && return R
if a == b == c == A4Irrep(3)
R[1, 1] = -1
Expand Down
12 changes: 7 additions & 5 deletions src/irreps/cu1irrep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ end
dim(c::CU1Irrep) = ifelse(c.j == zero(HalfInt), 1, 2)

FusionStyle(::Type{CU1Irrep}) = SimpleFusion()
fusionscalartype(::Type{CU1Irrep}) = Float64
braidingscalartype(::Type{CU1Irrep}) = Float64
sectorscalartype(::Type{CU1Irrep}) = Float64
Base.isreal(::Type{CU1Irrep}) = true

Expand All @@ -121,15 +123,15 @@ function Nsymbol(a::CU1Irrep, b::CU1Irrep, c::CU1Irrep)
end

function Fsymbol(
a::CU1Irrep, b::CU1Irrep, c::CU1Irrep, d::CU1Irrep, e::CU1Irrep,
f::CU1Irrep
a::CU1Irrep, b::CU1Irrep, c::CU1Irrep,
d::CU1Irrep, e::CU1Irrep, f::CU1Irrep
)
Nabe = convert(Int, Nsymbol(a, b, e))
Necd = convert(Int, Nsymbol(e, c, d))
Nbcf = convert(Int, Nsymbol(b, c, f))
Nafd = convert(Int, Nsymbol(a, f, d))

T = sectorscalartype(CU1Irrep)
T = fusionscalartype(CU1Irrep)
Nabe * Necd * Nbcf * Nafd == 0 && return zero(T)

op = CU1Irrep(0, 0)
Expand Down Expand Up @@ -211,12 +213,12 @@ function Fsymbol(
end

function Rsymbol(a::CU1Irrep, b::CU1Irrep, c::CU1Irrep)
R = convert(sectorscalartype(CU1Irrep), Nsymbol(a, b, c))
R = convert(braidingscalartype(CU1Irrep), Nsymbol(a, b, c))
return c.s == 1 && a.j > 0 ? -R : R
end

function fusiontensor(a::CU1Irrep, b::CU1Irrep, c::CU1Irrep)
C = fill(0.0, dim(a), dim(b), dim(c), 1)
C = fill(zero(sectorscalartype(CU1Irrep)), dim(a), dim(b), dim(c), 1)
!Nsymbol(a, b, c) && return C
if c.j == 0
if a.j == b.j == 0
Expand Down
6 changes: 4 additions & 2 deletions src/irreps/dnirrep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ function Base.getproperty(a::DNIrrep{N}, sym::Symbol) where {N}
end

FusionStyle(::Type{DNIrrep{N}}) where {N} = N < 3 ? UniqueFusion() : SimpleFusion()
fusionscalartype(::Type{DNIrrep{N}}) where {N} = Float64
braidingscalartype(::Type{DNIrrep{N}}) where {N} = Float64
sectorscalartype(::Type{DNIrrep{N}}) where {N} = Float64

unit(::Type{DNIrrep{N}}) where {N} = DNIrrep{N}(0, false)
Expand Down Expand Up @@ -186,7 +188,7 @@ function Nsymbol(a::DNIrrep{N}, b::DNIrrep{N}, c::DNIrrep{N}) where {N}
end

function Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {N, I <: DNIrrep{N}}
T = sectorscalartype(I)
T = fusionscalartype(I)
(Nsymbol(a, b, e) & Nsymbol(e, c, d) & Nsymbol(b, c, f) & Nsymbol(a, f, d)) || return zero(T)

# tensoring with units gives 1
Expand All @@ -206,7 +208,7 @@ function Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {N, I <: DNIrrep{N}}
end

function Rsymbol(a::I, b::I, c::I) where {N, I <: DNIrrep{N}}
R = convert(sectorscalartype(I), Nsymbol(a, b, c))
R = convert(braidingscalartype(I), Nsymbol(a, b, c))
return ifelse((c.j == 0) & c.isodd & !(a.j == b.j == 0) & !((2 * a.j) == (2 * b.j) == N), -R, R)
end

Expand Down
18 changes: 12 additions & 6 deletions src/irreps/irreps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,26 @@ function Base.show(io::IO, c::AbstractIrrep)
end

const AbelianIrrep{G} = AbstractIrrep{G} where {G <: AbelianGroup}

FusionStyle(::Type{<:AbelianIrrep}) = UniqueFusion()
fusionscalartype(::Type{<:AbelianIrrep}) = Int
braidingscalartype(::Type{<:AbelianIrrep}) = Int
sectorscalartype(::Type{<:AbelianIrrep}) = Int
dimscalartype(::Type{<:AbelianIrrep}) = Int

Nsymbol(a::I, b::I, c::I) where {I <: AbelianIrrep} = c == first(a ⊗ b)
function Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I <: AbelianIrrep}
return Int(Nsymbol(a, b, e) * Nsymbol(e, c, d) * Nsymbol(b, c, f) * Nsymbol(a, f, d))
T = fusionscalartype(I)
return T(Nsymbol(a, b, e) * Nsymbol(e, c, d) * Nsymbol(b, c, f) * Nsymbol(a, f, d))
end
frobenius_schur_phase(a::AbelianIrrep) = 1
Asymbol(a::I, b::I, c::I) where {I <: AbelianIrrep} = Int(Nsymbol(a, b, c))
Bsymbol(a::I, b::I, c::I) where {I <: AbelianIrrep} = Int(Nsymbol(a, b, c))
Rsymbol(a::I, b::I, c::I) where {I <: AbelianIrrep} = Int(Nsymbol(a, b, c))
frobenius_schur_phase(a::AbelianIrrep) = one(fusionscalartype(typeof(a)))
Asymbol(a::I, b::I, c::I) where {I <: AbelianIrrep} = fusionscalartype(I)(Nsymbol(a, b, c))
Bsymbol(a::I, b::I, c::I) where {I <: AbelianIrrep} = fusionscalartype(I)(Nsymbol(a, b, c))
Rsymbol(a::I, b::I, c::I) where {I <: AbelianIrrep} = braidingscalartype(I)(Nsymbol(a, b, c))

function fusiontensor(a::I, b::I, c::I) where {I <: AbelianIrrep}
return fill(Int(Nsymbol(a, b, c)), (1, 1, 1, 1))
T = sectorscalartype(I)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that it matters, but from the perspective that the Fsymbols can be determined by contracting fusiontensors, I think it makes sense that fusiontensors have fusionscalartype as scalar type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But in the cases where fusiontensor exists, it also determines the Rsybmol, so I can also see the sectorscalartype motivation.

return fill(T(Nsymbol(a, b, c)), (1, 1, 1, 1))
end

include("znirrep.jl")
Expand Down
16 changes: 9 additions & 7 deletions src/irreps/su2irrep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ findindex(::SectorValues{SU2Irrep}, s::SU2Irrep) = twice(s.j) + 1
dim(s::SU2Irrep) = twice(s.j) + 1

FusionStyle(::Type{SU2Irrep}) = SimpleFusion()
fusionscalartype(::Type{SU2Irrep}) = Float64
braidingscalartype(::Type{SU2Irrep}) = Float64
sectorscalartype(::Type{SU2Irrep}) = Float64

Nsymbol(sa::SU2Irrep, sb::SU2Irrep, sc::SU2Irrep) = WignerSymbols.δ(sa.j, sb.j, sc.j)
Expand All @@ -56,26 +58,26 @@ function Fsymbol(
else
return sqrtdim(s5) * sqrtdim(s6) *
WignerSymbols.racahW(
sectorscalartype(SU2Irrep), s1.j, s2.j, s4.j, s3.j,
fusionscalartype(SU2Irrep), s1.j, s2.j, s4.j, s3.j,
s5.j, s6.j
)
end
end

function Rsymbol(sa::SU2Irrep, sb::SU2Irrep, sc::SU2Irrep)
Nsymbol(sa, sb, sc) || return zero(sectorscalartype(SU2Irrep))
return iseven(convert(Int, sa.j + sb.j - sc.j)) ? one(sectorscalartype(SU2Irrep)) :
-one(sectorscalartype(SU2Irrep))
T = braidingscalartype(SU2Irrep)
Nsymbol(sa, sb, sc) || return zero(T)
return iseven(convert(Int, sa.j + sb.j - sc.j)) ? one(T) : -one(T)
end

function fusiontensor(a::SU2Irrep, b::SU2Irrep, c::SU2Irrep)
C = Array{Float64}(undef, dim(a), dim(b), dim(c), 1)
T = sectorscalartype(SU2Irrep)
C = Array{T}(undef, dim(a), dim(b), dim(c), 1)
ja, jb, jc = a.j, b.j, c.j

for kc in 1:dim(c), kb in 1:dim(b), ka in 1:dim(a)
C[ka, kb, kc, 1] = WignerSymbols.clebschgordan(
ja, ja + 1 - ka, jb, jb + 1 - kb, jc,
jc + 1 - kc
T, ja, ja + 1 - ka, jb, jb + 1 - kb, jc, jc + 1 - kc
)
end
return C
Expand Down
10 changes: 7 additions & 3 deletions src/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
Precompile common methods for the given sector type.
"""
function precompile_sector(::Type{I}) where {I <: Sector}
precompile(FusionStyle, (I,))
precompile(BraidingStyle, (I,))

precompile(sectorscalartype, (I,))
precompile(fusionscalartype, (I,))
precompile(braidingscalartype, (I,))

precompile(Nsymbol, (I, I, I))
precompile(Fsymbol, (I, I, I, I, I, I))
precompile(Rsymbol, (I, I, I))
Expand All @@ -15,9 +22,6 @@ function precompile_sector(::Type{I}) where {I <: Sector}
precompile(⊗, (I, I, I))
precompile(⊗, (I, I, I, I))

precompile(FusionStyle, (I,))
precompile(BraidingStyle, (I,))

precompile(dim, (I,))
precompile(sqrtdim, (I,))
precompile(invsqrtdim, (I,))
Expand Down
39 changes: 19 additions & 20 deletions src/product.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Base.iterate(s::ProductSector, args...) = iterate(s.sectors, args...)
Base.indexed_iterate(s::ProductSector, args...) = Base.indexed_iterate(s.sectors, args...)

_sectors(::Type{Tuple{}}) = ()
Base.@pure function _sectors(::Type{T}) where {T <: SectorTuple}
@assume_effects :foldable function _sectors(::Type{T}) where {T <: SectorTuple}
return (Base.tuple_type_head(T), _sectors(Base.tuple_type_tail(T))...)
end

Expand Down Expand Up @@ -215,14 +215,23 @@ end
function FusionStyle(::Type{<:ProductSector{T}}) where {T <: SectorTuple}
return mapreduce(FusionStyle, &, _sectors(T))
end
@assume_effects :foldable function fusionscalartype(::Type{<:ProductSector{T}}) where {T <: SectorTuple}
return typeof(prod(zero ∘ fusionscalartype, _sectors(T)))
end
function UnitStyle(::Type{<:ProductSector{T}}) where {T <: SectorTuple}
return mapreduce(UnitStyle, &, _sectors(T))
end
function BraidingStyle(::Type{<:ProductSector{T}}) where {T <: SectorTuple}
return mapreduce(BraidingStyle, &, _sectors(T))
end
function sectorscalartype(::Type{<:ProductSector{T}}) where {T <: SectorTuple}
return mapreduce(sectorscalartype, promote_type, _sectors(T))
@assume_effects :foldable function braidingscalartype(::Type{<:ProductSector{T}}) where {T <: SectorTuple}
return typeof(prod(zero ∘ braidingscalartype, _sectors(T)))
end
@assume_effects :foldable function sectorscalartype(::Type{<:ProductSector{T}}) where {T <: SectorTuple}
return typeof(prod(zero ∘ sectorscalartype, _sectors(T)))
end
@assume_effects :foldable function dimscalartype(::Type{<:ProductSector{T}}) where {T <: SectorTuple}
return typeof(prod(zero ∘ dimscalartype, _sectors(T)))
end

fermionparity(P::ProductSector) = mapreduce(fermionparity, xor, P.sectors)
Expand Down Expand Up @@ -272,20 +281,10 @@ group representations, we have `Irrep[G₁] ⊠ Irrep[G₂] == Irrep[G₁ × G
⊠(I1::Type{Trivial}, I2::Type{<:Sector}) = I2

⊠(I1::Type{<:ProductSector}, I2::Type{Trivial}) = I1
@static if VERSION >= v"1.8"
Base.@assume_effects :foldable function ⊠(
I1::Type{<:ProductSector}, I2::Type{<:ProductSector}
)
T1 = I1.parameters[1]
T2 = I2.parameters[1]
return ProductSector{Tuple{T1.parameters..., T2.parameters...}}
end
else
Base.@pure function ⊠(I1::Type{<:ProductSector}, I2::Type{<:ProductSector})
T1 = I1.parameters[1]
T2 = I2.parameters[1]
return ProductSector{Tuple{T1.parameters..., T2.parameters...}}
end
@assume_effects :foldable function ⊠(I1::Type{<:ProductSector}, I2::Type{<:ProductSector})
T1 = I1.parameters[1]
T2 = I2.parameters[1]
return ProductSector{Tuple{T1.parameters..., T2.parameters...}}
end
⊠(I1::Type{<:ProductSector}, I2::Type{<:Sector}) = I1 ⊠ ProductSector{Tuple{I2}}

Expand Down Expand Up @@ -366,9 +365,9 @@ function type_repr(::Type{ProductSector{T}}) where {T <: Tuple{Vararg{AbstractIr
end

function Base.getindex(::IrrepTable, ::Type{ProductGroup{Gs}}) where {Gs <: GroupTuple}
G1 = tuple_type_head(Gs)
Grem = tuple_type_tail(Gs)
return ProductSector{Tuple{Irrep[G1]}} ⊠ Irrep[ProductGroup{tuple_type_tail(Gs)}]
G1 = Base.tuple_type_head(Gs)
Grem = Base.tuple_type_tail(Gs)
return ProductSector{Tuple{Irrep[G1]}} ⊠ Irrep[ProductGroup{Grem}]
end
function Base.getindex(::IrrepTable, ::Type{ProductGroup{Tuple{G}}}) where {G <: Group}
return ProductSector{Tuple{Irrep[G]}}
Expand Down
Loading