From e6188c3876e20f177906529a5954ab3fe6c9d48f Mon Sep 17 00:00:00 2001 From: Chenqi Meng Date: Tue, 21 Apr 2026 23:57:05 +0800 Subject: [PATCH 1/4] Added dual to S matrix convension --- src/sectors.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sectors.jl b/src/sectors.jl index 4234abdb..52186753 100644 --- a/src/sectors.jl +++ b/src/sectors.jl @@ -691,7 +691,7 @@ hopflink(a::I, b::I) where {I <: Sector} = sum(dim(c) * tr(Rsymbol(a, b, c) * Rs """ Smatrix(::Type{I}) where {I <: Sector} -Return the S-matrix of the sector type `I`, which is a matrix containing the hopflinks of all pairs of sectors of type `I`. +Return the S-matrix of the sector type `I`, which is a matrix containing the hopflinks of all pairs of sectors of type `I`, with the second sector being taken dual. The S-matrix is not normalized by the total quantum dimension here. """ function Smatrix(::Type{I}) where {I <: Sector} @@ -699,7 +699,7 @@ function Smatrix(::Type{I}) where {I <: Sector} throw(ArgumentError("Only defined for sectors with a finite number of simple objects")) vals = values(I) l = length(vals) - return reshape([hopflink(a, b) for a in vals, b in vals], (l, l)) + return reshape([hopflink(a, dual(b)) for a in vals, b in vals], (l, l)) end """ From 13769bf49422e4ee495ca4b3213db9ee7eb9f5fc Mon Sep 17 00:00:00 2001 From: Chenqi Meng Date: Tue, 21 Apr 2026 23:57:22 +0800 Subject: [PATCH 2/4] Allow non-modular central charge --- src/sectors.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sectors.jl b/src/sectors.jl index 52186753..e11463e7 100644 --- a/src/sectors.jl +++ b/src/sectors.jl @@ -715,12 +715,12 @@ end """ topological_central_charge(::Type{I}) where {I <: Sector} -Return the topological central charge c of the modular sector type `I`, where c is determined mod 8. +Return the topological central charge c of the braided sector type `I`, where c is determined mod 8. We choose convention by restrict the returning value as rational numbers in (-4, 4]. """ function topological_central_charge(::Type{I}) where {I <: Sector} ξ = sum(dim(a)^2 * twist(a) for a in values(I)) / dim(I) - @assert isapprox(abs(ξ), 1) "Sector $I is not modular" + isapprox(abs(ξ), 0) && return missing # For non-modular categories, central charge is also meaningful. See https://arxiv.org/pdf/1602.05946. For super modular category, Gauss sum vanishes, and its central charge needs to be defined in another manner: https://arxiv.org/pdf/1603.09294. c_float = angle(ξ) * 8 / (2π) isapprox(c_float, -4) && return 4 // 1 From 684e69a045b9310c985fe7027bd9bff391039494 Mon Sep 17 00:00:00 2001 From: Chenqi Meng Date: Wed, 22 Apr 2026 22:36:40 +0800 Subject: [PATCH 3/4] =?UTF-8?q?Add=20issymmetric/istransparent/M=C3=BCger?= =?UTF-8?q?=20features?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Export and implement utilities to detect symmetric sectors, transparent objects, and compute the Müger centralizer. TensorKitSectors.jl exports new symbols (issymmetric, istransparent, Muger_centralizier and unicode alias Müger_centralizier). sectors.jl adds implementations: issymmetric (uses S-matrix), istransparent (checks hopflink against quantum dimensions), and Muger_centralizier (filters transparent objects). Tests in test/runtests.jl are expanded to validate these behaviours across Tannakian, Super-Tannakian, UMTC, and UMTC-over-RepG examples, asserting expected modularity, symmetry, transparency, and centralizer contents. --- src/TensorKitSectors.jl | 3 ++- src/sectors.jl | 25 ++++++++++++++++++++++ test/runtests.jl | 47 ++++++++++++++++++++++++++++++++--------- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/TensorKitSectors.jl b/src/TensorKitSectors.jl index bceb3f88..0a7bbef4 100644 --- a/src/TensorKitSectors.jl +++ b/src/TensorKitSectors.jl @@ -8,7 +8,7 @@ export Irrep, GroupElement export Nsymbol, Fsymbol, Rsymbol, Asymbol, Bsymbol export sectorscalartype, fusionscalartype, braidingscalartype, dimscalartype export dim, sqrtdim, invsqrtdim, frobenius_schur_indicator, frobenius_schur_phase, twist, fusiontensor, dual -export topological_spin, hopflink, Tmatrix, Smatrix, ismodular, topological_central_charge +export topological_spin, hopflink, Tmatrix, Smatrix, ismodular, issymmetric, istransparent, Muger_centralizier, topological_central_charge export otimes, deligneproduct, times export FusionStyle, UniqueFusion, MultipleFusion, SimpleFusion, GenericFusion, MultiplicityFreeFusion export BraidingStyle, NoBraiding, HasBraiding, SymmetricBraiding, Bosonic, Fermionic, Anyonic @@ -39,6 +39,7 @@ export ⊠, ⊗, × export Cyclic, ℤ, ℤ₂, ℤ₃, ℤ₄, U₁, SU, SU₂, Dihedral, D₃, D₄, CU₁ export Alternating, A₄ export fℤ₂, fU₁, fSU₂ +export Müger_centralizier # public # ------ diff --git a/src/sectors.jl b/src/sectors.jl index e11463e7..da1f761e 100644 --- a/src/sectors.jl +++ b/src/sectors.jl @@ -712,6 +712,31 @@ function ismodular(::Type{II}; kwargs...) where {II <: Sector} return isapprox(s' * s, dim(II)^2 * I(size(s)[1]); kwargs...) end +""" + issymmetric(::Type{I}; kwargs...) where {I <: Sector} + +Check whether a sector type `I` is symmetric, i.e. the S-matrix is fully degenerate. +""" +function issymmetric(::Type{I}; kwargs...) where {I <: Sector} + s = Smatrix(I) + dims = vec(dim.(values(I))) + return isapprox(s, dims * dims'; kwargs...) +end + +""" + istransparent(a::I; kwargs...) where {I <: Sector} + +Check whether a sector `a` in sector type `I` braids trivially with other sectors in `I`. +""" +istransparent(a::I; kwargs...) where {I <: Sector} = all(b -> isapprox(hopflink(a, b), dim(a) * dim(b); kwargs...), values(I)) + +""" + Muger_centralizier(::Type{I}; kwargs...) where {I <: Sector} +""" +Muger_centralizier(::Type{I}; kwargs...) where {I <: Sector} = vec(collect(filter(obj -> istransparent(obj; kwargs...), values(I)))) + +const Müger_centralizier = Muger_centralizier + """ topological_central_charge(::Type{I}) where {I <: Sector} diff --git a/test/runtests.jl b/test/runtests.jl index 86addc51..d424225a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -265,16 +265,43 @@ end end end -@testset "Ismodular" begin - @test !ismodular(Z2Irrep) - @test !ismodular(Z3Irrep) - @test !ismodular(FermionParity) - @test !ismodular(A4Irrep) - @test !ismodular(IsingAnyon ⊠ Z2Irrep) - @test ismodular(IsingAnyon) - @test ismodular(FibonacciAnyon) - @test ismodular(TimeReversed{IsingAnyon}) - @test ismodular(IsingAnyon ⊠ TimeReversed{IsingAnyon}) +@testset "Ismodular, issymmetric, istransparent and Müger_centralizier" begin + Tannakian_list = [Z2Irrep, Z3Irrep, FermionParity, A4Irrep, D3Irrep, D4Irrep, Z2Irrep ⊠ D4Irrep, D3Irrep ⊠ A4Irrep] + Super_Tannakian_list = [FermionParity, FermionParity ⊠ A4Irrep, FermionParity ⊠ Z3Irrep, D4Irrep ⊠ FermionParity] + UMTC_list = [ + IsingAnyon, FibonacciAnyon, TimeReversed{IsingAnyon}, TimeReversed{FibonacciAnyon}, + FibonacciAnyon ⊠ FibonacciAnyon, FibonacciAnyon ⊠ IsingAnyon, IsingAnyon ⊠ TimeReversed{IsingAnyon}, + TimeReversed{FibonacciAnyon} ⊠ IsingAnyon, IsingAnyon ⊠ IsingAnyon ⊠ IsingAnyon, + IsingAnyon ⊠ FibonacciAnyon ⊠ IsingAnyon ⊠ TimeReversed{IsingAnyon} ⊠ TimeReversed{FibonacciAnyon}, + ] + UMTC_over_RepG_list = [Z2Irrep ⊠ IsingAnyon, Z3Irrep ⊠ FibonacciAnyon, D3Irrep ⊠ TimeReversed{IsingAnyon}, A4Irrep ⊠ FibonacciAnyon ⊠ TimeReversed{IsingAnyon}] + + for sect in [Tannakian_list..., Super_Tannakian_list...] + @test !ismodular(sect) + @test issymmetric(sect) + for charge in values(sect) + @test istransparent(charge) + end + @test Müger_centralizier(sect) == vec(collect(values(sect))) + end + + for sect in UMTC_list + @test ismodular(sect) + @test !issymmetric(sect) + for anyon in values(sect) + anyon == unit(sect) && continue + @test !istransparent(anyon) + end + @test Müger_centralizier(sect) == [unit(sect)] + end + + for sect in UMTC_over_RepG_list + charge_part = (TensorKitSectors._sectors)(sect)[1] + @test !ismodular(sect) + @test !issymmetric(sect) + @test map(x -> x[1], Müger_centralizier(sect)) == collect(values(charge_part)) + end + end @testset "Total quantum dimension" begin From c655b2edfee7d87af5a7e80d8946a70ff8dd1824 Mon Sep 17 00:00:00 2001 From: Chenqi Meng Date: Fri, 24 Apr 2026 00:15:47 +0800 Subject: [PATCH 4/4] commit some advised changes --- src/TensorKitSectors.jl | 3 +-- src/sectors.jl | 23 +++++++++++++---------- test/runtests.jl | 6 +++--- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/TensorKitSectors.jl b/src/TensorKitSectors.jl index 0a7bbef4..553486b2 100644 --- a/src/TensorKitSectors.jl +++ b/src/TensorKitSectors.jl @@ -8,7 +8,7 @@ export Irrep, GroupElement export Nsymbol, Fsymbol, Rsymbol, Asymbol, Bsymbol export sectorscalartype, fusionscalartype, braidingscalartype, dimscalartype export dim, sqrtdim, invsqrtdim, frobenius_schur_indicator, frobenius_schur_phase, twist, fusiontensor, dual -export topological_spin, hopflink, Tmatrix, Smatrix, ismodular, issymmetric, istransparent, Muger_centralizier, topological_central_charge +export topological_spin, hopflink, Tmatrix, Smatrix, ismodular, hassymmetricbraiding, istransparent, centralizer, topological_central_charge export otimes, deligneproduct, times export FusionStyle, UniqueFusion, MultipleFusion, SimpleFusion, GenericFusion, MultiplicityFreeFusion export BraidingStyle, NoBraiding, HasBraiding, SymmetricBraiding, Bosonic, Fermionic, Anyonic @@ -39,7 +39,6 @@ export ⊠, ⊗, × export Cyclic, ℤ, ℤ₂, ℤ₃, ℤ₄, U₁, SU, SU₂, Dihedral, D₃, D₄, CU₁ export Alternating, A₄ export fℤ₂, fU₁, fSU₂ -export Müger_centralizier # public # ------ diff --git a/src/sectors.jl b/src/sectors.jl index da1f761e..b3284a73 100644 --- a/src/sectors.jl +++ b/src/sectors.jl @@ -713,29 +713,32 @@ function ismodular(::Type{II}; kwargs...) where {II <: Sector} end """ - issymmetric(::Type{I}; kwargs...) where {I <: Sector} + hassymmetricbraiding(::Type{I}; kwargs...) where {I <: Sector} Check whether a sector type `I` is symmetric, i.e. the S-matrix is fully degenerate. """ -function issymmetric(::Type{I}; kwargs...) where {I <: Sector} - s = Smatrix(I) - dims = vec(dim.(values(I))) - return isapprox(s, dims * dims'; kwargs...) +function hassymmetricbraiding(::Type{I}; kwargs...) where {I <: Sector} + @assert BraidingStyle(I) isa HasBraiding "The sector type $I is not braided" + if BraidingStyle(I) isa SymmetricBraiding + return true + else + return all(a -> istransparent(a; kwargs...), values(I)) + end end """ istransparent(a::I; kwargs...) where {I <: Sector} -Check whether a sector `a` in sector type `I` braids trivially with other sectors in `I`. +Check whether a sector `a` in the sector type `I` braids trivially with other sectors in `I`. """ istransparent(a::I; kwargs...) where {I <: Sector} = all(b -> isapprox(hopflink(a, b), dim(a) * dim(b); kwargs...), values(I)) """ - Muger_centralizier(::Type{I}; kwargs...) where {I <: Sector} -""" -Muger_centralizier(::Type{I}; kwargs...) where {I <: Sector} = vec(collect(filter(obj -> istransparent(obj; kwargs...), values(I)))) + centralizer(::Type{I}; kwargs...) where {I <: Sector} -const Müger_centralizier = Muger_centralizier +Collect all transparent sectors in the sector type `I`. +""" +centralizer(::Type{I}; kwargs...) where {I <: Sector} = vec(collect(filter(obj -> istransparent(obj; kwargs...), values(I)))) """ topological_central_charge(::Type{I}) where {I <: Sector} diff --git a/test/runtests.jl b/test/runtests.jl index d424225a..289cdfce 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -282,7 +282,7 @@ end for charge in values(sect) @test istransparent(charge) end - @test Müger_centralizier(sect) == vec(collect(values(sect))) + @test centralizier(sect) == vec(collect(values(sect))) end for sect in UMTC_list @@ -292,14 +292,14 @@ end anyon == unit(sect) && continue @test !istransparent(anyon) end - @test Müger_centralizier(sect) == [unit(sect)] + @test centralizier(sect) == [unit(sect)] end for sect in UMTC_over_RepG_list charge_part = (TensorKitSectors._sectors)(sect)[1] @test !ismodular(sect) @test !issymmetric(sect) - @test map(x -> x[1], Müger_centralizier(sect)) == collect(values(charge_part)) + @test map(x -> x[1], centralizier(sect)) == collect(values(charge_part)) end end