Skip to content

Cheaper ProductSector symbols - #113

Merged
leburgel merged 2 commits into
mainfrom
lb/product_symbols
Oct 15, 2026
Merged

leburgel merged 2 commits into
mainfrom
lb/product_symbols

Conversation

@leburgel

@leburgel leburgel commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

The symbols of a ProductSector combine the symbols of its factors with _kron_promote, which
always computed the sizes needed to promote a scalar symbol to an array (4–6 Nsymbol calls on the
factors) and then promoted it with fill and _kron. Now:

  • the sizes are only computed when one of the two symbols is a scalar;
  • a scalar without multiplicities scales the other symbol, and a scalar one returns it as is;
  • two arrays are combined with _kron as before.

The results are unchanged (checked symbol by symbol for fℤ₂ × U(1) × SU(3) and
fℤ₂ × U(1) × SU(2) × U(1)). This only matters when a factor has array-valued symbols, i.e. fusion
multiplicities: for SU(3) the product symbols become 3–4× cheaper, for SU(2) nothing changes.

Time per symbol, for all F- and R-symbols over six sectors of a fermionic PEPS bond space (script
below), factor symbols cached, median of 3 interleaved rounds:

before after
fℤ₂ × U(1) × SU(3), Fsymbol (1576) 768 ns 256 ns (3.0×)
fℤ₂ × U(1) × SU(3), Rsymbol (72) 239 ns 57.5 ns (4.2×)
fℤ₂ × U(1) × SU(2) × U(1), Fsymbol (647) 406 ns 406 ns
fℤ₂ × U(1) × SU(2) × U(1), Rsymbol (53) 5.1 ns 5.1 ns

SUNRepresentations with QuantumKitHub/SUNRepresentations.jl#56, QuantumKitHub/SUNRepresentations.jl#58
and QuantumKitHub/SUNRepresentations.jl#59 (MemoizationKit with QuantumKitHub/MemoizationKit.jl#21),
WignerSymbols 2.0.0, Julia 1.12.5; shared 80-core machine at load 5–11.

Reproducer
using TensorKitSectors, SUNRepresentations, BenchmarkTools
SUNRepresentations.use_disk_cache(false; persist = false)

# sectors of a bond space of a fermionic PEPS with fℤ₂ × U(1) × SU(3) and fℤ₂ × U(1) × SU(2) × U(1) symmetry
s3(f, q, a, b) = FermionParity(f) ⊠ U1Irrep(q) ⊠ SU3Irrep(a, b)
s2(f, q, j, q′) = FermionParity(f) ⊠ U1Irrep(q) ⊠ SU2Irrep(j) ⊠ U1Irrep(q′)
S3 = [s3(0, 0, 0, 0), s3(0, 0, 1, 1), s3(1, 1, 1, 0), s3(1, -1, 0, 1), s3(0, 2, 0, 1), s3(0, -2, 1, 0)]
S2 = [s2(0, 0, 0, 0), s2(0, 0, 1, 0), s2(1, 1, 1 // 2, 1), s2(1, -1, 1 // 2, -1), s2(0, 0, 1 // 2, 3), s2(1, 1, 0, -2)]

# all F- and R-symbols with incoming sectors from `S`
function fkeys(S)
    ks = []
    for a in S, b in S, c in S, e in a ⊗ b, f in b ⊗ c, d in e ⊗ c
        Nsymbol(a, f, d) > 0 && push!(ks, (a, b, c, d, e, f))
    end
    return ks
end
rkeys(S) = [(a, b, c) for a in S, b in S for c in a ⊗ b]
allF(ks) = foreach(k -> Fsymbol(k...), ks)
allR(ks) = foreach(k -> Rsymbol(k...), ks)

for (name, S) in (("fℤ₂ × U(1) × SU(3)", S3), ("fℤ₂ × U(1) × SU(2) × U(1)", S2))
    F, R = fkeys(S), rkeys(S)
    allF(F); allR(R) # the symbols of the factors are cached from here on
    tF = @belapsed allF($F)
    tR = @belapsed allR($R)
    println(name, ": Fsymbol ", round(tF / length(F) * 1e9; digits = 1), " ns (", length(F), " symbols), ",
        "Rsymbol ", round(tR / length(R) * 1e9; digits = 1), " ns (", length(R), " symbols)")
end

🤖 Generated with Claude Code

The sizes needed to promote a scalar symbol of a factor to an array take several `Nsymbol` evaluations; they are now only computed when one of the two symbols is a scalar. A scalar symbol without multiplicities scales the other symbol (which is returned as is for a scalar one), instead of going through `fill` and `_kron`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/auxiliary.jl 93.42% <100.00%> (+0.66%) ⬆️
src/product.jl 93.45% <100.00%> (-0.99%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@leburgel
leburgel marked this pull request as ready for review October 15, 2026 07:35
Comment thread src/auxiliary.jl Outdated
Broadcasting a scalar over a `SparseArray` gives a dense `Array`, so the type of a product symbol depended on the value of the scalar factor, which breaks contractions in e.g. the pentagon checks for `CategoryData` sectors. Use scalar multiplication instead, and promote a scalar symbol to an array similar to the other symbol.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@leburgel
leburgel merged commit 2756cb3 into main Oct 15, 2026
12 checks passed
@leburgel
leburgel deleted the lb/product_symbols branch October 15, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants