From b2f21ff631be8f348d178e67e1be2a255c9c0188 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 19 Nov 2024 20:29:18 -0500 Subject: [PATCH 1/7] Make braidingtensor behave --- src/tensors/braidingtensor.jl | 40 +++++++++++------------------------ 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/tensors/braidingtensor.jl b/src/tensors/braidingtensor.jl index 17406b6a2..13f3efe42 100644 --- a/src/tensors/braidingtensor.jl +++ b/src/tensors/braidingtensor.jl @@ -78,22 +78,19 @@ end throw(SectorMismatch()) end @inbounds begin - d = (dims(V2 ⊗ V1, f₁.uncoupled)..., dims(V1 ⊗ V2, f₂.uncoupled)...) + d = (dims(codomain(b), f₁.uncoupled)..., dims(domain(b), f₂.uncoupled)...) n1 = d[1] * d[2] n2 = d[3] * d[4] - data = storagetype(b)(undef, (n1, n2)) + data = sreshape(StridedView(Matrix{eltype(b)}(undef, n1, n2)), d) fill!(data, zero(eltype(b))) - a1, a2 = f₂.uncoupled - if f₁.uncoupled == (a2, a1) + if f₁.uncoupled == reverse(f₂.uncoupled) braiddict = artin_braid(f₂, 1; inv=b.adjoint) r = get(braiddict, f₁, zero(valtype(braiddict))) - si = 1 + d[1] * d[2] * d[3] - sj = d[1] + d[1] * d[2] - @inbounds for i in 1:d[1], j in 1:d[2] - data[(i - 1) * si + (j - 1) * sj + 1] = r + @inbounds for i in axes(data, 1), j in axes(data, 2) + data[i, j, j, i] = r end end - return sreshape(StridedView(data), d) + return data end end @inline function Base.getindex(b::BraidingTensor, ::Nothing, ::Nothing) @@ -104,25 +101,12 @@ end # efficient copy constructor Base.copy(b::BraidingTensor) = b -function Base.copy!(t::TensorMap, b::BraidingTensor) - space(t) == space(b) || throw(SectorMismatch()) - fill!(t, zero(scalartype(t))) - for (f₁, f₂) in fusiontrees(t) - data = t[f₁, f₂] - if sectortype(t) == Trivial - r = one(scalartype(t)) - else - a1, a2 = f₂.uncoupled - c = f₂.coupled - f₁.uncoupled == (a2, a1) || continue - braiddict = artin_braid(f₂, 1; inv=b.adjoint) - r = convert(scalartype(t), get(braiddict, f₁, zero(valtype(braiddict)))) - end - @inbounds for i in axes(data, 1), j in axes(data, 2) - data[i, j, j, i] = r - end +function Base.copy!(tdst::TensorMap, tsrc::BraidingTensor) + space(tdst) == space(tsrc) || throw(SectorMismatch()) + for (c, b) in blocks(tdst) + copy!(b, block(tsrc, c)) end - return t + return tdst end TensorMap(b::BraidingTensor) = copy!(similar(b), b) Base.convert(::Type{TensorMap}, b::BraidingTensor) = TensorMap(b) @@ -141,7 +125,7 @@ function block(b::BraidingTensor, s::Sector) data = fill!(data, zero(eltype(b))) - V1, V2 = domain(b) + V1, V2 = codomain(b) if sectortype(b) === Trivial d1, d2 = dim(V1), dim(V2) subblock = sreshape(StridedView(data), (d1, d2, d2, d1)) From daddd9ebff61f4a3a9ef6087ba4035a11d53c841 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 19 Nov 2024 20:29:32 -0500 Subject: [PATCH 2/7] fix `treebraider` --- src/tensors/treetransformers.jl | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/tensors/treetransformers.jl b/src/tensors/treetransformers.jl index 6caef06dd..afa94e664 100644 --- a/src/tensors/treetransformers.jl +++ b/src/tensors/treetransformers.jl @@ -69,8 +69,34 @@ function TreeTransformer(transform::Function, Vsrc::HomSpace{S}, end end +# braid is special because it has levels +const treebraidercache = LRU{Any,Any}(; maxsize=10^5) +const usetreebraidercache = Ref{Bool}(true) +@noinline function _get_treebraider(A, key) + d::A = get!(treebraidercache, key) do + return _treebraider(key) + end + return d +end +function _treebraider((Vdst, Vsrc, p, levels)) + fusiontreebraider(f1, f2) = braid(f1, f2, levels..., p...) + return TreeTransformer(fusiontreebraider, Vsrc, Vdst) +end +function treebraider(::AbstractTensorMap, ::AbstractTensorMap, p, levels) + return fusiontreetransform(f1, f2) = braid(f1, f2, levels..., p...) +end +function treebraider(tdst::TensorMap, tsrc::TensorMap, p, levels) + if usetreebraidercache[] + key = (space(tdst), space(tsrc), p, levels) + A = treetransformertype(space(tdst), space(tsrc)) + return _get_treebraider(A, key) + else + return _treebraider((space(tdst), space(tsrc), p, levels)) + end +end + for (transform, transformer) in - ((:permute, :permuter), (:braid, :braider), (:transpose, :transposer)) + ((:permute, :permuter), (:transpose, :transposer)) treetransformcache = Symbol("tree", transformer, "cache") usetreetransformcache = Symbol("usetree", transformer, "cache") treetransformer = Symbol("tree", transformer) From acaef58a6eccc86a50c68a9e70981db9529f1646 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 19 Nov 2024 20:29:41 -0500 Subject: [PATCH 3/7] expand BraidingTensor tests --- test/planar.jl | 67 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/test/planar.jl b/test/planar.jl index 0487404f6..8ffdac9df 100644 --- a/test/planar.jl +++ b/test/planar.jl @@ -30,22 +30,59 @@ function force_planar(tsrc::TensorMap{<:Any,<:GradedSpace}) return tdst end +Vtr = (ℂ^3, + (ℂ^2)', + ℂ^5, + ℂ^6, + (ℂ^7)') +VU₁ = (ℂ[U1Irrep](0 => 1, 1 => 2, -1 => 2), + ℂ[U1Irrep](0 => 3, 1 => 1, -1 => 1), + ℂ[U1Irrep](0 => 2, 1 => 2, -1 => 1)', + ℂ[U1Irrep](0 => 1, 1 => 2, -1 => 3), + ℂ[U1Irrep](0 => 1, 1 => 3, -1 => 3)') +VfU₁ = (ℂ[FermionNumber](0 => 1, 1 => 2, -1 => 2), + ℂ[FermionNumber](0 => 3, 1 => 1, -1 => 1), + ℂ[FermionNumber](0 => 2, 1 => 2, -1 => 1)', + ℂ[FermionNumber](0 => 1, 1 => 2, -1 => 3), + ℂ[FermionNumber](0 => 1, 1 => 3, -1 => 3)') +VfSU₂ = (ℂ[FermionSpin](0 => 3, 1 // 2 => 1), + ℂ[FermionSpin](0 => 2, 1 => 1), + ℂ[FermionSpin](1 // 2 => 1, 1 => 1)', + ℂ[FermionSpin](0 => 2, 1 // 2 => 2), + ℂ[FermionSpin](0 => 1, 1 // 2 => 1, 3 // 2 => 1)') +Vfib = (Vect[FibonacciAnyon](:I => 1, :τ => 2), + Vect[FibonacciAnyon](:I => 2, :τ => 1), + Vect[FibonacciAnyon](:I => 1, :τ => 1), + Vect[FibonacciAnyon](:I => 1, :τ => 1), + Vect[FibonacciAnyon](:I => 1, :τ => 1)) @testset "Braiding tensor" begin - V1 = ℂ^2 ⊗ ℂ^3 ← ℂ^3 ⊗ ℂ^2 - t1 = @constinferred BraidingTensor(V1) - @test space(t1) == V1 - @test codomain(t1) == codomain(V1) - @test domain(t1) == domain(V1) - @test scalartype(t1) == Float64 - @test storagetype(t1) == Vector{Float64} - t2 = @constinferred BraidingTensor{ComplexF64}(V1) - @test scalartype(t2) == ComplexF64 - @test storagetype(t2) == Vector{ComplexF64} - - V2 = ℂ^2 ⊗ ℂ^3 ← ℂ^2 ⊗ ℂ^3 - @test_throws SpaceMismatch BraidingTensor(V2) - - @test adjoint(t1) isa BraidingTensor + for V in (Vtr, VU₁, VfU₁, VfSU₂, Vfib) + V1 = V[1] ⊗ V[2] ← V[2] ⊗ V[1] + t1 = @constinferred BraidingTensor(V1) + @test space(t1) == V1 + @test codomain(t1) == codomain(V1) + @test domain(t1) == domain(V1) + @test scalartype(t1) == (isreal(sectortype(V1)) ? Float64 : ComplexF64) + @test storagetype(t1) == Vector{scalartype(t1)} + t2 = @constinferred BraidingTensor{ComplexF64}(V1) + @test scalartype(t2) == ComplexF64 + @test storagetype(t2) == Vector{ComplexF64} + + V2 = reverse(codomain(V1)) ← domain(V1) + @test_throws SpaceMismatch BraidingTensor(V2) + + @test adjoint(t1) isa BraidingTensor + + t3 = TensorMap(t2) + t4 = braid(id(storagetype(t2), domain(t2)), ((2, 1), (3, 4)), (1, 2, 3, 4)) + @test t1 ≈ t4 + for (c, b) in blocks(t1) + @test block(t1, c) ≈ b ≈ block(t3, c) + end + for (f1, f2) in fusiontrees(t1) + @test t1[f1, f2] ≈ t3[f1, f2] + end + end end @testset "planar methods" verbose = true begin From 21003c9d094266abfdc27999a08d9e1cf0af88f6 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 20 Nov 2024 07:04:49 -0500 Subject: [PATCH 4/7] Remove duplicate copy --- src/tensors/braidingtensor.jl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/tensors/braidingtensor.jl b/src/tensors/braidingtensor.jl index 13f3efe42..8b82ec8df 100644 --- a/src/tensors/braidingtensor.jl +++ b/src/tensors/braidingtensor.jl @@ -101,18 +101,9 @@ end # efficient copy constructor Base.copy(b::BraidingTensor) = b -function Base.copy!(tdst::TensorMap, tsrc::BraidingTensor) - space(tdst) == space(tsrc) || throw(SectorMismatch()) - for (c, b) in blocks(tdst) - copy!(b, block(tsrc, c)) - end - return tdst -end TensorMap(b::BraidingTensor) = copy!(similar(b), b) Base.convert(::Type{TensorMap}, b::BraidingTensor) = TensorMap(b) -# TODO: fix this! -# block(b::BraidingTensor, s::Sector) = block(TensorMap(b), s) function block(b::BraidingTensor, s::Sector) sectortype(b) == typeof(s) || throw(SectorMismatch()) From 1789710d2a28d1418e62a04d5c12e8bbf8a57d0f Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 20 Nov 2024 07:07:09 -0500 Subject: [PATCH 5/7] rename `V1 -> W` --- test/planar.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/planar.jl b/test/planar.jl index 8ffdac9df..84e6afc99 100644 --- a/test/planar.jl +++ b/test/planar.jl @@ -57,23 +57,23 @@ Vfib = (Vect[FibonacciAnyon](:I => 1, :τ => 2), Vect[FibonacciAnyon](:I => 1, :τ => 1)) @testset "Braiding tensor" begin for V in (Vtr, VU₁, VfU₁, VfSU₂, Vfib) - V1 = V[1] ⊗ V[2] ← V[2] ⊗ V[1] - t1 = @constinferred BraidingTensor(V1) - @test space(t1) == V1 - @test codomain(t1) == codomain(V1) - @test domain(t1) == domain(V1) - @test scalartype(t1) == (isreal(sectortype(V1)) ? Float64 : ComplexF64) + W = V[1] ⊗ V[2] ← V[2] ⊗ V[1] + t1 = @constinferred BraidingTensor(W) + @test space(t1) == W + @test codomain(t1) == codomain(W) + @test domain(t1) == domain(W) + @test scalartype(t1) == (isreal(sectortype(W)) ? Float64 : ComplexF64) @test storagetype(t1) == Vector{scalartype(t1)} - t2 = @constinferred BraidingTensor{ComplexF64}(V1) + t2 = @constinferred BraidingTensor{ComplexF64}(W) @test scalartype(t2) == ComplexF64 @test storagetype(t2) == Vector{ComplexF64} - V2 = reverse(codomain(V1)) ← domain(V1) + V2 = reverse(codomain(W)) ← domain(V1) @test_throws SpaceMismatch BraidingTensor(V2) @test adjoint(t1) isa BraidingTensor - t3 = TensorMap(t2) + t3 = @inferred TensorMap(t2) t4 = braid(id(storagetype(t2), domain(t2)), ((2, 1), (3, 4)), (1, 2, 3, 4)) @test t1 ≈ t4 for (c, b) in blocks(t1) From cf3ce683ad262b1be1f48806055b0c2cd68cf662 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 20 Nov 2024 08:34:58 -0500 Subject: [PATCH 6/7] Apply suggestions from code review --- test/planar.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/planar.jl b/test/planar.jl index 84e6afc99..c9e1c3c47 100644 --- a/test/planar.jl +++ b/test/planar.jl @@ -68,8 +68,8 @@ Vfib = (Vect[FibonacciAnyon](:I => 1, :τ => 2), @test scalartype(t2) == ComplexF64 @test storagetype(t2) == Vector{ComplexF64} - V2 = reverse(codomain(W)) ← domain(V1) - @test_throws SpaceMismatch BraidingTensor(V2) + W2 = reverse(codomain(W)) ← domain(W) + @test_throws SpaceMismatch BraidingTensor(W2) @test adjoint(t1) isa BraidingTensor From 1b7e928ea43d472095ba8ad2b93c9b4429d88516 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 20 Nov 2024 09:34:36 -0500 Subject: [PATCH 7/7] Remove stackoverflow --- src/tensors/braidingtensor.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tensors/braidingtensor.jl b/src/tensors/braidingtensor.jl index 8b82ec8df..01c0f94cb 100644 --- a/src/tensors/braidingtensor.jl +++ b/src/tensors/braidingtensor.jl @@ -149,8 +149,6 @@ function block(b::BraidingTensor, s::Sector) return data end -blocks(b::BraidingTensor) = blocks(TensorMap(b)) - # Index manipulations # ------------------- has_shared_permute(t::BraidingTensor, ::Index2Tuple) = false