Context
FusionTreeBlock is conceptually fully determined by its outer charges and duality flags: the canonical constructor FusionTreeBlock{I}(uncoupled, isdual) deterministically enumerates all compatible tree pairs (sorted coupled sectors, deterministic tree iterators), and all blocks on the main code path (fusionblocks(::HomSpace) and the duality/braiding manipulations) are built this way. Ideally, both hash and == would exploit this invariant and operate on (uncoupled, isdual) only, making dictionary/LRU-cache operations on block keys O(1) instead of comparing full trees vectors.
The obstacle
planar_trace for non-UniqueFusion sectors contains a workaround (marked TODO: this is a bit of a hack in src/fusiontrees/duality_manipulations.jl) that wraps individual tree pairs in ad-hoc single-pair blocks:
src = FusionTreeBlock([(f₁, f₂)])
...
src′ = FusionTreeBlock([(f₁′′, f₂′)])
dst′, U′ = transpose(src′, (p₁′, p₂′))
These blocks violate the invariant: they share (uncoupled, isdual) with each other and with the canonical block, while being genuinely different objects. They also flow into the cached fstranspose as keys. As a consequence:
== cannot be defined on (uncoupled, isdual) — distinct single-pair blocks would compare equal and the fstranspose cache would return wrong results.
hash currently includes the first tree pair (hash(first(fusiontrees(b)), h)) rather than just the defining data, specifically to keep these single-pair blocks from all colliding in the cache.
Proposal
Rework the planar_trace implementation so that it no longer constructs non-canonical single-pair blocks (or at least no longer feeds them into the cached fstranspose path). Once every FusionTreeBlock in circulation is canonical, both hash and == can be redefined purely in terms of (uncoupled, isdual), making cache lookups on block keys O(1).
Related: #518 introduced the current hash implementation.
Context
FusionTreeBlockis conceptually fully determined by its outer charges and duality flags: the canonical constructorFusionTreeBlock{I}(uncoupled, isdual)deterministically enumerates all compatible tree pairs (sorted coupled sectors, deterministic tree iterators), and all blocks on the main code path (fusionblocks(::HomSpace)and the duality/braiding manipulations) are built this way. Ideally, bothhashand==would exploit this invariant and operate on(uncoupled, isdual)only, making dictionary/LRU-cache operations on block keys O(1) instead of comparing fulltreesvectors.The obstacle
planar_tracefor non-UniqueFusionsectors contains a workaround (markedTODO: this is a bit of a hackinsrc/fusiontrees/duality_manipulations.jl) that wraps individual tree pairs in ad-hoc single-pair blocks:These blocks violate the invariant: they share
(uncoupled, isdual)with each other and with the canonical block, while being genuinely different objects. They also flow into the cachedfstransposeas keys. As a consequence:==cannot be defined on(uncoupled, isdual)— distinct single-pair blocks would compare equal and thefstransposecache would return wrong results.hashcurrently includes the first tree pair (hash(first(fusiontrees(b)), h)) rather than just the defining data, specifically to keep these single-pair blocks from all colliding in the cache.Proposal
Rework the
planar_traceimplementation so that it no longer constructs non-canonical single-pair blocks (or at least no longer feeds them into the cachedfstransposepath). Once everyFusionTreeBlockin circulation is canonical, bothhashand==can be redefined purely in terms of(uncoupled, isdual), making cache lookups on block keys O(1).Related: #518 introduced the current
hashimplementation.