From d04adc94e63336e9f45533c45f61d24b78f4b9ab Mon Sep 17 00:00:00 2001 From: leburgel Date: Thu, 27 Aug 2026 14:02:14 +0200 Subject: [PATCH 1/3] Add `hash` for `FusionTreeBlock` --- src/fusiontrees/fusiontrees.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fusiontrees/fusiontrees.jl b/src/fusiontrees/fusiontrees.jl index 13710ee5b..c16f4191c 100644 --- a/src/fusiontrees/fusiontrees.jl +++ b/src/fusiontrees/fusiontrees.jl @@ -214,6 +214,7 @@ function Base.hash(f::FusionTree{I}, h::UInt) where {I} end return h end +Base.hash(b::FusionTreeBlock, h::UInt) = hash(fusiontrees(b), h) function Base.:(==)(f₁::FusionTree{I, N}, f₂::FusionTree{I, N}) where {I <: Sector, N} f₁.coupled == f₂.coupled || return false @inbounds for i in 1:N From cae6b3ab3f881c7c6cb8bd484b566d6383cf7c1a Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 31 Aug 2026 03:34:35 -0400 Subject: [PATCH 2/3] rework hash --- src/fusiontrees/fusiontrees.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fusiontrees/fusiontrees.jl b/src/fusiontrees/fusiontrees.jl index c16f4191c..ea22ce871 100644 --- a/src/fusiontrees/fusiontrees.jl +++ b/src/fusiontrees/fusiontrees.jl @@ -214,7 +214,8 @@ function Base.hash(f::FusionTree{I}, h::UInt) where {I} end return h end -Base.hash(b::FusionTreeBlock, h::UInt) = hash(fusiontrees(b), h) +Base.hash(b::FusionTreeBlock, h::UInt) = isempty(b) ? h : hash(b.uncoupled, hash(b.isdual, h)) + function Base.:(==)(f₁::FusionTree{I, N}, f₂::FusionTree{I, N}) where {I <: Sector, N} f₁.coupled == f₂.coupled || return false @inbounds for i in 1:N From cfd7bc2267293dbb526f1f403c733f452d9b8dc6 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 31 Aug 2026 08:24:50 -0400 Subject: [PATCH 3/3] Include first tree pair in FusionTreeBlock hash Hashing the first tree pair still covers the block's defining data (uncoupled, isdual), but additionally disambiguates the ad-hoc single-pair blocks constructed in planar_trace, which would otherwise all collide in the fstranspose LRU cache. Co-Authored-By: Claude Fable 5 --- src/fusiontrees/fusiontrees.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fusiontrees/fusiontrees.jl b/src/fusiontrees/fusiontrees.jl index ea22ce871..7b97223ec 100644 --- a/src/fusiontrees/fusiontrees.jl +++ b/src/fusiontrees/fusiontrees.jl @@ -214,7 +214,9 @@ function Base.hash(f::FusionTree{I}, h::UInt) where {I} end return h end -Base.hash(b::FusionTreeBlock, h::UInt) = isempty(b) ? h : hash(b.uncoupled, hash(b.isdual, h)) +# Hashing the first tree pair covers the block's defining data `(uncoupled, isdual)`, while +# also disambiguating the ad-hoc single-pair blocks constructed in `planar_trace` +Base.hash(b::FusionTreeBlock, h::UInt) = isempty(b) ? h : hash(first(fusiontrees(b)), h) function Base.:(==)(f₁::FusionTree{I, N}, f₂::FusionTree{I, N}) where {I <: Sector, N} f₁.coupled == f₂.coupled || return false