Tensor networks and modular data

Change a fusion basis

For four labels a, b, c, d, fmatrix changes between the intermediate channels of ((a b)_e c)_d and (a (b c)_f)_d. It returns the matrix and both channel lists.

using QRecoupling, LinearAlgebra
F, e, f = fmatrix(1,1,1,1; k=6)
(F, e, f)
([0.41421356237309503 -0.6435942529055826 0.6435942529055826; -0.6435942529055826 0.2928932188134525 0.7071067811865476; 0.6435942529055826 0.7071067811865476 0.2928932188134525], Rational{Int64}[0, 1, 2], Rational{Int64}[0, 1, 2])

Columns express f-basis states in the e basis, so state_e = F * state_f. Keep channel labels with each tensor leg; array positions alone do not specify the fusion channel.

state_f = zeros(length(f)); state_f[1] = 1
state_e = F * state_f
state_e
3-element Vector{Float64}:
  0.41421356237309503
 -0.6435942529055826
  0.6435942529055826

For complex q, the algebraic relation is bilinear:

Fc, ec, fc = fmatrix(1,1,1,1; q=0.8+0.2im)
norm(transpose(Fc)*Fc - I)
2.1791220413003877e-15

Use transpose, not the adjoint, for this identity. Generic complex-q matrices need not preserve a Hilbert-space norm. See Accuracy and performance before requesting higher matrix element types.

Braiding in the fusion basis

B, incoming, outgoing = bmatrix(1,1,1,1; k=6)
(size(B), incoming, outgoing)
((3, 3), Rational{Int64}[0, 1, 2], Rational{Int64}[0, 1, 2])

bmatrix assembles the basis changes and channel R phases. The ordered channel lists matter when the exchanged labels differ. The scalar rmatrix is a single-channel braiding eigenvalue, not a full many-body operator.

The rows of B carry the incoming channels and the columns the outgoing channels. For a column vector state_in, apply the braid as state_out = transpose(B) * state_in; use the transpose here even at complex q.

Modular data

S, labels = smatrix(3)
T, labels_T = tmatrix(3)
(S, T, QRecoupling.total_qdim(3))
([0.3717480344601845 0.6015009550075457 0.6015009550075457 0.37174803446018445; 0.6015009550075457 0.37174803446018445 -0.3717480344601845 -0.6015009550075457; 0.6015009550075457 -0.3717480344601845 -0.37174803446018445 0.6015009550075457; 0.37174803446018445 -0.6015009550075457 0.6015009550075457 -0.3717480344601845], ComplexF64[0.8910065241883679 - 0.45399049973954675im 0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im; 0.0 + 0.0im 0.8910065241883678 + 0.4539904997395468im 0.0 + 0.0im 0.0 + 0.0im; 0.0 + 0.0im 0.0 + 0.0im -0.45399049973954697 + 0.8910065241883678im 0.0 + 0.0im; 0.0 + 0.0im 0.0 + 0.0im 0.0 + 0.0im -0.45399049973954675 - 0.8910065241883679im], 2.6899940478558295)

tmatrix includes the central-charge anomaly by default; anomaly=false retains only the twists. QRecoupling.level_labels, twist, QRecoupling.central_charge, QRecoupling.gauss_sum, QRecoupling.monodromy, and QRecoupling.verlinde expose the related data. QRecoupling.verlinde computes and rounds a numerical fusion coefficient with a consistency check; it is not an exact symbolic summation routine.

From local data to an application

A tensor-network application can enumerate allowed channels, cache the required F and R data at a fixed level, attach labels to sparse blocks, and contract using its chosen tensor library. QRecoupling supplies the local recoupling data. Network construction, contractions, truncation, optimization, and observable definitions belong to the surrounding application.

Before scaling up, compare every matrix convention against scalar entries and check a small identity or known network evaluation. These checks catch channel-order and phase errors that high precision cannot fix.