Skip to content

Commit dbea001

Browse files
committed
get double fusion tree tests working for GenericUnit
1 parent f53b0ef commit dbea001

File tree

1 file changed

+163
-150
lines changed

1 file changed

+163
-150
lines changed

test/symmetries/fusiontrees.jl

Lines changed: 163 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -403,13 +403,12 @@ using .TestSetup
403403
end
404404
end
405405

406-
if isa(UnitStyle(I), SimpleUnit) # could get these to work for GenericUnit, but somewhat hardcoded
407-
if I <: ProductSector
408-
N = 3
409-
else
410-
N = 4
411-
end
412-
406+
if I <: ProductSector
407+
N = 3
408+
else
409+
N = 4
410+
end
411+
if isa(UnitStyle(I), SimpleUnit)
413412
out = random_fusion(I, N)
414413
numtrees = count(n -> true, fusiontrees((out..., map(dual, out)...)))
415414
while !(0 < numtrees < 100)
@@ -419,112 +418,87 @@ using .TestSetup
419418
incoming = rand(collect((out...)))
420419
f1 = rand(collect(fusiontrees(out, incoming, ntuple(n -> rand(Bool), N))))
421420
f2 = rand(collect(fusiontrees(out[randperm(N)], incoming, ntuple(n -> rand(Bool), N))))
422-
@testset "Double fusion tree $Istr: repartitioning" begin
423-
for n in 0:(2 * N)
424-
d = @constinferred TK.repartition(f1, f2, $n)
425-
@test dim(incoming)
426-
sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d)
427-
d2 = Dict{typeof((f1, f2)), valtype(d)}()
428-
for ((f1′, f2′), coeff) in d
429-
for ((f1′′, f2′′), coeff2) in TK.repartition(f1′, f2′, N)
430-
d2[(f1′′, f2′′)] = get(d2, (f1′′, f2′′), zero(coeff)) + coeff2 * coeff
431-
end
432-
end
433-
for ((f1′, f2′), coeff2) in d2
434-
if f1 == f1′ && f2 == f2′
435-
@test coeff2 1
436-
else
437-
@test isapprox(coeff2, 0; atol = 1.0e-12, rtol = 1.0e-12)
438-
end
421+
else
422+
out = random_fusion(I, N)
423+
out2 = random_fusion(I, N)
424+
tp = (out...)
425+
tp2 = (out2...)
426+
while isempty(intersect(tp, tp2)) # guarantee fusion to same coloring
427+
out2 = random_fusion(I, N)
428+
tp2 = (out2...)
429+
end
430+
@test_throws ArgumentError fusiontrees((out..., map(dual, out)...))
431+
incoming = rand(collect(intersect(tp, tp2)))
432+
f1 = rand(collect(fusiontrees(out, incoming, ntuple(n -> rand(Bool), N))))
433+
f2 = rand(collect(fusiontrees(out2, incoming, ntuple(n -> rand(Bool), N)))) # no permuting
434+
end
435+
436+
@testset "Double fusion tree $Istr: repartitioning" begin
437+
for n in 0:(2 * N)
438+
d = @constinferred TK.repartition(f1, f2, $n)
439+
@test dim(incoming)
440+
sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d)
441+
d2 = Dict{typeof((f1, f2)), valtype(d)}()
442+
for ((f1′, f2′), coeff) in d
443+
for ((f1′′, f2′′), coeff2) in TK.repartition(f1′, f2′, N)
444+
d2[(f1′′, f2′′)] = get(d2, (f1′′, f2′′), zero(coeff)) + coeff2 * coeff
439445
end
440-
if (BraidingStyle(I) isa Bosonic) && hasfusiontensor(I)
441-
Af1 = convert(Array, f1)
442-
Af2 = permutedims(convert(Array, f2), [N:-1:1; N + 1])
443-
sz1 = size(Af1)
444-
sz2 = size(Af2)
445-
d1 = prod(sz1[1:(end - 1)])
446-
d2 = prod(sz2[1:(end - 1)])
447-
dc = sz1[end]
448-
A = reshape(
449-
reshape(Af1, (d1, dc)) * reshape(Af2, (d2, dc))',
450-
(sz1[1:(end - 1)]..., sz2[1:(end - 1)]...)
451-
)
452-
A2 = zero(A)
453-
for ((f1′, f2′), coeff) in d
454-
Af1′ = convert(Array, f1′)
455-
Af2′ = permutedims(convert(Array, f2′), [(2N - n):-1:1; 2N - n + 1])
456-
sz1′ = size(Af1′)
457-
sz2′ = size(Af2′)
458-
d1′ = prod(sz1′[1:(end - 1)])
459-
d2′ = prod(sz2′[1:(end - 1)])
460-
dc′ = sz1′[end]
461-
A2 += coeff *
462-
reshape(
463-
reshape(Af1′, (d1′, dc′)) * reshape(Af2′, (d2′, dc′))',
464-
(sz1′[1:(end - 1)]..., sz2′[1:(end - 1)]...)
465-
)
466-
end
467-
@test A A2
446+
end
447+
for ((f1′, f2′), coeff2) in d2
448+
if f1 == f1′ && f2 == f2′
449+
@test coeff2 1
450+
else
451+
@test isapprox(coeff2, 0; atol = 1.0e-12, rtol = 1.0e-12)
468452
end
469453
end
470-
end
471-
@testset "Double fusion tree $Istr: permutation" begin
472-
if BraidingStyle(I) isa SymmetricBraiding
473-
for n in 0:(2N)
474-
p = (randperm(2 * N)...,)
475-
p1, p2 = p[1:n], p[(n + 1):(2N)]
476-
ip = invperm(p)
477-
ip1, ip2 = ip[1:N], ip[(N + 1):(2N)]
478-
479-
d = @constinferred TK.permute(f1, f2, p1, p2)
480-
@test dim(incoming)
481-
sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d)
482-
d2 = Dict{typeof((f1, f2)), valtype(d)}()
483-
for ((f1′, f2′), coeff) in d
484-
d′ = TK.permute(f1′, f2′, ip1, ip2)
485-
for ((f1′′, f2′′), coeff2) in d′
486-
d2[(f1′′, f2′′)] = get(d2, (f1′′, f2′′), zero(coeff)) +
487-
coeff2 * coeff
488-
end
489-
end
490-
for ((f1′, f2′), coeff2) in d2
491-
if f1 == f1′ && f2 == f2′
492-
@test coeff2 1
493-
else
494-
@test abs(coeff2) < 1.0e-12
495-
end
496-
end
497-
498-
if (BraidingStyle(I) isa Bosonic) && hasfusiontensor(I)
499-
A = convert(Array, (f1, f2))
500-
Ap = permutedims(A, (p1..., p2...))
501-
A2 = zero(Ap)
502-
for ((f1′, f2′), coeff) in d
503-
A2 .+= coeff .* convert(Array, (f1′, f2′))
504-
end
505-
@test Ap A2
506-
end
454+
if (BraidingStyle(I) isa Bosonic) && hasfusiontensor(I)
455+
Af1 = convert(Array, f1)
456+
Af2 = permutedims(convert(Array, f2), [N:-1:1; N + 1])
457+
sz1 = size(Af1)
458+
sz2 = size(Af2)
459+
d1 = prod(sz1[1:(end - 1)])
460+
d2 = prod(sz2[1:(end - 1)])
461+
dc = sz1[end]
462+
A = reshape(
463+
reshape(Af1, (d1, dc)) * reshape(Af2, (d2, dc))',
464+
(sz1[1:(end - 1)]..., sz2[1:(end - 1)]...)
465+
)
466+
A2 = zero(A)
467+
for ((f1′, f2′), coeff) in d
468+
Af1′ = convert(Array, f1′)
469+
Af2′ = permutedims(convert(Array, f2′), [(2N - n):-1:1; 2N - n + 1])
470+
sz1′ = size(Af1′)
471+
sz2′ = size(Af2′)
472+
d1′ = prod(sz1′[1:(end - 1)])
473+
d2′ = prod(sz2′[1:(end - 1)])
474+
dc′ = sz1′[end]
475+
A2 += coeff *
476+
reshape(
477+
reshape(Af1′, (d1′, dc′)) * reshape(Af2′, (d2′, dc′))',
478+
(sz1′[1:(end - 1)]..., sz2′[1:(end - 1)]...)
479+
)
507480
end
481+
@test A A2
508482
end
509483
end
510-
@testset "Double fusion tree $Istr: transposition" begin
484+
end
485+
@testset "Double fusion tree $Istr: permutation" begin
486+
if BraidingStyle(I) isa SymmetricBraiding
511487
for n in 0:(2N)
512-
i0 = rand(1:(2N))
513-
p = mod1.(i0 .+ (1:(2N)), 2N)
514-
ip = mod1.(-i0 .+ (1:(2N)), 2N)
515-
p′ = tuple(getindex.(Ref(vcat(1:N, (2N):-1:(N + 1))), p)...)
516-
p1, p2 = p′[1:n], p′[(2N):-1:(n + 1)]
517-
ip′ = tuple(getindex.(Ref(vcat(1:n, (2N):-1:(n + 1))), ip)...)
518-
ip1, ip2 = ip′[1:N], ip′[(2N):-1:(N + 1)]
519-
520-
d = @constinferred transpose(f1, f2, p1, p2)
488+
p = (randperm(2 * N)...,)
489+
p1, p2 = p[1:n], p[(n + 1):(2N)]
490+
ip = invperm(p)
491+
ip1, ip2 = ip[1:N], ip[(N + 1):(2N)]
492+
493+
d = @constinferred TK.permute(f1, f2, p1, p2)
521494
@test dim(incoming)
522495
sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d)
523496
d2 = Dict{typeof((f1, f2)), valtype(d)}()
524497
for ((f1′, f2′), coeff) in d
525-
d′ = transpose(f1′, f2′, ip1, ip2)
498+
d′ = TK.permute(f1′, f2′, ip1, ip2)
526499
for ((f1′′, f2′′), coeff2) in d′
527-
d2[(f1′′, f2′′)] = get(d2, (f1′′, f2′′), zero(coeff)) + coeff2 * coeff
500+
d2[(f1′′, f2′′)] = get(d2, (f1′′, f2′′), zero(coeff)) +
501+
coeff2 * coeff
528502
end
529503
end
530504
for ((f1′, f2′), coeff2) in d2
@@ -535,69 +509,108 @@ using .TestSetup
535509
end
536510
end
537511

538-
if BraidingStyle(I) isa Bosonic
539-
d3 = permute(f1, f2, p1, p2)
540-
for (f1′, f2′) in union(keys(d), keys(d3))
541-
coeff1 = get(d, (f1′, f2′), zero(valtype(d)))
542-
coeff3 = get(d3, (f1′, f2′), zero(valtype(d3)))
543-
@test isapprox(coeff1, coeff3; atol = 1.0e-12)
544-
end
545-
end
546-
547512
if (BraidingStyle(I) isa Bosonic) && hasfusiontensor(I)
548-
Af1 = convert(Array, f1)
549-
Af2 = convert(Array, f2)
550-
sz1 = size(Af1)
551-
sz2 = size(Af2)
552-
d1 = prod(sz1[1:(end - 1)])
553-
d2 = prod(sz2[1:(end - 1)])
554-
dc = sz1[end]
555-
A = reshape(
556-
reshape(Af1, (d1, dc)) * reshape(Af2, (d2, dc))',
557-
(sz1[1:(end - 1)]..., sz2[1:(end - 1)]...)
558-
)
513+
A = convert(Array, (f1, f2))
559514
Ap = permutedims(A, (p1..., p2...))
560515
A2 = zero(Ap)
561516
for ((f1′, f2′), coeff) in d
562-
Af1′ = convert(Array, f1′)
563-
Af2′ = convert(Array, f2′)
564-
sz1′ = size(Af1′)
565-
sz2′ = size(Af2′)
566-
d1′ = prod(sz1′[1:(end - 1)])
567-
d2′ = prod(sz2′[1:(end - 1)])
568-
dc′ = sz1′[end]
569-
A2 += coeff * reshape(
570-
reshape(Af1′, (d1′, dc′)) *
571-
reshape(Af2′, (d2′, dc′))',
572-
(sz1′[1:(end - 1)]..., sz2′[1:(end - 1)]...)
573-
)
517+
A2 .+= coeff .* convert(Array, (f1′, f2′))
574518
end
575519
@test Ap A2
576520
end
577521
end
578522
end
579-
@testset "Double fusion tree $Istr: planar trace" begin
580-
d1 = transpose(f1, f1, (N + 1, 1:N..., ((2N):-1:(N + 3))...), (N + 2,))
581-
f1front, = TK.split(f1, N - 1)
582-
T = sectorscalartype(I)
583-
d2 = Dict{typeof((f1front, f1front)), T}()
584-
for ((f1′, f2′), coeff′) in d1
585-
for ((f1′′, f2′′), coeff′′) in
586-
TK.planar_trace(
587-
f1′, f2′, (2:N...,), (1, ((2N):-1:(N + 3))...), (N + 1,),
588-
(N + 2,)
589-
)
590-
coeff = coeff′ * coeff′′
591-
d2[(f1′′, f2′′)] = get(d2, (f1′′, f2′′), zero(coeff)) + coeff
523+
end
524+
@testset "Double fusion tree $Istr: transposition" begin
525+
for n in 0:(2N)
526+
i0 = rand(1:(2N))
527+
p = mod1.(i0 .+ (1:(2N)), 2N)
528+
ip = mod1.(-i0 .+ (1:(2N)), 2N)
529+
p′ = tuple(getindex.(Ref(vcat(1:N, (2N):-1:(N + 1))), p)...)
530+
p1, p2 = p′[1:n], p′[(2N):-1:(n + 1)]
531+
ip′ = tuple(getindex.(Ref(vcat(1:n, (2N):-1:(n + 1))), ip)...)
532+
ip1, ip2 = ip′[1:N], ip′[(2N):-1:(N + 1)]
533+
534+
d = @constinferred transpose(f1, f2, p1, p2)
535+
@test dim(incoming)
536+
sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d)
537+
d2 = Dict{typeof((f1, f2)), valtype(d)}()
538+
for ((f1′, f2′), coeff) in d
539+
d′ = transpose(f1′, f2′, ip1, ip2)
540+
for ((f1′′, f2′′), coeff2) in d′
541+
d2[(f1′′, f2′′)] = get(d2, (f1′′, f2′′), zero(coeff)) + coeff2 * coeff
592542
end
593543
end
594-
for ((f1_, f2_), coeff) in d2
595-
if (f1_, f2_) == (f1front, f1front)
596-
@test coeff dim(f1.coupled) / dim(f1front.coupled)
544+
for ((f1′, f2′), coeff2) in d2
545+
if f1 == f1′ && f2 == f2′
546+
@test coeff2 1
597547
else
598-
@test abs(coeff) < 1.0e-12
548+
@test abs(coeff2) < 1.0e-12
599549
end
600550
end
551+
552+
if BraidingStyle(I) isa Bosonic
553+
d3 = permute(f1, f2, p1, p2)
554+
for (f1′, f2′) in union(keys(d), keys(d3))
555+
coeff1 = get(d, (f1′, f2′), zero(valtype(d)))
556+
coeff3 = get(d3, (f1′, f2′), zero(valtype(d3)))
557+
@test isapprox(coeff1, coeff3; atol = 1.0e-12)
558+
end
559+
end
560+
561+
if (BraidingStyle(I) isa Bosonic) && hasfusiontensor(I)
562+
Af1 = convert(Array, f1)
563+
Af2 = convert(Array, f2)
564+
sz1 = size(Af1)
565+
sz2 = size(Af2)
566+
d1 = prod(sz1[1:(end - 1)])
567+
d2 = prod(sz2[1:(end - 1)])
568+
dc = sz1[end]
569+
A = reshape(
570+
reshape(Af1, (d1, dc)) * reshape(Af2, (d2, dc))',
571+
(sz1[1:(end - 1)]..., sz2[1:(end - 1)]...)
572+
)
573+
Ap = permutedims(A, (p1..., p2...))
574+
A2 = zero(Ap)
575+
for ((f1′, f2′), coeff) in d
576+
Af1′ = convert(Array, f1′)
577+
Af2′ = convert(Array, f2′)
578+
sz1′ = size(Af1′)
579+
sz2′ = size(Af2′)
580+
d1′ = prod(sz1′[1:(end - 1)])
581+
d2′ = prod(sz2′[1:(end - 1)])
582+
dc′ = sz1′[end]
583+
A2 += coeff * reshape(
584+
reshape(Af1′, (d1′, dc′)) *
585+
reshape(Af2′, (d2′, dc′))',
586+
(sz1′[1:(end - 1)]..., sz2′[1:(end - 1)]...)
587+
)
588+
end
589+
@test Ap A2
590+
end
591+
end
592+
end
593+
@testset "Double fusion tree $Istr: planar trace" begin
594+
d1 = transpose(f1, f1, (N + 1, 1:N..., ((2N):-1:(N + 3))...), (N + 2,))
595+
f1front, = TK.split(f1, N - 1)
596+
T = sectorscalartype(I)
597+
d2 = Dict{typeof((f1front, f1front)), T}()
598+
for ((f1′, f2′), coeff′) in d1
599+
for ((f1′′, f2′′), coeff′′) in
600+
TK.planar_trace(
601+
f1′, f2′, (2:N...,), (1, ((2N):-1:(N + 3))...), (N + 1,),
602+
(N + 2,)
603+
)
604+
coeff = coeff′ * coeff′′
605+
d2[(f1′′, f2′′)] = get(d2, (f1′′, f2′′), zero(coeff)) + coeff
606+
end
607+
end
608+
for ((f1_, f2_), coeff) in d2
609+
if (f1_, f2_) == (f1front, f1front)
610+
@test coeff dim(f1.coupled) / dim(f1front.coupled)
611+
else
612+
@test abs(coeff) < 1.0e-12
613+
end
601614
end
602615
end
603616
TK.empty_globalcaches!()

0 commit comments

Comments
 (0)