@@ -59,7 +59,6 @@ function treeindex_map(fs::FusionTreeBlock)
5959 return fusiontreedict(I)(f => ind for (ind, f) in enumerate(fusiontrees(fs)))
6060end
6161
62-
6362# Manipulations
6463# -------------
6564function transformation_matrix(transform, dst:: FusionTreeBlock{I} ,
@@ -451,10 +450,128 @@ function artin_braid(src::FusionTreeBlock{I,N,0}, i; inv::Bool=false) where {I,N
451450 isdual′ = TupleTools. setindex(isdual′, isdual[i + 1 ], i)
452451 dst = FusionTreeBlock{I}((uncoupled′, ()), (isdual′, ()))
453452
454- # TODO : do we want to rewrite `artin_braid` to take double trees instead?
455- U = transformation_matrix(dst, src) do (f₁, f₂)
456- return ((f₁′, f₂) => c for (f₁′, c) in artin_braid(f₁, i; inv))
453+ indexmap = treeindex_map(dst)
454+ U = zeros(sectorscalartype(I), length(dst), length(src))
455+
456+ for (col, (f, f₂)) in enumerate(fusiontrees(src))
457+ a, b = uncoupled[i], uncoupled[i + 1 ]
458+ uncoupled′ = TupleTools. setindex(uncoupled, b, i)
459+ uncoupled′ = TupleTools. setindex(uncoupled′, a, i + 1 )
460+ coupled′ = f. coupled
461+ isdual′ = TupleTools. setindex(f. isdual, f. isdual[i], i + 1 )
462+ isdual′ = TupleTools. setindex(isdual′, f. isdual[i + 1 ], i)
463+ inner = f. innerlines
464+ inner_extended = (uncoupled[1 ], inner... , coupled′)
465+ vertices = f. vertices
466+ oneT = one(sectorscalartype(I))
467+
468+ if isone(uncoupled[i]) || isone(uncoupled[i + 1 ])
469+ # braiding with trivial sector: simple and always possible
470+ inner′ = inner
471+ vertices′ = vertices
472+ if i > 1 # we also need to alter innerlines and vertices
473+ inner′ = TupleTools. setindex(inner,
474+ inner_extended[isone(a) ? (i + 1 ) : (i - 1 )],
475+ i - 1 )
476+ vertices′ = TupleTools. setindex(vertices′, vertices[i], i - 1 )
477+ vertices′ = TupleTools. setindex(vertices′, vertices[i - 1 ], i)
478+ end
479+ f′ = FusionTree{I}(uncoupled′, coupled′, isdual′, inner′, vertices′)
480+ row = indexmap[(f′, f₂)]
481+ @inbounds U[row, col] = oneT
482+ continue
483+ end
484+
485+ BraidingStyle(I) isa NoBraiding &&
486+ throw(SectorMismatch(" Cannot braid sectors $(uncoupled[i]) and $(uncoupled[i + 1 ]) " ))
487+
488+ if i == 1
489+ c = N > 2 ? inner[1 ] : coupled′
490+ if FusionStyle(I) isa MultiplicityFreeFusion
491+ R = oftype(oneT, (inv ? conj(Rsymbol(b, a, c)) : Rsymbol(a, b, c)))
492+ f′ = FusionTree{I}(uncoupled′, coupled′, isdual′, inner, vertices)
493+ row = indexmap[(f′, f₂)]
494+ @inbounds U[row, col] = R
495+ else # GenericFusion
496+ μ = vertices[1 ]
497+ Rmat = inv ? Rsymbol(b, a, c)' : Rsymbol(a, b, c)
498+ local newtrees
499+ for ν in axes(Rmat, 2 )
500+ R = oftype(oneT, Rmat[μ, ν])
501+ iszero(R) && continue
502+ vertices′ = TupleTools. setindex(vertices, ν, 1 )
503+ f′ = FusionTree{I}(uncoupled′, coupled′, isdual′, inner, vertices′)
504+ row = indexmap[(f′, f₂)]
505+ @inbounds U[row, col] = R
506+ end
507+ end
508+ continue
509+ end
510+ # case i > 1: other naming convention
511+ b = uncoupled[i]
512+ d = uncoupled[i + 1 ]
513+ a = inner_extended[i - 1 ]
514+ c = inner_extended[i]
515+ e = inner_extended[i + 1 ]
516+ if FusionStyle(I) isa UniqueFusion
517+ c′ = first(a ⊗ d)
518+ coeff = oftype(oneT,
519+ if inv
520+ conj(Rsymbol(d, c, e) * Fsymbol(d, a, b, e, c′, c)) *
521+ Rsymbol(d, a, c′)
522+ else
523+ Rsymbol(c, d, e) *
524+ conj(Fsymbol(d, a, b, e, c′, c) * Rsymbol(a, d, c′))
525+ end )
526+ inner′ = TupleTools. setindex(inner, c′, i - 1 )
527+ f′ = FusionTree{I}(uncoupled′, coupled′, isdual′, inner′)
528+ row = indexmap[(f′, f₂)]
529+ @inbounds U[row, col] = coeff
530+ elseif FusionStyle(I) isa SimpleFusion
531+ cs = collect(I, intersect(a ⊗ d, e ⊗ conj(b)))
532+ for c′ in cs
533+ coeff = oftype(oneT,
534+ if inv
535+ conj(Rsymbol(d, c, e) * Fsymbol(d, a, b, e, c′, c)) *
536+ Rsymbol(d, a, c′)
537+ else
538+ Rsymbol(c, d, e) *
539+ conj(Fsymbol(d, a, b, e, c′, c) * Rsymbol(a, d, c′))
540+ end )
541+ iszero(coeff) && continue
542+ inner′ = TupleTools. setindex(inner, c′, i - 1 )
543+ f′ = FusionTree{I}(uncoupled′, coupled′, isdual′, inner′)
544+ row = indexmap[(f′, f₂)]
545+ @inbounds U[row, col] = coeff
546+ end
547+ else # GenericFusion
548+ cs = collect(I, intersect(a ⊗ d, e ⊗ conj(b)))
549+ for c′ in cs
550+ Rmat1 = inv ? Rsymbol(d, c, e)' : Rsymbol(c, d, e)
551+ Rmat2 = inv ? Rsymbol(d, a, c′)' : Rsymbol(a, d, c′)
552+ Fmat = Fsymbol(d, a, b, e, c′, c)
553+ μ = vertices[i - 1 ]
554+ ν = vertices[i]
555+ for σ in 1 : Nsymbol(a, d, c′)
556+ for λ in 1 : Nsymbol(c′, b, e)
557+ coeff = zero(oneT)
558+ for ρ in 1 : Nsymbol(d, c, e), κ in 1 : Nsymbol(d, a, c′)
559+ coeff += Rmat1[ν, ρ] * conj(Fmat[κ, λ, μ, ρ]) *
560+ conj(Rmat2[σ, κ])
561+ end
562+ iszero(coeff) && continue
563+ vertices′ = TupleTools. setindex(vertices, σ, i - 1 )
564+ vertices′ = TupleTools. setindex(vertices′, λ, i)
565+ inner′ = TupleTools. setindex(inner, c′, i - 1 )
566+ f′ = FusionTree{I}(uncoupled′, coupled′, isdual′, inner′, vertices′)
567+ row = indexmap[(f′, f₂)]
568+ @inbounds U[row, col] = coeff
569+ end
570+ end
571+ end
572+ end
457573 end
574+
458575 return dst, U
459576end
460577
0 commit comments