From 7607f73f2ac76605e6a57a8999f7b69e098827cd Mon Sep 17 00:00:00 2001 From: lkdvos Date: Thu, 28 May 2026 11:14:55 -0400 Subject: [PATCH 01/50] docs: set up documentation skeleton Adds the documentation plan, top-level make.jl with the full page navigation (home, sector interface subsection, sector types subsection, library), the index page formatting tweak, the sector overview summary table, the sector interface introduction page, and template pages for every concrete sector type (abelian, anyon, composite, fermionic, non-abelian). --- docs/make.jl | 35 ++++++++++++++++++ docs/src/index.md | 10 +++--- docs/src/interface/overview.md | 32 +++++++++++++++++ docs/src/sectors.md | 22 ++++++++++++ docs/src/sectors/abelian/trivial.md | 15 ++++++++ docs/src/sectors/abelian/u1.md | 29 +++++++++++++++ docs/src/sectors/abelian/zn.md | 41 ++++++++++++++++++++++ docs/src/sectors/anyons/fibonacci.md | 31 ++++++++++++++++ docs/src/sectors/anyons/ising.md | 31 ++++++++++++++++ docs/src/sectors/anyons/planartrivial.md | 27 ++++++++++++++ docs/src/sectors/composite/product.md | 33 +++++++++++++++++ docs/src/sectors/composite/timereversed.md | 29 +++++++++++++++ docs/src/sectors/fermions/number.md | 29 +++++++++++++++ docs/src/sectors/fermions/parity.md | 29 +++++++++++++++ docs/src/sectors/fermions/spin.md | 29 +++++++++++++++ docs/src/sectors/nonabelian/a4.md | 29 +++++++++++++++ docs/src/sectors/nonabelian/cu1.md | 29 +++++++++++++++ docs/src/sectors/nonabelian/dn.md | 39 ++++++++++++++++++++ 18 files changed, 513 insertions(+), 6 deletions(-) create mode 100644 docs/src/interface/overview.md create mode 100644 docs/src/sectors.md create mode 100644 docs/src/sectors/abelian/trivial.md create mode 100644 docs/src/sectors/abelian/u1.md create mode 100644 docs/src/sectors/abelian/zn.md create mode 100644 docs/src/sectors/anyons/fibonacci.md create mode 100644 docs/src/sectors/anyons/ising.md create mode 100644 docs/src/sectors/anyons/planartrivial.md create mode 100644 docs/src/sectors/composite/product.md create mode 100644 docs/src/sectors/composite/timereversed.md create mode 100644 docs/src/sectors/fermions/number.md create mode 100644 docs/src/sectors/fermions/parity.md create mode 100644 docs/src/sectors/fermions/spin.md create mode 100644 docs/src/sectors/nonabelian/a4.md create mode 100644 docs/src/sectors/nonabelian/cu1.md create mode 100644 docs/src/sectors/nonabelian/dn.md diff --git a/docs/make.jl b/docs/make.jl index 13f2ec05..af258e46 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -19,6 +19,41 @@ makedocs(; ), pages = [ "Home" => "index.md", + "Sector Interface" => [ + "Overview" => "interface/overview.md", + "Required Methods" => "interface/required.md", + "Optional Methods" => "interface/optional.md", + "Traits and Styles" => "interface/traits.md", + "Implementation Guidelines" => "interface/guidelines.md", + ], + "Sector Types" => [ + "Overview" => "sectors.md", + "Abelian Groups" => [ + "Trivial" => "sectors/abelian/trivial.md", + "ℤₙ (Cyclic)" => "sectors/abelian/zn.md", + "U₁" => "sectors/abelian/u1.md", + ], + "Non-Abelian Groups" => [ + "SU₂" => "sectors/nonabelian/su2.md", + "CU₁" => "sectors/nonabelian/cu1.md", + "Dₙ (Dihedral)" => "sectors/nonabelian/dn.md", + "A₄ (Alternating)" => "sectors/nonabelian/a4.md", + ], + "Anyonic Sectors" => [ + "PlanarTrivial" => "sectors/anyons/planartrivial.md", + "Fibonacci" => "sectors/anyons/fibonacci.md", + "Ising" => "sectors/anyons/ising.md", + ], + "Fermionic Sectors" => [ + "Fermion Parity" => "sectors/fermions/parity.md", + "Fermion Number" => "sectors/fermions/number.md", + "Fermion Spin" => "sectors/fermions/spin.md", + ], + "Composite Sectors" => [ + "Product" => "sectors/composite/product.md", + "Time-Reversed" => "sectors/composite/timereversed.md", + ], + ], "Library" => "lib.md", ], checkdocs = :exports, diff --git a/docs/src/index.md b/docs/src/index.md index fb7fdea5..60e387d1 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -2,11 +2,9 @@ A Julia package for working with objects in fusion categories. -This package provides functionality for defining objects in fusion categories, along with -their topological data. This includes the fusion rules, the associators, and the braiding. -In particular, this is the data that is needed to define (symmetric) tensors, which are -defined over vector spaces graded by these objects. For the full functionality, we refer to -[TensorKit.jl](https://github.com/QuantumKitHub/TensorKit.jl) and [its -documentation](https://quantumkithub.github.io/TensorKit.jl/stable/). +This package provides functionality for defining objects in fusion categories, along with their topological data. +This includes the fusion rules, the associators, and the braiding. +In particular, this is the data that is needed to define (symmetric) tensors, which are defined over vector spaces graded by these objects. +For the full functionality, we refer to [TensorKit.jl](https://github.com/QuantumKitHub/TensorKit.jl) and [its documentation](https://quantumkithub.github.io/TensorKit.jl/stable/). Install via the package manager. diff --git a/docs/src/interface/overview.md b/docs/src/interface/overview.md new file mode 100644 index 00000000..6c06cb3f --- /dev/null +++ b/docs/src/interface/overview.md @@ -0,0 +1,32 @@ +# Sector Interface + +## Introduction + +A `Sector` is a label for the different *symmetry charges* or *quantum numbers* that organize graded vector spaces. +In particular, these are the labels use to decompose vector spaces as: + +```math +V = \bigoplus_{a \in \text{Sectors}} \mathbb{C}^{n_a} \otimes V_a +``` + +where ``n_a`` is the multiplicity of sector ``a`` and ``V_a`` is the associated vector space. + +Sectors encode the structural rules TensorKit needs: +- **Objects**: the labels themselves (irreps, anyons, …) +- **Fusion rules**: which labels appear in ``a \otimes b \rightarrow \bigoplus_c N^{ab}_c c`` +- **Associativity**: how different parenthesizations are related +- **Braiding**: how labels behave under exchange (if supported) + +More rigorously, a `Sector` represents the isomorphism classes of simple objects in unitary and pivotal fusion categories. +This package defines an interface for accessing the topological data that is associated to these categories. +This section explains the required and optional methods needed to create a new sector type. +Once this interface is fulfilled, TensorKit.jl will create symmetric tensors that correspond to the implemented sector. + +## Organization + +The interface documentation is divided into several pages: + +- **[Required Methods](required.md)**: The minimum interface needed for a valid sector type +- **[Optional Methods](optional.md)**: Additional methods with default implementations that can be specialized +- **[Traits and Styles](traits.md)**: Compile-time properties that control behavior and optimizations +- **[Implementation Guidelines](guidelines.md)**: Practical advice and helper types for implementing sectors diff --git a/docs/src/sectors.md b/docs/src/sectors.md new file mode 100644 index 00000000..d13bfa17 --- /dev/null +++ b/docs/src/sectors.md @@ -0,0 +1,22 @@ +# Sector Types + +This page provides an overview of the concrete sector types implemented in TensorKitSectors.jl. + +## Summary Table + +| Sector Type | Group/Category | Fusion Style | Braiding | Infinite? | Common Use Cases | +|--------------------------|--------------------------|--------------|-----------|-----------|---------------------------------------| +| [`Trivial`](@ref) | Trivial group | Unique | Bosonic | No | No symmetry | +| [`ZNIrrep`](@ref) | ℤₙ (cyclic) | Unique | Bosonic | No | Clock models, discrete symmetries | +| [`U1Irrep`](@ref) | U(1) | Unique | Bosonic | Yes | Particle number, charge conservation | +| [`SU2Irrep`](@ref) | SU(2) | Simple | Bosonic | Yes | Spin systems, angular momentum | +| [`CU1Irrep`](@ref) | U(1) ⋊ ℤ₂ | Simple | Bosonic | Yes | Particle-hole symmetry, O(2) | +| [`DNIrrep`](@ref) | Dₙ (dihedral) | Simple | Bosonic | No | Molecular/crystal symmetries | +| [`A4Irrep`](@ref) | A₄ (alternating) | Generic | Bosonic | No | Tetrahedral symmetry | +| [`FibonacciAnyon`](@ref) | Fibonacci category | Simple | Anyonic | No | Topological quantum computing | +| [`IsingAnyon`](@ref) | Ising category | Simple | Anyonic | No | Majorana fermions, ν=5/2 QHE | +| [`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 | +| [`ProductSector`](@ref) | Product categories | Varies | Varies | Varies | Multiple simultaneous symmetries | +| [`TimeReversed`](@ref) | Inverted braiding | Varies | Varies | Varies | ?? | diff --git a/docs/src/sectors/abelian/trivial.md b/docs/src/sectors/abelian/trivial.md new file mode 100644 index 00000000..728ccaad --- /dev/null +++ b/docs/src/sectors/abelian/trivial.md @@ -0,0 +1,15 @@ +# Trivial Sector + +## Trivial + +### Type Definition + +### Construction + +### Labels + +### Fusion Rules + +### Quantum Dimensions + +### Topological Data diff --git a/docs/src/sectors/abelian/u1.md b/docs/src/sectors/abelian/u1.md new file mode 100644 index 00000000..8ab74f07 --- /dev/null +++ b/docs/src/sectors/abelian/u1.md @@ -0,0 +1,29 @@ +# U(1) Representations: U1Irrep + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +## Basis Conventions + +## Iteration Order + +## Code Examples + +## Implementation Notes diff --git a/docs/src/sectors/abelian/zn.md b/docs/src/sectors/abelian/zn.md new file mode 100644 index 00000000..8013bb43 --- /dev/null +++ b/docs/src/sectors/abelian/zn.md @@ -0,0 +1,41 @@ +# Cyclic Groups: ZNIrrep + +## Type Definition + +## Construction + +## Labels + +### ZNIrrep{N} + +### LargeZNIrrep{N} + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +## Basis Conventions + +## Iteration + +## Code Examples + +## Implementation Notes + +### Storage Details + +### Performance Considerations + +## Related Types + +### Z2Irrep, Z3Irrep, Z4Irrep diff --git a/docs/src/sectors/anyons/fibonacci.md b/docs/src/sectors/anyons/fibonacci.md new file mode 100644 index 00000000..f9c5e575 --- /dev/null +++ b/docs/src/sectors/anyons/fibonacci.md @@ -0,0 +1,31 @@ +# Fibonacci Anyons + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +### Twist + +## Code Examples + +## Implementation Notes + +### Key Values + +### References diff --git a/docs/src/sectors/anyons/ising.md b/docs/src/sectors/anyons/ising.md new file mode 100644 index 00000000..1b93e313 --- /dev/null +++ b/docs/src/sectors/anyons/ising.md @@ -0,0 +1,31 @@ +# Ising Anyons + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +### Twist + +## Code Examples + +## Implementation Notes + +### Key Values + +### References diff --git a/docs/src/sectors/anyons/planartrivial.md b/docs/src/sectors/anyons/planartrivial.md new file mode 100644 index 00000000..b48ae15e --- /dev/null +++ b/docs/src/sectors/anyons/planartrivial.md @@ -0,0 +1,27 @@ +# PlanarTrivial + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +### Twist + +## Code Examples + +## Implementation Notes diff --git a/docs/src/sectors/composite/product.md b/docs/src/sectors/composite/product.md new file mode 100644 index 00000000..10506c0f --- /dev/null +++ b/docs/src/sectors/composite/product.md @@ -0,0 +1,33 @@ +# Product Sectors: ProductSector + +## Type Definition + +## Construction + +### Direct Construction + +### Using the ⊠ Operator + +## Labels + +## Combining Symmetries + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +## Code Examples + +## Implementation Notes + +### Type Parameters + +### Deligne Tensor Product diff --git a/docs/src/sectors/composite/timereversed.md b/docs/src/sectors/composite/timereversed.md new file mode 100644 index 00000000..4516934e --- /dev/null +++ b/docs/src/sectors/composite/timereversed.md @@ -0,0 +1,29 @@ +# Time-Reversed Sectors: TimeReversed + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Braiding Reversal + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +## Code Examples + +## Implementation Notes + +### Anti-unitary Symmetries diff --git a/docs/src/sectors/fermions/number.md b/docs/src/sectors/fermions/number.md new file mode 100644 index 00000000..07106c1f --- /dev/null +++ b/docs/src/sectors/fermions/number.md @@ -0,0 +1,29 @@ +# Fermion Number: FermionNumber + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +### Twist + +## Code Examples + +## Implementation Notes + +### Relationship to U₁ × Fermion Parity diff --git a/docs/src/sectors/fermions/parity.md b/docs/src/sectors/fermions/parity.md new file mode 100644 index 00000000..ee613321 --- /dev/null +++ b/docs/src/sectors/fermions/parity.md @@ -0,0 +1,29 @@ +# Fermion Parity: FermionParity + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +### Twist + +## Code Examples + +## Implementation Notes + +### Relationship to Super Vector Spaces diff --git a/docs/src/sectors/fermions/spin.md b/docs/src/sectors/fermions/spin.md new file mode 100644 index 00000000..a4cdb945 --- /dev/null +++ b/docs/src/sectors/fermions/spin.md @@ -0,0 +1,29 @@ +# Fermion Spin: FermionSpin + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +### Twist + +## Code Examples + +## Implementation Notes + +### Relationship to SU₂ × Fermion Parity diff --git a/docs/src/sectors/nonabelian/a4.md b/docs/src/sectors/nonabelian/a4.md new file mode 100644 index 00000000..2c6d97b7 --- /dev/null +++ b/docs/src/sectors/nonabelian/a4.md @@ -0,0 +1,29 @@ +# Alternating Group A₄: A4Irrep + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +## Basis Conventions + +## Iteration + +## Code Examples + +## Implementation Notes diff --git a/docs/src/sectors/nonabelian/cu1.md b/docs/src/sectors/nonabelian/cu1.md new file mode 100644 index 00000000..57f2c971 --- /dev/null +++ b/docs/src/sectors/nonabelian/cu1.md @@ -0,0 +1,29 @@ +# CU(1): U(1) ⋉ ℤ₂ + +## Type Definition + +## Construction + +## Labels + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +## Basis Conventions + +## Iteration + +## Code Examples + +## Implementation Notes diff --git a/docs/src/sectors/nonabelian/dn.md b/docs/src/sectors/nonabelian/dn.md new file mode 100644 index 00000000..e4821923 --- /dev/null +++ b/docs/src/sectors/nonabelian/dn.md @@ -0,0 +1,39 @@ +# Dihedral Groups: DNIrrep + +## Type Definition + +## Construction + +## Labels + +### DNIrrep{N} for N odd + +### DNIrrep{N} for N even + +## Physical Interpretation + +## Fusion Rules + +## Quantum Dimensions + +## Topological Data + +### F-symbols + +### R-symbols + +### Braiding Style + +## Basis Conventions + +## Iteration + +## Code Examples + +### D3Irrep + +### D4Irrep + +## Implementation Notes + +### Character Tables From cf59c97668ef433c842eb91cd0592847df99c7b2 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Thu, 28 May 2026 11:16:53 -0400 Subject: [PATCH 02/50] docs: document required sector interface methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the required-methods page (set-of-sectors enumeration, fusion structure, identity/duality, associativity, braiding, utility methods) and rewrites the corresponding docstrings on ⊗, Nsymbol, sqrtdim, and invsqrtdim with explicit return-type guarantees and cross-references to FusionStyle. Co-authored-by: Boris De Vos <143942306+borisdevos@users.noreply.github.com> Co-authored-by: Jutho --- docs/src/interface/required.md | 151 +++++++++++++++++++++++++++++++++ src/sectors.jl | 34 +++++++- 2 files changed, 181 insertions(+), 4 deletions(-) create mode 100644 docs/src/interface/required.md diff --git a/docs/src/interface/required.md b/docs/src/interface/required.md new file mode 100644 index 00000000..7a427c75 --- /dev/null +++ b/docs/src/interface/required.md @@ -0,0 +1,151 @@ +```@meta +CollapsedDocStrings = true +``` + +# Required Methods + +The following methods **must** be implemented for any new sector type `I <: Sector`. +These methods are grouped by functionality to help understand their purpose. + +## Defining the Set of Sectors + +A sector type `I <: Sector` represents the set of all labels that can be used to grade a vector space. +This corresponds to all irreducible representations of a group, or all simple objects in a fusion category. +The first requirement is making this set **enumerable** through the iterator interface. + +The set of all sector values is obtained via `values(I)`, which returns a `SectorValues{I}()` singleton type by default. +This `SectorValues{I}()` must be iterable, enabling enumeration of all sectors of type `I`. +To do so, one needs to implement the [Iteration interface](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration). +In particular, we require the following methods to be defined: + +- `Base.iterate(::SectorValues{I}, state...)` — Iterate over all possible values of sector type `I`. +- `Base.IteratorSize(::Type{SectorValues{I}})` — Specify whether the number of sector values is known, finite, or infinite. + +Here the `IteratorSize` is either `HasLength()`, `SizeUnknown()` or `IsInfinite()`. +If the length is known (`HasLength()`), three further methods are required so that sectors can be indexed by position: + +- `Base.length(::SectorValues{I})` — Return the number of sectors. +- `Base.getindex(::SectorValues{I}, i::Int)` — Access the `i`-th sector value. +- `findindex(::SectorValues{I}, c::I)` — Find the index of sector `c`. + +!!! note + The choice of `IteratorSize` determines how associative containers are constructed in e.g. a `GradedSpace`. + In the case of `HasLength()`, an implicit mapping between the values and the position is used to enable storage through `Tuple`s or `Vector`s. + In the other cases one has to resort to `AbstractDict`-like containers. + If the set of simple objects is sufficiently large, it might be beneficial to register its length as `SizeUnknown()` to avoid putting too much pressure on the compiler. + + +## Fusion Structure + +The fusion structure describes how sectors combine when taking tensor products. +In code, `a ⊗ b` returns the allowed output labels, and `Nsymbol(a, b, c)` tells you whether (or how many times) `c` appears. + +The formal decomposition is: +```math +a ⊗ b = \bigoplus_c N^{ab}_c \, c +``` +where ``N^{ab}_c`` is the fusion multiplicity. + +The fusion structure is defined through three related methods: + +```@docs; canonical = false +⊗ +Nsymbol +FusionStyle +``` + + +## Identity and Duality + +Every sector type has a unit (identity) label and a notion of dual (conjugate). +`unit` returns the identity label, and `dual` returns the label that fuses with `a` to give the unit. + +The unit ``\mathbb{1}`` acts as the identity under fusion: +```math +\mathbb{1} ⊗ a ≅ a ≅ a ⊗ \mathbb{1} +``` +The dual of a sector ``a`` is the unique sector ``\bar{a}`` such that: +```math +N^{a\bar{a}}_{\mathbb{1}} = 1 \quad \text{and} \quad N^{\bar{a}a}_{\mathbb{1}} = 1 +``` + +```@docs; canonical = false +unit +dual +``` + +**Multifusion categories** can have multiple units and may distinguish between left and right units. +For such cases, additional methods are available: + +```@docs; canonical = false +allunits +leftunit +rightunit +``` + +For regular fusion categories the unit object is unique, such that `unit`, `leftunit` and `rightunit` all coincide. + + +## Associativity + +The associativity of the fusion tensor product tells us how to relate the basis states ``|(a ⊗ b → e) ⊗ c → d\rangle`` to the states ``|a ⊗ (b ⊗ c → f) → d\rangle``. +This is encoded in the F-symbols, which give the coefficients to transform the different ways of fusing three sectors to one. + +```@docs; canonical = false +Fsymbol +``` + +Formally, the F-symbol ``F^{abc}_d`` with intermediate sectors ``e`` and ``f`` is a linear transformation between the two different parenthesizations: + +```math +(F_{abc}^d)^e_f : (a ⊗ b → e) ⊗ c → d \quad \longrightarrow \quad a ⊗ (b ⊗ c → f) → d +``` + +For sectors with `UniqueFusion` or `SimpleFusion`, the F-symbol is a scalar `<:Number`. +For `GenericFusion`, it is a rank-4 tensor with indices corresponding to the multiplicity labels of each fusion vertex. + +The F-symbols must satisfy the **pentagon equation** for every choice of sectors: + +```math +(F_{fcd}^e)^g_h (F_{abh}^e)^f_i = (F_{abc}^g)^f_j (F_{ajd}^e)^g_i (F_{bcd}^i)^j_h +``` + +This ensures that all ways of reassociating four tensor factors ``(((a ⊗ b) ⊗ c) ⊗ d)`` to ``(a ⊗ (b ⊗ (c ⊗ d)))`` give the same result, regardless of the sequence of reassociations. + + +## Braiding + +Sectors can have a braiding structure that describes the effect of exchanging two tensor factors. +The braiding is encoded in the R-symbol ``R^{ab}_c``, which is a linear transformation between the fusion channels ``a ⊗ b → c`` and ``b ⊗ a → c``. +For sectors with `UniqueFusion` or `SimpleFusion`, the R-symbol is a complex phase. +For `GenericFusion`, it is a square matrix relating the multiplicity spaces of the two fusion orders. + +The R-symbols must satisfy the **hexagon equations** together with the F-symbols: + +```math +R^{cd}_e (\overline{F}_{dab}^e)^g_c \overline{R}^{da}_g = (F_{abd}^e)^c_f R^{bd}_f (\overline{F}_{adb}^e)^g_f +``` + +and the analogous equation with ``a`` and ``b`` swapped. +These ensure that the braiding is compatible with the associativity encoded by F-symbols. + +The `BraidingStyle` trait categorizes behavior into four classes: +- `NoBraiding()` for planar categories where braiding is undefined +- `Bosonic()` for symmetric braiding with trivial twist (all R-symbols square to identity, all twists equal +1) +- `Fermionic()` for symmetric braiding with fermion parity (twists can be ±1) +- `Anyonic()` for general braiding with arbitrary phases or non-symmetric exchange + +```@docs; canonical = false +Rsymbol +BraidingStyle +``` + + +## Utility Methods + +Sectors must support a deterministic ordering and hashing so they can be used as dictionary keys, sorted collections, and canonical fusion outputs. +One should keep the order consistent with `values(I)`, i.e. the enumeration of objects should happen in a sorted fashion. +To achieve this, we must have + +- `Base.isless(::Sector, ::Sector)` — Define an order on the sectors. +- `Base.hash(::Sector, h::UInt)` — Associate a hash value with a sector. diff --git a/src/sectors.jl b/src/sectors.jl index 2faaebea..1a6a28f4 100644 --- a/src/sectors.jl +++ b/src/sectors.jl @@ -220,9 +220,12 @@ Base.isreal(I::Type{<:Sector}) = sectorscalartype(I) <: Real otimes(a::I, b::I...) where {I <: Sector} Return an iterable of elements of `c::I` that appear in the fusion product `a ⊗ b`. +Each sector `c` should appear at most once in this iteration, even if the multiplicity ``N_c^{ab} > 1``. +The actual multiplicities are accessed separately through [`Nsymbol`](@ref). -Note that every element `c` should appear at most once, fusion degeneracies (if -`FusionStyle(I) == GenericFusion()`) should be accessed via `Nsymbol(a, b, c)`. +The return type is typically [`SectorProductIterator{I}`](@ref) which provides a type-stable iterable that supports pretty-printing, but could also be any custom iterable. + +See also [`FusionStyle`](@ref) for the trait associated to the fusion behavior of a given sector type. """ function ⊗ end const otimes = ⊗ @@ -297,8 +300,11 @@ end """ Nsymbol(a::I, b::I, c::I) where {I <: Sector} -> Integer -Return an `Integer` representing the number of times `c` appears in the fusion product -`a ⊗ b`. Could be a `Bool` if `FusionStyle(I) == UniqueFusion()` or `SimpleFusion()`. +The fusion multiplicity ``N_c^{ab}``, indicating how many times sector `c` appears in the fusion product `a ⊗ b`. + +The return type depends on the [`FusionStyle`](@ref), where [`UniqueFusion`](@ref) and [`SimpleFusion`](@ref) return `Bool` values, while [`GenericFusion`](@ref) returns `Int`. + +See also [`⊗`](@ref) to obtain the set of sectors `c` that appear in `a ⊗ b`. """ function Nsymbol end @@ -437,7 +443,27 @@ function dim_from_Fsymbol(a::Sector) abs(1 / Fsymbol(a, dual(a), a, a, leftunit(a), rightunit(a))[1]) end end + +""" + sqrtdim(a::Sector) + +Return the square root of the (quantum) dimension of sector `a`. + +This is a performance specialization that avoids computing `sqrt(1)` for sectors with +`UniqueFusion`, preserving the number type (returning `1::Int` instead of `1.0::Float64`). +For other sectors, it is equivalent to `sqrt(dim(a))`. +""" sqrtdim(a::Sector) = (FusionStyle(a) isa UniqueFusion) ? 1 : sqrt(dim(a)) + +""" + invsqrtdim(a::Sector) + +Return the inverse square root of the (quantum) dimension of sector `a`. + +This is a performance specialization that avoids computing `inv(sqrt(1))` for sectors with +`UniqueFusion`, preserving the number type (returning `1::Int` instead of `1.0::Float64`). +For other sectors, it is equivalent to `inv(sqrt(dim(a)))`. +""" invsqrtdim(a::Sector) = (FusionStyle(a) isa UniqueFusion) ? 1 : inv(sqrt(dim(a))) """ From 3a5e123608640af24b0d95b653cbf49cdd9619f4 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Thu, 28 May 2026 11:17:08 -0400 Subject: [PATCH 03/50] docs: document optional sector interface methods Adds the optional-methods page (quantum dimensions, Frobenius-Schur, scalar type, derived topological data, optional fusion-tensor methods) and corrects frobenius_schur_indicator to compare against dual(a) instead of conj(a). Co-authored-by: Boris De Vos <143942306+borisdevos@users.noreply.github.com> --- docs/src/interface/optional.md | 96 ++++++++++++++++++++++++++++++++++ src/sectors.jl | 2 +- 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 docs/src/interface/optional.md diff --git a/docs/src/interface/optional.md b/docs/src/interface/optional.md new file mode 100644 index 00000000..124b9ae3 --- /dev/null +++ b/docs/src/interface/optional.md @@ -0,0 +1,96 @@ +```@meta +CollapsedDocStrings = true +``` + +# Optional Methods + +The following methods have default implementations but can be overridden for performance or to provide additional functionality. + +## Quantum Dimensions + +The quantum dimension of a sector is a fundamental invariant that determines the behavior of fusions and braiding. +The default implementation extracts the dimension from [`Fsymbol`](@ref) via the quantum dimension formula. + +```math +d_a = \left| \frac{1}{(F_{a \bar{a} a}^a)^{1_a}_{_a1} } \right| +``` + +For many common sectors, however, the dimension is known directly from representation theory. +In these cases, it can be beneficial to overload [`dim`](@ref) to bypass computing F-symbols, either for performance reasons or to enforce tighter output types. +For example, dimensions of irreducible representations of groups are always integers. + +```@docs; canonical = false +dim +sqrtdim +invsqrtdim +``` + +## Frobenius-Schur Indicators + +The Frobenius-Schur indicator and phase characterize the self-duality properties of sectors. + +```math +\kappa_a = \text{sign}\left( (F_{a \bar{a} a}^a)^{1_a}_{_a1} \right) +``` + +The indicator distinguishes real, complex, and quaternionic representations. +The phase is the category-theoretic version that appears in line bending operations. + +```@docs; canonical = false +frobenius_schur_indicator +frobenius_schur_phase +``` + +## Scalar Type + +Various utility functions exist for determining what number type is used in various parts of the topological data. + +```@docs; canonical = false +fusionscalartype +braidingscalartype +dimscalartype +sectorscalartype +``` + +!!! note + While there is a fallback definition that tries to determine the result from computing the functions on the unit sector, + it is often a good idea to define this method explicitly to avoid depending on compiler heuristics to constant-fold these calls. + +## Topological Data Symbols + +The [`Asymbol`](@ref), [`Bsymbol`](@ref) and [`twist`](@ref) are derived from F- and R-symbols but are often occurring combinations. +The A-symbol and B-symbol relate different ways of bending strands, while the twist is the topological spin (quantum dimension phase) of a sector. + +The A-symbol ``A^{ab}_c`` relates splitting and fusion vertices: +```math +A^{ab}_c = \sqrt{\frac{d_a d_b}{d_c}} \overline{\kappa_a} (F_{\bar{a} a b}^b)^1_c +``` + +The B-symbol ``B^{ab}_c`` relates splitting and fusion vertices: +```math +B^{ab}_c = \sqrt{\frac{d_a d_b}{d_c}} (F_{a b \bar{b}}^a)^c_1 +``` + +The twist ``\theta_a`` of a sector is the topological spin phase, computed as the trace of the R-matrix for braiding a sector with itself: +```math +\theta_a = \frac{1}{d_a} \sum_{b \in a \otimes a} d_b \text{tr}(R^{aa}_b) +``` + +```@docs; canonical = false +Asymbol +Bsymbol +twist +``` + +## Fusion Basis + +The fusion tensor provides explicit matrix elements for the tensor product of representations. +It is a rank-4 array whose components are the Clebsch-Gordan coefficients for fusing sector `a` and `b` into `c`. +The fusion tensor is not uniquely determined by topological data alone, instead the topological data can be extracted from it when it is available. +However, there is not always a concrete representation of these tensors in terms of simple `Array` objects, and the exact representation is not important for TensorKit.jl. +For this reason, it is optional: TensorKit can work with the topological data alone. +Note however that they are still required whenever we want to convert symmetric tensors to and from dense arrays. + +```@docs; canonical = false +fusiontensor +``` diff --git a/src/sectors.jl b/src/sectors.jl index 1a6a28f4..18dd30e4 100644 --- a/src/sectors.jl +++ b/src/sectors.jl @@ -505,7 +505,7 @@ context of line bending. """ function frobenius_schur_indicator(a::Sector) ν = frobenius_schur_phase(a) - return a == conj(a) ? ν : zero(ν) + return a == dual(a) ? ν : zero(ν) end """ From 44fdfa66fd58f6d378e62d42d84ac1a863089c82 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Thu, 28 May 2026 11:17:28 -0400 Subject: [PATCH 04/50] docs: document trait-based dispatch Adds the traits-and-styles page covering FusionStyle, BraidingStyle, and UnitStyle, with jldoctest examples for the & combinator. Rewrites the corresponding docstrings on FusionStyle (and UniqueFusion / MultipleFusion / SimpleFusion / GenericFusion / MultiplicityFreeFusion), UnitStyle (and SimpleUnit / GenericUnit), and BraidingStyle (and HasBraiding / NoBraiding / SymmetricBraiding / Bosonic / Fermionic / Anyonic) so each subtype has its own docstring. --- docs/src/interface/traits.md | 95 +++++++++++++++++++ src/sectors.jl | 174 +++++++++++++++++++++++++++-------- 2 files changed, 229 insertions(+), 40 deletions(-) create mode 100644 docs/src/interface/traits.md diff --git a/docs/src/interface/traits.md b/docs/src/interface/traits.md new file mode 100644 index 00000000..a863a240 --- /dev/null +++ b/docs/src/interface/traits.md @@ -0,0 +1,95 @@ +```@meta +CollapsedDocStrings = true + +DocTestSetup = quote + using TensorKitSectors +end +``` + +# Traits and Styles + +Traits define compile-time properties that can be assumed about a sector type. +They control behavior and enable optimizations. + +## FusionStyle + +The `FusionStyle` trait indicates how many outputs to expect when fusing two sectors. + +```@docs; canonical = false +FusionStyle +UniqueFusion +SimpleFusion +GenericFusion +``` + +This enables various optimizations for different cases. +Firstly, since the shape (size of the arrays) of the topological data is determined by combinations of the [`Nsymbol`](@ref), for `UniqueFusion` and `SimpleFusion` we can use scalar quantities instead of arrays. +Secondly, in the `UniqueFusion` case, there is only a single channel for ``a \otimes b \otimes c \otimes \ldots``, avoiding the need to iterate through all options. + +It is additionally possible to combine fusion styles through the `&` operator, which returns the style with the least assumptions. +For example: + +```jldoctest +julia> UniqueFusion() & SimpleFusion() +SimpleFusion() + +julia> GenericFusion() & UniqueFusion() +GenericFusion() +``` + +Finally, some predefined combinations that appear often have dedicated names: + +```@docs; canonical = false +MultipleFusion +MultiplicityFreeFusion +``` + +## BraidingStyle + +The `BraidingStyle` describes whether and how exchange of sectors is defined. +It determines how TensorKit interprets [`Rsymbol`](@ref) and [`twist`](@ref). + +```@docs; canonical = false +BraidingStyle +NoBraiding +Bosonic +Fermionic +Anyonic +``` + +Additionally, this dictates whether or not permutations are sufficient to specify generic exchanges, or if a full braid group representation is needed. + +It is also possible to combine braiding styles through the `&` operator, which returns the style with the least assumptions. +For example: + +```jldoctest +julia> Bosonic() & Fermionic() +Fermionic() + +julia> Fermionic() & Anyonic() +Anyonic() + +julia> Bosonic() & NoBraiding() +NoBraiding() +``` + +Finally, some predefined combinations that appear often have dedicated names: + +```@docs; canonical = false +HasBraiding +SymmetricBraiding +``` + +## UnitStyle + +The `UnitStyle` tells whether there is a single identity label or multiple units. +By default, it is derived from `length(allunits(I))`. + +```@docs; canonical = false +UnitStyle +SimpleUnit +GenericUnit +``` + +Whenever the style is `SimpleUnit`, a unique value of [`unit`](@ref) can be defined and there is no distinction between [`leftunit`](@ref) and [`rightunit`](@ref). +For `GenericUnit`, this is no longer the case and special care has to be taken to use the *correct* unit for various fusion diagrams. diff --git a/src/sectors.jl b/src/sectors.jl index 18dd30e4..c2c62d6b 100644 --- a/src/sectors.jl +++ b/src/sectors.jl @@ -315,29 +315,63 @@ function Nsymbol end FusionStyle(I::Type{<:Sector}) Trait to describe the fusion behavior of sectors of type `I`, which can be either -* `UniqueFusion()`: single fusion output when fusing two sectors; -* `SimpleFusion()`: multiple outputs, but every output occurs at most one, - also known as multiplicity-free (e.g. irreps of ``SU(2)``); -* `GenericFusion()`: multiple outputs that can occur more than once (e.g. irreps - of ``SU(3)``). +* [`UniqueFusion`](@ref): each fusion `a ⊗ b` has exactly one output `c`. +* [`SimpleFusion`](@ref): fusing `a ⊗ b` can lead to multiple values `c`, but each appears at most once. +* [`GenericFusion`](@ref): fusing `a ⊗ b` can lead to multiple values `c` that could appear multiple times. -There is an abstract supertype `MultipleFusion` of which both `SimpleFusion` and -`GenericFusion` are subtypes. Furthermore, there is a type alias `MultiplicityFreeFusion` -for those fusion types which do not require muliplicity labels, i.e. -`MultiplicityFreeFusion = Union{UniqueFusion,SimpleFusion}`. +There is an abstract supertype [`MultipleFusion`](@ref) of which both `SimpleFusion` and `GenericFusion` are subtypes. +Furthermore, there is a type alias [`MultiplicityFreeFusion`](@ref) for those fusion types which do not require muliplicity labels. """ abstract type FusionStyle end FusionStyle(a::Sector) = FusionStyle(typeof(a)) -struct UniqueFusion <: FusionStyle end # unique fusion output when fusing two sectors +""" + struct UniqueFusion <: FusionStyle + +Fusion style where every product `a ⊗ b` has exactly one output `c`. +As a result, ``N_c^{ab} ≤ 1`` and no multiplicity labels are needed. + +See also [`FusionStyle`](@ref). +""" +struct UniqueFusion <: FusionStyle end + +""" + abstract type MultipleFusion <: FusionStyle + +Fusion styles that allow more than one fusion output for `a ⊗ b`. + +See also [`SimpleFusion`](@ref), [`GenericFusion`](@ref) and [`FusionStyle`](@ref). +""" abstract type MultipleFusion <: FusionStyle end -struct SimpleFusion <: MultipleFusion end # multiple fusion but multiplicity free -struct GenericFusion <: MultipleFusion end # multiple fusion with multiplicities -const MultiplicityFreeFusion = Union{UniqueFusion, SimpleFusion} -@doc (@doc FusionStyle) UniqueFusion -@doc (@doc FusionStyle) SimpleFusion -@doc (@doc FusionStyle) GenericFusion +""" + struct SimpleFusion <: MultipleFusion + +Fusion style where multiple outputs `c` can appear in `a ⊗ b`, but each appears at most once. +As a result, ``N_c^{ab} ≤ 1`` and no multiplicity labels are needed. + +See also [`FusionStyle`](@ref). +""" +struct SimpleFusion <: MultipleFusion end + +""" + struct GenericFusion <: MultipleFusion + +Fusion style with potentially multiple outputs `c` and nontrivial multiplicities. +Here ``N_c^{ab}`` can exceed 1, and multiplicity labels are required. + +See also [`FusionStyle`](@ref). +""" +struct GenericFusion <: MultipleFusion end + +""" + const MultiplicityFreeFusion = Union{UniqueFusion, SimpleFusion} + +Convenience alias for fusion styles that can assume `Nsymbol(a, b, c)::Bool`, and therefore never require multiplicity labels. + +See also [`UniqueFusion`](@ref), [`SimpleFusion`](@ref) and [`FusionStyle`](@ref). +""" +const MultiplicityFreeFusion = Union{UniqueFusion, SimpleFusion} # combine fusion properties of tensor products of sectors Base.:&(f::F, ::F) where {F <: FusionStyle} = f @@ -355,17 +389,31 @@ Base.:&(::GenericFusion, ::SimpleFusion) = GenericFusion() Trait to describe the semisimplicity of the unit sector of type `I`. This can be either -* `SimpleUnit()`: the unit is simple (e.g. fusion categories); -* `GenericUnit()`: the unit is semisimple. +* [`SimpleUnit`](@ref): the unit is simple (e.g. fusion categories). +* [`GenericUnit`](@ref): the unit is semisimple (e.g. multifusion categories). """ abstract type UnitStyle end UnitStyle(a::Sector) = UnitStyle(typeof(a)) +""" + struct SimpleUnit <: UnitStyle + +Unit style for fusion categories with a unique unit (identity) object. +The unit satisfies ``\\mathbb{1} ⊗ a ≅ a ≅ a ⊗ \\mathbb{1}`` for all sectors. + +See also [`UnitStyle`](@ref). +""" struct SimpleUnit <: UnitStyle end -struct GenericUnit <: UnitStyle end -@doc (@doc UnitStyle) SimpleUnit -@doc (@doc UnitStyle) GenericUnit +""" + struct GenericUnit <: UnitStyle + +Unit style for multifusion categories with multiple unit objects (semisimple unit). +Requires implementation of `allunits(::Type{I})`, `leftunit(a)`, and `rightunit(a)`. + +See also [`UnitStyle`](@ref). +""" +struct GenericUnit <: UnitStyle end UnitStyle(::Type{I}) where {I <: Sector} = length(allunits(I)) == 1 ? SimpleUnit() : GenericUnit() @@ -373,7 +421,7 @@ UnitStyle(::Type{I}) where {I <: Sector} = length(allunits(I)) == 1 ? SimpleUnit throw(DomainError(I, "Sector has multiple units, use `allunits` instead of `unit`")) end -# combine fusion properties of tensor products of multifusion sectors +# combine unitstyle properties of tensor products of multifusion sectors Base.:&(f::F, ::F) where {F <: UnitStyle} = f Base.:&(f₁::UnitStyle, f₂::UnitStyle) = f₂ & f₁ @@ -595,35 +643,81 @@ end # trait to describe type to denote how the elementary spaces in a tensor product space # interact under permutations or actions of the braid group """ - abstract type BradingStyle + abstract type BraidingStyle BraidingStyle(::Sector) -> ::BraidingStyle BraidingStyle(I::Type{<:Sector}) -> ::BraidingStyle -Return the type of braiding and twist behavior of sectors of type `I`, which can be either -* `NoBraiding()`: no braiding structure -* `Bosonic()`: symmetric braiding with trivial twist (i.e. identity) -* `Fermionic()`: symmetric braiding with non-trivial twist (squares to identity) -* `Anyonic()`: general ``R^{ab}_c`` phase or matrix (depending on `SimpleFusion` or - `GenericFusion` fusion) and arbitrary twists +Trait to describe the braiding behavior of sectors of type `I`, which can be either +* [`NoBraiding`](@ref): no braiding structure defined. +* [`Bosonic`](@ref): symmetric braiding structure with a trivial twist. +* [`Fermionic`](@ref): symmetric braiding structure with a non-trivial twist that squares to identity. +* [`Anyonic`](@ref): general braiding structure and arbitrary twists. -Note that `Bosonic` and `Fermionic` are subtypes of `SymmetricBraiding`, which means that -braids are in fact equivalent to crossings (i.e. braiding twice is an identity: -`isone(Rsymbol(b,a,c)*Rsymbol(a,b,c)) == true`) and permutations are uniquely defined. +There is an abstract supertype [`HasBraiding`](@ref) that includes all styles that define [`Rsymbol`](@ref) (everything but `NoBraiding`). +Furthermore, the abstract supertype [`SymmetricBraiding`](@ref) denotes the cases where braidings are equivalent to crossings, i.e. braiding twice is an identity operation. +This includes the `Bosonic` and `Fermionic` styles, for which we can uniquely define permutations. """ abstract type BraidingStyle end BraidingStyle(a::Sector) = BraidingStyle(typeof(a)) +""" + abstract type HasBraiding <: BraidingStyle + +Supertype for all braiding styles where an [`Rsymbol`](@ref) is defined. +This includes all current `BraidingStyle`s except `NoBraiding`. +""" abstract type HasBraiding <: BraidingStyle end + +""" + struct NoBraiding <: BraidingStyle + +Braiding style for categories without a braiding structure. +Except for braiding with the unit sector, only planar diagrams are meaningful; [`Rsymbol`](@ref) is undefined. + +See also [`BraidingStyle`](@ref). +""" struct NoBraiding <: BraidingStyle end -abstract type SymmetricBraiding <: HasBraiding end # symmetric braiding => actions of permutation group are well defined -struct Bosonic <: SymmetricBraiding end # all twists are one -struct Fermionic <: SymmetricBraiding end # twists one and minus one -struct Anyonic <: HasBraiding end -@doc (@doc BraidingStyle) NoBraiding -@doc (@doc BraidingStyle) Bosonic -@doc (@doc BraidingStyle) Fermionic -@doc (@doc BraidingStyle) Anyonic +""" + abstract type SymmetricBraiding <: HasBraiding + +Supertype for braiding styles with symmetric braiding, where braiding twice is the identity operation. +Subtypes include [`Bosonic`](@ref) (trivial twist) and [`Fermionic`](@ref) (nontrivial twist ±1). +Supports permutation group statistics. + +See also [`BraidingStyle`](@ref). +""" +abstract type SymmetricBraiding <: HasBraiding end + +""" + struct Bosonic <: SymmetricBraiding + +Braiding style with symmetric braiding and trivial twist. +This is characterized by ``R^{ab}_c R^{ba}_c = 1`` and ``\\theta_a = 1`` for all sectors. + +See also [`BraidingStyle`](@ref). +""" +struct Bosonic <: SymmetricBraiding end + +""" + struct Fermionic <: SymmetricBraiding + +Braiding style with symmetric braiding and nontrivial (symmetric) twist. +This is characterized by ``R^{ab}_c R^{ba}_c = 1`` and ``\\theta_a = \\pm 1`` for all sectors. + +See also [`BraidingStyle`](@ref). +""" +struct Fermionic <: SymmetricBraiding end + +""" + struct Anyonic <: HasBraiding + +Braiding style with general (non-symmetric) braiding and arbitrary twists. +Characterized by nontrivial braid group representations where ``R^{ab}_c R^{ba}_c ≠ 1`` in general. + +See also [`BraidingStyle`](@ref). +""" +struct Anyonic <: HasBraiding end Base.:&(b::B, ::B) where {B <: BraidingStyle} = b Base.:&(B1::BraidingStyle, B2::BraidingStyle) = B2 & B1 From bec932b55e7a6210c6ac6f1f294d3d0244dafccf Mon Sep 17 00:00:00 2001 From: lkdvos Date: Thu, 28 May 2026 11:17:40 -0400 Subject: [PATCH 05/50] docs: add implementation guidelines for new sectors Adds the guidelines page covering shape of topological data, multiplicity- free vs generic fusion, the & combinator pattern, and how to use the FusionStyle/BraidingStyle dispatch when implementing a new sector. Co-authored-by: Boris De Vos <143942306+borisdevos@users.noreply.github.com> --- docs/src/interface/guidelines.md | 63 ++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 docs/src/interface/guidelines.md diff --git a/docs/src/interface/guidelines.md b/docs/src/interface/guidelines.md new file mode 100644 index 00000000..518518fb --- /dev/null +++ b/docs/src/interface/guidelines.md @@ -0,0 +1,63 @@ +```@meta +CollapsedDocStrings = true +``` + +# Implementation Guidelines + +This section provides practical advice for implementing new sector types efficiently and correctly. + +## Helper Type: SectorProductIterator + +Instead of materializing all fusion outputs in a tuple or array, one can use `SectorProductIterator` for type-stable, lazy iteration. + +```@docs; canonical = false +TensorKitSectors.SectorProductIterator +``` + +This is enabled by default, and new sectors should provide implementations for the following functions: + +```julia +Base.iterate(ab::SectorProductIterator{I}, [state]) = ... +# optional optimizations: +Base.IteratorSize(::Type{SectorProductIterator{I}}) = HasLength() +Base.length(ab::SectorProductIterator{I}) = ... +``` + +This has the benefit of helping with type stability, and has a pretty-printing overload: + +```@example +using TensorKitSectors # hide +SU2Irrep(1) ⊗ SU2Irrep(1) +``` + +## Shape of Topological Data + +The size of [`Fsymbol`](@ref) and [`Rsymbol`](@ref) data depends on the fusion multiplicities ([`Nsymbol`](@ref)). +For multiplicity‑free sectors scalars are sufficient; for generic fusion we need arrays. +Therefore, we distinguish the behavior through the [`FusionStyle`](@ref). + + +### [`MultiplicityFreeFusion`](@ref) + +- `Nsymbol(a, b, c)`: Returns a `Bool`. +- `Fsymbol(a, b, c, d, e, f)`: Returns a scalar of type `sectorscalartype(I)`. +- `Rsymbol(a, b, c)`: Returns a scalar of type `sectorscalartype(I)`. + +Additionally, if the [`Fsymbol`](@ref) and [`Rsymbol`](@ref) do not correspond to valid fusion channels, the result is ``0``. +Therefore, computing the number of valid fusion channels for both diagrams as the product of the relevant [`Nsymbol`](@ref)s, we have: + +```math +\left(N^{ab}_e N^{ec}_d = 0 \lor N^{af}_d N^{bc}_f = 0\right) \implies (F_{abc}^d)^e_f = 0 +``` + +```math +N^{ab}_c = 0 \implies R^{ab}_c = 0 +``` + +### [`GenericFusion`](@ref) + +- `Nsymbol(a, b, c)`: Returns a positive `Integer`. +- `Fsymbol(a, b, c, d, e, f)`: Returns a ``N^{ab}_e \times N^{ec}_d \times N^{af}_d \times N^{bc}_f`` array of `sectorscalartype(I)` elements. +- `Rsymbol(a, b, c)`: Returns a ``N^{ab}_c \times N^{ba}_c`` array of `sectorscalartype(I)` elements. + +Here invalid fusion channels will necessarily lead to empty arrays. From fba44f9f0bc930c027091f1358f18a0cc2de70b5 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Thu, 28 May 2026 11:17:51 -0400 Subject: [PATCH 06/50] docs: document SU2Irrep sector Adds the SU2Irrep page with fusion rules, F-symbols, Clebsch-Gordan coefficients, and worked examples (depending on TensorOperations). Tightens the SU2Irrep docstring (typo and rewording). --- docs/Project.toml | 1 + docs/src/sectors/nonabelian/su2.md | 130 +++++++++++++++++++++++++++++ src/irreps/su2irrep.jl | 5 +- 3 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 docs/src/sectors/nonabelian/su2.md diff --git a/docs/Project.toml b/docs/Project.toml index dcc80af7..707c82f4 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,6 +1,7 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" +TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2" [compat] Documenter = "1" diff --git a/docs/src/sectors/nonabelian/su2.md b/docs/src/sectors/nonabelian/su2.md new file mode 100644 index 00000000..f10b8cf7 --- /dev/null +++ b/docs/src/sectors/nonabelian/su2.md @@ -0,0 +1,130 @@ +# ``SU(2)`` Representations: `SU2Irrep` + +`SU2Irrep` represents irreducible representations of the compact group ``SU(2)`` as a `Sector`. +This page documents how the type behaves in code (construction, iteration, fusion, and access to topological data). + +## Sector type + +The irreducible representations of ``SU(2)`` are labeled by non-negative half-integers (e.g. ``0``, ``\frac{1}{2}``, ``1``, ``\frac{3}{2}``, …). + +```@docs; canonical = false +SU2Irrep +``` + +Fusing two irreps together leads to a direct sum of irreps: + +```math +a \otimes b = \bigoplus_{c_j = |j_a - j_b|}^{j_a + j_b} c +``` + +Since each output appears only once, we have `FusionStyle(SU2Irrep) = SimpleFusion()`. +The [`Nsymbol`](@ref) returns a `Bool` that checks the triangle inequality: + +```math +N_c^{ab} = |j_a - j_b| \leq j_c \leq j_a + j_b \land j_a + j_b + j_c \in \mathbb{N} +``` + +Each irrep has dimension ``d = 2j + 1``. + +The [`Fsymbol`](@ref) is computed from [Wigner ``6j``](https://en.wikipedia.org/wiki/6-j_symbol) (Racah-``W``) symbols as + +```math +\left(F_{abc}^d\right)_e^f = (-1)^{j_a + j_b + j_c + j_e} \sqrt{d_e d_f} \begin{Bmatrix} +j_a & j_b & j_d \\ +j_c & j_e & j_f +\end{Bmatrix} +``` + +The `BraidingStyle` is `Bosonic`, and [`Rsymbol`](@ref) is ``\pm 1`` for allowed fusion channels based on the parity of ``j_a + j_b - j_c``. + +## Fusion Tensor and Basis Conventions + +`fusiontensor(a, b, c)` returns Clebsch–Gordan coefficients as a rank‑4 array of size ``d_a \times d_b \times d_c \times 1``. +We can label the basis by using ``\ket{j, m}``, where the magnetic quantum number takes on values ``m \in \{j, j-1, \ldots, -j\}`` (in that order). + +Each irrep acts on the standard basis $\lvert j, m \rangle$ where $m = j, j-1, \dots, -j$. +In that basis, the generators of ``\mathfrak{su}(2)`` are represented by the usual angular momentum operators: + +```math +J_z \lvert j, m \rangle = m \lvert j, m \rangle, \quad +J_\pm \lvert j, m \rangle = \sqrt{(j \mp m)(j \pm m + 1)}\, \lvert j, m \pm 1 \rangle. +``` + +```jldoctest generators; output = false +using TensorKitSectors + +function generators(a::SU2Irrep) + Jp = zeros(dim(a), dim(a)) + Jm = zeros(dim(a), dim(a)) + Jz = zeros(dim(a), dim(a)) + + for row in axes(Jp, 1), col in axes(Jp, 2) + m = a.j - col + 1 + if row == col + Jz[row, col] = m + elseif row + 1 == col + Jp[row, col] = sqrt((a.j - m) * (a.j + m + 1)) + elseif row == col + 1 + Jm[row, col] = sqrt((a.j + m) * (a.j - m + 1)) + end + end + + return Jp, Jm, Jz +end + +a = SU2Irrep(1) +Jp, Jm, Jz = generators(a) + +# output +([0.0 1.4142135623730951 0.0; 0.0 0.0 1.4142135623730951; 0.0 0.0 0.0], [0.0 0.0 0.0; 1.4142135623730951 0.0 0.0; 0.0 1.4142135623730951 0.0], [1.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 -1.0]) +``` + +The tensor product representation for ``a \otimes b`` is given in terms of the representations ``a`` and ``b`` as: + +```math +\mathbf{J}^{(a \otimes b)} = \mathbf{J}^{(a)} \otimes \mathbf{1}^{(b)} + \mathbf{1}^{(a)} \otimes \mathbf{J}^{(b)} +``` + +The [`fusiontensor`](@ref) supplies the change‑of‑basis coefficients ``C^{J M}_{j_a m_a, j_b m_b}`` that map the uncoupled product basis to the coupled basis: + +```math +\lvert J, M \rangle = \sum_{m_a, m_b} C^{J M}_{j_a m_a, j_b m_b} +\lvert j_a, m_a \rangle \otimes \lvert j_b, m_b \rangle. +``` + +In particular, this block-diagonalizes the generators, and we must have that for every ``\mathbf{J}``, the following holds: + +```math +\left(\mathbf{J}^{(a)} \otimes \mathbf{1}^{(b)} + \mathbf{1}^{(a)} \otimes \mathbf{J}^{(b)}\right) \cdot C^c_{ab} = + C^c_{ab} \cdot \mathbf{J}^{(c)} +``` + +```jldoctest generators; output = false +using TensorOperations: @tensor +using Test: @test + +a = SU2Irrep(1) +b = SU2Irrep(1) + +for c in a ⊗ b + CGC = dropdims(fusiontensor(a, b, c); dims = 4) # drop trivial multiplicity dimension + for (ga, gb, gc) in zip(generators(a), generators(b), generators(c)) + @tensor lhs[a b; c] := ga[a; a'] * CGC[a' b; c] + gb[b; b'] * CGC[a b'; c] + @tensor rhs[a b; c] := CGC[a b; c'] * gc[c'; c] + @test isapprox(lhs, rhs) + end +end + +# output + +``` + +## References + +For a quick refresher on the group structure and representation theory (without turning this page into a math course), the following references are useful: + +- [Special unitary group](https://en.wikipedia.org/wiki/Special_unitary_group) +- [SU(2)](https://en.wikipedia.org/wiki/SU(2)) +- [Representation theory of SU(2)](https://en.wikipedia.org/wiki/Representation_theory_of_SU(2)) +- [Clebsch–Gordan coefficients](https://en.wikipedia.org/wiki/Clebsch%E2%80%93Gordan_coefficients) +- [Wigner 6j symbol](https://en.wikipedia.org/wiki/6-j_symbol) diff --git a/src/irreps/su2irrep.jl b/src/irreps/su2irrep.jl index 27312ed3..dc92ba26 100644 --- a/src/irreps/su2irrep.jl +++ b/src/irreps/su2irrep.jl @@ -3,9 +3,8 @@ SU2Irrep(j::Real) Irrep[SU₂](j::Real) -Represents irreps of the group ``SU₂``. The irrep is labelled by a half integer `j` which -can be entered as an abitrary `Real`, but is stored as a `HalfInt` from the HalfIntegers.jl -package. +Represents irreps of the group ``SU₂``. +The irrep is labeled by a half integer `j` which can be entered as an arbitrary `Real`, but is stored as a `HalfInt` from the HalfIntegers.jl package. ## Fields - `j::HalfInt`: the label of the irrep, which can be any non-negative half integer. From 7e5631793267fda8b4e4b9a002c698c93099a174 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Thu, 28 May 2026 11:18:03 -0400 Subject: [PATCH 07/50] ci: add PR_comment workflow Adds a GitHub Action that posts the Documenter preview URL as a comment on pull requests. --- .github/workflows/PR_comment.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/PR_comment.yml diff --git a/.github/workflows/PR_comment.yml b/.github/workflows/PR_comment.yml new file mode 100644 index 00000000..1c193280 --- /dev/null +++ b/.github/workflows/PR_comment.yml @@ -0,0 +1,17 @@ +name: Docs preview comment +on: + pull_request: + types: [labeled] + +permissions: + pull-requests: write +jobs: + pr_comment: + runs-on: ubuntu-latest + steps: + - name: Create PR comment + if: github.event_name == 'pull_request' && github.repository == github.event.pull_request.head.repo.full_name && github.event.label.name == 'documentation' + uses: thollander/actions-comment-pull-request@v3 + with: + message: 'After the build completes, the updated documentation will be available [here](https://quantumkithub.github.io/TensorKitSectors.jl/previews/PR${{ github.event.number }}/)' + comment-tag: 'preview-doc' From da40bfe40fb18201dd2fd93ecc7d19d2547956f6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 29 May 2026 17:03:07 +0200 Subject: [PATCH 08/50] a4 --- docs/src/sectors/nonabelian/a4.md | 135 +++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 13 deletions(-) diff --git a/docs/src/sectors/nonabelian/a4.md b/docs/src/sectors/nonabelian/a4.md index 2c6d97b7..ee885bb8 100644 --- a/docs/src/sectors/nonabelian/a4.md +++ b/docs/src/sectors/nonabelian/a4.md @@ -1,29 +1,138 @@ -# Alternating Group A₄: A4Irrep +# Alternating Group ``A_4``: `A4Irrep` -## Type Definition +`A4Irrep` represents irreducible representations (irreps) of the alternating group ``A_4`` as a `Sector`. +This page documents how the type behaves in code (construction, iteration, fusion, and access to topological data). -## Construction +## Sector type -## Labels +The irreps of ``A_4`` are labeled by integers `0:3`. +The first three labels are the one-dimensional representations ``1``, ``1'``, and ``1''``; label `3` is the three-dimensional irrep ``3``. -## Physical Interpretation +```@docs; canonical = false +A4Irrep +``` + +The trivial sector is `A4Irrep(0)`. +Duals are + +```math +0^* = 0,\qquad 1^* = 2,\qquad 2^* = 1,\qquad 3^* = 3. +``` ## Fusion Rules -## Quantum Dimensions +The one-dimensional irreps fuse as the group ``\mathbb{Z}_3``: + +```math +a \otimes b = (a + b) \bmod 3,\qquad a,b \in \{0,1,2\}. +``` + +Fusing a one-dimensional irrep with the triplet gives the triplet again: + +```math +a \otimes 3 = 3 \otimes a = 3,\qquad a \in \{0,1,2\}. +``` + +The triplet product decomposes as + +```math +3 \otimes 3 = 0 \oplus 1 \oplus 2 \oplus 2 * 3. +``` + +Because the triplet appears with multiplicity two in ``3 \otimes 3``, `FusionStyle(A4Irrep) = GenericFusion()`. +The [`Nsymbol`](@ref) returns the corresponding integer multiplicity: + +```math +N_c^{ab} = +\begin{cases} +1 + \delta_{c,3}, & a = b = 3,\\ +\delta_{c,3}, & a = 3 \text{ or } b = 3,\\ +\delta_{c,(a+b)\bmod 3}, & a,b \in \{0,1,2\}. +\end{cases} +``` + +The quantum dimensions are the ordinary representation space dimensions: + +```math +d_0 = d_1 = d_2 = 1,\qquad d_3 = 3. +``` ## Topological Data -### F-symbols +`A4Irrep` describes the fusion category ``\mathsf{Rep(A_4)}``. +The braiding is bosonic, and all topological twists are `1`. + +The [`Fsymbol`](@ref) is computed from the chosen [`fusiontensor`](@ref) basis, see below. +The [`Rsymbol`](@ref) is the identity on all simple fusion channels, except for the two ``3`` channels in +``3 \otimes 3 \to 3``: + +```math +R^{33}_3 = +\begin{pmatrix} +-1 & 0\\ +0 & 1 +\end{pmatrix}. +``` + +The first channel is the antisymmetric triplet and the second channel is the symmetric triplet. + +## Fusion Tensor and Basis Conventions + +`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. +The one-dimensional fusion tensors are scalar phases/permutations in the selected basis. +For ``3 \otimes 3``, the singlet channels are normalized with a factor ``1/\sqrt{3}``, and the two triplet channels use the real antisymmetric and symmetric Clebsch-Gordan tensors from the tetrahedral basis convention used in the implementation. + +In this basis the triplet representation can be generated by + +```math +T_3 = +\begin{pmatrix} +1 & 0 & 0\\ +0 & \omega & 0\\ +0 & 0 & \omega^2 +\end{pmatrix}, +\qquad +S_3 = \frac{1}{3} +\begin{pmatrix} +-1 & 2 & 2\\ +2 & -1 & 2\\ +2 & 2 & -1 +\end{pmatrix}, +\qquad +\omega = e^{2\pi i/3}. +``` + +The one-dimensional irreps have ``S = 1`` and ``T = \omega^n`` for label `n`. +For every allowed fusion channel, the fusion tensor intertwines the product representation with the output representation. + +```jldoctest a4_intertwiner; output = false +using TensorKitSectors +using LinearAlgebra: kron +using Test: @test + +omega = cis(2pi / 3) +T3 = [1 0 0; 0 omega 0; 0 0 omega^2] +S3 = 1 / 3 * [-1 2 2; 2 -1 2; 2 2 -1] -### R-symbols +T(a::A4Irrep) = a.n == 3 ? T3 : hcat(omega^a.n) +S(a::A4Irrep) = a.n == 3 ? S3 : hcat(1) -### Braiding Style +a = A4Irrep(3) +b = A4Irrep(3) +c = A4Irrep(3) +C = fusiontensor(a, b, c) -## Basis Conventions +for mu in 1:Nsymbol(a, b, c) + Cmat = reshape(view(C, :, :, :, mu), dim(a) * dim(b), dim(c)) + @test Cmat' * kron(T(a), T(b)) * Cmat ≈ T(c) + @test Cmat' * kron(S(a), S(b)) * Cmat ≈ S(c) +end +``` -## Iteration +## References -## Code Examples +For background on the group and the representation basis, see: -## Implementation Notes +- [Alternating group](https://en.wikipedia.org/wiki/Alternating_group) +- [Tetrahedral symmetry](https://en.wikipedia.org/wiki/Tetrahedral_symmetry) +- G. Altarelli and F. Feruglio, "Discrete Flavor Symmetries and Models of Neutrino Mixing", Rev. Mod. Phys. 82, 2701 (2010). From 1d94788f1c03d80c34ce73f39dfa1a4606ea4ce6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 29 May 2026 17:12:19 +0200 Subject: [PATCH 09/50] minor su2 changes --- docs/src/sectors/nonabelian/su2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/sectors/nonabelian/su2.md b/docs/src/sectors/nonabelian/su2.md index f10b8cf7..1eea2341 100644 --- a/docs/src/sectors/nonabelian/su2.md +++ b/docs/src/sectors/nonabelian/su2.md @@ -1,11 +1,11 @@ # ``SU(2)`` Representations: `SU2Irrep` -`SU2Irrep` represents irreducible representations of the compact group ``SU(2)`` as a `Sector`. +`SU2Irrep` represents irreducible representations (irreps) of the compact group ``SU(2)`` as a `Sector`. This page documents how the type behaves in code (construction, iteration, fusion, and access to topological data). ## Sector type -The irreducible representations of ``SU(2)`` are labeled by non-negative half-integers (e.g. ``0``, ``\frac{1}{2}``, ``1``, ``\frac{3}{2}``, …). +The irreps of ``SU(2)`` are labeled by non-negative integers or half-integers (e.g. ``0``, ``\frac{1}{2}``, ``1``, ``\frac{3}{2}``, …). ```@docs; canonical = false SU2Irrep From eec44280e006d70f467df82e66485764570931cf Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 29 May 2026 17:19:13 +0200 Subject: [PATCH 10/50] small a4 change --- docs/src/sectors/nonabelian/a4.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/sectors/nonabelian/a4.md b/docs/src/sectors/nonabelian/a4.md index ee885bb8..b19e56ba 100644 --- a/docs/src/sectors/nonabelian/a4.md +++ b/docs/src/sectors/nonabelian/a4.md @@ -1,4 +1,4 @@ -# Alternating Group ``A_4``: `A4Irrep` +# Representation of the Alternating Group ``A_4``: `A4Irrep` `A4Irrep` represents irreducible representations (irreps) of the alternating group ``A_4`` as a `Sector`. This page documents how the type behaves in code (construction, iteration, fusion, and access to topological data). From 6e7a41781efeb2e4f2e0aca09b0f71b0f8bad3e1 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 29 May 2026 17:28:15 +0200 Subject: [PATCH 11/50] u1 --- docs/src/sectors/abelian/u1.md | 46 ++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/docs/src/sectors/abelian/u1.md b/docs/src/sectors/abelian/u1.md index 8ab74f07..0125359a 100644 --- a/docs/src/sectors/abelian/u1.md +++ b/docs/src/sectors/abelian/u1.md @@ -1,29 +1,49 @@ -# U(1) Representations: U1Irrep +# ``U(1)`` Representations: `U1Irrep` -## Type Definition +`U1Irrep` represents irreducible representations of the compact abelian group ``U(1)`` as a `Sector`. +The implementation stores charges as half-integers, which is useful for spin systems where z-component of an ``SU(2)`` spin may be half-integral. -## Construction +## Sector type -## Labels +```@docs; canonical = false +U1Irrep +``` -## Physical Interpretation +The unit is `U1Irrep(0)`, and duality negates the charge: + +```math +q^* = -q. +``` ## Fusion Rules -## Quantum Dimensions +Fusion adds charges: + +```math +q_1 \otimes q_2 = q_1 + q_2. +``` ## Topological Data -### F-symbols +The category has `FusionStyle(U1Irrep) = UniqueFusion()`. +All irreps have quantum dimension `1`, and the [`Nsymbol`](@ref) is `true` exactly when the output charge is the sum of the input charges. + +The [`Fsymbol`](@ref), [`Rsymbol`](@ref), and [`fusiontensor`](@ref) are all trivial on allowed fusion channels. +Since this is a representation category, the braiding style is `Bosonic()` and all twists are `1`. -### R-symbols +## Iteration and basis conventions -### Braiding Style +`values(U1Irrep)` is infinite. +The iterator starts at zero and alternates positive and negative charges: -## Basis Conventions +```julia +using TensorKitSectors -## Iteration Order +values(U1Irrep)[6] # output: Irrep[U₁](3/2) +values(U1Irrep)[7] # output: Irrep[U₁](-3/2) +``` -## Code Examples +## References -## Implementation Notes +- [Unitary group](https://en.wikipedia.org/wiki/Unitary_group) +- [Circle group](https://en.wikipedia.org/wiki/Circle_group) From 4d6a31ff5faedc70228779be7a5ba7e4d398351d Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 29 May 2026 17:38:18 +0200 Subject: [PATCH 12/50] trivial and planartrivial --- docs/src/sectors/abelian/trivial.md | 45 +++++++++++++++++++----- docs/src/sectors/anyons/planartrivial.md | 34 ++++++++++-------- 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/docs/src/sectors/abelian/trivial.md b/docs/src/sectors/abelian/trivial.md index 728ccaad..8a77e58e 100644 --- a/docs/src/sectors/abelian/trivial.md +++ b/docs/src/sectors/abelian/trivial.md @@ -1,15 +1,44 @@ -# Trivial Sector +# Trivial Sector: `Trivial` -## Trivial +`Trivial` is the trivial sector for ordinary vector spaces. +It is the trivial representation of the trivial group, equivalently `Rep[ℤ₁]`. -### Type Definition +## Sector type -### Construction +```@docs; canonical = false +Trivial +``` -### Labels +There is only one label: -### Fusion Rules +```julia +using TensorKitSectors -### Quantum Dimensions +Trivial() +``` -### Topological Data +## Fusion Rules + +Fusion is uniquely trivial: + +```math +1 \otimes 1 = 1. +``` + +Therefore `FusionStyle(Trivial) = UniqueFusion()` and `Nsymbol(Trivial(), Trivial(), Trivial()) == true`. + +## Topological Data + +The quantum dimension is `1`. +`fusiontensor` is a `1 × 1 × 1 × 1` array containing `1`. +The associator and braiding are both trivial: + +```math +F = 1,\qquad R = 1. +``` + +The braiding style is `Bosonic()`. + +## References + +- [Trivial group](https://en.wikipedia.org/wiki/Trivial_group) diff --git a/docs/src/sectors/anyons/planartrivial.md b/docs/src/sectors/anyons/planartrivial.md index b48ae15e..a824780d 100644 --- a/docs/src/sectors/anyons/planartrivial.md +++ b/docs/src/sectors/anyons/planartrivial.md @@ -1,27 +1,31 @@ -# PlanarTrivial +# Planar Trivial Anyon: `PlanarTrivial` -## Type Definition +`PlanarTrivial` is the one-object fusion category without braiding. +It is mostly useful as the smallest planar, non-braided sector in tests and examples. -## Construction +## Sector type -## Labels +```@docs; canonical = false +PlanarTrivial +``` -## Physical Interpretation +There is only one label, `PlanarTrivial()`. +It is its own unit and dual. ## Fusion Rules -## Quantum Dimensions +Fusion is uniquely trivial: -## Topological Data - -### F-symbols +```math +1 \otimes 1 = 1. +``` -### R-symbols +`FusionStyle(PlanarTrivial) = UniqueFusion()` and `Nsymbol` is `1` for the only allowed channel. -### Braiding Style - -### Twist +## Topological Data -## Code Examples +The [`Fsymbol`](@ref) is `1`. +The quantum dimension is `1`. -## Implementation Notes +Unlike [`Trivial`](@ref), this sector has `BraidingStyle(PlanarTrivial) = NoBraiding()`. +Consequently, braiding data such as [`Rsymbol`](@ref) and twists are not part of this sector. From 522de26699d2623904b4d34f15fc65016b5226e1 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 29 May 2026 17:46:28 +0200 Subject: [PATCH 13/50] ising and fibonacci --- docs/src/sectors/anyons/fibonacci.md | 57 +++++++++++++++++++------- docs/src/sectors/anyons/ising.md | 61 +++++++++++++++++++++------- 2 files changed, 90 insertions(+), 28 deletions(-) diff --git a/docs/src/sectors/anyons/fibonacci.md b/docs/src/sectors/anyons/fibonacci.md index f9c5e575..81bbcece 100644 --- a/docs/src/sectors/anyons/fibonacci.md +++ b/docs/src/sectors/anyons/fibonacci.md @@ -1,31 +1,60 @@ -# Fibonacci Anyons +# Fibonacci Anyons: `FibonacciAnyon` -## Type Definition +`FibonacciAnyon` represents the Fibonacci modular fusion category. +It has a trivial anyon `:I` and a non-trivial anyon `:τ` (`:tau` is accepted as an ASCII constructor alias). -## Construction +## Sector type -## Labels +```@docs; canonical = false +FibonacciAnyon +``` -## Physical Interpretation +Both sectors are self-dual, and the unit is `FibonacciAnyon(:I)`. ## Fusion Rules -## Quantum Dimensions +The only non-trivial fusion rule is + +```math +\tau \otimes \tau = I \oplus \tau. +``` + +Thus `FusionStyle(FibonacciAnyon) = SimpleFusion()`. +The quantum dimensions are + +```math +d_I = 1,\qquad d_\tau = \varphi = \frac{1 + \sqrt{5}}{2}. +``` ## Topological Data -### F-symbols +The non-trivial associator appears when all external anyons are ``\tau``: + +```math +F^{\tau\tau\tau}_{\tau} = +\begin{pmatrix} +\varphi^{-1} & \varphi^{-1/2}\\ +\varphi^{-1/2} & -\varphi^{-1} +\end{pmatrix}, +``` -### R-symbols +in the intermediate basis ``(I,\tau)``. +All other allowed `Fsymbol` values are `1`. -### Braiding Style +The braiding style is `Anyonic()`. +For ``\tau \otimes \tau``, -### Twist +```math +R^{\tau\tau}_I = e^{4\pi i/5},\qquad +R^{\tau\tau}_\tau = e^{-3\pi i/5}. +``` -## Code Examples +There is no fusion tensor as the fusion category does not originate from a group or its representations. -## Implementation Notes +## Iteration and basis conventions +`values(FibonacciAnyon)` iterates the labels in the order `:I`, `:τ`. -### Key Values +## References -### References +- [Fibonacci anyon](https://en.wikipedia.org/wiki/Anyon#Fibonacci_anyons) +- [Modular tensor category](https://en.wikipedia.org/wiki/Modular_tensor_category) diff --git a/docs/src/sectors/anyons/ising.md b/docs/src/sectors/anyons/ising.md index 1b93e313..fc7d23b1 100644 --- a/docs/src/sectors/anyons/ising.md +++ b/docs/src/sectors/anyons/ising.md @@ -1,31 +1,64 @@ -# Ising Anyons +# Ising Anyons: `IsingAnyon` -## Type Definition +`IsingAnyon` represents the Ising modular fusion category. +It has labels `:I`, `:σ`, and `:ψ`; the ASCII aliases `:sigma` and `:psi` are accepted by the constructor. -## Construction +## Sector type -## Labels +```@docs; canonical = false +IsingAnyon +``` -## Physical Interpretation +All three sectors are self-dual, and the unit is `IsingAnyon(:I)`. ## Fusion Rules -## Quantum Dimensions +The non-trivial fusion rules are + +```math +\psi \otimes \psi = I,\qquad +\sigma \otimes \psi = \psi \otimes \sigma = \sigma,\qquad +\sigma \otimes \sigma = I \oplus \psi. +``` + +Thus `FusionStyle(IsingAnyon) = SimpleFusion()`. +The quantum dimensions are + +```math +d_I = 1,\qquad d_\psi = 1,\qquad d_\sigma = \sqrt{2}. +``` ## Topological Data -### F-symbols +The non-trivial associator for four ``\sigma`` anyons is + +```math +F^{\sigma\sigma\sigma}_{\sigma} = +\frac{1}{\sqrt{2}} +\begin{pmatrix} +1 & 1\\ +1 & -1 +\end{pmatrix}, +``` -### R-symbols +in the intermediate basis ``(I,\psi)``. +Additional signs involving the fermion ``\psi`` are encoded by [`Fsymbol`](@ref). -### Braiding Style +The braiding style is `Anyonic()`. +Important braiding phases are -### Twist +```math +R^{\sigma\sigma}_I = e^{-\pi i/8},\qquad +R^{\sigma\sigma}_\psi = e^{3\pi i/8},\qquad +R^{\psi\psi}_I = -1. +``` -## Code Examples +There is no fusion tensor as the fusion category does not originate from a group or its representations. -## Implementation Notes +## Iteration and basis conventions +`values(IsingAnyon)` iterates the labels in the order `:I`, `:σ`, `:ψ`. -### Key Values +## References -### References +- [Ising anyon](https://en.wikipedia.org/wiki/Anyon#Ising_anyons) +- [Modular tensor category](https://en.wikipedia.org/wiki/Modular_tensor_category) From 47766319b7f8c5e45d5b839a23f04931d33de7ad Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 29 May 2026 17:51:46 +0200 Subject: [PATCH 14/50] zn --- docs/src/sectors/abelian/zn.md | 54 +++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/docs/src/sectors/abelian/zn.md b/docs/src/sectors/abelian/zn.md index 8013bb43..dd5805ca 100644 --- a/docs/src/sectors/abelian/zn.md +++ b/docs/src/sectors/abelian/zn.md @@ -1,41 +1,47 @@ -# Cyclic Groups: ZNIrrep +# Cyclic Group Representations: `ZNIrrep` -## Type Definition +`ZNIrrep{N}` and `LargeZNIrrep{N}` represent irreducible representations of the cyclic group ``\mathbb{Z}_N``. +Use `ZNIrrep{N}` when possible; it selects the compact storage type automatically. -## Construction +## Sector types -## Labels +```@docs; canonical = false +ZNIrrep +LargeZNIrrep +``` -### ZNIrrep{N} - -### LargeZNIrrep{N} - -## Physical Interpretation +`Z2Irrep`, `Z3Irrep`, and `Z4Irrep` are aliases for `ZNIrrep{2}`, `ZNIrrep{3}`, and `ZNIrrep{4}`. +For small `N`, labels are stored as `UInt8`; larger `N` uses `LargeZNIrrep{N}`. ## Fusion Rules -## Quantum Dimensions - -## Topological Data - -### F-symbols +Labels are charges modulo `N`. +The unit is charge `0`, duality negates the charge modulo `N`, and fusion adds charges: -### R-symbols +```math +a \otimes b = (a + b) \bmod N,\qquad a^* = -a \bmod N. +``` -### Braiding Style +The category has `FusionStyle(ZNIrrep{N}) = UniqueFusion()`. -## Basis Conventions +## Topological Data -## Iteration +All quantum dimensions are `1`, as well as all twist. +F-symbols, R-symbols and fusion tensors are trivial in allowed channels. +The braiding style is `Bosonic()`. -## Code Examples +## Iteration and basis conventions -## Implementation Notes +`values(ZNIrrep{N})` iterates charges in increasing order from `0` to `N - 1`. -### Storage Details +```julia +using TensorKitSectors -### Performance Considerations +values(ZNIrrep{5})[4] # output is Irrep[ℤ{5}](3) +values(ZNIrrep{34})[34] # output is Irrep[ℤ{34}](33) +``` -## Related Types +## References -### Z2Irrep, Z3Irrep, Z4Irrep +- [Cyclic group](https://en.wikipedia.org/wiki/Cyclic_group) +- [Representation theory of finite groups](https://en.wikipedia.org/wiki/Representation_theory_of_finite_groups) From f5d8892a8c38e56ded75c7ad875b4e0331ca5535 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Sun, 31 May 2026 11:57:55 +0200 Subject: [PATCH 15/50] fermions --- docs/src/sectors/fermions/number.md | 41 ++++++++++++++++--------- docs/src/sectors/fermions/parity.md | 47 ++++++++++++++++++++--------- docs/src/sectors/fermions/spin.md | 46 +++++++++++++++++++--------- 3 files changed, 91 insertions(+), 43 deletions(-) diff --git a/docs/src/sectors/fermions/number.md b/docs/src/sectors/fermions/number.md index 07106c1f..38a9c9a2 100644 --- a/docs/src/sectors/fermions/number.md +++ b/docs/src/sectors/fermions/number.md @@ -1,29 +1,42 @@ -# Fermion Number: FermionNumber +# Fermion Number: `FermionNumber` -## Type Definition +`FermionNumber` is a convenience sector for integer ``U(1)`` charge together with the matching fermion parity. +It is implemented as `U1Irrep ⊠ FermionParity`, with odd charge assigned odd parity. -## Construction +## Sector type -## Labels +```@docs; canonical = false +FermionNumber +``` -## Physical Interpretation +Construct `FermionNumber(n)` from an integer charge `n`. +The underlying product label is + +```math +n \mapsto (U(1)\text{ charge } n,\; n \bmod 2). +``` + +The unit is `FermionNumber(0)`, and duality negates the ``U(1)`` charge while preserving the parity constraint. ## Fusion Rules -## Quantum Dimensions +Fusion adds charges: -## Topological Data +```math +n_1 \otimes n_2 = n_1 + n_2. +``` -### F-symbols +The fermion parity component is then fixed automatically by the resulting charge. -### R-symbols +## Topological data -### Braiding Style +All sectors have quantum dimension `1`. -### Twist +The ``U(1)`` part has bosonic representation-category data, while the parity part supplies the fermionic exchange sign. +Thus exchanging two odd-charge sectors contributes a minus sign. -## Code Examples +Because this is a product sector, its fusion and topological data is inherited componentwise from [`U1Irrep`](@ref) and [`FermionParity`](@ref). -## Implementation Notes +## References -### Relationship to U₁ × Fermion Parity +- [Fermion number](https://en.wikipedia.org/wiki/Fermion_number) \ No newline at end of file diff --git a/docs/src/sectors/fermions/parity.md b/docs/src/sectors/fermions/parity.md index ee613321..049cc0d2 100644 --- a/docs/src/sectors/fermions/parity.md +++ b/docs/src/sectors/fermions/parity.md @@ -1,29 +1,48 @@ -# Fermion Parity: FermionParity +# Fermion Parity: `FermionParity` -## Type Definition +`FermionParity` is the two-sector fermionic category ``SVect`` for even and odd parity. +Odd sectors pick up a minus sign when exchanged with another odd sector. -## Construction +## Sector type -## Labels +```@docs; canonical = false +FermionParity +``` -## Physical Interpretation +The labels are `FermionParity(false)` for even parity and `FermionParity(true)` for odd parity. +They are displayed as `FermionParity(0)` and `FermionParity(1)`. +The unit is even parity, and every sector is self-dual. ## Fusion Rules -## Quantum Dimensions +Fusion is addition modulo two: -## Topological Data +```math +p \otimes q = p \oplus q. +``` -### F-symbols +The category has `FusionStyle(FermionParity) = UniqueFusion()`. -### R-symbols +## Topological data -### Braiding Style +All quantum dimensions are `1`, and [`Fsymbol`](@ref) is trivial on allowed channels. -### Twist +The braiding style is `Fermionic()`. +The [`Rsymbol`](@ref) is `-1` only when both input sectors are odd: -## Code Examples +```math +R^{11}_0 = -1. +``` -## Implementation Notes +The twists are -### Relationship to Super Vector Spaces +```math +\theta_0 = 1,\qquad \theta_1 = -1. +``` + +`fusiontensor` is defined for array construction, but it emits a warning because plain arrays with `FermionParity` labels do not preserve all fermionic signs. + +## References + +- [Fermion parity](https://en.wikipedia.org/wiki/Fermion_parity) +- [Super vector space](https://en.wikipedia.org/wiki/Super_vector_space) \ No newline at end of file diff --git a/docs/src/sectors/fermions/spin.md b/docs/src/sectors/fermions/spin.md index a4cdb945..2352e29f 100644 --- a/docs/src/sectors/fermions/spin.md +++ b/docs/src/sectors/fermions/spin.md @@ -1,29 +1,45 @@ -# Fermion Spin: FermionSpin +# Fermion Spin: `FermionSpin` -## Type Definition +`FermionSpin` is a convenience sector for ``SU(2)`` spin together with the matching fermion parity. +It is implemented as `SU2Irrep ⊠ FermionParity`, with half-integer spin assigned odd parity. -## Construction +## Sector type -## Labels +```@docs; canonical = false +FermionSpin +``` -## Physical Interpretation +Construct `FermionSpin(j)` from an integer or half-integer spin. +The parity is odd exactly when `2j` is odd: -## Fusion Rules +```math +j \mapsto (SU(2)\text{ spin }j,\; 2j \bmod 2). +``` + +The unit is `FermionSpin(0)`, and all sectors are self-dual because the ``SU(2)`` irreps and parity sectors are self-dual. -## Quantum Dimensions +## Fusion Rules -## Topological Data +The ``SU(2)`` component fuses by angular-momentum addition: -### F-symbols +```math +j_1 \otimes j_2 = +\bigoplus_{j = |j_1-j_2|}^{j_1+j_2} j. +``` -### R-symbols +The parity component is fixed by the output spin. +Quantum dimensions are inherited from `SU2Irrep`: -### Braiding Style +```math +d_j = 2j + 1. +``` -### Twist +The parity component supplies fermionic signs, so exchanging two half-integer-spin sectors has the odd-parity sign in addition to the `SU2Irrep` representation-category data. -## Code Examples +Because this is a product sector, most fusion and topological data is inherited componentwise from [`SU2Irrep`](@ref) and [`FermionParity`](@ref). -## Implementation Notes +## References -### Relationship to SU₂ × Fermion Parity +- [Spin (physics)](https://en.wikipedia.org/wiki/Spin_(physics)) +- [SU(2)](https://en.wikipedia.org/wiki/SU(2)) +- [Fermion parity](https://en.wikipedia.org/wiki/Fermion_parity) From 7d15f9e4d9c4d9f30fde12dc179c7978b8c3b84f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Sun, 31 May 2026 12:20:19 +0200 Subject: [PATCH 16/50] dn --- docs/src/sectors/nonabelian/dn.md | 71 ++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/docs/src/sectors/nonabelian/dn.md b/docs/src/sectors/nonabelian/dn.md index e4821923..c11b6f58 100644 --- a/docs/src/sectors/nonabelian/dn.md +++ b/docs/src/sectors/nonabelian/dn.md @@ -1,39 +1,72 @@ -# Dihedral Groups: DNIrrep +# Dihedral Group Representations: `DNIrrep` -## Type Definition +`DNIrrep{N}` represents irreducible representations of the dihedral group ``D_N = \mathbb{Z}_N ⋊ C``. +The aliases `D3Irrep` and `D4Irrep` are provided for `DNIrrep{3}` and `DNIrrep{4}`. -## Construction +## Sector type -## Labels +```@docs; canonical = false +DNIrrep +``` -### DNIrrep{N} for N odd +Labels are constructed as `DNIrrep{N}(j, isodd=false)`. +The integer `j` satisfies `0 <= j <= N ÷ 2`. +The `isodd` flag is valid only for one-dimensional irreps: always at `j == 0`, and also at `j == N/2` when `N` is even. -### DNIrrep{N} for N even +For odd `N`, the labels are -## Physical Interpretation +```math +(0,\text{false}),\ (0,\text{true}),\ 1,2,\ldots,(\frac{N-1}{2},\text{false}). +``` + +For even `N`, the labels are + +```math +(0,\text{false}),\ (0,\text{true}),\ 1,2,\ldots,\frac{N}{2}-1,\ (N/2,\text{false}),\ (N/2,\text{true}). +``` + +The unit is `DNIrrep{N}(0, false)`, and all irreps are self-dual. ## Fusion Rules -## Quantum Dimensions +The one-dimensional irreps fuse by XOR of the parity label. +The fusion product of a one-dimensional irrep with a two-dimensional irrep preserves the two-dimensional label, up to the special one-dimensional labels at `j == N/2` for even `N`. -## Topological Data +For ordinary two-dimensional labels, fusion follows the dihedral character rule: -### F-symbols +```math +\rho_i \otimes \rho_j = \rho_{|i-j|} \oplus \rho_{i+j}, +``` -### R-symbols +where labels are folded back into the range `0:N÷2`. +When a folded output lands on a one-dimensional point (`0`, or `N/2` for even `N`), it splits into the corresponding even and odd one-dimensional irreps. -### Braiding Style +For `N < 3`, `FusionStyle(DNIrrep{N}) = UniqueFusion()`. +Otherwise, `FusionStyle(DNIrrep{N}) = SimpleFusion()`. -## Basis Conventions +Quantum dimensions are -## Iteration +```math +d_{(0,\pm)} = 1,\qquad d_{\rho_j} = 2,\qquad +d_{(N/2,\pm)} = 1\quad (N \text{ even}). +``` -## Code Examples +## Topological Data + +`DNIrrep{N}` is a bosonic representation category, so all twists are `1`. +The [`Fsymbol`](@ref) is computed from the selected [`fusiontensor`](@ref) basis. +The [`Rsymbol`](@ref) is the N-symbol with a possible sign on odd one-dimensional output channels from two non-trivial two-dimensional inputs. + +## Fusion tensor and basis conventions -### D3Irrep +`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. +The implementation uses real Clebsch-Gordan coefficients. +#TODO: source for the convention used here + +## Iteration -### D4Irrep +The `DNIrrep{N}` labels are iterable, with the same ordering as described above. -## Implementation Notes +## References -### Character Tables +- [Dihedral group](https://en.wikipedia.org/wiki/Dihedral_group) \ No newline at end of file From cef7492fa0e43b630b8fef58c7ca555805287589 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Sun, 31 May 2026 12:37:49 +0200 Subject: [PATCH 17/50] cu1 --- docs/src/sectors/nonabelian/cu1.md | 129 ++++++++++++++++++++++++++--- 1 file changed, 117 insertions(+), 12 deletions(-) diff --git a/docs/src/sectors/nonabelian/cu1.md b/docs/src/sectors/nonabelian/cu1.md index 57f2c971..1e69222e 100644 --- a/docs/src/sectors/nonabelian/cu1.md +++ b/docs/src/sectors/nonabelian/cu1.md @@ -1,29 +1,134 @@ -# CU(1): U(1) ⋉ ℤ₂ +# ``CU(1)`` Representations: `CU1Irrep` -## Type Definition +`CU1Irrep` represents irreducible representations of ``U(1) ⋊ C``, where `C` acts by charge conjugation. +This group is also known as ``O(2)``. -## Construction +## Sector type -## Labels +```@docs; canonical = false +CU1Irrep +``` -## Physical Interpretation +Labels are pairs `(j, s)`, where `j` is a `U1Irrep` charge and `s` is an integer in `0:2`. +For `j == 0`, there are two one-dimensional irreps: `CU1Irrep(0, 0)` and `CU1Irrep(0, 1)`. +For `j > 0`, only `s == 2` is valid and the representation is two-dimensional. +The unit is `CU1Irrep(0, 0)`, and every irrep is self-dual. ## Fusion Rules -## Quantum Dimensions +The two one-dimensional irreps fuse by XOR of the `s` label. +Fusing either one-dimensional irrep with a two-dimensional irrep returns the same two-dimensional label. +For two positive charges, the outputs are governed by sum and absolute difference: + +```math +j_1 \otimes j_2 = +|j_1-j_2| \oplus (j_1+j_2), +``` + +with the special case `j1 == j2`, where the zero-charge difference splits into the two one-dimensional irreps. +The category has `FusionStyle(CU1Irrep) = SimpleFusion()`. + +Quantum dimensions are + +```math +d_{(0,0)} = d_{(0,1)} = 1,\qquad d_{(j,2)} = 2\quad (j>0). +``` ## Topological Data -### F-symbols +`CU1Irrep` is a bosonic representation category, so all twists are `1`. +The [`Fsymbol`](@ref) values are real and encode the chosen Clebsch-Gordan basis. +The [`Rsymbol`](@ref) is real and equals the N-symbol, with an additional negative sign on channels with `c.s == 1` and positive left overbraiding input charge. + +## Fusion Tensor and Basis Conventions + +`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. +Since `CU1Irrep` has simple fusion, the final multiplicity axis has length `0` or `1`. +For allowed channels, the tensor entries are real Clebsch-Gordan coefficients in the convention explained below. + +For a two-dimensional irrep `(j, 2)` with `j > 0`, the basis is ordered as a pair of charge-conjugate ``U(1)`` weights, which we can denote by + +```math +\ket{+j},\ \ket{-j}. +``` + +The zero-charge irreps `(0, 0)` and `(0, 1)` are one-dimensional. The label `(0, 0)` is even under charge conjugation, while `(0, 1)` is odd. + +When two equal positive-charge irreps fuse to a zero-charge irrep, the fusion tensors pick the symmetric and antisymmetric combinations: + +```math +\ket{(0,0)} = +\frac{1}{\sqrt{2}}\left(\ket{+j}\otimes\ket{-j} + \ket{-j}\otimes\ket{+j}\right), +``` + +```math +\ket{(0,1)} = +\frac{1}{\sqrt{2}}\left(\ket{+j}\otimes\ket{-j} - \ket{-j}\otimes\ket{+j}\right). +``` + +In array form, these are the entries + +```math +C_{1,2,1} = \frac{1}{\sqrt{2}},\qquad +C_{2,1,1} = \pm\frac{1}{\sqrt{2}}, +``` -### R-symbols +with the plus sign for `(0, 0)` and the minus sign for `(0, 1)`. -### Braiding Style +Fusing a zero-charge irrep with a two-dimensional irrep leaves the charge label unchanged. +The odd zero-charge irrep contributes a sign on the second basis vector: -## Basis Conventions +```math +(0,s) \otimes (j,2) \to (j,2):\qquad +\ket{+j}\mapsto\ket{+j},\quad +\ket{-j}\mapsto (-1)^s\ket{-j}. +``` + +The same convention is used for `(j,2) ⊗ (0,s)`, with the sign attached to the second basis vector of the two-dimensional input. + +For two positive charges, the sum channel is diagonal: + +```math +(j_a,2)\otimes(j_b,2)\to(j_a+j_b,2):\qquad +\ket{+j_a,+j_b}\mapsto\ket{+(j_a+j_b)},\quad +\ket{-j_a,-j_b}\mapsto\ket{-(j_a+j_b)}. +``` + +The difference channel pairs opposite weights. If `j_a > j_b`, + +```math +\ket{+j_a,-j_b}\mapsto\ket{+(j_a-j_b)},\qquad +\ket{-j_a,+j_b}\mapsto\ket{-(j_a-j_b)}. +``` + +If `j_b > j_a`, the output basis is ordered by the positive charge `j_b - j_a`, so the two nonzero entries are swapped accordingly: + +```math +\ket{-j_a,+j_b}\mapsto\ket{+(j_b-j_a)},\qquad +\ket{+j_a,-j_b}\mapsto\ket{-(j_b-j_a)}. +``` + +All omitted entries are zero. These conventions determine the real [`Fsymbol`](@ref) values. ## Iteration -## Code Examples +`values(CU1Irrep)` is infinite. +It starts with the two zero-charge irreps and then lists positive half-integer charges: + +```julia +using TensorKitSectors + +values(CU1Irrep)[1] +Irrep[CU₁](0, 0) + +values(CU1Irrep)[2] +Irrep[CU₁](0, 1) + +values(CU1Irrep)[5] +Irrep[CU₁](3/2, 2) +``` + +## References -## Implementation Notes +- [Orthogonal group in two dimensions](https://en.wikipedia.org/wiki/Orthogonal_group_in_two_dimensions) +- [Semidirect product](https://en.wikipedia.org/wiki/Semidirect_product) \ No newline at end of file From deb2cc0f8653aa6057722df632d3572ecf819ec9 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Sun, 31 May 2026 12:50:51 +0200 Subject: [PATCH 18/50] product and timereversed --- docs/src/sectors/composite/product.md | 102 ++++++++++++++++++--- docs/src/sectors/composite/timereversed.md | 67 +++++++++++--- 2 files changed, 141 insertions(+), 28 deletions(-) diff --git a/docs/src/sectors/composite/product.md b/docs/src/sectors/composite/product.md index 10506c0f..05f0efae 100644 --- a/docs/src/sectors/composite/product.md +++ b/docs/src/sectors/composite/product.md @@ -1,33 +1,105 @@ -# Product Sectors: ProductSector +# Product Sectors: `ProductSector` -## Type Definition +`ProductSector` represents the Deligne tensor product of sector categories. +It is the standard way to combine independent symmetry or anyon labels, such as charge and parity, or two different anyon theories. For the bosonic group or representation categories, this Deligne product corresponds to the ordinary product of groups or direct product of representations. -## Construction +## Sector type -### Direct Construction +```@docs; canonical = false +ProductSector +⊠ +``` -### Using the ⊠ Operator +A product sector stores its component sectors in a tuple. +The recommended constructor is the Deligne product operator `⊠` or `boxtimes`: -## Labels +```julia +using TensorKitSectors -## Combining Symmetries +a = Z2Irrep(1) ⊠ FibonacciAnyon(:τ) # (Irrep[ℤ₂](1) ⊠ FibonacciAnyon(:τ)) +``` + +The same operator works on sector types: + +```julia +using TensorKitSectors + +I = Z2Irrep ⊠ FibonacciAnyon +a = I(1, :τ) +``` + +Products are flattened, and `Trivial` factors are removed: + +```math +(a \boxtimes b) \boxtimes c = a \boxtimes b \boxtimes c,\qquad +a \boxtimes \mathbf{1} = a. +``` + +For representation categories, type-level products are displayed as irreps of the product group. +For example, `Z2Irrep ⊠ Z3Irrep` behaves as `Irrep[ℤ₂ × ℤ₃]`. +Product sectors are used to define several convenience aliases, such as [`FermionNumber`](@ref) and [`FermionSpin`](@ref). ## Fusion Rules -## Quantum Dimensions +Fusion is componentwise. +For product sectors + +```math +a = (a_1,\ldots,a_n),\qquad b = (b_1,\ldots,b_n), +``` + +the fusion outputs are + +```math +a \otimes b = +\bigoplus_{c_i \in a_i \otimes b_i} N^{ab}_c +(c_1,\ldots,c_n). +``` + +The fusion multiplicities multiply: + +```math +N^{ab}_c = \prod_i N^{a_i b_i}_{c_i}. +``` + +The fusion style is the combined style of the components. +In particular, a product of unique-fusion sectors remains unique, while adding a simple or generic component promotes the product accordingly. + +Duals, units, and quantum dimensions are also componentwise: + +```math +(a_1,\ldots,a_n)^* = (a_1^*,\ldots,a_n^*),\qquad +d_{(a_1,\ldots,a_n)} = \prod_i d_{a_i}. +``` + +If a component category has multiple units, `allunits` returns the product of the component unit sets. ## Topological Data -### F-symbols +The topological data is the tensor product of the component data. +For multiplicity-free channels this reduces to ordinary multiplication: + +```math +F_{\boxtimes_i a_i,\boxtimes_i b_i,\boxtimes_i c_i}^{\boxtimes_i d_i} += \prod_i F_{a_i b_i c_i}^{d_i}, +\qquad +R_{\boxtimes_i a_i,\boxtimes_i b_i}^{\boxtimes_i c_i} += \prod_i R_{a_i b_i}^{c_i}. +``` + +When multiplicity spaces are present, the implementation forms the corresponding Kronecker products so that the product multiplicity basis is ordered componentwise. +The same convention is used for `Fsymbol`, `Rsymbol`, `Asymbol`, `Bsymbol`, and `fusiontensor`. -### R-symbols +Braiding style and scalar types are combined from the component categories. -### Braiding Style +For products containing [`FermionParity`](@ref), `fermionparity` is the XOR of the component parities. -## Code Examples +## Iteration -## Implementation Notes +`values(I1 ⊠ I2)` iterates over the Cartesian product of `values(I1)` and `values(I2)`. +Indexing and `findindex` use the same componentwise ordering. +For infinite component sectors, the product iterator can also be infinite. -### Type Parameters +## References -### Deligne Tensor Product +- [Deligne tensor product](https://ncatlab.org/nlab/show/Deligne+tensor+product) \ No newline at end of file diff --git a/docs/src/sectors/composite/timereversed.md b/docs/src/sectors/composite/timereversed.md index 4516934e..769c0dcd 100644 --- a/docs/src/sectors/composite/timereversed.md +++ b/docs/src/sectors/composite/timereversed.md @@ -1,29 +1,70 @@ -# Time-Reversed Sectors: TimeReversed +# Time-Reversed Sectors: `TimeReversed` -## Type Definition +`TimeReversed{I}` represents the time-reversed, or conjugate-braided, version of a sector type `I`. +It keeps the same objects, fusion rules, dimensions, and associators, but reverses the braiding. -## Construction +## Sector type -## Labels +```@docs; canonical = false +TimeReversed +timereversed +``` -## Physical Interpretation +Construct a wrapped sector with `TimeReversed(a)` or `TimeReversed{I}(a)`. +The helper `timereversed(a)` avoids unnecessary wrappers for symmetric braiding categories and unwraps an already time-reversed sector: -## Braiding Reversal +```julia +using TensorKitSectors + +a = IsingAnyon(:σ) +timereversed(a) # TimeReversed{IsingAnyon}(:σ) +timereversed(timereversed(a)) # IsingAnyon(:σ) +``` + +`TimeReversed` is not defined for sectors with `NoBraiding()`. ## Fusion Rules -## Quantum Dimensions +Fusion is inherited from the original sector type. +The fusion multiplicities, fusion style, units, duals, and quantum dimensions are unchanged: + +```math +N_{\overline{c}}^{\overline{a}\,\overline{b}} = N_c^{ab},\qquad +d_{\overline{a}} = d_a,\qquad +\overline{a}^{\,*} = \overline{a^*}. +``` + +`values(TimeReversed{I})` follows the same order as `values(I)`, with every element wrapped. ## Topological Data -### F-symbols +The [`Fsymbol`](@ref), [`Asymbol`](@ref), and [`Bsymbol`](@ref) are inherited directly from the original sector. +The [`Rsymbol`](@ref) is adjointed: + +```math +R_{\overline{c}}^{\overline{a}\,\overline{b}} += \left(R_c^{ab}\right)^\dagger. +``` + +For scalar braiding phases this is complex conjugation, so anyonic spins change sign: + +```math +\theta_{\overline{a}} = \overline{\theta_a}. +``` + +For example, in the conventions of this package, -### R-symbols +```math +\theta_\sigma = e^{\pi i/8} +\quad\Longrightarrow\quad +\theta_{\overline{\sigma}} = e^{-\pi i/8} +``` -### Braiding Style +for the Ising `σ` anyon. -## Code Examples +The braiding style and scalar types are reported as those of the original sector type. +For bosonic or fermionic symmetric categories, time reversal is physically trivial; `timereversed(a)` therefore returns `a` directly. -## Implementation Notes +## References -### Anti-unitary Symmetries +- [Time reversal symmetry](https://en.wikipedia.org/wiki/T-symmetry) \ No newline at end of file From cacb0397abd05b68e3eeedbaf5295e9f353e72ca Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 2 Jun 2026 15:22:28 +0200 Subject: [PATCH 19/50] jldoctest block fix --- docs/src/sectors/nonabelian/a4.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/sectors/nonabelian/a4.md b/docs/src/sectors/nonabelian/a4.md index b19e56ba..9340a6c9 100644 --- a/docs/src/sectors/nonabelian/a4.md +++ b/docs/src/sectors/nonabelian/a4.md @@ -127,6 +127,8 @@ for mu in 1:Nsymbol(a, b, c) @test Cmat' * kron(T(a), T(b)) * Cmat ≈ T(c) @test Cmat' * kron(S(a), S(b)) * Cmat ≈ S(c) end + +# output ``` ## References From ef2e2253c79cee8774d0d6fc2f01e0828cec3505 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 6 Jul 2026 12:21:17 +0200 Subject: [PATCH 20/50] add heisenbergirrep --- docs/src/sectors/nonabelian/heisenberg.md | 128 ++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 docs/src/sectors/nonabelian/heisenberg.md diff --git a/docs/src/sectors/nonabelian/heisenberg.md b/docs/src/sectors/nonabelian/heisenberg.md new file mode 100644 index 00000000..cc6bbec9 --- /dev/null +++ b/docs/src/sectors/nonabelian/heisenberg.md @@ -0,0 +1,128 @@ +# Representation of the finite Heisenberg Group ``H_N``: `HeisenbergIrrep{N}` + +`HeisenbergIrrep{N}` represents irreducible representations (irreps) of the finite Heisenberg group ``H_N`` as a `Sector`. +``H_N`` is the group of ``3\times 3`` upper triangular matrices which is identified with the group ``\mathbb{Z}_N \rtimes \mathbb{Z}_N^2``; it is only defined here for prime `N`. +This page documents how the type behaves in code (construction, iteration, fusion, and access to topological data). + +## Sector type + +```@docs; canonical = false +HeisenbergIrrep +``` + +Every irrep is labeled by a single integer `n::Int8`, but the meaning of `n` depends on its sign: + +- If `0 <= n < N^2`, the irrep is the one-dimensional character ``\chi_{a,b}`` with `a, b = divrem(n, N)`. + There are ``N^2`` such characters, one for each pair `(a, b) ∈ 0:N-1`. +- If `-N < n < 0`, the irrep is the ``N``-dimensional Schrödinger representation ``\pi_k`` with `k = -n`, `k ∈ 1:N-1`. + +In total there are ``N^2 + N - 1`` irreps (the trivial ``k = 0`` Schrödinger representation is excluded, since it is reducible and decomposes into the ``N^2`` characters). +The alias `Heis3Irrep = HeisenbergIrrep{3}` is provided for the smallest (and most commonly used) case. + +The trivial sector is `HeisenbergIrrep{N}(0)`, i.e. ``\chi_{0,0}``. +Duals are + +```math +\chi_{a,b}^* = \chi_{-a \bmod N,\,-b \bmod N}, \qquad \pi_k^* = \pi_{N-k}. +``` + +## Fusion Rules + +Characters fuse among themselves as the abelian group ``\mathbb{Z}_N \times \mathbb{Z}_N``: + +```math +\chi_{a,b} \otimes \chi_{a',b'} = \chi_{(a+a')\bmod N,\,(b+b')\bmod N}. +``` + +Fusing a character with a Schrödinger irrep leaves the latter unchanged, regardless of the character's labels: + +```math +\chi_{a,b} \otimes \pi_k = \pi_k \otimes \chi_{a,b} = \pi_k. +``` + +This reflects that ``\pi_k`` is the unique irrep with a given nontrivial central character, so twisting it by any character of the full group produces an isomorphic representation. + +Two Schrödinger irreps fuse according to whether their labels cancel modulo `N`: + +```math +\pi_k \otimes \pi_{k'} = +\begin{cases} +N \cdot \pi_{(k+k') \bmod N}, & k + k' \not\equiv 0 \pmod N, \\[4pt] +\displaystyle\bigoplus_{a,b=0}^{N-1} \chi_{a,b}, & k + k' \equiv 0 \pmod N. +\end{cases} +``` + +In the first case the ``N``-fold multiplicity accounts for the dimension count ``N \times N = N \times N`` (``N`` copies of the ``N``-dimensional ``\pi_{(k+k')\bmod N}``); in the second, the ``N^2``-dimensional product decomposes into all ``N^2`` one-dimensional characters, each with multiplicity one. + +Because of this multiplicity-``N`` channel, `FusionStyle(HeisenbergIrrep) = GenericFusion()`. +The [`Nsymbol`](@ref) returns the corresponding integer multiplicities directly from the case distinction above. + +Quantum dimensions are the ordinary representation space dimensions: + +```math +d_{\chi_{a,b}} = 1, \qquad d_{\pi_k} = N. +``` + +## Topological Data + +`BraidingStyle(HeisenbergIrrep) = Bosonic()`: braiding is symmetric, and `braidingscalartype(HeisenbergIrrep) = ComplexF64` since the Clebsch-Gordan coefficients are generally complex. + +The [`Fsymbol`](@ref) and [`Rsymbol`](@ref) are both computed generically from the chosen [`fusiontensor`](@ref) basis (via `Fsymbol_from_fusiontensor` and `Rsymbol_from_fusiontensor`), see below. +On the single-channel sectors (``\chi \otimes \chi \to \chi`` and ``\chi \otimes \pi \to \pi``) the R-symbol evaluates to the trivial phase `1`. +On the multiplicity-``N`` channel ``\pi_k \otimes \pi_{k'} \to \pi_{(k+k')\bmod N}`` and on the channels ``\pi_k \otimes \pi_{-k} \to \chi_{a,b}``, the R-symbol carries nontrivial phases built out of `N`-th roots of unity. + +## Fusion Tensor and Basis Conventions + +`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. +The one-dimensional (character) fusion tensors are trivial scalars. +For the Schrödinger irreps, the fusion tensor is built out of the ``N``-th root of unity ``\omega = e^{2\pi i/N}``, following the reference below: + +- ``\pi_k \otimes \pi_{k'} \to \pi_{(k+k')\bmod N}`` (``k+k' \not\equiv 0``): a permutation tensor (with a phase for the case where one of the factors is a character, see below). +- ``\pi_k \otimes \pi_{-k} \to \chi_{a,b}``: normalized with a factor ``1/\sqrt{N}``, with phase ``\omega^{-a i}`` along the surviving diagonal. +- ``\chi_{a,b} \otimes \pi_k \to \pi_k`` (and the symmetric ``\pi_k \otimes \chi_{a,b} \to \pi_k``): a permutation tensor dressed with the phase ``\omega^{a m}``. + +The representation can be checked against the generators `X` and `Z` of ``H_N`` acting as ``X|i\rangle = |i+1\rangle`` and ``Z|i\rangle = \omega^{ki}|i\rangle`` on ``\pi_k``, and as ``X \mapsto \omega^a``, ``Z \mapsto \omega^b`` on ``\chi_{a,b}``. +For every allowed fusion channel, the fusion tensor acts as an intertwiner between the tensor product representation and the fused representation: + +```jldoctest heisenberg_intertwiner; output = false +using TensorKitSectors +using LinearAlgebra: kron, Diagonal +using Test: @test + +N = 3 +ω = cispi(2 / N) + +function X(s::HeisenbergIrrep{N}) where {N} + s.n < 0 || return hcat(ω^div(s.n, N)) + M = zeros(ComplexF64, N, N) + for i in 0:(N - 1) + M[mod(i + 1, N) + 1, i + 1] = 1 + end + return M +end +Z(s::HeisenbergIrrep{N}) where {N} = s.n < 0 ? Diagonal([ω^(-s.n * i) for i in 0:(N - 1)]) : hcat(ω^mod(s.n, N)) + +for a in values(HeisenbergIrrep{N}), b in values(HeisenbergIrrep{N}) + for c in a ⊗ b + C = fusiontensor(a, b, c) + for μ in 1:Nsymbol(a, b, c) + Cmat = reshape(view(C, :, :, :, μ), dim(a) * dim(b), dim(c)) + @test Cmat' * kron(X(b), X(a)) * Cmat ≈ X(c) + @test Cmat' * kron(Z(b), Z(a)) * Cmat ≈ Z(c) + end + end +end + +# output +``` + +## Iteration + +Iterating over `values(HeisenbergIrrep{N})` first yields the ``N^2`` characters ``\chi_{0,0}, \chi_{0,1}, \ldots`` (in order of increasing `n`), followed by the Schrödinger irreps ``\pi_1, \ldots, \pi_{N-1}``. + +## References + +For background on the group and the representation basis, see: + +- [Heisenberg group](https://en.wikipedia.org/wiki/Heisenberg_group#Heisenberg_group_modulo_an_odd_prime_p) +- [Bacon, D., How a Clebsch-Gordan Transform Helps to Solve the Heisenberg Hidden Subgroup Problem](https://arxiv.org/abs/quant-ph/0612107) From d8dc9c110595b6806eadf2a29df6e0dd1036b769 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 6 Jul 2026 14:02:12 +0200 Subject: [PATCH 21/50] znelement --- docs/src/sectors/groupelement/znelement.md | 104 +++++++++++++++++++++ src/groupelements.jl | 2 +- 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 docs/src/sectors/groupelement/znelement.md diff --git a/docs/src/sectors/groupelement/znelement.md b/docs/src/sectors/groupelement/znelement.md new file mode 100644 index 00000000..b4e9aa24 --- /dev/null +++ b/docs/src/sectors/groupelement/znelement.md @@ -0,0 +1,104 @@ +# Cyclic Group Elements: `ZNElement{N,p}` + +`ZNElement{N,p}` represents the elements of the cyclic group ``\mathbb{Z}_N`` directly as a `Sector`, as opposed to [`ZNIrrep`](@ref) which represents its (one-dimensional) irreps. +Fusion is given by the group multiplication itself, and the associator can carry a nontrivial phase determined by a level-`p` 3-cocycle on ``\mathbb{Z}_N``. +For special values of `p` this also yields a consistent braiding, turning `ZNElement{N,p}` into a simple model of abelian anyons. +As a fusion category, this is identified with ``\text{Vec}_{\mathbb{Z}_N}^{\omega_p}``, the category of ``\mathbb{Z}_N``-graded vector spaces with associator the 3-cocycle ``\omega_p``. + +## Group elements as sectors + +```@docs; canonical = false +AbstractGroupElement +``` + +`ZNElement{N,p}` is currently the only concrete subtype of `AbstractGroupElement{Group}`. Any concrete `G <: AbstractGroupElement{Group}` only needs to implement `Base.:*`, `Base.one`, `Base.inv`, and optionally `TensorKitSectors.cocycle`; the fusion category structure (`⊗`, `dual`, `unit`, `Nsymbol`, `Fsymbol`, `dim`, `Asymbol`, `Bsymbol`, `frobenius_schur_phase`) follows automatically. +`FusionStyle(AbstractGroupElement) = UniqueFusion()` always, and `BraidingStyle(AbstractGroupElement) = NoBraiding()` by default, though a concrete type is free to override this (as `ZNElement` does, see below). +If no `cocycle` method is defined, it defaults to the trivial one. + +## Sector type + +```@docs; canonical = false +ZNElement +``` + +Elements are labeled by a single integer `n`, stored as `Int8` and only meaningful modulo `N` (which must satisfy `N < 64`). +The concrete type is obtained through `GroupElement[ℤ{N}, p]`, or through the aliases `Z2Element{p}`, `Z3Element{p}`, and `Z4Element{p}` for `N = 2, 3, 4`. +If `p` is omitted, it defaults to `0`, i.e. the trivial cocycle. + +The unit is `ZNElement{N,p}(0)`, and duals are given by group inversion: + +```math +a^* = a^{-1} = -a \bmod N. +``` + +## Fusion Rules + +Fusion is literally the group operation, so there is a single fusion channel with multiplicity one: + +```math +a \otimes b = (a + b) \bmod N, +``` + +and `FusionStyle(ZNElement{N,p}) = UniqueFusion()` for every `N` and `p`. +All quantum dimensions are `1`. + +## Associativity: the 3-cocycle and F-symbol + +The [`Fsymbol`](@ref) is not assumed trivial: it is given by the 3-cocycle + +```math +\omega_p(a,b,c) = \exp\left(\frac{2\pi i\, p\, a\,\big(b + c - [b+c]_N\big)}{N^2}\right), \qquad [x]_N := x \bmod N, +``` + +which is a representative of a class in ``H^3(\mathbb{Z}_N, U(1)) \cong \mathbb{Z}_N``, indexed by the level `p ∈ 0:N-1`. +Concretely, + +```math +F^{abc}_{e,d,f} = \omega_p(a,b,c) \quad \text{when } e = a+b,\ d = e+c,\ f = b + c \pmod N, +``` + +and zero otherwise (since fusion is unique, all the other symbols such as [`Asymbol`](@ref), [`Bsymbol`](@ref) and `frobenius_schur_phase` are likewise built directly out of `ω_p`). +For `p = 0` the cocycle is trivial and `ZNElement{N,0}` reduces to the ordinary ``\mathbb{Z}_N``-graded vector spaces. +The [`pentagon_equation`](@ref) holds for every `N` and every `p ∈ 0:N-1`, i.e. every `ZNElement{N,p}` is a consistent fusion category. + +## Topological Data (Braiding) + +Braiding is only defined in two cases: + +- `p = 0`: `BraidingStyle(ZNElement{N,0}) = Bosonic()`, and the [`Rsymbol`](@ref) is trivial (`Rsymbol(a,b,c) = Nsymbol(a,b,c)`). +- `2p ≡ N`: `BraidingStyle(ZNElement{N,p}) = Anyonic()`, and + + ```math + R^{ab}_{a+b} = \exp\left(\frac{2\pi i\, p\, a\, b}{N^2}\right), + ``` + + giving abelian braiding statistics for the ``\mathbb{Z}_N`` charges (e.g. `N = 4, p = 2` reproduces semion-like statistics). + +For any other value of `p`, `BraidingStyle(ZNElement{N,p}) = NoBraiding()`. + +## Iteration + +`values(ZNElement{N,p})` iterates the labels `0, 1, …, N-1` in increasing order, exactly as for [`ZNIrrep`](@ref). + +## Examples + +```jldoctest znelement_consistency +using TensorKitSectors + +a, b = Z3Element(1), Z3Element(2) +only(a ⊗ b) == unit(typeof(a)) + +# output +``` + +```jldoctest znelement_consistency +I = Z4Element{2} # 2p == N, so this admits a braiding +BraidingStyle(I) + +# output +``` + +## References + +- [Cyclic group](https://en.wikipedia.org/wiki/Cyclic_group) +- [Group cohomology](https://en.wikipedia.org/wiki/Group_cohomology) \ No newline at end of file diff --git a/src/groupelements.jl b/src/groupelements.jl index 2657b01d..a9614e0b 100644 --- a/src/groupelements.jl +++ b/src/groupelements.jl @@ -100,7 +100,7 @@ to the constructor, but only the value `mod(n, N)` is relevant. The second type is then being given by ```julia -cocycle(a, b, c) = cispi(2 * p * a.n * (b.n + c.n - mod(b.n + c.n, N)) / N)) +cocycle(a, b, c) = cispi(2 * p * a.n * (b.n + c.n - mod(b.n + c.n, N)) / N^2)) ``` If `p` is not specified, it defaults to `0`, i.e. the trivial cocycle. From 96c55e131dfc00ab8da53c5d5846bd72cd282609 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 6 Jul 2026 14:04:30 +0200 Subject: [PATCH 22/50] give love to `deligneproduct` --- docs/src/sectors/composite/product.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/src/sectors/composite/product.md b/docs/src/sectors/composite/product.md index 05f0efae..c90c5ae3 100644 --- a/docs/src/sectors/composite/product.md +++ b/docs/src/sectors/composite/product.md @@ -8,15 +8,18 @@ It is the standard way to combine independent symmetry or anyon labels, such as ```@docs; canonical = false ProductSector ⊠ +deligneproduct ``` A product sector stores its component sectors in a tuple. -The recommended constructor is the Deligne product operator `⊠` or `boxtimes`: +The recommended constructor is the Deligne product operator `⊠` or `boxtimes`. +The more verbose option is `deligneproduct`: ```julia using TensorKitSectors a = Z2Irrep(1) ⊠ FibonacciAnyon(:τ) # (Irrep[ℤ₂](1) ⊠ FibonacciAnyon(:τ)) +deligneproduct(Z2Irrep(1), FibonacciAnyon(:τ)) # same as above ``` The same operator works on sector types: From 738358414b3f978131fedcab289bd91347ed7715 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 6 Jul 2026 14:26:48 +0200 Subject: [PATCH 23/50] update summary table + add new pages --- docs/make.jl | 4 ++++ docs/src/sectors.md | 41 +++++++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index af258e46..9e95d1df 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -38,6 +38,7 @@ makedocs(; "CU₁" => "sectors/nonabelian/cu1.md", "Dₙ (Dihedral)" => "sectors/nonabelian/dn.md", "A₄ (Alternating)" => "sectors/nonabelian/a4.md", + "Heisenberg" => "sectors/nonabelian/heisenberg.md", ], "Anyonic Sectors" => [ "PlanarTrivial" => "sectors/anyons/planartrivial.md", @@ -49,6 +50,9 @@ makedocs(; "Fermion Number" => "sectors/fermions/number.md", "Fermion Spin" => "sectors/fermions/spin.md", ], + "Group Sectors" => [ + "ℤₙ (Cyclic)" => "sectors/groupelement/znelement.md", + ], "Composite Sectors" => [ "Product" => "sectors/composite/product.md", "Time-Reversed" => "sectors/composite/timereversed.md", diff --git a/docs/src/sectors.md b/docs/src/sectors.md index d13bfa17..6e0bdfc8 100644 --- a/docs/src/sectors.md +++ b/docs/src/sectors.md @@ -4,19 +4,28 @@ This page provides an overview of the concrete sector types implemented in Tenso ## Summary Table -| Sector Type | Group/Category | Fusion Style | Braiding | Infinite? | Common Use Cases | -|--------------------------|--------------------------|--------------|-----------|-----------|---------------------------------------| -| [`Trivial`](@ref) | Trivial group | Unique | Bosonic | No | No symmetry | -| [`ZNIrrep`](@ref) | ℤₙ (cyclic) | Unique | Bosonic | No | Clock models, discrete symmetries | -| [`U1Irrep`](@ref) | U(1) | Unique | Bosonic | Yes | Particle number, charge conservation | -| [`SU2Irrep`](@ref) | SU(2) | Simple | Bosonic | Yes | Spin systems, angular momentum | -| [`CU1Irrep`](@ref) | U(1) ⋊ ℤ₂ | Simple | Bosonic | Yes | Particle-hole symmetry, O(2) | -| [`DNIrrep`](@ref) | Dₙ (dihedral) | Simple | Bosonic | No | Molecular/crystal symmetries | -| [`A4Irrep`](@ref) | A₄ (alternating) | Generic | Bosonic | No | Tetrahedral symmetry | -| [`FibonacciAnyon`](@ref) | Fibonacci category | Simple | Anyonic | No | Topological quantum computing | -| [`IsingAnyon`](@ref) | Ising category | Simple | Anyonic | No | Majorana fermions, ν=5/2 QHE | -| [`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 | -| [`ProductSector`](@ref) | Product categories | Varies | Varies | Varies | Multiple simultaneous symmetries | -| [`TimeReversed`](@ref) | Inverted braiding | Varies | Varies | Varies | ?? | +| Sector Type | Group/Category | Fusion Style | Braiding | Infinite? | Common Use Cases | +|--------------------------|--------------------------------|--------------|-----------|-----------|-------------------------------------------------------------| +| [`Trivial`](@ref) | Trivial group | Unique | Bosonic | No | No symmetry | +| [`ZNIrrep`](@ref) | Rep(ℤₙ) | Unique | Bosonic | No | Clock models, discrete symmetries | +| [`ZNElement`](@ref) | Vec[ℤₙ] | Unique | Varies | No | Group-graded categories, discrete torsion | +| [`U1Irrep`](@ref) | Rep[U₁] | Unique | Bosonic | Yes | Particle number, charge conservation | +| [`SU2Irrep`](@ref) | Rep[SU₂] | Simple | Bosonic | Yes | Spin systems, angular momentum | +| [`CU1Irrep`](@ref) | Rep[U₁ ⋊ ℤ₂] | Simple | Bosonic | Yes | Particle-hole symmetry, O(2) | +| [`DNIrrep`](@ref) | Rep[Dₙ] | Simple | Bosonic | No | Molecular/crystal symmetries | +| [`A4Irrep`](@ref) | Rep[A₄] | Generic | Bosonic | No | Tetrahedral symmetry | +| [`HeisenbergIrrep`](@ref)| Rep[H_N] | Generic | Anyonic | No | Chern-Simons theory, quantum computing | +| [`FibonacciAnyon`](@ref) | Fibonacci category | Simple | Anyonic | No | Topological quantum computing | +| [`IsingAnyon`](@ref) | Ising category | Simple | Anyonic | No | Majorana fermions, ν=5/2 QHE | +| [`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 | +| [`ProductSector`](@ref) | Product categories | Varies | Varies | Varies | Multiple simultaneous symmetries | +| [`TimeReversed`](@ref) | Inverted braiding | Varies | Varies | Varies | Time-reversal or other orientation-reversing symmetries | + +## Other packages + +TensorKitSectors.jl provides the architecture for implementing new sector types, but does not implement all possible sectors. Other packages which implement additional sector types and their topological data include: +- [`SUNRepresentations.jl`](https://github.com/QuantumKitHub/SUNRepresentations.jl): Implements irreducible representations of SU(N) for arbitrary N +- [`CategoryData.jl`](https://github.com/QuantumKitHub/CategoryData.jl): Provides a variety of fusion categories up to rank 7, based on the [`AnyonWiki`](https://anyonwiki.github.io/) +- [`QWignerSymbols.jl`](https://github.com/QuantumKitHub/QWignerSymbols.jl): Provides the irreps of q-deformed SU(2) From c6b6434e8b993a3ea1efa8dfc31c5291da6365a7 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 6 Jul 2026 14:33:08 +0200 Subject: [PATCH 24/50] same same but different --- docs/src/sectors/groupelement/znelement.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/src/sectors/groupelement/znelement.md b/docs/src/sectors/groupelement/znelement.md index b4e9aa24..ff268b82 100644 --- a/docs/src/sectors/groupelement/znelement.md +++ b/docs/src/sectors/groupelement/znelement.md @@ -89,6 +89,7 @@ a, b = Z3Element(1), Z3Element(2) only(a ⊗ b) == unit(typeof(a)) # output +true ``` ```jldoctest znelement_consistency @@ -96,6 +97,7 @@ I = Z4Element{2} # 2p == N, so this admits a braiding BraidingStyle(I) # output +Anyonic() ``` ## References From 01aa7b81b30f0e6d827cf81e76011e04f5d70873 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:51:28 -0400 Subject: [PATCH 25/50] docs: fix SU2Irrep F-symbol formula (d/e were swapped) The displayed F-symbol had j_d and j_e interchanged in both the phase exponent and the 6j symbol, making it numerically wrong for generic inputs. Match src/irreps/su2irrep.jl, which computes sqrt(d_e d_f) * racahW(a,b,d,c,e,f). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/nonabelian/su2.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/sectors/nonabelian/su2.md b/docs/src/sectors/nonabelian/su2.md index 1eea2341..07d0f45f 100644 --- a/docs/src/sectors/nonabelian/su2.md +++ b/docs/src/sectors/nonabelian/su2.md @@ -29,9 +29,9 @@ Each irrep has dimension ``d = 2j + 1``. The [`Fsymbol`](@ref) is computed from [Wigner ``6j``](https://en.wikipedia.org/wiki/6-j_symbol) (Racah-``W``) symbols as ```math -\left(F_{abc}^d\right)_e^f = (-1)^{j_a + j_b + j_c + j_e} \sqrt{d_e d_f} \begin{Bmatrix} -j_a & j_b & j_d \\ -j_c & j_e & j_f +\left(F_{abc}^d\right)_e^f = (-1)^{j_a + j_b + j_c + j_d} \sqrt{d_e d_f} \begin{Bmatrix} +j_a & j_b & j_e \\ +j_c & j_d & j_f \end{Bmatrix} ``` From 8fc22b093c6c193c83a22482a6ee67fd8cfd2801 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:51:57 -0400 Subject: [PATCH 26/50] docs: fix HeisenbergIrrep braiding in summary table (Anyonic -> Bosonic) src/irreps/heisenbergirrep.jl:26 defines BraidingStyle = Bosonic(), and the HeisenbergIrrep page itself says Bosonic; only the summary table was wrong. Also reword the use-case blurb, which implied anyonic behavior. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/sectors.md b/docs/src/sectors.md index 6e0bdfc8..b50e4508 100644 --- a/docs/src/sectors.md +++ b/docs/src/sectors.md @@ -14,7 +14,7 @@ This page provides an overview of the concrete sector types implemented in Tenso | [`CU1Irrep`](@ref) | Rep[U₁ ⋊ ℤ₂] | Simple | Bosonic | Yes | Particle-hole symmetry, O(2) | | [`DNIrrep`](@ref) | Rep[Dₙ] | Simple | Bosonic | No | Molecular/crystal symmetries | | [`A4Irrep`](@ref) | Rep[A₄] | Generic | Bosonic | No | Tetrahedral symmetry | -| [`HeisenbergIrrep`](@ref)| Rep[H_N] | Generic | Anyonic | No | Chern-Simons theory, quantum computing | +| [`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 | | [`FermionParity`](@ref) | fℤ₂ | Unique | Fermionic | No | Fermion parity conservation | From b2428dde39fcd9209b6ff796b15d6560c3b62866 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:52:09 -0400 Subject: [PATCH 27/50] docs: conjugate F-symbol in A-symbol formula Asymbol_from_Fsymbol (src/sectors.jl:575-578) computes conj(kappa_a * Fsymbol(...)), i.e. the F-symbol is conjugated too. The documented formula only conjugated kappa_a, which is wrong for complex (anyonic) topological data (identical for real data such as SU(2)/Zn). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/interface/optional.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/interface/optional.md b/docs/src/interface/optional.md index 124b9ae3..6d4dd11a 100644 --- a/docs/src/interface/optional.md +++ b/docs/src/interface/optional.md @@ -63,7 +63,7 @@ The A-symbol and B-symbol relate different ways of bending strands, while the tw The A-symbol ``A^{ab}_c`` relates splitting and fusion vertices: ```math -A^{ab}_c = \sqrt{\frac{d_a d_b}{d_c}} \overline{\kappa_a} (F_{\bar{a} a b}^b)^1_c +A^{ab}_c = \sqrt{\frac{d_a d_b}{d_c}} \, \overline{\kappa_a (F_{\bar{a} a b}^b)^1_c} ``` The B-symbol ``B^{ab}_c`` relates splitting and fusion vertices: From ec8d48c5c24f2b62a4827511afa34c2b79e40bb3 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:52:24 -0400 Subject: [PATCH 28/50] docs: drop non-existent 'boxtimes' from ProductSector page There is no boxtimes function/alias; the name only appears inside the otimes docstring as the LaTeX input hint. Only the operator (typed \boxtimes) and the deligneproduct alias are callable. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/composite/product.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/sectors/composite/product.md b/docs/src/sectors/composite/product.md index c90c5ae3..8c0581c4 100644 --- a/docs/src/sectors/composite/product.md +++ b/docs/src/sectors/composite/product.md @@ -12,8 +12,8 @@ deligneproduct ``` A product sector stores its component sectors in a tuple. -The recommended constructor is the Deligne product operator `⊠` or `boxtimes`. -The more verbose option is `deligneproduct`: +The recommended constructor is the Deligne product operator `⊠` (typed as `\boxtimes`). +The more verbose alias `deligneproduct` is also available: ```julia using TensorKitSectors From a9f924f5a008d14530a94e4c19b0e793c0be57c4 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:52:48 -0400 Subject: [PATCH 29/50] docs: fix imprecise 'semion-like' claim for ZNElement N=4,p=2 N=4,p=2 gives topological spins theta_a = exp(i*pi*a^2/4), which is not the canonical semion (that is N=2,p=1 with theta=i). State the actual spins instead. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/groupelement/znelement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/sectors/groupelement/znelement.md b/docs/src/sectors/groupelement/znelement.md index ff268b82..2b6aa8b7 100644 --- a/docs/src/sectors/groupelement/znelement.md +++ b/docs/src/sectors/groupelement/znelement.md @@ -72,7 +72,7 @@ Braiding is only defined in two cases: R^{ab}_{a+b} = \exp\left(\frac{2\pi i\, p\, a\, b}{N^2}\right), ``` - giving abelian braiding statistics for the ``\mathbb{Z}_N`` charges (e.g. `N = 4, p = 2` reproduces semion-like statistics). + giving abelian anyonic braiding statistics for the ``\mathbb{Z}_N`` charges. For example, `N = 4, p = 2` (used in the example below) yields topological spins ``\theta_a = \exp(i\pi a^2 / 4)``. For any other value of `p`, `BraidingStyle(ZNElement{N,p}) = NoBraiding()`. From 9630336420d30294f3d94da61580ba0ed487b0c8 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:53:03 -0400 Subject: [PATCH 30/50] docs: clarify only length is required for HasLength sectors getindex and findindex have working generic fallbacks (src/sectors.jl:77-103) and are only recommended for performance; they are not strictly required. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/interface/required.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/src/interface/required.md b/docs/src/interface/required.md index 7a427c75..6678af23 100644 --- a/docs/src/interface/required.md +++ b/docs/src/interface/required.md @@ -22,11 +22,12 @@ In particular, we require the following methods to be defined: - `Base.IteratorSize(::Type{SectorValues{I}})` — Specify whether the number of sector values is known, finite, or infinite. Here the `IteratorSize` is either `HasLength()`, `SizeUnknown()` or `IsInfinite()`. -If the length is known (`HasLength()`), three further methods are required so that sectors can be indexed by position: +If the length is known (`HasLength()`), sectors can be indexed by position. +This requires `Base.length`, while `Base.getindex` and `findindex` have generic fallbacks that are typically overridden for performance: -- `Base.length(::SectorValues{I})` — Return the number of sectors. -- `Base.getindex(::SectorValues{I}, i::Int)` — Access the `i`-th sector value. -- `findindex(::SectorValues{I}, c::I)` — Find the index of sector `c`. +- `Base.length(::SectorValues{I})` — Return the number of sectors. **(required for `HasLength()`)** +- `Base.getindex(::SectorValues{I}, i::Int)` — Access the `i`-th sector value. A fallback linearly iterates the values. +- `findindex(::SectorValues{I}, c::I)` — Find the index of sector `c`. A fallback linearly searches the values. !!! note The choice of `IteratorSize` determines how associative containers are constructed in e.g. a `GradedSpace`. From 0eb5267830976611f907eca892b357682db82d38 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:53:13 -0400 Subject: [PATCH 31/50] docs: drop misleading 'by default' from values(I) description Base.values(::Type{I}) = SectorValues{I}() is defined unconditionally (src/sectors.jl:75), not as an overridable default. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/interface/required.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/interface/required.md b/docs/src/interface/required.md index 6678af23..536b306e 100644 --- a/docs/src/interface/required.md +++ b/docs/src/interface/required.md @@ -13,7 +13,7 @@ A sector type `I <: Sector` represents the set of all labels that can be used to This corresponds to all irreducible representations of a group, or all simple objects in a fusion category. The first requirement is making this set **enumerable** through the iterator interface. -The set of all sector values is obtained via `values(I)`, which returns a `SectorValues{I}()` singleton type by default. +The set of all sector values is obtained via `values(I)`, which returns a `SectorValues{I}()` singleton. This `SectorValues{I}()` must be iterable, enabling enumeration of all sectors of type `I`. To do so, one needs to implement the [Iteration interface](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-iteration). In particular, we require the following methods to be defined: From 54ddb057f04ca55f5bf3e9c35bd3b735af14a8ec Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:53:32 -0400 Subject: [PATCH 32/50] docs: note fusiontensor has no default in optional-methods intro Unlike the other optional methods, fusiontensor has no default implementation; topological data is instead derived from it when supplied. Qualify the blanket intro sentence. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/interface/optional.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/src/interface/optional.md b/docs/src/interface/optional.md index 6d4dd11a..e52c5cce 100644 --- a/docs/src/interface/optional.md +++ b/docs/src/interface/optional.md @@ -4,7 +4,8 @@ CollapsedDocStrings = true # Optional Methods -The following methods have default implementations but can be overridden for performance or to provide additional functionality. +Most of the following methods have default implementations derived from the required methods, but can be overridden for performance or to provide additional functionality. +The exception is [`fusiontensor`](@ref), which has no default: it is genuinely optional and, when needed, must be supplied explicitly (see the Fusion Basis section below). ## Quantum Dimensions From 9faee015840346c8e344e9a9d7f6fb5e486fb7d7 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:53:55 -0400 Subject: [PATCH 33/50] docs: distinguish Frobenius-Schur phase from indicator The sign(F) formula gives the FS phase kappa_a; the indicator nu_a equals it only for self-dual sectors and is 0 otherwise. Clarify which quantity the formula and each descriptive sentence refer to. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/interface/optional.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/src/interface/optional.md b/docs/src/interface/optional.md index e52c5cce..f1b545d3 100644 --- a/docs/src/interface/optional.md +++ b/docs/src/interface/optional.md @@ -29,13 +29,14 @@ invsqrtdim ## Frobenius-Schur Indicators The Frobenius-Schur indicator and phase characterize the self-duality properties of sectors. +The Frobenius-Schur phase ``\kappa_a`` is obtained from the F-symbol as ```math \kappa_a = \text{sign}\left( (F_{a \bar{a} a}^a)^{1_a}_{_a1} \right) ``` -The indicator distinguishes real, complex, and quaternionic representations. -The phase is the category-theoretic version that appears in line bending operations. +and is the category-theoretic quantity that appears in line-bending operations. +The Frobenius-Schur indicator ``\nu_a`` coincides with ``\kappa_a`` for self-dual sectors (``a = \bar{a}``) and is ``0`` otherwise; it distinguishes real, complex, and quaternionic representations. ```@docs; canonical = false frobenius_schur_indicator From 24db58c8b741908895899d47a3e0194656433c08 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:54:20 -0400 Subject: [PATCH 34/50] docs: specify DNIrrep R-symbol sign applies to the (0,-) channel only Rsymbol (src/irreps/dnirrep.jl:193-195) flips sign only for the j==0 odd 1-D output (the (0,-) sector), not for the (N/2, odd) 1-D output. The previous 'odd one-dimensional output channels' was too broad. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/nonabelian/dn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/sectors/nonabelian/dn.md b/docs/src/sectors/nonabelian/dn.md index c11b6f58..fc582fc6 100644 --- a/docs/src/sectors/nonabelian/dn.md +++ b/docs/src/sectors/nonabelian/dn.md @@ -55,7 +55,7 @@ d_{(N/2,\pm)} = 1\quad (N \text{ even}). `DNIrrep{N}` is a bosonic representation category, so all twists are `1`. The [`Fsymbol`](@ref) is computed from the selected [`fusiontensor`](@ref) basis. -The [`Rsymbol`](@ref) is the N-symbol with a possible sign on odd one-dimensional output channels from two non-trivial two-dimensional inputs. +The [`Rsymbol`](@ref) equals the N-symbol, up to a sign of ``-1`` on the ``(0,-)`` odd one-dimensional output channel produced by fusing two two-dimensional irreps. ## Fusion tensor and basis conventions From bc77f1b3b1da77941bbd9e531f664495776656f3 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:54:36 -0400 Subject: [PATCH 35/50] docs: fix tautological dimension count in HeisenbergIrrep fusion 'N x N = N x N' should read 'N x N = N^2' (N copies of the N-dimensional pi). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/nonabelian/heisenberg.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/sectors/nonabelian/heisenberg.md b/docs/src/sectors/nonabelian/heisenberg.md index cc6bbec9..1fa8e249 100644 --- a/docs/src/sectors/nonabelian/heisenberg.md +++ b/docs/src/sectors/nonabelian/heisenberg.md @@ -52,7 +52,7 @@ N \cdot \pi_{(k+k') \bmod N}, & k + k' \not\equiv 0 \pmod N, \\[4pt] \end{cases} ``` -In the first case the ``N``-fold multiplicity accounts for the dimension count ``N \times N = N \times N`` (``N`` copies of the ``N``-dimensional ``\pi_{(k+k')\bmod N}``); in the second, the ``N^2``-dimensional product decomposes into all ``N^2`` one-dimensional characters, each with multiplicity one. +In the first case the ``N``-fold multiplicity accounts for the dimension count ``N \times N = N^2`` (``N`` copies of the ``N``-dimensional ``\pi_{(k+k')\bmod N}``); in the second, the ``N^2``-dimensional product decomposes into all ``N^2`` one-dimensional characters, each with multiplicity one. Because of this multiplicity-``N`` channel, `FusionStyle(HeisenbergIrrep) = GenericFusion()`. The [`Nsymbol`](@ref) returns the corresponding integer multiplicities directly from the case distinction above. From e698d614869722bb22eaccc3f029b2f19a72c453 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:54:52 -0400 Subject: [PATCH 36/50] docs: fix typo 'labels use to decompose' -> 'used to' Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/interface/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/interface/overview.md b/docs/src/interface/overview.md index 6c06cb3f..38cfac9b 100644 --- a/docs/src/interface/overview.md +++ b/docs/src/interface/overview.md @@ -3,7 +3,7 @@ ## Introduction A `Sector` is a label for the different *symmetry charges* or *quantum numbers* that organize graded vector spaces. -In particular, these are the labels use to decompose vector spaces as: +In particular, these are the labels used to decompose vector spaces as: ```math V = \bigoplus_{a \in \text{Sectors}} \mathbb{C}^{n_a} \otimes V_a From ac0b7cd3f2a7fddb3a0921de1ec4e0a709902582 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:55:02 -0400 Subject: [PATCH 37/50] docs: fix typo 'all twist' -> 'all twists' in ZNIrrep page Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/abelian/zn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/sectors/abelian/zn.md b/docs/src/sectors/abelian/zn.md index dd5805ca..e317f283 100644 --- a/docs/src/sectors/abelian/zn.md +++ b/docs/src/sectors/abelian/zn.md @@ -26,7 +26,7 @@ The category has `FusionStyle(ZNIrrep{N}) = UniqueFusion()`. ## Topological Data -All quantum dimensions are `1`, as well as all twist. +All quantum dimensions are `1`, as well as all twists. F-symbols, R-symbols and fusion tensors are trivial in allowed channels. The braiding style is `Bosonic()`. From e9185c1342d20c61c2a853da5b780f381dae0892 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:55:21 -0400 Subject: [PATCH 38/50] docs: normalize section-heading capitalization to Title Case 'Topological data' -> 'Topological Data' (parity, number) and 'Fusion tensor and basis conventions' -> Title Case (dn), matching the convention used by all other sector pages. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/fermions/number.md | 2 +- docs/src/sectors/fermions/parity.md | 2 +- docs/src/sectors/nonabelian/dn.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/sectors/fermions/number.md b/docs/src/sectors/fermions/number.md index 38a9c9a2..9056c073 100644 --- a/docs/src/sectors/fermions/number.md +++ b/docs/src/sectors/fermions/number.md @@ -28,7 +28,7 @@ n_1 \otimes n_2 = n_1 + n_2. The fermion parity component is then fixed automatically by the resulting charge. -## Topological data +## Topological Data All sectors have quantum dimension `1`. diff --git a/docs/src/sectors/fermions/parity.md b/docs/src/sectors/fermions/parity.md index 049cc0d2..9c9a69a3 100644 --- a/docs/src/sectors/fermions/parity.md +++ b/docs/src/sectors/fermions/parity.md @@ -23,7 +23,7 @@ p \otimes q = p \oplus q. The category has `FusionStyle(FermionParity) = UniqueFusion()`. -## Topological data +## Topological Data All quantum dimensions are `1`, and [`Fsymbol`](@ref) is trivial on allowed channels. diff --git a/docs/src/sectors/nonabelian/dn.md b/docs/src/sectors/nonabelian/dn.md index fc582fc6..3b125a32 100644 --- a/docs/src/sectors/nonabelian/dn.md +++ b/docs/src/sectors/nonabelian/dn.md @@ -57,7 +57,7 @@ d_{(N/2,\pm)} = 1\quad (N \text{ even}). The [`Fsymbol`](@ref) is computed from the selected [`fusiontensor`](@ref) basis. The [`Rsymbol`](@ref) equals the N-symbol, up to a sign of ``-1`` on the ``(0,-)`` odd one-dimensional output channel produced by fusing two two-dimensional irreps. -## Fusion tensor and basis conventions +## Fusion Tensor and Basis Conventions `fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. The implementation uses real Clebsch-Gordan coefficients. From 2835db1bd14e4ff6489b360d3db4bd1731374ae8 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:55:33 -0400 Subject: [PATCH 39/50] docs: use bracket notation Rep[Zn] in summary table for consistency Every other representation-category row uses Rep[...]; ZNIrrep was the only one with parentheses. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/sectors.md b/docs/src/sectors.md index b50e4508..084fc125 100644 --- a/docs/src/sectors.md +++ b/docs/src/sectors.md @@ -7,7 +7,7 @@ This page provides an overview of the concrete sector types implemented in Tenso | Sector Type | Group/Category | Fusion Style | Braiding | Infinite? | Common Use Cases | |--------------------------|--------------------------------|--------------|-----------|-----------|-------------------------------------------------------------| | [`Trivial`](@ref) | Trivial group | Unique | Bosonic | No | No symmetry | -| [`ZNIrrep`](@ref) | Rep(ℤₙ) | Unique | Bosonic | No | Clock models, discrete symmetries | +| [`ZNIrrep`](@ref) | Rep[ℤₙ] | Unique | Bosonic | No | Clock models, discrete symmetries | | [`ZNElement`](@ref) | Vec[ℤₙ] | Unique | Varies | No | Group-graded categories, discrete torsion | | [`U1Irrep`](@ref) | Rep[U₁] | Unique | Bosonic | Yes | Particle number, charge conservation | | [`SU2Irrep`](@ref) | Rep[SU₂] | Simple | Bosonic | Yes | Spin systems, angular momentum | From 4c822a6ca4070ae7b1e1ce3dca51e0d4fc3dde53 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:55:44 -0400 Subject: [PATCH 40/50] docs: rename nav category 'Group Sectors' -> 'Group Elements' 'Group Sectors' was ambiguous next to 'Abelian/Non-Abelian Groups' (which are also group-derived, via their irreps). This category holds group-element (Vec_G) sectors, so 'Group Elements' is clearer. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 9e95d1df..13968fbb 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -50,7 +50,7 @@ makedocs(; "Fermion Number" => "sectors/fermions/number.md", "Fermion Spin" => "sectors/fermions/spin.md", ], - "Group Sectors" => [ + "Group Elements" => [ "ℤₙ (Cyclic)" => "sectors/groupelement/znelement.md", ], "Composite Sectors" => [ From 236bfa9ac39b8b95b85a35c149064706a9df3a06 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:56:02 -0400 Subject: [PATCH 41/50] docs: cross-reference ZNElement from the ZNIrrep page The ZNElement page contrasts itself with ZNIrrep, but the link was one-directional. Add a note distinguishing Rep[Zn] (irreps) from Vec[Zn] (group elements) with a link to ZNElement. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/abelian/zn.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/sectors/abelian/zn.md b/docs/src/sectors/abelian/zn.md index e317f283..68cd3223 100644 --- a/docs/src/sectors/abelian/zn.md +++ b/docs/src/sectors/abelian/zn.md @@ -3,6 +3,10 @@ `ZNIrrep{N}` and `LargeZNIrrep{N}` represent irreducible representations of the cyclic group ``\mathbb{Z}_N``. Use `ZNIrrep{N}` when possible; it selects the compact storage type automatically. +!!! note + `ZNIrrep{N}` grades a space by the *irreps* of ``\mathbb{Z}_N`` (the `Rep[ℤₙ]` category). + To instead grade by the *group elements* of ``\mathbb{Z}_N`` (the `Vec[ℤₙ]` category, which also supports discrete torsion), see [`ZNElement`](@ref). + ## Sector types ```@docs; canonical = false From 33f2c83a61c63974d4f23e919f2da96c2ba070d4 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:56:21 -0400 Subject: [PATCH 42/50] docs: add install command and next-steps pointers to landing page The landing page had only 'Install via the package manager.' and no navigation cues. Add the Pkg add command and links into the Sector Interface and Sector Types sections. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/index.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/src/index.md b/docs/src/index.md index 60e387d1..460fbd9e 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -7,4 +7,15 @@ This includes the fusion rules, the associators, and the braiding. In particular, this is the data that is needed to define (symmetric) tensors, which are defined over vector spaces graded by these objects. For the full functionality, we refer to [TensorKit.jl](https://github.com/QuantumKitHub/TensorKit.jl) and [its documentation](https://quantumkithub.github.io/TensorKit.jl/stable/). -Install via the package manager. +## Installation + +Install via the package manager, by entering the Pkg REPL mode with `]` and running: + +```julia-repl +pkg> add TensorKitSectors +``` + +## Where to go next + +- **[Sector Interface](@ref)** — the methods a sector type must (and may) implement, and the traits that control its behavior. Start here to implement a new sector. +- **[Sector Types](@ref)** — the concrete sectors shipped with this package (groups, anyons, fermions, and composites), with a summary table and a page per type. From 6e850372d5b959fe66255d30087f261a8fa13513 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:57:30 -0400 Subject: [PATCH 43/50] docs: add NamedSector page, nav entry, and summary-table row NamedSector/@NamedSector are exported (src/named.jl) and are a first-class named-tuple counterpart to ProductSector, but had no conceptual page and no table row. Add a page under Composite Sectors mirroring the Product page, wire it into make.jl, and add a table row. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/make.jl | 1 + docs/src/sectors.md | 1 + docs/src/sectors/composite/named.md | 46 +++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 docs/src/sectors/composite/named.md diff --git a/docs/make.jl b/docs/make.jl index 13968fbb..6765daa3 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -55,6 +55,7 @@ makedocs(; ], "Composite Sectors" => [ "Product" => "sectors/composite/product.md", + "Named" => "sectors/composite/named.md", "Time-Reversed" => "sectors/composite/timereversed.md", ], ], diff --git a/docs/src/sectors.md b/docs/src/sectors.md index 084fc125..74648ea9 100644 --- a/docs/src/sectors.md +++ b/docs/src/sectors.md @@ -21,6 +21,7 @@ This page provides an overview of the concrete sector types implemented in Tenso | [`FermionNumber`](@ref) | fU₁ | Unique | Fermionic | Yes | Fermion number conservation | | [`FermionSpin`](@ref) | fSU₂ | Simple | Fermionic | Yes | Fermions with spin symmetry | | [`ProductSector`](@ref) | Product categories | Varies | Varies | Varies | Multiple simultaneous symmetries | +| [`NamedSector`](@ref) | Product categories | Varies | Varies | Varies | Product sectors with name-accessible components | | [`TimeReversed`](@ref) | Inverted braiding | Varies | Varies | Varies | Time-reversal or other orientation-reversing symmetries | ## Other packages diff --git a/docs/src/sectors/composite/named.md b/docs/src/sectors/composite/named.md new file mode 100644 index 00000000..584d4e43 --- /dev/null +++ b/docs/src/sectors/composite/named.md @@ -0,0 +1,46 @@ +# Named Sectors: `NamedSector` + +`NamedSector` represents the same Deligne tensor product as [`ProductSector`](@ref), but stores its component sectors in a *named* tuple so that they can be accessed by name rather than by position. +This is convenient when a product mixes several symmetries (e.g. a charge and a spin) and positional indexing would be error-prone. + +## Sector type + +```@docs; canonical = false +NamedSector +@NamedSector +``` + +A named sector is constructed with keyword arguments to `⊠`/`NamedSector`, or from a type built with the [`@NamedSector`](@ref) macro: + +```julia +using TensorKitSectors + +s = ⊠(; charge = U1Irrep(1), spin = SU2Irrep(1//2)) # (charge=1, spin=1/2) +s.charge # 1 +s.spin # 1/2 + +I = @NamedSector{charge::U1Irrep, spin::SU2Irrep} +I(U1Irrep(1), SU2Irrep(1//2)) # same as above +``` + +The components are stored in the `s.sectors` field, so `sectors` cannot be used as a component name. + +## Fusion Rules + +`NamedSector` behaves identically to the underlying `ProductSector`: fusion, duality, and units act componentwise, and every piece of topological data is forwarded to the corresponding `ProductSector` of the same components. +Concretely, `NamedSector` converts to `ProductSector` (via `ProductSector(s)`) and delegates [`⊗`](@ref), [`Nsymbol`](@ref), [`dual`](@ref), [`unit`](@ref), and [`allunits`](@ref). +See the [`ProductSector`](@ref) page for the componentwise fusion rules. + +## Topological Data + +[`Fsymbol`](@ref), [`Rsymbol`](@ref), [`Asymbol`](@ref), [`Bsymbol`](@ref), [`fusiontensor`](@ref), and [`dim`](@ref) are all computed by forwarding to the underlying `ProductSector`. +Likewise, [`FusionStyle`](@ref), [`BraidingStyle`](@ref), `UnitStyle`, and the scalar-type traits are inherited from the product of the components. + +## Iteration + +`values(I)` for a `NamedSector` type `I` iterates the same Cartesian product as the corresponding `ProductSector`, wrapping each result back into the named type. +Indexing and `findindex` use the same ordering. + +## References + +- [Deligne tensor product](https://ncatlab.org/nlab/show/Deligne+tensor+product) From 7331f5a4d4d7cf8c97dbcb73d19f0d950b2c2782 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:57:56 -0400 Subject: [PATCH 44/50] docs: document multifusion support and IsingBimodule example IsingBimodule is exported but was undocumented anywhere. Add a short 'Multifusion categories' note pointing to it as a reference example, without listing it in the fusion-category summary table. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/src/sectors.md b/docs/src/sectors.md index 74648ea9..cf19dcd0 100644 --- a/docs/src/sectors.md +++ b/docs/src/sectors.md @@ -24,6 +24,13 @@ This page provides an overview of the concrete sector types implemented in Tenso | [`NamedSector`](@ref) | Product categories | Varies | Varies | Varies | Product sectors with name-accessible components | | [`TimeReversed`](@ref) | Inverted braiding | Varies | Varies | Varies | Time-reversal or other orientation-reversing symmetries | +## Multifusion categories + +Beyond fusion categories (with a unique simple unit), TensorKitSectors.jl also supports *multifusion* categories, whose unit is semisimple. +These are signalled by `UnitStyle(I) === GenericUnit()` and require the additional `allunits`, `leftunit`, and `rightunit` methods. +The exported [`IsingBimodule`](@ref) is a minimal worked example: the Ising category reinterpreted as a bimodule category over two copies of `Irrep[ℤ₂]`. +It is intended as a reference implementation illustrating how to build such categories, rather than as a general-purpose sector, so it is not listed in the summary table above. + ## Other packages TensorKitSectors.jl provides the architecture for implementing new sector types, but does not implement all possible sectors. Other packages which implement additional sector types and their topological data include: From 3ab69bae6dd5845a0a81350c32ce845d1df78841 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 11:58:51 -0400 Subject: [PATCH 45/50] docs: make CU1Irrep iteration example a runnable jldoctest The block interleaved bare output lines with inputs (not copy-pasteable and not validated). Convert to a jldoctest with julia> prompts so the outputs are checked at build time. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/nonabelian/cu1.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/src/sectors/nonabelian/cu1.md b/docs/src/sectors/nonabelian/cu1.md index 1e69222e..982c14fb 100644 --- a/docs/src/sectors/nonabelian/cu1.md +++ b/docs/src/sectors/nonabelian/cu1.md @@ -115,16 +115,16 @@ All omitted entries are zero. These conventions determine the real [`Fsymbol`](@ `values(CU1Irrep)` is infinite. It starts with the two zero-charge irreps and then lists positive half-integer charges: -```julia -using TensorKitSectors +```jldoctest +julia> using TensorKitSectors -values(CU1Irrep)[1] +julia> values(CU1Irrep)[1] Irrep[CU₁](0, 0) -values(CU1Irrep)[2] +julia> values(CU1Irrep)[2] Irrep[CU₁](0, 1) -values(CU1Irrep)[5] +julia> values(CU1Irrep)[5] Irrep[CU₁](3/2, 2) ``` From 6b5eb928afa2ad2795e5a9b7467f024a021045ce Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 12:17:16 -0400 Subject: [PATCH 46/50] docs: use Unicode for math symbols and Greek letters (interface pages) Convert safe LaTeX commands to Unicode inside math contexts (Greek letters, binary operators, relations, arrows, blackboard-bold) for a more readable source. Structural macros (\frac, \sqrt, \overline, matrices, big operators, \ket) and code/doctest blocks are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/interface/guidelines.md | 8 ++++---- docs/src/interface/optional.md | 12 ++++++------ docs/src/interface/overview.md | 4 ++-- docs/src/interface/required.md | 8 ++++---- docs/src/interface/traits.md | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/src/interface/guidelines.md b/docs/src/interface/guidelines.md index 518518fb..6bc9f198 100644 --- a/docs/src/interface/guidelines.md +++ b/docs/src/interface/guidelines.md @@ -47,17 +47,17 @@ Additionally, if the [`Fsymbol`](@ref) and [`Rsymbol`](@ref) do not correspond t Therefore, computing the number of valid fusion channels for both diagrams as the product of the relevant [`Nsymbol`](@ref)s, we have: ```math -\left(N^{ab}_e N^{ec}_d = 0 \lor N^{af}_d N^{bc}_f = 0\right) \implies (F_{abc}^d)^e_f = 0 +\left(N^{ab}_e N^{ec}_d = 0 ∨ N^{af}_d N^{bc}_f = 0\right) ⟹ (F_{abc}^d)^e_f = 0 ``` ```math -N^{ab}_c = 0 \implies R^{ab}_c = 0 +N^{ab}_c = 0 ⟹ R^{ab}_c = 0 ``` ### [`GenericFusion`](@ref) - `Nsymbol(a, b, c)`: Returns a positive `Integer`. -- `Fsymbol(a, b, c, d, e, f)`: Returns a ``N^{ab}_e \times N^{ec}_d \times N^{af}_d \times N^{bc}_f`` array of `sectorscalartype(I)` elements. -- `Rsymbol(a, b, c)`: Returns a ``N^{ab}_c \times N^{ba}_c`` array of `sectorscalartype(I)` elements. +- `Fsymbol(a, b, c, d, e, f)`: Returns a ``N^{ab}_e × N^{ec}_d × N^{af}_d × N^{bc}_f`` array of `sectorscalartype(I)` elements. +- `Rsymbol(a, b, c)`: Returns a ``N^{ab}_c × N^{ba}_c`` array of `sectorscalartype(I)` elements. Here invalid fusion channels will necessarily lead to empty arrays. diff --git a/docs/src/interface/optional.md b/docs/src/interface/optional.md index f1b545d3..9d947dd9 100644 --- a/docs/src/interface/optional.md +++ b/docs/src/interface/optional.md @@ -29,14 +29,14 @@ invsqrtdim ## Frobenius-Schur Indicators The Frobenius-Schur indicator and phase characterize the self-duality properties of sectors. -The Frobenius-Schur phase ``\kappa_a`` is obtained from the F-symbol as +The Frobenius-Schur phase ``κ_a`` is obtained from the F-symbol as ```math -\kappa_a = \text{sign}\left( (F_{a \bar{a} a}^a)^{1_a}_{_a1} \right) +κ_a = \text{sign}\left( (F_{a \bar{a} a}^a)^{1_a}_{_a1} \right) ``` and is the category-theoretic quantity that appears in line-bending operations. -The Frobenius-Schur indicator ``\nu_a`` coincides with ``\kappa_a`` for self-dual sectors (``a = \bar{a}``) and is ``0`` otherwise; it distinguishes real, complex, and quaternionic representations. +The Frobenius-Schur indicator ``ν_a`` coincides with ``κ_a`` for self-dual sectors (``a = \bar{a}``) and is ``0`` otherwise; it distinguishes real, complex, and quaternionic representations. ```@docs; canonical = false frobenius_schur_indicator @@ -65,7 +65,7 @@ The A-symbol and B-symbol relate different ways of bending strands, while the tw The A-symbol ``A^{ab}_c`` relates splitting and fusion vertices: ```math -A^{ab}_c = \sqrt{\frac{d_a d_b}{d_c}} \, \overline{\kappa_a (F_{\bar{a} a b}^b)^1_c} +A^{ab}_c = \sqrt{\frac{d_a d_b}{d_c}} \, \overline{κ_a (F_{\bar{a} a b}^b)^1_c} ``` The B-symbol ``B^{ab}_c`` relates splitting and fusion vertices: @@ -73,9 +73,9 @@ The B-symbol ``B^{ab}_c`` relates splitting and fusion vertices: B^{ab}_c = \sqrt{\frac{d_a d_b}{d_c}} (F_{a b \bar{b}}^a)^c_1 ``` -The twist ``\theta_a`` of a sector is the topological spin phase, computed as the trace of the R-matrix for braiding a sector with itself: +The twist ``θ_a`` of a sector is the topological spin phase, computed as the trace of the R-matrix for braiding a sector with itself: ```math -\theta_a = \frac{1}{d_a} \sum_{b \in a \otimes a} d_b \text{tr}(R^{aa}_b) +θ_a = \frac{1}{d_a} \sum_{b ∈ a ⊗ a} d_b \text{tr}(R^{aa}_b) ``` ```@docs; canonical = false diff --git a/docs/src/interface/overview.md b/docs/src/interface/overview.md index 38cfac9b..b9d9f6fa 100644 --- a/docs/src/interface/overview.md +++ b/docs/src/interface/overview.md @@ -6,14 +6,14 @@ A `Sector` is a label for the different *symmetry charges* or *quantum numbers* In particular, these are the labels used to decompose vector spaces as: ```math -V = \bigoplus_{a \in \text{Sectors}} \mathbb{C}^{n_a} \otimes V_a +V = \bigoplus_{a ∈ \text{Sectors}} ℂ^{n_a} ⊗ V_a ``` where ``n_a`` is the multiplicity of sector ``a`` and ``V_a`` is the associated vector space. Sectors encode the structural rules TensorKit needs: - **Objects**: the labels themselves (irreps, anyons, …) -- **Fusion rules**: which labels appear in ``a \otimes b \rightarrow \bigoplus_c N^{ab}_c c`` +- **Fusion rules**: which labels appear in ``a ⊗ b → \bigoplus_c N^{ab}_c c`` - **Associativity**: how different parenthesizations are related - **Braiding**: how labels behave under exchange (if supported) diff --git a/docs/src/interface/required.md b/docs/src/interface/required.md index 536b306e..895535e0 100644 --- a/docs/src/interface/required.md +++ b/docs/src/interface/required.md @@ -61,13 +61,13 @@ FusionStyle Every sector type has a unit (identity) label and a notion of dual (conjugate). `unit` returns the identity label, and `dual` returns the label that fuses with `a` to give the unit. -The unit ``\mathbb{1}`` acts as the identity under fusion: +The unit ``𝟙`` acts as the identity under fusion: ```math -\mathbb{1} ⊗ a ≅ a ≅ a ⊗ \mathbb{1} +𝟙 ⊗ a ≅ a ≅ a ⊗ 𝟙 ``` The dual of a sector ``a`` is the unique sector ``\bar{a}`` such that: ```math -N^{a\bar{a}}_{\mathbb{1}} = 1 \quad \text{and} \quad N^{\bar{a}a}_{\mathbb{1}} = 1 +N^{a\bar{a}}_{𝟙} = 1 \quad \text{and} \quad N^{\bar{a}a}_{𝟙} = 1 ``` ```@docs; canonical = false @@ -99,7 +99,7 @@ Fsymbol Formally, the F-symbol ``F^{abc}_d`` with intermediate sectors ``e`` and ``f`` is a linear transformation between the two different parenthesizations: ```math -(F_{abc}^d)^e_f : (a ⊗ b → e) ⊗ c → d \quad \longrightarrow \quad a ⊗ (b ⊗ c → f) → d +(F_{abc}^d)^e_f : (a ⊗ b → e) ⊗ c → d \quad ⟶ \quad a ⊗ (b ⊗ c → f) → d ``` For sectors with `UniqueFusion` or `SimpleFusion`, the F-symbol is a scalar `<:Number`. diff --git a/docs/src/interface/traits.md b/docs/src/interface/traits.md index a863a240..dcdcc407 100644 --- a/docs/src/interface/traits.md +++ b/docs/src/interface/traits.md @@ -24,7 +24,7 @@ GenericFusion This enables various optimizations for different cases. Firstly, since the shape (size of the arrays) of the topological data is determined by combinations of the [`Nsymbol`](@ref), for `UniqueFusion` and `SimpleFusion` we can use scalar quantities instead of arrays. -Secondly, in the `UniqueFusion` case, there is only a single channel for ``a \otimes b \otimes c \otimes \ldots``, avoiding the need to iterate through all options. +Secondly, in the `UniqueFusion` case, there is only a single channel for ``a ⊗ b ⊗ c ⊗ …``, avoiding the need to iterate through all options. It is additionally possible to combine fusion styles through the `&` operator, which returns the style with the least assumptions. For example: From 64d9da4097e7722faddb0fc9988594db8f214e13 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 6 Jul 2026 12:17:17 -0400 Subject: [PATCH 47/50] docs: use Unicode for math symbols and Greek letters (sector pages) Same Unicode conversion as the previous commit, applied to all sector type pages. Purely a symbol swap inside math contexts; rendering is unchanged (verified by rebuilding the docs) and doctests still pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/src/sectors/abelian/trivial.md | 2 +- docs/src/sectors/abelian/u1.md | 2 +- docs/src/sectors/abelian/zn.md | 8 ++-- docs/src/sectors/anyons/fibonacci.md | 20 +++++----- docs/src/sectors/anyons/ising.md | 22 +++++------ docs/src/sectors/anyons/planartrivial.md | 2 +- docs/src/sectors/composite/product.md | 12 +++--- docs/src/sectors/composite/timereversed.md | 8 ++-- docs/src/sectors/fermions/number.md | 4 +- docs/src/sectors/fermions/parity.md | 4 +- docs/src/sectors/fermions/spin.md | 4 +- docs/src/sectors/groupelement/znelement.md | 22 +++++------ docs/src/sectors/nonabelian/a4.md | 30 +++++++------- docs/src/sectors/nonabelian/cu1.md | 32 +++++++-------- docs/src/sectors/nonabelian/dn.md | 14 +++---- docs/src/sectors/nonabelian/heisenberg.md | 46 +++++++++++----------- docs/src/sectors/nonabelian/su2.md | 24 +++++------ 17 files changed, 128 insertions(+), 128 deletions(-) diff --git a/docs/src/sectors/abelian/trivial.md b/docs/src/sectors/abelian/trivial.md index 8a77e58e..bff8dd7e 100644 --- a/docs/src/sectors/abelian/trivial.md +++ b/docs/src/sectors/abelian/trivial.md @@ -22,7 +22,7 @@ Trivial() Fusion is uniquely trivial: ```math -1 \otimes 1 = 1. +1 ⊗ 1 = 1. ``` Therefore `FusionStyle(Trivial) = UniqueFusion()` and `Nsymbol(Trivial(), Trivial(), Trivial()) == true`. diff --git a/docs/src/sectors/abelian/u1.md b/docs/src/sectors/abelian/u1.md index 0125359a..88ebf3e2 100644 --- a/docs/src/sectors/abelian/u1.md +++ b/docs/src/sectors/abelian/u1.md @@ -20,7 +20,7 @@ q^* = -q. Fusion adds charges: ```math -q_1 \otimes q_2 = q_1 + q_2. +q_1 ⊗ q_2 = q_1 + q_2. ``` ## Topological Data diff --git a/docs/src/sectors/abelian/zn.md b/docs/src/sectors/abelian/zn.md index 68cd3223..a9a28506 100644 --- a/docs/src/sectors/abelian/zn.md +++ b/docs/src/sectors/abelian/zn.md @@ -1,11 +1,11 @@ # Cyclic Group Representations: `ZNIrrep` -`ZNIrrep{N}` and `LargeZNIrrep{N}` represent irreducible representations of the cyclic group ``\mathbb{Z}_N``. +`ZNIrrep{N}` and `LargeZNIrrep{N}` represent irreducible representations of the cyclic group ``ℤ_N``. Use `ZNIrrep{N}` when possible; it selects the compact storage type automatically. !!! note - `ZNIrrep{N}` grades a space by the *irreps* of ``\mathbb{Z}_N`` (the `Rep[ℤₙ]` category). - To instead grade by the *group elements* of ``\mathbb{Z}_N`` (the `Vec[ℤₙ]` category, which also supports discrete torsion), see [`ZNElement`](@ref). + `ZNIrrep{N}` grades a space by the *irreps* of ``ℤ_N`` (the `Rep[ℤₙ]` category). + To instead grade by the *group elements* of ``ℤ_N`` (the `Vec[ℤₙ]` category, which also supports discrete torsion), see [`ZNElement`](@ref). ## Sector types @@ -23,7 +23,7 @@ Labels are charges modulo `N`. The unit is charge `0`, duality negates the charge modulo `N`, and fusion adds charges: ```math -a \otimes b = (a + b) \bmod N,\qquad a^* = -a \bmod N. +a ⊗ b = (a + b) \bmod N,\qquad a^* = -a \bmod N. ``` The category has `FusionStyle(ZNIrrep{N}) = UniqueFusion()`. diff --git a/docs/src/sectors/anyons/fibonacci.md b/docs/src/sectors/anyons/fibonacci.md index 81bbcece..6d1b3a46 100644 --- a/docs/src/sectors/anyons/fibonacci.md +++ b/docs/src/sectors/anyons/fibonacci.md @@ -16,37 +16,37 @@ Both sectors are self-dual, and the unit is `FibonacciAnyon(:I)`. The only non-trivial fusion rule is ```math -\tau \otimes \tau = I \oplus \tau. +τ ⊗ τ = I ⊕ τ. ``` Thus `FusionStyle(FibonacciAnyon) = SimpleFusion()`. The quantum dimensions are ```math -d_I = 1,\qquad d_\tau = \varphi = \frac{1 + \sqrt{5}}{2}. +d_I = 1,\qquad d_τ = φ = \frac{1 + \sqrt{5}}{2}. ``` ## Topological Data -The non-trivial associator appears when all external anyons are ``\tau``: +The non-trivial associator appears when all external anyons are ``τ``: ```math -F^{\tau\tau\tau}_{\tau} = +F^{τττ}_{τ} = \begin{pmatrix} -\varphi^{-1} & \varphi^{-1/2}\\ -\varphi^{-1/2} & -\varphi^{-1} +φ^{-1} & φ^{-1/2}\\ +φ^{-1/2} & -φ^{-1} \end{pmatrix}, ``` -in the intermediate basis ``(I,\tau)``. +in the intermediate basis ``(I,τ)``. All other allowed `Fsymbol` values are `1`. The braiding style is `Anyonic()`. -For ``\tau \otimes \tau``, +For ``τ ⊗ τ``, ```math -R^{\tau\tau}_I = e^{4\pi i/5},\qquad -R^{\tau\tau}_\tau = e^{-3\pi i/5}. +R^{ττ}_I = e^{4π i/5},\qquad +R^{ττ}_τ = e^{-3π i/5}. ``` There is no fusion tensor as the fusion category does not originate from a group or its representations. diff --git a/docs/src/sectors/anyons/ising.md b/docs/src/sectors/anyons/ising.md index fc7d23b1..b9ab54d5 100644 --- a/docs/src/sectors/anyons/ising.md +++ b/docs/src/sectors/anyons/ising.md @@ -16,24 +16,24 @@ All three sectors are self-dual, and the unit is `IsingAnyon(:I)`. The non-trivial fusion rules are ```math -\psi \otimes \psi = I,\qquad -\sigma \otimes \psi = \psi \otimes \sigma = \sigma,\qquad -\sigma \otimes \sigma = I \oplus \psi. +ψ ⊗ ψ = I,\qquad +σ ⊗ ψ = ψ ⊗ σ = σ,\qquad +σ ⊗ σ = I ⊕ ψ. ``` Thus `FusionStyle(IsingAnyon) = SimpleFusion()`. The quantum dimensions are ```math -d_I = 1,\qquad d_\psi = 1,\qquad d_\sigma = \sqrt{2}. +d_I = 1,\qquad d_ψ = 1,\qquad d_σ = \sqrt{2}. ``` ## Topological Data -The non-trivial associator for four ``\sigma`` anyons is +The non-trivial associator for four ``σ`` anyons is ```math -F^{\sigma\sigma\sigma}_{\sigma} = +F^{σσσ}_{σ} = \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1\\ @@ -41,16 +41,16 @@ F^{\sigma\sigma\sigma}_{\sigma} = \end{pmatrix}, ``` -in the intermediate basis ``(I,\psi)``. -Additional signs involving the fermion ``\psi`` are encoded by [`Fsymbol`](@ref). +in the intermediate basis ``(I,ψ)``. +Additional signs involving the fermion ``ψ`` are encoded by [`Fsymbol`](@ref). The braiding style is `Anyonic()`. Important braiding phases are ```math -R^{\sigma\sigma}_I = e^{-\pi i/8},\qquad -R^{\sigma\sigma}_\psi = e^{3\pi i/8},\qquad -R^{\psi\psi}_I = -1. +R^{σσ}_I = e^{-π i/8},\qquad +R^{σσ}_ψ = e^{3π i/8},\qquad +R^{ψψ}_I = -1. ``` There is no fusion tensor as the fusion category does not originate from a group or its representations. diff --git a/docs/src/sectors/anyons/planartrivial.md b/docs/src/sectors/anyons/planartrivial.md index a824780d..1860ca45 100644 --- a/docs/src/sectors/anyons/planartrivial.md +++ b/docs/src/sectors/anyons/planartrivial.md @@ -17,7 +17,7 @@ It is its own unit and dual. Fusion is uniquely trivial: ```math -1 \otimes 1 = 1. +1 ⊗ 1 = 1. ``` `FusionStyle(PlanarTrivial) = UniqueFusion()` and `Nsymbol` is `1` for the only allowed channel. diff --git a/docs/src/sectors/composite/product.md b/docs/src/sectors/composite/product.md index 8c0581c4..42545bc8 100644 --- a/docs/src/sectors/composite/product.md +++ b/docs/src/sectors/composite/product.md @@ -48,15 +48,15 @@ Fusion is componentwise. For product sectors ```math -a = (a_1,\ldots,a_n),\qquad b = (b_1,\ldots,b_n), +a = (a_1,…,a_n),\qquad b = (b_1,…,b_n), ``` the fusion outputs are ```math -a \otimes b = -\bigoplus_{c_i \in a_i \otimes b_i} N^{ab}_c -(c_1,\ldots,c_n). +a ⊗ b = +\bigoplus_{c_i ∈ a_i ⊗ b_i} N^{ab}_c +(c_1,…,c_n). ``` The fusion multiplicities multiply: @@ -71,8 +71,8 @@ In particular, a product of unique-fusion sectors remains unique, while adding a Duals, units, and quantum dimensions are also componentwise: ```math -(a_1,\ldots,a_n)^* = (a_1^*,\ldots,a_n^*),\qquad -d_{(a_1,\ldots,a_n)} = \prod_i d_{a_i}. +(a_1,…,a_n)^* = (a_1^*,…,a_n^*),\qquad +d_{(a_1,…,a_n)} = \prod_i d_{a_i}. ``` If a component category has multiple units, `allunits` returns the product of the component unit sets. diff --git a/docs/src/sectors/composite/timereversed.md b/docs/src/sectors/composite/timereversed.md index 769c0dcd..a08e0368 100644 --- a/docs/src/sectors/composite/timereversed.md +++ b/docs/src/sectors/composite/timereversed.md @@ -49,15 +49,15 @@ R_{\overline{c}}^{\overline{a}\,\overline{b}} For scalar braiding phases this is complex conjugation, so anyonic spins change sign: ```math -\theta_{\overline{a}} = \overline{\theta_a}. +θ_{\overline{a}} = \overline{θ_a}. ``` For example, in the conventions of this package, ```math -\theta_\sigma = e^{\pi i/8} -\quad\Longrightarrow\quad -\theta_{\overline{\sigma}} = e^{-\pi i/8} +θ_σ = e^{π i/8} +\quad⟹\quad +θ_{\overline{σ}} = e^{-π i/8} ``` for the Ising `σ` anyon. diff --git a/docs/src/sectors/fermions/number.md b/docs/src/sectors/fermions/number.md index 9056c073..10651b84 100644 --- a/docs/src/sectors/fermions/number.md +++ b/docs/src/sectors/fermions/number.md @@ -13,7 +13,7 @@ Construct `FermionNumber(n)` from an integer charge `n`. The underlying product label is ```math -n \mapsto (U(1)\text{ charge } n,\; n \bmod 2). +n ↦ (U(1)\text{ charge } n,\; n \bmod 2). ``` The unit is `FermionNumber(0)`, and duality negates the ``U(1)`` charge while preserving the parity constraint. @@ -23,7 +23,7 @@ The unit is `FermionNumber(0)`, and duality negates the ``U(1)`` charge while pr Fusion adds charges: ```math -n_1 \otimes n_2 = n_1 + n_2. +n_1 ⊗ n_2 = n_1 + n_2. ``` The fermion parity component is then fixed automatically by the resulting charge. diff --git a/docs/src/sectors/fermions/parity.md b/docs/src/sectors/fermions/parity.md index 9c9a69a3..09fddedc 100644 --- a/docs/src/sectors/fermions/parity.md +++ b/docs/src/sectors/fermions/parity.md @@ -18,7 +18,7 @@ The unit is even parity, and every sector is self-dual. Fusion is addition modulo two: ```math -p \otimes q = p \oplus q. +p ⊗ q = p ⊕ q. ``` The category has `FusionStyle(FermionParity) = UniqueFusion()`. @@ -37,7 +37,7 @@ R^{11}_0 = -1. The twists are ```math -\theta_0 = 1,\qquad \theta_1 = -1. +θ_0 = 1,\qquad θ_1 = -1. ``` `fusiontensor` is defined for array construction, but it emits a warning because plain arrays with `FermionParity` labels do not preserve all fermionic signs. diff --git a/docs/src/sectors/fermions/spin.md b/docs/src/sectors/fermions/spin.md index 2352e29f..6ddcc84b 100644 --- a/docs/src/sectors/fermions/spin.md +++ b/docs/src/sectors/fermions/spin.md @@ -13,7 +13,7 @@ Construct `FermionSpin(j)` from an integer or half-integer spin. The parity is odd exactly when `2j` is odd: ```math -j \mapsto (SU(2)\text{ spin }j,\; 2j \bmod 2). +j ↦ (SU(2)\text{ spin }j,\; 2j \bmod 2). ``` The unit is `FermionSpin(0)`, and all sectors are self-dual because the ``SU(2)`` irreps and parity sectors are self-dual. @@ -23,7 +23,7 @@ The unit is `FermionSpin(0)`, and all sectors are self-dual because the ``SU(2)` The ``SU(2)`` component fuses by angular-momentum addition: ```math -j_1 \otimes j_2 = +j_1 ⊗ j_2 = \bigoplus_{j = |j_1-j_2|}^{j_1+j_2} j. ``` diff --git a/docs/src/sectors/groupelement/znelement.md b/docs/src/sectors/groupelement/znelement.md index 2b6aa8b7..5a627c93 100644 --- a/docs/src/sectors/groupelement/znelement.md +++ b/docs/src/sectors/groupelement/znelement.md @@ -1,9 +1,9 @@ # Cyclic Group Elements: `ZNElement{N,p}` -`ZNElement{N,p}` represents the elements of the cyclic group ``\mathbb{Z}_N`` directly as a `Sector`, as opposed to [`ZNIrrep`](@ref) which represents its (one-dimensional) irreps. -Fusion is given by the group multiplication itself, and the associator can carry a nontrivial phase determined by a level-`p` 3-cocycle on ``\mathbb{Z}_N``. +`ZNElement{N,p}` represents the elements of the cyclic group ``ℤ_N`` directly as a `Sector`, as opposed to [`ZNIrrep`](@ref) which represents its (one-dimensional) irreps. +Fusion is given by the group multiplication itself, and the associator can carry a nontrivial phase determined by a level-`p` 3-cocycle on ``ℤ_N``. For special values of `p` this also yields a consistent braiding, turning `ZNElement{N,p}` into a simple model of abelian anyons. -As a fusion category, this is identified with ``\text{Vec}_{\mathbb{Z}_N}^{\omega_p}``, the category of ``\mathbb{Z}_N``-graded vector spaces with associator the 3-cocycle ``\omega_p``. +As a fusion category, this is identified with ``\text{Vec}_{ℤ_N}^{ω_p}``, the category of ``ℤ_N``-graded vector spaces with associator the 3-cocycle ``ω_p``. ## Group elements as sectors @@ -36,7 +36,7 @@ a^* = a^{-1} = -a \bmod N. Fusion is literally the group operation, so there is a single fusion channel with multiplicity one: ```math -a \otimes b = (a + b) \bmod N, +a ⊗ b = (a + b) \bmod N, ``` and `FusionStyle(ZNElement{N,p}) = UniqueFusion()` for every `N` and `p`. @@ -47,18 +47,18 @@ All quantum dimensions are `1`. The [`Fsymbol`](@ref) is not assumed trivial: it is given by the 3-cocycle ```math -\omega_p(a,b,c) = \exp\left(\frac{2\pi i\, p\, a\,\big(b + c - [b+c]_N\big)}{N^2}\right), \qquad [x]_N := x \bmod N, +ω_p(a,b,c) = \exp\left(\frac{2π i\, p\, a\,\big(b + c - [b+c]_N\big)}{N^2}\right), \qquad [x]_N := x \bmod N, ``` -which is a representative of a class in ``H^3(\mathbb{Z}_N, U(1)) \cong \mathbb{Z}_N``, indexed by the level `p ∈ 0:N-1`. +which is a representative of a class in ``H^3(ℤ_N, U(1)) ≅ ℤ_N``, indexed by the level `p ∈ 0:N-1`. Concretely, ```math -F^{abc}_{e,d,f} = \omega_p(a,b,c) \quad \text{when } e = a+b,\ d = e+c,\ f = b + c \pmod N, +F^{abc}_{e,d,f} = ω_p(a,b,c) \quad \text{when } e = a+b,\ d = e+c,\ f = b + c \pmod N, ``` and zero otherwise (since fusion is unique, all the other symbols such as [`Asymbol`](@ref), [`Bsymbol`](@ref) and `frobenius_schur_phase` are likewise built directly out of `ω_p`). -For `p = 0` the cocycle is trivial and `ZNElement{N,0}` reduces to the ordinary ``\mathbb{Z}_N``-graded vector spaces. +For `p = 0` the cocycle is trivial and `ZNElement{N,0}` reduces to the ordinary ``ℤ_N``-graded vector spaces. The [`pentagon_equation`](@ref) holds for every `N` and every `p ∈ 0:N-1`, i.e. every `ZNElement{N,p}` is a consistent fusion category. ## Topological Data (Braiding) @@ -68,11 +68,11 @@ Braiding is only defined in two cases: - `p = 0`: `BraidingStyle(ZNElement{N,0}) = Bosonic()`, and the [`Rsymbol`](@ref) is trivial (`Rsymbol(a,b,c) = Nsymbol(a,b,c)`). - `2p ≡ N`: `BraidingStyle(ZNElement{N,p}) = Anyonic()`, and - ```math + `````math R^{ab}_{a+b} = \exp\left(\frac{2\pi i\, p\, a\, b}{N^2}\right), - ``` + ````` - giving abelian anyonic braiding statistics for the ``\mathbb{Z}_N`` charges. For example, `N = 4, p = 2` (used in the example below) yields topological spins ``\theta_a = \exp(i\pi a^2 / 4)``. + giving abelian anyonic braiding statistics for the ``ℤ_N`` charges. For example, `N = 4, p = 2` (used in the example below) yields topological spins ``θ_a = \exp(iπ a^2 / 4)``. For any other value of `p`, `BraidingStyle(ZNElement{N,p}) = NoBraiding()`. diff --git a/docs/src/sectors/nonabelian/a4.md b/docs/src/sectors/nonabelian/a4.md index 9340a6c9..0d5f98d8 100644 --- a/docs/src/sectors/nonabelian/a4.md +++ b/docs/src/sectors/nonabelian/a4.md @@ -21,33 +21,33 @@ Duals are ## Fusion Rules -The one-dimensional irreps fuse as the group ``\mathbb{Z}_3``: +The one-dimensional irreps fuse as the group ``ℤ_3``: ```math -a \otimes b = (a + b) \bmod 3,\qquad a,b \in \{0,1,2\}. +a ⊗ b = (a + b) \bmod 3,\qquad a,b ∈ \{0,1,2\}. ``` Fusing a one-dimensional irrep with the triplet gives the triplet again: ```math -a \otimes 3 = 3 \otimes a = 3,\qquad a \in \{0,1,2\}. +a ⊗ 3 = 3 ⊗ a = 3,\qquad a ∈ \{0,1,2\}. ``` The triplet product decomposes as ```math -3 \otimes 3 = 0 \oplus 1 \oplus 2 \oplus 2 * 3. +3 ⊗ 3 = 0 ⊕ 1 ⊕ 2 ⊕ 2 * 3. ``` -Because the triplet appears with multiplicity two in ``3 \otimes 3``, `FusionStyle(A4Irrep) = GenericFusion()`. +Because the triplet appears with multiplicity two in ``3 ⊗ 3``, `FusionStyle(A4Irrep) = GenericFusion()`. The [`Nsymbol`](@ref) returns the corresponding integer multiplicity: ```math N_c^{ab} = \begin{cases} -1 + \delta_{c,3}, & a = b = 3,\\ -\delta_{c,3}, & a = 3 \text{ or } b = 3,\\ -\delta_{c,(a+b)\bmod 3}, & a,b \in \{0,1,2\}. +1 + δ_{c,3}, & a = b = 3,\\ +δ_{c,3}, & a = 3 \text{ or } b = 3,\\ +δ_{c,(a+b)\bmod 3}, & a,b ∈ \{0,1,2\}. \end{cases} ``` @@ -64,7 +64,7 @@ The braiding is bosonic, and all topological twists are `1`. The [`Fsymbol`](@ref) is computed from the chosen [`fusiontensor`](@ref) basis, see below. The [`Rsymbol`](@ref) is the identity on all simple fusion channels, except for the two ``3`` channels in -``3 \otimes 3 \to 3``: +``3 ⊗ 3 → 3``: ```math R^{33}_3 = @@ -78,9 +78,9 @@ The first channel is the antisymmetric triplet and the second channel is the sym ## Fusion Tensor and Basis Conventions -`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. +`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a × d_b × d_c × N_c^{ab}``. The one-dimensional fusion tensors are scalar phases/permutations in the selected basis. -For ``3 \otimes 3``, the singlet channels are normalized with a factor ``1/\sqrt{3}``, and the two triplet channels use the real antisymmetric and symmetric Clebsch-Gordan tensors from the tetrahedral basis convention used in the implementation. +For ``3 ⊗ 3``, the singlet channels are normalized with a factor ``1/\sqrt{3}``, and the two triplet channels use the real antisymmetric and symmetric Clebsch-Gordan tensors from the tetrahedral basis convention used in the implementation. In this basis the triplet representation can be generated by @@ -88,8 +88,8 @@ In this basis the triplet representation can be generated by T_3 = \begin{pmatrix} 1 & 0 & 0\\ -0 & \omega & 0\\ -0 & 0 & \omega^2 +0 & ω & 0\\ +0 & 0 & ω^2 \end{pmatrix}, \qquad S_3 = \frac{1}{3} @@ -99,10 +99,10 @@ S_3 = \frac{1}{3} 2 & 2 & -1 \end{pmatrix}, \qquad -\omega = e^{2\pi i/3}. +ω = e^{2π i/3}. ``` -The one-dimensional irreps have ``S = 1`` and ``T = \omega^n`` for label `n`. +The one-dimensional irreps have ``S = 1`` and ``T = ω^n`` for label `n`. For every allowed fusion channel, the fusion tensor intertwines the product representation with the output representation. ```jldoctest a4_intertwiner; output = false diff --git a/docs/src/sectors/nonabelian/cu1.md b/docs/src/sectors/nonabelian/cu1.md index 982c14fb..a4d03944 100644 --- a/docs/src/sectors/nonabelian/cu1.md +++ b/docs/src/sectors/nonabelian/cu1.md @@ -21,8 +21,8 @@ Fusing either one-dimensional irrep with a two-dimensional irrep returns the sam For two positive charges, the outputs are governed by sum and absolute difference: ```math -j_1 \otimes j_2 = -|j_1-j_2| \oplus (j_1+j_2), +j_1 ⊗ j_2 = +|j_1-j_2| ⊕ (j_1+j_2), ``` with the special case `j1 == j2`, where the zero-charge difference splits into the two one-dimensional irreps. @@ -42,7 +42,7 @@ The [`Rsymbol`](@ref) is real and equals the N-symbol, with an additional negati ## Fusion Tensor and Basis Conventions -`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. +`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a × d_b × d_c × N_c^{ab}``. Since `CU1Irrep` has simple fusion, the final multiplicity axis has length `0` or `1`. For allowed channels, the tensor entries are real Clebsch-Gordan coefficients in the convention explained below. @@ -58,19 +58,19 @@ When two equal positive-charge irreps fuse to a zero-charge irrep, the fusion te ```math \ket{(0,0)} = -\frac{1}{\sqrt{2}}\left(\ket{+j}\otimes\ket{-j} + \ket{-j}\otimes\ket{+j}\right), +\frac{1}{\sqrt{2}}\left(\ket{+j}⊗\ket{-j} + \ket{-j}⊗\ket{+j}\right), ``` ```math \ket{(0,1)} = -\frac{1}{\sqrt{2}}\left(\ket{+j}\otimes\ket{-j} - \ket{-j}\otimes\ket{+j}\right). +\frac{1}{\sqrt{2}}\left(\ket{+j}⊗\ket{-j} - \ket{-j}⊗\ket{+j}\right). ``` In array form, these are the entries ```math C_{1,2,1} = \frac{1}{\sqrt{2}},\qquad -C_{2,1,1} = \pm\frac{1}{\sqrt{2}}, +C_{2,1,1} = ±\frac{1}{\sqrt{2}}, ``` with the plus sign for `(0, 0)` and the minus sign for `(0, 1)`. @@ -79,9 +79,9 @@ Fusing a zero-charge irrep with a two-dimensional irrep leaves the charge label The odd zero-charge irrep contributes a sign on the second basis vector: ```math -(0,s) \otimes (j,2) \to (j,2):\qquad -\ket{+j}\mapsto\ket{+j},\quad -\ket{-j}\mapsto (-1)^s\ket{-j}. +(0,s) ⊗ (j,2) → (j,2):\qquad +\ket{+j}↦\ket{+j},\quad +\ket{-j}↦ (-1)^s\ket{-j}. ``` The same convention is used for `(j,2) ⊗ (0,s)`, with the sign attached to the second basis vector of the two-dimensional input. @@ -89,23 +89,23 @@ The same convention is used for `(j,2) ⊗ (0,s)`, with the sign attached to the For two positive charges, the sum channel is diagonal: ```math -(j_a,2)\otimes(j_b,2)\to(j_a+j_b,2):\qquad -\ket{+j_a,+j_b}\mapsto\ket{+(j_a+j_b)},\quad -\ket{-j_a,-j_b}\mapsto\ket{-(j_a+j_b)}. +(j_a,2)⊗(j_b,2)→(j_a+j_b,2):\qquad +\ket{+j_a,+j_b}↦\ket{+(j_a+j_b)},\quad +\ket{-j_a,-j_b}↦\ket{-(j_a+j_b)}. ``` The difference channel pairs opposite weights. If `j_a > j_b`, ```math -\ket{+j_a,-j_b}\mapsto\ket{+(j_a-j_b)},\qquad -\ket{-j_a,+j_b}\mapsto\ket{-(j_a-j_b)}. +\ket{+j_a,-j_b}↦\ket{+(j_a-j_b)},\qquad +\ket{-j_a,+j_b}↦\ket{-(j_a-j_b)}. ``` If `j_b > j_a`, the output basis is ordered by the positive charge `j_b - j_a`, so the two nonzero entries are swapped accordingly: ```math -\ket{-j_a,+j_b}\mapsto\ket{+(j_b-j_a)},\qquad -\ket{+j_a,-j_b}\mapsto\ket{-(j_b-j_a)}. +\ket{-j_a,+j_b}↦\ket{+(j_b-j_a)},\qquad +\ket{+j_a,-j_b}↦\ket{-(j_b-j_a)}. ``` All omitted entries are zero. These conventions determine the real [`Fsymbol`](@ref) values. diff --git a/docs/src/sectors/nonabelian/dn.md b/docs/src/sectors/nonabelian/dn.md index 3b125a32..9a9e59b9 100644 --- a/docs/src/sectors/nonabelian/dn.md +++ b/docs/src/sectors/nonabelian/dn.md @@ -1,6 +1,6 @@ # Dihedral Group Representations: `DNIrrep` -`DNIrrep{N}` represents irreducible representations of the dihedral group ``D_N = \mathbb{Z}_N ⋊ C``. +`DNIrrep{N}` represents irreducible representations of the dihedral group ``D_N = ℤ_N ⋊ C``. The aliases `D3Irrep` and `D4Irrep` are provided for `DNIrrep{3}` and `DNIrrep{4}`. ## Sector type @@ -16,13 +16,13 @@ The `isodd` flag is valid only for one-dimensional irreps: always at `j == 0`, a For odd `N`, the labels are ```math -(0,\text{false}),\ (0,\text{true}),\ 1,2,\ldots,(\frac{N-1}{2},\text{false}). +(0,\text{false}),\ (0,\text{true}),\ 1,2,…,(\frac{N-1}{2},\text{false}). ``` For even `N`, the labels are ```math -(0,\text{false}),\ (0,\text{true}),\ 1,2,\ldots,\frac{N}{2}-1,\ (N/2,\text{false}),\ (N/2,\text{true}). +(0,\text{false}),\ (0,\text{true}),\ 1,2,…,\frac{N}{2}-1,\ (N/2,\text{false}),\ (N/2,\text{true}). ``` The unit is `DNIrrep{N}(0, false)`, and all irreps are self-dual. @@ -35,7 +35,7 @@ The fusion product of a one-dimensional irrep with a two-dimensional irrep prese For ordinary two-dimensional labels, fusion follows the dihedral character rule: ```math -\rho_i \otimes \rho_j = \rho_{|i-j|} \oplus \rho_{i+j}, +ρ_i ⊗ ρ_j = ρ_{|i-j|} ⊕ ρ_{i+j}, ``` where labels are folded back into the range `0:N÷2`. @@ -47,8 +47,8 @@ Otherwise, `FusionStyle(DNIrrep{N}) = SimpleFusion()`. Quantum dimensions are ```math -d_{(0,\pm)} = 1,\qquad d_{\rho_j} = 2,\qquad -d_{(N/2,\pm)} = 1\quad (N \text{ even}). +d_{(0,±)} = 1,\qquad d_{ρ_j} = 2,\qquad +d_{(N/2,±)} = 1\quad (N \text{ even}). ``` ## Topological Data @@ -59,7 +59,7 @@ The [`Rsymbol`](@ref) equals the N-symbol, up to a sign of ``-1`` on the ``(0,-) ## Fusion Tensor and Basis Conventions -`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. +`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a × d_b × d_c × N_c^{ab}``. The implementation uses real Clebsch-Gordan coefficients. #TODO: source for the convention used here diff --git a/docs/src/sectors/nonabelian/heisenberg.md b/docs/src/sectors/nonabelian/heisenberg.md index 1fa8e249..e0bc60df 100644 --- a/docs/src/sectors/nonabelian/heisenberg.md +++ b/docs/src/sectors/nonabelian/heisenberg.md @@ -1,7 +1,7 @@ # Representation of the finite Heisenberg Group ``H_N``: `HeisenbergIrrep{N}` `HeisenbergIrrep{N}` represents irreducible representations (irreps) of the finite Heisenberg group ``H_N`` as a `Sector`. -``H_N`` is the group of ``3\times 3`` upper triangular matrices which is identified with the group ``\mathbb{Z}_N \rtimes \mathbb{Z}_N^2``; it is only defined here for prime `N`. +``H_N`` is the group of ``3× 3`` upper triangular matrices which is identified with the group ``ℤ_N ⋊ ℤ_N^2``; it is only defined here for prime `N`. This page documents how the type behaves in code (construction, iteration, fusion, and access to topological data). ## Sector type @@ -12,47 +12,47 @@ HeisenbergIrrep Every irrep is labeled by a single integer `n::Int8`, but the meaning of `n` depends on its sign: -- If `0 <= n < N^2`, the irrep is the one-dimensional character ``\chi_{a,b}`` with `a, b = divrem(n, N)`. +- If `0 <= n < N^2`, the irrep is the one-dimensional character ``χ_{a,b}`` with `a, b = divrem(n, N)`. There are ``N^2`` such characters, one for each pair `(a, b) ∈ 0:N-1`. -- If `-N < n < 0`, the irrep is the ``N``-dimensional Schrödinger representation ``\pi_k`` with `k = -n`, `k ∈ 1:N-1`. +- If `-N < n < 0`, the irrep is the ``N``-dimensional Schrödinger representation ``π_k`` with `k = -n`, `k ∈ 1:N-1`. In total there are ``N^2 + N - 1`` irreps (the trivial ``k = 0`` Schrödinger representation is excluded, since it is reducible and decomposes into the ``N^2`` characters). The alias `Heis3Irrep = HeisenbergIrrep{3}` is provided for the smallest (and most commonly used) case. -The trivial sector is `HeisenbergIrrep{N}(0)`, i.e. ``\chi_{0,0}``. +The trivial sector is `HeisenbergIrrep{N}(0)`, i.e. ``χ_{0,0}``. Duals are ```math -\chi_{a,b}^* = \chi_{-a \bmod N,\,-b \bmod N}, \qquad \pi_k^* = \pi_{N-k}. +χ_{a,b}^* = χ_{-a \bmod N,\,-b \bmod N}, \qquad π_k^* = π_{N-k}. ``` ## Fusion Rules -Characters fuse among themselves as the abelian group ``\mathbb{Z}_N \times \mathbb{Z}_N``: +Characters fuse among themselves as the abelian group ``ℤ_N × ℤ_N``: ```math -\chi_{a,b} \otimes \chi_{a',b'} = \chi_{(a+a')\bmod N,\,(b+b')\bmod N}. +χ_{a,b} ⊗ χ_{a',b'} = χ_{(a+a')\bmod N,\,(b+b')\bmod N}. ``` Fusing a character with a Schrödinger irrep leaves the latter unchanged, regardless of the character's labels: ```math -\chi_{a,b} \otimes \pi_k = \pi_k \otimes \chi_{a,b} = \pi_k. +χ_{a,b} ⊗ π_k = π_k ⊗ χ_{a,b} = π_k. ``` -This reflects that ``\pi_k`` is the unique irrep with a given nontrivial central character, so twisting it by any character of the full group produces an isomorphic representation. +This reflects that ``π_k`` is the unique irrep with a given nontrivial central character, so twisting it by any character of the full group produces an isomorphic representation. Two Schrödinger irreps fuse according to whether their labels cancel modulo `N`: ```math -\pi_k \otimes \pi_{k'} = +π_k ⊗ π_{k'} = \begin{cases} -N \cdot \pi_{(k+k') \bmod N}, & k + k' \not\equiv 0 \pmod N, \\[4pt] -\displaystyle\bigoplus_{a,b=0}^{N-1} \chi_{a,b}, & k + k' \equiv 0 \pmod N. +N ⋅ π_{(k+k') \bmod N}, & k + k' ≢ 0 \pmod N, \\[4pt] +\displaystyle\bigoplus_{a,b=0}^{N-1} χ_{a,b}, & k + k' ≡ 0 \pmod N. \end{cases} ``` -In the first case the ``N``-fold multiplicity accounts for the dimension count ``N \times N = N^2`` (``N`` copies of the ``N``-dimensional ``\pi_{(k+k')\bmod N}``); in the second, the ``N^2``-dimensional product decomposes into all ``N^2`` one-dimensional characters, each with multiplicity one. +In the first case the ``N``-fold multiplicity accounts for the dimension count ``N × N = N^2`` (``N`` copies of the ``N``-dimensional ``π_{(k+k')\bmod N}``); in the second, the ``N^2``-dimensional product decomposes into all ``N^2`` one-dimensional characters, each with multiplicity one. Because of this multiplicity-``N`` channel, `FusionStyle(HeisenbergIrrep) = GenericFusion()`. The [`Nsymbol`](@ref) returns the corresponding integer multiplicities directly from the case distinction above. @@ -60,7 +60,7 @@ The [`Nsymbol`](@ref) returns the corresponding integer multiplicities directly Quantum dimensions are the ordinary representation space dimensions: ```math -d_{\chi_{a,b}} = 1, \qquad d_{\pi_k} = N. +d_{χ_{a,b}} = 1, \qquad d_{π_k} = N. ``` ## Topological Data @@ -68,20 +68,20 @@ d_{\chi_{a,b}} = 1, \qquad d_{\pi_k} = N. `BraidingStyle(HeisenbergIrrep) = Bosonic()`: braiding is symmetric, and `braidingscalartype(HeisenbergIrrep) = ComplexF64` since the Clebsch-Gordan coefficients are generally complex. The [`Fsymbol`](@ref) and [`Rsymbol`](@ref) are both computed generically from the chosen [`fusiontensor`](@ref) basis (via `Fsymbol_from_fusiontensor` and `Rsymbol_from_fusiontensor`), see below. -On the single-channel sectors (``\chi \otimes \chi \to \chi`` and ``\chi \otimes \pi \to \pi``) the R-symbol evaluates to the trivial phase `1`. -On the multiplicity-``N`` channel ``\pi_k \otimes \pi_{k'} \to \pi_{(k+k')\bmod N}`` and on the channels ``\pi_k \otimes \pi_{-k} \to \chi_{a,b}``, the R-symbol carries nontrivial phases built out of `N`-th roots of unity. +On the single-channel sectors (``χ ⊗ χ → χ`` and ``χ ⊗ π → π``) the R-symbol evaluates to the trivial phase `1`. +On the multiplicity-``N`` channel ``π_k ⊗ π_{k'} → π_{(k+k')\bmod N}`` and on the channels ``π_k ⊗ π_{-k} → χ_{a,b}``, the R-symbol carries nontrivial phases built out of `N`-th roots of unity. ## Fusion Tensor and Basis Conventions -`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a \times d_b \times d_c \times N_c^{ab}``. +`fusiontensor(a, b, c)` returns a rank-4 array of size ``d_a × d_b × d_c × N_c^{ab}``. The one-dimensional (character) fusion tensors are trivial scalars. -For the Schrödinger irreps, the fusion tensor is built out of the ``N``-th root of unity ``\omega = e^{2\pi i/N}``, following the reference below: +For the Schrödinger irreps, the fusion tensor is built out of the ``N``-th root of unity ``ω = e^{2π i/N}``, following the reference below: -- ``\pi_k \otimes \pi_{k'} \to \pi_{(k+k')\bmod N}`` (``k+k' \not\equiv 0``): a permutation tensor (with a phase for the case where one of the factors is a character, see below). -- ``\pi_k \otimes \pi_{-k} \to \chi_{a,b}``: normalized with a factor ``1/\sqrt{N}``, with phase ``\omega^{-a i}`` along the surviving diagonal. -- ``\chi_{a,b} \otimes \pi_k \to \pi_k`` (and the symmetric ``\pi_k \otimes \chi_{a,b} \to \pi_k``): a permutation tensor dressed with the phase ``\omega^{a m}``. +- ``π_k ⊗ π_{k'} → π_{(k+k')\bmod N}`` (``k+k' ≢ 0``): a permutation tensor (with a phase for the case where one of the factors is a character, see below). +- ``π_k ⊗ π_{-k} → χ_{a,b}``: normalized with a factor ``1/\sqrt{N}``, with phase ``ω^{-a i}`` along the surviving diagonal. +- ``χ_{a,b} ⊗ π_k → π_k`` (and the symmetric ``π_k ⊗ χ_{a,b} → π_k``): a permutation tensor dressed with the phase ``ω^{a m}``. -The representation can be checked against the generators `X` and `Z` of ``H_N`` acting as ``X|i\rangle = |i+1\rangle`` and ``Z|i\rangle = \omega^{ki}|i\rangle`` on ``\pi_k``, and as ``X \mapsto \omega^a``, ``Z \mapsto \omega^b`` on ``\chi_{a,b}``. +The representation can be checked against the generators `X` and `Z` of ``H_N`` acting as ``X|i\rangle = |i+1\rangle`` and ``Z|i\rangle = ω^{ki}|i\rangle`` on ``π_k``, and as ``X ↦ ω^a``, ``Z ↦ ω^b`` on ``χ_{a,b}``. For every allowed fusion channel, the fusion tensor acts as an intertwiner between the tensor product representation and the fused representation: ```jldoctest heisenberg_intertwiner; output = false @@ -118,7 +118,7 @@ end ## Iteration -Iterating over `values(HeisenbergIrrep{N})` first yields the ``N^2`` characters ``\chi_{0,0}, \chi_{0,1}, \ldots`` (in order of increasing `n`), followed by the Schrödinger irreps ``\pi_1, \ldots, \pi_{N-1}``. +Iterating over `values(HeisenbergIrrep{N})` first yields the ``N^2`` characters ``χ_{0,0}, χ_{0,1}, …`` (in order of increasing `n`), followed by the Schrödinger irreps ``π_1, …, π_{N-1}``. ## References diff --git a/docs/src/sectors/nonabelian/su2.md b/docs/src/sectors/nonabelian/su2.md index 07d0f45f..0ed67666 100644 --- a/docs/src/sectors/nonabelian/su2.md +++ b/docs/src/sectors/nonabelian/su2.md @@ -14,14 +14,14 @@ SU2Irrep Fusing two irreps together leads to a direct sum of irreps: ```math -a \otimes b = \bigoplus_{c_j = |j_a - j_b|}^{j_a + j_b} c +a ⊗ b = \bigoplus_{c_j = |j_a - j_b|}^{j_a + j_b} c ``` Since each output appears only once, we have `FusionStyle(SU2Irrep) = SimpleFusion()`. The [`Nsymbol`](@ref) returns a `Bool` that checks the triangle inequality: ```math -N_c^{ab} = |j_a - j_b| \leq j_c \leq j_a + j_b \land j_a + j_b + j_c \in \mathbb{N} +N_c^{ab} = |j_a - j_b| ≤ j_c ≤ j_a + j_b ∧ j_a + j_b + j_c ∈ ℕ ``` Each irrep has dimension ``d = 2j + 1``. @@ -35,19 +35,19 @@ j_c & j_d & j_f \end{Bmatrix} ``` -The `BraidingStyle` is `Bosonic`, and [`Rsymbol`](@ref) is ``\pm 1`` for allowed fusion channels based on the parity of ``j_a + j_b - j_c``. +The `BraidingStyle` is `Bosonic`, and [`Rsymbol`](@ref) is ``± 1`` for allowed fusion channels based on the parity of ``j_a + j_b - j_c``. ## Fusion Tensor and Basis Conventions -`fusiontensor(a, b, c)` returns Clebsch–Gordan coefficients as a rank‑4 array of size ``d_a \times d_b \times d_c \times 1``. -We can label the basis by using ``\ket{j, m}``, where the magnetic quantum number takes on values ``m \in \{j, j-1, \ldots, -j\}`` (in that order). +`fusiontensor(a, b, c)` returns Clebsch–Gordan coefficients as a rank‑4 array of size ``d_a × d_b × d_c × 1``. +We can label the basis by using ``\ket{j, m}``, where the magnetic quantum number takes on values ``m ∈ \{j, j-1, …, -j\}`` (in that order). -Each irrep acts on the standard basis $\lvert j, m \rangle$ where $m = j, j-1, \dots, -j$. +Each irrep acts on the standard basis $\lvert j, m \rangle$ where $m = j, j-1, …, -j$. In that basis, the generators of ``\mathfrak{su}(2)`` are represented by the usual angular momentum operators: ```math J_z \lvert j, m \rangle = m \lvert j, m \rangle, \quad -J_\pm \lvert j, m \rangle = \sqrt{(j \mp m)(j \pm m + 1)}\, \lvert j, m \pm 1 \rangle. +J_± \lvert j, m \rangle = \sqrt{(j ∓ m)(j ± m + 1)}\, \lvert j, m ± 1 \rangle. ``` ```jldoctest generators; output = false @@ -79,24 +79,24 @@ Jp, Jm, Jz = generators(a) ([0.0 1.4142135623730951 0.0; 0.0 0.0 1.4142135623730951; 0.0 0.0 0.0], [0.0 0.0 0.0; 1.4142135623730951 0.0 0.0; 0.0 1.4142135623730951 0.0], [1.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 -1.0]) ``` -The tensor product representation for ``a \otimes b`` is given in terms of the representations ``a`` and ``b`` as: +The tensor product representation for ``a ⊗ b`` is given in terms of the representations ``a`` and ``b`` as: ```math -\mathbf{J}^{(a \otimes b)} = \mathbf{J}^{(a)} \otimes \mathbf{1}^{(b)} + \mathbf{1}^{(a)} \otimes \mathbf{J}^{(b)} +\mathbf{J}^{(a ⊗ b)} = \mathbf{J}^{(a)} ⊗ \mathbf{1}^{(b)} + \mathbf{1}^{(a)} ⊗ \mathbf{J}^{(b)} ``` The [`fusiontensor`](@ref) supplies the change‑of‑basis coefficients ``C^{J M}_{j_a m_a, j_b m_b}`` that map the uncoupled product basis to the coupled basis: ```math \lvert J, M \rangle = \sum_{m_a, m_b} C^{J M}_{j_a m_a, j_b m_b} -\lvert j_a, m_a \rangle \otimes \lvert j_b, m_b \rangle. +\lvert j_a, m_a \rangle ⊗ \lvert j_b, m_b \rangle. ``` In particular, this block-diagonalizes the generators, and we must have that for every ``\mathbf{J}``, the following holds: ```math -\left(\mathbf{J}^{(a)} \otimes \mathbf{1}^{(b)} + \mathbf{1}^{(a)} \otimes \mathbf{J}^{(b)}\right) \cdot C^c_{ab} = - C^c_{ab} \cdot \mathbf{J}^{(c)} +\left(\mathbf{J}^{(a)} ⊗ \mathbf{1}^{(b)} + \mathbf{1}^{(a)} ⊗ \mathbf{J}^{(b)}\right) ⋅ C^c_{ab} = + C^c_{ab} ⋅ \mathbf{J}^{(c)} ``` ```jldoctest generators; output = false From 7a1bf3d5eadfce623e4979d0a1cc0b4cad30c599 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 7 Jul 2026 07:05:14 -0400 Subject: [PATCH 48/50] Apply suggestions from code review Co-authored-by: Jutho --- docs/src/sectors/anyons/planartrivial.md | 2 +- docs/src/sectors/composite/named.md | 1 - docs/src/sectors/fermions/parity.md | 2 +- docs/src/sectors/groupelement/znelement.md | 4 +--- docs/src/sectors/nonabelian/su2.md | 6 +++--- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/src/sectors/anyons/planartrivial.md b/docs/src/sectors/anyons/planartrivial.md index 1860ca45..34d7dad4 100644 --- a/docs/src/sectors/anyons/planartrivial.md +++ b/docs/src/sectors/anyons/planartrivial.md @@ -1,7 +1,7 @@ # Planar Trivial Anyon: `PlanarTrivial` `PlanarTrivial` is the one-object fusion category without braiding. -It is mostly useful as the smallest planar, non-braided sector in tests and examples. +It is mostly useful as the smallest non-braided sector to be used tests and examples, e.g. of planar contractions (hence the name). ## Sector type diff --git a/docs/src/sectors/composite/named.md b/docs/src/sectors/composite/named.md index 584d4e43..8f399e14 100644 --- a/docs/src/sectors/composite/named.md +++ b/docs/src/sectors/composite/named.md @@ -23,7 +23,6 @@ I = @NamedSector{charge::U1Irrep, spin::SU2Irrep} I(U1Irrep(1), SU2Irrep(1//2)) # same as above ``` -The components are stored in the `s.sectors` field, so `sectors` cannot be used as a component name. ## Fusion Rules diff --git a/docs/src/sectors/fermions/parity.md b/docs/src/sectors/fermions/parity.md index 09fddedc..5948d260 100644 --- a/docs/src/sectors/fermions/parity.md +++ b/docs/src/sectors/fermions/parity.md @@ -40,7 +40,7 @@ The twists are θ_0 = 1,\qquad θ_1 = -1. ``` -`fusiontensor` is defined for array construction, but it emits a warning because plain arrays with `FermionParity` labels do not preserve all fermionic signs. +`fusiontensor` is defined for array construction, but it emits a warning because plain arrays with `FermionParity` labels can not preserve all fermionic signs. ## References diff --git a/docs/src/sectors/groupelement/znelement.md b/docs/src/sectors/groupelement/znelement.md index 5a627c93..9d696912 100644 --- a/docs/src/sectors/groupelement/znelement.md +++ b/docs/src/sectors/groupelement/znelement.md @@ -11,9 +11,7 @@ As a fusion category, this is identified with ``\text{Vec}_{ℤ_N}^{ω_p}``, the AbstractGroupElement ``` -`ZNElement{N,p}` is currently the only concrete subtype of `AbstractGroupElement{Group}`. Any concrete `G <: AbstractGroupElement{Group}` only needs to implement `Base.:*`, `Base.one`, `Base.inv`, and optionally `TensorKitSectors.cocycle`; the fusion category structure (`⊗`, `dual`, `unit`, `Nsymbol`, `Fsymbol`, `dim`, `Asymbol`, `Bsymbol`, `frobenius_schur_phase`) follows automatically. -`FusionStyle(AbstractGroupElement) = UniqueFusion()` always, and `BraidingStyle(AbstractGroupElement) = NoBraiding()` by default, though a concrete type is free to override this (as `ZNElement` does, see below). -If no `cocycle` method is defined, it defaults to the trivial one. +`ZNElement{N,p}` is currently the only concrete subtype of `AbstractGroupElement{Group}`. ## Sector type diff --git a/docs/src/sectors/nonabelian/su2.md b/docs/src/sectors/nonabelian/su2.md index 0ed67666..7c63b81f 100644 --- a/docs/src/sectors/nonabelian/su2.md +++ b/docs/src/sectors/nonabelian/su2.md @@ -108,9 +108,9 @@ b = SU2Irrep(1) for c in a ⊗ b CGC = dropdims(fusiontensor(a, b, c); dims = 4) # drop trivial multiplicity dimension - for (ga, gb, gc) in zip(generators(a), generators(b), generators(c)) - @tensor lhs[a b; c] := ga[a; a'] * CGC[a' b; c] + gb[b; b'] * CGC[a b'; c] - @tensor rhs[a b; c] := CGC[a b; c'] * gc[c'; c] + for (Ja, Jb, Jc) in zip(generators(a), generators(b), generators(c)) + @tensor lhs[a b; c] := Ja[a; a'] * CGC[a' b; c] + Jb[b; b'] * CGC[a b'; c] + @tensor rhs[a b; c] := CGC[a b; c'] * Jc[c'; c] @test isapprox(lhs, rhs) end end From 43481f79900e05577620dfeccbda67035b957576 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Tue, 7 Jul 2026 07:05:34 -0400 Subject: [PATCH 49/50] more updates from suggestions --- docs/src/sectors/composite/timereversed.md | 7 +++---- src/groupelements.jl | 12 +++++++----- src/named.jl | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/src/sectors/composite/timereversed.md b/docs/src/sectors/composite/timereversed.md index a08e0368..e670bf38 100644 --- a/docs/src/sectors/composite/timereversed.md +++ b/docs/src/sectors/composite/timereversed.md @@ -39,11 +39,10 @@ d_{\overline{a}} = d_a,\qquad ## Topological Data The [`Fsymbol`](@ref), [`Asymbol`](@ref), and [`Bsymbol`](@ref) are inherited directly from the original sector. -The [`Rsymbol`](@ref) is adjointed: +The [`Rsymbol`](@ref) is replaced by its adjoint: ```math -R_{\overline{c}}^{\overline{a}\,\overline{b}} -= \left(R_c^{ab}\right)^\dagger. +R_{\overline{c}}^{\overline{a}\,\overline{b}} = \left(R_c^{ab}\right)^\dagger. ``` For scalar braiding phases this is complex conjugation, so anyonic spins change sign: @@ -67,4 +66,4 @@ For bosonic or fermionic symmetric categories, time reversal is physically trivi ## References -- [Time reversal symmetry](https://en.wikipedia.org/wiki/T-symmetry) \ No newline at end of file +- [Time reversal symmetry](https://en.wikipedia.org/wiki/T-symmetry) diff --git a/src/groupelements.jl b/src/groupelements.jl index a9614e0b..3309f016 100644 --- a/src/groupelements.jl +++ b/src/groupelements.jl @@ -16,19 +16,21 @@ overridden by a concrete implementation of `AbstractGroupElement`. For the fusion structure, a specific `SomeGroupElement <: AbstractGroupElement{SomeGroup}` should only implement the following methods + ```julia -Base.:*(c1::GroupElement, c2::GroupElement) -> GroupElement -Base.one(::Type{GroupElement}) -> GroupElement -Base.inv(c::GroupElement) -> GroupElement +Base.:*(c1::SomeGroupElement, c2::SomeGroupElement) -> SomeGroupElement +Base.one(::Type{SomeGroupElement}) -> SomeGroupElement +Base.inv(c::SomeGroupElement) -> SomeGroupElement # and optionally -TensorKitSectors.cocycle(c1::GroupElement, c2::GroupElement, c3::GroupElement) -> Number +TensorKitSectors.cocycle(c1::SomeGroupElement, c2::SomeGroupElement, c3::SomeGroupElement) -> Number ``` + The methods `conj`, `dual`, `⊗`, `Nsymbol`, `Fsymbol`, `dim`, `Asymbol`, `Bsymbol` and `frobenius_schur_phase` will then be automatically defined. If no `cocycle` method is defined, the cocycle will be assumed to be trivial, i.e. equal to `1`. - """ abstract type AbstractGroupElement{G <: Group} <: Sector end + FusionStyle(::Type{<:AbstractGroupElement}) = UniqueFusion() BraidingStyle(::Type{<:AbstractGroupElement}) = NoBraiding() diff --git a/src/named.jl b/src/named.jl index 2114d36d..8d0eb130 100644 --- a/src/named.jl +++ b/src/named.jl @@ -23,7 +23,7 @@ julia> s.spin ``` !!! warning - The sectors are stored internally in the `s.sectors` field, so the named components should not contain the `sectors` as a name. + The sectors are stored internally in the `s.sectors` field, so the named components should not contain `sectors` as a name. """ struct NamedSector{NT <: NamedSectorTuple} <: Sector sectors::NT From d9b6d8abaf585b88c3e74c381d609e9295716ecd Mon Sep 17 00:00:00 2001 From: lkdvos Date: Tue, 7 Jul 2026 07:42:12 -0400 Subject: [PATCH 50/50] small typos --- docs/src/sectors/anyons/planartrivial.md | 2 +- docs/src/sectors/fermions/parity.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/sectors/anyons/planartrivial.md b/docs/src/sectors/anyons/planartrivial.md index 34d7dad4..d2072aed 100644 --- a/docs/src/sectors/anyons/planartrivial.md +++ b/docs/src/sectors/anyons/planartrivial.md @@ -1,7 +1,7 @@ # Planar Trivial Anyon: `PlanarTrivial` `PlanarTrivial` is the one-object fusion category without braiding. -It is mostly useful as the smallest non-braided sector to be used tests and examples, e.g. of planar contractions (hence the name). +It is mostly useful as the smallest non-braided sector to be used in tests and examples, e.g. of planar contractions (hence the name). ## Sector type diff --git a/docs/src/sectors/fermions/parity.md b/docs/src/sectors/fermions/parity.md index 5948d260..53929e89 100644 --- a/docs/src/sectors/fermions/parity.md +++ b/docs/src/sectors/fermions/parity.md @@ -40,9 +40,9 @@ The twists are θ_0 = 1,\qquad θ_1 = -1. ``` -`fusiontensor` is defined for array construction, but it emits a warning because plain arrays with `FermionParity` labels can not preserve all fermionic signs. +`fusiontensor` is defined for array construction, but it emits a warning because plain arrays with `FermionParity` labels cannot preserve all fermionic signs. ## References - [Fermion parity](https://en.wikipedia.org/wiki/Fermion_parity) -- [Super vector space](https://en.wikipedia.org/wiki/Super_vector_space) \ No newline at end of file +- [Super vector space](https://en.wikipedia.org/wiki/Super_vector_space)