diff --git a/docs/make.jl b/docs/make.jl index 35ba3604..71183952 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -58,6 +58,9 @@ makedocs(; "Group Elements" => [ "ℤₙ (Cyclic)" => "sectors/groupelement/znelement.md", ], + "Other" => [ + "ℤₙ-Tambara-Yamagami" => "sectors/other/ty.md", + ], "Composite Sectors" => [ "Product" => "sectors/composite/product.md", "Named" => "sectors/composite/named.md", diff --git a/docs/src/sectors.md b/docs/src/sectors.md index f3f365bc..ad993c1d 100644 --- a/docs/src/sectors.md +++ b/docs/src/sectors.md @@ -17,6 +17,7 @@ This page provides an overview of the concrete sector types implemented in Tenso | [`HeisenbergIrrep`](@ref)| Rep[H_N] | Generic | Bosonic | No | Weyl-Heisenberg symmetry, projective representations | | [`FibonacciAnyon`](@ref) | Fibonacci category | Simple | Anyonic | No | Topological quantum computing | | [`IsingAnyon`](@ref) | Ising category | Simple | Anyonic | No | Majorana fermions, ν=5/2 QHE | +| [`TambaraYamagami`](@ref) | ℤₙ-Tambara-Yamagami category | Simple | No | No | Self-dual spin chains | | [`FermionParity`](@ref) | fℤ₂ | Unique | Fermionic | No | Fermion parity conservation | | [`FermionNumber`](@ref) | fU₁ | Unique | Fermionic | Yes | Fermion number conservation | | [`FermionSpin`](@ref) | fSU₂ | Simple | Fermionic | Yes | Fermions with spin symmetry | diff --git a/docs/src/sectors/other/ty.md b/docs/src/sectors/other/ty.md new file mode 100644 index 00000000..78461f08 --- /dev/null +++ b/docs/src/sectors/other/ty.md @@ -0,0 +1,52 @@ +# The $\mathbb Z_N$-Tambara-Yamagami categories: `TambaraYamagami` + +`TambaraYamagami{N, K}` represents the Tambara-Yamagami fusion category ${\rm TY}(\mathbb Z_N, K)$ based on the cyclic group of order $N$. + +The $N+1$ simple objects coincide with the group elements of $\mathbb Z_N$ supplemented with one non-invertible object $m$. The type parameter `K` specifies the Frobenius-Schur indicator of $m$ as $\varkappa_m = (-1)^K = \pm 1$, i.e. `K = false` corresponds to $\varkappa_m = 1$ and `K = true` to $\varkappa_m = -1$. + +## Sector type + +```@docs; canonical = false +TambaraYamagami +``` +Here, the type parameters `N` and `K` correspond respectively to the order of the underlying cyclic group and the Frobenius-Schur sign $(-1)^K$ of the non-invertible object. + +## Fusion Rules + +The non-trivial fusion rules read + +```math +g ⊗ h = g + h \mod N, \qquad g ⊗ m = m ⊗ g = m, \qquad m ⊗ m = \bigoplus_{g ∈ ℤ_N} g, +``` +for all group elements $g, h \in \mathbb Z_N$. + +Hence `FusionStyle(::Type{<:TambaraYamagami}) = SimpleFusion()`. + +The quantum dimensions are + +```math +d_g = 1, \quad \forall g\in\mathbb Z_N, \quad {\rm and} \quad d_m = \sqrt{N}. +``` + +## Topological Data + +We write $χ(g, h) = \exp(2π i g h / N)$ for a normalised non-degenerate symmetric bicharacter on $\mathbb Z_N$. The nontrivial F-symbols are then given by + +```math +F^{g\,m\,h}_{m} = χ(g, h), \qquad +F^{m\,g\,m}_{h} = χ(g, h), \qquad +\left[F^{m\,m\,m}_{m}\right]_g^h = \frac{\varkappa_m}{\sqrt{N}}\,\overline{χ(g, h)}, +``` + +for all $g, h \in \mathbb Z_N$. + +Crucially, there exists no braiding on this fusion category, except when $N=2$, in which case it coincides with `IsingAnyon`. + +## Iteration and basis conventions +`values(TambaraYamagami{N,K})` iterates the labels `0, 1, …, N-1,:m` in increasing order. + +## References +[1] D. Tambara and S. Yamagami, *Tensor categories with fusion rules of self-duality for + finite abelian groups*, J. Algebra **209**, 692-707 (1998). + +[2] M. Barkeshli, P. Bonderson, M. Cheng and Z. Wang, *Symmetry Fractionalization, Defects, and Gauging of Topological Phases*, Phys. Rev. B **100**, 115147 (2019), [arXiv:1410.4540](https://arxiv.org/abs/1410.4540). \ No newline at end of file diff --git a/src/TensorKitSectors.jl b/src/TensorKitSectors.jl index 69a5b54c..1186ab84 100644 --- a/src/TensorKitSectors.jl +++ b/src/TensorKitSectors.jl @@ -29,6 +29,7 @@ export ZNElement, Z2Element, Z3Element, Z4Element export ProductSector, NamedSector, @NamedSector, TimeReversed export FermionParity, FermionNumber, FermionSpin export PlanarTrivial, FibonacciAnyon, IsingAnyon +export TambaraYamagami export IsingBimodule # accessors @@ -83,6 +84,7 @@ include("named.jl") # named tuple product of different sectors include("fermions.jl") # irreps with defined fermionparity and fermionic braiding include("anyons.jl") # non-group sectors include("multifusion.jl") # multifusion example, namely Rep Z2 ⊕ Rep Z2 ≅ Ising +include("ty.jl") # Tambara-Yamagami category for ℤ_N # precompile # ---------- diff --git a/src/ty.jl b/src/ty.jl new file mode 100644 index 00000000..81d2e367 --- /dev/null +++ b/src/ty.jl @@ -0,0 +1,142 @@ +# Tambara-Yamagami category for the cyclic group ℤ_N +#---------------------------------------------------------------------------------------# +""" + struct TambaraYamagami{N, K} <: Sector + TambaraYamagami{N, K}(n::Integer) + +Represents the Tambara-Yamagami fusion category built from the cyclic group ``ℤ_N``. +The simple objects are the group elements `0, 1, …, N - 1` of ``ℤ_N``, +together with a single non-invertible object `m`. + +The non-trivial fusion rules are given by +```math +g ⊗ h = g + h \\mod N, \\qquad g ⊗ m = m ⊗ g = m, \\qquad m ⊗ m = \\bigoplus_{g ∈ ℤ_N} g. +``` + +The F-symbols are constructed from a non-degenerate symmetric bicharacter +``χ(g, h) = \\exp(2π i g h / N)``, together with a Frobenius-Schur sign for the +non-invertible object; the latter is fixed as `κ = (-1)^K` through the type parameter +`K::Bool`. For fixed `N`, the two choices `K = false` (`κ = 1`) and `K = true` (`κ = -1`) +generally give distinct fusion categories. + +Only the case `N == 2` and `K == false` admits a braiding, as this case coincides with Ising, but this is not currently implemented. + +## Fields +- `n::UInt8`: a group element for `0 <= n < N`, or the non-invertible object `m` for `n == N`. + +## References +[1] D. Tambara and S. Yamagami, *Tensor categories with fusion rules of self-duality for + finite abelian groups*, J. Algebra **209**, 692-707 (1998). +[2] M. Barkeshli, P. Bonderson, M. Cheng and Z. Wang, *Symmetry Fractionalization, Defects, + and Gauging of Topological Phases*, Phys. Rev. B **100**, 115147 (2019), + [arXiv:1410.4540](https://arxiv.org/abs/1410.4540). +""" +struct TambaraYamagami{N, K} <: Sector + n::UInt8 + function TambaraYamagami{N, K}(n) where {N, K} + _check_TY_typeparams(N, K) + 0 <= n <= N || throw(DomainError(n, "TambaraYamagami{$N, $K} labels must satisfy 0 <= n <= $N")) + return new{N, K}(n) + end +end +function TambaraYamagami{N, K}(s::Symbol) where {N, K} + s === :m || throw(ArgumentError("Unknown label $s: use an integer or `:m`")) + return TambaraYamagami{N, K}(N) +end + +# Labels are stored as `UInt8`; restricting to `N <= 128` guarantees that the sum `a.n + b.n` +# of two group labels (at most `2(N - 1) = 254`) never overflows before taking it modulo `N`. +const SMALL_TY_CUTOFF = (typemax(UInt8) + 1) ÷ 2 + +function _check_TY_typeparams(N, K) + N isa Int && 1 <= N <= SMALL_TY_CUTOFF || throw(ArgumentError("N must be an Int satisfying 1 <= N <= $SMALL_TY_CUTOFF, got $N::$(typeof(N))")) + K isa Bool || throw(ArgumentError("K must be a Bool, encoding the Frobenius-Schur indicator (-1)^K, got $K")) + return nothing +end + +""" + modulus(n::TambaraYamagami{N, K}) -> N + modulus(::Type{<:TambaraYamagami{N, K}}) -> N + +The order of the cyclic group, or the modulus of the charge labels. +""" +modulus(n::TambaraYamagami) = modulus(typeof(n)) +modulus(::Type{<:TambaraYamagami{N, K}}) where {N, K} = N + +_ism(a::TambaraYamagami) = a.n == modulus(a) # Checks whether a is the non-invertible +_chi(a::I, b::I) where {I <: TambaraYamagami} = cispi(2 * a.n * b.n / modulus(I)) # Non-degenerate symmetric bicharacter on ℤ_N + +Base.length(::SectorValues{I}) where {I <: TambaraYamagami} = modulus(I) + 1 +Base.IteratorSize(::Type{SectorValues{I}}) where {I <: TambaraYamagami} = HasLength() +Base.@propagate_inbounds function Base.getindex(v::SectorValues{I}, i::Int) where {I <: TambaraYamagami} + @boundscheck 1 <= i <= length(v) || throw(BoundsError(v, i)) + return I(i - 1) +end +findindex(::SectorValues{I}, c::I) where {I <: TambaraYamagami} = Int(c.n) + 1 +Base.IteratorSize(::Type{<:SectorProductIterator{I}}) where {I <: TambaraYamagami} = HasLength() + +function Base.length(it::SectorProductIterator{I}) where {I <: TambaraYamagami} + return (_ism(it.a) && _ism(it.b)) ? modulus(I) : 1 +end +function Base.iterate(::SectorValues{I}, i::Int = 0) where {I <: TambaraYamagami} + return i > modulus(I) ? nothing : (I(i), i + 1) +end +function Base.iterate(it::SectorProductIterator{I}, state::Int = 0) where {I <: TambaraYamagami} + a, b = it.a, it.b + am, bm = _ism(a), _ism(b) + N = modulus(I) + if am && bm + state == N && return nothing + return I(state), state + 1 + else + state == 0 || return nothing + c = (am || bm) ? I(N) : I(mod(a.n + b.n, N)) + return c, 1 + end +end + +Base.isless(a1::I, a2::I) where {I <: TambaraYamagami} = isless(a1.n, a2.n) +dim(a::TambaraYamagami) = _ism(a) ? sqrt(float(modulus(a))) : 1.0 +unit(::Type{I}) where {I <: TambaraYamagami} = I(0) +dual(a::TambaraYamagami) = _ism(a) ? a : typeof(a)(mod(- Int(a.n), modulus(a))) + +FusionStyle(::Type{<:TambaraYamagami}) = SimpleFusion() +BraidingStyle(::Type{<:TambaraYamagami}) = NoBraiding() +fusionscalartype(::Type{<:TambaraYamagami}) = ComplexF64 + +function Nsymbol(a::I, b::I, c::I) where {N, I <: TambaraYamagami{N}} + am, bm, cm = _ism(a), _ism(b), _ism(c) + if am && bm + return !cm + elseif am || bm + return cm + else + return !cm && c.n == mod(a.n + b.n, N) + end +end + +function Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {N, K, I <: TambaraYamagami{N, K}} + T = fusionscalartype(I) + + (Nsymbol(a, b, e) && Nsymbol(e, c, d) && Nsymbol(b, c, f) && Nsymbol(a, f, d)) || return zero(T) + + am, bm, cm = _ism(a), _ism(b), _ism(c) + + if am && bm && cm # F^{mmm}_m + return ((1 - 2 * K) / sqrt(N)) * conj(_chi(e, f)) + elseif !am && bm && !cm # F^{gmh}_{m} + return _chi(a, c) + elseif am && !bm && cm # F^{mgm}_{h} + return _chi(b, d) + else # F^{abc}_{a+b+c} + return one(T) + end +end + +function Base.show(io::IO, a::TambaraYamagami) + print_type = get(io, :typeinfo, nothing) !== typeof(a) + print_type && print(io, type_repr(typeof(a)), "(") + print(io, _ism(a) ? ":m" : Int(a.n)) + print_type && print(io, ")") + return nothing +end diff --git a/test/runtests.jl b/test/runtests.jl index 9bb8d59a..0f50aded 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -30,6 +30,14 @@ const sectorlist = ( FibonacciAnyon ⊠ Z4Element{3}, IsingBimodule, IsingBimodule ⊠ IsingBimodule, IsingBimodule ⊠ Z2Irrep, IsingBimodule ⊠ SU2Irrep, IsingBimodule ⊠ FibonacciAnyon, + TambaraYamagami{1, false}, TambaraYamagami{1, true}, + TambaraYamagami{2, false}, TambaraYamagami{2, true}, + TambaraYamagami{4, false}, TambaraYamagami{4, true}, + TambaraYamagami{7, false}, TambaraYamagami{8, true}, + TambaraYamagami{67, false}, TambaraYamagami{128, false}, + TambaraYamagami{3, true} ⊠ TambaraYamagami{2, true}, TambaraYamagami{2, false} ⊠ Z3Irrep, + TambaraYamagami{3, true} ⊠ FibonacciAnyon, TambaraYamagami{5, true} ⊠ IsingAnyon, + TambaraYamagami{64, false} ⊠ Z4Irrep, TambaraYamagami{128, true} ⊠ SU2Irrep, TimeReversed{Z2Irrep}, TimeReversed{Z3Irrep}, TimeReversed{Z4Irrep}, TimeReversed{A4Irrep}, TimeReversed{U1Irrep}, TimeReversed{CU1Irrep}, TimeReversed{SU2Irrep}, @@ -223,6 +231,22 @@ end end end +@testset "TambaraYamagami edge cases" begin + I = TambaraYamagami{3, true} + @test hash(I) isa UInt + @test hash(I(1)) == hash(I(1)) + @test hash(I(1)) != hash(I(2)) + @test_throws ArgumentError TambaraYamagami{UInt8(3), true}(1) + @test_throws ArgumentError TambaraYamagami{true, false}(0) + @test_throws ArgumentError TambaraYamagami{3, 1}(0) + for (i, c) in enumerate(values(I)) + @test values(I)[i] == c + @test findindex(values(I), c) === i + end + @test_throws BoundsError values(I)[0] + @test_throws BoundsError values(I)[5] +end + @testset "Converter constructions" begin @test IsingAnyon(:ψ) isa IsingAnyon @test (IsingAnyon ⊠ IsingAnyon)(:ψ, :σ) isa (IsingAnyon ⊠ IsingAnyon)