Repository navigation
Conversation
Braid and transpose a block of a ProductSector through its head and tail factors: the recoupling matrix is the Kronecker product of those of the factors, so blocks that only differ in their abelian charges share the cached manipulations of the non-abelian factors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
This looks great, but I think there might be some additional gain for the specific case where there's only one symmetry factor which doesn't actually have For products with a single factor without 1. Choose the head. Take the first factor without # blocks of products with `UniqueFusion` have a single tree and don't reach `product_transform` (see 3.)
@generated headfactor(::Type{ProductSector{T}}) where {T} =
something(findfirst(F -> !(FusionStyle(F) isa UniqueFusion), collect(fieldtypes(T))), 1)
headsector(s::ProductSector) = s.sectors[headfactor(typeof(s))]
function tailsector(s::ProductSector)
tail = _deletefactor(s.sectors, Val(headfactor(typeof(s))))
return length(tail) == 1 ? only(tail) : ProductSector(tail)
end
@generated _deletefactor(t::Tuple, ::Val{k}) where {k} =
Expr(:tuple, (:(t[$i]) for i in 1:fieldcount(t) if i != k)...)2. Join head and tail at that position. The tree joinsectors(::Type{I}, h, t) where {I} =
I(_insertfactor(t isa ProductSector ? t.sectors : (t,), h, Val(headfactor(I))))
@generated _insertfactor(t::Tuple, h, ::Val{k}) where {k} =
Expr(:tuple, (i < k ? :(t[$i]) : i == k ? :h : :(t[$(i - 1)]) for i in 1:(fieldcount(t) + 1))...)
function jointrees(::Type{I}, h::FusionTree, t::FusionTree) where {I}
vertices = ... # as in `⊠`, see 3.
join(a, b) = joinsectors(I, a, b)
return FusionTree(
map(join, h.uncoupled, t.uncoupled), join(h.coupled, t.coupled), h.isdual,
map(join, h.innerlines, t.innerlines), vertices
)
endwith 3. Use that the tail has unique fusion. With a single factor without
For products with several factors without |
Construct a FusionTreeBlock of a ProductSector as the Kronecker product of its head and tail blocks, such that the factorized manipulations produce canonical blocks without reordering. Bound the tuple elements of the product signatures by Sector, which fixes dispatch to the two-factor tailsector method. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A product with both UniqueFusion and other factors is split into its other factors and its UniqueFusion factors, instead of its first and remaining factors. The UniqueFusion part has a single tree pair, such that block construction and manipulation take a single step instead of recursing through every factor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
One more thing for products with a single factor without function braid(src::ProductSectorBlock, p::Index2Tuple, levels::Index2Tuple)
# blocks of products without multiplicities have a single tree
(isempty(src) || FusionStyle(sectortype(src)) isa UniqueFusion) && return fsbraid((src, p, levels))
return product_transform(sectorscalartype(sectortype(src)), src) do x
return braid(x, p, levels)
end
endand in the same way with |
…the UniqueFusion factors in one step Construct the UniqueFusion part of a mixed product block first, such that fusionblocks skips the non-abelian construction for blocks with mismatching abelian charges. Construct and manipulate blocks of UniqueFusion products, which hold a single tree pair, directly instead of recursing over their factors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Braid and transpose a
FusionTreeBlockof aProductSectorthrough its factors: the fusion trees of a product are pairs of fusion trees of two parts of the product, so the recoupling matrix of a block is the Kronecker product of the recoupling matrices of the two parts.UniqueFusionand other factors is split into its other factors and itsUniqueFusionfactors. The latter have a single tree pair, such that a block is a block of the other factors with a fixed tree pair and a scalar. All blocks that only differ in their abelian charges therefore share the cached manipulations of the non-abelian factors: for fℤ₂ × U(1) × SU(2) × U(1) below, 26004 blocks map onto 142 SU(2) blocks.FusionTreeBlock{I}(uncoupled, isdual)and therefore offusionblocks, is now the Kronecker order of the two parts, such that the factorized manipulations produce canonical blocks without reordering. This only affects the order of the trees within a block: the order offusiontrees(::HomSpace), and thus the data layout of tensors, is unchanged.fusionblocksalso benefits: the abelian part of a block is constructed first, which skips the non-abelian construction for the (many) combinations of uncoupled sectors with mismatching abelian charges.UniqueFusionsectors, which hold a single tree pair, are braided and transposed through the tree pair.The code lives in
src/fusiontrees/producttrees.jl;braidandtransposedispatch onProductSectorBlock.Cold construction of the recoupling data for one permutation of a tensor from a PEPS CTMRG step (the reproducers of #580 and #581), main → this PR, minimum of 5:
Ranges are over two interleaved rounds; Julia 1.13.2, shared 32-core machine. For SU(2),
fusionblocks(~0.4 s, single-threaded) is now the largest part of the remaining time, which is what #581 addresses; for SU(3), the remaining time is mostly braiding genuinely distinct SU(3) blocks, which is what #580 addresses. Both should compose with this PR.Tested: a new test compares the factorized
braid/transposewith the unfactorizedfsbraid/fstransposefor all product sectors in the test list. Additionally, for every block of a 3 ← 3 space of every product sector with a simple unit (includingA4Irrep ⊠ A4Irrepwith multiplicities,FermionParity ⊠ SU2Irrep ⊠ SU2Irrepand the anyonic products), and for the blocks of both reproducers, the results agree with the unfactorized ones to ~1e-15.🤖 Generated with Claude Code