From 5473e0f400eb159f2b5634bd6f499a04279cecf5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 24 Feb 2025 11:43:45 +0100 Subject: [PATCH 001/206] define leftone and rightone of BimoduleSector --- src/bimodulesector.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 71901a5..dc99fac 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -127,6 +127,14 @@ function Base.one(a::BimoduleSector) return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) end +function leftone(a::BimoduleSector) + return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) +end + +function rightone(a::BimoduleSector) + return A4Object(a.j, a.j, _get_dual_cache(typeof(a))[a.j][1]) +end + function Base.conj(a::BimoduleSector) a.i == a.j || error("don't know how to define dual for modules") return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][2][a.label]) From 85541aa40f9aa5cadb0edf998a6c8f0f8a01b988 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 24 Feb 2025 12:05:58 +0100 Subject: [PATCH 002/206] make left/rightone a new method of TensorKitSectors left/rightone --- src/bimodulesector.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index dc99fac..78bc3b4 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -127,11 +127,11 @@ function Base.one(a::BimoduleSector) return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) end -function leftone(a::BimoduleSector) +function TensorKitSectors.leftone(a::BimoduleSector) return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) end -function rightone(a::BimoduleSector) +function TensorKitSectors.rightone(a::BimoduleSector) return A4Object(a.j, a.j, _get_dual_cache(typeof(a))[a.j][1]) end From cf06437c94f9363a5624e42356f3e1c39ff06208 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 24 Feb 2025 11:43:45 +0100 Subject: [PATCH 003/206] define leftone and rightone of BimoduleSector --- src/bimodulesector.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 9e7fe19..7310dae 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -127,6 +127,14 @@ function Base.one(a::BimoduleSector) return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) end +function leftone(a::BimoduleSector) + return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) +end + +function rightone(a::BimoduleSector) + return A4Object(a.j, a.j, _get_dual_cache(typeof(a))[a.j][1]) +end + function Base.conj(a::BimoduleSector) a.i == a.j || error("don't know how to define dual for modules") return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][2][a.label]) From 4390d8ded80decb88c2a592c8778586a1b69499e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 24 Feb 2025 12:05:58 +0100 Subject: [PATCH 004/206] make left/rightone a new method of TensorKitSectors left/rightone --- src/bimodulesector.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 7310dae..8f37fc3 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -127,11 +127,11 @@ function Base.one(a::BimoduleSector) return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) end -function leftone(a::BimoduleSector) +function TensorKitSectors.leftone(a::BimoduleSector) return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) end -function rightone(a::BimoduleSector) +function TensorKitSectors.rightone(a::BimoduleSector) return A4Object(a.j, a.j, _get_dual_cache(typeof(a))[a.j][1]) end From 09acafc1e0c641537465889f88e73d3b3567ec75 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 10 Mar 2025 15:31:47 +0100 Subject: [PATCH 005/206] add tests --- test/localtests.jl | 20 ++++++++++++++++++++ test/test_A4.jl | 6 ++++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 test/localtests.jl diff --git a/test/localtests.jl b/test/localtests.jl new file mode 100644 index 0000000..492e1b9 --- /dev/null +++ b/test/localtests.jl @@ -0,0 +1,20 @@ +using TensorKitSectors +using .MultiTensorKit +using Revise + +testobj = A4Object(1,1,1) # fusion cat object +unit = one(testobj) +collect(testobjβŠ—unit) +@assert unit == leftone(testobj) == rightone(testobj) + +testobj2 = A4Object(2,2,1) +unit2 = one(testobj2) +collect(testobj2βŠ—unit2) +@assert unit2 == leftone(testobj2) == rightone(testobj2) + +testmodobj = A4Object(1,2,1) +one(testmodobj) +leftone(testmodobj) +rightone(testmodobj) + +Fsymbol(testobj, testobj, testobj, testobj, testobj, testobj) diff --git a/test/test_A4.jl b/test/test_A4.jl index 696ca5b..7c07249 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -19,8 +19,8 @@ end @test @constinferred(hash(s[1])) == hash(deepcopy(s[1])) @test isone(@constinferred(one(s[1]))) @constinferred dual(s[1]) - @constinferred dim(s[1]) - @constinferred frobeniusschur(s[1]) + @constinferred dim(s[1]) # problem with this and 3 below + @constinferred frobeniusschur(s[1]) @constinferred Bsymbol(s...) @constinferred Fsymbol(s..., s...) end @@ -52,3 +52,5 @@ end end end end + +#TODO: add tests for module categories \ No newline at end of file From 6cb34fa3debe1109bdf49001aac7e4f884beb4eb Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 10 Mar 2025 15:32:30 +0100 Subject: [PATCH 006/206] test reading data from txt --- Project.toml | 1 + src/MultiTensorKit.jl | 1 + src/bimodulesector.jl | 52 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index a542085..1c369bb 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "0.1.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 34d66bc..1134ca4 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -3,6 +3,7 @@ module MultiTensorKit export BimoduleSector, A4Object using JSON3 +using DelimitedFiles using Artifacts using TensorKitSectors diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 8f37fc3..9d9e411 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -4,7 +4,13 @@ struct BimoduleSector{Name} <: Sector label::Int end BimoduleSector{Name}(data::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(data...) +#TODO: place bound on what BimoduleSectors can be made +# currently you can define A4Object(anyint, anyint, anyint) const A4Object = BimoduleSector{:A4} +# function A4Object(i::Int, j::Int, label::Int) +# i <= 12 && j <= 12 || throw(DomainError("object outside the matrix")) +# return BimoduleSector{A4Object}(i, j, label) +# end # Utility implementations # ----------------------- @@ -146,6 +152,7 @@ function extract_Fsymbol(::Type{A4Object}) @assert isfile(filename) "cannot find $filename" json_string = read(filename, String) Farray_part = copy(JSON3.read(json_string)) + @show Farray_part return map(enumerate(Farray_part[Symbol(i)])) do (I, x) j, k, l = Tuple(CartesianIndices((12, 12, 12))[I]) y = Dict{NTuple{6,Int},Array{ComplexF64,4}}() @@ -159,6 +166,49 @@ function extract_Fsymbol(::Type{A4Object}) Nsymbol(e_ob, c_ob, d_ob), Nsymbol(b_ob, c_ob, f_ob), Nsymbol(a_ob, f_ob, d_ob))) + #@show size(result), a_ob, b_ob, c_ob, d_ob, e_ob, f_ob, v + #@show result, v + s1 = length(result) + s2 = length(v) + @assert s1 == s2 "$s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $v, $result" + map!(result, reshape(v, size(result))) do cmplxdict + return complex(cmplxdict[:re], cmplxdict[:im]) + end + + y[(a, b, c, d, e, f)] = result + end + end + end +end + +function extract_Fsymbol2(::Type{A4Object}) + return mapreduce((x, y) -> cat(x, y; dims=1), 1:12) do i + filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") + filename2 = joinpath(artifact_path, "A4", "Fsymbol_$i.json") + @assert isfile(filename) "cannot find $filename" + json_string = read(filename2, String) + txt_string = read(filename, String) + Farray_part = copy(readdlm(txt_string)) + Farray_part2 = copy(JSON3.read(json_string)) + @assert F_array_part == Farray_part2 + return map(enumerate(Farray_part[Symbol(i)])) do (I, x) + j, k, l = Tuple(CartesianIndices((12, 12, 12))[I]) + y = Dict{NTuple{6,Int},Array{ComplexF64,4}}() + for (key, v) in x + a, b, c, d, e, f = parse.(Int, split(string(key)[2:(end - 1)], ", ")) + a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), + (k, l, c), (i, l, d), + (i, k, e), (j, l, f))) + result = Array{ComplexF64,4}(undef, + (Nsymbol(a_ob, b_ob, e_ob), + Nsymbol(e_ob, c_ob, d_ob), + Nsymbol(b_ob, c_ob, f_ob), + Nsymbol(a_ob, f_ob, d_ob))) + #@show size(result), a_ob, b_ob, c_ob, d_ob, e_ob, f_ob, v + #@show result, v + s1 = length(result) + s2 = length(v) + @assert s1 == s2 "$s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $v, $result" map!(result, reshape(v, size(result))) do cmplxdict return complex(cmplxdict[:re], cmplxdict[:im]) end @@ -175,7 +225,7 @@ const Fcache = IdDict{Type{<:BimoduleSector}, function _get_Fcache(::Type{T}) where {T<:BimoduleSector} global Fcache return get!(Fcache, T) do - return extract_Fsymbol(T) + return extract_Fsymbol2(T) end end From a45be26e74d4ceb0211e95dd9419d54235629b28 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 11 Mar 2025 15:19:36 +0100 Subject: [PATCH 007/206] rewrite extract_Fsymbol to read txt info --- src/bimodulesector.jl | 117 +++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 53 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 9d9e411..fffcf4a 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -146,18 +146,52 @@ function Base.conj(a::BimoduleSector) return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][2][a.label]) end +# function extract_Fsymbol(::Type{A4Object}) +# return mapreduce((x, y) -> cat(x, y; dims=1), 1:12) do i +# filename = joinpath(artifact_path, "A4", "Fsymbol_$i.json") +# @assert isfile(filename) "cannot find $filename" +# json_string = read(filename, String) +# Farray_part = copy(JSON3.read(json_string)) # Dict with one entry, that entry has as value a Dict (a,b,c,d,e,f) of Dicts (re, im) +# return map(enumerate(Farray_part[Symbol(i)])) do (I, x) +# j, k, l = Tuple(CartesianIndices((12, 12, 12))[I]) +# y = Dict{NTuple{6,Int},Array{ComplexF64,4}}() +# for (key, v) in x +# a, b, c, d, e, f = parse.(Int, split(string(key)[2:(end - 1)], ", ")) +# a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), +# (k, l, c), (i, l, d), +# (i, k, e), (j, l, f))) +# result = Array{ComplexF64,4}(undef, +# (Nsymbol(a_ob, b_ob, e_ob), +# Nsymbol(e_ob, c_ob, d_ob), +# Nsymbol(b_ob, c_ob, f_ob), +# Nsymbol(a_ob, f_ob, d_ob))) +# #@show size(result), a_ob, b_ob, c_ob, d_ob, e_ob, f_ob, v +# #@show result, v +# s1 = length(result) +# s2 = length(v) +# @assert s1 == s2 "$s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $v, $result" +# map!(result, reshape(v, size(result))) do cmplxdict +# return complex(cmplxdict[:re], cmplxdict[:im]) +# end + +# y[(a, b, c, d, e, f)] = result +# end +# end +# end +# end +#TODO: figure out missing Fsymbol function extract_Fsymbol(::Type{A4Object}) - return mapreduce((x, y) -> cat(x, y; dims=1), 1:12) do i - filename = joinpath(artifact_path, "A4", "Fsymbol_$i.json") + return mapreduce((colordict, Fdict) -> cat(colordict, Fdict; dims=1), 1:12) do i + filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") @assert isfile(filename) "cannot find $filename" - json_string = read(filename, String) - Farray_part = copy(JSON3.read(json_string)) - @show Farray_part - return map(enumerate(Farray_part[Symbol(i)])) do (I, x) - j, k, l = Tuple(CartesianIndices((12, 12, 12))[I]) - y = Dict{NTuple{6,Int},Array{ComplexF64,4}}() - for (key, v) in x - a, b, c, d, e, f = parse.(Int, split(string(key)[2:(end - 1)], ", ")) + txt_string = read(filename, String) + Farray_part = copy(readdlm(IOBuffer(txt_string))); # now a matrix with 16 columns + Farray_part = convert_Fs(Farray_part) + return for (colors, colordict) in Farray_part + i,j,k,l = colors + Fdict = Dict{NTuple{6,Int},Array{ComplexF64,4}}() + for (labels, Fvals) in colordict + a, b, c, d, e, f = labels a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), (k, l, c), (i, l, d), (i, k, e), (j, l, f))) @@ -166,57 +200,34 @@ function extract_Fsymbol(::Type{A4Object}) Nsymbol(e_ob, c_ob, d_ob), Nsymbol(b_ob, c_ob, f_ob), Nsymbol(a_ob, f_ob, d_ob))) - #@show size(result), a_ob, b_ob, c_ob, d_ob, e_ob, f_ob, v - #@show result, v + s1 = length(result) - s2 = length(v) - @assert s1 == s2 "$s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $v, $result" - map!(result, reshape(v, size(result))) do cmplxdict - return complex(cmplxdict[:re], cmplxdict[:im]) + s2 = length(Fvals) + @assert s1 == s2 "$i, $j, $k, $l, $labels, $Fvals" + map!(result, reshape(Fvals, size(result))) do pair + return pair[2] end - y[(a, b, c, d, e, f)] = result + Fdict[(a, b, c, d, e, f)] = result end end end end -function extract_Fsymbol2(::Type{A4Object}) - return mapreduce((x, y) -> cat(x, y; dims=1), 1:12) do i - filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") - filename2 = joinpath(artifact_path, "A4", "Fsymbol_$i.json") - @assert isfile(filename) "cannot find $filename" - json_string = read(filename2, String) - txt_string = read(filename, String) - Farray_part = copy(readdlm(txt_string)) - Farray_part2 = copy(JSON3.read(json_string)) - @assert F_array_part == Farray_part2 - return map(enumerate(Farray_part[Symbol(i)])) do (I, x) - j, k, l = Tuple(CartesianIndices((12, 12, 12))[I]) - y = Dict{NTuple{6,Int},Array{ComplexF64,4}}() - for (key, v) in x - a, b, c, d, e, f = parse.(Int, split(string(key)[2:(end - 1)], ", ")) - a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), - (k, l, c), (i, l, d), - (i, k, e), (j, l, f))) - result = Array{ComplexF64,4}(undef, - (Nsymbol(a_ob, b_ob, e_ob), - Nsymbol(e_ob, c_ob, d_ob), - Nsymbol(b_ob, c_ob, f_ob), - Nsymbol(a_ob, f_ob, d_ob))) - #@show size(result), a_ob, b_ob, c_ob, d_ob, e_ob, f_ob, v - #@show result, v - s1 = length(result) - s2 = length(v) - @assert s1 == s2 "$s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $v, $result" - map!(result, reshape(v, size(result))) do cmplxdict - return complex(cmplxdict[:re], cmplxdict[:im]) - end - - y[(a, b, c, d, e, f)] = result - end - end +function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with 16 columns + data_dict = Dict{NTuple{4, Int}, Dict{NTuple{6, Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}}() + # want to make a Dict with keys (i,j,k,l) and vals + # a Dict with keys (a,b,c,d,e,f) and vals + # a pair of (mu, nu, rho, sigma) and the F value + for row in eachrow(Farray_part) + row = string.(split(string(row)[2:(end - 1)], ", ")) + i, j, k, l, a, b, c, d, e, f, mu, nu, rho, sigma = Int.(parse.(Float64, row[1:14])) + v = complex(parse.(Float64, row[15:16])...) + colordict = get!(data_dict, (i,j,k,l), Dict{NTuple{6,Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}()) + Fdict = get!(colordict, (a, b, c, d, e, f), Vector{Pair{CartesianIndex{4}, ComplexF64}}()) + push!(Fdict, CartesianIndex(mu, nu, rho, sigma) => v) end + return data_dict end const Fcache = IdDict{Type{<:BimoduleSector}, @@ -225,7 +236,7 @@ const Fcache = IdDict{Type{<:BimoduleSector}, function _get_Fcache(::Type{T}) where {T<:BimoduleSector} global Fcache return get!(Fcache, T) do - return extract_Fsymbol2(T) + return extract_Fsymbol(T) end end From eaa05c929eca11d5f8022ebef4a3e090b48c8809 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 11 Mar 2025 15:21:22 +0100 Subject: [PATCH 008/206] tests to run locally for my smooth brain --- test/localtests.jl | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/localtests.jl b/test/localtests.jl index 492e1b9..a98eddc 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -18,3 +18,46 @@ leftone(testmodobj) rightone(testmodobj) Fsymbol(testobj, testobj, testobj, testobj, testobj, testobj) + +using Artifacts +using DelimitedFiles + +artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.1") +filename = joinpath(artifact_path, "A4", "Fsymbol_4.txt") +txt_string = read(filename, String) +F_arraypart = copy(readdlm(IOBuffer(txt_string))); + +F_arraypart = MTK.convert_Fs(F_arraypart) +for (color, colordict) in F_arraypart + for (labels, F) in colordict + if length(F) == 2 + println(color, labels, F) + end + end +end +i,j,k,l = (4,12,12,2) # 5,2,8,10 +a,b,c,d,e,f = (1, 11, 3, 1, 1, 3) #(2,1,1,2,2,3) +testF = F_arraypart[(i,j,k,l)][(a,b,c,d,e,f)] +a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), + (k, l, c), (i, l, d), + (i, k, e), (j, l, f))) +result = Array{ComplexF64,4}(undef, + (Nsymbol(a_ob, b_ob, e_ob), + Nsymbol(e_ob, c_ob, d_ob), + Nsymbol(b_ob, c_ob, f_ob), + Nsymbol(a_ob, f_ob, d_ob))) + +map!(result, reshape(testF, size(result))) do pair + return pair[2] +end + +function bla() + return for (k,v) in F_arraypart + @show k + end +end + +using JSON3 +filename2 = joinpath(artifact_path, "A4", "Fsymbol_1.json") +json_string = read(filename2, String) +Farray_part2 = copy(JSON3.read(json_string)); \ No newline at end of file From 599b74e4bcdffd0181b41adc46b2e0ef8f3a38a1 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 09:55:11 +0100 Subject: [PATCH 009/206] start on adding missing elements of extract_Fsymbol --- src/bimodulesector.jl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index fffcf4a..112d0ac 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -103,7 +103,7 @@ function extract_dual(::Type{A4Object}) ncats = size(N, 1) return map(1:ncats) do i Niii = N[i, i, i] - nobj = maximum(first, keys(Niii)) + nobj = maximum(first, keys(Niii)) # this only works for fusion cats # find identity object: # I x I -> I, a x I -> a, I x a -> a @@ -201,11 +201,13 @@ function extract_Fsymbol(::Type{A4Object}) Nsymbol(b_ob, c_ob, f_ob), Nsymbol(a_ob, f_ob, d_ob))) - s1 = length(result) - s2 = length(Fvals) - @assert s1 == s2 "$i, $j, $k, $l, $labels, $Fvals" - map!(result, reshape(Fvals, size(result))) do pair - return pair[2] + if length(result) == length(Fvals) + map!(result, reshape(Fvals, size(result))) do pair + return pair[2] + end + else # due to sparse data, some Fvals are missing and we need to fill in zeros + # given result, can we track the missing CartesianIndices? + println("Mismatch in sizes: $s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob") end Fdict[(a, b, c, d, e, f)] = result From b9b099475b442d0b1d39c515c1b1c48084d18fae Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 09:57:10 +0100 Subject: [PATCH 010/206] change extract_dual to get duals of module cats as well --- src/bimodulesector.jl | 58 ++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 112d0ac..0e30020 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -101,31 +101,55 @@ end function extract_dual(::Type{A4Object}) N = _get_Ncache(A4Object) ncats = size(N, 1) - return map(1:ncats) do i + Is = zeros(Int, ncats) + + map(1:ncats) do i Niii = N[i, i, i] - nobj = maximum(first, keys(Niii)) # this only works for fusion cats + nobji = maximum(first, keys(N[i, i, i])) + # want to return a leftone and rightone for each entry in multifusion cat + # leftone/rightone needs to at least be the unit object within a fusion cat + Is[i] = findfirst(1:nobji) do a + get(Niii, (a, a, a), 0) == 1 || return false # I x I -> I + for othera in 1:nobji + get(Niii, (othera, a, othera), 0) == 1 || return false # a x I -> a + get(Niii, (a, othera, othera), 0) == 1 || return false # I x a -> a + end + + # check leftone + map(1:ncats) do j + nobjj = maximum(first, keys(N[j, j, j])) + for b in 1:nobjj + get(N[i, j, j], (a, b, b), 0) == 1 || return false # I = leftone(b) + end + end - # find identity object: - # I x I -> I, a x I -> a, I x a -> a - I = findfirst(1:nobj) do u - get(Niii, (u, u, u), 0) == 1 || return false - for j in 1:nobj - get(Niii, (j, u, j), 0) == 1 || return false - get(Niii, (u, j, j), 0) == 1 || return false + # check rightone + map(1:ncats) do k + nobjk = maximum(first, keys(N[k, k, k])) + for c in 1:nobjk + get(N[k, i, k], (c, a, c), 0) == 1 || return false # I = rightone(c) + end end return true end - - # find duals - # a x abar -> I - duals = map(1:nobj) do j - return findfirst(1:nobj) do k - return get(Niii, (j, k, I), 0) == 1 + end + + allduals = 0 .|> fill(x->Vector{Int}(), ncats, ncats) # ncats square matrix of vectors + map(1:ncats) do i + nobji = maximum(first, keys(N[i, i, i])) + map(1:ncats) do j + nobjj = maximum(first, keys(N[j, j, j])) + # the nested vectors contain the duals of the objects in π’ž_ij, which are in C_ji + Niji = N[i, j, i] # π’ž_ij x π’ž_ji -> C_ii + Njij = N[j, i, j] # π’ž_ji x π’ž_ij -> C_jj + for i_ob in 1:nobji, j_ob in 1:nobjj + get(Niji, (i_ob, j_ob, Is[i]), 0) == 1 || continue # leftone(c_ij) ∈ c_ij x c_ji + get(Njij, (j_ob, i_ob, Is[j]), 0) == 1 || continue # rightone(c_ij) ∈ c_ji x c_ij + push!(allduals[i,j], j_ob) end end - - return I, duals end + return Is, allduals end function Base.one(a::BimoduleSector) From 2683ad18583d52a87735666f3967b968d8d44b7c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 10:11:56 +0100 Subject: [PATCH 011/206] update one, leftone, rightone, conj functions with new extract_dual --- src/bimodulesector.jl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 0e30020..ef322a2 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -89,7 +89,7 @@ function TensorKitSectors.Nsymbol(a::I, b::I, c::I) where {I<:A4Object} end # TODO: can we define dual for modules? -const Dualcache = IdDict{Type{<:BimoduleSector},Vector{Tuple{Int,Vector{Int}}}}() +const Dualcache = IdDict{Type{<:BimoduleSector},Tuple{Vector{Int64}, Matrix{Vector{Int64}}}}() function _get_dual_cache(::Type{T}) where {T<:BimoduleSector} global Dualcache @@ -154,20 +154,19 @@ end function Base.one(a::BimoduleSector) a.i == a.j || error("don't know how to define one for modules") - return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) + return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end function TensorKitSectors.leftone(a::BimoduleSector) - return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][1]) + return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end function TensorKitSectors.rightone(a::BimoduleSector) - return A4Object(a.j, a.j, _get_dual_cache(typeof(a))[a.j][1]) + return A4Object(a.j, a.j, _get_dual_cache(typeof(a))[1][a.j]) end function Base.conj(a::BimoduleSector) - a.i == a.j || error("don't know how to define dual for modules") - return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[a.i][2][a.label]) + return A4Object(a.j, a.i, _get_dual_cache(typeof(a))[2][a.i,a.j][a.label]) end # function extract_Fsymbol(::Type{A4Object}) From c425551496de17bfbd3de0d90fa9ef4c427678c5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 10:37:17 +0100 Subject: [PATCH 012/206] add test to check units and duals --- test/test_A4.jl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 7c07249..7a523e1 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -11,7 +11,7 @@ I = A4Object end @testset "Fusion Category $i" for i in 1:12 - objects = A4Object.(i, i, MultiTensorKit._get_dual_cache(I)[i][2]) + objects = A4Object.(i, i, MultiTensorKit._get_dual_cache(I)[2][i,i]) @testset "Basic properties" begin s = rand(objects, 3) @@ -53,4 +53,14 @@ end end end -#TODO: add tests for module categories \ No newline at end of file +@testset "A4 Category ($i, $j) units and duals" for i in 1:12, j in 1:12 + Cij_obs = A4Object.(i, j, MultiTensorKit._get_dual_cache(I)[2][i,j]) + + s = rand(Cij_obs, 1)[1] + @test eval(Meta.parse(sprint(show, s))) == s + @test @constinferred(hash(s)) == hash(deepcopy(s)) + @test i == j ? isone(@constinferred(one(s))) : (isone(@constinferred(leftone(s))) && isone(@constinferred(rightone(s)))) + @constinferred dual(s) + @test dual(s) == A4Object(j, i, MultiTensorKit._get_dual_cache(I)[2][i,j][s.label]) + @test dual(dual(s)) == s +end \ No newline at end of file From 87c11b3b7b92de3369066da8dc9d80eeba7df97a Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 10:39:05 +0100 Subject: [PATCH 013/206] remove TODO about duals for modules --- src/bimodulesector.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index ef322a2..76c0cc1 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -88,7 +88,6 @@ function TensorKitSectors.Nsymbol(a::I, b::I, c::I) where {I<:A4Object} return get(_get_Ncache(I)[i, j, k], (a.label, b.label, c.label), 0) end -# TODO: can we define dual for modules? const Dualcache = IdDict{Type{<:BimoduleSector},Tuple{Vector{Int64}, Matrix{Vector{Int64}}}}() function _get_dual_cache(::Type{T}) where {T<:BimoduleSector} From 66e6ef2beeaae68fca402d1894e4f95c1808a6b9 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 14:50:30 +0100 Subject: [PATCH 014/206] add missing elements of extract_Fsymbol --- src/bimodulesector.jl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 76c0cc1..693a544 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -223,13 +223,17 @@ function extract_Fsymbol(::Type{A4Object}) Nsymbol(b_ob, c_ob, f_ob), Nsymbol(a_ob, f_ob, d_ob))) - if length(result) == length(Fvals) - map!(result, reshape(Fvals, size(result))) do pair - return pair[2] + # due to sparse data, some Fvals are missing and we need to fill in zeros + # error("Mismatch in sizes: $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob") + for index in CartesianIndices(result) + if index βˆ‰ [first(ind) for ind in Fvals] #wrong condition + push!(Fvals, index => ComplexF64(0)) end - else # due to sparse data, some Fvals are missing and we need to fill in zeros - # given result, can we track the missing CartesianIndices? - println("Mismatch in sizes: $s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob") + end + # s1, s2 = length(result), length(Fvals) + # @assert s1 == s2 "$a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $Fvals, $result" + map!(result, reshape(Fvals, size(result))) do pair + return pair[2] end Fdict[(a, b, c, d, e, f)] = result From adcc5fe57e55f1d1a53c359241047ee6492d4581 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 15:04:39 +0100 Subject: [PATCH 015/206] change Fcache definition --- src/bimodulesector.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 693a544..08a431d 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -201,7 +201,7 @@ end # end # end # end -#TODO: figure out missing Fsymbol + function extract_Fsymbol(::Type{A4Object}) return mapreduce((colordict, Fdict) -> cat(colordict, Fdict; dims=1), 1:12) do i filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") @@ -258,8 +258,9 @@ function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with return data_dict end +# TODO: figure out correct Fcache type const Fcache = IdDict{Type{<:BimoduleSector}, - Array{Dict{NTuple{6,Int},Array{ComplexF64,4}},4}}() + Array{Dict{NTuple{4, Int}, Dict{NTuple{6, Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}}}}() function _get_Fcache(::Type{T}) where {T<:BimoduleSector} global Fcache From 10ee1b630a8c3783706de22d7a3d6ad8e066f347 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 15:18:48 +0100 Subject: [PATCH 016/206] fix extract_Fsymbol to output something useful --- src/bimodulesector.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 08a431d..6517e27 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -209,7 +209,7 @@ function extract_Fsymbol(::Type{A4Object}) txt_string = read(filename, String) Farray_part = copy(readdlm(IOBuffer(txt_string))); # now a matrix with 16 columns Farray_part = convert_Fs(Farray_part) - return for (colors, colordict) in Farray_part + for (colors, colordict) in Farray_part i,j,k,l = colors Fdict = Dict{NTuple{6,Int},Array{ComplexF64,4}}() for (labels, Fvals) in colordict @@ -238,6 +238,7 @@ function extract_Fsymbol(::Type{A4Object}) Fdict[(a, b, c, d, e, f)] = result end + return Fdict end end end From 6236465820ecb4e50b7d8c59bd44d103ee4f6669 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 15:19:32 +0100 Subject: [PATCH 017/206] go back to correct definition Fcache --- src/bimodulesector.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 6517e27..59bce2c 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -261,7 +261,7 @@ end # TODO: figure out correct Fcache type const Fcache = IdDict{Type{<:BimoduleSector}, - Array{Dict{NTuple{4, Int}, Dict{NTuple{6, Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}}}}() + Array{Dict{NTuple{6,Int},Array{ComplexF64,4}},4}}() function _get_Fcache(::Type{T}) where {T<:BimoduleSector} global Fcache From d366a401d8aed9a18c1cce3b87479745eea856f7 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 15:22:10 +0100 Subject: [PATCH 018/206] Revert "go back to correct definition Fcache" This reverts commit 6236465820ecb4e50b7d8c59bd44d103ee4f6669. --- src/bimodulesector.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 59bce2c..6517e27 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -261,7 +261,7 @@ end # TODO: figure out correct Fcache type const Fcache = IdDict{Type{<:BimoduleSector}, - Array{Dict{NTuple{6,Int},Array{ComplexF64,4}},4}}() + Array{Dict{NTuple{4, Int}, Dict{NTuple{6, Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}}}}() function _get_Fcache(::Type{T}) where {T<:BimoduleSector} global Fcache From 383218b48ab022f0d208ea54098b3dd1c6b57e05 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 17:04:17 +0100 Subject: [PATCH 019/206] output correct dictionary in extract_Fsymbol --- src/bimodulesector.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 6517e27..40d7d0d 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -209,7 +209,7 @@ function extract_Fsymbol(::Type{A4Object}) txt_string = read(filename, String) Farray_part = copy(readdlm(IOBuffer(txt_string))); # now a matrix with 16 columns Farray_part = convert_Fs(Farray_part) - for (colors, colordict) in Farray_part + dict_data = Iterators.map(Farray_part) do (colors, colordict) i,j,k,l = colors Fdict = Dict{NTuple{6,Int},Array{ComplexF64,4}}() for (labels, Fvals) in colordict @@ -238,8 +238,9 @@ function extract_Fsymbol(::Type{A4Object}) Fdict[(a, b, c, d, e, f)] = result end - return Fdict + return colors => Fdict end + return Dict(dict_data) end end From 54b64cdc53d2085d7005491366fb9bf86e7ef029 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 17:21:56 +0100 Subject: [PATCH 020/206] fix Fcache to new output extract_Fsymbol --- src/bimodulesector.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 40d7d0d..65168ef 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -262,7 +262,7 @@ end # TODO: figure out correct Fcache type const Fcache = IdDict{Type{<:BimoduleSector}, - Array{Dict{NTuple{4, Int}, Dict{NTuple{6, Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}}}}() + Array{Dict{NTuple{4, Int64}, Dict{NTuple{6, Int64}, Array{ComplexF64, 4}}}}}() function _get_Fcache(::Type{T}) where {T<:BimoduleSector} global Fcache From 16e683b29edf3f17871558622f81b53372c2f169 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 17:26:27 +0100 Subject: [PATCH 021/206] add sectorscalartype --- src/bimodulesector.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 65168ef..3f3b75f 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -39,6 +39,7 @@ end TensorKitSectors.FusionStyle(::Type{A4Object}) = GenericFusion() TensorKitSectors.BraidingStyle(::Type{A4Object}) = NoBraiding() +TensorKitSectors.sectorscalartype(::Type{A4Object}) = ComplexF64 function TensorKitSectors.:βŠ—(a::A4Object, b::A4Object) @assert a.j == b.i @@ -280,7 +281,7 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, i, j, k, l = a.i, a.j, b.j, c.j return get(_get_Fcache(I)[i, j, k, l], - (a.label, b.label, c.label, d.label, e.label, f.label)) do + (a.label, b.label, c.label, d.label, e.label, f.label)) do return zeros(sectorscalartype(A4Object), (Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d))) From f8d45c32f92f1e76fb1658873531443d58e3485e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 14 Mar 2025 17:49:44 +0100 Subject: [PATCH 022/206] have a functioning Fsymbol --- src/bimodulesector.jl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 3f3b75f..8120555 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -261,7 +261,7 @@ function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with return data_dict end -# TODO: figure out correct Fcache type +# TODO: do we want this type for Fcache? const Fcache = IdDict{Type{<:BimoduleSector}, Array{Dict{NTuple{4, Int64}, Dict{NTuple{6, Int64}, Array{ComplexF64, 4}}}}}() @@ -280,10 +280,8 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, throw(ArgumentError("invalid fusion channel")) i, j, k, l = a.i, a.j, b.j, c.j - return get(_get_Fcache(I)[i, j, k, l], - (a.label, b.label, c.label, d.label, e.label, f.label)) do - return zeros(sectorscalartype(A4Object), - (Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), - Nsymbol(a, f, d))) + colordict = _get_Fcache(I)[i][i, j, k, l] + return get(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) do + return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] end end From c0caddff324f4779cbb44e04c1180da5d1ea613a Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 10:06:57 +0100 Subject: [PATCH 023/206] add bounds to what A4Object can be defined as --- src/bimodulesector.jl | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 8120555..e78468a 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -2,15 +2,13 @@ struct BimoduleSector{Name} <: Sector i::Int j::Int label::Int + function BimoduleSector{:A4}(i::Int, j::Int, label::Int) + i <= 12 && j <= 12 || throw(DomainError("object outside the matrix A4")) + return label <= _numlabels(BimoduleSector{:A4}, i, j) ? new{:A4}(i, j, label) : throw(DomainError("label outside category A4($i, $j)")) + end end BimoduleSector{Name}(data::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(data...) -#TODO: place bound on what BimoduleSectors can be made -# currently you can define A4Object(anyint, anyint, anyint) const A4Object = BimoduleSector{:A4} -# function A4Object(i::Int, j::Int, label::Int) -# i <= 12 && j <= 12 || throw(DomainError("object outside the matrix")) -# return BimoduleSector{A4Object}(i, j, label) -# end # Utility implementations # ----------------------- @@ -25,7 +23,6 @@ end Base.IteratorSize(::Type{SectorValues{<:BimoduleSector}}) = Base.SizeUnknown() # TODO: generalize? -# TODO: numlabels? function Base.iterate(iter::SectorValues{A4Object}, (I, label)=(1, 1)) I > 12 * 12 && return nothing i, j = CartesianIndices((12, 12))[I].I @@ -49,8 +46,8 @@ function TensorKitSectors.:βŠ—(a::A4Object, b::A4Object) if (a_l == a.label && b_l == b.label)] end -function _numlabels(::Type{A4Object}, i, j) - return Ncache = _get_Ncache(A4Object) +function _numlabels(::Type{T}, i, j) where {T<:BimoduleSector} + return length(_get_dual_cache(T)[2][i,j]) end # Data from files @@ -284,4 +281,4 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, return get(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) do return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] end -end +end \ No newline at end of file From df9eb3eaa4b46acf4d0f0adc1f9e98322f862186 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 10:08:42 +0100 Subject: [PATCH 024/206] remove JSON3 dependency --- Project.toml | 2 -- src/bimodulesector.jl | 35 ----------------------------------- 2 files changed, 37 deletions(-) diff --git a/Project.toml b/Project.toml index 1c369bb..f557f7f 100644 --- a/Project.toml +++ b/Project.toml @@ -6,13 +6,11 @@ version = "0.1.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" -JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" [compat] Aqua = "0.8.9" Artifacts = "1.10, 1" -JSON3 = "1.14.1" SafeTestsets = "0.1" TensorKitSectors = "0.1.2" Test = "1.10" diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index e78468a..d61d99a 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -166,40 +166,6 @@ function Base.conj(a::BimoduleSector) return A4Object(a.j, a.i, _get_dual_cache(typeof(a))[2][a.i,a.j][a.label]) end -# function extract_Fsymbol(::Type{A4Object}) -# return mapreduce((x, y) -> cat(x, y; dims=1), 1:12) do i -# filename = joinpath(artifact_path, "A4", "Fsymbol_$i.json") -# @assert isfile(filename) "cannot find $filename" -# json_string = read(filename, String) -# Farray_part = copy(JSON3.read(json_string)) # Dict with one entry, that entry has as value a Dict (a,b,c,d,e,f) of Dicts (re, im) -# return map(enumerate(Farray_part[Symbol(i)])) do (I, x) -# j, k, l = Tuple(CartesianIndices((12, 12, 12))[I]) -# y = Dict{NTuple{6,Int},Array{ComplexF64,4}}() -# for (key, v) in x -# a, b, c, d, e, f = parse.(Int, split(string(key)[2:(end - 1)], ", ")) -# a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), -# (k, l, c), (i, l, d), -# (i, k, e), (j, l, f))) -# result = Array{ComplexF64,4}(undef, -# (Nsymbol(a_ob, b_ob, e_ob), -# Nsymbol(e_ob, c_ob, d_ob), -# Nsymbol(b_ob, c_ob, f_ob), -# Nsymbol(a_ob, f_ob, d_ob))) -# #@show size(result), a_ob, b_ob, c_ob, d_ob, e_ob, f_ob, v -# #@show result, v -# s1 = length(result) -# s2 = length(v) -# @assert s1 == s2 "$s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $v, $result" -# map!(result, reshape(v, size(result))) do cmplxdict -# return complex(cmplxdict[:re], cmplxdict[:im]) -# end - -# y[(a, b, c, d, e, f)] = result -# end -# end -# end -# end - function extract_Fsymbol(::Type{A4Object}) return mapreduce((colordict, Fdict) -> cat(colordict, Fdict; dims=1), 1:12) do i filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") @@ -258,7 +224,6 @@ function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with return data_dict end -# TODO: do we want this type for Fcache? const Fcache = IdDict{Type{<:BimoduleSector}, Array{Dict{NTuple{4, Int64}, Dict{NTuple{6, Int64}, Array{ComplexF64, 4}}}}}() From 7743a008100e6be2ae020f087435ef8ea4d6018f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 10:09:24 +0100 Subject: [PATCH 025/206] more local tests --- test/localtests.jl | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index a98eddc..d794cd4 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -1,5 +1,5 @@ using TensorKitSectors -using .MultiTensorKit +using MultiTensorKit using Revise testobj = A4Object(1,1,1) # fusion cat object @@ -17,7 +17,7 @@ one(testmodobj) leftone(testmodobj) rightone(testmodobj) -Fsymbol(testobj, testobj, testobj, testobj, testobj, testobj) +Fsymbol(testobj, testobj, A4Object(1,1,3), testobj, A4Object(1,1,3), A4Object(1,1,4)) using Artifacts using DelimitedFiles @@ -27,14 +27,15 @@ filename = joinpath(artifact_path, "A4", "Fsymbol_4.txt") txt_string = read(filename, String) F_arraypart = copy(readdlm(IOBuffer(txt_string))); +MTK = MultiTensorKit F_arraypart = MTK.convert_Fs(F_arraypart) -for (color, colordict) in F_arraypart - for (labels, F) in colordict - if length(F) == 2 - println(color, labels, F) - end - end -end +# for (color, colordict) in F_arraypart +# for (labels, F) in colordict +# if length(F) == 2 +# println(color, labels, F) +# end +# end +# end i,j,k,l = (4,12,12,2) # 5,2,8,10 a,b,c,d,e,f = (1, 11, 3, 1, 1, 3) #(2,1,1,2,2,3) testF = F_arraypart[(i,j,k,l)][(a,b,c,d,e,f)] @@ -51,13 +52,32 @@ map!(result, reshape(testF, size(result))) do pair return pair[2] end +for c in testF[2] + println(c) +end + function bla() return for (k,v) in F_arraypart @show k end end -using JSON3 -filename2 = joinpath(artifact_path, "A4", "Fsymbol_1.json") -json_string = read(filename2, String) -Farray_part2 = copy(JSON3.read(json_string)); \ No newline at end of file +N = MultiTensorKit._get_Ncache(A4Object); + +duals = MultiTensorKit._get_dual_cache(A4Object)[2] +# checking duals is correct +for i in 1:12, j in 1:12 + for (index, a) in enumerate(duals[i,j]) + aob = A4Object(i,j,index) + bob = A4Object(j,i,a) + leftone(aob) ∈ aob βŠ— bob && rightone(aob) ∈ bob βŠ— aob || @show i,j,aob,bob + end +end + +A = MultiTensorKit._get_Fcache(A4Object) +a,b,c,d,e,f = A4Object(1,1,3), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,2) +a,b,c,d,e,f = A4Object(1,1,1), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,1), A4Object(1,1,2), A4Object(1,1,4) +coldict = A[a.i][a.i, a.j, b.j, c.j] +bla = get(coldict, (a.label, b.label, c.label, d.label, e.label, f.label)) do + return coldict[(a.label, b.label, c.label, d.label, e.label, f.label)] + end \ No newline at end of file From 07dfc6ccbf0ee3f5d9c0643758546c0c12215e25 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 10:11:14 +0100 Subject: [PATCH 026/206] actually remove all JSON3 deps --- src/MultiTensorKit.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 1134ca4..b933b88 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -2,7 +2,6 @@ module MultiTensorKit export BimoduleSector, A4Object -using JSON3 using DelimitedFiles using Artifacts using TensorKitSectors From 71f6916f0fc59299f8b433a9b99d225bced3c3d6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 10:14:26 +0100 Subject: [PATCH 027/206] Revert "actually remove all JSON3 deps" This reverts commit 07dfc6ccbf0ee3f5d9c0643758546c0c12215e25. --- src/MultiTensorKit.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index b933b88..1134ca4 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -2,6 +2,7 @@ module MultiTensorKit export BimoduleSector, A4Object +using JSON3 using DelimitedFiles using Artifacts using TensorKitSectors From 1f37a92572b970a30d08e2ff65de2e5e04724e5d Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 10:15:03 +0100 Subject: [PATCH 028/206] Revert "remove JSON3 dependency" This reverts commit df9eb3eaa4b46acf4d0f0adc1f9e98322f862186. --- Project.toml | 2 ++ src/bimodulesector.jl | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/Project.toml b/Project.toml index f557f7f..1c369bb 100644 --- a/Project.toml +++ b/Project.toml @@ -6,11 +6,13 @@ version = "0.1.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" +JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" [compat] Aqua = "0.8.9" Artifacts = "1.10, 1" +JSON3 = "1.14.1" SafeTestsets = "0.1" TensorKitSectors = "0.1.2" Test = "1.10" diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index d61d99a..e78468a 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -166,6 +166,40 @@ function Base.conj(a::BimoduleSector) return A4Object(a.j, a.i, _get_dual_cache(typeof(a))[2][a.i,a.j][a.label]) end +# function extract_Fsymbol(::Type{A4Object}) +# return mapreduce((x, y) -> cat(x, y; dims=1), 1:12) do i +# filename = joinpath(artifact_path, "A4", "Fsymbol_$i.json") +# @assert isfile(filename) "cannot find $filename" +# json_string = read(filename, String) +# Farray_part = copy(JSON3.read(json_string)) # Dict with one entry, that entry has as value a Dict (a,b,c,d,e,f) of Dicts (re, im) +# return map(enumerate(Farray_part[Symbol(i)])) do (I, x) +# j, k, l = Tuple(CartesianIndices((12, 12, 12))[I]) +# y = Dict{NTuple{6,Int},Array{ComplexF64,4}}() +# for (key, v) in x +# a, b, c, d, e, f = parse.(Int, split(string(key)[2:(end - 1)], ", ")) +# a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), +# (k, l, c), (i, l, d), +# (i, k, e), (j, l, f))) +# result = Array{ComplexF64,4}(undef, +# (Nsymbol(a_ob, b_ob, e_ob), +# Nsymbol(e_ob, c_ob, d_ob), +# Nsymbol(b_ob, c_ob, f_ob), +# Nsymbol(a_ob, f_ob, d_ob))) +# #@show size(result), a_ob, b_ob, c_ob, d_ob, e_ob, f_ob, v +# #@show result, v +# s1 = length(result) +# s2 = length(v) +# @assert s1 == s2 "$s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $v, $result" +# map!(result, reshape(v, size(result))) do cmplxdict +# return complex(cmplxdict[:re], cmplxdict[:im]) +# end + +# y[(a, b, c, d, e, f)] = result +# end +# end +# end +# end + function extract_Fsymbol(::Type{A4Object}) return mapreduce((colordict, Fdict) -> cat(colordict, Fdict; dims=1), 1:12) do i filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") @@ -224,6 +258,7 @@ function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with return data_dict end +# TODO: do we want this type for Fcache? const Fcache = IdDict{Type{<:BimoduleSector}, Array{Dict{NTuple{4, Int64}, Dict{NTuple{6, Int64}, Array{ComplexF64, 4}}}}}() From c50f31ab8b7add7d85454ea53bcc2c4c161a86b2 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 10:16:00 +0100 Subject: [PATCH 029/206] remove Fsymbol code that was JSON dependent --- src/bimodulesector.jl | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index e78468a..a9970fe 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -166,40 +166,6 @@ function Base.conj(a::BimoduleSector) return A4Object(a.j, a.i, _get_dual_cache(typeof(a))[2][a.i,a.j][a.label]) end -# function extract_Fsymbol(::Type{A4Object}) -# return mapreduce((x, y) -> cat(x, y; dims=1), 1:12) do i -# filename = joinpath(artifact_path, "A4", "Fsymbol_$i.json") -# @assert isfile(filename) "cannot find $filename" -# json_string = read(filename, String) -# Farray_part = copy(JSON3.read(json_string)) # Dict with one entry, that entry has as value a Dict (a,b,c,d,e,f) of Dicts (re, im) -# return map(enumerate(Farray_part[Symbol(i)])) do (I, x) -# j, k, l = Tuple(CartesianIndices((12, 12, 12))[I]) -# y = Dict{NTuple{6,Int},Array{ComplexF64,4}}() -# for (key, v) in x -# a, b, c, d, e, f = parse.(Int, split(string(key)[2:(end - 1)], ", ")) -# a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), -# (k, l, c), (i, l, d), -# (i, k, e), (j, l, f))) -# result = Array{ComplexF64,4}(undef, -# (Nsymbol(a_ob, b_ob, e_ob), -# Nsymbol(e_ob, c_ob, d_ob), -# Nsymbol(b_ob, c_ob, f_ob), -# Nsymbol(a_ob, f_ob, d_ob))) -# #@show size(result), a_ob, b_ob, c_ob, d_ob, e_ob, f_ob, v -# #@show result, v -# s1 = length(result) -# s2 = length(v) -# @assert s1 == s2 "$s1, $s2, $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $v, $result" -# map!(result, reshape(v, size(result))) do cmplxdict -# return complex(cmplxdict[:re], cmplxdict[:im]) -# end - -# y[(a, b, c, d, e, f)] = result -# end -# end -# end -# end - function extract_Fsymbol(::Type{A4Object}) return mapreduce((colordict, Fdict) -> cat(colordict, Fdict; dims=1), 1:12) do i filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") From 0d5045287c7e52d3bdbd8abc9c42b05a8ca18589 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 16:39:51 +0100 Subject: [PATCH 030/206] add TensorKit dependency --- Project.toml | 1 + src/MultiTensorKit.jl | 1 + 2 files changed, 2 insertions(+) diff --git a/Project.toml b/Project.toml index 1c369bb..3bed8ca 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ version = "0.1.0" Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" +TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" [compat] diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 1134ca4..45498ec 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -6,6 +6,7 @@ using JSON3 using DelimitedFiles using Artifacts using TensorKitSectors +using TensorKit include("bimodulesector.jl") From 013c3d85ae6fba814dea36329d22e6901a6847aa Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 17 Mar 2025 16:41:28 +0100 Subject: [PATCH 031/206] define length of SectorValues of A4Object + typo in Base.iterate of SectorValues --- src/bimodulesector.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index a9970fe..592a1fe 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -26,7 +26,7 @@ Base.IteratorSize(::Type{SectorValues{<:BimoduleSector}}) = Base.SizeUnknown() function Base.iterate(iter::SectorValues{A4Object}, (I, label)=(1, 1)) I > 12 * 12 && return nothing i, j = CartesianIndices((12, 12))[I].I - maxlabel = numlabels(A4Object, i, j) + maxlabel = _numlabels(A4Object, i, j) return if label > maxlabel iterate(iter, (I + 1, 1)) else @@ -34,6 +34,8 @@ function Base.iterate(iter::SectorValues{A4Object}, (I, label)=(1, 1)) end end +Base.length(::SectorValues{A4Object}) = sum(_numlabels(A4Object, i, j) for i in 1:12, j in 1:12) + TensorKitSectors.FusionStyle(::Type{A4Object}) = GenericFusion() TensorKitSectors.BraidingStyle(::Type{A4Object}) = NoBraiding() TensorKitSectors.sectorscalartype(::Type{A4Object}) = ComplexF64 From fb7413184a1b5ef037cb18fc9295d4e586703222 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 24 Mar 2025 15:47:40 +0100 Subject: [PATCH 032/206] export TensorKit hasblock --- src/MultiTensorKit.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 45498ec..f922133 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -6,7 +6,9 @@ using JSON3 using DelimitedFiles using Artifacts using TensorKitSectors + using TensorKit +import TensorKit: hasblock include("bimodulesector.jl") From 9250470543a07964e8647d9367b5df01a524fd8b Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 24 Mar 2025 15:48:06 +0100 Subject: [PATCH 033/206] custom TensorKit.blocksectors --- src/bimodulesector.jl | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 592a1fe..c175a8d 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -249,4 +249,32 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, return get(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) do return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] end +end + + +# interface with TensorKit where necessary +#----------------------------------------- + +function TensorKit.blocksectors(W::HomSpace{S}) where {S<:GradedSpace{A4Object}} + sectortype(W) === Trivial && + return OneOrNoneIterator(dim(domain(W)) != 0 && dim(codomain(W)) != 0, Trivial()) + + codom = codomain(W) + dom = domain(W) + N₁ = length(codom) + Nβ‚‚ = length(dom) + if N₁ == 0 && Nβ‚‚ == 0 # 0x0-dimensional TensorMap is just a scalar, return all units + # this is a problem in full contractions where the coloring outside is π’ž + return NTuple{12, A4Object}(one(A4Object(i,i,1)) for i in 1:12) # have to return all units b/c no info on W in this case + elseif N₁ == 0 + @assert Nβ‚‚ != 0 "one of Type A4Object doesn't exist" + return filter!(isone, collect(blocksectors(dom))) + elseif Nβ‚‚ == 0 + @assert N₁ != 0 "one of Type A4Object doesn't exist" + return filter!(isone, collect(blocksectors(codom))) + elseif Nβ‚‚ <= N₁ # this filter will keep the blocksectors of the domain which appear in the codomain as well + return filter!(c -> hasblock(codom, c), collect(blocksectors(dom))) + else + return filter!(c -> hasblock(dom, c), collect(blocksectors(codom))) + end end \ No newline at end of file From 0c7d6182ac8e211da6e2534646b6a7a9b5e4a4c5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 24 Mar 2025 15:48:31 +0100 Subject: [PATCH 034/206] start of TensorKit tests --- test/localtests.jl | 61 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/test/localtests.jl b/test/localtests.jl index d794cd4..ff10ea9 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -80,4 +80,63 @@ a,b,c,d,e,f = A4Object(1,1,1), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,1) coldict = A[a.i][a.i, a.j, b.j, c.j] bla = get(coldict, (a.label, b.label, c.label, d.label, e.label, f.label)) do return coldict[(a.label, b.label, c.label, d.label, e.label, f.label)] - end \ No newline at end of file + end + +###### TensorKit stuff ###### +using MultiTensorKit +using TensorKit +using Test + +# π’ž x π’ž example + +obj = A4Object(2,2,1) +obj2 = A4Object(2,2,2) +sp = Vect[A4Object](obj=>1, obj2=>1) +A = TensorMap(ones, ComplexF64, sp βŠ— sp ← sp βŠ— sp) +transpose(A, (2,4,), (1,3,)) + +# π’ž x β„³ example +obj = A4Object(1,1,1) +obj2 = A4Object(1,2,1) + +sp = Vect[A4Object](obj=>1) +sp2 = Vect[A4Object](obj2=>1) +@test_throws ArgumentError("invalid fusion channel") TensorMap(rand, ComplexF64, sp βŠ— sp2 ← sp) +homspace = sp βŠ— sp2 ← sp2 +A = TensorMap(ones, ComplexF64, homspace) +for sector in sectors(sp2) + @show sector +end +fusiontrees(A) +permute(space(A),((1,),(3,2))) +transpose(A, (1,2,), (3,)) == A +transpose(A, (3,1,), (2,)) + +Aop = TensorMap(ones, ComplexF64, conj(sp2) βŠ— sp ← conj(sp2)) +transpose(Aop, (1,2,), (3,)) == Aop +transpose(Aop, (1,), (3,2)) + +@plansor Acont[a] := A[a b;b] # should not have data bc sp isn't the unit + +spfix = Vect[A4Object](one(obj)=>1) +Afix = TensorMap(ones, ComplexF64, spfix βŠ— sp2 ← sp2) +@plansor Acontfix[a] := Afix[a b;b] # should have a fusion tree + +# completely off-diagonal example + +obj = A4Object(5, 4, 1) +obj2 = A4Object(4, 5, 1) +sp = Vect[A4Object](obj=>1) +sp2 = Vect[A4Object](obj2=>1) +conj(sp) == sp2 + +A = TensorMap(ones, ComplexF64, sp βŠ— sp2 ← sp βŠ— sp2) +Aop = TensorMap(ones, ComplexF64, sp2 βŠ— sp ← sp2 βŠ— sp) + +At = transpose(A, (2,4,), (1,3,)) +Aopt = transpose(Aop, (2,4,), (1,3,)) + +blocksectors(At) == blocksectors(Aop) +blocksectors(Aopt) == blocksectors(A) + +@plansor Acont[] := A[a b;a b] \ No newline at end of file From a6c9aaf119589eea8d777997a30ddfa19da59fb6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 25 Mar 2025 10:12:12 +0100 Subject: [PATCH 035/206] some tests for bram --- test/localtests.jl | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/test/localtests.jl b/test/localtests.jl index ff10ea9..3addf17 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -139,4 +139,48 @@ Aopt = transpose(Aop, (2,4,), (1,3,)) blocksectors(At) == blocksectors(Aop) blocksectors(Aopt) == blocksectors(A) -@plansor Acont[] := A[a b;a b] \ No newline at end of file +@plansor Acont[] := A[a b;a b] + +testsp = SU2Space(0=>1, 1=>1) + + + +# bram stuff + +for i in 1:12, j in 1:12 + for a in A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i,j]) + F = Fsymbol(a, dual(a), a, a, leftone(a), rightone(a))[1,1,1,1] + isapprox(F, frobeniusschur(a) / dim(a); atol=1e-15) || @show a, F, frobeniusschur(a)/ dim(a) # check real + isreal(frobeniusschur(a)) || @show a, frobeniusschur(a) + end +end + +for i in 1:12, j in 1:12 # 18a + i != j || continue + objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i,j]) + @assert all(dim(m) > 0 for m in objsij) +end + +for i in 1:12, j in 1:12 # 18b + objsii = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i,i]) + objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i,j]) + + Ndict = Dict{Tuple{A4Object, A4Object, A4Object}, Int}() + for a in objsii, m in objsij + for n in aβŠ—m + Ndict[(a, m, n)] = Nsymbol(a, m, n) + end + end + + for a in objsii, m in objsij + isapprox(dim(a)*dim(m), sum(Ndict[(a, m, n)]*dim(n) for n in aβŠ—m); atol=2e-9) || @show a, m + end +end + +for i in 1:12, j in 1:12 # 18c + objsii = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i,i]) + objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i,j]) + m_dimsum = sum(dim(m)^2 for m in objsij) + c_dimsum = sum(dim(c)^2 for c in objsii) + isapprox(m_dimsum, c_dimsum; atol=1e-8) || @show i, j, c_dimsum, m_dimsum +end \ No newline at end of file From 471ce1e18acf1a979631b9eea8402bb41fb95ac8 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 25 Mar 2025 14:03:25 +0100 Subject: [PATCH 036/206] update localtests --- test/localtests.jl | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index 3addf17..593309c 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -95,6 +95,9 @@ sp = Vect[A4Object](obj=>1, obj2=>1) A = TensorMap(ones, ComplexF64, sp βŠ— sp ← sp βŠ— sp) transpose(A, (2,4,), (1,3,)) +blocksectors(sp βŠ— sp) +@plansor fullcont[] := A[a b;a b] # problem here is that fusiontrees for all 12 units are given + # π’ž x β„³ example obj = A4Object(1,1,1) obj2 = A4Object(1,2,1) @@ -104,9 +107,6 @@ sp2 = Vect[A4Object](obj2=>1) @test_throws ArgumentError("invalid fusion channel") TensorMap(rand, ComplexF64, sp βŠ— sp2 ← sp) homspace = sp βŠ— sp2 ← sp2 A = TensorMap(ones, ComplexF64, homspace) -for sector in sectors(sp2) - @show sector -end fusiontrees(A) permute(space(A),((1,),(3,2))) transpose(A, (1,2,), (3,)) == A @@ -122,6 +122,10 @@ spfix = Vect[A4Object](one(obj)=>1) Afix = TensorMap(ones, ComplexF64, spfix βŠ— sp2 ← sp2) @plansor Acontfix[a] := Afix[a b;b] # should have a fusion tree +blocksectors(sp βŠ— sp2) +A = TensorMap(ones, ComplexF64, sp βŠ— sp2 ← sp βŠ— sp2) +@plansor fullcont[] := A[a b;a b] # same 12 fusiontrees problem + # completely off-diagonal example obj = A4Object(5, 4, 1) @@ -142,8 +146,15 @@ blocksectors(Aopt) == blocksectors(A) @plansor Acont[] := A[a b;a b] testsp = SU2Space(0=>1, 1=>1) +Atest = TensorMap(ones, ComplexF64, testsp βŠ— testsp ← testsp βŠ— testsp) +@plansor Aconttest[] := Atest[a b;a b] +# π’ž x β„³ ← β„³ x π’Ÿ +c = A4Object(1,1,1) +m = A4Object(1,2,1) +d = A4Object(2,2,1) +W = Vect[A4Object](c=>1) βŠ— Vect[A4Object](m=>1) ← Vect[A4Object](m=>1) βŠ— Vect[A4Object](d=>1) # bram stuff From b1afb014cc1676d9150cb9515a8b634f9eff3998 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 27 Mar 2025 12:10:11 +0100 Subject: [PATCH 037/206] add custom `scalar` for `TensorMap`s of `A4Object` --- src/bimodulesector.jl | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index c175a8d..264e231 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -246,6 +246,7 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, i, j, k, l = a.i, a.j, b.j, c.j colordict = _get_Fcache(I)[i][i, j, k, l] + @show a, b, c, d, e, f return get(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) do return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] end @@ -272,9 +273,19 @@ function TensorKit.blocksectors(W::HomSpace{S}) where {S<:GradedSpace{A4Object}} elseif Nβ‚‚ == 0 @assert N₁ != 0 "one of Type A4Object doesn't exist" return filter!(isone, collect(blocksectors(codom))) - elseif Nβ‚‚ <= N₁ # this filter will keep the blocksectors of the domain which appear in the codomain as well + elseif Nβ‚‚ <= N₁ # keep intersection return filter!(c -> hasblock(codom, c), collect(blocksectors(dom))) else return filter!(c -> hasblock(dom, c), collect(blocksectors(codom))) end -end \ No newline at end of file +end + +function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T<:Number, S<:GradedSpace{A4Object}} + _vector = findall(!iszero, values(blocks(t))) # should have 0 or 1 elements, since only one of the blocks could be non-zero + if isempty(_vector) + return zero(scalartype(t)) + end + return only(values(blocks(t))[only(_vector)]) +end + +# TODO: definitions for zero and oneunit of GradedSpace? dim? \ No newline at end of file From 0cb5b18f552a55a2a667cda1887133642e696b90 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 27 Mar 2025 12:10:31 +0100 Subject: [PATCH 038/206] comments and changes in tests --- test/test_A4.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 7a523e1..48985c5 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -19,9 +19,9 @@ end @test @constinferred(hash(s[1])) == hash(deepcopy(s[1])) @test isone(@constinferred(one(s[1]))) @constinferred dual(s[1]) - @constinferred dim(s[1]) # problem with this and 3 below + @constinferred dim(s[1]) @constinferred frobeniusschur(s[1]) - @constinferred Bsymbol(s...) + @constinferred Bsymbol(s...) # ill-defined test, doesn't necessarily exist and will error at dictionary keys @constinferred Fsymbol(s..., s...) end @@ -41,14 +41,14 @@ end end end F = hvcat(length(fs), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) + @test isapprox(F' * F, one(F); atol=1e-9, rtol=1e-9) # some are simply not unitary? end end end @testset "Pentagon equation" begin for a in objects, b in objects, c in objects, d in objects - @test pentagon_equation(a, b, c, d; atol=1e-12, rtol=1e-12) + @test pentagon_equation(a, b, c, d; atol=1e-9, rtol=1e-9) # ill-defined for same reason end end end From 303876e8aa9d885de658a9a257df7208cfa69042 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 27 Mar 2025 12:10:51 +0100 Subject: [PATCH 039/206] start of MPSKit tests --- test/localtests.jl | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index 593309c..0f8355b 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -143,7 +143,8 @@ Aopt = transpose(Aop, (2,4,), (1,3,)) blocksectors(At) == blocksectors(Aop) blocksectors(Aopt) == blocksectors(A) -@plansor Acont[] := A[a b;a b] +@plansor Acont[] := A[a b;a b] # ignore this error for now +@plansor Acont2[] := A[b a;b a] testsp = SU2Space(0=>1, 1=>1) Atest = TensorMap(ones, ComplexF64, testsp βŠ— testsp ← testsp βŠ— testsp) @@ -194,4 +195,42 @@ for i in 1:12, j in 1:12 # 18c m_dimsum = sum(dim(m)^2 for m in objsij) c_dimsum = sum(dim(c)^2 for c in objsii) isapprox(m_dimsum, c_dimsum; atol=1e-8) || @show i, j, c_dimsum, m_dimsum -end \ No newline at end of file +end + +############ MPSKit wow ############ +using MultiTensorKit +using TensorKit +using MPSKit, MPSKitModels +C1 = A4Object(1,1,1) +C0 = A4Object(1,1,4) # unit +M = A4Object(1,2,1) +D0 = A4Object(2,2,12) # unit +D1 = A4Object(2,2,1) +collect(D0 βŠ— D1) +collect(D1 βŠ— D1) + +P = Vect[A4Object](D0 => 1, D1 => 1) +h = TensorMap(ones, ComplexF64, P βŠ— P ← P βŠ— P) + +lattice = InfiniteChain(1) +# @profview begin sample_rate = 0.0002 +# for _ in 1:1 +# LocalOperator(h, lattice[1], lattice[2]) +# end +# end + +op = LocalOperator(h, lattice[1], lattice[2]) +InfiniteMPOHamiltonian([P, P], [op]) +H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); + +D = 2 +V = Vect[A4Object](M => D); +inf_init = InfiniteMPS([P], [V]) + +ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=200)); +expectation_value(ψ, H, envs) +entropy(ψ) +entanglement_spectrum(ψ) +correlation_length(ψ) +transfer_spectrum(ψ) +norm(ψ) From 5c1330e25a276558c569b4f843875d6098e4fd86 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 7 Apr 2025 12:48:45 +0200 Subject: [PATCH 040/206] quick fix to Fsymbol to return 0 when expected to be 0 --- src/bimodulesector.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 264e231..c9c47d5 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -246,10 +246,13 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, i, j, k, l = a.i, a.j, b.j, c.j colordict = _get_Fcache(I)[i][i, j, k, l] - @show a, b, c, d, e, f - return get(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) do - return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] - end + # @show a, b, c, d, e, f + # return get(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) do + # return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] + # end + return haskey(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) ? + colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] : + zeros(sectorscalartype(I), 1, 1, 1, 1) # quick fix to just return zeroes end @@ -264,6 +267,7 @@ function TensorKit.blocksectors(W::HomSpace{S}) where {S<:GradedSpace{A4Object}} dom = domain(W) N₁ = length(codom) Nβ‚‚ = length(dom) + @show N₁, Nβ‚‚ if N₁ == 0 && Nβ‚‚ == 0 # 0x0-dimensional TensorMap is just a scalar, return all units # this is a problem in full contractions where the coloring outside is π’ž return NTuple{12, A4Object}(one(A4Object(i,i,1)) for i in 1:12) # have to return all units b/c no info on W in this case From a77b77d8ea3caab0e57bb419a5578e11438a4629 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 8 Apr 2025 10:07:39 +0200 Subject: [PATCH 041/206] get blocksectors working --- src/bimodulesector.jl | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index c9c47d5..385ed79 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -259,15 +259,15 @@ end # interface with TensorKit where necessary #----------------------------------------- -function TensorKit.blocksectors(W::HomSpace{S}) where {S<:GradedSpace{A4Object}} +function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where + {S<:Union{GradedSpace{A4Object, NTuple{486, Int64}}, + SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}}, N₁, Nβ‚‚} sectortype(W) === Trivial && return OneOrNoneIterator(dim(domain(W)) != 0 && dim(codomain(W)) != 0, Trivial()) codom = codomain(W) dom = domain(W) - N₁ = length(codom) - Nβ‚‚ = length(dom) - @show N₁, Nβ‚‚ + @info "in the correct blocksectors" if N₁ == 0 && Nβ‚‚ == 0 # 0x0-dimensional TensorMap is just a scalar, return all units # this is a problem in full contractions where the coloring outside is π’ž return NTuple{12, A4Object}(one(A4Object(i,i,1)) for i in 1:12) # have to return all units b/c no info on W in this case @@ -284,12 +284,13 @@ function TensorKit.blocksectors(W::HomSpace{S}) where {S<:GradedSpace{A4Object}} end end -function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T<:Number, S<:GradedSpace{A4Object}} - _vector = findall(!iszero, values(blocks(t))) # should have 0 or 1 elements, since only one of the blocks could be non-zero - if isempty(_vector) - return zero(scalartype(t)) - end - return only(values(blocks(t))[only(_vector)]) -end +# function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T<:Number, S<:GradedSpace{A4Object}} +# @show t +# _vector = findall(!iszero, values(blocks(t))) # should have 0 or 1 elements, since only one of the blocks could be non-zero +# if isempty(_vector) +# return zero(scalartype(t)) +# end +# return only(values(blocks(t))[only(_vector)]) +# end # TODO: definitions for zero and oneunit of GradedSpace? dim? \ No newline at end of file From 5809f7761ecda2f8aa1fa81501f3c4ed7d0c7d98 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 8 Apr 2025 10:07:59 +0200 Subject: [PATCH 042/206] add BlockTensorKit dependency --- src/MultiTensorKit.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index f922133..659ca00 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -7,6 +7,9 @@ using DelimitedFiles using Artifacts using TensorKitSectors +using BlockTensorKit +import BlockTensorKit: SumSpace + using TensorKit import TensorKit: hasblock From 366110276d65c050ad99eb2052abece7d7b71098 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 8 Apr 2025 10:08:24 +0200 Subject: [PATCH 043/206] many many (temporary) dependencies --- Project.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 3bed8ca..7ff7818 100644 --- a/Project.toml +++ b/Project.toml @@ -5,17 +5,21 @@ version = "0.1.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" +MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502" +MPSKitModels = "ca635005-6f8c-4cd1-b51d-8491250ef2ab" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" +TestExtras = "5ed8adda-3752-4e41-b88a-e8b09835ee3a" +TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] Aqua = "0.8.9" Artifacts = "1.10, 1" JSON3 = "1.14.1" SafeTestsets = "0.1" -TensorKitSectors = "0.1.2" Test = "1.10" TestExtras = "0.3" julia = "1.10" From 4e2c0d58940cbe3ae0576e38b976ff5b57786255 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 9 Apr 2025 12:36:39 +0200 Subject: [PATCH 044/206] edit Fsymbol to return correctly shaped zero arrays --- src/bimodulesector.jl | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 385ed79..a162c3d 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -226,7 +226,6 @@ function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with return data_dict end -# TODO: do we want this type for Fcache? const Fcache = IdDict{Type{<:BimoduleSector}, Array{Dict{NTuple{4, Int64}, Dict{NTuple{6, Int64}, Array{ComplexF64, 4}}}}}() @@ -239,22 +238,25 @@ end function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I<:A4Object} - # TODO: should this error or return 0? - (a.j == b.i && b.j == c.i && a.i == d.i && c.j == d.j && - a.i == e.i && b.j == e.j && f.i == a.j && f.j == c.j) || - throw(ArgumentError("invalid fusion channel")) + # required to keep track of multiplicities where F-move is partially unallowed + # also deals with invalid fusion channels + Nsymbol(a, b, e) > 0 && Nsymbol(e, c, d) > 0 && + Nsymbol(b, c, f) > 0 && Nsymbol(a, f, d) > 0 || + return correct_zeros_F(a, b, c, d, e, f) i, j, k, l = a.i, a.j, b.j, c.j colordict = _get_Fcache(I)[i][i, j, k, l] - # @show a, b, c, d, e, f - # return get(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) do - # return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] - # end - return haskey(colordict, (a.label, b.label, c.label, d.label, e.label, f.label)) ? - colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] : - zeros(sectorscalartype(I), 1, 1, 1, 1) # quick fix to just return zeroes + return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] end +function correct_zeros_F(a::I, b::I, c::I, d::I, e::I, + f::I) where {I<:BimoduleSector} + sizes = [Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)] + for i in findall(iszero, sizes) + sizes[i] = 1 + end + return zeros(sectorscalartype(I), sizes...) +end # interface with TensorKit where necessary #----------------------------------------- @@ -267,7 +269,7 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where codom = codomain(W) dom = domain(W) - @info "in the correct blocksectors" + # @info "in the correct blocksectors" if N₁ == 0 && Nβ‚‚ == 0 # 0x0-dimensional TensorMap is just a scalar, return all units # this is a problem in full contractions where the coloring outside is π’ž return NTuple{12, A4Object}(one(A4Object(i,i,1)) for i in 1:12) # have to return all units b/c no info on W in this case From c1255d603e4abf4794d08f024d31eea6ef521a1a Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 9 Apr 2025 12:36:52 +0200 Subject: [PATCH 045/206] temporary BenchmarkTools dep --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index 7ff7818..b40fb6a 100644 --- a/Project.toml +++ b/Project.toml @@ -5,6 +5,7 @@ version = "0.1.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" From 75ec5c064127f4499e116d6ede869d8abd28b43c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 9 Apr 2025 12:37:27 +0200 Subject: [PATCH 046/206] more tinkering --- test/localtests.jl | 116 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 11 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index 0f8355b..4dc168d 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -213,24 +213,118 @@ P = Vect[A4Object](D0 => 1, D1 => 1) h = TensorMap(ones, ComplexF64, P βŠ— P ← P βŠ— P) lattice = InfiniteChain(1) -# @profview begin sample_rate = 0.0002 -# for _ in 1:1 -# LocalOperator(h, lattice[1], lattice[2]) -# end -# end - -op = LocalOperator(h, lattice[1], lattice[2]) -InfiniteMPOHamiltonian([P, P], [op]) H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); D = 2 V = Vect[A4Object](M => D); inf_init = InfiniteMPS([P], [V]) -ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=200)); +# (a, b, c, d, e, f) = (A4Object(2, 1, 1), A4Object(1, 2, 1), A4Object(2, 2, 11), A4Object(2, 2, 11), A4Object(2, 2, 9), A4Object(1, 2, 1)) +# Fsymbol(a,b,c,d,e,f) +# zeros(ComplexF64, Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)) + +# VUMPS +ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=500)); expectation_value(ψ, H, envs) + +# testing blocksectors +W = Vect[A4Object](A4Object(2, 2, 12)=>1) ← ProductSpace{GradedSpace{A4Object, NTuple{486, Int64}}, 0}() +W isa TensorMapSpace{GradedSpace{A4Object, NTuple{486, Int64}}} +W isa HomSpace +W isa HomSpace{S} where {S<:SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}} +W isa TensorMapSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}} + +# this appears as well (N1=N2=0) +W = ProductSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}, 0}() ← ProductSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}, 0}() +typeof(W) +W isa TensorMapSpace{S} where {S<:GradedSpace{A4Object, NTuple{486, Int64}}} +W isa HomSpace{S} where {S<:GradedSpace{A4Object, NTuple{486, Int64}}} +W isa HomSpace +W isa TensorMapSpace + +W isa TensorMapSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}, 0, 0} +W isa TensorMapSpace{GradedSpace{A4Object, NTuple{486, Int64}}, 0, 0} +TensorMapSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}, 0, 0} <: TensorMapSpace{GradedSpace{A4Object, NTuple{486, Int64}}, N₁,Nβ‚‚} where {N₁,Nβ‚‚} +W isa TensorSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}} + +GradedSpace{A4Object, NTuple{486, Int64}} <: BlockTensorKit.SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}} + entropy(ψ) entanglement_spectrum(ψ) -correlation_length(ψ) -transfer_spectrum(ψ) +transfer_spectrum(ψ,sector=C0) +correlation_length(ψ,sector=C0) norm(ψ) + +#IDMRG + +ψ, envs = find_groundstate(inf_init, H, IDMRG(verbosity=3, tol=1e-8, maxiter=100)); +expectation_value(ψ, H, envs) + +inf_init2 = InfiniteMPS([P,P], [V,V]) +H2 = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(2))); +ψ2, envs2 = find_groundstate(inf_init2, H2, IDMRG2(verbosity=3, tol=1e-8, maxiter=100)); +expectation_value(ψ2, H2, envs2) + +#QuasiParticleAnsatz + +momenta = range(0, 2Ο€, 4) +excE, excqp = excitations(H, QuasiparticleAnsatz(ishermitian=false), momenta, ψ, envs, sector=C0, num=1); + +# problem in QPA +f1 = FusionTree{A4Object}((A4Object(1, 2, 1), A4Object(2, 1, 1), A4Object(1, 2, 1)), A4Object(1, 2, 1), (false, false, false), (A4Object(1, 1, 2),), (3, 2)) +f2 = FusionTree{A4Object}((A4Object(2, 1, 1), A4Object(1, 1, 4)), A4Object(2, 1, 1), (true, true), (), (1,)) +i = 2 +a = A4Object(1, 2, 1) # (f1.uncoupled[1], f1.innerlines..., f1.coupled)[i-1] +b = A4Object(2, 1, 1) # f2.uncoupled[1] +c = A4Object(1, 1, 4) # f2.uncoupled[2] +d = A4Object(1, 1, 2) # (f1.uncoupled[1], f1.innerlines..., f1.coupled)[i] +e = A4Object(1, 1, 1) # in aβŠ—b +ep = A4Object(2, 1, 1) # f2.uncoupled[i] + +Fs = MultiTensorKit._get_Fcache(A4Object) +i,j,k,l = 1,2,1,1 +colordict = Fs[i][i,j,k,l] +colordict[(1,1,4,2,1,1)] +s1, s2, s3, s4 = Nsymbol(a,b,e), Nsymbol(e,c,d), Nsymbol(b,c,ep), Nsymbol(a,ep,d) +size = [s1, s2, s3, s4] + +using BenchmarkTools +@btime for i in 1:4 + size[i] == 0 ? size[i] = 1 : nothing +end +@btime for i in findall(iszero, size) + size[i] = 1 +end + +size +zeros(sectorscalartype(A4Object), size...) + + +# finite stuff +L = 6 +# lattice = FiniteChain(L) +# P = Vect[A4Object](D0 => 1, D1 => 1) +# D = 2 +# V = Vect[A4Object](M => D) + +# fin_init = FiniteMPS(L, P, V, left=V, right=V) +# Hfin = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); +# ψ, envs = find_groundstate(fin_init, Hfin, DMRG(verbosity=3, tol=1e-8, maxiter=100)); +# expectation_value(ψ, Hfin, envs) + +# entropy(ψ, round(Int, L/2)) +# entanglement_spectrum(ψ) +# exact_diagonalization(Hfin; sector=D0) + +# ψ, envs = find_groundstate(fin_init, Hfin, DMRG2(verbosity=3, tol=1e-8, maxiter=100)); +# expectation_value(ψ, Hfin, envs) + +# entropy(ψ, round(Int, L/2)) +# entanglement_spectrum(ψ) + +# HfinPBC = periodic_boundary_conditions(Hfin,L); +# ψ, envs = find_groundstate(fin_init, HfinPBC, DMRG(verbosity=3, tol=1e-8, maxiter=100)); +# expectation_value(ψ, HfinPBC, envs) + +# # excitations +# excE, excqp = excitations(Hfin, QuasiparticleAnsatz(ishermitian=false), ψ, envs;sector=C0, num=1) \ No newline at end of file From 50c4614ee97bfa57124e9912c4e15bada15cb487 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 9 Apr 2025 15:26:00 +0200 Subject: [PATCH 047/206] tests done for QPA infinite --- test/localtests.jl | 56 ++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index 4dc168d..48381ab 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -271,35 +271,37 @@ momenta = range(0, 2Ο€, 4) excE, excqp = excitations(H, QuasiparticleAnsatz(ishermitian=false), momenta, ψ, envs, sector=C0, num=1); # problem in QPA -f1 = FusionTree{A4Object}((A4Object(1, 2, 1), A4Object(2, 1, 1), A4Object(1, 2, 1)), A4Object(1, 2, 1), (false, false, false), (A4Object(1, 1, 2),), (3, 2)) -f2 = FusionTree{A4Object}((A4Object(2, 1, 1), A4Object(1, 1, 4)), A4Object(2, 1, 1), (true, true), (), (1,)) -i = 2 -a = A4Object(1, 2, 1) # (f1.uncoupled[1], f1.innerlines..., f1.coupled)[i-1] -b = A4Object(2, 1, 1) # f2.uncoupled[1] -c = A4Object(1, 1, 4) # f2.uncoupled[2] -d = A4Object(1, 1, 2) # (f1.uncoupled[1], f1.innerlines..., f1.coupled)[i] -e = A4Object(1, 1, 1) # in aβŠ—b -ep = A4Object(2, 1, 1) # f2.uncoupled[i] - -Fs = MultiTensorKit._get_Fcache(A4Object) -i,j,k,l = 1,2,1,1 -colordict = Fs[i][i,j,k,l] -colordict[(1,1,4,2,1,1)] -s1, s2, s3, s4 = Nsymbol(a,b,e), Nsymbol(e,c,d), Nsymbol(b,c,ep), Nsymbol(a,ep,d) -size = [s1, s2, s3, s4] - -using BenchmarkTools -@btime for i in 1:4 - size[i] == 0 ? size[i] = 1 : nothing -end -@btime for i in findall(iszero, size) - size[i] = 1 -end - -size -zeros(sectorscalartype(A4Object), size...) +# f1 = FusionTree{A4Object}((A4Object(1, 2, 1), A4Object(2, 1, 1), A4Object(1, 2, 1)), A4Object(1, 2, 1), (false, false, false), (A4Object(1, 1, 2),), (3, 2)) +# f2 = FusionTree{A4Object}((A4Object(2, 1, 1), A4Object(1, 1, 4)), A4Object(2, 1, 1), (true, true), (), (1,)) +# i = 2 +# a = A4Object(1, 2, 1) # (f1.uncoupled[1], f1.innerlines..., f1.coupled)[i-1] +# b = A4Object(2, 1, 1) # f2.uncoupled[1] +# c = A4Object(1, 1, 4) # f2.uncoupled[2] +# d = A4Object(1, 1, 2) # (f1.uncoupled[1], f1.innerlines..., f1.coupled)[i] +# e = A4Object(1, 1, 1) # in aβŠ—b +# ep = A4Object(2, 1, 1) # f2.uncoupled[i] + +# Fs = MultiTensorKit._get_Fcache(A4Object) +# i,j,k,l = 1,2,1,1 +# colordict = Fs[i][i,j,k,l] +# colordict[(1,1,4,2,1,1)] +# Fsymbol(a,b,c,d,e,ep) +# s1, s2, s3, s4 = Nsymbol(a,b,e), Nsymbol(e,c,d), Nsymbol(b,c,ep), Nsymbol(a,ep,d) +# size = [s1, s2, s3, s4] + +# using BenchmarkTools +# @btime for i in 1:4 +# size[i] == 0 ? size[i] = 1 : nothing +# end +# @btime for i in findall(iszero, size) +# size[i] = 1 +# end +# size +# zeros(sectorscalartype(A4Object), size...) +# util = similar(ψ.AL[1], space(parent(H)[1],1)[1]) +# MPSKit.fill_data!(util, one) # finite stuff L = 6 # lattice = FiniteChain(L) From afb8272aa4b816949fc67b4902be11245519bc87 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 9 Apr 2025 16:13:53 +0200 Subject: [PATCH 048/206] add custom `dim` of `GradedSpace` for `A4Object` to return floats as dimensions --- src/MultiTensorKit.jl | 2 +- src/bimodulesector.jl | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 659ca00..fe059f3 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -11,7 +11,7 @@ using BlockTensorKit import BlockTensorKit: SumSpace using TensorKit -import TensorKit: hasblock +import TensorKit: hasblock, dim include("bimodulesector.jl") diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index a162c3d..0e682e8 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -295,4 +295,9 @@ end # return only(values(blocks(t))[only(_vector)]) # end -# TODO: definitions for zero and oneunit of GradedSpace? dim? \ No newline at end of file +# TODO: definitions for zero and oneunit of GradedSpace? + +function dim(V::GradedSpace{I, NTuple{486, Int64}}) where {I<:A4Object} + return reduce(+, dim(V, c) * dim(c) for c in sectors(V); + init=zero(Float64)) +end \ No newline at end of file From def64eadbd2f0db87b1e237c749bc3b217488b31 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 9 Apr 2025 17:34:22 +0200 Subject: [PATCH 049/206] define `oneunit` of `A4Object`-graded vector spaces where possible --- src/bimodulesector.jl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 0e682e8..2fa0002 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -300,4 +300,21 @@ end function dim(V::GradedSpace{I, NTuple{486, Int64}}) where {I<:A4Object} return reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(Float64)) +end + +# limited oneunit +function Base.oneunit(S::GradedSpace{A4Object, NTuple{486, Int64}}) + allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || + throw(ArgumentError("sectors of $S are not all equal")) + first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) + sector = one(first(sectors(S))) + return β„‚[A4Object](sector => 1) +end + +function Base.oneunit(S::SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}) + allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || + throw(ArgumentError("sectors of $S are not all equal")) + first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) + sector = one(first(sectors(S))) + return SumSpace(β„‚[A4Object](sector => 1)) end \ No newline at end of file From c686b9ba89876f893e6891c4afa08f7af8e24974 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 10 Apr 2025 10:55:56 +0200 Subject: [PATCH 050/206] finite tests --- test/localtests.jl | 48 +++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index 48381ab..c95c764 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -302,31 +302,39 @@ excE, excqp = excitations(H, QuasiparticleAnsatz(ishermitian=false), momenta, ψ # util = similar(ψ.AL[1], space(parent(H)[1],1)[1]) # MPSKit.fill_data!(util, one) + +# quick test on complex f symbols and dimensions +testp = Vect[A4Object](one(A4Object(i,i,1)) => 1 for i in 1:12) +dim(testp) + # finite stuff L = 6 -# lattice = FiniteChain(L) -# P = Vect[A4Object](D0 => 1, D1 => 1) -# D = 2 -# V = Vect[A4Object](M => D) +lattice = FiniteChain(L) +P = Vect[A4Object](D0 => 1, D1 => 1) +D = 2 +V = Vect[A4Object](M => D) -# fin_init = FiniteMPS(L, P, V, left=V, right=V) -# Hfin = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); -# ψ, envs = find_groundstate(fin_init, Hfin, DMRG(verbosity=3, tol=1e-8, maxiter=100)); -# expectation_value(ψ, Hfin, envs) +fin_init = FiniteMPS(L, P, V, left=V, right=V) +Hfin = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); +ψfin, envsfin = find_groundstate(fin_init, Hfin, DMRG(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))); +expectation_value(ψfin, Hfin, envsfin) / (L-1) -# entropy(ψ, round(Int, L/2)) -# entanglement_spectrum(ψ) -# exact_diagonalization(Hfin; sector=D0) +entropy(ψfin, round(Int, L/2)) +entanglement_spectrum(ψfin, round(Int, L/2)) +Es, states, convhist = exact_diagonalization(Hfin; sector=D0); +Es / (L-1) -# ψ, envs = find_groundstate(fin_init, Hfin, DMRG2(verbosity=3, tol=1e-8, maxiter=100)); -# expectation_value(ψ, Hfin, envs) +ψfin2, envsfin2 = find_groundstate(fin_init, Hfin, DMRG2(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))); +expectation_value(ψfin2, Hfin, envsfin2) / (L-1) -# entropy(ψ, round(Int, L/2)) -# entanglement_spectrum(ψ) +entropy(ψfin2, round(Int, L/2)) +entanglement_spectrum(ψfin2) -# HfinPBC = periodic_boundary_conditions(Hfin,L); -# ψ, envs = find_groundstate(fin_init, HfinPBC, DMRG(verbosity=3, tol=1e-8, maxiter=100)); -# expectation_value(ψ, HfinPBC, envs) +S = left_virtualspace(Hfin, 1) +oneunit(S) +eltype(S) +oneunit(eltype(S)) # problematic -# # excitations -# excE, excqp = excitations(Hfin, QuasiparticleAnsatz(ishermitian=false), ψ, envs;sector=C0, num=1) \ No newline at end of file +# excitations +excEfin, excqpfin = excitations(Hfin, QuasiparticleAnsatz(ishermitian=false), ψfin, envsfin;sector=C0, num=1); +excEfin From 50a14d6f903cd84f7931220ae143431ff3193189 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 10 Apr 2025 10:57:21 +0200 Subject: [PATCH 051/206] remove unnecessary check in specialised blocksectors --- src/bimodulesector.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 2fa0002..4c2a172 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -264,9 +264,6 @@ end function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where {S<:Union{GradedSpace{A4Object, NTuple{486, Int64}}, SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}}, N₁, Nβ‚‚} - sectortype(W) === Trivial && - return OneOrNoneIterator(dim(domain(W)) != 0 && dim(codomain(W)) != 0, Trivial()) - codom = codomain(W) dom = domain(W) # @info "in the correct blocksectors" @@ -295,7 +292,7 @@ end # return only(values(blocks(t))[only(_vector)]) # end -# TODO: definitions for zero and oneunit of GradedSpace? +# TODO: definition for zero/one of GradedSpace? function dim(V::GradedSpace{I, NTuple{486, Int64}}) where {I<:A4Object} return reduce(+, dim(V, c) * dim(c) for c in sectors(V); From 86525d25b99a6f583935f602a498be9af956ca6f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 10 Apr 2025 16:11:01 +0200 Subject: [PATCH 052/206] clean up dim and oneunit to accept `GradedSpace{<:BimoduleSector}` --- src/bimodulesector.jl | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 4c2a172..f30ca56 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -292,15 +292,12 @@ end # return only(values(blocks(t))[only(_vector)]) # end -# TODO: definition for zero/one of GradedSpace? +# TODO: definition for zero of GradedSpace? -function dim(V::GradedSpace{I, NTuple{486, Int64}}) where {I<:A4Object} - return reduce(+, dim(V, c) * dim(c) for c in sectors(V); - init=zero(Float64)) -end +dim(V::GradedSpace{<:BimoduleSector}) = reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(Float64)) # limited oneunit -function Base.oneunit(S::GradedSpace{A4Object, NTuple{486, Int64}}) +function Base.oneunit(S::GradedSpace{<:BimoduleSector}) allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || throw(ArgumentError("sectors of $S are not all equal")) first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) @@ -314,4 +311,12 @@ function Base.oneunit(S::SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}) first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) sector = one(first(sectors(S))) return SumSpace(β„‚[A4Object](sector => 1)) -end \ No newline at end of file +end + +# function Base.oneunit(S::SumSpace{GradedSpace{<:BimoduleSector}}) +# allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || +# throw(ArgumentError("sectors of $S are not all equal")) +# first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) +# sector = one(first(sectors(S))) +# return SumSpace(β„‚[A4Object](sector => 1)) +# end \ No newline at end of file From fedb1e4a920c2f015e263e765d4a6054edc86e68 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 10 Apr 2025 16:26:04 +0200 Subject: [PATCH 053/206] clean up `oneunit` of `SumSpace` to accept `SumSpace{<:GradedSpace{<:BimoduleSector}}` --- src/bimodulesector.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index f30ca56..487e3ba 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -305,18 +305,18 @@ function Base.oneunit(S::GradedSpace{<:BimoduleSector}) return β„‚[A4Object](sector => 1) end -function Base.oneunit(S::SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}) - allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || - throw(ArgumentError("sectors of $S are not all equal")) - first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) - sector = one(first(sectors(S))) - return SumSpace(β„‚[A4Object](sector => 1)) -end - -# function Base.oneunit(S::SumSpace{GradedSpace{<:BimoduleSector}}) +# function Base.oneunit(S::SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}) # allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || # throw(ArgumentError("sectors of $S are not all equal")) # first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) # sector = one(first(sectors(S))) # return SumSpace(β„‚[A4Object](sector => 1)) -# end \ No newline at end of file +# end + +function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) + allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || + throw(ArgumentError("sectors of $S are not all equal")) + first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) + sector = one(first(sectors(S))) + return SumSpace(β„‚[A4Object](sector => 1)) +end \ No newline at end of file From d5862b6d9a9bfea0668c7bfe2f6381a4ada9fe81 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Thu, 10 Apr 2025 13:09:54 -0400 Subject: [PATCH 054/206] Fix `dim` --- src/bimodulesector.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 487e3ba..ad81fca 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -294,7 +294,10 @@ end # TODO: definition for zero of GradedSpace? -dim(V::GradedSpace{<:BimoduleSector}) = reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(Float64)) +function TensorKit.dim(V::GradedSpace{<:BimoduleSector}) + T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) + return reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(T)) +end # limited oneunit function Base.oneunit(S::GradedSpace{<:BimoduleSector}) @@ -319,4 +322,4 @@ function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) sector = one(first(sectors(S))) return SumSpace(β„‚[A4Object](sector => 1)) -end \ No newline at end of file +end From 722ea952e0c4360bf4cd3b681346a3faf367f3fb Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Thu, 10 Apr 2025 16:51:24 -0400 Subject: [PATCH 055/206] performance improvements --- src/bimodulesector.jl | 76 +++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 47 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index ad81fca..1449961 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -76,6 +76,7 @@ const Ncache = IdDict{Type{<:BimoduleSector},Array{Dict{NTuple{3,Int},Int},3}}() function _get_Ncache(::Type{T}) where {T<:BimoduleSector} global Ncache return get!(Ncache, T) do + @debug "loading Nsymbol cache for $T" return extract_Nsymbol(T) end end @@ -93,6 +94,7 @@ const Dualcache = IdDict{Type{<:BimoduleSector},Tuple{Vector{Int64}, Matrix{Vect function _get_dual_cache(::Type{T}) where {T<:BimoduleSector} global Dualcache return get!(Dualcache, T) do + @debug "loading dual cache for $T" return extract_dual(T) end end @@ -169,45 +171,30 @@ function Base.conj(a::BimoduleSector) end function extract_Fsymbol(::Type{A4Object}) - return mapreduce((colordict, Fdict) -> cat(colordict, Fdict; dims=1), 1:12) do i + result = Dict{NTuple{4,Int},Dict{NTuple{6,Int},Array{ComplexF64,4}}}() + for i in 1:12 filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") + @debug "loading $filename" @assert isfile(filename) "cannot find $filename" - txt_string = read(filename, String) - Farray_part = copy(readdlm(IOBuffer(txt_string))); # now a matrix with 16 columns - Farray_part = convert_Fs(Farray_part) - dict_data = Iterators.map(Farray_part) do (colors, colordict) - i,j,k,l = colors - Fdict = Dict{NTuple{6,Int},Array{ComplexF64,4}}() - for (labels, Fvals) in colordict - a, b, c, d, e, f = labels + Farray_part = readdlm(filename) + for ((i, j, k, l), colordict) in convert_Fs(Farray_part) + result[(i, j, k, l)] = Dict{NTuple{6,Int},Array{ComplexF64,4}}() + for ((a, b, c, d, e, f), Fvals) in colordict a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), (k, l, c), (i, l, d), (i, k, e), (j, l, f))) - result = Array{ComplexF64,4}(undef, - (Nsymbol(a_ob, b_ob, e_ob), - Nsymbol(e_ob, c_ob, d_ob), - Nsymbol(b_ob, c_ob, f_ob), - Nsymbol(a_ob, f_ob, d_ob))) - - # due to sparse data, some Fvals are missing and we need to fill in zeros - # error("Mismatch in sizes: $a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob") - for index in CartesianIndices(result) - if index βˆ‰ [first(ind) for ind in Fvals] #wrong condition - push!(Fvals, index => ComplexF64(0)) - end + result[(i, j, k, l)][(a, b, c, d, e, f)] = zeros(ComplexF64, + Nsymbol(a_ob, b_ob, e_ob), + Nsymbol(e_ob, c_ob, d_ob), + Nsymbol(b_ob, c_ob, f_ob), + Nsymbol(a_ob, f_ob, d_ob)) + for (I, v) in Fvals + result[(i, j, k, l)][(a, b, c, d, e, f)][I] = v end - # s1, s2 = length(result), length(Fvals) - # @assert s1 == s2 "$a_ob, $b_ob, $c_ob, $d_ob, $e_ob, $f_ob, $Fvals, $result" - map!(result, reshape(Fvals, size(result))) do pair - return pair[2] - end - - Fdict[(a, b, c, d, e, f)] = result end - return colors => Fdict end - return Dict(dict_data) end + return result end function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with 16 columns @@ -216,9 +203,8 @@ function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with # a Dict with keys (a,b,c,d,e,f) and vals # a pair of (mu, nu, rho, sigma) and the F value for row in eachrow(Farray_part) - row = string.(split(string(row)[2:(end - 1)], ", ")) - i, j, k, l, a, b, c, d, e, f, mu, nu, rho, sigma = Int.(parse.(Float64, row[1:14])) - v = complex(parse.(Float64, row[15:16])...) + i, j, k, l, a, b, c, d, e, f, mu, nu, rho, sigma = Int.(@view(row[1:14])) + v = complex(row[15], row[16]) colordict = get!(data_dict, (i,j,k,l), Dict{NTuple{6,Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}()) Fdict = get!(colordict, (a, b, c, d, e, f), Vector{Pair{CartesianIndex{4}, ComplexF64}}()) push!(Fdict, CartesianIndex(mu, nu, rho, sigma) => v) @@ -227,11 +213,12 @@ function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with end const Fcache = IdDict{Type{<:BimoduleSector}, - Array{Dict{NTuple{4, Int64}, Dict{NTuple{6, Int64}, Array{ComplexF64, 4}}}}}() + Dict{NTuple{4,Int64},Dict{NTuple{6,Int64},Array{ComplexF64,4}}}}() function _get_Fcache(::Type{T}) where {T<:BimoduleSector} global Fcache return get!(Fcache, T) do + @debug "loading Fsymbol cache for $T" return extract_Fsymbol(T) end end @@ -240,24 +227,19 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I<:A4Object} # required to keep track of multiplicities where F-move is partially unallowed # also deals with invalid fusion channels - Nsymbol(a, b, e) > 0 && Nsymbol(e, c, d) > 0 && - Nsymbol(b, c, f) > 0 && Nsymbol(a, f, d) > 0 || - return correct_zeros_F(a, b, c, d, e, f) + Nabe = Nsymbol(a, b, e) + Necd = Nsymbol(e, c, d) + Nbcf = Nsymbol(b, c, f) + Nafd = Nsymbol(a, f, d) + + Nabe > 0 && Necd > 0 && Nbcf > 0 && Nafd > 0 || + return zeros(sectorscalartype(I), Nabe, Necd, Nbcf, Nafd) i, j, k, l = a.i, a.j, b.j, c.j - colordict = _get_Fcache(I)[i][i, j, k, l] + colordict = _get_Fcache(I)[i, j, k, l] return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] end -function correct_zeros_F(a::I, b::I, c::I, d::I, e::I, - f::I) where {I<:BimoduleSector} - sizes = [Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)] - for i in findall(iszero, sizes) - sizes[i] = 1 - end - return zeros(sectorscalartype(I), sizes...) -end - # interface with TensorKit where necessary #----------------------------------------- From d5b3006d7c18fb593efab4a3e7a9abdb6ed1ffd6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 11 Apr 2025 09:22:34 +0200 Subject: [PATCH 056/206] fix `convert_Fs` to not contain elaborate (useless) identity function --- src/bimodulesector.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index ad81fca..6826dd4 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -216,9 +216,8 @@ function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with # a Dict with keys (a,b,c,d,e,f) and vals # a pair of (mu, nu, rho, sigma) and the F value for row in eachrow(Farray_part) - row = string.(split(string(row)[2:(end - 1)], ", ")) - i, j, k, l, a, b, c, d, e, f, mu, nu, rho, sigma = Int.(parse.(Float64, row[1:14])) - v = complex(parse.(Float64, row[15:16])...) + i, j, k, l, a, b, c, d, e, f, mu, nu, rho, sigma = Int.(row[1:14]) + v = complex(row[15:16]...) colordict = get!(data_dict, (i,j,k,l), Dict{NTuple{6,Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}()) Fdict = get!(colordict, (a, b, c, d, e, f), Vector{Pair{CartesianIndex{4}, ComplexF64}}()) push!(Fdict, CartesianIndex(mu, nu, rho, sigma) => v) From 76df51bb029f483e86e27f815d9ce3862376775f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 11 Apr 2025 12:28:22 +0200 Subject: [PATCH 057/206] `FiniteExcited` and `changebonds` tests --- test/localtests.jl | 50 +++++++++++++--------------------------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index c95c764..95cc88f 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -270,39 +270,6 @@ expectation_value(ψ2, H2, envs2) momenta = range(0, 2Ο€, 4) excE, excqp = excitations(H, QuasiparticleAnsatz(ishermitian=false), momenta, ψ, envs, sector=C0, num=1); -# problem in QPA -# f1 = FusionTree{A4Object}((A4Object(1, 2, 1), A4Object(2, 1, 1), A4Object(1, 2, 1)), A4Object(1, 2, 1), (false, false, false), (A4Object(1, 1, 2),), (3, 2)) -# f2 = FusionTree{A4Object}((A4Object(2, 1, 1), A4Object(1, 1, 4)), A4Object(2, 1, 1), (true, true), (), (1,)) -# i = 2 -# a = A4Object(1, 2, 1) # (f1.uncoupled[1], f1.innerlines..., f1.coupled)[i-1] -# b = A4Object(2, 1, 1) # f2.uncoupled[1] -# c = A4Object(1, 1, 4) # f2.uncoupled[2] -# d = A4Object(1, 1, 2) # (f1.uncoupled[1], f1.innerlines..., f1.coupled)[i] -# e = A4Object(1, 1, 1) # in aβŠ—b -# ep = A4Object(2, 1, 1) # f2.uncoupled[i] - -# Fs = MultiTensorKit._get_Fcache(A4Object) -# i,j,k,l = 1,2,1,1 -# colordict = Fs[i][i,j,k,l] -# colordict[(1,1,4,2,1,1)] -# Fsymbol(a,b,c,d,e,ep) -# s1, s2, s3, s4 = Nsymbol(a,b,e), Nsymbol(e,c,d), Nsymbol(b,c,ep), Nsymbol(a,ep,d) -# size = [s1, s2, s3, s4] - -# using BenchmarkTools -# @btime for i in 1:4 -# size[i] == 0 ? size[i] = 1 : nothing -# end -# @btime for i in findall(iszero, size) -# size[i] = 1 -# end - -# size -# zeros(sectorscalartype(A4Object), size...) - -# util = similar(ψ.AL[1], space(parent(H)[1],1)[1]) -# MPSKit.fill_data!(util, one) - # quick test on complex f symbols and dimensions testp = Vect[A4Object](one(A4Object(i,i,1)) => 1 for i in 1:12) dim(testp) @@ -314,9 +281,10 @@ P = Vect[A4Object](D0 => 1, D1 => 1) D = 2 V = Vect[A4Object](M => D) +dmrgalg = DMRG(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) fin_init = FiniteMPS(L, P, V, left=V, right=V) Hfin = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); -ψfin, envsfin = find_groundstate(fin_init, Hfin, DMRG(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))); +ψfin, envsfin = find_groundstate(fin_init, Hfin, dmrgalg); expectation_value(ψfin, Hfin, envsfin) / (L-1) entropy(ψfin, round(Int, L/2)) @@ -324,11 +292,13 @@ entanglement_spectrum(ψfin, round(Int, L/2)) Es, states, convhist = exact_diagonalization(Hfin; sector=D0); Es / (L-1) -ψfin2, envsfin2 = find_groundstate(fin_init, Hfin, DMRG2(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))); +#DMRG2 weird real data incompatibility with sector type A4Object +dmrg2alg = DMRG2(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) +ψfin2, envsfin2 = find_groundstate(fin_init, Hfin, dmrg2alg); expectation_value(ψfin2, Hfin, envsfin2) / (L-1) entropy(ψfin2, round(Int, L/2)) -entanglement_spectrum(ψfin2) +entanglement_spectrum(ψfin2, round(Int, L/2)) S = left_virtualspace(Hfin, 1) oneunit(S) @@ -338,3 +308,11 @@ oneunit(eltype(S)) # problematic # excitations excEfin, excqpfin = excitations(Hfin, QuasiparticleAnsatz(ishermitian=false), ψfin, envsfin;sector=C0, num=1); excEfin + +excFIN, excqpFIN = excitations(Hfin, FiniteExcited(;gsalg=DMRG2(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))), ψfin;num=1); +excFIN + +# changebonds test +dim(left_virtualspace(ψ, 1)) +ψch, envsch = changebonds(ψ, H, OptimalExpand(; trscheme=truncerr(1e-3)), envs) +dim(left_virtualspace(ψch, 1)) \ No newline at end of file From b5155bf600f4c8e8ce2405f20e37e9d459d5cf4f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 11 Apr 2025 17:46:47 +0200 Subject: [PATCH 058/206] time evolution test + `(In)FiniteMPOHamiltonian` constructor w/o `LocalOperator` --- test/localtests.jl | 85 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/test/localtests.jl b/test/localtests.jl index 95cc88f..4830d0d 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -273,6 +273,7 @@ excE, excqp = excitations(H, QuasiparticleAnsatz(ishermitian=false), momenta, ψ # quick test on complex f symbols and dimensions testp = Vect[A4Object](one(A4Object(i,i,1)) => 1 for i in 1:12) dim(testp) +oneunit(testp) # finite stuff L = 6 @@ -284,6 +285,7 @@ V = Vect[A4Object](M => D) dmrgalg = DMRG(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) fin_init = FiniteMPS(L, P, V, left=V, right=V) Hfin = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); +open_boundary_conditions(H, L) == Hfin ψfin, envsfin = find_groundstate(fin_init, Hfin, dmrgalg); expectation_value(ψfin, Hfin, envsfin) / (L-1) @@ -315,4 +317,85 @@ excFIN # changebonds test dim(left_virtualspace(ψ, 1)) ψch, envsch = changebonds(ψ, H, OptimalExpand(; trscheme=truncerr(1e-3)), envs) -dim(left_virtualspace(ψch, 1)) \ No newline at end of file +dim(left_virtualspace(ψch, 1)) + +# time evolution +ψt, envst = timestep(ψ, H, 10, 1, TDVP(integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=false)), envs); +et = expectation_value(ψt, H, envst) +e = expectation_value(ψ, H, envs) +isapprox(et, e*exp(-1im * 10 * e); atol=1e-1) # not hermitian + + +# testing InfiniteMPOHamiltonian and FiniteMPOHamiltonian constructor not relying on MPSKitModels +function S_x(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} + return if spin == 1 // 2 + TensorMap(T[0 1; 1 0], β„‚^2 ← β„‚^2) + elseif spin == 1 + TensorMap(T[0 1 0; 1 0 1; 0 1 0], β„‚^3 ← β„‚^3) / sqrt(2) + else + throw(ArgumentError("spin $spin not supported")) + end +end +function S_y(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} + return if spin == 1 // 2 + TensorMap(T[0 -im; im 0], β„‚^2 ← β„‚^2) + elseif spin == 1 + TensorMap(T[0 -im 0; im 0 -im; 0 im 0], β„‚^3 ← β„‚^3) / sqrt(2) + else + throw(ArgumentError("spin $spin not supported")) + end +end +function S_z(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} + return if spin == 1 // 2 + TensorMap(T[1 0; 0 -1], β„‚^2 ← β„‚^2) + elseif spin == 1 + TensorMap(T[1 0 0; 0 0 0; 0 0 -1], β„‚^3 ← β„‚^3) + else + throw(ArgumentError("spin $spin not supported")) + end +end +function S_xx(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} + return S_x(Trivial, T; spin) βŠ— S_x(Trivial, T; spin) +end +function S_yy(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} + return S_y(Trivial, T; spin) βŠ— S_y(Trivial, T; spin) +end +function S_zz(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} + return S_z(Trivial, T; spin) βŠ— S_z(Trivial, T; spin) +end + +function transverse_field_isingg(; g=1.0, L=Inf) + X = S_x(; spin=1 // 2) + ZZ = S_zz(; spin=1 // 2) + E = TensorMap(ComplexF64[1 0; 0 1], β„‚^2 ← β„‚^2) + + # lattice = L == Inf ? PeriodicVector([β„‚^2]) : fill(β„‚^2, L) + if L == Inf + lattice = PeriodicArray([β„‚^2]) + return InfiniteMPOHamiltonian(lattice, + (i, i + 1) => -(ZZ + (g / 2) * (X βŠ— E + E βŠ— X)) + for i in 1:1) + # return MPOHamiltonian(-ZZ - (g / 2) * (X βŠ— E + E βŠ— X)) + else + lattice = fill(β„‚^2, L) + return FiniteMPOHamiltonian(lattice, + (i, i + 1) => -(ZZ + (g / 2) * (X βŠ— E + E βŠ— X)) + for i in 1:(L - 1)) #+ + # FiniteMPOHamiltonian(lattice, (i,) => -g * X for i in 1:L) + end + + H = S_zz(; spin=1 // 2) + (g / 2) * (X βŠ— E + E βŠ— X) + return if L == Inf + MPOHamiltonian(H) + else + FiniteMPOHamiltonian(fill(β„‚^2, L), (i, i + 1) => H for i in 1:(L - 1)) + end + return MPOHamiltonian(-H) +end + + +transverse_field_isingg(; g=1.0, L=3) +sp = Vect[FibonacciAnyon](:I=>1, :Ο„ => 1) +t = TensorMap(ones, ComplexF64, sp ← sp) +InfiniteMPOHamiltonian(PeriodicArray([sp]), i => t for i in 1:1) +H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(1))); \ No newline at end of file From 2e64e632b6b4726fdba9fc49b08bb90636978f90 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 17 Apr 2025 17:39:27 +0200 Subject: [PATCH 059/206] add custom `insertleftunit` and `insertrightunit` to evaluate a valid `oneunit` --- src/MultiTensorKit.jl | 3 +++ src/bimodulesector.jl | 28 +++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index fe059f3..c321bff 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -7,6 +7,9 @@ using DelimitedFiles using Artifacts using TensorKitSectors +using TupleTools +import TupleTools: insertafter + using BlockTensorKit import BlockTensorKit: SumSpace diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 6826dd4..8d6593e 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -293,7 +293,7 @@ end # TODO: definition for zero of GradedSpace? -function TensorKit.dim(V::GradedSpace{<:BimoduleSector}) +function dim(V::GradedSpace{<:BimoduleSector}) T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) return reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(T)) end @@ -322,3 +322,29 @@ function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) sector = one(first(sectors(S))) return SumSpace(β„‚[A4Object](sector => 1)) end + +# maybe from the homspace +function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P)); + conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{<:I}, N} where {I<:BimoduleSector} + #possible change to rightone of correct space for N = 0 + u = N > 0 ? oneunit(P[1]) : error("no unit object in this space") + if dual + u = TensorKit.dual(u) + end + if conj + u = TensorKit.conj(u) + end + return ProductSpace(TupleTools.insertafter(P.spaces, i, (u,))) +end + +function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P) + 1); + conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{<:I}, N} where {I<:BimoduleSector} + u = N > 0 ? oneunit(P[1]) : error("no unit object in this space") + if dual + u = TensorKit.dual(u) + end + if conj + u = TensorKit.conj(u) + end + return ProductSpace(TupleTools.insertafter(P.spaces, i - 1, (u,))) +end \ No newline at end of file From 52063d94c67d64258bc1cd29b597406a05110df5 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 22 Apr 2025 13:31:49 -0400 Subject: [PATCH 060/206] replace `map` with `for` loop --- src/bimodulesector.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 20a5695..d235625 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -138,10 +138,12 @@ function extract_dual(::Type{A4Object}) end end - allduals = fill(x -> Vector{Int}(), ncats, ncats)(0) # ncats square matrix of vectors - map(1:ncats) do i + allduals = Matrix{Vector{Int}}(undef, ncats, ncats) # ncats square matrix of vectors + for i in 1:ncats nobji = maximum(first, keys(N[i, i, i])) - map(1:ncats) do j + for j in 1:ncats + allduals[i, j] = Int[] + nobjj = maximum(first, keys(N[j, j, j])) # the nested vectors contain the duals of the objects in π’ž_ij, which are in C_ji Niji = N[i, j, i] # π’ž_ij x π’ž_ji -> C_ii From a7005779c24a18ebe11c567c5a727df2a506cb32 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Tue, 22 Apr 2025 13:40:40 -0400 Subject: [PATCH 061/206] Test all pentagons --- test/test_A4.jl | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 48985c5..81cb8bd 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -45,10 +45,20 @@ end end end end +end - @testset "Pentagon equation" begin - for a in objects, b in objects, c in objects, d in objects - @test pentagon_equation(a, b, c, d; atol=1e-9, rtol=1e-9) # ill-defined for same reason +@testset "Pentagon equation" begin + objects = collect(values(A4Object)) + for a in objects + for b in objects + a.j == b.i || continue # skip if not compatible + for c in objects + b.j == c.i || continue # skip if not compatible + for d in objects + c.j == d.i || continue # skip if not compatible + @test pentagon_equation(a, b, c, d; atol=1e-9, rtol=1e-9) # ill-defined for same reason + end + end end end end @@ -63,4 +73,4 @@ end @constinferred dual(s) @test dual(s) == A4Object(j, i, MultiTensorKit._get_dual_cache(I)[2][i,j][s.label]) @test dual(dual(s)) == s -end \ No newline at end of file +end From ed8019d04c8b3a77f64fc96aac889f1a5597daf8 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 23 Apr 2025 08:36:49 +0200 Subject: [PATCH 062/206] more local tests --- test/localtests.jl | 269 ++++++++++++++++++++++++++++----------------- 1 file changed, 166 insertions(+), 103 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index 4830d0d..b3d1b9f 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -197,35 +197,9 @@ for i in 1:12, j in 1:12 # 18c isapprox(m_dimsum, c_dimsum; atol=1e-8) || @show i, j, c_dimsum, m_dimsum end -############ MPSKit wow ############ -using MultiTensorKit -using TensorKit -using MPSKit, MPSKitModels -C1 = A4Object(1,1,1) -C0 = A4Object(1,1,4) # unit -M = A4Object(1,2,1) -D0 = A4Object(2,2,12) # unit -D1 = A4Object(2,2,1) -collect(D0 βŠ— D1) -collect(D1 βŠ— D1) - -P = Vect[A4Object](D0 => 1, D1 => 1) -h = TensorMap(ones, ComplexF64, P βŠ— P ← P βŠ— P) - -lattice = InfiniteChain(1) -H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); - -D = 2 -V = Vect[A4Object](M => D); -inf_init = InfiniteMPS([P], [V]) - -# (a, b, c, d, e, f) = (A4Object(2, 1, 1), A4Object(1, 2, 1), A4Object(2, 2, 11), A4Object(2, 2, 11), A4Object(2, 2, 9), A4Object(1, 2, 1)) -# Fsymbol(a,b,c,d,e,f) -# zeros(ComplexF64, Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)) - -# VUMPS -ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=500)); -expectation_value(ψ, H, envs) +(a, b, c, d, e, f) = (A4Object(2, 1, 1), A4Object(1, 2, 1), A4Object(2, 2, 11), A4Object(2, 2, 11), A4Object(2, 2, 9), A4Object(1, 2, 1)) +Fsymbol(a,b,c,d,e,f) +zeros(ComplexF64, Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)) # testing blocksectors W = Vect[A4Object](A4Object(2, 2, 12)=>1) ← ProductSpace{GradedSpace{A4Object, NTuple{486, Int64}}, 0}() @@ -249,6 +223,46 @@ W isa TensorSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}} GradedSpace{A4Object, NTuple{486, Int64}} <: BlockTensorKit.SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}} +############ MPSKit wow ############ +using MultiTensorKit +using TensorKit +using MPSKit, MPSKitModels +C1 = A4Object(1,1,1) +C0 = A4Object(1,1,4) # unit +M = A4Object(1,2,1) +D0 = A4Object(2,2,12) # unit +D1 = A4Object(2,2,2) # self-dual object +collect(D0 βŠ— D1) +collect(D1 βŠ— D1) + +P = Vect[A4Object](D0 => 1, D1 => 1) +h = TensorMap(ones, ComplexF64, P βŠ— P ← P βŠ— P) + +lattice = InfiniteChain(1); +H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); + +# testing insertleft/rightunit +sp = SU2Space(0=>1, 1=>1) +ht = TensorMap(ones, ComplexF64, P ← P) +htl = TensorMap(ones, ComplexF64, P ← one(P)) +htr = TensorMap(ones, ComplexF64, one(P) ← P) +htnone = TensorMap(ones, ComplexF64, one(P) ← one(P)) +insertrightunit(htr) # adding to empty space +insertleftunit(htr) +insertrightunit(htl) +insertleftunit(htl) # adding to empty space +insertrightunit(htnone) +insertleftunit(htnone) + + +D = 2 +V = Vect[A4Object](M => D); +inf_init = InfiniteMPS([P], [V]); + +# VUMPS +ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=15)); +expectation_value(ψ, H, envs) + entropy(ψ) entanglement_spectrum(ψ) transfer_spectrum(ψ,sector=C0) @@ -257,18 +271,20 @@ norm(ψ) #IDMRG -ψ, envs = find_groundstate(inf_init, H, IDMRG(verbosity=3, tol=1e-8, maxiter=100)); +ψ, envs = find_groundstate(inf_init, H, IDMRG(verbosity=3, tol=1e-8, maxiter=15)); expectation_value(ψ, H, envs) +#IDMRG2 inf_init2 = InfiniteMPS([P,P], [V,V]) H2 = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(2))); -ψ2, envs2 = find_groundstate(inf_init2, H2, IDMRG2(verbosity=3, tol=1e-8, maxiter=100)); +idmrg2alg = IDMRG2(verbosity=3, tol=1e-8, maxiter=15, trscheme=truncdim(10)) +ψ2, envs2 = find_groundstate(inf_init2, H2, idmrg2alg); expectation_value(ψ2, H2, envs2) #QuasiParticleAnsatz -momenta = range(0, 2Ο€, 4) -excE, excqp = excitations(H, QuasiparticleAnsatz(ishermitian=false), momenta, ψ, envs, sector=C0, num=1); +momenta = range(0, 2Ο€, 5) +excE, excqp = excitations(H, QuasiparticleAnsatz(ishermitian=false), momenta, ψ, envs, sector=C0, num=1); # not working for some reason # quick test on complex f symbols and dimensions testp = Vect[A4Object](one(A4Object(i,i,1)) => 1 for i in 1:12) @@ -282,7 +298,7 @@ P = Vect[A4Object](D0 => 1, D1 => 1) D = 2 V = Vect[A4Object](M => D) -dmrgalg = DMRG(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) +dmrgalg = DMRG(verbosity=3, tol=1e-8, maxiter=15, alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) fin_init = FiniteMPS(L, P, V, left=V, right=V) Hfin = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); open_boundary_conditions(H, L) == Hfin @@ -295,7 +311,7 @@ Es, states, convhist = exact_diagonalization(Hfin; sector=D0); Es / (L-1) #DMRG2 weird real data incompatibility with sector type A4Object -dmrg2alg = DMRG2(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) +dmrg2alg = DMRG2(verbosity=3, tol=1e-8, maxiter=15; alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false), trscheme=truncdim(10)) ψfin2, envsfin2 = find_groundstate(fin_init, Hfin, dmrg2alg); expectation_value(ψfin2, Hfin, envsfin2) / (L-1) @@ -305,13 +321,13 @@ entanglement_spectrum(ψfin2, round(Int, L/2)) S = left_virtualspace(Hfin, 1) oneunit(S) eltype(S) -oneunit(eltype(S)) # problematic +oneunit(eltype(S)) # should error # excitations excEfin, excqpfin = excitations(Hfin, QuasiparticleAnsatz(ishermitian=false), ψfin, envsfin;sector=C0, num=1); excEfin -excFIN, excqpFIN = excitations(Hfin, FiniteExcited(;gsalg=DMRG2(verbosity=3, tol=1e-8, maxiter=100, eigalg=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))), ψfin;num=1); +excFIN, excqpFIN = excitations(Hfin, FiniteExcited(;gsalg=dmrg2alg), ψfin;num=1); excFIN # changebonds test @@ -320,82 +336,129 @@ dim(left_virtualspace(ψ, 1)) dim(left_virtualspace(ψch, 1)) # time evolution -ψt, envst = timestep(ψ, H, 10, 1, TDVP(integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=false)), envs); + +ψt, envst = timestep(ψ, H, 10, 0, TDVP(integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=false)), envs); # not working for some reason et = expectation_value(ψt, H, envst) e = expectation_value(ψ, H, envs) isapprox(et, e*exp(-1im * 10 * e); atol=1e-1) # not hermitian +tdvpalg = TDVP(integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=false, krylovdim=10)) +ψt, envst = time_evolve(ψ, H, range(0, 1, 10), tdvpalg, envs) -# testing InfiniteMPOHamiltonian and FiniteMPOHamiltonian constructor not relying on MPSKitModels -function S_x(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} - return if spin == 1 // 2 - TensorMap(T[0 1; 1 0], β„‚^2 ← β„‚^2) - elseif spin == 1 - TensorMap(T[0 1 0; 1 0 1; 0 1 0], β„‚^3 ← β„‚^3) / sqrt(2) - else - throw(ArgumentError("spin $spin not supported")) - end -end -function S_y(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} - return if spin == 1 // 2 - TensorMap(T[0 -im; im 0], β„‚^2 ← β„‚^2) - elseif spin == 1 - TensorMap(T[0 -im 0; im 0 -im; 0 im 0], β„‚^3 ← β„‚^3) / sqrt(2) - else - throw(ArgumentError("spin $spin not supported")) +make_time_mpo(H, 0.1, alg=WII(tol=1e-8, maxiter=100)) + +# stat-mech stuff +mpo = InfiniteMPO([h]) +ψ, envs = leading_boundary(inf_init, mpo, VUMPS(verbosity=3, tol=1e-8, maxiter=15, alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))); + +# addition, substraction, multiplication + +# finite +Hfin * ψfin + +# infinite +H * ψ # currently doesn't work +MPSKit.DenseMPO(H) * ψ # does work + + +# approximate +ψa, _ = approximate(ψ, (mpo, inf_init), IDMRG()); + +mpo2 = InfiniteMPO([h,h]) +inf_init2 = InfiniteMPS([P,P], [V,V]) +H2 = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(2))); +ψ2, envs2 = find_groundstate(inf_init2, H2, VUMPS(verbosity=3, tol=1e-10, maxiter=15)); + +ψa, _ = approximate(ψ2, (mpo2, inf_init2), IDMRG2(trscheme=truncdim(10))); + +# # testing InfiniteMPOHamiltonian and FiniteMPOHamiltonian constructor not relying on MPSKitModels + +sp = Vect[FibonacciAnyon](:I=>1, :Ο„ => 1) +t = TensorMap(ones, ComplexF64, sp ← sp) +InfiniteMPOHamiltonian(PeriodicArray([sp]), i => t for i in 1:1) +H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(1))); + +# gradient grassmann test for fun +# ggalg = GradientGrassmann(method=OptimKit.ConjugateGradient, maxiter = 100, tol=1e-8, verbosity=3) # can only do this after tagging v0.13 + + + +############################################## +# diagonal case + +D = 2 +V = Vect[A4Object](D0 => D, D1 => D); +inf_init = InfiniteMPS([P], [V]); + +ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=500)); + +# other module categories + +k = 6 # 4,5,6 gives lapackexception(22), 8,9,10,11 take forever with poorly converged environments, 2,12 has poorly converged envs with imags, 1,3 has imag comps: only 1 and 2 give nonzero +V = Vect[A4Object](A4Object(k,2,i) => 2 for i in 1:MultiTensorKit._numlabels(A4Object, k, 2)) +inf_init = InfiniteMPS([P], [V]); +# expectation_value(inf_init, H) + +ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=10)); +expectation_value(ψ, H, envs) + +# unitarity test +i = 1 +objects = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i,i]); +count = 0 +for a in objects, b in objects, c in objects + for d in βŠ—(a, b, c) + es = collect(intersect(βŠ—(a, b), map(dual, βŠ—(c, dual(d))))) + fs = collect(intersect(βŠ—(b, c), map(dual, βŠ—(dual(d), a)))) + Fblocks = Vector{Any}() + for e in es + for f in fs + Fs = Fsymbol(a, b, c, d, e, f) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + F = hvcat(length(fs), Fblocks...) + if !isapprox(F' * F, one(F); atol=1e-9) + @show a,b,c,d,es,fs F + count += 1 + end end end -function S_z(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} - return if spin == 1 // 2 - TensorMap(T[1 0; 0 -1], β„‚^2 ← β„‚^2) - elseif spin == 1 - TensorMap(T[1 0 0; 0 0 0; 0 0 -1], β„‚^3 ← β„‚^3) - else - throw(ArgumentError("spin $spin not supported")) +count + +# i=1 one thing not unitary +a,b,c,d,es,fs = (A4Object(1, 1, 2), A4Object(1, 1, 2), A4Object(1, 1, 2), A4Object(1, 1, 2), A4Object[A4Object(1, 1, 4), A4Object(1, 1, 1), A4Object(1, 1, 3), A4Object(1, 1, 2)], A4Object[A4Object(1, 1, 4), A4Object(1, 1, 1), A4Object(1, 1, 3), A4Object(1, 1, 2)]) + +Fblocks = Vector{Any}() +for e in es + for f in fs + Fs = Fsymbol(a, b, c, d, e, f) + @show a,b,c,d,e,f Nsymbol(a,b,e), Nsymbol(e,c,d), Nsymbol(b,c,f), Nsymbol(a,f,d) Fs + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) end end -function S_xx(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} - return S_x(Trivial, T; spin) βŠ— S_x(Trivial, T; spin) -end -function S_yy(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} - return S_y(Trivial, T; spin) βŠ— S_y(Trivial, T; spin) -end -function S_zz(::Type{Trivial}=Trivial, ::Type{T}=ComplexF64; spin=1 // 2) where {T<:Number} - return S_z(Trivial, T; spin) βŠ— S_z(Trivial, T; spin) -end +Fblocks +Fblocks[end] +F = hvcat(length(fs), Fblocks...) +F * F' -function transverse_field_isingg(; g=1.0, L=Inf) - X = S_x(; spin=1 // 2) - ZZ = S_zz(; spin=1 // 2) - E = TensorMap(ComplexF64[1 0; 0 1], β„‚^2 ← β„‚^2) - - # lattice = L == Inf ? PeriodicVector([β„‚^2]) : fill(β„‚^2, L) - if L == Inf - lattice = PeriodicArray([β„‚^2]) - return InfiniteMPOHamiltonian(lattice, - (i, i + 1) => -(ZZ + (g / 2) * (X βŠ— E + E βŠ— X)) - for i in 1:1) - # return MPOHamiltonian(-ZZ - (g / 2) * (X βŠ— E + E βŠ— X)) - else - lattice = fill(β„‚^2, L) - return FiniteMPOHamiltonian(lattice, - (i, i + 1) => -(ZZ + (g / 2) * (X βŠ— E + E βŠ— X)) - for i in 1:(L - 1)) #+ - # FiniteMPOHamiltonian(lattice, (i,) => -g * X for i in 1:L) - end +block22 = Fsymbol(a,a,a,a,a,a) +Fblock22 = hvcat(4, block22...) - H = S_zz(; spin=1 // 2) + (g / 2) * (X βŠ— E + E βŠ— X) - return if L == Inf - MPOHamiltonian(H) - else - FiniteMPOHamiltonian(fill(β„‚^2, L), (i, i + 1) => H for i in 1:(L - 1)) - end - return MPOHamiltonian(-H) -end +transpose.(Fblocks) +Ftr = hvcat(length(fs), transpose.(Fblocks)...) +# checking multiplicity +function obs(i::Int) + return A4Object.(i, i, MultiTensorKit._get_dual_cache(I)[2][i,i]) +end -transverse_field_isingg(; g=1.0, L=3) -sp = Vect[FibonacciAnyon](:I=>1, :Ο„ => 1) -t = TensorMap(ones, ComplexF64, sp ← sp) -InfiniteMPOHamiltonian(PeriodicArray([sp]), i => t for i in 1:1) -H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(1))); \ No newline at end of file +for i in 1:12 + !any(Nsymbol(a,b,c) > 1 for a in obs(i), b in obs(i), c in obs(i)) && @show i +end \ No newline at end of file From 0b3d668071ded1e243e4693d7577841c5ebe0fd6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 23 Apr 2025 09:13:00 +0200 Subject: [PATCH 063/206] update `artifact_path` --- src/bimodulesector.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index d235625..87bf456 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -57,7 +57,7 @@ end # Data from files # --------------- -const artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.1") +const artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.2") function extract_Nsymbol(::Type{A4Object}) filename = joinpath(artifact_path, "A4", "Nsymbol.json") From 0995d180959afaae0f97a13ec074729ceb6338b4 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 14 May 2025 12:40:07 +0200 Subject: [PATCH 064/206] add file to test caching --- test/caching.jl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 test/caching.jl diff --git a/test/caching.jl b/test/caching.jl new file mode 100644 index 0000000..0921cc1 --- /dev/null +++ b/test/caching.jl @@ -0,0 +1,21 @@ +using MultiTensorKit +using TensorKit +using MPSKit, MPSKitModels + +C1 = A4Object(1,1,1) +C0 = A4Object(1,1,4) # unit +M = A4Object(1,2,1) +D0 = A4Object(2,2,12) # unit +D1 = A4Object(2,2,2) # self-dual object + +P = Vect[A4Object](D0 => 1, D1 => 1) +h = TensorMap(ones, ComplexF64, P βŠ— P ← P βŠ— P) + +lattice = InfiniteChain(1) +H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); + +D = 4 +V = Vect[A4Object](M => D); +inf_init = InfiniteMPS([P], [V]); + +ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-12, maxiter=20)); \ No newline at end of file From 287bb39d265321ce7ada018f8bc2d09b2f106f9a Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 14 May 2025 12:50:13 +0200 Subject: [PATCH 065/206] add TensorKit tests --- test/caching.jl | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/test/caching.jl b/test/caching.jl index 0921cc1..c385c86 100644 --- a/test/caching.jl +++ b/test/caching.jl @@ -18,4 +18,43 @@ D = 4 V = Vect[A4Object](M => D); inf_init = InfiniteMPS([P], [V]); -ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-12, maxiter=20)); \ No newline at end of file +ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-12, maxiter=20)); + +# basic TensorKit tests + +# diagonal +obj = A4Object(2,2,1) +obj2 = A4Object(2,2,2) +sp = Vect[A4Object](obj=>1, obj2=>1) +A = TensorMap(ones, ComplexF64, sp βŠ— sp ← sp βŠ— sp) +transpose(A, (2,4,), (1,3,)) + +blocksectors(sp βŠ— sp) +@plansor fullcont[] := A[a b;a b] # 12 fusiontrees + +# π’ž x β„³ +obj = A4Object(1,1,1) +obj2 = A4Object(1,2,1) + +sp = Vect[A4Object](obj=>1) +sp2 = Vect[A4Object](obj2=>1) +TensorMap(rand, ComplexF64, sp βŠ— sp2 ← sp) # should throw ArgumentError +homspace = sp βŠ— sp2 ← sp2 +A = TensorMap(ones, ComplexF64, homspace) +permute(space(A),((1,),(3,2))) +transpose(A, (1,2,), (3,)) == A +transpose(A, (3,1,), (2,)) + +Aop = TensorMap(ones, ComplexF64, conj(sp2) βŠ— sp ← conj(sp2)) +transpose(Aop, (1,2,), (3,)) == Aop +transpose(Aop, (1,), (3,2)) + +@plansor Acont[a] := A[a b;b] # should not have data bc sp isn't the unit + +spfix = Vect[A4Object](one(obj)=>1) +Afix = TensorMap(ones, ComplexF64, spfix βŠ— sp2 ← sp2) +@plansor Acontfix[a] := Afix[a b;b] # should have a fusion tree + +blocksectors(sp βŠ— sp2) +A = TensorMap(ones, ComplexF64, sp βŠ— sp2 ← sp βŠ— sp2) +@plansor fullcont[] := A[a b;a b] # 12 fusiontrees \ No newline at end of file From f96812f7dadf7753ac18845d0d05dce631317829 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 4 Jun 2025 11:03:19 +0200 Subject: [PATCH 066/206] debugging fun + progress --- test/localtests.jl | 565 ++++++++++++++++++++++++++------------------- 1 file changed, 325 insertions(+), 240 deletions(-) diff --git a/test/localtests.jl b/test/localtests.jl index b3d1b9f..f8ba2bb 100644 --- a/test/localtests.jl +++ b/test/localtests.jl @@ -2,85 +2,69 @@ using TensorKitSectors using MultiTensorKit using Revise -testobj = A4Object(1,1,1) # fusion cat object +testobj = A4Object(1, 1, 1) # fusion cat object unit = one(testobj) -collect(testobjβŠ—unit) +collect(testobj βŠ— unit) @assert unit == leftone(testobj) == rightone(testobj) -testobj2 = A4Object(2,2,1) +testobj2 = A4Object(2, 2, 1) unit2 = one(testobj2) -collect(testobj2βŠ—unit2) +collect(testobj2 βŠ— unit2) @assert unit2 == leftone(testobj2) == rightone(testobj2) -testmodobj = A4Object(1,2,1) +testmodobj = A4Object(1, 2, 1) one(testmodobj) leftone(testmodobj) rightone(testmodobj) -Fsymbol(testobj, testobj, A4Object(1,1,3), testobj, A4Object(1,1,3), A4Object(1,1,4)) - -using Artifacts -using DelimitedFiles - -artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.1") -filename = joinpath(artifact_path, "A4", "Fsymbol_4.txt") -txt_string = read(filename, String) -F_arraypart = copy(readdlm(IOBuffer(txt_string))); - -MTK = MultiTensorKit -F_arraypart = MTK.convert_Fs(F_arraypart) -# for (color, colordict) in F_arraypart -# for (labels, F) in colordict -# if length(F) == 2 -# println(color, labels, F) -# end -# end +Fsymbol(testobj, testobj, A4Object(1, 1, 3), testobj, A4Object(1, 1, 3), A4Object(1, 1, 4)) + +# using Artifacts +# using DelimitedFiles + +# artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.1") +# filename = joinpath(artifact_path, "A4", "Fsymbol_4.txt") +# txt_string = read(filename, String) +# F_arraypart = copy(readdlm(IOBuffer(txt_string))); + +# F_arraypart = MultiTensorKit.convert_Fs(F_arraypart) +# i,j,k,l = (4,12,12,2) # 5,2,8,10 +# a,b,c,d,e,f = (1, 11, 3, 1, 1, 3) #(2,1,1,2,2,3) +# testF = F_arraypart[(i,j,k,l)][(a,b,c,d,e,f)] +# a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), +# (k, l, c), (i, l, d), +# (i, k, e), (j, l, f))) +# result = Array{ComplexF64,4}(undef, +# (Nsymbol(a_ob, b_ob, e_ob), +# Nsymbol(e_ob, c_ob, d_ob), +# Nsymbol(b_ob, c_ob, f_ob), +# Nsymbol(a_ob, f_ob, d_ob))) + +# map!(result, reshape(testF, size(result))) do pair +# return pair[2] # end -i,j,k,l = (4,12,12,2) # 5,2,8,10 -a,b,c,d,e,f = (1, 11, 3, 1, 1, 3) #(2,1,1,2,2,3) -testF = F_arraypart[(i,j,k,l)][(a,b,c,d,e,f)] -a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), - (k, l, c), (i, l, d), - (i, k, e), (j, l, f))) -result = Array{ComplexF64,4}(undef, - (Nsymbol(a_ob, b_ob, e_ob), - Nsymbol(e_ob, c_ob, d_ob), - Nsymbol(b_ob, c_ob, f_ob), - Nsymbol(a_ob, f_ob, d_ob))) - -map!(result, reshape(testF, size(result))) do pair - return pair[2] -end - -for c in testF[2] - println(c) -end - -function bla() - return for (k,v) in F_arraypart - @show k - end -end N = MultiTensorKit._get_Ncache(A4Object); duals = MultiTensorKit._get_dual_cache(A4Object)[2] # checking duals is correct for i in 1:12, j in 1:12 - for (index, a) in enumerate(duals[i,j]) - aob = A4Object(i,j,index) - bob = A4Object(j,i,a) - leftone(aob) ∈ aob βŠ— bob && rightone(aob) ∈ bob βŠ— aob || @show i,j,aob,bob + for (index, a) in enumerate(duals[i, j]) + aob = A4Object(i, j, index) + bob = A4Object(j, i, a) + leftone(aob) ∈ aob βŠ— bob && rightone(aob) ∈ bob βŠ— aob || @show i, j, aob, bob end end A = MultiTensorKit._get_Fcache(A4Object) -a,b,c,d,e,f = A4Object(1,1,3), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,2) -a,b,c,d,e,f = A4Object(1,1,1), A4Object(1,1,2), A4Object(1,1,2), A4Object(1,1,1), A4Object(1,1,2), A4Object(1,1,4) -coldict = A[a.i][a.i, a.j, b.j, c.j] +a, b, c, d, e, f = A4Object(1, 1, 3), A4Object(1, 1, 2), A4Object(1, 1, 2), + A4Object(1, 1, 2), A4Object(1, 1, 2), A4Object(1, 1, 2) +a, b, c, d, e, f = A4Object(1, 1, 1), A4Object(1, 1, 2), A4Object(1, 1, 2), + A4Object(1, 1, 1), A4Object(1, 1, 2), A4Object(1, 1, 4) +coldict = A[a.i, a.j, b.j, c.j] bla = get(coldict, (a.label, b.label, c.label, d.label, e.label, f.label)) do - return coldict[(a.label, b.label, c.label, d.label, e.label, f.label)] - end + return coldict[(a.label, b.label, c.label, d.label, e.label, f.label)] +end ###### TensorKit stuff ###### using MultiTensorKit @@ -89,234 +73,344 @@ using Test # π’ž x π’ž example -obj = A4Object(2,2,1) -obj2 = A4Object(2,2,2) -sp = Vect[A4Object](obj=>1, obj2=>1) +obj = A4Object(2, 2, 1) +obj2 = A4Object(2, 2, 2) +sp = Vect[A4Object](obj => 1, obj2 => 1) A = TensorMap(ones, ComplexF64, sp βŠ— sp ← sp βŠ— sp) -transpose(A, (2,4,), (1,3,)) +transpose(A, (2, 4), (1, 3)) blocksectors(sp βŠ— sp) -@plansor fullcont[] := A[a b;a b] # problem here is that fusiontrees for all 12 units are given +@plansor fullcont[] := A[a b; a b] # problem here is that fusiontrees for all 12 units are given # π’ž x β„³ example -obj = A4Object(1,1,1) -obj2 = A4Object(1,2,1) +obj = A4Object(1, 1, 1) +obj2 = A4Object(1, 2, 1) -sp = Vect[A4Object](obj=>1) -sp2 = Vect[A4Object](obj2=>1) -@test_throws ArgumentError("invalid fusion channel") TensorMap(rand, ComplexF64, sp βŠ— sp2 ← sp) +sp = Vect[A4Object](obj => 1) +sp2 = Vect[A4Object](obj2 => 1) +@test_throws ArgumentError("invalid fusion channel") TensorMap(rand, ComplexF64, + sp βŠ— sp2 ← sp) homspace = sp βŠ— sp2 ← sp2 A = TensorMap(ones, ComplexF64, homspace) fusiontrees(A) -permute(space(A),((1,),(3,2))) -transpose(A, (1,2,), (3,)) == A -transpose(A, (3,1,), (2,)) +permute(space(A), ((1,), (3, 2))) +transpose(A, (1, 2), (3,)) == A +transpose(A, (3, 1), (2,)) Aop = TensorMap(ones, ComplexF64, conj(sp2) βŠ— sp ← conj(sp2)) -transpose(Aop, (1,2,), (3,)) == Aop -transpose(Aop, (1,), (3,2)) +transpose(Aop, (1, 2), (3,)) == Aop +transpose(Aop, (1,), (3, 2)) -@plansor Acont[a] := A[a b;b] # should not have data bc sp isn't the unit +@plansor Acont[a] := A[a b; b] # should not have data bc sp isn't the unit -spfix = Vect[A4Object](one(obj)=>1) +spfix = Vect[A4Object](one(obj) => 1) Afix = TensorMap(ones, ComplexF64, spfix βŠ— sp2 ← sp2) -@plansor Acontfix[a] := Afix[a b;b] # should have a fusion tree +@plansor Acontfix[a] := Afix[a b; b] # should have a fusion tree blocksectors(sp βŠ— sp2) A = TensorMap(ones, ComplexF64, sp βŠ— sp2 ← sp βŠ— sp2) -@plansor fullcont[] := A[a b;a b] # same 12 fusiontrees problem +@plansor fullcont[] := A[a b; a b] # same 12 fusiontrees problem # completely off-diagonal example obj = A4Object(5, 4, 1) obj2 = A4Object(4, 5, 1) -sp = Vect[A4Object](obj=>1) -sp2 = Vect[A4Object](obj2=>1) -conj(sp) == sp2 +sp = Vect[A4Object](obj => 1) +sp2 = Vect[A4Object](obj2 => 1) +conj(sp) == sp2 A = TensorMap(ones, ComplexF64, sp βŠ— sp2 ← sp βŠ— sp2) Aop = TensorMap(ones, ComplexF64, sp2 βŠ— sp ← sp2 βŠ— sp) -At = transpose(A, (2,4,), (1,3,)) -Aopt = transpose(Aop, (2,4,), (1,3,)) +At = transpose(A, (2, 4), (1, 3)) +Aopt = transpose(Aop, (2, 4), (1, 3)) blocksectors(At) == blocksectors(Aop) blocksectors(Aopt) == blocksectors(A) -@plansor Acont[] := A[a b;a b] # ignore this error for now -@plansor Acont2[] := A[b a;b a] +@plansor Acont[] := A[a b; a b] # ignore this error for now +@plansor Acont2[] := A[b a; b a] -testsp = SU2Space(0=>1, 1=>1) +testsp = SU2Space(0 => 1, 1 => 1) Atest = TensorMap(ones, ComplexF64, testsp βŠ— testsp ← testsp βŠ— testsp) -@plansor Aconttest[] := Atest[a b;a b] - +@plansor Aconttest[] := Atest[a b; a b] # π’ž x β„³ ← β„³ x π’Ÿ -c = A4Object(1,1,1) -m = A4Object(1,2,1) -d = A4Object(2,2,1) -W = Vect[A4Object](c=>1) βŠ— Vect[A4Object](m=>1) ← Vect[A4Object](m=>1) βŠ— Vect[A4Object](d=>1) +c = A4Object(1, 1, 1) +m = A4Object(1, 2, 1) +d = A4Object(2, 2, 1) +W = Vect[A4Object](c => 1) βŠ— Vect[A4Object](m => 1) ← + Vect[A4Object](m => 1) βŠ— Vect[A4Object](d => 1) # bram stuff - +using TensorKitSectors for i in 1:12, j in 1:12 - for a in A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i,j]) - F = Fsymbol(a, dual(a), a, a, leftone(a), rightone(a))[1,1,1,1] - isapprox(F, frobeniusschur(a) / dim(a); atol=1e-15) || @show a, F, frobeniusschur(a)/ dim(a) # check real - isreal(frobeniusschur(a)) || @show a, frobeniusschur(a) + for a in A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i, j]) + F = Fsymbol(a, dual(a), a, a, leftone(a), rightone(a))[1, 1, 1, 1] + isapprox(F, frobeniusschur(a) / dim(a); atol=1e-15) || + @show a, F, frobeniusschur(a) / dim(a) # check real + isreal(frobeniusschur(a)) || isapprox(abs(frobeniusschur(a)), 1.0; atol=1e-15) || + @show a, frobeniusschur(a), abs(frobeniusschur(a)) end end for i in 1:12, j in 1:12 # 18a i != j || continue - objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i,j]) + objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i, j]) @assert all(dim(m) > 0 for m in objsij) end for i in 1:12, j in 1:12 # 18b - objsii = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i,i]) - objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i,j]) + objsii = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i, i]) + objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i, j]) - Ndict = Dict{Tuple{A4Object, A4Object, A4Object}, Int}() + Ndict = Dict{Tuple{A4Object,A4Object,A4Object},Int}() for a in objsii, m in objsij - for n in aβŠ—m + for n in a βŠ— m Ndict[(a, m, n)] = Nsymbol(a, m, n) end end for a in objsii, m in objsij - isapprox(dim(a)*dim(m), sum(Ndict[(a, m, n)]*dim(n) for n in aβŠ—m); atol=2e-9) || @show a, m + isapprox(dim(a) * dim(m), sum(Ndict[(a, m, n)] * dim(n) for n in a βŠ— m); + atol=2e-9) || @show a, m end end for i in 1:12, j in 1:12 # 18c - objsii = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i,i]) - objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i,j]) + objsii = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i, i]) + objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i, j]) m_dimsum = sum(dim(m)^2 for m in objsij) c_dimsum = sum(dim(c)^2 for c in objsii) isapprox(m_dimsum, c_dimsum; atol=1e-8) || @show i, j, c_dimsum, m_dimsum end -(a, b, c, d, e, f) = (A4Object(2, 1, 1), A4Object(1, 2, 1), A4Object(2, 2, 11), A4Object(2, 2, 11), A4Object(2, 2, 9), A4Object(1, 2, 1)) -Fsymbol(a,b,c,d,e,f) -zeros(ComplexF64, Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)) +(a, b, c, d, e, f) = (A4Object(2, 1, 1), A4Object(1, 2, 1), A4Object(2, 2, 11), + A4Object(2, 2, 11), A4Object(2, 2, 9), A4Object(1, 2, 1)) +Fsymbol(a, b, c, d, e, f) +zeros(ComplexF64, Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)) == +Fsymbol(a, b, c, d, e, f) # testing blocksectors -W = Vect[A4Object](A4Object(2, 2, 12)=>1) ← ProductSpace{GradedSpace{A4Object, NTuple{486, Int64}}, 0}() -W isa TensorMapSpace{GradedSpace{A4Object, NTuple{486, Int64}}} +using BlockTensorKit +W = Vect[A4Object](A4Object(2, 2, 12) => 1) ← + ProductSpace{GradedSpace{A4Object,NTuple{486,Int64}},0}() +W isa TensorMapSpace{GradedSpace{A4Object,NTuple{486,Int64}}} W isa HomSpace -W isa HomSpace{S} where {S<:SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}} -W isa TensorMapSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}} +W isa HomSpace{S} where {S<:SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}}} +W isa TensorMapSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}}} # this appears as well (N1=N2=0) -W = ProductSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}, 0}() ← ProductSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}, 0}() +W = ProductSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}},0}() ← + ProductSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}},0}() typeof(W) -W isa TensorMapSpace{S} where {S<:GradedSpace{A4Object, NTuple{486, Int64}}} -W isa HomSpace{S} where {S<:GradedSpace{A4Object, NTuple{486, Int64}}} +W isa TensorMapSpace{S} where {S<:GradedSpace{A4Object,NTuple{486,Int64}}} +W isa HomSpace{S} where {S<:GradedSpace{A4Object,NTuple{486,Int64}}} W isa HomSpace W isa TensorMapSpace -W isa TensorMapSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}, 0, 0} -W isa TensorMapSpace{GradedSpace{A4Object, NTuple{486, Int64}}, 0, 0} -TensorMapSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}, 0, 0} <: TensorMapSpace{GradedSpace{A4Object, NTuple{486, Int64}}, N₁,Nβ‚‚} where {N₁,Nβ‚‚} -W isa TensorSpace{SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}} +W isa TensorMapSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}},0,0} +W isa TensorMapSpace{GradedSpace{A4Object,NTuple{486,Int64}},0,0} +TensorMapSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}},0,0} <: +TensorMapSpace{GradedSpace{A4Object,NTuple{486,Int64}},N₁,Nβ‚‚} where {N₁,Nβ‚‚} +W isa TensorSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}}} -GradedSpace{A4Object, NTuple{486, Int64}} <: BlockTensorKit.SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}} +GradedSpace{A4Object,NTuple{486,Int64}} <: +BlockTensorKit.SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}} ############ MPSKit wow ############ using MultiTensorKit using TensorKit using MPSKit, MPSKitModels -C1 = A4Object(1,1,1) -C0 = A4Object(1,1,4) # unit -M = A4Object(1,2,1) -D0 = A4Object(2,2,12) # unit -D1 = A4Object(2,2,2) # self-dual object +C1 = A4Object(1, 1, 1) +C0 = A4Object(1, 1, 4) # unit +M = A4Object(1, 2, 1) +D0 = A4Object(2, 2, 12) # unit +D1 = A4Object(2, 2, 2) # self-dual object collect(D0 βŠ— D1) collect(D1 βŠ— D1) P = Vect[A4Object](D0 => 1, D1 => 1) h = TensorMap(ones, ComplexF64, P βŠ— P ← P βŠ— P) -lattice = InfiniteChain(1); -H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); +using Profile +Profile.init(; delay=0.1) +lattice = InfiniteChain(1) +t = time() +H = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(lattice)); # 15min, 10.5min +dt = time() - t +println("Time to create Hamiltonian: ", dt, " seconds") # testing insertleft/rightunit -sp = SU2Space(0=>1, 1=>1) -ht = TensorMap(ones, ComplexF64, P ← P) -htl = TensorMap(ones, ComplexF64, P ← one(P)) -htr = TensorMap(ones, ComplexF64, one(P) ← P) -htnone = TensorMap(ones, ComplexF64, one(P) ← one(P)) +sp = SU2Space(0 => 1, 1 => 1) +ht = TensorMap(ones, ComplexF64, P ← P) +htl = TensorMap(ones, ComplexF64, P ← one(P)) +htr = TensorMap(ones, ComplexF64, one(P) ← P) +htnone = TensorMap(ones, ComplexF64, one(P) ← one(P)) insertrightunit(htr) # adding to empty space -insertleftunit(htr) +insertleftunit(htr) insertrightunit(htl) insertleftunit(htl) # adding to empty space insertrightunit(htnone) insertleftunit(htnone) - -D = 2 +D = 4 V = Vect[A4Object](M => D); -inf_init = InfiniteMPS([P], [V]); +t = time() +inf_init = InfiniteMPS([P], [V]); # 8min, 6.5min +dt = time() - t +println("Time to create InfiniteMPS: ", dt, " seconds") # VUMPS -ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=15)); +t = time() +ψ, envs = find_groundstate(inf_init, H, VUMPS(; verbosity=3, tol=1e-12, maxiter=20)); # 40 min, 30min +dt = time() - t +println("Time to find groundstate: ", dt, " seconds") expectation_value(ψ, H, envs) +using JLD2 +# jldsave("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testH.jld2"; H) +# jldsave("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testinf_init.jld2"; inf_init) +# jldsave("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testgs.jld2"; ψ) +# jldsave("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testenvs.jld2"; envs) + +ψ = jldopen("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testgs.jld2", "r") do file + return read(file, "ψ") +end +H = jldopen("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testH.jld2", "r") do file + return read(file, "H") +end +inf_init = jldopen("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testinf_init.jld2", + "r") do file + return read(file, "inf_init") +end +envs = jldopen("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testenvs.jld2", "r") do file + return read(file, "envs") +end + entropy(ψ) entanglement_spectrum(ψ) -transfer_spectrum(ψ,sector=C0) -correlation_length(ψ,sector=C0) +transfer_spectrum(ψ; sector=C0) +correlation_length(ψ; sector=C0) norm(ψ) +# test correlator + #IDMRG -ψ, envs = find_groundstate(inf_init, H, IDMRG(verbosity=3, tol=1e-8, maxiter=15)); +ψ, envs = find_groundstate(inf_init, H, IDMRG(; verbosity=3, tol=1e-8, maxiter=15)); expectation_value(ψ, H, envs) #IDMRG2 -inf_init2 = InfiniteMPS([P,P], [V,V]) -H2 = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(2))); -idmrg2alg = IDMRG2(verbosity=3, tol=1e-8, maxiter=15, trscheme=truncdim(10)) +inf_init2 = InfiniteMPS([P, P], [V, V]) +H2 = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(InfiniteChain(2))); +idmrg2alg = IDMRG2(; verbosity=3, tol=1e-8, maxiter=15, trscheme=truncdim(10)) ψ2, envs2 = find_groundstate(inf_init2, H2, idmrg2alg); expectation_value(ψ2, H2, envs2) #QuasiParticleAnsatz -momenta = range(0, 2Ο€, 5) -excE, excqp = excitations(H, QuasiparticleAnsatz(ishermitian=false), momenta, ψ, envs, sector=C0, num=1); # not working for some reason +momenta = range(0, 2Ο€, 3) +t = time() +excE, excqp = excitations(H, QuasiparticleAnsatz(; ishermitian=true), momenta, ψ, envs; + sector=C0, num=1, parallel=false); # not working for some reason +dt = time() - t +# 15min, 100min +println("Time to create excitations: ", dt, " seconds") + +####################################################### +# debugging QPA for infinite systems +momentum = momenta[begin] +Ο•β‚€ = LeftGaugedQP(rand, ψ, ψ; sector=C0, momentum=momenta[begin]); +E = MPSKit.effective_excitation_renormalization_energy(H, Ο•β‚€, envs, envs) +H_eff = MPSKit.EffectiveExcitationHamiltonian(H, envs, envs, E); # function that acts on QP +alg = QuasiparticleAnsatz(; ishermitian=true) + +# do block with eigsolve effectively doing this +my_operator(Ο•) = H_eff(Ο•; alg.alg_environments...) +Es, Ο•s, convhist = eigsolve(my_operator, Ο•β‚€, 1, :SR, alg.alg) + +# goes back in the eigsolve during KrylovKit.initialise +iter = LanczosIterator(my_operator, Ο•β‚€, alg.alg.orth); +fact = initialize(iter; verbosity=alg.alg.verbosity) + +# goes wrong during apply of KrylovKit.initialise +Axβ‚€ = KrylovKit.apply(iter.operator, iter.xβ‚€) + +# apply(f,x) = f(x) calculates EffectiveExcitationHamiltonian(H, envs, envs, E) of QP +iter.operator(iter.xβ‚€) +MPSKit.EffectiveExcitationHamiltonian(H, envs, envs, E)(Ο•β‚€; alg.alg_environments...) +H_eff(Ο•β‚€; alg.alg_environments...) + +# error occurs when calculating the environment +qp_envs = environments(Ο•β‚€, H, envs, envs; alg.alg_environments...) + +# goes wrong when calculating environments of QP +lBs = PeriodicVector([MPSKit.allocate_GBL(Ο•β‚€, H, Ο•β‚€, i) for i in 1:length(Ο•β‚€)]); +MPSKit.left_excitation_transfer_system(lBs[1], H, Ο•β‚€; solver=MPSKit.Defaults.linearsolver) + +# problem occurs at the linsolve which calls GMRES +found = zerovector(lBs[1]) +H_partial = map(h -> getindex(h, 1:1, 1, 1, 1:1), parent(H)) +T = TransferMatrix(exci.right_gs.AR, H_partial, exci.left_gs.AL) +start = scale!(last(found[1:1] * T), cis(-momenta[begin] * 1)) +if exci.trivial && isidentitylevel(H, i) + # not using braiding tensors here, leads to extra leg + util = similar(exci.left_gs.AL[1], space(parent(H)[1], 1)[1]) + fill_data!(util, one) + @plansor start[-1 -2; -3 -4] -= start[2 1; -3 3] * + util[1] * + r_RL(exci.right_gs)[3; 2] * + l_RL(exci.right_gs)[-1; -4] * + conj(util[-2]) +end +found[1] = add!(start, lBs[1]) + +T = TransferMatrix(exci.right_gs.AR, exci.left_gs.AL) +if exci.trivial + # deal with extra leg + @plansor lRL_util[-1 -2; -3] := l_RL(exci.right_gs)[-1; -3] * conj(util[-2]) + @plansor rRL_util[-1 -2; -3] := r_RL(exci.right_gs)[-1; -3] * util[-2] + T = regularize(T, lRL_util, rRL_util) +end + +found[1], convhist = linsolve(flip(T), found[1], found[1], MPSKit.Defaults.linearsolver, 1, + -cis(-momenta[begin] * 1)) +############################################################################## # quick test on complex f symbols and dimensions -testp = Vect[A4Object](one(A4Object(i,i,1)) => 1 for i in 1:12) +testp = Vect[A4Object](one(A4Object(i, i, 1)) => 1 for i in 1:12) dim(testp) oneunit(testp) # finite stuff -L = 6 +L = 10 lattice = FiniteChain(L) P = Vect[A4Object](D0 => 1, D1 => 1) -D = 2 +D = 4 V = Vect[A4Object](M => D) -dmrgalg = DMRG(verbosity=3, tol=1e-8, maxiter=15, alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) -fin_init = FiniteMPS(L, P, V, left=V, right=V) -Hfin = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); +dmrgalg = DMRG(; verbosity=3, tol=1e-8, maxiter=100, + alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) +fin_init = FiniteMPS(L, P, V; left=V, right=V) +Hfin = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(lattice)); open_boundary_conditions(H, L) == Hfin ψfin, envsfin = find_groundstate(fin_init, Hfin, dmrgalg); -expectation_value(ψfin, Hfin, envsfin) / (L-1) +expectation_value(ψfin, Hfin, envsfin) / (L - 1) -entropy(ψfin, round(Int, L/2)) -entanglement_spectrum(ψfin, round(Int, L/2)) +entropy(ψfin, round(Int, L / 2)) +entanglement_spectrum(ψfin, round(Int, L / 2)) Es, states, convhist = exact_diagonalization(Hfin; sector=D0); -Es / (L-1) +Es / (L - 1) -#DMRG2 weird real data incompatibility with sector type A4Object -dmrg2alg = DMRG2(verbosity=3, tol=1e-8, maxiter=15; alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false), trscheme=truncdim(10)) +dmrg2alg = DMRG2(; verbosity=3, tol=1e-8, maxiter=15, + alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false), + trscheme=truncdim(10)) ψfin2, envsfin2 = find_groundstate(fin_init, Hfin, dmrg2alg); -expectation_value(ψfin2, Hfin, envsfin2) / (L-1) +0expectation_value(ψfin2, Hfin, envsfin2) / (L - 1) -entropy(ψfin2, round(Int, L/2)) -entanglement_spectrum(ψfin2, round(Int, L/2)) +entropy(ψfin2, round(Int, L / 2)) +entanglement_spectrum(ψfin2, round(Int, L / 2)) S = left_virtualspace(Hfin, 1) oneunit(S) @@ -324,10 +418,11 @@ eltype(S) oneunit(eltype(S)) # should error # excitations -excEfin, excqpfin = excitations(Hfin, QuasiparticleAnsatz(ishermitian=false), ψfin, envsfin;sector=C0, num=1); +qpaalg = QuasiparticleAnsatz(; ishermitian=false, tol=1e-8, maxiter=100) +excEfin, excqpfin = excitations(Hfin, qpaalg, ψfin, envsfin; sector=C0, num=1); excEfin -excFIN, excqpFIN = excitations(Hfin, FiniteExcited(;gsalg=dmrg2alg), ψfin;num=1); +excFIN, excqpFIN = excitations(Hfin, FiniteExcited(; gsalg=dmrg2alg), ψfin; num=1); excFIN # changebonds test @@ -337,19 +432,25 @@ dim(left_virtualspace(ψch, 1)) # time evolution -ψt, envst = timestep(ψ, H, 10, 0, TDVP(integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=false)), envs); # not working for some reason -et = expectation_value(ψt, H, envst) +ψt, envst = timestep(ψ, H, 3, 0, + TDVP(; integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=true)), + envs); +et = expectation_value(ψt, H, envst) e = expectation_value(ψ, H, envs) -isapprox(et, e*exp(-1im * 10 * e); atol=1e-1) # not hermitian +isapprox(et, e; atol=1e-12) # hermitian -tdvpalg = TDVP(integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=false, krylovdim=10)) +tdvpalg = TDVP(; integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=true, krylovdim=10)) ψt, envst = time_evolve(ψ, H, range(0, 1, 10), tdvpalg, envs) -make_time_mpo(H, 0.1, alg=WII(tol=1e-8, maxiter=100)) +timealg = WII(; tol=1e-8, maxiter=100) +make_time_mpo(H, 0.1, timealg) # stat-mech stuff mpo = InfiniteMPO([h]) -ψ, envs = leading_boundary(inf_init, mpo, VUMPS(verbosity=3, tol=1e-8, maxiter=15, alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false))); +ψ, envs = leading_boundary(inf_init, mpo, + VUMPS(; verbosity=3, tol=1e-8, maxiter=15, + alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; + ishermitian=false))); # addition, substraction, multiplication @@ -360,105 +461,89 @@ Hfin * ψfin H * ψ # currently doesn't work MPSKit.DenseMPO(H) * ψ # does work - # approximate ψa, _ = approximate(ψ, (mpo, inf_init), IDMRG()); -mpo2 = InfiniteMPO([h,h]) -inf_init2 = InfiniteMPS([P,P], [V,V]) -H2 = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(2))); -ψ2, envs2 = find_groundstate(inf_init2, H2, VUMPS(verbosity=3, tol=1e-10, maxiter=15)); - -ψa, _ = approximate(ψ2, (mpo2, inf_init2), IDMRG2(trscheme=truncdim(10))); +mpo2 = InfiniteMPO([h, h]) +inf_init2 = InfiniteMPS([P, P], [V, V]) +H2 = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(InfiniteChain(2))); +ψ2, envs2 = find_groundstate(inf_init2, H2, VUMPS(; verbosity=3, tol=1e-10, maxiter=15)); +ψa, _ = approximate(ψ2, (mpo2, inf_init2), IDMRG2(; trscheme=truncdim(10))); # # testing InfiniteMPOHamiltonian and FiniteMPOHamiltonian constructor not relying on MPSKitModels -sp = Vect[FibonacciAnyon](:I=>1, :Ο„ => 1) +sp = Vect[FibonacciAnyon](:I => 1, :Ο„ => 1) t = TensorMap(ones, ComplexF64, sp ← sp) InfiniteMPOHamiltonian(PeriodicArray([sp]), i => t for i in 1:1) -H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(1))); - -# gradient grassmann test for fun -# ggalg = GradientGrassmann(method=OptimKit.ConjugateGradient, maxiter = 100, tol=1e-8, verbosity=3) # can only do this after tagging v0.13 - - +H = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(InfiniteChain(1))); ############################################## # diagonal case -D = 2 +D = 4 V = Vect[A4Object](D0 => D, D1 => D); inf_init = InfiniteMPS([P], [V]); -ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=500)); +ψ, envs = find_groundstate(inf_init, H, VUMPS(; verbosity=3, tol=1e-10, maxiter=500)); # other module categories - -k = 6 # 4,5,6 gives lapackexception(22), 8,9,10,11 take forever with poorly converged environments, 2,12 has poorly converged envs with imags, 1,3 has imag comps: only 1 and 2 give nonzero -V = Vect[A4Object](A4Object(k,2,i) => 2 for i in 1:MultiTensorKit._numlabels(A4Object, k, 2)) +# 4,5,7,8,9,10,11,12 gives poorly converged envs, +k = 6 # 6 gives lapackexception(22) +V = Vect[A4Object](A4Object(k, 2, i) => 2 + for i in 1:MultiTensorKit._numlabels(A4Object, k, 2)) inf_init = InfiniteMPS([P], [V]); # expectation_value(inf_init, H) -ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-10, maxiter=10)); +ψ, envs = find_groundstate(inf_init, H, VUMPS(; verbosity=3, tol=1e-10, maxiter=10)); expectation_value(ψ, H, envs) -# unitarity test -i = 1 -objects = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i,i]); -count = 0 -for a in objects, b in objects, c in objects - for d in βŠ—(a, b, c) - es = collect(intersect(βŠ—(a, b), map(dual, βŠ—(c, dual(d))))) - fs = collect(intersect(βŠ—(b, c), map(dual, βŠ—(dual(d), a)))) - Fblocks = Vector{Any}() - for e in es - for f in fs - Fs = Fsymbol(a, b, c, d, e, f) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(fs), Fblocks...) - if !isapprox(F' * F, one(F); atol=1e-9) - @show a,b,c,d,es,fs F - count += 1 - end - end +# checking multiplicity +function obs(i::Int) + return A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i, i]) end -count - -# i=1 one thing not unitary -a,b,c,d,es,fs = (A4Object(1, 1, 2), A4Object(1, 1, 2), A4Object(1, 1, 2), A4Object(1, 1, 2), A4Object[A4Object(1, 1, 4), A4Object(1, 1, 1), A4Object(1, 1, 3), A4Object(1, 1, 2)], A4Object[A4Object(1, 1, 4), A4Object(1, 1, 1), A4Object(1, 1, 3), A4Object(1, 1, 2)]) - -Fblocks = Vector{Any}() -for e in es - for f in fs - Fs = Fsymbol(a, b, c, d, e, f) - @show a,b,c,d,e,f Nsymbol(a,b,e), Nsymbol(e,c,d), Nsymbol(b,c,f), Nsymbol(a,f,d) Fs - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end + +for i in 1:12 + !any(Nsymbol(a, b, c) > 1 for a in obs(i), b in obs(i), c in obs(i)) && @show i end -Fblocks -Fblocks[end] -F = hvcat(length(fs), Fblocks...) -F * F' -block22 = Fsymbol(a,a,a,a,a,a) -Fblock22 = hvcat(4, block22...) +# trying to make heisenberg +using MultiTensorKit, TensorKit +using MPSKit, MPSKitModels -transpose.(Fblocks) -Ftr = hvcat(length(fs), transpose.(Fblocks)...) +D1 = A4Object(1, 1, 2) # 3-dimensional irrep of A4 +M = A4Object(2, 1, 1) # Vec -# checking multiplicity -function obs(i::Int) - return A4Object.(i, i, MultiTensorKit._get_dual_cache(I)[2][i,i]) -end +P = Vect[A4Object](D1 => 1) +h_aux1 = TensorMap(ones, ComplexF64, P ← P βŠ— P) +h_aux2 = TensorMap(ones, ComplexF64, P βŠ— P ← P) -for i in 1:12 - !any(Nsymbol(a,b,c) > 1 for a in obs(i), b in obs(i), c in obs(i)) && @show i -end \ No newline at end of file +@plansor h[-1 -2; -3 -4] := h_aux2[-1 1; -3] * h_aux1[-2; 1 -4] # different basis +lattice = InfiniteChain(1) +t = time() +H = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(lattice)); +dt = time() - t +println("Time to create Hamiltonian: ", dt, " seconds") + +D = 4 +V = Vect[A4Object](M => D) +t = time() +inf_init = InfiniteMPS([P], [V]); +dt = time() - t +println("Time to create InfiniteMPS: ", dt, " seconds") + +# VUMPS +t = time() +ψ, envs = find_groundstate(inf_init, H, VUMPS(; verbosity=3, tol=1e-12, maxiter=200)); +dt = time() - t +println("Time to find groundstate: ", dt, " seconds") +expectation_value(ψ, H, envs) # this gives 0 oopsie + +### caching checks +length(TensorKit.GLOBAL_FUSIONBLOCKSTRUCTURE_CACHE) + +length(TensorKit.treepermutercache) # tensor stuff +length(TensorKit.treetransposercache) +length(TensorKit.treebraidercache) + +length(TensorKit.transposecache) # fusion tree stuff +length(TensorKit.braidcache) From 87e75021e78ba0776e711151c5981b7e963e2ab7 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 4 Jun 2025 17:28:41 +0200 Subject: [PATCH 067/206] remove commented code --- src/bimodulesector.jl | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 87bf456..7ce4e8e 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -273,15 +273,6 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where end end -# function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T<:Number, S<:GradedSpace{A4Object}} -# @show t -# _vector = findall(!iszero, values(blocks(t))) # should have 0 or 1 elements, since only one of the blocks could be non-zero -# if isempty(_vector) -# return zero(scalartype(t)) -# end -# return only(values(blocks(t))[only(_vector)]) -# end - # TODO: definition for zero of GradedSpace? function dim(V::GradedSpace{<:BimoduleSector}) @@ -299,14 +290,6 @@ function Base.oneunit(S::GradedSpace{<:BimoduleSector}) return β„‚[A4Object](sector => 1) end -# function Base.oneunit(S::SumSpace{GradedSpace{A4Object, NTuple{486, Int64}}}) -# allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || -# throw(ArgumentError("sectors of $S are not all equal")) -# first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) -# sector = one(first(sectors(S))) -# return SumSpace(β„‚[A4Object](sector => 1)) -# end - function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || throw(ArgumentError("sectors of $S are not all equal")) From 9e8381574e96e9e046a83f8816fa56caf339adde Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 4 Jun 2025 17:42:58 +0200 Subject: [PATCH 068/206] build empty docs --- docs/Project.toml | 2 ++ docs/make.jl | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 docs/Project.toml create mode 100644 docs/make.jl diff --git a/docs/Project.toml b/docs/Project.toml new file mode 100644 index 0000000..dfa65cd --- /dev/null +++ b/docs/Project.toml @@ -0,0 +1,2 @@ +[deps] +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" diff --git a/docs/make.jl b/docs/make.jl new file mode 100644 index 0000000..2ed4141 --- /dev/null +++ b/docs/make.jl @@ -0,0 +1,7 @@ +using Documenter +using MultiTensorKit + +makedocs(; sitename="MultiTensorKit Documentation", modules=[MultiTensorKit], + authors="Boris De Vos, Laurens Lootens and Lukas Devos") + +deploydocs(; repo="https://github.com/QuantumKitHub/MultiTensorKit.jl") \ No newline at end of file From 8a62f08d8d70840fd7b79ddcdfc5f6afcae159df Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Jun 2025 09:27:25 +0200 Subject: [PATCH 069/206] add library and pages --- docs/make.jl | 5 ++++- docs/src/lib/library.md | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 docs/src/lib/library.md diff --git a/docs/make.jl b/docs/make.jl index 2ed4141..5b332c2 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,7 +1,10 @@ using Documenter using MultiTensorKit +pages = ["Home" => "index.md", "Library" => "lib/library.md"] + makedocs(; sitename="MultiTensorKit Documentation", modules=[MultiTensorKit], - authors="Boris De Vos, Laurens Lootens and Lukas Devos") + authors="Boris De Vos, Laurens Lootens and Lukas Devos", + pages=pages, pagesonly=true) deploydocs(; repo="https://github.com/QuantumKitHub/MultiTensorKit.jl") \ No newline at end of file diff --git a/docs/src/lib/library.md b/docs/src/lib/library.md new file mode 100644 index 0000000..cf49473 --- /dev/null +++ b/docs/src/lib/library.md @@ -0,0 +1,22 @@ +# MultiTensorKit + +**TensorKit extension to multifusion categories + +## Table of contents + +```@contents +Pages = ["lib/library.md"] +Depth = 1 +``` + +## Installation + +MultiTensorKit.jl is currently not registered to the Julia General Registry. You can install the package as +``` +pkg> add https://github.com/QuantumKitHub/MultiTensorKit.jl.git +``` + +## Usage + +As the name suggests, MultiTensorKit is an extension of [TensorKit.jl](https://github.com/Jutho/TensorKit.jl) and +[TensorKitSectors.jl](https://github.com/QuantumKitHub/TensorKitSectors.jl). \ No newline at end of file From 9c1b7cc92a141e98292481def51a54f45921c718 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Jun 2025 10:03:00 +0200 Subject: [PATCH 070/206] add docstring to `BimoduleSector` --- src/bimodulesector.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 7ce4e8e..1cf4673 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -1,3 +1,15 @@ +""" + struct BimoduleSector{Name} <: Sector + BimoduleSector{Name}(i::Int, j::Int, label::Int) + +Represents objects in the component subcategory ``π’žα΅’β±Ό`` of the multifusion category ``π’ž = ⨁ᡒⱼ π’žα΅’β±Ό``, +where ``π’ž`` is identified as Name. + +## Fields +- `i::Int`: The row index of the object in the matrix representation of the multifusion category. +- `j::Int`: The column index of the object in the matrix representation of the multifusion category. +- `label::Int`: The label of the object within the component subcategory. +""" struct BimoduleSector{Name} <: Sector i::Int j::Int From 2ee3e0c956ec3d07fba859adf03b9ae8e71cb05a Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Jun 2025 10:04:19 +0200 Subject: [PATCH 071/206] add MTK to project to build --- docs/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Project.toml b/docs/Project.toml index dfa65cd..6aba9cd 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,2 +1,3 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +MultiTensorKit = "f0555a46-f681-4ef1-bed5-d64870568636" From d6957ceb30f7ad187c231c8a80b8396362a114fc Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Jun 2025 10:04:56 +0200 Subject: [PATCH 072/206] make library --- docs/src/lib/library.md | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/docs/src/lib/library.md b/docs/src/lib/library.md index cf49473..86a8f6c 100644 --- a/docs/src/lib/library.md +++ b/docs/src/lib/library.md @@ -1,22 +1,5 @@ -# MultiTensorKit +# Library -**TensorKit extension to multifusion categories - -## Table of contents - -```@contents -Pages = ["lib/library.md"] -Depth = 1 -``` - -## Installation - -MultiTensorKit.jl is currently not registered to the Julia General Registry. You can install the package as -``` -pkg> add https://github.com/QuantumKitHub/MultiTensorKit.jl.git -``` - -## Usage - -As the name suggests, MultiTensorKit is an extension of [TensorKit.jl](https://github.com/Jutho/TensorKit.jl) and -[TensorKitSectors.jl](https://github.com/QuantumKitHub/TensorKitSectors.jl). \ No newline at end of file +```@autodocs +Modules = [MultiTensorKit] +``` \ No newline at end of file From 6d8650ba3825d2543e62ca7edc7138ce0dd0dcab Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Jun 2025 10:59:43 +0200 Subject: [PATCH 073/206] add structure of manual --- docs/src/man/fusioncats.md | 10 ++++++++++ docs/src/man/multifusioncats.md | 1 + 2 files changed, 11 insertions(+) create mode 100644 docs/src/man/fusioncats.md create mode 100644 docs/src/man/multifusioncats.md diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md new file mode 100644 index 0000000..7d5de61 --- /dev/null +++ b/docs/src/man/fusioncats.md @@ -0,0 +1,10 @@ +# Introduction + +The manual has been divided into different sections in an attempt to break down the information the user requires to use MultiTensorKit.jl. +We start off with a short summary of fusion category theory. Users familiar with TensorKit.jl may have read the [Optional introduction to category theory](https://jutho.github.io/TensorKit.jl/stable/man/categories/) in the documentation of TensorKit; this section can then largely be skipped. Be aware that notation may differ from the literature. + +Afterwards, the extension to multifusion categories is explained, and its relation to (bi)module categories over fusion categories is shown. + +# Fusion category theory + +The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [Optional introduction to category theory](https://jutho.github.io/TensorKit.jl/stable/man/categories/) or the book [Tensor Categories](add citation after figuring out how) diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md new file mode 100644 index 0000000..ef7cad7 --- /dev/null +++ b/docs/src/man/multifusioncats.md @@ -0,0 +1 @@ +# Extending to multifusion category theory \ No newline at end of file From bcb95c15b06fd59078c157c7953d2f67b056c611 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Jun 2025 11:00:06 +0200 Subject: [PATCH 074/206] start on references --- docs/make.jl | 4 +++- docs/src/references.md | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 docs/src/references.md diff --git a/docs/make.jl b/docs/make.jl index 5b332c2..ec10dba 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,7 +1,9 @@ using Documenter using MultiTensorKit -pages = ["Home" => "index.md", "Library" => "lib/library.md"] +pages = ["Home" => "index.md", "Library" => "lib/library.md", + "Manual" => ["man/fusioncats.md", "man/multifusioncats.md"], + "References" => "references.md"] makedocs(; sitename="MultiTensorKit Documentation", modules=[MultiTensorKit], authors="Boris De Vos, Laurens Lootens and Lukas Devos", diff --git a/docs/src/references.md b/docs/src/references.md new file mode 100644 index 0000000..d0f92e9 --- /dev/null +++ b/docs/src/references.md @@ -0,0 +1,4 @@ +# References used in documentation + +```@bibliography +``` \ No newline at end of file From 22b01d99cd8301f99feda3254017428a59a03ce2 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 5 Jun 2025 12:49:38 +0200 Subject: [PATCH 075/206] get a reference working --- docs/Project.toml | 1 + docs/make.jl | 8 +++++++- docs/src/assets/MTKrefs.bib | 11 +++++++++++ docs/src/man/fusioncats.md | 2 +- 4 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 docs/src/assets/MTKrefs.bib diff --git a/docs/Project.toml b/docs/Project.toml index 6aba9cd..a36ea53 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,3 +1,4 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244" MultiTensorKit = "f0555a46-f681-4ef1-bed5-d64870568636" diff --git a/docs/make.jl b/docs/make.jl index ec10dba..fb3f7bb 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,12 +1,18 @@ using Documenter +using DocumenterCitations using MultiTensorKit pages = ["Home" => "index.md", "Library" => "lib/library.md", "Manual" => ["man/fusioncats.md", "man/multifusioncats.md"], "References" => "references.md"] + +# bibliography +bibpath = joinpath(@__DIR__, "src", "assets", "MTKrefs.bib") +bib = CitationBibliography(bibpath; style=:authoryear) + makedocs(; sitename="MultiTensorKit Documentation", modules=[MultiTensorKit], authors="Boris De Vos, Laurens Lootens and Lukas Devos", - pages=pages, pagesonly=true) + pages=pages, pagesonly=true, plugins=[bib]) deploydocs(; repo="https://github.com/QuantumKitHub/MultiTensorKit.jl") \ No newline at end of file diff --git a/docs/src/assets/MTKrefs.bib b/docs/src/assets/MTKrefs.bib new file mode 100644 index 0000000..630f882 --- /dev/null +++ b/docs/src/assets/MTKrefs.bib @@ -0,0 +1,11 @@ +@book{etingof2016tensor, + title={Tensor Categories}, + author={Etingof, P. and Gelaki, S. and Nikshych, D. and Ostrik, V.}, + isbn={9781470434410}, + lccn={2015006773}, + series={Mathematical Surveys and Monographs}, + url={https://books.google.be/books?id=Z6XLDAAAQBAJ}, + year={2016}, + publisher={American Mathematical Society} +} + diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 7d5de61..5f3c009 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -7,4 +7,4 @@ Afterwards, the extension to multifusion categories is explained, and its relati # Fusion category theory -The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [Optional introduction to category theory](https://jutho.github.io/TensorKit.jl/stable/man/categories/) or the book [Tensor Categories](add citation after figuring out how) +The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [Optional introduction to category theory](https://jutho.github.io/TensorKit.jl/stable/man/categories/) or the book Tensor Categories ([etingof2016tensor](@cite)). From d50cdc995fdda526fd247321b4fa6a7295c7e213 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 6 Jun 2025 09:10:31 +0200 Subject: [PATCH 076/206] progress on body of docs --- docs/src/assets/MTKrefs.bib | 12 +++++++++ docs/src/man/fusioncats.md | 45 ++++++++++++++++++++++++++++++++- docs/src/man/multifusioncats.md | 11 +++++++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/docs/src/assets/MTKrefs.bib b/docs/src/assets/MTKrefs.bib index 630f882..7f3ed70 100644 --- a/docs/src/assets/MTKrefs.bib +++ b/docs/src/assets/MTKrefs.bib @@ -9,3 +9,15 @@ @book{etingof2016tensor publisher={American Mathematical Society} } +@article{Lootens_2023, + title={Dualities in One-Dimensional Quantum Lattice Models: Symmetric Hamiltonians and Matrix Product Operator Intertwiners}, + volume={4}, + ISSN={2691-3399}, + url={http://dx.doi.org/10.1103/PRXQuantum.4.020357}, + DOI={10.1103/prxquantum.4.020357}, + number={2}, + journal={PRX Quantum}, + publisher={American Physical Society (APS)}, + author={Lootens, Laurens and Delcamp, Clement and Ortiz, Gerardo and Verstraete, Frank}, + year={2023}, + month=jun } diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 5f3c009..6f89ddd 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -7,4 +7,47 @@ Afterwards, the extension to multifusion categories is explained, and its relati # Fusion category theory -The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [Optional introduction to category theory](https://jutho.github.io/TensorKit.jl/stable/man/categories/) or the book Tensor Categories ([etingof2016tensor](@cite)). +The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [TensorKit documentation](https://jutho.github.io/TensorKit.jl/stable/man/categories/) or the book Tensor Categories ([etingof2016tensor](@cite)). + +Let us start simple and introduce the **fusion ring** $\mathcal{C}$ in a black-box manner. This ring +* consists of finitely many simple objects $\{ X_1, X_2, ..., X_R \}$, with $R$ the rank of the fusion ring, +* which can be fused with one another: $X_i \otimes X_j = \sum_k N_{ij}^k X_k$, introducing the **N-symbol** $N_{ij}^k \in \mathbb{N}$ in the fusion rules, +* contains a *unique* unit object $1_\mathcal{C}$ which satisfies $1_\mathcal{C} \otimes X_i = X_i \otimes 1_\mathcal{C} = X_i$ for all objects $X_i \in \mathcal{C}$, +* has a dual object $\overline{X}$ for every object $X$ such that $X \otimes \overline{X} = \overline{X} \otimes X = 1_\mathcal{C} \oplus ...$, generalising the notion of the inverse element. + +To extend the fusion ring to the **fusion category**, we need to add the following structure: +* Consider only the representatives of isomorphism classes of simple objects $\mathcal{I}_\mathcal{C}$, +* The associator $F^{X_iX_jX_k}: (X_i \otimes X_j) \otimes X_k \rightarrow X_i \otimes (X_j \otimes X_k)$ which fulfills the famous pentagon equation, +* Morphisms between (simple) objects $\text{\text{Hom}}_\mathcal{C}(X_i, X_j)$, which are empty vector spaces unless the objects are isomorphic, the latter then giving $\mathbb{C}$, +* More general morphisms $\text{\text{Hom}}_\mathcal{C}(X_i \otimes X_j, X_k) = \mathbb{C}^{N_{ij}^k}$. + +Vectors in these hom-spaces are graphically denoted + +![homvector](img/...) + +With the associator, commonly called the **F-symbol**, we can perform F-moves: + +![Fmove](img/...) + +TensorKit requires the F-symbols to be unitary. This way, we can interpret the F-symbol with 4 indices as a unitary matrix, and the F-move as a unitary basis transformation. + +## Examples + +### $\mathsf{VecG}$ and $\mathsf{RepG}$ +Colloquially speaking, category theory attempts to generalise mathematical structures and their relations in a way that different structures can be treated in an equal manner. This is noted in particular as fusion category theory encompasses not only finite and compact groups, but also their representations. We show a table sketching how these are put on equal footing categorically. + +|$\mathsf{VecG}$|$\mathsf{RepG}$|Categorical generalisation| +|:---:|:---:|:---:| +|$G$-graded vector spaces $V_1, V_2, ...$|Representations of $G$
$(V_1, \pi_1), (V_2, \pi_2), ...$|Objects| +|$G$-graded preserving linear maps
$\phi: V \rightarrow W$|Intertwiners $f: V_1 \rightarrow V_2$,
$f \circ \pi_1 = \pi_2 \circ f$|Morphisms $\text{Hom}_\mathcal{C}$| +1d subspaces $\mathbb{C}_{g_1}, \mathbb{C}_{g_2}$:
$\text{Hom}_{\mathsf{VecG}}(\mathbb{C}_{g_1},\mathbb{C}_{g_2}) = \delta_{g_1g_2}$|Irreps: $\text{Hom}_{\mathsf{RepG}}(\rho_i,\rho_j) = \delta_{ij} \mathbb{C}$ (Schur)|Simple objects: $\text{Hom}_{\mathcal{C}}(a,b) = \delta_{ab}\mathbb{C}$| +$G$-graded tensor product $(V \otimes W)_g = \oplus_{hk=g} V_h \otimes W_k$| $\pi_i \otimes \pi_j \simeq \oplus_i N_{ij}^k\rho_k$ | Direct sum, monoidal product, fusion rules, multiplicity| +$\mathbb{C}_1 \otimes W \simeq W \simeq W \otimes \mathbb{C}_1$ | Trivial rep 1: $1 \otimes \rho = \rho = \rho \otimes 1$ | Monoidal unit $1_\mathcal{C}$ +$\mathbb{C}_g \otimes \mathbb{C}_{g^{-1}} = \mathbb{C}_1 = \mathbb{C}_{g^{-1}} \otimes \mathbb{C}_g$ | $\pi \otimes \overline{\pi} = 1 \oplus ...$ | Dual object +$F:(V \otimes W) \otimes U \xrightarrow{\sim}V \otimes (W \otimes U)$|$F: (\pi_1 \otimes \pi_2) \otimes \pi_3 \xrightarrow{\sim} \pi_1 \otimes (\pi_2 \otimes \pi_3)$|F-symbol| + +# Fusion categories in condensed matter physics +- String-net models -> non-chiral topological order classification +- Kitaev's appendix E -> anyonic excitations +- Golden chain, anyonic spin chains +- \ No newline at end of file diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index ef7cad7..1f4f7a1 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -1 +1,10 @@ -# Extending to multifusion category theory \ No newline at end of file +# Extending to multifusion category theory + +This section will explain how to go from a fusion category to a multifusion category, as well as why one would want to consider the latter. Multifusion categories naturally embed the structure of **bimodule categories**. To explain this, we must start by explaining module categories over fusion categories, following this up with (invertible) bimodule categories, and finishing off with the multifusion structure. + +## Module categories +We will use the notation in [Lootens et al.](@cite Lootens_2023) for fusion categories and module categories over these. Starting from a fusion category $\mathcal{D}$ with simple objects $\alpha, \beta, ... \in \mathcal{I}_\mathcal{D}$, we call its associator $F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) \xrightarrow{\sim} (\alpha \otimes \beta) \otimes \gamma$ the **monoidal associator**. An F-move is now graphically portrayed as + +![Fmove_D]() + +We can consider the right module category $\mathcal{M}$ over $\mathcal{D}$, which is a category (not necessarily fusion!) with a right action $\triangleleft: \mathcal{M} \times \mathcal{D} \rightarrow \mathcal{M}$ \ No newline at end of file From 5fe6277bb41932b619cac3788857ff5fe9fc125c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 6 Jun 2025 17:43:53 +0200 Subject: [PATCH 077/206] more work on body --- docs/src/assets/MTKrefs.bib | 20 ++++++++++++++ docs/src/man/fusioncats.md | 21 ++++++++------- docs/src/man/img/Fmove.pdf | Bin 0 -> 46117 bytes docs/src/man/multifusioncats.md | 46 ++++++++++++++++++++++++++++++-- 4 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 docs/src/man/img/Fmove.pdf diff --git a/docs/src/assets/MTKrefs.bib b/docs/src/assets/MTKrefs.bib index 7f3ed70..c7fe36c 100644 --- a/docs/src/assets/MTKrefs.bib +++ b/docs/src/assets/MTKrefs.bib @@ -21,3 +21,23 @@ @article{Lootens_2023 author={Lootens, Laurens and Delcamp, Clement and Ortiz, Gerardo and Verstraete, Frank}, year={2023}, month=jun } + +@misc{etingof2009, + title={Fusion categories and homotopy theory}, + author={Pavel Etingof and Dmitri Nikshych and Victor Ostrik and with an appendix by Ehud Meir}, + year={2009}, + eprint={0909.3140}, + archivePrefix={arXiv}, + primaryClass={math.QA}, + url={https://arxiv.org/abs/0909.3140}, +} + +@misc{henriques2020, + title={Representations of fusion categories and their commutants}, + author={AndrΓ© Henriques and David Penneys}, + year={2020}, + eprint={2004.08271}, + archivePrefix={arXiv}, + primaryClass={math.OA}, + url={https://arxiv.org/abs/2004.08271}, +} \ No newline at end of file diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 6f89ddd..47d31cb 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -11,25 +11,28 @@ The aim of this section is to explain the bare minimum required to proceed to th Let us start simple and introduce the **fusion ring** $\mathcal{C}$ in a black-box manner. This ring * consists of finitely many simple objects $\{ X_1, X_2, ..., X_R \}$, with $R$ the rank of the fusion ring, -* which can be fused with one another: $X_i \otimes X_j = \sum_k N_{ij}^k X_k$, introducing the **N-symbol** $N_{ij}^k \in \mathbb{N}$ in the fusion rules, -* contains a *unique* unit object $1_\mathcal{C}$ which satisfies $1_\mathcal{C} \otimes X_i = X_i \otimes 1_\mathcal{C} = X_i$ for all objects $X_i \in \mathcal{C}$, -* has a dual object $\overline{X}$ for every object $X$ such that $X \otimes \overline{X} = \overline{X} \otimes X = 1_\mathcal{C} \oplus ...$, generalising the notion of the inverse element. +* which can be fused with one another: $X_i \otimes X_j \cong \sum_k N_{ij}^k X_k,$ introducing the **N-symbol** $N_{ij}^k \in \mathbb{N}$ in the fusion rules, +* contains a *unique* unit object $1_\mathcal{C}$ which satisfies $1_\mathcal{C} \otimes X_i \cong X_i \otimes 1_\mathcal{C} \cong X_i$ for all objects $X_i \in \mathcal{C}$, +* has a dual object $\overline{X}$ for every object $X$ such that $X \otimes \overline{X} \cong \overline{X} \otimes X \cong 1_\mathcal{C} \oplus ...$, generalising the notion of the inverse element. To extend the fusion ring to the **fusion category**, we need to add the following structure: * Consider only the representatives of isomorphism classes of simple objects $\mathcal{I}_\mathcal{C}$, -* The associator $F^{X_iX_jX_k}: (X_i \otimes X_j) \otimes X_k \rightarrow X_i \otimes (X_j \otimes X_k)$ which fulfills the famous pentagon equation, +* The associator $F^{X_iX_jX_k}: (X_i \otimes X_j) \otimes X_k \xrightarrow{\sim} X_i \otimes (X_j \otimes X_k)$ + which fulfills the famous pentagon equation, * Morphisms between (simple) objects $\text{\text{Hom}}_\mathcal{C}(X_i, X_j)$, which are empty vector spaces unless the objects are isomorphic, the latter then giving $\mathbb{C}$, -* More general morphisms $\text{\text{Hom}}_\mathcal{C}(X_i \otimes X_j, X_k) = \mathbb{C}^{N_{ij}^k}$. +* More general morphisms $\text{\text{Hom}}_\mathcal{C}(X_i \otimes X_j, X_k) \cong \mathbb{C}^{N_{ij}^k}$. -Vectors in these hom-spaces are graphically denoted +This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C}, F)$ of $\mathcal{C}$ defining its monoidal product, unit object and monoidal associator, the latter also commonly called the **F-symbol**. In particular, the simple objects have their respective quantum dimensions $d_i = \dim(X_i)$ which form their own one-dimensional representation of the fusion algebra: $d_i d_j = \sum_k N_{ij}^k d_k$. In particular, the unit object always has quantum dimension 1, and all other quantum dimensions are larger or equal to one. These quantum dimensions are encoded in the F-symbol. The isomorphisms instead of the equalities are a technical detail, so we drop that notation. + +Vectors in these hom-spaces are graphically denoted as living in the trivalent junction ![homvector](img/...) -With the associator, commonly called the **F-symbol**, we can perform F-moves: +With the F-symbol, we can perform F-moves: -![Fmove](img/...) +![Fmove](img/Fmove.pdf) -TensorKit requires the F-symbols to be unitary. This way, we can interpret the F-symbol with 4 indices as a unitary matrix, and the F-move as a unitary basis transformation. +TensorKit requires the F-symbols to be unitary. This way, we can interpret the F-symbol $F^{ijk}_l$ as a unitary matrix, and the F-move as a unitary basis transformation. Unitarity is also useful from a diagrammatic point of view because the category is then equipped with a pivotal and spherical structure. This essentially means that morphisms can be drawn and moved around freely on a 2-sphere, such that vector spaces can be moved freely from domain (codomain) to codomain (domain). ## Examples diff --git a/docs/src/man/img/Fmove.pdf b/docs/src/man/img/Fmove.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6771aa4573004feed007e6cab48e8f008da17d9f GIT binary patch literal 46117 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 V(b@g$dBZU?vBQy(iOP$?{U3-t9#jAT literal 0 HcmV?d00001 diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 1f4f7a1..4231f49 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -3,8 +3,50 @@ This section will explain how to go from a fusion category to a multifusion category, as well as why one would want to consider the latter. Multifusion categories naturally embed the structure of **bimodule categories**. To explain this, we must start by explaining module categories over fusion categories, following this up with (invertible) bimodule categories, and finishing off with the multifusion structure. ## Module categories -We will use the notation in [Lootens et al.](@cite Lootens_2023) for fusion categories and module categories over these. Starting from a fusion category $\mathcal{D}$ with simple objects $\alpha, \beta, ... \in \mathcal{I}_\mathcal{D}$, we call its associator $F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) \xrightarrow{\sim} (\alpha \otimes \beta) \otimes \gamma$ the **monoidal associator**. An F-move is now graphically portrayed as +We will mostly use the notation in [Lootens et al.](@cite Lootens_2023) for fusion categories and module categories over these. We start from a fusion category $\mathcal{D}$ defined by the triple $(\otimes_\mathcal{D}, \mathbb{1}_\mathcal{D}, {}^\mathcal{D}\!F)$ with simple objects $\alpha, \beta, ... \in \mathcal{I}_\mathcal{D}$. We drop the $\mathcal{D}$ subscript when there is no ambiguity concerning the fusion category. We call its associator +$${}^\mathcal{D}\!F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) \rightarrow (\alpha \otimes \beta) \otimes \gamma$$ + the **monoidal associator**. An F-move is now graphically portrayed as: ![Fmove_D]() -We can consider the right module category $\mathcal{M}$ over $\mathcal{D}$, which is a category (not necessarily fusion!) with a right action $\triangleleft: \mathcal{M} \times \mathcal{D} \rightarrow \mathcal{M}$ \ No newline at end of file +We can consider the **right module category** $\mathcal{M}$ over $\mathcal{D}$, which is a category (not necessarily fusion!) with (isomorphism classes of) simple objects $\mathcal{I}_\mathcal{M} = \{A,B,...\}$, a right action +$$\triangleleft: \mathcal{M} \times \mathcal{D} \rightarrow \mathcal{M}$$ +and the **right module associator** +$${}^\triangleleft\!F^{A\alpha\beta}: A \triangleleft (\alpha \otimes \beta) \rightarrow (A \triangleleft \alpha) \triangleleft \beta.$$ +An F-move with this module associator can be expressed as: + +![Fmove_MD]() + +The module structure of $\mathcal{M}$ is now defined as the triple $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$. The right module associator now satisfies a mixed pentagon equation with ${}^\mathcal{D}\!F$. + +Similarly, we can define a **left module category** $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ over a fusion category $(\otimes_\mathcal{C}, 1_\mathcal{C}, {}^\mathcal{C}\!F)$. The functor is now a left action of $\mathcal{C}$ on $\mathcal{M}$ +$$\triangleright: \mathcal{C} \times \mathcal{M} \rightarrow \mathcal{M},$$ +while the **left module associator** is a natural isomorphism that acts as +$${}^\triangleright\!F^{abA}: (a \otimes b) \triangleright A \rightarrow a \triangleright (b \triangleright A)$$ +for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. The left module associator also fulfills a mixed pentagon equation with ${}^\mathcal{C}\!F$. An F-move with ${}^\mathcal{C}\!F$ takes on the form: + +![Fmove_CM]() + +We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, and $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as +$${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F^{aA\alpha}: (a \triangleright A) \triangleleft \alpha \rightarrow a \triangleright (A \triangleleft \alpha)$$ +for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. The bimodule associator fulfills a mixed pentagon equation with the module associators. An F-move with ${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F$ is given by: + +![Fmove_CMD]() +## Opposite module categories +Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). Then $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. A similar statement can be made starting from a left module category and getting an opposite right module category. In particular, given a $(\mathcal{C}, \mathcal{D})$-bimodule category $\mathcal{M}$ over the fusion categories $\mathcal{C}, \mathcal{D}$, we see immediately that $\mathcal{M}^{\text{op}}$ is a $(\mathcal{D}, \mathcal{C})$-bimodule category. + +Interestingly, due to the opposite actions +$$\triangleleft^{\text{op}}: \mathcal{D} \times \mathcal{M}^{\text{op}} \rightarrow \mathcal{M}^{\text{op}}$$ +and +$$\triangleright^{\text{op}}: \mathcal{M}^{\text{op}} \times \mathcal{C} \rightarrow \mathcal{M}^{\text{op}},$$ +there is a valid notion of multiplying a module category with its opposite: +$$ +\mathcal{M} \times \mathcal{M}^\text{op} \rightarrow \mathcal{C}, \quad \mathcal{M}^\text{op} \times \mathcal{M} \rightarrow \mathcal{D}. +$$ + +## Multifusion categories +A fusion category has the important condition that $\mathsf{End}_\mathcal{C}(1_\mathcal{C}) \cong \mathbb{C}$, i.e., the unit of the fusion category is simple. If we drop this condition, then we consider a **multifusion category**. We assume the multifusion category itself to be indecomposable, meaning it is not the direct sum of two non-trivial multifusion categories. Let us call this multifusion category $\mathcal{C}$. It will be clear in a moment that this will not be ambiguous. Its unit can then be decomposed as +$$ 1_\mathcal{C} = \bigoplus_{i=1}^r 1_r$$, +i.e., it is decomposed into simple objects of the +### Why opposite module categories end up being necessary in MultiTensorKit +something something B-move of module leg \ No newline at end of file From b4bd63758a51b65754ba0d092e1972e8cc7c32ba Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 6 Jun 2025 17:46:05 +0200 Subject: [PATCH 078/206] add main index --- .gitignore | 1 - docs/src/index.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 docs/src/index.md diff --git a/.gitignore b/.gitignore index 10593a9..5f9fc64 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,3 @@ Manifest.toml benchmark/*.json docs/Manifest.toml docs/build/ -docs/src/index.md diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..01474e4 --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,34 @@ +# MultiTensorKit + +**TensorKit extension to multifusion categories** + +## Package summary +MultiTensorKit.jl provides the user a package to work with multifusion categories, the extension of regular fusion categories where the unit is no longer simple and unique. +Multifusion categories naturally embed the structure of module categories over fusion categories. Hence, MultiTensorKit.jl allows not only the fusion of objects within the same +fusion category (as TensorKit.jl), but also the fusion with and between module categories over these fusion categories. + +MultiTensorKit.jl is built to be compatible with TensorKit, thus allowing the construction of symmetric tensors with new symmetries due to the module structure. Through this, +tensor network simulations of quantum many-body systems with aid of [MPSKit.jl](https://github.com/QuantumKitHub/MPSKit.jl) can be performed. + +## Table of contents + +```@contents +Pages = ["man/fusioncats.md", "man/multifusioncats.md","lib/library.md", "references.md"] +Depth = 2 +``` + +## Installation + +MultiTensorKit.jl is currently not registered to the Julia General Registry. You can install the package as +``` +pkg> add https://github.com/QuantumKitHub/MultiTensorKit.jl.git +``` + +## Usage + +As the name suggests, MultiTensorKit is an extension of [TensorKit.jl](https://github.com/Jutho/TensorKit.jl) and +[TensorKitSectors.jl](https://github.com/QuantumKitHub/TensorKitSectors.jl). Therefore, we recommend including TensorKit +to your project. Additionally, MultiTensorKit was made to be functional with [MPSKit.jl](https://github.com/QuantumKitHub/MPSKit.jl) +and [MPSKitModels.jl](https://github.com/QuantumKitHub/MPSKitModels.jl) for Matrix Product State (MPS) calculations, supporting symmetries +which go beyond TensorKit. + From c644657fabe5f113fdc8d09b53537f1b61a50029 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 6 Jun 2025 18:21:16 +0200 Subject: [PATCH 079/206] add more Fmove images --- docs/src/man/img/Fmove_CM.pdf | Bin 0 -> 37670 bytes docs/src/man/img/Fmove_CMD.pdf | Bin 0 -> 37814 bytes docs/src/man/img/Fmove_MD.pdf | Bin 0 -> 37863 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/src/man/img/Fmove_CM.pdf create mode 100644 docs/src/man/img/Fmove_CMD.pdf create mode 100644 docs/src/man/img/Fmove_MD.pdf diff --git a/docs/src/man/img/Fmove_CM.pdf b/docs/src/man/img/Fmove_CM.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c20ffb229f2d53500685050ca819535655ed7c5b GIT binary patch literal 37670 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 HBldp*8TSkH literal 0 HcmV?d00001 diff --git a/docs/src/man/img/Fmove_CMD.pdf b/docs/src/man/img/Fmove_CMD.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cae10bc1f573da0175677b36cdf5e7a66f813198 GIT binary patch literal 37814 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 z%0A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 BChGtI literal 0 HcmV?d00001 diff --git a/docs/src/man/img/Fmove_MD.pdf b/docs/src/man/img/Fmove_MD.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2ae3251a4fb76cbefb79f0766d815db3cf630e38 GIT binary patch literal 37863 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

-OcovT+JG=}k@ckNpd2*g@5+{#U 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

4E>iPA3DX$OS@Cv0RxgZNq~J!pBf;k@ptA(`YH_ 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 literal 0 HcmV?d00001 From c584a895a3aa1597fe96df3554f0be55493da48e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 9 Jun 2025 14:34:55 +0200 Subject: [PATCH 080/206] change `IteratorSize` to actually evaluate `SizeUnknown` --- src/bimodulesector.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 7ce4e8e..09c40ff 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -21,7 +21,7 @@ function Base.convert(::Type{BimoduleSector{Name}}, d::NTuple{3,Int}) where {Nam return BimoduleSector{Name}(d...) end -Base.IteratorSize(::Type{SectorValues{<:BimoduleSector}}) = Base.SizeUnknown() +Base.IteratorSize(::Type{<:SectorValues{<:BimoduleSector}}) = Base.SizeUnknown() # TODO: generalize? function Base.iterate(iter::SectorValues{A4Object}, (I, label)=(1, 1)) From 55c8708e71f39fc5f2f523e82532a5bf67a7a9b8 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 9 Jun 2025 14:36:35 +0200 Subject: [PATCH 081/206] change `blocksectors` definition to be flexible with `GradedSpace` type --- src/bimodulesector.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 09c40ff..8340b8c 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -252,8 +252,8 @@ end #----------------------------------------- function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where - {S<:Union{GradedSpace{A4Object,NTuple{486,Int64}}, - SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}}},N₁,Nβ‚‚} + {S<:Union{Vect[A4Object], + SumSpace{Vect[A4Object]}},N₁,Nβ‚‚} codom = codomain(W) dom = domain(W) # @info "in the correct blocksectors" From 480d944fe64e21afde2835db4e9d32e6730dd8e8 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 10 Jun 2025 14:28:24 +0200 Subject: [PATCH 082/206] remove debug elements + clean up error messages --- src/bimodulesector.jl | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 8340b8c..090eb31 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -79,7 +79,6 @@ const Ncache = IdDict{Type{<:BimoduleSector},Array{Dict{NTuple{3,Int},Int},3}}() function _get_Ncache(::Type{T}) where {T<:BimoduleSector} global Ncache return get!(Ncache, T) do - @debug "loading Nsymbol cache for $T" return extract_Nsymbol(T) end end @@ -97,7 +96,6 @@ const Dualcache = IdDict{Type{<:BimoduleSector},Tuple{Vector{Int64},Matrix{Vecto function _get_dual_cache(::Type{T}) where {T<:BimoduleSector} global Dualcache return get!(Dualcache, T) do - @debug "loading dual cache for $T" return extract_dual(T) end end @@ -159,7 +157,7 @@ function extract_dual(::Type{A4Object}) end function Base.one(a::BimoduleSector) - a.i == a.j || error("don't know how to define one for modules") + a.i == a.j || error("unit object for module categories is ill-defined") return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end @@ -179,7 +177,6 @@ function extract_Fsymbol(::Type{A4Object}) result = Dict{NTuple{4,Int},Dict{NTuple{6,Int},Array{ComplexF64,4}}}() for i in 1:12 filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") - @debug "loading $filename" @assert isfile(filename) "cannot find $filename" Farray_part = readdlm(filename) for ((i, j, k, l), colordict) in convert_Fs(Farray_part) @@ -226,7 +223,6 @@ const Fcache = IdDict{Type{<:BimoduleSector}, function _get_Fcache(::Type{T}) where {T<:BimoduleSector} global Fcache return get!(Fcache, T) do - @debug "loading Fsymbol cache for $T" return extract_Fsymbol(T) end end @@ -256,7 +252,6 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where SumSpace{Vect[A4Object]}},N₁,Nβ‚‚} codom = codomain(W) dom = domain(W) - # @info "in the correct blocksectors" if N₁ == 0 && Nβ‚‚ == 0 # 0x0-dimensional TensorMap is just a scalar, return all units # this is a problem in full contractions where the coloring outside is π’ž return NTuple{12,A4Object}(one(A4Object(i, i, 1)) for i in 1:12) # have to return all units b/c no info on W in this case @@ -304,7 +299,7 @@ function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P)) conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{<:I},N} where {I<:BimoduleSector} #possible change to rightone of correct space for N = 0 - u = N > 0 ? oneunit(P[1]) : error("no unit object in this space") + u = N > 0 ? oneunit(P[1]) : error("no unit object in $P") if dual u = TensorKit.dual(u) end @@ -317,7 +312,7 @@ end function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P) + 1); conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{<:I},N} where {I<:BimoduleSector} - u = N > 0 ? oneunit(P[1]) : error("no unit object in this space") + u = N > 0 ? oneunit(P[1]) : error("no unit object in $P") if dual u = TensorKit.dual(u) end From 42e3704de336705802fde8d114c26b052d7e9712 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 13 Jun 2025 17:41:30 +0200 Subject: [PATCH 083/206] more docs and figs --- docs/src/man/img/Nsymbol_coloring.pdf | Bin 0 -> 37275 bytes docs/src/man/multifusioncats.md | 64 ++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 docs/src/man/img/Nsymbol_coloring.pdf diff --git a/docs/src/man/img/Nsymbol_coloring.pdf b/docs/src/man/img/Nsymbol_coloring.pdf new file mode 100644 index 0000000000000000000000000000000000000000..079bb95e6428cc6ed87e202b853e8f6b679330f2 GIT binary patch literal 37275 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 S0OOm>$k2>SRn^tsjSB$(4jgU( literal 0 HcmV?d00001 diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 4231f49..1886474 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -44,9 +44,67 @@ $$ \mathcal{M} \times \mathcal{M}^\text{op} \rightarrow \mathcal{C}, \quad \mathcal{M}^\text{op} \times \mathcal{M} \rightarrow \mathcal{D}. $$ +something something morita equivalence and invertible bimodule, maybe drinfeld center, maybe anyons, maybe domain walls + ## Multifusion categories A fusion category has the important condition that $\mathsf{End}_\mathcal{C}(1_\mathcal{C}) \cong \mathbb{C}$, i.e., the unit of the fusion category is simple. If we drop this condition, then we consider a **multifusion category**. We assume the multifusion category itself to be indecomposable, meaning it is not the direct sum of two non-trivial multifusion categories. Let us call this multifusion category $\mathcal{C}$. It will be clear in a moment that this will not be ambiguous. Its unit can then be decomposed as -$$ 1_\mathcal{C} = \bigoplus_{i=1}^r 1_r$$, -i.e., it is decomposed into simple objects of the +$$ 1_\mathcal{C} = \bigoplus_{i=1}^r 1_r,$$ +i.e., it is decomposed into simple unit objects of the subcategories $\mathcal{C}_{ij} \coloneqq 1_i \otimes \mathcal{C} \otimes 1_j$. With this, we see that the multifusion category itself can be decomposed into its subcategories +$$\mathcal{C} = \bigoplus_{i,j=1}^r \mathcal{C}_{ij}.$$ +We call this an $r \times r$ multifusion category. + +We want to consider multifusion categories because **their structure encapsulates that of (bi-)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. In particular, the tensor product +$$\otimes_\mathcal{C}: \mathcal{C}_{ij} \times \mathcal{C}_{kl} \rightarrow \delta_{jk}\mathcal{C}_{il}$$ +takes on the same structure as the product of two matrix units. This is not a coincidence; there is a deep relation between multifusion categories and matrix algebras [etingof2016tensor; Section 4.3](@cite). + +Given a subcategory $\mathcal{C}_{ij}$, we can define the **left** unit as the unit object of the fusion category $\mathcal{C}_i$, while the **right** unit is the unit object of the fusion category $\mathcal{C}_j$. In other words, the left unit of $\mathcal{C}_{ij}$ is the unique object of the multifusion category $\mathcal{C}$ for which +$$1_i \otimes_\mathcal{C} M_{ij} = M_{ij} \quad \forall M_{ij} \in \mathcal{C}_{ij},$$ +and similarly for the right unit of $\mathcal{C}_{ij}$, +$$M_{ij} \otimes_\mathcal{C} 1_j = M_{ij} \quad \forall M_{ij} \in \mathcal{C}_{ij}.$$ + +We can also immediately see that for a (bi)module subcategory $\mathcal{C}_{ij}$, the opposite (bi)module subcategory $\mathcal{C}_{ij}^{\text{op}} \equiv \mathcal{C}_{ji}$, and as expected, +$$\mathcal{C}_{ij} \times \mathcal{C}_{ji} \rightarrow \mathcal{C}_i,$$ +just like what we concluded when considering opposite module categories outside of the multifusion structure. +### 2-category and coloring +diagrammatic calculus with coloring and such and so + +Multifusion categories can also be interpreted as 2-categories. We still interpret the objects of this 2-category the same way. The 1-morphisms are the subcategories themselves, and the 2-morphisms the morphisms of the multifusion category. The graphical calculus of monoidal 1-categories can be extended to 2-categories by use of *colorings*. We have previously differed between module strands and fusion strands by the color of the strand itself. However, in 2-categories the strands (1-morphisms) separate regions which are colored based on the objects they are representing. Since we draw the strands vertically, a single strand results in a left and right region, and the colorings will determine the fusion category which fuses from the left or right with that single strand. In particular, fusion strands necessarily have the same coloring on the left and right, while module strands have a mismatching coloring. + +The simplest non-trivial fusion diagram is a trivalent junction: + +![Nsymbol_coloring]() + +The most general case is the top left figure, where all three regions have a different coloring. The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. However, as will be explained more in detail later, this most general trivalent junction with three colorings will never be needed. In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. This is displayed in the top middle and right. Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. This is shown in the bottom right. + ### Why opposite module categories end up being necessary in MultiTensorKit -something something B-move of module leg \ No newline at end of file +something something B-move of module leg + +One of the common manipulations which can act on a tensor map is the transposition of vector spaces. We will refer to this as the bending of legs. One of the elementary bends is the **right bend**, where one of the tensor legs is bent along the right from the codomain to the domain, or vice versa. At the level of the tensor, a covariant index becomes contravariant, or vice versa. Similarly, a **left bend** can also be performed, bending the leg along the left. This guarantees that legs will not cross, preventing braidings which require extra data known as R-symbols. + +Linear algebra tells us that given a (finite-dimensional) vector space $V$ with a basis denoted $\{|e_i\rangle\}$, one can consider the **dual** vector space $V^*$, whose dual basis $\{\langle e_i^*|\}$ satisfies the property $\langle e_j^* | e_i \rangle = \delta_{ij}$. In the diagrammatic calculus, specifying whether a tensor map leg represents a vector space or its dual is done with an arrow. Following the TensorKit convention, legs with arrows pointing downwards are vector spaces, and arrows pointing upwards state that we are considering its dual. In particular, at the level of fusion trees we can also draw arrows on the strands to denote whether we are considering morphisms between objects or dual objects. + +In principle, choosing to bend e.g. codomain legs to the right and domain legs to left is an arbitrary choice, but would require to distinguish between left and right transposes. However, TensorKit.jl is implemented in a way that does not differentiate the two. In particular, we do not have to worry about this when considering categorical symmetries where, in principle, the left and right dual of an object are not equivalent. This is because this left-right symmetry is guaranteed when considering unitary fusion categories, which is what is done in TensorKit and necessarily in MultiTensorKit. + +For this reason, at the level of the fusion trees the topological move that is performed to bend the legs along the right is called a **B-move**. Graphically, one can show that this bend boils down to a particular F-move. The typical equation found in the literature is the following: +![Bmove_lit]() + +... The reason to only consider B-moves is rooted in the choice of canonical form of fusion trees within TensorKit, where fusions are iterated over from left to right and splittings from right to left. + +Importantly, we identify the dual vector space labeled by a module category with a vector space labeled by the opposite module category. Consequently, +$$\mathcal{M}^* \simeq \mathcal{M}^\text{op}.$$ +In the multifusion setting, this can also be seen graphically. By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: (search that one paper from ethan lake which shows this stuff) + +![Bmove_MF]() + +need to show other changed expressions like A-move, dimension, frobenius-schur indicator, what else outside of TensorKitSectors in terms of fusion tree manipulations? + +no figures up till now with arrows, will this even be necessary? maybe if we show B-moves with M->Mop + +## Examples of multifusion categories +2x2 thing that is isomorphic to ising +generalisation to Tambara-Yamagami + +where to say something about rewriting mpskit to be planar such that braidings with module legs are avoided? + +Without specifying any of the categories, the simplest non-trivial multifusion category is a $2\times 2$ one, and the categories can be organised in a matrix as +$$\mathcal{C} = \begin{pmatrix} \end{pmatrix}$$ \ No newline at end of file From 96962c083d1d67c5ae8a1d7dbfdf84d2b8f7201f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 13 Jun 2025 21:33:04 +0200 Subject: [PATCH 084/206] clean up A4 tests --- test/test_A4.jl | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 81cb8bd..bb3f08c 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -4,14 +4,14 @@ using Test, TestExtras I = A4Object -@testset "Basic type properties" begin +@testset "Basic type properties" verbose = true begin Istr = TensorKitSectors.type_repr(I) @test eval(Meta.parse(sprint(show, I))) == I @test eval(Meta.parse(TensorKitSectors.type_repr(I))) == I end @testset "Fusion Category $i" for i in 1:12 - objects = A4Object.(i, i, MultiTensorKit._get_dual_cache(I)[2][i,i]) + objects = A4Object.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) @testset "Basic properties" begin s = rand(objects, 3) @@ -19,9 +19,9 @@ end @test @constinferred(hash(s[1])) == hash(deepcopy(s[1])) @test isone(@constinferred(one(s[1]))) @constinferred dual(s[1]) - @constinferred dim(s[1]) - @constinferred frobeniusschur(s[1]) - @constinferred Bsymbol(s...) # ill-defined test, doesn't necessarily exist and will error at dictionary keys + @constinferred dim(s[1]) + @constinferred frobeniusschur(s[1]) + @constinferred Bsymbol(s...) @constinferred Fsymbol(s..., s...) end @@ -41,7 +41,7 @@ end end end F = hvcat(length(fs), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-9, rtol=1e-9) # some are simply not unitary? + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) end end end @@ -56,7 +56,7 @@ end b.j == c.i || continue # skip if not compatible for d in objects c.j == d.i || continue # skip if not compatible - @test pentagon_equation(a, b, c, d; atol=1e-9, rtol=1e-9) # ill-defined for same reason + @test pentagon_equation(a, b, c, d; atol=1e-12, rtol=1e-12) end end end @@ -64,13 +64,14 @@ end end @testset "A4 Category ($i, $j) units and duals" for i in 1:12, j in 1:12 - Cij_obs = A4Object.(i, j, MultiTensorKit._get_dual_cache(I)[2][i,j]) + Cij_obs = A4Object.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) s = rand(Cij_obs, 1)[1] @test eval(Meta.parse(sprint(show, s))) == s @test @constinferred(hash(s)) == hash(deepcopy(s)) - @test i == j ? isone(@constinferred(one(s))) : (isone(@constinferred(leftone(s))) && isone(@constinferred(rightone(s)))) + @test i == j ? isone(@constinferred(one(s))) : + (isone(@constinferred(leftone(s))) && isone(@constinferred(rightone(s)))) @constinferred dual(s) - @test dual(s) == A4Object(j, i, MultiTensorKit._get_dual_cache(I)[2][i,j][s.label]) + @test dual(s) == A4Object(j, i, MultiTensorKit._get_dual_cache(I)[2][i, j][s.label]) @test dual(dual(s)) == s end From d5c6b32e59ca028ee782ab672414cd5d47fc9230 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 13 Jun 2025 21:38:48 +0200 Subject: [PATCH 085/206] clean up deps and add compat --- Project.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index b40fb6a..64b911f 100644 --- a/Project.toml +++ b/Project.toml @@ -5,15 +5,11 @@ version = "0.1.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" -BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" -MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502" -MPSKitModels = "ca635005-6f8c-4cd1-b51d-8491250ef2ab" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" -TestExtras = "5ed8adda-3752-4e41-b88a-e8b09835ee3a" TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] @@ -21,6 +17,7 @@ Aqua = "0.8.9" Artifacts = "1.10, 1" JSON3 = "1.14.1" SafeTestsets = "0.1" +TensorKitSectors = "0.1.4" Test = "1.10" TestExtras = "0.3" julia = "1.10" From 564c0266fade2f0b73b41bd22d34884ab91c7e63 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 13 Jun 2025 21:41:24 +0200 Subject: [PATCH 086/206] delete local test files --- test/caching.jl | 60 ----- test/localtests.jl | 549 --------------------------------------------- 2 files changed, 609 deletions(-) delete mode 100644 test/caching.jl delete mode 100644 test/localtests.jl diff --git a/test/caching.jl b/test/caching.jl deleted file mode 100644 index c385c86..0000000 --- a/test/caching.jl +++ /dev/null @@ -1,60 +0,0 @@ -using MultiTensorKit -using TensorKit -using MPSKit, MPSKitModels - -C1 = A4Object(1,1,1) -C0 = A4Object(1,1,4) # unit -M = A4Object(1,2,1) -D0 = A4Object(2,2,12) # unit -D1 = A4Object(2,2,2) # self-dual object - -P = Vect[A4Object](D0 => 1, D1 => 1) -h = TensorMap(ones, ComplexF64, P βŠ— P ← P βŠ— P) - -lattice = InfiniteChain(1) -H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(lattice)); - -D = 4 -V = Vect[A4Object](M => D); -inf_init = InfiniteMPS([P], [V]); - -ψ, envs = find_groundstate(inf_init, H, VUMPS(verbosity=3, tol=1e-12, maxiter=20)); - -# basic TensorKit tests - -# diagonal -obj = A4Object(2,2,1) -obj2 = A4Object(2,2,2) -sp = Vect[A4Object](obj=>1, obj2=>1) -A = TensorMap(ones, ComplexF64, sp βŠ— sp ← sp βŠ— sp) -transpose(A, (2,4,), (1,3,)) - -blocksectors(sp βŠ— sp) -@plansor fullcont[] := A[a b;a b] # 12 fusiontrees - -# π’ž x β„³ -obj = A4Object(1,1,1) -obj2 = A4Object(1,2,1) - -sp = Vect[A4Object](obj=>1) -sp2 = Vect[A4Object](obj2=>1) -TensorMap(rand, ComplexF64, sp βŠ— sp2 ← sp) # should throw ArgumentError -homspace = sp βŠ— sp2 ← sp2 -A = TensorMap(ones, ComplexF64, homspace) -permute(space(A),((1,),(3,2))) -transpose(A, (1,2,), (3,)) == A -transpose(A, (3,1,), (2,)) - -Aop = TensorMap(ones, ComplexF64, conj(sp2) βŠ— sp ← conj(sp2)) -transpose(Aop, (1,2,), (3,)) == Aop -transpose(Aop, (1,), (3,2)) - -@plansor Acont[a] := A[a b;b] # should not have data bc sp isn't the unit - -spfix = Vect[A4Object](one(obj)=>1) -Afix = TensorMap(ones, ComplexF64, spfix βŠ— sp2 ← sp2) -@plansor Acontfix[a] := Afix[a b;b] # should have a fusion tree - -blocksectors(sp βŠ— sp2) -A = TensorMap(ones, ComplexF64, sp βŠ— sp2 ← sp βŠ— sp2) -@plansor fullcont[] := A[a b;a b] # 12 fusiontrees \ No newline at end of file diff --git a/test/localtests.jl b/test/localtests.jl deleted file mode 100644 index f8ba2bb..0000000 --- a/test/localtests.jl +++ /dev/null @@ -1,549 +0,0 @@ -using TensorKitSectors -using MultiTensorKit -using Revise - -testobj = A4Object(1, 1, 1) # fusion cat object -unit = one(testobj) -collect(testobj βŠ— unit) -@assert unit == leftone(testobj) == rightone(testobj) - -testobj2 = A4Object(2, 2, 1) -unit2 = one(testobj2) -collect(testobj2 βŠ— unit2) -@assert unit2 == leftone(testobj2) == rightone(testobj2) - -testmodobj = A4Object(1, 2, 1) -one(testmodobj) -leftone(testmodobj) -rightone(testmodobj) - -Fsymbol(testobj, testobj, A4Object(1, 1, 3), testobj, A4Object(1, 1, 3), A4Object(1, 1, 4)) - -# using Artifacts -# using DelimitedFiles - -# artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.1") -# filename = joinpath(artifact_path, "A4", "Fsymbol_4.txt") -# txt_string = read(filename, String) -# F_arraypart = copy(readdlm(IOBuffer(txt_string))); - -# F_arraypart = MultiTensorKit.convert_Fs(F_arraypart) -# i,j,k,l = (4,12,12,2) # 5,2,8,10 -# a,b,c,d,e,f = (1, 11, 3, 1, 1, 3) #(2,1,1,2,2,3) -# testF = F_arraypart[(i,j,k,l)][(a,b,c,d,e,f)] -# a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), -# (k, l, c), (i, l, d), -# (i, k, e), (j, l, f))) -# result = Array{ComplexF64,4}(undef, -# (Nsymbol(a_ob, b_ob, e_ob), -# Nsymbol(e_ob, c_ob, d_ob), -# Nsymbol(b_ob, c_ob, f_ob), -# Nsymbol(a_ob, f_ob, d_ob))) - -# map!(result, reshape(testF, size(result))) do pair -# return pair[2] -# end - -N = MultiTensorKit._get_Ncache(A4Object); - -duals = MultiTensorKit._get_dual_cache(A4Object)[2] -# checking duals is correct -for i in 1:12, j in 1:12 - for (index, a) in enumerate(duals[i, j]) - aob = A4Object(i, j, index) - bob = A4Object(j, i, a) - leftone(aob) ∈ aob βŠ— bob && rightone(aob) ∈ bob βŠ— aob || @show i, j, aob, bob - end -end - -A = MultiTensorKit._get_Fcache(A4Object) -a, b, c, d, e, f = A4Object(1, 1, 3), A4Object(1, 1, 2), A4Object(1, 1, 2), - A4Object(1, 1, 2), A4Object(1, 1, 2), A4Object(1, 1, 2) -a, b, c, d, e, f = A4Object(1, 1, 1), A4Object(1, 1, 2), A4Object(1, 1, 2), - A4Object(1, 1, 1), A4Object(1, 1, 2), A4Object(1, 1, 4) -coldict = A[a.i, a.j, b.j, c.j] -bla = get(coldict, (a.label, b.label, c.label, d.label, e.label, f.label)) do - return coldict[(a.label, b.label, c.label, d.label, e.label, f.label)] -end - -###### TensorKit stuff ###### -using MultiTensorKit -using TensorKit -using Test - -# π’ž x π’ž example - -obj = A4Object(2, 2, 1) -obj2 = A4Object(2, 2, 2) -sp = Vect[A4Object](obj => 1, obj2 => 1) -A = TensorMap(ones, ComplexF64, sp βŠ— sp ← sp βŠ— sp) -transpose(A, (2, 4), (1, 3)) - -blocksectors(sp βŠ— sp) -@plansor fullcont[] := A[a b; a b] # problem here is that fusiontrees for all 12 units are given - -# π’ž x β„³ example -obj = A4Object(1, 1, 1) -obj2 = A4Object(1, 2, 1) - -sp = Vect[A4Object](obj => 1) -sp2 = Vect[A4Object](obj2 => 1) -@test_throws ArgumentError("invalid fusion channel") TensorMap(rand, ComplexF64, - sp βŠ— sp2 ← sp) -homspace = sp βŠ— sp2 ← sp2 -A = TensorMap(ones, ComplexF64, homspace) -fusiontrees(A) -permute(space(A), ((1,), (3, 2))) -transpose(A, (1, 2), (3,)) == A -transpose(A, (3, 1), (2,)) - -Aop = TensorMap(ones, ComplexF64, conj(sp2) βŠ— sp ← conj(sp2)) -transpose(Aop, (1, 2), (3,)) == Aop -transpose(Aop, (1,), (3, 2)) - -@plansor Acont[a] := A[a b; b] # should not have data bc sp isn't the unit - -spfix = Vect[A4Object](one(obj) => 1) -Afix = TensorMap(ones, ComplexF64, spfix βŠ— sp2 ← sp2) -@plansor Acontfix[a] := Afix[a b; b] # should have a fusion tree - -blocksectors(sp βŠ— sp2) -A = TensorMap(ones, ComplexF64, sp βŠ— sp2 ← sp βŠ— sp2) -@plansor fullcont[] := A[a b; a b] # same 12 fusiontrees problem - -# completely off-diagonal example - -obj = A4Object(5, 4, 1) -obj2 = A4Object(4, 5, 1) -sp = Vect[A4Object](obj => 1) -sp2 = Vect[A4Object](obj2 => 1) -conj(sp) == sp2 - -A = TensorMap(ones, ComplexF64, sp βŠ— sp2 ← sp βŠ— sp2) -Aop = TensorMap(ones, ComplexF64, sp2 βŠ— sp ← sp2 βŠ— sp) - -At = transpose(A, (2, 4), (1, 3)) -Aopt = transpose(Aop, (2, 4), (1, 3)) - -blocksectors(At) == blocksectors(Aop) -blocksectors(Aopt) == blocksectors(A) - -@plansor Acont[] := A[a b; a b] # ignore this error for now -@plansor Acont2[] := A[b a; b a] - -testsp = SU2Space(0 => 1, 1 => 1) -Atest = TensorMap(ones, ComplexF64, testsp βŠ— testsp ← testsp βŠ— testsp) -@plansor Aconttest[] := Atest[a b; a b] - -# π’ž x β„³ ← β„³ x π’Ÿ -c = A4Object(1, 1, 1) -m = A4Object(1, 2, 1) -d = A4Object(2, 2, 1) -W = Vect[A4Object](c => 1) βŠ— Vect[A4Object](m => 1) ← - Vect[A4Object](m => 1) βŠ— Vect[A4Object](d => 1) - -# bram stuff -using TensorKitSectors -for i in 1:12, j in 1:12 - for a in A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i, j]) - F = Fsymbol(a, dual(a), a, a, leftone(a), rightone(a))[1, 1, 1, 1] - isapprox(F, frobeniusschur(a) / dim(a); atol=1e-15) || - @show a, F, frobeniusschur(a) / dim(a) # check real - isreal(frobeniusschur(a)) || isapprox(abs(frobeniusschur(a)), 1.0; atol=1e-15) || - @show a, frobeniusschur(a), abs(frobeniusschur(a)) - end -end - -for i in 1:12, j in 1:12 # 18a - i != j || continue - objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i, j]) - @assert all(dim(m) > 0 for m in objsij) -end - -for i in 1:12, j in 1:12 # 18b - objsii = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i, i]) - objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i, j]) - - Ndict = Dict{Tuple{A4Object,A4Object,A4Object},Int}() - for a in objsii, m in objsij - for n in a βŠ— m - Ndict[(a, m, n)] = Nsymbol(a, m, n) - end - end - - for a in objsii, m in objsij - isapprox(dim(a) * dim(m), sum(Ndict[(a, m, n)] * dim(n) for n in a βŠ— m); - atol=2e-9) || @show a, m - end -end - -for i in 1:12, j in 1:12 # 18c - objsii = A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i, i]) - objsij = A4Object.(i, j, MultiTensorKit._get_dual_cache(A4Object)[2][i, j]) - m_dimsum = sum(dim(m)^2 for m in objsij) - c_dimsum = sum(dim(c)^2 for c in objsii) - isapprox(m_dimsum, c_dimsum; atol=1e-8) || @show i, j, c_dimsum, m_dimsum -end - -(a, b, c, d, e, f) = (A4Object(2, 1, 1), A4Object(1, 2, 1), A4Object(2, 2, 11), - A4Object(2, 2, 11), A4Object(2, 2, 9), A4Object(1, 2, 1)) -Fsymbol(a, b, c, d, e, f) -zeros(ComplexF64, Nsymbol(a, b, e), Nsymbol(e, c, d), Nsymbol(b, c, f), Nsymbol(a, f, d)) == -Fsymbol(a, b, c, d, e, f) - -# testing blocksectors -using BlockTensorKit -W = Vect[A4Object](A4Object(2, 2, 12) => 1) ← - ProductSpace{GradedSpace{A4Object,NTuple{486,Int64}},0}() -W isa TensorMapSpace{GradedSpace{A4Object,NTuple{486,Int64}}} -W isa HomSpace -W isa HomSpace{S} where {S<:SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}}} -W isa TensorMapSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}}} - -# this appears as well (N1=N2=0) -W = ProductSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}},0}() ← - ProductSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}},0}() -typeof(W) -W isa TensorMapSpace{S} where {S<:GradedSpace{A4Object,NTuple{486,Int64}}} -W isa HomSpace{S} where {S<:GradedSpace{A4Object,NTuple{486,Int64}}} -W isa HomSpace -W isa TensorMapSpace - -W isa TensorMapSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}},0,0} -W isa TensorMapSpace{GradedSpace{A4Object,NTuple{486,Int64}},0,0} -TensorMapSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}},0,0} <: -TensorMapSpace{GradedSpace{A4Object,NTuple{486,Int64}},N₁,Nβ‚‚} where {N₁,Nβ‚‚} -W isa TensorSpace{SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}}} - -GradedSpace{A4Object,NTuple{486,Int64}} <: -BlockTensorKit.SumSpace{GradedSpace{A4Object,NTuple{486,Int64}}} - -############ MPSKit wow ############ -using MultiTensorKit -using TensorKit -using MPSKit, MPSKitModels -C1 = A4Object(1, 1, 1) -C0 = A4Object(1, 1, 4) # unit -M = A4Object(1, 2, 1) -D0 = A4Object(2, 2, 12) # unit -D1 = A4Object(2, 2, 2) # self-dual object -collect(D0 βŠ— D1) -collect(D1 βŠ— D1) - -P = Vect[A4Object](D0 => 1, D1 => 1) -h = TensorMap(ones, ComplexF64, P βŠ— P ← P βŠ— P) - -using Profile -Profile.init(; delay=0.1) -lattice = InfiniteChain(1) -t = time() -H = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(lattice)); # 15min, 10.5min -dt = time() - t -println("Time to create Hamiltonian: ", dt, " seconds") - -# testing insertleft/rightunit -sp = SU2Space(0 => 1, 1 => 1) -ht = TensorMap(ones, ComplexF64, P ← P) -htl = TensorMap(ones, ComplexF64, P ← one(P)) -htr = TensorMap(ones, ComplexF64, one(P) ← P) -htnone = TensorMap(ones, ComplexF64, one(P) ← one(P)) -insertrightunit(htr) # adding to empty space -insertleftunit(htr) -insertrightunit(htl) -insertleftunit(htl) # adding to empty space -insertrightunit(htnone) -insertleftunit(htnone) - -D = 4 -V = Vect[A4Object](M => D); -t = time() -inf_init = InfiniteMPS([P], [V]); # 8min, 6.5min -dt = time() - t -println("Time to create InfiniteMPS: ", dt, " seconds") - -# VUMPS -t = time() -ψ, envs = find_groundstate(inf_init, H, VUMPS(; verbosity=3, tol=1e-12, maxiter=20)); # 40 min, 30min -dt = time() - t -println("Time to find groundstate: ", dt, " seconds") -expectation_value(ψ, H, envs) - -using JLD2 -# jldsave("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testH.jld2"; H) -# jldsave("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testinf_init.jld2"; inf_init) -# jldsave("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testgs.jld2"; ψ) -# jldsave("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testenvs.jld2"; envs) - -ψ = jldopen("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testgs.jld2", "r") do file - return read(file, "ψ") -end -H = jldopen("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testH.jld2", "r") do file - return read(file, "H") -end -inf_init = jldopen("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testinf_init.jld2", - "r") do file - return read(file, "inf_init") -end -envs = jldopen("C:/Boris/Unief/PhD/Code/MultiTensorKit/Saves/testenvs.jld2", "r") do file - return read(file, "envs") -end - -entropy(ψ) -entanglement_spectrum(ψ) -transfer_spectrum(ψ; sector=C0) -correlation_length(ψ; sector=C0) -norm(ψ) - -# test correlator - -#IDMRG - -ψ, envs = find_groundstate(inf_init, H, IDMRG(; verbosity=3, tol=1e-8, maxiter=15)); -expectation_value(ψ, H, envs) - -#IDMRG2 -inf_init2 = InfiniteMPS([P, P], [V, V]) -H2 = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(InfiniteChain(2))); -idmrg2alg = IDMRG2(; verbosity=3, tol=1e-8, maxiter=15, trscheme=truncdim(10)) -ψ2, envs2 = find_groundstate(inf_init2, H2, idmrg2alg); -expectation_value(ψ2, H2, envs2) - -#QuasiParticleAnsatz - -momenta = range(0, 2Ο€, 3) -t = time() -excE, excqp = excitations(H, QuasiparticleAnsatz(; ishermitian=true), momenta, ψ, envs; - sector=C0, num=1, parallel=false); # not working for some reason -dt = time() - t -# 15min, 100min -println("Time to create excitations: ", dt, " seconds") - -####################################################### -# debugging QPA for infinite systems -momentum = momenta[begin] -Ο•β‚€ = LeftGaugedQP(rand, ψ, ψ; sector=C0, momentum=momenta[begin]); -E = MPSKit.effective_excitation_renormalization_energy(H, Ο•β‚€, envs, envs) -H_eff = MPSKit.EffectiveExcitationHamiltonian(H, envs, envs, E); # function that acts on QP -alg = QuasiparticleAnsatz(; ishermitian=true) - -# do block with eigsolve effectively doing this -my_operator(Ο•) = H_eff(Ο•; alg.alg_environments...) -Es, Ο•s, convhist = eigsolve(my_operator, Ο•β‚€, 1, :SR, alg.alg) - -# goes back in the eigsolve during KrylovKit.initialise -iter = LanczosIterator(my_operator, Ο•β‚€, alg.alg.orth); -fact = initialize(iter; verbosity=alg.alg.verbosity) - -# goes wrong during apply of KrylovKit.initialise -Axβ‚€ = KrylovKit.apply(iter.operator, iter.xβ‚€) - -# apply(f,x) = f(x) calculates EffectiveExcitationHamiltonian(H, envs, envs, E) of QP -iter.operator(iter.xβ‚€) -MPSKit.EffectiveExcitationHamiltonian(H, envs, envs, E)(Ο•β‚€; alg.alg_environments...) -H_eff(Ο•β‚€; alg.alg_environments...) - -# error occurs when calculating the environment -qp_envs = environments(Ο•β‚€, H, envs, envs; alg.alg_environments...) - -# goes wrong when calculating environments of QP -lBs = PeriodicVector([MPSKit.allocate_GBL(Ο•β‚€, H, Ο•β‚€, i) for i in 1:length(Ο•β‚€)]); -MPSKit.left_excitation_transfer_system(lBs[1], H, Ο•β‚€; solver=MPSKit.Defaults.linearsolver) - -# problem occurs at the linsolve which calls GMRES -found = zerovector(lBs[1]) -H_partial = map(h -> getindex(h, 1:1, 1, 1, 1:1), parent(H)) -T = TransferMatrix(exci.right_gs.AR, H_partial, exci.left_gs.AL) -start = scale!(last(found[1:1] * T), cis(-momenta[begin] * 1)) -if exci.trivial && isidentitylevel(H, i) - # not using braiding tensors here, leads to extra leg - util = similar(exci.left_gs.AL[1], space(parent(H)[1], 1)[1]) - fill_data!(util, one) - @plansor start[-1 -2; -3 -4] -= start[2 1; -3 3] * - util[1] * - r_RL(exci.right_gs)[3; 2] * - l_RL(exci.right_gs)[-1; -4] * - conj(util[-2]) -end -found[1] = add!(start, lBs[1]) - -T = TransferMatrix(exci.right_gs.AR, exci.left_gs.AL) -if exci.trivial - # deal with extra leg - @plansor lRL_util[-1 -2; -3] := l_RL(exci.right_gs)[-1; -3] * conj(util[-2]) - @plansor rRL_util[-1 -2; -3] := r_RL(exci.right_gs)[-1; -3] * util[-2] - T = regularize(T, lRL_util, rRL_util) -end - -found[1], convhist = linsolve(flip(T), found[1], found[1], MPSKit.Defaults.linearsolver, 1, - -cis(-momenta[begin] * 1)) - -############################################################################## -# quick test on complex f symbols and dimensions -testp = Vect[A4Object](one(A4Object(i, i, 1)) => 1 for i in 1:12) -dim(testp) -oneunit(testp) - -# finite stuff -L = 10 -lattice = FiniteChain(L) -P = Vect[A4Object](D0 => 1, D1 => 1) -D = 4 -V = Vect[A4Object](M => D) - -dmrgalg = DMRG(; verbosity=3, tol=1e-8, maxiter=100, - alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false)) -fin_init = FiniteMPS(L, P, V; left=V, right=V) -Hfin = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(lattice)); -open_boundary_conditions(H, L) == Hfin -ψfin, envsfin = find_groundstate(fin_init, Hfin, dmrgalg); -expectation_value(ψfin, Hfin, envsfin) / (L - 1) - -entropy(ψfin, round(Int, L / 2)) -entanglement_spectrum(ψfin, round(Int, L / 2)) -Es, states, convhist = exact_diagonalization(Hfin; sector=D0); -Es / (L - 1) - -dmrg2alg = DMRG2(; verbosity=3, tol=1e-8, maxiter=15, - alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; ishermitian=false), - trscheme=truncdim(10)) -ψfin2, envsfin2 = find_groundstate(fin_init, Hfin, dmrg2alg); -0expectation_value(ψfin2, Hfin, envsfin2) / (L - 1) - -entropy(ψfin2, round(Int, L / 2)) -entanglement_spectrum(ψfin2, round(Int, L / 2)) - -S = left_virtualspace(Hfin, 1) -oneunit(S) -eltype(S) -oneunit(eltype(S)) # should error - -# excitations -qpaalg = QuasiparticleAnsatz(; ishermitian=false, tol=1e-8, maxiter=100) -excEfin, excqpfin = excitations(Hfin, qpaalg, ψfin, envsfin; sector=C0, num=1); -excEfin - -excFIN, excqpFIN = excitations(Hfin, FiniteExcited(; gsalg=dmrg2alg), ψfin; num=1); -excFIN - -# changebonds test -dim(left_virtualspace(ψ, 1)) -ψch, envsch = changebonds(ψ, H, OptimalExpand(; trscheme=truncerr(1e-3)), envs) -dim(left_virtualspace(ψch, 1)) - -# time evolution - -ψt, envst = timestep(ψ, H, 3, 0, - TDVP(; integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=true)), - envs); -et = expectation_value(ψt, H, envst) -e = expectation_value(ψ, H, envs) -isapprox(et, e; atol=1e-12) # hermitian - -tdvpalg = TDVP(; integrator=MPSKit.Defaults.alg_expsolve(; ishermitian=true, krylovdim=10)) -ψt, envst = time_evolve(ψ, H, range(0, 1, 10), tdvpalg, envs) - -timealg = WII(; tol=1e-8, maxiter=100) -make_time_mpo(H, 0.1, timealg) - -# stat-mech stuff -mpo = InfiniteMPO([h]) -ψ, envs = leading_boundary(inf_init, mpo, - VUMPS(; verbosity=3, tol=1e-8, maxiter=15, - alg_eigsolve=MPSKit.Defaults.alg_eigsolve(; - ishermitian=false))); - -# addition, substraction, multiplication - -# finite -Hfin * ψfin - -# infinite -H * ψ # currently doesn't work -MPSKit.DenseMPO(H) * ψ # does work - -# approximate -ψa, _ = approximate(ψ, (mpo, inf_init), IDMRG()); - -mpo2 = InfiniteMPO([h, h]) -inf_init2 = InfiniteMPS([P, P], [V, V]) -H2 = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(InfiniteChain(2))); -ψ2, envs2 = find_groundstate(inf_init2, H2, VUMPS(; verbosity=3, tol=1e-10, maxiter=15)); -ψa, _ = approximate(ψ2, (mpo2, inf_init2), IDMRG2(; trscheme=truncdim(10))); - -# # testing InfiniteMPOHamiltonian and FiniteMPOHamiltonian constructor not relying on MPSKitModels - -sp = Vect[FibonacciAnyon](:I => 1, :Ο„ => 1) -t = TensorMap(ones, ComplexF64, sp ← sp) -InfiniteMPOHamiltonian(PeriodicArray([sp]), i => t for i in 1:1) -H = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(InfiniteChain(1))); - -############################################## -# diagonal case - -D = 4 -V = Vect[A4Object](D0 => D, D1 => D); -inf_init = InfiniteMPS([P], [V]); - -ψ, envs = find_groundstate(inf_init, H, VUMPS(; verbosity=3, tol=1e-10, maxiter=500)); - -# other module categories -# 4,5,7,8,9,10,11,12 gives poorly converged envs, -k = 6 # 6 gives lapackexception(22) -V = Vect[A4Object](A4Object(k, 2, i) => 2 - for i in 1:MultiTensorKit._numlabels(A4Object, k, 2)) -inf_init = InfiniteMPS([P], [V]); -# expectation_value(inf_init, H) - -ψ, envs = find_groundstate(inf_init, H, VUMPS(; verbosity=3, tol=1e-10, maxiter=10)); -expectation_value(ψ, H, envs) - -# checking multiplicity -function obs(i::Int) - return A4Object.(i, i, MultiTensorKit._get_dual_cache(A4Object)[2][i, i]) -end - -for i in 1:12 - !any(Nsymbol(a, b, c) > 1 for a in obs(i), b in obs(i), c in obs(i)) && @show i -end - -# trying to make heisenberg -using MultiTensorKit, TensorKit -using MPSKit, MPSKitModels - -D1 = A4Object(1, 1, 2) # 3-dimensional irrep of A4 -M = A4Object(2, 1, 1) # Vec - -P = Vect[A4Object](D1 => 1) -h_aux1 = TensorMap(ones, ComplexF64, P ← P βŠ— P) -h_aux2 = TensorMap(ones, ComplexF64, P βŠ— P ← P) - -@plansor h[-1 -2; -3 -4] := h_aux2[-1 1; -3] * h_aux1[-2; 1 -4] # different basis -lattice = InfiniteChain(1) -t = time() -H = @mpoham -sum(h{i,j} for (i, j) in nearest_neighbours(lattice)); -dt = time() - t -println("Time to create Hamiltonian: ", dt, " seconds") - -D = 4 -V = Vect[A4Object](M => D) -t = time() -inf_init = InfiniteMPS([P], [V]); -dt = time() - t -println("Time to create InfiniteMPS: ", dt, " seconds") - -# VUMPS -t = time() -ψ, envs = find_groundstate(inf_init, H, VUMPS(; verbosity=3, tol=1e-12, maxiter=200)); -dt = time() - t -println("Time to find groundstate: ", dt, " seconds") -expectation_value(ψ, H, envs) # this gives 0 oopsie - -### caching checks -length(TensorKit.GLOBAL_FUSIONBLOCKSTRUCTURE_CACHE) - -length(TensorKit.treepermutercache) # tensor stuff -length(TensorKit.treetransposercache) -length(TensorKit.treebraidercache) - -length(TensorKit.transposecache) # fusion tree stuff -length(TensorKit.braidcache) From 24e0f4be5cdb42e93d389e00a0b1807f703718df Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 13 Jun 2025 21:43:19 +0200 Subject: [PATCH 087/206] format --- test/test_aqua.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_aqua.jl b/test/test_aqua.jl index 14e5b7c..f57c8ba 100644 --- a/test/test_aqua.jl +++ b/test/test_aqua.jl @@ -3,5 +3,5 @@ using Aqua: Aqua using Test: @testset @testset "Code quality (Aqua.jl)" begin - Aqua.test_all(MultiTensorKit) + Aqua.test_all(MultiTensorKit) end From d16156811b8b956a7554e70603aa592e2083f6cd Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 16 Jun 2025 11:45:16 +0200 Subject: [PATCH 088/206] apply some suggested changes --- src/bimodulesector.jl | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 090eb31..b180672 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -162,15 +162,15 @@ function Base.one(a::BimoduleSector) end function TensorKitSectors.leftone(a::BimoduleSector) - return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) + return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end function TensorKitSectors.rightone(a::BimoduleSector) - return A4Object(a.j, a.j, _get_dual_cache(typeof(a))[1][a.j]) + return typeof(a)(a.j, a.j, _get_dual_cache(typeof(a))[1][a.j]) end function Base.conj(a::BimoduleSector) - return A4Object(a.j, a.i, _get_dual_cache(typeof(a))[2][a.i, a.j][a.label]) + return typeof(a)(a.j, a.i, _get_dual_cache(typeof(a))[2][a.i, a.j][a.label]) end function extract_Fsymbol(::Type{A4Object}) @@ -282,22 +282,18 @@ function Base.oneunit(S::GradedSpace{<:BimoduleSector}) first(sectors(S)).i == first(sectors(S)).j || throw(ArgumentError("sectors of $S are non-diagonal")) sector = one(first(sectors(S))) - return β„‚[A4Object](sector => 1) + return spacetype(S)(sector => 1) end function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) - allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || - throw(ArgumentError("sectors of $S are not all equal")) - first(sectors(S)).i == first(sectors(S)).j || - throw(ArgumentError("sectors of $S are non-diagonal")) - sector = one(first(sectors(S))) - return SumSpace(β„‚[A4Object](sector => 1)) + @assert !isempty(S) "Cannot determine type of empty space" + return SumSpace(oneunit(first(S.spaces))) end # maybe from the homspace function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P)); conj::Bool=false, - dual::Bool=false) where {i,V<:GradedSpace{<:I},N} where {I<:BimoduleSector} + dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} #possible change to rightone of correct space for N = 0 u = N > 0 ? oneunit(P[1]) : error("no unit object in $P") if dual @@ -311,7 +307,7 @@ end function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P) + 1); conj::Bool=false, - dual::Bool=false) where {i,V<:GradedSpace{<:I},N} where {I<:BimoduleSector} + dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} u = N > 0 ? oneunit(P[1]) : error("no unit object in $P") if dual u = TensorKit.dual(u) From 801a774ce76fe191eca080711b7dfced76664ed0 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 16 Jun 2025 14:17:15 +0200 Subject: [PATCH 089/206] TupleTools changes --- Project.toml | 1 + src/MultiTensorKit.jl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 64b911f..52a149a 100644 --- a/Project.toml +++ b/Project.toml @@ -20,6 +20,7 @@ SafeTestsets = "0.1" TensorKitSectors = "0.1.4" Test = "1.10" TestExtras = "0.3" +TupleTools = "1.1" julia = "1.10" [extras] diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index c321bff..8e5edc9 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -8,7 +8,7 @@ using Artifacts using TensorKitSectors using TupleTools -import TupleTools: insertafter +using TupleTools: insertafter using BlockTensorKit import BlockTensorKit: SumSpace From aaeb4c36cc7c197073d97d626c167bc18a4f89fc Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 18 Jun 2025 10:19:45 +0200 Subject: [PATCH 090/206] change `insertleft/rightunit` to evaluate `left/rightoneunit`s --- src/MultiTensorKit.jl | 1 + src/bimodulesector.jl | 47 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 8e5edc9..41a4845 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -1,6 +1,7 @@ module MultiTensorKit export BimoduleSector, A4Object +export leftoneunit, rightoneunit using JSON3 using DelimitedFiles diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index b180672..626196e 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -290,12 +290,45 @@ function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) return SumSpace(oneunit(first(S.spaces))) end -# maybe from the homspace -function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P)); +# oneunit for spaces whose elements all belong to the same sector +function rightoneunit(S::GradedSpace{<:BimoduleSector}) + allequal(a.j for a in sectors(S)) || + throw(ArgumentError("sectors of $S do not have the same rightone")) + + allequal(a.i for a in sectors(S)) || + throw(ArgumentError("sectors of $S are not all equal")) + + sector = rightone(first(sectors(S))) + return spacetype(S)(sector => 1) +end + +function rightoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) + @assert !isempty(S) "Cannot determine type of empty space" + return SumSpace(rightoneunit(first(S.spaces))) +end + +function leftoneunit(S::GradedSpace{<:BimoduleSector}) + allequal(a.i for a in sectors(S)) || + throw(ArgumentError("sectors of $S do not have the same leftone")) + + allequal(a.j for a in sectors(S)) || + throw(ArgumentError("sectors of $S are not all equal")) + + sector = leftone(first(sectors(S))) + return spacetype(S)(sector => 1) +end + +function leftoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) + @assert !isempty(S) "Cannot determine type of empty space" + return SumSpace(leftoneunit(first(S.spaces))) +end + +function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}; conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} - #possible change to rightone of correct space for N = 0 - u = N > 0 ? oneunit(P[1]) : error("no unit object in $P") + i > N && error("cannot insert a sensible right unit onto $P at index $(i+1)") + # possible change to rightone of correct space for N = 0 + u = N > 0 ? rightoneunit(P[i]) : error("no unit object in $P") if dual u = TensorKit.dual(u) end @@ -305,10 +338,12 @@ function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P)) return ProductSpace(TupleTools.insertafter(P.spaces, i, (u,))) end -function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}=Val(length(P) + 1); +# possible TODO: overwrite defaults at level of HomSpace and TensorMap? +function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}; # want no defaults? conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} - u = N > 0 ? oneunit(P[1]) : error("no unit object in $P") + i > N && error("cannot insert a sensible left unit onto $P at index $i") # do we want this to error in the diagonal case? + u = N > 0 ? leftoneunit(P[i]) : error("no unit object in $P") if dual u = TensorKit.dual(u) end From e08a712b2890476bdd8364b16d44cbb65c0f8c79 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 18 Jun 2025 10:20:12 +0200 Subject: [PATCH 091/206] add tests for left and right units --- test/test_A4.jl | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index bb3f08c..2d6afd3 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -1,5 +1,5 @@ using MultiTensorKit -using TensorKitSectors +using TensorKitSectors, TensorKit using Test, TestExtras I = A4Object @@ -75,3 +75,42 @@ end @test dual(s) == A4Object(j, i, MultiTensorKit._get_dual_cache(I)[2][i, j][s.label]) @test dual(dual(s)) == s end + +@testset "A4 Category ($i, $j) left and right units" for i in 1:12, j in 1:12 + Cij_obs = A4Object.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) + + s = rand(Cij_obs, 1)[1] + sp = Vect[A4Object](s => 1) + W = sp ← sp + for T in (Float32, ComplexF64) + t = @constinferred rand(T, W) + + for a in 1:2 + tl = @constinferred insertleftunit(t, Val(a)) + @test numind(tl) == numind(t) + 1 + @test space(tl) == insertleftunit(space(t), a) + @test scalartype(tl) === T + @test t.data === tl.data + @test @constinferred(removeunit(tl, $(a))) == t + + tr = @constinferred insertrightunit(t, Val(a)) + @test numind(tr) == numind(t) + 1 + @test space(tr) == insertrightunit(space(t), a) + @test scalartype(tr) === T + @test t.data === tr.data + @test @constinferred(removeunit(tr, $(a + 1))) == t + end + + @test_throws ErrorException insertleftunit(t) # default should error here + @test insertrightunit(t) isa TensorMap + @test_throws ErrorException insertleftunit(t, numind(t) + 1) # same as default + @test_throws ErrorException insertrightunit(t, numind(t) + 1) # not same as default + + t2 = @constinferred insertrightunit(t; copy=true) + @test t.data !== t2.data + for (c, b) in blocks(t) + @test b == block(t2, c) + end + @test @constinferred(removeunit(t2, $(numind(t2)))) == t + end +end \ No newline at end of file From 213e23e32bb66fa55e5c556567d8f9649e672596 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 18 Jun 2025 10:23:23 +0200 Subject: [PATCH 092/206] one more suggested change --- src/bimodulesector.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 626196e..a51d9d1 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -158,7 +158,7 @@ end function Base.one(a::BimoduleSector) a.i == a.j || error("unit object for module categories is ill-defined") - return A4Object(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) + return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end function TensorKitSectors.leftone(a::BimoduleSector) From 1320c3a940a513f5a256b301633dfdc3c55a08a2 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 19 Jun 2025 18:04:31 +0200 Subject: [PATCH 093/206] more figs and text --- docs/src/man/Implementation.md | 2 ++ docs/src/man/img/Bmove_MF.pdf | Bin 0 -> 58387 bytes docs/src/man/img/Bmove_lit.pdf | Bin 0 -> 64949 bytes docs/src/man/img/qdim_fs_MF.pdf | Bin 0 -> 30636 bytes docs/src/man/multifusioncats.md | 8 +++++++- 5 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 docs/src/man/Implementation.md create mode 100644 docs/src/man/img/Bmove_MF.pdf create mode 100644 docs/src/man/img/Bmove_lit.pdf create mode 100644 docs/src/man/img/qdim_fs_MF.pdf diff --git a/docs/src/man/Implementation.md b/docs/src/man/Implementation.md new file mode 100644 index 0000000..515c20b --- /dev/null +++ b/docs/src/man/Implementation.md @@ -0,0 +1,2 @@ +need to explain the label=1 thing not being the unit +explain the f-symbol and n-symbol storage system \ No newline at end of file diff --git a/docs/src/man/img/Bmove_MF.pdf b/docs/src/man/img/Bmove_MF.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1c8c7c2ab027dbd0f307287bb58e421ed0753ba0 GIT binary patch literal 58387 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 Bmk$5{ literal 0 HcmV?d00001 diff --git a/docs/src/man/img/Bmove_lit.pdf b/docs/src/man/img/Bmove_lit.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a6b6d99703139491d28ad1ca97726e215d5b21c3 GIT binary patch literal 64949 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 literal 0 HcmV?d00001 diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 1886474..c15617c 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -92,10 +92,16 @@ For this reason, at the level of the fusion trees the topological move that is p Importantly, we identify the dual vector space labeled by a module category with a vector space labeled by the opposite module category. Consequently, $$\mathcal{M}^* \simeq \mathcal{M}^\text{op}.$$ -In the multifusion setting, this can also be seen graphically. By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: (search that one paper from ethan lake which shows this stuff) +In the multifusion setting, this can also be seen graphically. By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: ![Bmove_MF]() +where by $\mathbb{1}_a$ we mean the right unit of $a$ (the left unit we would denote $^{}_a \mathbb{1}$). + +Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{a \bar{a} a}_{a}$ needs to be evaluated for these topological data. Graphically, we find that + +![qdim_fs_MF]() + need to show other changed expressions like A-move, dimension, frobenius-schur indicator, what else outside of TensorKitSectors in terms of fusion tree manipulations? no figures up till now with arrows, will this even be necessary? maybe if we show B-moves with M->Mop From 1fc3c261656886341888ff0fe548d7ed7f82cd50 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 20 Jun 2025 11:07:23 +0200 Subject: [PATCH 094/206] add and update images + actually display them --- docs/src/man/fusioncats.md | 2 +- docs/src/man/img/Bmove_lit.pdf | Bin 64949 -> 64945 bytes docs/src/man/img/Fmove.pdf | Bin 46117 -> 45783 bytes docs/src/man/img/Fmove_CM.pdf | Bin 37670 -> 37686 bytes docs/src/man/img/Fmove_CMD.pdf | Bin 37814 -> 37826 bytes docs/src/man/img/Fmove_D.pdf | Bin 0 -> 37888 bytes docs/src/man/img/Fmove_MD.pdf | Bin 37863 -> 37887 bytes docs/src/man/img/homvector.pdf | Bin 0 -> 38810 bytes docs/src/man/multifusioncats.md | 16 ++++++++-------- 9 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 docs/src/man/img/Fmove_D.pdf create mode 100644 docs/src/man/img/homvector.pdf diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 47d31cb..e4b848d 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -26,7 +26,7 @@ This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C} Vectors in these hom-spaces are graphically denoted as living in the trivalent junction -![homvector](img/...) +![homvector](img/homvector.pdf) With the F-symbol, we can perform F-moves: diff --git a/docs/src/man/img/Bmove_lit.pdf b/docs/src/man/img/Bmove_lit.pdf index a6b6d99703139491d28ad1ca97726e215d5b21c3..3b63a5b3227bf52ec215cc51c3a896b926d051d4 100644 GIT binary patch delta 2264 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 J^1n<1`%lAe3>g3b diff --git a/docs/src/man/img/Fmove.pdf b/docs/src/man/img/Fmove.pdf index 6771aa4573004feed007e6cab48e8f008da17d9f..89e6ab5dbea88e3bbd3ec5883a56437dfcf2ca01 100644 GIT binary patch delta 9945 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 diff --git a/docs/src/man/img/Fmove_CM.pdf b/docs/src/man/img/Fmove_CM.pdf index c20ffb229f2d53500685050ca819535655ed7c5b..346dace716b0ac8d6a5cadcc05027dd963f89fea 100644 GIT binary patch delta 1503 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 F#@}AaiKhSn diff --git a/docs/src/man/img/Fmove_CMD.pdf b/docs/src/man/img/Fmove_CMD.pdf index cae10bc1f573da0175677b36cdf5e7a66f813198..4952361a820fadc147605e5bc60020fcae835228 100644 GIT binary patch delta 1530 zcmb`H{X5eM0Kgf|ut$Z|B#ml1dD+W%Z#6sC(l9TrQIwaN5fK*}y4qN6WMO7Ahfb1F zAuqe~L|&5WkW8+a(s{~Gc^#$F%iT}+!~J}p=lT5b`3F9~DM8&zP=N~wjgug4)?om+ zs~;Q%cV)sccr1WzJc`gi0^s2P#np=nKSClR0RRc0u~;GokH#QzNIbye;MqVV4#1#M zSQeSYA+TBaC;}40W=9dDSpUe0j>6+OL>wEB!w{pSFZ6dgpx}1HYwf9-=e+l1t2Wb+ zC4v@I76c4N^i~Ss2~hDeT<>Zylzzyy9%aK$F@?FvQaWkqIwX4gnr zXvP8mS8^exn(SgRy9Nr?d&`B0rQ;AX7>#y8Vu@0?@o^qNgp3RM1e@R;HfKR0Z@ zb-@hgYZ`AK4GLzk+l~aCNxzsx&-y+e{CTGvWPK5f8^0po;P^}_bXi1_i%r^6)u;q_ zTFh37Vb+yVy@c$#O6I%E&jf}=fx$N!u@7!g6^q|cV}>=fTDtrYZ+^oi+1n?8S>S=G zZC;crT@Bef2{BnUBJMkE_^w<|&rJ15tG+oF&nu|KO%39K((Br`+|E0s1$DdFF0w%&g~~`U$NM{~a+y z#`o!T`@#9x)~&KC!+`ZwLmxHz35nvx_>R*$imA}R)`9&!lS3EIe2<=YA%}lc@l>lk zb~s3-$eH`%BzbMxR~Z#RBJnL-+TQ=+$To{d;v$ev8b0T;0YMA6EHT=b*2xTZ1bR+e z|J4O?pl_*zzNwlXLGNsYf_xb{!Z@rD6F7!0dO5IcbyO0NRd?PGiyc27%HlA4%R<74 zknl?J@qWEU_o=Y5!yL6o0Aa|JCy*Omb7G^n2aYOJWhzCW%oq67oqVHrQm9K2r@g;@ zF<4YF%tyzzZRm|d(1qKv9o#tUe(wRQ)RiQPD>Bkzo543w%G$10rg)E$$O@rft@V1a zs>(BYa^d03M@pg-Xw{4>2h%ODOfV&OvOMJrSkT@eZ}a=xD3+B^dFi< zT&FC^sJrT+3Q3zvj}HcDq=v;Z#&FJAb(3LiwYk)&_&nUgzBV0qSiVN>U9!_kD20Am zNlbpcI6kVos`8~Kh40JuBic{eL*A7HrFHk@JWA{_WHn_C-R;rX&Vw5ePfLwQYAE-I zeo2{wX&uIwd`LW`OZ^GgR`kY0T)}gb7-@ZSo36a1I4Iku!*jBmxZh{n(W%doo!th0 zdEi61x#3nu%}-CBA3Z5rIf$J--e}tpe{TVIWsSo4k%yywQAS;No22w9V~?QmN?HD1 zTbFurYWX>+VuR00%zL}FO^|YjPYCDL-F>iLZMFd{b;kscs(yyH3-#fK=MR*JPuQAi z9@cAStkoWvXQ@Aj9wf|cS+#9Wr0)Ov_Cc2}KjcA!ny3@0@@k%s^=Nu68rH!Umse_& znUkGc3Q@2^vtrF0GZuN>6t(o)bjUeZ*Eez2pO;$<=vr={QjYj1!575#f?bV9n>Gf3 zIrM84cX;2z;@pqt`h1AC+iflwNGj68@)e<7)k_a6#xh9rxAq!@%!+cRxeK;xPbatb z(fP*;XCrmw*#cupmrXMR*2JM$KdePi%eB=DBql9w*pJh{ezUsUlT3B%5uIy}hxpc3 zVIuB{`W4RG)RDU#%+0JNY+kxHdGOA3fMuwKzdd94MAHhbF3niP?9lrFl?OK)n_Un< t&`2Z!OT^-(r4o;SqxrRjpilW9E*mDbg6@OTp<*kj9wb4Z`p-&ne*=23r7!>h delta 1533 zcmbu9Z9LNn0LKmOHkL@9pZ;P*v4{U=TQQmG(_|`Q9-?NO#7(ZcM0IP;KL2|ZLW*O z0w`Yq1E3B8AOR18b%*UBp&$#mK{iG*3E7Tx2CN@$+DhdodGAVVG~0_V z5Hw&e!Jtq(MTs2XB81C;+O-6^lX^1LQ431ESRY($3~edS=gac>+5Ed@MPZ2t_fO@e zP_C1m_2)Mr5NdDdVRFfH7#Rw>ID;gd1c1lzKmtG}Yn?iMlEdU`oh_OVqMtA$=ytqk zEJj)Np8S(;OtPix1Fd5>V!1ke0WN)B-ECzdKBa$Fyf4~-MtklFc_zNm3@(T~m6^yj z32imeKD%B0Yc3++g(6_8b<^&Dw2bG0J?)Y3776A4(I@W0ly_#+B@-g(#S1cb-U(Rx zUCk(A{BY%_6M9*+#m}O$=BZ?2DteLab0-3D>GH=7K5+n&b{!O3bRbSi7;gfHHW=zrRCfa>oP~H z#R8p?d&ZnEJ#8FSud;MtSM=9H7yVZob1W-gymYHSb8Yg`@Dj3X-n_%R%VX+S&Fu}@ z_DBav!)Ap^5z;>D97|}lHo5;+1DiPY19sIaSi$c7s zx=j_Mc4UY>J}m;fN0pC4tAr$`pbjEnK7sDgwn#eVJA*}y@7i>bbij`zy~z(Zepgy? zEmu~Aa|?k&`T^s?yeLPl%xRz8CPdjWuww(mR(do>=1<=k&twFd#Qqz79vlT?@bzjdyR3y1BWYwA0`-!(%>hVf+%f`GY)kdcqPr&KSs@}*#x&8%x(Gi#*{jAw6v+7li^-eBgLC9qYw;)2C|`KEFP+j9jpb+Ih&ozs;kg`_xh}tJtXBVdDdyf)1GGv5T%=3AZ_T|`A1(|*UrcTiqe_c z&RvXH}n)su!2OelA6MnWN(>To_klIz(oB#ovw)Y?aTMfql?4u-Q8-{WnZUMI!Adi>W* z)ra$hXIs1oQXzYi{&Bb18a4f0&fJ~wro4M{1D&4*FtiKiTS1bfT;%Z&$QMOK2>bs# jl^pgj)3GAd)a?}M#}PgVp&>#IW&$BfQ0mr_8i~Q*<}0L2 diff --git a/docs/src/man/img/Fmove_D.pdf b/docs/src/man/img/Fmove_D.pdf new file mode 100644 index 0000000000000000000000000000000000000000..11e996980566ad32fe50bf092bf11dc2c5805b19 GIT binary patch literal 37888 zcmc$^W0)mPvo_kc?Otu$Hm7adwr$(CF>TxCwB0>zP1}9u+3()pdH31hkMGYpXVtZ? zTA3M@RS}VK-?1u^OhHtfj)|TPhOFBa1O9f3{T*fIVh1qD{UfXLx5duL0pRC{F|{-K zXFkCH#~&Ehe^W%o)4>$LprK@H_E!y4J98Hc06Q0eLEO^D#nkEV*~ZYtRMgbi-sG>; zzs?GVPPWc~e~chvZ{uof=L}#4Feo^gnphgU*gFB3nE$ES2_^vZ-|t^DNZFZ~ zdi?ER`K$ZC+Gh5DM;HN000t#{dlvxPzkVzKH7J0U@js?>`wu&D{tw$QNQnZpdCeG& zxXg^qOj$TN*%^&FO&D2>S&WU?jZI8gSXo)wnfQ4*SQuH1*jY{4jE&h$xtNXE%uJX$ zOt{z#&CCp0Iamz&b^mdJvx}3dp)HI@ju zU+94O$5;Oq26BeBrp^Esu79~t-oeyP$k@fw-tKP@{HsgB(A-q^KNgRwv#GqRi_PD- zasKPyzunFN=Ks9zUu#gr(8bWk-u&MJgZoekaszSMWuPa4GfyU%SuZvKS=K3=b(zCZRTzQpa z;qPniX6v9=pmHEGda=H~ev+9P6V7AMugnOzr4n?Q#|r@}7nIb|Kx$`32!WWGpAJxZ zF%#-S3jw9UjzG&nZ%3r!0C1I9kb^sn;7LZxZ-@y@GbZ5hu^^!2TAB$Rpr<{Yvb9vm zFC?-P^7{sTewt^}p6sUo`oQQFa!O;1t;a~fdn0_E&L@oBD`Vji1toSxm>{)R$d@7F zqGp(!HPFE@Wz#idkK~&M5tC&dk5mjj_o7R z(fMNK=le9G!cg6gxoLvojDJAz<*U9kRaQ%h+IuFwuwk^HaBl-p~)Z^4PY2)pgcaZZ*bZpU2bJ%g@Op%5t84vry@b9knZ9`cP$jGG#R4$e0*7 z_3(-@;McD$HrzB=hQJ!r125Kt7;+Eh>fr7q_(ZvDMi{*oEasSBTU|I!U--$N<=8RE z$NTQ=r!MeoUDo}MHv2uxrY}&@X?!0-UAn9Al9WSaQ;H_cD12G2$TY>bCq=0KaXz5c z?UXxHiyOTp6~aDNDf%a_>72Q~*361u4i%fq_D~s~qxiajX$fu_Pl<7et+o?#Kr7-H zSCMt;uYGeku_MHCjz~VpW*$j)OCl4EgTpK3Sn%<->=bI z?~4#pC$%WUN()_vF-~Jk3BF5pRKam~ah^i`!U?60qzlo&$yEyICGk(~(QL>cIHVMC zXC(!voWYAuQdrFcs?x8iq_IC78AhZd%+akHs#wd5_J}5U2$fKFC|j0ph~N2jrN@hV z``B}ee!EC7N)DeV#0IHUC74P)(kvs<^o#kvJTszJX#kWDtQ)H69`6hW(a@8Kv@pJT zU5G+QvBMg8LNZ*qiP#WL^oklkW(h|bmDWOFDuTU^8>FZ%Jq~R=FYjM{Mc}jF0KR(9Nv3MA zV*7m@ZLhq&Dkh@#kLUYD)=rlJFMmEIgGC>yJyq$ibD7|D_ zWIO%9`UdqK9i8Amk;;doSjsi|Ne)5GE{w^2fP>jPVS1Roe8Su>uQLT9ayM(!Xylns z*48_bq#23*WHw}8`pQI@q|;~t^qUqa+RVSbDZaE z=jcE$P}A_{XAZoBSKY0DOWUxN z;kW<_MyH#z{_vmE37K)X`BO6;{bKp`nMJ}c@WgI>hW|+#9RG%T|63YX2C)1^z5gU@ zw*SZ^{%;yHFxWFP*rPNC3W}qHa{w}J5@dpN5MlxqVFD!t4Q}G0DLWkwxa~Q0hcnvY^Ur_<*+6o^&dP=L7R?UH=~ zjPT!rYSs!czN`-4E-$c9_Xy0lfQ6FNJ^MY=FK}NN z@;^aA3?FxSi72i`=@t`5pf!EpqS+o|gQ!RG)CDPu+8!Z84D(Rid~-rg(t06_SUKth zF=Cb7-dyTEmQUsQ+@-OQipA`eA82-L=?Y9U)le!aQjgr++JCC9~M0*KRT||Ancv~etY-5UNjFAb+gm^bdS=_W7H@kyV zMM+UqV?<3Vv3_EkQp=Q0Ny9oa?OZde(7AM2#B+yjWyH@Ri+O6v7E_r}bIj2x4H1O# zGqzw*Wm+XXh!rvk!hAu~I}^Yy*9p=sQ9Gm|C$7>@I%+dQD`ZWTTAU#jS6V>kKD%F< zt~o6FOXfu|(^gK$3|yHg8Dn$XoMug2wv38AkA!NYAnh7k>9m9w|4@?(y(#gaRcYmC z3z}kN9=eDs`JWl=GiDadbnGcHK=^ni@lXU@M#+m%s%3#~tYK8FVWN<~f1Mq#;=3*r zM|WmqTmqx#Rc55T3#kedTzdH6Z*Ov8#+Cp@FLJ_wD$$A&{_eu#KgUmwCj1GpTLK(u&TFvcTJyKT z>@L(n3ud2at(O&U+yuBL7DXjEoMvtv(8(?w>IG>fJLr#3IWmGJKYJUEHT}nk&;% zt1>$BvQ57TL-d`I%5da(b>T3>6pp%rDGaR)*I&H1SkdVozs-^fv; zV4#b4u@%YZcVZd`dcG2byA~#LsZ2qxVySSq+A@_@jx6|jDr6GwlP6&w*@`E3{4YnA z!SizsS=A{sPbcQPl{Jp9yE93uzJWw~i$VS;Ff#oEdH)A6#ROntWnuX*oMr~FGyg@c z|3vM7{z?89fO9Z$asIdLG}awlB}I3YJ+{P!k}1FiVLMma9cE}6NMyR7@o0VAwq=HRJLPrLUh>95hkQD`(0-po)vA_x_z}lk&M0z5*ej()n zOJ+2|!Zgk8<^vHhG5}GMkdWPO;ujnMiw*VzI0X?yoC3WJ+`xjjfXSg4;i6z(B%la9 zG0`TK)il=T=H#J{_US?dxoPfTfIbW;F$0*EaibnWg@O8{Ax?vN3;d-~iI2fDI{Ul7 zL1d8RCHecwy^)^8sQ*ttgfL7UzET=PzbMLU>)8hj9&nKq-p%42%--; ze6V>HCXfI|^smY}+?Wv0qVCXc!|OgPv@diB=V=^=2%NzoP#6hM)bB}o{J&;nIw1gj zly}%Ugb?C=K2JhJgmZpUgB~1G*+7JQz6!c7e>*UeANX(P6jBC+M8s62l#l|Qg9p3? z>xTH-8sO|ff5L3K(@8#1N0g!+K z0~LWJDp=s;K5kC2SeDP~*~-2pGX(m@!AJxEf=8?O^$a{Qg8-;@@BY5CK5g2X%AzXU zqM7gVBmcmvDky&-Ed>=k03|gE6$nt&j|k9`5>eoRZ#WaEpiikIfgIO8IjDeX{Z}J| z^P3#s?}&htxsY3sFYF(Lfr<2J{rC2zn^BSx0Zan@-%UIIT_4{jUo?~7RS(~@l1pRT zpB%IInET%YLIjM@0RnI_F1`vGO!FcJVZdLzDzK;eP1TU0{XV>3xW9w~84n9U+}*xc zg$BFX48Ig2h~U88UVkw8uh00+Wbwcuu!(vM`EAn!2^B<)`x|BegLWC(A=$^!`im$` ze|$Lqfak;ler2;LLP-KbLV<<>j5cF8B>@!#W<-Vve)_{=18Bh{3K;2uWIP9eD8Q0l z)aAv12JvT&h{cX?T@xDY#k`Wx_eZwT{piLSnPc>E~s4bO~_ znpg3pJ6)t1=iP#D!|pnyKT&2Nv~(IGK3DE@*ZO+o`^}PXG^!rEVnuqBsFM;8MV?Kz z9+n>Ggu#6r%k&eq04&q~R`Ke67mttoOIY>xHS6&j)bC*L%A^6M`LW1ia$RFjr?j%- zS$mWxW(97#T|y;4tYg0FLeu?>V&0VOeolN{DTlYdCB-IAc1Y2VU%s8}6iyNzxc>%} zUHDfOp$bczDl#!Ps7d}bGRITP(O|ysGtFA3uS#VZWQW9f2=0)nwQ1DxZ7u2j3y=lb zd_sa(F?yqdx6>fCr^J%s`4NJF%A4BzeriDt2P3??Y zbB#mYiyUSdCk)RqO9+_~l{(!KvL3lgf|?a#8Jay!Z(a0z=bD-*BzO)m8%XUPEe*JS2&sslV4FQ+A&D`HoT#sHG?aWGVdi`W zX@|RcP#l^=sw(zZ-*yu0ctR59nx{}_4u#A{*vbu(c&u1aL!N+x*4G)zwovMBS&u2b z+d_2Nw0HEM&Y@bBjkBv~D{5V(7e5{^c%9Y7Es}vk6ebf@kXZlvHO5Zmmf>@b|r6-2(dSbrH}Yl6Nrc$mVr zosW!E=j4VPK$rGI$b+@1s{{+X!o#}us%$#)>lRgi;OwS%4#Sf{MmE3lo~iBh6atgg zlj)ZqUAE&xz5*|o*%J|>-H+=-4 zek&(a#*OX#**5#x)i|S|PB(}#97(^K$Jf2dJiYXmce`p!M%fD}Pc8>H`NgZit#(L~ z0&#l`a=mE?3uXFR36sY}W~c>X@zZm>c_IYDI6S6*J{!}B>depMX+Ag*vTc7>+4AP0FT}sS#H%DEQS5%4J0c2SByT5`6G}Q;Ys{f<&`#^t*g0YA7gn!{ikO>euXeOOBqmK0o-5%e z=XauSN-)dxVd?cYD0+*j3w}S1)CQK)UAIj-#`NoLkTr<2zV`0)bTl)*A3DERx@#41 zEg_)mNL+q}03%;8t3F6O5@DP8w8RQNTsx{gMjdboPQFaVz6^M$DoOqD;6kmm#I-F9F?L!UWFtz`WasraDDLWX zR&(t3&&SPmF&wx4sw65=Pz7L88rhE7c;)eykxPT7Dl2>uvmt(Kl1SkVYdEluGSd_Y zVShFMF$eSahc%x;^mbBh9N#xCM7i0@o;s;)xB2knwwZuN9Ft8+iPLL z`3Xt$VrYL`gD-Ctd|bW5*NPCSMQ|evLGkJbpNLDh;dj5H9W@JIdIQl6EqxjjQ1cea zY*X#DNIJO$8*ehiukK_EQ+8J&5f#zB!LaG>q-;!H(g4j+F`M;hE|Ybrb{l`z4E5{l zD+mlj_)=CcOHj;P^9<8FE$5?Vr=Xo~+NX(|9w&{*i$mN!aeqpF_CZGcL8D&>A&wm5 z5WI`l@sV`i?5WC|;ie28+h>ahC#%ndqN0~N<&p0M8f(NfzjVc!!k_MifTx&;#4vBIZECED8;b0AeP8ZM7}9l9wY>{x{BKZ8j5DNSkHL>c zfvTZ&H1pcK4Ppm7P5%A*FWzQNZC75DZGzn$stZwlL#fJDt}a4DRy~0vdlx4gCiNLZ(`eyK{o3F69OQV`r`WYciwAi4SY;*}0SlY$q{0(e%8j zE)##Sd|fOayk|Kw-6r79PZ;ozR?u8qwJuik9_zR{8u+MGSORP1-A({GVQ)ESs9V@R zCdfwepp6+bPbX32PqsqfFD|)GFPmG4n1{L4Dd|pxuX291GVP7MHI8Hp>b{nkn!-&C zXty|SCPXW~a-@NAKfL_I@uRh_pGHG|h3bk$4Jor@-2(akX`JP*!ti4`g;X<5>4*%l zk3F)PQ!nIC7|Sg%mCK?U*-xzJ=`Jg@!ryHa-(Jh-LozPa6z^6!W?|1plEhAr(N64} zA=)AH8zP#}?{WXeXBSp8#$y`_T8U0NN{F3_tMs!udA8;Mrc{?L=0oF<96GuvDhaMTl0{*FoA! z`*;BkWZKu9G^}PZ6Ve4R0G!!hCSQgtk#`;S#7qymyt{ovjTHD=oN*n;Yt?-*}a* zaj=bKs-fG5OD9{1>qg}Df}8OUTynp8h<<0PC2%6U+Xd&uED=2QyuUhSaRwGJ_K83U z$_x%<-F3bqaUIz;po_1*jS7b#e=E_~Jn{DFN%3grf1!Id*qg(z{&o|pmwTcO=czHY z=PURk`dp6XS(Q8oe}zCZwgZ_)!Cn4zIbnehvmwTopB$&=bct<=&Rxd{M?&{L>i+zfqG;$kd>`q<>f)Z7zM6 zlSth(l;%W68_Oh!Wo`U4R@Sk~IY>N@^T8%coMHQ!NVT1P?DZ*Lgo|_bo64BtkG?ZFHuswpWc-F{me7hmFxjkTV zB14h8UO#JrS1NKvWln8&y4P8igQwX%d-xXu6Z+M(&I5wf&v(y|dd}14;$Nw!4bBjj z?K;3Q`4s(@iC(KCTKLgu)`TcKIgjEd`M&10q01+l1fqL^ZTl{nsP*@CPBvh1X#+j| z#WDv!Q(M|*M9IaTpIPF>7r`}R$8r{1v+GzpZJev?VGY+>E_)fK8wDmO>aN$Z@Ui?g zQ!`DRhJu>Ma$b98F5BKA?u!Y`Kd48*SZ%s$4g-!(MapmmdR41ZqCC{9aZ-F6GFv#_ zhz9FbN5)Qih&P%gw&l)e9#_JB#~0b(_BDUSB9EHFqFp^p^2wiPl>a<)AUGdH_0tCS zVwSh&Ia9~q7MoG^GjR8g)!t0TwAV)rv)p&s;?KtVR9apCCEB9-s4*}r9TjyWHOa}m zcnZ`1x03fx2D9$0;&&O-1GSKB==l!r7hOMcOIA>rO9g&1VH9*2q@gkrc8=@covi?~ zXlz>05FJSKWy!i7d&;tzoCEv|=qI7496*=A)4q=;0AyqB<#+T`h?3SEges_FndWgU z63$$#JPxu9$EteX5{znR=+hZ*jUHGu&s4m9^L+hug%=j#PdIqy(OMBuae;DlTg~&z*&q6rzRV zmrlhday|MvQE*nmZoikMI=TKcbMB}j_UD;M0}M@Tf)w65B*h5n@TT#$c~5B4`k?bJ zH*=?V1$=XLA@z@u1`prxU_7+Ox~}SBcqLLYdoo;mX3g4e{7(DJsTi9zg+cp*RRMes z!UgO+7%+DJ=e~UNibf_*w;m*=4!10ShIsT{$W%M0&;9{!C&j6?z!BCZO&jelWgja0 zAa5+Mxs2&TANDP}_;1w_-or&+@KWn}rKV+CqXseU-Gu&VYW~=}x_hL+7s=Dv(F2wT zZ0|)5yiZ)n5NG%2GKx@k1i!sQ0(yi7DrL^o*G@h8l13@jVN;ewgVH9cZl!~lLarv9z%j#@VcU@z)-&MLV%kyPFI*twQ=KLC zWndaIUlDx~JD}OzR2h}AXceEes=J->OJ1)`{yeJ0${O$QcW3NCL z4E0W*Cq1HOYP^e#_G(c{wao{vuKH~@sB9AGvU96b`>PGfBtWL*ygmn1Jkbso1d#QZqOe=m$aK@`I@};Afs!iN(}kC-`p*sQ^ndF zq97?q*-nqK@VqWkScW*83F{uIin%}2e6_7|Hr^y>&NG0#**f@ZUXz7Rj5=z7Hme_g zuw+@Z@c1mzvuo|^=Byn|TtF~|U*Ua>03$Y$u7{(=#)4Csa`9`NJGp86UcxB#RfrE) zQGs5YM%7VKQy;U!$h709Lx^|&vVe}ms=Ba9rZW>Ae;6^_C~_~ZdaBpf<@7a;Ygcp$ zaW)|egF#+of)jS+If>qBFqQe(KlT~hal z*+FBFCtqYdMG#-okQRk4T|tw=+s~XnLjYx>P0=(FIV;~ghLBy~_IT~j@QPgV^lCO^ zg|^fx{GUe7k%CT-2bh)eOuYQPe6D^Hd_pK4?&45Ux9^lE5>k}Ou9h3D(XW!U`<>W# z#>i8Q1(*5g6TgeRMO(pL?Os zKIKGO3TB`S=MAHreybIzTovcjBiKZ&%2f^Ev|L)~{+63jd<&7ZPp5PIC`ISax8@(S z0#f*Y6qcv7Fy>r4u3sT0h2slrpY%F(>Rn`SoKq=Eb~bhNFk7MO8#$t4ix_SQ55qj;6V4a;8Tg$nl!^9W0;S9s4(%YkoqYD`qnH(V`5R2$1 zjS$y7PtOm(o(zdZ!qYK`L5H@A1dK#iM$H=_eCIy5LN5yK$s{tN!MGo z)#hcFeDE@$wf=M|XIYaZt8cv!P46f}?yGg4oQ-LUe}_;MmarZL8_@f4G`1h!HPTU_Do_lPAp*4%;C)5SvNg~%gA=qp?L!1-dd7=%^ zt>r+Ea(C9Bqer<(CnoDwQL~XDwC%-V@MvhH4zo%f*AV^0@ei2xV!vEXvTAl?b|Y^C zwR9A`og&~Q?K-kl3AwDTF%tif=O7O^JkmXd{4mt-IA#j*vNgA^%IX|1y5|+j*`;Gq z@ZEW#ftxMd^DMO4IGF30n>qN5m57fw(BDeGZ?1UTy5)J%guha0eo4Q}w8ux523=9_ zSFK9i-@Cm!VLruYGlxx<)vMosQQLPc%cXofMvg!ODGQ(x&(0H-A`O_$R#CfEh0|f$vOqv2w zg^`@y;-SE*EeLx4&w=?5%2uKV075Awx8t{DkSTO8#+K?i7)z&OA_KNGzZHC{n?cVP zEdtx%!L&Yq zMDEnY!y<^)z^1|_*uH|7r}Eu;w+40Vo|Px=x+Pz=ylw-V-rNf_x%_ zj&8Lgu}t=$Q%Lpd`y(hs-?I;7`FiM?E}{C7oqe6hy$YE#R+U@}s16bYSA8KB8^BWFSo9F*R#OV)~kwxx5RVuf|T`isY4y11;pHER+7qY z=U4RCy)UITh%HsGk<1Yj25idBq_<2twaLQ+O(W~eh-js3G_I*k<$}lU$n9r*+$vjY zIi{sLiCbtfG)Vzz9SYm2-Anm=TGVrC35`q5-D~9uL~U3T1}Gr2xU34AnN2zs+^ftU z-i!&THgW22;(;hrGwP0%iVa2i2=sM=W5_DUPS{TD`BY!q8U1>NW+soQ$TUt*+*5aB z7A3wF$y&9kt4~wdQBWxu$$7r<6X(_B4U_}Q1c7J3tY9629g{iVMu7X4ZnMCPnO9{^ zC%SOheR_yl62qVOdai9Vr)gOAl#X|!WZQEnsW|LAk@juk=Q(J0FkHw8W%E#exJ_+P zbK^_9BJ?Ns3O>+&8gt-0ihQdc2Ji{0 zyHV&1c1PfDDSd4|Xbv2Qp&8Y%RCY}QiPWDC1d11G$*6pPco%@kcGn+f54E+m9_PY+ zq`Xw<#z$@iehQyIt6o5%g^N!@u3DuZDqcmh5|pmt`TD|?%-U@XhT0Wd^;QYxLu$xk zM*b=N7ANZr z;2U*ZNjOASjxqt_th3k6A`Qdr@kr5XoiPbcp9rjePj1PrDY$-NA0k>C1vXPkJp6H2 z8ugXKaHTih7TM1w@T762UPP;djVR|6#nA!ocMdZE1QJ#{)$g$_z3&Ht{uO0AA~XCY=*PdrCz5(m}=XF z5^%YFvT34QbTyuNwK_;>d+jp+V{U(ki_JN@T#IFGmNmyS6@<(1lMq;O3;KUkj{Ik% z-TzrRl7;Kv%aKgXf46P^Ye&U@D@QVNu>U{Gk&r6M7me(TAq7fe+=_v+6oo%-dL$u% ziJ*anrG!xe=S$pEcCwYkO5BkZssbp*&`P8eiwYiQV@>m&pI*OPu5~qOJk5_YpJrKh z-v)g@TO$)1L1AE41&JJm4Ga_D6jb%~ap6FM1dRp(36ufZn`nW~!QZuz4%tIY8elL~ z_k>WYaCku^r^^6N5Cy_eu=6cv(4dh311apEDR59=XyAc%pYWoFCIMDR@*$uK`dAgg z!h;P!cB*JN@j{$jhftnh{2-o&K7zNk+DbuvTY;0;4sak4LLiSsoaXI3L?mzr5UfH2 zNDg>kghU>{a~wIFV`GH8|`m;z_aKGci0DquLQ0I~NAs}(APN5IG9fJg+7WXNT4#LEcKZx>> zLU6&Pfj+45L6#NRL4=|3zs?Y0hXC`OHH;YhPfZeu`G!!dHE}KqVjW#WiJY{1=Dt=? zaCqYF?%m`0`<=v!dXl?+WD;PD1AokM5uWFX%_Kv{_}W`H2;u&|MQfXdjsukrC@CE- zAq#Lo1Z?3R)84TJQW3y^n}U6-pnBatixtlcN(kdR_=k|>+=AYY2=nd>;vExg?LG^@ zf2RN$FwO%54*?fCP=KM_-kgH5ZT)GJ$q<0phi`^JK81t`^7H$0Z6sry1`c%@`o{gT z9wzom%W_wN1OICNU?`4)nZ!M%Ati@FLrDb!9soF67NG6#ea~^W5k&~NeuUSvFCv3~ zU|*W|ghan}nav51?tL~9`Sklkum~boz(U@AWuLJFppjy3!M_CVKhvkag{b*P*l_ zoXL2_e}dV4u?zhSNgevcIg-bg)2Q-aDU1s##PhSuuLvPU3K|f+1sc4CP6C_9l+jRz zY=35O0~HHNq{JHlmpol3JdGFx@2wcoV-W^qmmkrnJmMuX!DYZ z6+a~kL2jFTYuV5Lmy4gw-GL$HuY^TtYc`9E3hJ2^W0Nk^ug4~)I_wSePSS><2lXBE z=Wrs}26jbDh)fQb-x~l)KBFK&OB&R?~3k-iF+(d@qVl_!k%df#a(bK?*mw+X2wP0rnpO_egQ6MX~4 zLW+jmZ5=gH&(KY*K4;B;=e`FD>QYGQ`G;z?po3EWa<#M1|feJ2s#wYFcQ`rbD-IFeT zw`9d?7>PW-L<-4f7!@S8bg@}ItY}vlcc$m&Pd3SKGa5`2uQ9HCunu+>wLg!yAkOjS+E{MYsmRyY*q6%EoYDg^GxAs0pWxCfAk{_)Q8e5_|iv!tY_F!e{k9J&; zwymC`*gU>$RDKw$&-g#{jFjhu*j1;{)b5^F4bZz&3+G7JC$t3@+Rm(Vn<5Fkv!Ar1 zoci{r>!}fCGg=cQ{J49@`9Vze5r`VVzn!^W!gR@mxbExE{g637o^|-53pn!FLYSX9 zC%-oC?d%C+-N~~yZ;KA5QC+!1eSaw>FVO&m;M&9A@tw|$D?xL3GDf3&zuy*G_wH?L zSQs6<=Led>K>ZTTXwQXt9mL_o-d=W`n@9FgHt#>`AB39Q9oQCI%T(iH?r3?w@wavg9}uBb=%fb(xXVQ;S=1z5lEP zgoj2$KAwcv$y z2_L1_bx1vd@3hL{XJz*G!M?lT3r&oGzi(-~=YC~8gl6?(*|?G-et*z?XWFOijC0GI zNI(|sGM}sn`~TTm_!9rD2{Jbhc`Y#zzIm%AH7BHXS= z8LYN$D=3f~nw(yKMp4*r*w^*bY&}H0eOOQmyP~s+4(92wHNZ$9TOb#Tc#-?CNrn@S z=KE0%Yq;+K-dIH6_EF7slr!2$Rs)Tb+eGwEuo%k@m=H)t#NBu-1h|eSfVQ z%jcmKX@11pMOXm)<#aVxc;1-a2P>r#@j5ai68MIbs#MG+m-D8=t#nRP~C1?_Xs%MDS#~wddskuHJEXox<=@EX$=dO=z%t~RQ1+` z75s#1BT=SnV_qJf0;nr-pZ*+&ht zxGmRQxd048+))dL-n?x|qx!vGDpZv@eNjWn!PIM-rQYtuRpTKRD)GqV@$4FADnc;A z>~*H|Z8e#So2x#v0<8v{qP}N>hS#sV65&bojl8z^#2@Ktei48C9Xc!*GK*Wudr*d2 z*v{Khy?Yc%yjuMkJI`WFU6mN5R<8N`2Pjn~va1WpT9&HfpGi=QyBfw|KK%mY*p!U| z4msf`=mwU{lUnlY*8}5W#6i0QROVLme`Z1@Q3VlFhbbu7#?!>R&K+!f1Y-M6`?4cSpJjVu&k<8eQH`pgGA>P zhl|F}A6i~-Au2A;CHzZwdcw!KUvYD90BPwQ&ADd@8M-^PE?<6c{7HDjy>9|yYeX0m zJ^UA=^D9g~bi)L~l4EYbis?mG>s!;a(NlTetGNX!`S4{@Z-b%s_tH!Q6?V{BdiH!R99NTP3-HhKUGP!syV%M=k4C+wJWn1B(N%xSAP|Y~ zt;xrl1c=HGCU+17B1iPDb1Y(EUwuepG7Bq+_t(_g{D?)B{5D=(pC_dyEfeOVmrKJl zV3^NaI*{v#Q<BkPFS0+_TB5;{`n*ecTu#;SLp`5#pf85w)Xzdt}P(aov=~RAay#1K2$;kee zO!{?v=oUPA=d)-Mr1QP8c%?zl8adU}AD5?EFQ=0MROAAos92%Qp0?@14B=y_w#;{n z-(~bG=@8}k8_VDxro6P%&9Uh_fkXtXfV~gQXGi`lI>4PyXA(e_?yWMh(fahXe3Saq z9;b$S@CxXm0Fcxc;&|6fE!NpTirY%w8p$JTZb1*2L&TAUcEwNk(ku#7%i%%Zy==)8 zW@>cWs`-OLJQWK&e0AmZslp~ge!Fsx*+o=%@>K`yH6*Ryo7&gOTR^qz`doQG#>T%o zSz`uP%Id)%hs>-8fYhGoD^`{7z}TPm}KTAR9z{{?;q$FHVyR zd9M8AF!w<<|HM~NIyN%+p&gZv?E>?m8+hfa?Xun8p{b^;l%2;!g?M~%Yu?eOA`doFI1NDo^#QB=q^1HF znqx2SNpUF#XrnAM>zLv<>8mBZS4`ONDPNX#2ck#Aw9=oX%g)NDCueSvBa@>~$(ThG zwlMO2=U(0st{5{ttwX6l1*WuO{ZBY-{si)%s4!CY)#MeZtS8ZSQ+c@~C~K1@k4@E; zDj?`*cJp!S@{ntHd^bD~6)X6=M_;NI58wG^1{o3>&0}*rF53 zP3g`@*dUg&%c%H2vd-9&n2oNBFA;bdA`TMiW~`5o@HG8$UzLgJT_kC;vvGGe)K0w| zU2>j#$|%!KXVEI+9C_$2t^_uHS{OBj-dC!T$+l&vu1T{HTZ_gKYkTU%!2;brz+Sj2 z`pms>hzgRo7UsMSjwhxi?txb5xJ@akR9-bsB-_=z`?YVPvZBE6dpg9yM+&PSUBcF3 zSv)UNTfgd!^XNYwQ-((*ukSb@1G1_~R+mn8+!~-%Bp^>6sw-~`rJ+)c*F#0;efCvc z+j(zGOXa<@-9qh2@#`iY^*pEy9Z`Kn;6*1Twy8)et|RXlP}u7bNwom4en z(vq9cLQcSEhFZk8g4jRW`uQM!$CbQ}_Dg&sWV@K(9PaV@5lLFkqvLY2KeZn@+HPMd zJivE`CBf_M1Bpy=KL*94p^$PGR}tM-@7R&b@MqDZpusOP2CnZ5J$1V=dz#ad9T-vqLpiiL0J^rH>Vyw@j=6o-QUmU*7Z@G>1 zo9G9ou!QoN9fXRQ5T@I3-PEq~F1wbjT=AZ+dUA5DYvuX5J#SX-ydF2&2=h+?y9_?H zI%k+w882glMO^p`WPBdW*MLG)gnYdOull#Wx+>`}pJ{3I;15=Ezcqf>Xrj%TL+tvB zD;MuD;2bsycQS01sV~(A6EJwW?QbDh4tn1Um?2fI_f25(lbpNGrIV=h@TtxkO-$wyDo}Fu-f!xY>0V=cILuMh52ZT0smQ`YDRO_< zD>YYGGS&Z<4S0(%d<165#&(UOrwie*g+QP1NML??;5u|IznEn;`CT)6zZ04Z=JICC zXPZ-sS6sTwgg(%mkKwFlN9``Os^txP9*4O-*|F{8CYYH3beT@tvRMUj(8&(Jq&*dN z&f$+mBJrebS2NSKlQX+1rNTTRaJN)=z_Yv1NMuT8ev2tX@P}1dCHW8*Pjb7NZkn5J zOVaa;ui@ihIDckezDT$WPWY`3{ zedvile|Ae6UE5*R`AbxN}&EB|`;Ik7B}d7!{^(7L@y#~pK* zl1^b6vwTeO0hC0)RL{75T_5zBM{YMz&F^@;pfhACI)R`LqV!SXtp{J%n&oIO`_ZFK zv^X)SScYwygg)W9j>_tcJUX-cqhZaiL;H(2@>m5>>ok13qSW5_4Ok+UbiQWjdi-lFgL|QDbOXfBQ+IdaZaJ1=Wt7;FH`(Cot8@keTekp|FxuEiBKG_doCxGNi+TsThW<5IA1H*REwm6>F(-epeu$ykhpx8IchQrB+Z=k7CI z<;+i5m5~o;aXyz@S!tsiK0kn8OY7j$S*?d8&7rcP$UF)r~~T=qGd+&uSi^dSA!Cf-x`V7BnbN6ejHyM~(3 znj}g@9q!ReyQbRH|M0}zt3oiB35{$;^S$yF(UmV@im0Ui!t#<< zxDyJ_aHtb7w!IstFQAHm95e%YT zNJu2+o+FG}5bYAn&X(FMio>!JJ^efbK4O`v&75E|retevFDYJT47CN_T5RZk@bbn% zFFwf7wF)Ss?P$&P)VPtIO`8m?aY+GcgO905mllt-K^ey|d&g<4Nj@Lm$S7Ml8GXfw zwC?WtU%370a+VoT9&aV9i$4xx$72IM1y*B}^f+14p_XE1m)K>i$~s8ncDBwSw*5@%~^vg!Ob22q~%HgLD;*9Z}ho4)^$ z&Wu;I8KyoT9rSu6fhkL0Z6_sU&Kp2{u1l+s@`Q$v_w^j$8pD4sPC4fWn%_X?Vi436 z^59XJM<$Y*i`t^_8CZqi4IYQscj{iatat(WBtx3!N=tyMmoMs1Cw?YXuhOlY0EzsO zI9JE@YR={$`@a}F$L36+w#&x0ZQHipvDvZh+_BTKZFFqgwr$(a^iwq-o|<`UYW~Bi zbLw1suXQ1U#Wu+sIEfEt!|ydvkZ>e0SQHl^PfeU0Go9$_P;ln_YKUdyDK*V7n8U)T zcG|j(Drv2zP?13sl|>t#lJtoO?r)4MzR7l3U-2GLV7!uwze)zh|B06ys`vP=f(kcb(6M-rMc$s*8bV1MFYtn;q3&XZ`*~|oi5(x&O_*H$1 zdvY~1+@xSh0Z>Y9H=t{Ii;GIDCz)_B4@0}w8_7X;^CboqcYo>u^Sk*?M}h?~2otG< zJZ$3ZTyx-RIw{O}`WLeFIkjTkM8R`5IIvLJvToVh%aE+@w`HI{eAfoZkhP#+g%W)w zC6}{Mllg}DuI!PoTq@Ql2ta@JNM-+UxEl)eVZ8zh8>40e)8g>_Yd|Mx!KB;aPyo+{ zSAPf9IkVOy(Y(uXkbKdNh+|CA(DNFw?}f7ISOvF7Q@C}1e8dj>ZLg1Y7+i`G@~(|* z0{DPvXeaXL?-K;!qd@zmr_uke;Z!yxKSoLNgs(xhamof;PSA}LF`U{(Rjd!_vS;_V zSuvP<3TZNusN73#vSKYU$NTqwz3G4DrauT))`9!7w^D?)3*A}poLKGBP8WLo1^RBf zVdhw`{Cy={iksxW$MV+8yKsW++znpL*$&@dRO$KgoUq%?R~>+_@m|^569=*0qk}P= z2??Kts|ChpSuT)XmQ)!ftky`+SN4t}hKzRi&X093*pu6H@IQot|G}*P|3X3be*pRa zjsaPSxS0MU&G^4VL2jmhc=vzXQlee{F^bkJ9Mt(qY;Y`WQd6^ATlkT^OmIwtilR}$ zMASr7(ZMdI!BXzBsY$^}MJ_&NCtuUtH$OE`Ki11$$7?Iy&%V#wFHQCoJoI`Bma>wt zX@R65W6;MS5kRI(OUd8?L`aO7P=i4egGG>%>jU3`j_GiQ4Al;j!J~pu^$bi<_XvqW zL^mGiF;IDtnfyqTuwby^{@~(5L_~;CWS@iug;7w72>S>vVCBxhYIw*@8oCr(l9Y^? ztxfRv*Q`ID;PoPF{)R?I!ZAC0LY9zeuy`=SKug3@xM>4hnE6QFdDWz72%=tJwBQwK z@F-_w{Zm(adwt-J4o6Ndbt#4iKwiD^976bMw39>lX3(EYOp2iUKpzX(m<*_jGZ5GB zkSnf@B3?qehP}MK1PCF-x;G@7NGVL1yIUgx?c-KL@|0Nnh+0>O0idrdHvWbTw?8Ex zwC@@uT>I`!U@)#O4uM3SyHM77=$ix(i>itTB3>li{z$<`j3k5GOLq(e`v?IWqIB0# zJ+xs!=tWHdaUBppRx{}5AnqdVPHp{Heodoav{PG2N60DlF$f4uVDsoN8UQB;Osq${ zOZ`nhg=K`j(}3HziP}I?x+-6GqqF0|s#t&Cj=rR$?}AO?RzKrqCbBp}GO|(HLC|1s zP@^10+-rlgr_L7S#LG$4-m6`+dEO*sAxJ{12de zlcgSK-V5T=kLTMU_s^d~%GoefxWmIeNZ>w0VJ5}f>!Ft&twy5To^qfs{PI7wPGEt; ze&t=b3w|_iKe9lTe)N#Iw>x8OcsHuBp!MJMPN+zNP+l)UKYp@b?xR2Qdp-4^J!0QG z;MA>a8$WIh-_JjUcHy9#+ZT-e*%n)I?yz~+9xV{zKP5Q*-*i$c#WQTUh zMaawUzmLHl90OjzcO5jqTPY`%VPk^VKjS9}b$?dM*9MT8=p{8?YdVe?V8GrPceZ?m zudc5VS9tZl9ffsoQsCb{u>96)J6zx0@$aF^3Xf{K4)!pCM09nD^jqB}{mkz`0ln_9 zR?rWhRW?MNnEl9}m>``OYnT>Cr-2_AX*Xcw@OAF>0iS_CM0`Sauvqu@{svg1fR-JE zpS)Y(HhQDypI!gAfK8^-jwV+z{~rj?fX(GNKk&e7k6XVq5Fxt_zqCLhyAHoJ5h1&e zo+;ky7r*oO6}UV*1_pQ0clxak;IENy0CJyU4inY&WD%(<+h{XO*#(I#mtrVOy z?5g?1U!0imaz^IS#has-d|!q?Y|$Vau?eTwg->KGN5{PLZ@`pae@-x#j}5U8N-Up7Otc zCZ7_dytSBrr1$Q+zyU2;e5VDXPz++lq@e)p4-NkefcGswHiV?^56Z@ZQgiEPT2qq3 zfGu24T)jZp)5?V%q1eW!Z3}FTa&ZrY+5!|3S8;|lqD$3RSveO>ng(}C*HxhqV(SW) z-gpP&)AyXhbG|Yul%m;=QZVA80dV+*K2a~p$QYMOs z+4WrCPBA;{e@XPZ8CXF(-$!@_y=>%*Wwn) zyv!w~{oO^hd6vInh3sjwzh67elBcQhv zoYr>z`2co9B_ZK~(*xUxaS~VaYP(eiU_PV}!>s=P+LcGqIA-1;R50Y~!z0M6*J`!r z!X=z}M6aULYy_jVI zO^A*{4Hl&F{+IRX!?F0F>r7`03 ziWhE3zM+7_uzAQVzle?;0u#15n*6=@0rLhQbM6!;qSd4j(Ft3tYh@Unsc)SnJ2Ras zh}F%m;6!>7#n=X6gFWf{1z$0PqZJlixfVe99#Xe5SF=h7*L9{>lY7)=W1+;Io<6v z#C5;y^=C3^kVqv9xK#M4lXE!ODxKX5Q&Y{+#IL}$#TB22&6JKPWKsjU&d|s~J zj;?Y1dHpVt#ASTL%%jyx+mDgHYA=Jk57jO)wS*kf81K@=g>61UO?Q>$`x?X7Bre`_ z(zSa733+bNXMIkBRDmvXvA~Th61tA+NltcSXy@A6fODhtkUR>r3t`!Hc4-fNHJM?9 z{3PCz-KGyfjpC^ zx%YtiqZWqa?yYLsuv+UqJ16Q%?2Es6k}ULR`8(S2cVcWb{NG=Y2Mlvd_tUc#(U9Ic zry0A&D0SBw(KX?& zsiPe)08QJlHdWU@q<$O*@hq)f?|0SRR~s9fV8PR~gNGZl2<)qpGgrqE(T}*7d2%A6 z+UGNTIJPe*7kHy~0Rps)(Vn`^5Lsw0I^&i11bNwJ(GB}2$wv=5x8PCtY_BW?K%>;_ z;SO`A(%EBD@*|T<6io2t{8L;fpv)MkS#mt)&UOZpdSJ1aI?#`Dt4l^mf5tRAIdpTj zBqpqZ5IwK)NT-pdAx|Z?2yF(!$tLnyoQEc`BLs1uXQ`jx*!T*la8kkJeX?@w+0}BL zm74xiku$+lKs&7EK+yIv!_>U6l3!N&G3`uxB%NG`K*S3A4KZ3vO{JixBc-7_IAZZ| zk;ffgd&?zEjF6(z1jH_<3-UM|>Q1`c?q_OBN1PDldgeA7e<+p!v>te~Eu+0vEDw`* ztk;vP*T%HdxttI5$$fa3rEp#QVyQ;id~6~DsDw%slIUtwlt$Mef>JGJRRruiHWeq2 zqDXIPWD<}_b;ZEX;iJn|Z^p3-Rb3KcezV!sr__w!w$qunC(fZLc>OWq?r+78D73VE zxuOyf#KKVDB|JAQNYS^}g3*Ptd`6wLKGnmisdDHyNF3K?fDzu_HYbc7kAk7~n)3<% znMy*uL51|(M*<*;k_1*CKg?wL@|zz~Xbq2`i@XM|Fqk)fJ*hUCfS~n3tSP&8pKBlx z)!Amy%jeP9M3W=x@8i}<7K;p26l2%C>4&bwvsGD7%=W*fWE1W@&}O6xto^A7W*aM@ zz|0sLX=lRbk#(Jao+&R^IZbz2;z>NA&8smzUyUP`%&FmCI%kK=nuCO*%n<`F$|`FlN7#yp8vr&KkD&_a^yZ z&wauABfDektrk9=A|Q-DY0r$h{m^LR{B;k*J3i>5U24w@35QC{AQ$h;*`3M1LV)A* zEvwNIG>{G}nNaDeq-TI#3cB866FukxdL3;5OMQv}{(93$U0fLHC3ERnFBNlAqKYE{ za=vjX^2Uv8)@t%J#V}$K`*&nhY*a96IG6rl;0<)huX0K=-F__--+NySA>Z*oSgZ!+ zUG?5{mgUyO`e7KdDNP9v+2K4V3(@$HnTpGz>vh-NbC9@81ZMS3X-PP9B!w5ljQweJ z0aSD>lwg#>HD)Wy5q)Zm;LkBKGr^E9<0E7$?i8EZTi1zvsnyx#FLtNPnyIvudz8f- zVW|SeqO%Q*^&iyNykbM@og5xiw%RG9d$3KWXK;=_$4m5+rU0STnaz20HLfMcaGj^#aQ9#xk<@%qpr4WiWh$CEk~_XPKUyo1$-yFN{kL-INwVOyHHv$>A7iQ(dZ7SLen$K`=cx%IK&3MyLBciBr6M4 zTeqx6c(B3ZxS3%E(A{!K=iOAl9RX^_NU_LO(+_a-$N&TzQ}KNIHtpvgUwtF?fvy6i zD`k(EuN0w?-mmlMvpeKrUuuN&vEGLmkm(kMg`CKa74K7Vu$qP1Pcp4q4wA~uuF|nf z+J^&?>E{+MmgTara;$Tw#EW9VahfEuAza>0M2@Z=QuHzLEZ!@gHKYbgVO#MRI41sL zktAjw3fVFby=#fNTJCEA$!+$~M3Qy$T0_?j-C5bjDAA+6X9DWh2f(-!DuKe5{{ zc2;xpKXXLJt1%IsD5b_ZHk{jAIeWq4yF^F6V#%{wx?nl;zY|?{8x6<9%#UvWDw61@ zF+W$D|MZ?~Q?+0gFEs!*=_6QG%@^1oRtNl}#yQXmo-pauEW1ySB|AB>sxre4DlaN_ z3&yzDF>N!q4|tmA3C!(^k%%FRBn;Y|j|q-3KRbJEBt#ZN+!>{}PpwK~EE3FYrMsvt zW6Ivdy3WPL4nVinPU&!ZBkldhFzm|naCUDh`dv9l#1}?RfZDf7Vo~(gr?@SL0moN7y0%Lqv}(t_~-+k=h^= ztL8)ec+AsqV0OkX^|?I_A)aI`WX15@9Q$5?RJC~^gCEnNMloHGsZ5eR79uU!ut!IK zqi_Y>(IgIc;(c h9hn0N-UwoI*G9MNUv@^0OjAXG#&(6Dq>*&mjJb5jI=*k}_^ zyv{yG(kH=k;C1#A9@hdWo*TFt@n_VIADz;1V2VVdo91I<@EtpH8faS zZ=@5mAl;xrcP=aHaI3LXgsj$U8_Ut~9dx;rLs0L%iFi&a)>Xd)XuW;~DZE!#lzsf| z<=u(=x7poJubesanL6wfB|us@GX6s=c|X{w;_vCF$9$z$Fc+G^Tw@@-vv}%hzTz+A z9n{c3D@)wwNP6aS&nNtXAsPrd%}FcBqdlCG!VAH4ir^P5~7`h->V5#BkA?{@byg}3(gdB=?!BIjiZMi zT_FB`>%y;Iw&wh>JYj30qy)%CM2*=NQ65S_I95OoCd&z2zPz%1Jm6t2%aV@TMF2Au z0pgz)0@Vy#c~zYttT;?ET?0OBt{eJ-qq)r0i7t}0S}cvos>0i5@=UI)0XYNC)ADEzAZ#l=b4~`=2VXWaYfTv0tiJ9`u5YldeIQ%n zTf?3J*O0OY-oRB!u+@vvG+KEIVbPn`!eG4(OmtiC_vPW~XkqIP+&QK8D*xB>A;5qz z3UfsSe5=_(Z?#xVyj9XV0V1F@*a6#E6DN9ftfZMEO&C^|QP=naH^OA}*C^wD zknNlJ7^3OIs9b}(%^kx^Dw=vFE#kS)pO5J)Ys19rO@b(e>>3~6Yed^jM8Es5q=eBC z9np$e?X~F%o|ryh{>Vc05<;2;xgR2gwbTqhHQTi%O2k`v&noniFU=F?gGH{!*K$`k zh}bfDZj*Olb2-V#pX>PLRA4VTGC;+u>N{_;SB*Qao^Hu`MC-}1v+2lz@*M1?L)0Y= z&B-rhbvJ#frg?l=jY60}ImKG7W|T8wMDN8ytVl@dwL@M0z4jA@N&1hqK zm(CpusBsnV11D@yvEk|8j-JwE4LHQPr%59QK^p_nw=@e*(kR>2DgmI}7;5VXup;b? zF6B|N`YXq57(q@E5@HCzuV`T;ukzSJ50_Kk&1DdsJ1l}Yym(Bl%!^?a=`$-<1;^5u zGI#@G4wewbS9a|0ucPjQ7#45|S1N3)!tB{IBxeJl|BhnXT9SFo@8aK4tR&73_?klx zx%YS6EAQNbo`=gV5c4btzO0EY^xU#H7#cmepLfp9WvV9ZwKf*Nz4-b01paJ`_^Xkg zFR#q|WBZD9$qhZGMf8Lpf0a_6S!NE=e;b$+C609!l!H0)P&)cnc;Y{+bWW z2nZgyA)M6V@`t?pPqhh=jGU`6xMD>JoruIV2UjiCAt-JCqUl;Dw8HJk_H1}v8axnK zt$uCHw(xA8qpGaB02g;WB=k(1meP1qoG}g?A5}1(X_G+=PPT6jw!e1W= zI>aXgH&1*QdHLu1YP!#o~FO zO1Crq)js!yuRMKe8_Tf5YSNREZ(k#W&%Ze`zK`E}7Ur$Lrdup13;Pu*usESw%84p^ zpgcdTA(a&a%Z-I_bqWRGM4XpWHa=;t@q3l;@GBi`8w)pqX>np4I(VJP`@7dHIkM!N z-@M5hne>dQEW)U{Grz-!-L?FS^vGUby;u_eD0QKOyFY}ItX-*XwyR!aw{{DY_JOrv zw)sBkYx#9r>hN2MW+AQXr(^rq^p`6ur-2(%daz^bqK>@lRGcXD#4*Cc9=^E*olIaT z5AJwrwo*hy;7yLPL0;UFI5W06AotE-dhOZEp~!RT%3kOXhYOYkvo_dvwy+y+6Qkc;|0 zwH+*&cRW^oY;@PL17F!Qi8lwm5ZolhFM0&rHfI9-$n0*mJE-HlhaEB3UTvxSRP{|X zw)&(rkY=L;3ubg-i1Z(3WQBK-%j&fFtsA_sQQf}NWybRx#^IkEJMjhKE=NpN&AKpX znsV#z_;(a^ELDS6^Bg5V3b;`UR?LZm+e`E{3idC=4h~o3UoA7U@#91hb{6$)mz%oc zP;%s0-mK)E$hcDTP`v6WnWb~+grlF&p|?#1#TY0Y?b{2?_+-YtaY%E2J4sl& zJ^6%JM|KyhlSi^1if)X-*ndDpwc2Ys5>=x3JU-i4l!^#=G{iX%t0q%T@l54Db>w&- zcZxxle9Pd}2DxnZu_@jMY^%O8_VZh*Yk!CP^97Krbks7*TFsj-&8Pa+vcil*iD4T&p>h-GCq8?yS zt4M5iN-a01$F9sBOa?UyM4-i=H${c{0u!yoB~!R_J{+|Cz0i`ZNaa$*3eu>~(Ao6c22 zR%39l*Qmp7{;aia34;cU_(`{1oxk#DBuVI~oSn}IzE>HLuCLDwEL<8pzA}=dG9rh( zDj(NIt>mC&?44?=%w*CL=Zf{+iyI|nB{gn@bTNW1i$H(RME2#j!~*^}m~hzcKV0W@ zY^nklkY`PgiBtQqd?&Lhtydo&CS2V07yVmo*GhzJIK{2r-ZWWKnV8)-j{m& z9-D>Q*?Xw0Cf=kY>k)OJ1-oLqhMNEh=Vy}Z5hi7UtwQnSQ??H3THDa zbEpdYOAotfBzmvSJ!TG|IQ3gzcPL_vmmxB;(jt}*jQLTNs_lsjP%4tWw~v>BBTHCa z+p0+2E1d!W*{QvV`jqU=Qa*Ek?7oaM2(_~?T=-8PMc#?v=V&)4o7+!H{1sh~x)H8M z&R%Yn8ZpIZVs-OQzJW-|60< zV6vWx2AghB27kSkxAx`;W6W%XjV{fPXE z+S}3%t()(Ah3ocAcY<>KjkF%2Egs+78PajO=tvSnn6@91{|MeiRK(sFK0CO4ypN?1 zLyc-^GWFDsqCum!{*(dX1n;h?Ey(M!i|V}LRZaw#B<>h8GtQK8qx$uJU=#9(&E@;- zLEG_#e)JX)djfm$u7DT#HHt) zL&o4Ko|#pwR%V3!N4@=@fuaE4qb-8s>^^A==NQwL zrAQVr#k46BIW%kPw%pvrmt<8_k`r;<-K5mUUb0KFeUvSArP?>tXYe7uT0Ea{-1p%0 zk4zZ?%AK&5IK>3T(3WmwvwPKGsb*7{#fP}B(8o3!0p&W(V(3BH11^IT2Ri3)QE;=& z)k1Cg&AJB+j9zxw&jONR+O*UnWCsq*0TBjx?V7Z&QrNZ`L7~i zzIT^LiZ*fa#QMr$w;*}wAb}6AIVisxenuax95M`hk-8U8HyZJ2dr(D$IHgePxh+CUe^<>V0NQ`A@=>QLt2$eywdm~WqIA#-+pJijV^7SqFq|>+bc13RnU|sqc}<+ zi|*jKqHopS?70N20>WV9;{@F0^}EP%AsZ}Iah<;MR!Zo@VIt+6R%8T|H8Prnu1i|N z6&4Ex#gwoRG+yLss=5KXNJ*zDpu&Q?WEDB-c`sM66<|JNu`djvNuZxZ z&u5BDRphBDRdhc4U4`9!BMIpRsg^~c(q+NyEpo9a=VVJPhps~S2Hpi2mb%mGJLKvT z_0=~QAWeeTwJ!xyepSuVi{;ja_HoP)Z}gfmyKyK3fpz*jg$J-%^P@(qEGgMvJW5=p>cgjD-M9sfhE=f5{l{XaG&{8Nv! za{V{!&-8CY&;L;C;o#=_KUn|&)OxPg8HlBzq{0Se-QlQ-|22E2fI$Bsurk5HgMjoy zk`z;+%=aq>68%j8k&)q?mkBBw6g+Qv`R)NsYoAnVU1Xn3pTt~vwXQ|Wg{bMqPb)H^ z1Ykf!gpUDRy;Be|3(3ieh{?%i1!r!+g@%g$s3$t;2q_6Lk%?UUahK)iA+f2KA_yCQ zJ;p-`jbI}9lL5sw;z>y;$iX3Dq9%T&lA@49mWh5ER{M8DBwV$~;7rm@uJ0X2bIM^Kw>k^@tpL(au1E3P6A21Ap~_Mn5N@ zqCdU7U6oU~t`Z4!l#DP~QfK_byduL%IUk@r@MueeWy*YrSz#ea0{3L&5z(hY0 zLR(vj_`8V0g|PbZ9fJDu{fRYyf#LgOfDl2g7{nm8BBJ0T-UapUBAHhX+>8?gX%1oe z8{&R;@DpO9O~PK0?t=#XSSdYf;9MrLBUM{T{rW`(awU3SA>fJya~_EAop+i$wJl2Y zh1}-{YsVB^u~9>z3+NJ?LT0izC~JP-VbDY$^K-dYWFsP{pr9b71s3W8w(yS%JFR&% z3(%k4k(gy3roSQGj64FR;X zbGQrnojw5+Ax@9B`++!mHCQyLTT3|m!@1}e_PK-fO*`=ed-$V=w2F!FV|)Bz`y)7s z^b3pc)*h110x+iua!OjqCiK}-LH>wn`IKMHWH9s7Y*k3CNm53%x%WdrItd8}>)(#k zH_JfaH+wH>{~h)3b_KBtehm2XQU@}+wECV1El!!>zg*Z03OTe#MVrX-)BhXbAl&|4 zkk*>S1|*zM6hO90ZcI*1gcW>LK+Cqv84j$342BX74_tc{0%9kHHdYfY69lAG*23s^ zt@&ghT|`F|38?m+_-P#oj8orj-&6oa{kz!j4`pJ@273D zPt$)x-}Vw2KK;47c?;e;){~U5RCJ(7^(wd{uC?vw&&KjJ^lJe>A>MZTrioFQp( z(jU-I{cgi6d*d#C_{$+t8a=FhdjoCpp3cwA?#JhB0;LBXIXqEavJ^`?C1#YKS;DYf zR|f{~DXW5r^p4;I6Ic4uZi}Gz%CYlzdt-c;2eNyN2*)?K{E;0lQ5CtYFB*UU;YH(E zZ&2Agm)Bh-%J92V)dTzrt(Ex z&hR@htaYnBU5hmzZU%!YPUe3Z_(IQ4vP-xmZ+jt+w8B*!5_l&}2?&T4P{xQFm}Y(j z-j667VF`Yawpdg^iZNUy-HCC@!W4G0Z7oGudQ&V)py0G!D)l?5C3PmjrUua*@}MP? zfFv@mRni{PM1aGfHqlhc*u$GW;-{7(Pu~KCM~|@|a8bb-3&3?uSsjm?-wc zzo1ziH(mi%R44MI{lls}Ph9$8k6y1S{F|Iu>`VhjeuvN9>Rf@6<;086?Zm0zc%ml+ zb!oZVH#>iE;IznvD6v^s@_aQ@)bQi+tM3Yk6kK|iYN8MSu{Q!^8Vx+X)5S{^Kqa$+ z`6$1C0_)6<2eJy=jzjO_`84Zrszd~Ov3dl+RJZH!yvcUx7#>!W7L^us+khJ}z8daa z;kBoku@tOsA7qV~YDl`ixX3#1X~dwtkbi_t$uaj}F>{|s*v;4XdgHmCP$+$lnv^xJqhp_+ zFE4Ecrb4knt*y~2R>1SqV6F=@GV}R!%tN?yhoECMTqO7MnW-G+z4-PDBkGMIRK|n6 z^h^YHJch>{nWEV8nuI!!3;9QWkB9zWQiB)hY*@j8lYoO7w~lMZxg$Oqa@kl&9^X$f zqzv2F9$7ux<8ep!T9t|!s?%H+J{(*{hDJ0*L!F+hsp^yW;@@W&P6yvCqau$=E$8@0 z<%H%sm%pj2mfJ@2RH~~M`VOicu4C>IMfn@Q4NkfvH%OVU9)v;;LK2!s%wcw(bk$~T znTWe|>BF-uNT!m@ig*>@Uxg@~X*~9fzPcFmpP^WxNJCtT} znx@yh6li^H4(wK%(Rr-J!4UZ&^shWPV?X^<7p6{{QY0GiW^ir3r+ zlk^;KSwg#$XG6nJF`J8Ts!A;b&vdW6cBJrky4>op=)Njy{BvsHa9ho2>=N`k#>kwCx{a(hIPBc3s+uDq)zAn77&>qZhYEteK;Q74s7*d@4ui^B%wXA55=Ayp>!avX{lGVM{GPPPqvPq_ha&kk zf&yi0md?!9Q8!v{OIU2TPVJ}Y1fr~MfVRD8RK+Q>nLwmr$>bmV}QKE#7885Y*U z3eld?EESYf%6zn%3F;Cl)ilX-EkHTrmcH^LDW$Ln6Y3oE;;RSUn9^FbzILFr^)}Q# zC)%LJw&ca@yD8z6WTrAw1&~=AZ9qATl0ogn8trGk&n;a^Dp$d#W}w|xzlbkMOB>lzs57ZI9ks1*V1K zAjw-$^cZIhXyb5=mnRT@H~Pu7MG40bqaPcQe8Da5j9gfck2+ai^f7oUt5Iy)1H^la zK^=`Ub^6#fd)b#Gby+yN5r>vz zs8O@v4A_D)>@{ZEi|*lgH(Mcn6)@N zRUyP|$RFe>2eZF&q1u5?69R2PsZfI;8@%kF=qxEEd3Z0rj+8xxu^Br+et;xsF2v^>s#USaGQ<(;zdsm5<$ zLcpIE;T#i*GHFhnL2f&Saz6O-@Gi`X>cIj)A(|zZbEiPBQ**|kn}9I_!kSc)M78jq zvxHx;bGq*DH|)tLetV{6`LfMv(FH0ee?>)MDA`x3S3~ez2pQ`pbH_&6AHZ$1hGR#p z0HQNl>2i1O0c7X|zyb%PWZ51j4oDiov^}>?vrqMvS0@;DGH+84o&m>P{{)L|zfyVr z7M3x;3ebz!!!%_?m{{Q`%wg=@^I>d1xi~D~ls*T+#!KArV1!YT4zw~!-*APJk!8e2 zn~a!p+M@WF7&~}or;KZjaVV*zlsZBDg5m4{gd%q2EY?w@wu^6%x)|1FMIR%lK9Zl7eLL!*|w)i(tVn z1a{24XNpUES2}?Me_;1oaLhM5_*BdcT+XHn&%(;jkMW&c-|LMU?=R1D6_w9 zAD03DTe;~7v#yn_2Z+qYuN|j&7Owaq59-K?Q?|eQc#H4h`}QMUt|uQ#C_>hBVlnEC zRhpe!spV%2T7<+SX8q*WjPe7h-pAOQeTWsNe;zL0+*+$&u62E>*EhQ!c8erl0# zhndYcd1R}#Wq#C-n%$SS+VHOZfuw=*5e-Tt4d}(jqKKNxbbnx`Wl3 ziIA2_MT>?6RY)AN3Y{JPV<=!ffM zPjr2SG_E-elPmT#8u+9~+%d~u#<-567&YKDJ?z?>b)ahb(_NzCs`17vFLahE1uwun z_3QpCx^ZE6+ap%CJ!g~kz;<=2n>x2D?hpXWTz82Z5PI=9K)H$s=&wMDIobBu0sgiD z3~5rz0c4PnRY@TI4&sq1&{p~Ml^C@u&vW+iJ&Kx-Xn(~17Qt~g4F7V@cv_gc;VQi( zZCw{5U8WrxV8nK9ThW7Ir@7$N@-y31%D!A`?m@Scf#QMSLJY;F<{$O8jV3(zG^`BK zAlT#-*Mkr#0s@d)PbJI=d#bNlLr*@h$b_C&IiBtpCKvasn4N^Zrb#KVB%(_bA8zU1=Znt?K&45OYN1=IWZ~ddR8HczzEu8(*(RPzR3H0W%ki}TB)}H2V{3tp zm$aw4qE?#JQgjtqXj49vSmGc)n^g~hKM(6|lgEz-_wBW5F;NPMKjrgJs;Gs8;9wlP zf`^?q>8L${yhJJDcOaPU!TY$VDAOq$^wAz3J}IasN0>@r8^34Q=LF>DUy$0UryOJE zpGY>jJ}u)nK_e9HksfTif3&YQZQl&yTInG_J@T75^8s)fdk9pvdI(cG%T#VsW%com z1P7%1**)<^nWrj_^U;WttC38{9s1@QpWa;mWn)&{q8N9uQd;t@O!DnAX|kIG_6|kl zcF_Vmz9hsjrPt^ujSH_t{XDPNjfrAVcr&rZ{eR;%aC4lIn-zz;m7R0Exoj4nEm>cs z3GyY59!s}&RAW8}vIlx#5*OBIJngZzn5Q)MpxFPs4udp%_?_`fNtJ3I zcXZDZS5jksxYm$TvGDSUP7KHJ&iPE(7l4N)+b~&-1sLr$Scwq1w+5{J{?duyg+o`z zg_W7gVdJ5ubm<>JQ5vDEEq0_oN-u(H2^fv?exe}3#SX*t?cCGLAyMrFl*rni%XcN- z_BwMwq^q`f;x307TiK8E^7kz9bXF}sCOa)ow)!gbLesoU2Vel$M7-MKW;xtep z(97_UFJ4vjm=~iI9hTq^7%uvToYXfXtZO<8{m$9;Zi|IgUZnKPlWKc=tP9W9>p8}~ zC5tut<&XM0*~uqc=sIoP+5kUWv(v|zG}en#_H^fAl1>rOD%F)M@-TPi0jlV1N73*` zatTQAKfg)ARAv`W>$r%ldGE(xB1c`Kh1EGjm?P^4euhY$v`iGtIjpGZKBL zxNDgB?y}o4a}S{r@3sdR-y zb1@4PxLoNUpvb3hX?Mu>`IU5+CQ_YjTR#^wHCVmU`FhGk4zSi?<8?SKMK$3}EicQY zn{KWbye?Tted)qkd$awPs{+eJTGruo3Q{-v@QS1IDxdAh)vtM?`k9Q?fxd!+&C}ef z^O1Gn2Y@3VJiNAHiTLxSb)r<8sGztY{XC+ob^iWZzoO@0H0mPGx&F+35Hi_pWWTdx=5Mwe{)CK!ZCboW=Aup4G~2 zaoYRU;Z11r=9pj)&t*=fm!G|UPUp}}pu!REPBHsu<;vHE{I3bQ-A)RbR^?LxBcrj; zPl)J6UJC)5R`%Pb&&BR{^g(}8k}&p={C6xkZG_ zww|B@Ks~bGZ#!|R`8|F=#UOz@xW|Lt;Z7yatA13*_(5%b$}axKU`+>NgB#4HMBa2% zr=(JgHX>~W+U;5)vF_FDlL$%q~{QkhYhb|;Q2RJm)^qpeynztSVspl^P_Qmcns{mzQ7=H&caX*+?mgCQi)QPh$PNzEW9C662P91f;{Vpjjf9A?sE0 zz@}@-X2x-~2c=YUOB8>qC9hvH)I=Yb0ZckKckD zy*m<}pUS9zX<90dI*Pf5so`dMR}K68i*a0)_?VoXtS3mPXpfnLxYyQVxvP4mO#Yvq zG2=d`KTP}CMLM9GUDKqF+9vza*aSU6)O~SG)@=QPk0Rl0%fos4L2iohFOo;hf7vYq zp@ADY%4`oUGz#9L@W(cwAD54cpERgT#k_6-BY*stgQa{PF5^7(E0Wf$)2QT4VIJx- z=huteY|fOdStTP+ocJ+f1n<1iB%@5g8;3;BLand30x2yb+{h+N0|l<1UKxT|w{E>D zVG9tWkD~d@Nk4%R=^Cq@q$Kc zV?2Vkn}v(T7LYigZmOOgu8R30d!hthi>#jL8n#V33I%n@`DFd>z`AEd9W%Fp$nB_B zIX!8LfNm%~qv1QP36TZ#!q;vX^gk5#CXjj~lh|LGeT-c=y!)s@+7c{PkI9uf%M&U5 z{Y$&sPGKcjOJ-KQY z07n#6i#tSeI>a^j8>f5nb|$e6_=UrW3Mbzo8oJCBNWE<>II>N z<2ig|qBdGLg7vF-xo5`-W`^gd$-qs%Zf!stYa zL_R%;E<}hR5=4*ai4p|Ci27*}-4HEr^4|N_dRZ@Tt?$ow*DY(Ez0W@T?EBm2-nGs- zd*jmBW~1NaImc?*71tKG=F1o)RNc6mP|mQygt1Kns6D$_#bi?0)K7~y_ZfKvY)i%+ zjOH`Pgvll`^ues<^*2JhZ7mfvrHZR9n)_C_7xFoJ->-y^qkxfcC}p6o{}y|wp4`go z0Ck@DbFc@BSx!gz@nH%BC1Ciej@I#8{xJ{~OLD?{L%(OS)*{VcYu4crZV9$p4+^Z8pWI zsmks0M_1Q~hMv7oQ+)El4$S#K&Z!^8PXA`=PX6!h$Op(P$^Wv`-aEw@{RG4uvw1?d zdC4p=KO-U7;(T0()_dqwS)66F2vJy0C4aevv zm&Drm_NkgucjJq7lkoYYVf6*`IDsM1jIR2^`ufc16yzc^9mk$&hvN;H;Z!^qEx zUA#AMx0o?6u^5#hG z=k?ACD)i2V#i<^4Hzv3Jc(+66`9w?ytu%%an3E)7TwCKZj^~e4T^-+baTqMyO1NXi zrf@ckkdztleNgBENR-k1(CfTQE51?#d=Qa+b%FdUqEuTeiI3`(6H znzWDD&7D$E8u7*c1~v+R6EmTJt#xifuD+ZV70U;R{uEb8i5_j@L?)cn(1UZ<=dY_LsF z|LK57da0<|*-dz;s%g9&Z;`0G<9sk7GV^+WYqlq=R@L#UN_D6R_wlW|2-08O+4NaX zs`2d$>Jv_D3#N6fj5|SUeEh53*dT3WovJd`PP~o<+5#u``uTHX&r;;obw<)#szatj ztBxy&2}4ATGQSiYB=Ewryqd;psQ*Wkr)1U{WZ~iN8NS+RxN)oDeMR;1NX6^Ziqop0 zL%>$jvIOa%I>n)i<*lk2QjsC7xA*jVAuE(W9R5S;HvcL24rjC?8g1=K)2oPh7Vzl zXKVCU7m9p)5|f`uqzmK;5z{!RxBI$1JHC)JFaYCVW!Rhq%qmB8(POGPswIw&ru)H!8%@s!5*+ue@eH~{!>JAlHk z?NaV%xLtBK2Q~iP=w=<=ks~!yxF<3CCKE8x<5q^0wk$b^f)tx zKPH7I1?rK<=y5imZ%6habhrk@$aX>5S`9K#NXfuCJl83#T z@J`|bYK{QMpzK5Q>t?6i2maA5GW%vMuezfXB1Ahbk_X&qj*5&)4K$$gMs6s*d7iqq z#dmn(A?nlLEI@e0(Izc**U6Tubx-oJcwsjECdmyLLXrF@!}zTaJ+tXHl&!M9yAN6< zkCL|ryEq!Y#qSIspmIKz6)Hqf-Krzj_TQYQwb^^300BBQHM0$cHO@uu{09Gue-r%+NK@G*p^dDW1YHEpYpjKixP(wI>+eO)u-WE z4Lkyp_}iS_Sft+Afw1?N=aaXqm>R?6!bCbtS%a%Jthx)zMEMAH9uV6B|B=42&&Chy zue2JETN$5rbOH zIBLrV?-$TMG6aXzq?~>XfkZR4?bS;dTa9k6pXp`hOyo`x-SZ>2ooislN}prKjw`2o zt5*G~D^u$d#z3oGk>>2i$fG+}87QmPEa%?u_oa4&*)tkW(7*!r<92;x$+W?3_A+;N zNrd~$_*=6aQ{*DojHBzNqUt*@vP&{PdRYazRpIPgWdzDBa_^uD6x%a>@D*q|{tS?r zaQ}X5<3?dl>;=gMcgZUW5m!bF!egTpw&J&VAcg!8AEVFv_3P_n+9hnm`@*cg@l0K% zg3_RY6G&&kX`BXTXNo7_9iI8pfcD$FYQ2=!ESyJCyKndDKjRZi7a&ZscP+KX^L=_Q z7c`LPj@WklehFBD;AlJpE)Hbfn{`U8By9KIUW0hf>pSnv5z``3yhp`Fo_*o0@3#2O zOsH<^t6lTaRu*DV8@fUcNx28P2pM{OqJ1qjMS3q@X}jQ3?=!|w?GySCmf_V6GvDF3 zUGsO#dIovC>_>!WnS&4S2cyi_u}@g?c#DHkYzSSggoXhBlfGqxkO7*myy|mdk7t$) z9#rCocRX`(E4xK*>L$uN_~Dm>DK~?2_Xx`d(!sf}Nd=S31|=lYE`HcEPc-LPwV1Fh z&aQ4!x`)5vHm-tg4L&gJo{I9{J6dC3u6V^%800m5EmpLmtbbn(mBsO#(5<$(Fhi|3 zh~Hw`-hF2J8)x|sU(xczxuY=vF>!$OH4FlZL!wbSP#gjvrlTwil2srDv;u)33J_TZ z+rKz|avMR-5!L{IB+eb+j`u-eFbG!?*${#EM`PgFe@Zh(!~eG+Q*&Kwpq`(X7YvF* zAxHwv-H})T>GXlSk|aw4ED;ziNfm$`P)1%xK}i;@ASWdY1WU;P=Z-}{0eAjg6%3RIf=F7KV$g6um!FONOZZXt}W=`rhK-$_2;riE#L4d3bsS45y zM`}u1&x>S49fS)SPU8C4(-eyF#sXATNrpyy`FW$T08(NhQw#!*bit8qD)TdP7(m(z zUpl7oTe5ehCY3J4`xn1U-@RuQhG0CgoLfK`-(syqBL^tr&u$VIy1c)2pTxTLtq j=mgJ2{x?mg}PA<)|pP+jYH=xS#6o)BS#TpYQqhe0e@T3k?Pz8VpK2JsEU>5C9wm z$RrvSAWqlLB$MWHOIJrO+TAMCMW<9$&zXgUA#vjSo>F7Ly2ZAqEL#5E)P$1X8)wI3mO& z(n)b3g%mHKQslqDojeRJq(1cOQ6@({y7p>^-K*kDW*Ar1n+f zr*n?mpXoc%P~ggqDLL;tR%u$+%T}mQj%{i~yno%&;!d@G%2*T4qc1M3;vNa4te{?1l*bmgtHs5E zVTeYTi)Jf&f6l}FSAS-#=vpdF5E}_|O9fVJ$=UaOv0YD0HnV%jTKXkPg+lU&h#;T0 z9KKX54relvGU15@%y&f)H&=BbC`ty8ugOgt5waH}y5~Z-eN`4=Q@7wlkY?P|etW-0 zM%}?NM#W>Lf^cf%ePn__s1H4reokK#*JcQYq7=g8(%BA($szXd?>Uh)8(IY%^>~&@4TGs;-!hIL+ zvo9`=ua{)vm9=m^`*GJ)*nWUwzsXTI0)jOk^T@*(PMP(+4T6@39bs73ZK`-FVw8ykD z&t)tlpOtELEBF|{^?LY^da;|=Ow3JiW9y478)hGW;gNQww#;eBE(!v^r%Tz{Jns%_I(seZbl6K&5Qsgk$* zt^~}@4EDeJGbzr^CCZ%W_Tk-U^Tr@5ME8Y;@tcN^_&i`(;Cl;9L#Jwi`)q&-@ zN%J;VN@n$;lLN^#ry%Xj_w&LOlwmSqC?-Yds=yQuSv<&aCd?{aZ2Z|ySMFCzF9fv= zq1)ATR7hg5i;KuYJy9)Hv^?V%2ye*KG*HKqQpBp7y>r=mSKZFQ`kD2{lRl)W*S6~- zKEU6xtG-mj*Y)Qj$wVT9#-LH;+EU+tL~SKw!2SM*9~aB5P4qSjJl+EjL*wC+zjq7% E1-lHbvj6}9 delta 1598 zcmbu9YdF&j0LEt{Gai?%*%J9r@zBY(|KG0Cj=A5JT!-2Psa(3Kh}tnuSP1K4$VtaF zl#DJem136Uv`|rrq9M21<8-gnr}I3Wujl>nKF{yN`+od=uYs#--~~h?%?==W0O0@x zQYipvM*$)Ml0U!zNUne#9ioE($q)EZfj@}KfC?i@;dHVj?>J6ksIfPK%CH0e8;MBlmU^MlII$h8xZK+9$;YwKo~Tza7oYX(=gmkFW^GjI|Z6XdU`&&uKOKF@%R}w z3|8|>VhdNvu!u}8S31CAq4p>3i{{0nlFI~K?l_-2uHeH&`BQp(V9_#1P;U<#L^y*8 zb3}&vz`+^U&gyUzl=RazpB5aM41;N2(FvA3N3vGfQHTsOC?V+V7D7M2&WHLYn$q<; z7cV_fva+$uw)jmHR}9cOG(9$29#QEThnubw-mG*hQRcR^FL&pspZ~41eAuCI(Q~CM zC+F8p^rHUk?d_HRmYea~u@XnkOC8rz9lls1)qYXq>~v3M&P^=?_39;?;%=>SYunU1}~Rn#dXgXsGFXy{fwq+s+76{cEzE;CMxND zP;(c}rklUE21J*VJjr`L|YZ2US_f0!NO96$G6RA0;>m$>VWRZoX>s4i;~lQWz$ z)LXPFYz88_O|i=#^B*Uvw;eQ&Qe~-x_cM$eg7DpOIg_h!zWoD}l(jcwr zuDtZsMCnyG9TQ{=zSrP97d82z{lnC(dO5N8eU^E?_h=~3s%<&a$_95@R>T%ADUh|v zsZSBK6DfO?Z65Mz4>y!9rYkiuw)D(&qqC|0Twr)ShYPFkXl`sxsb$>Xs$y4?vma&m zl=yKKW%17joKq4iu8zm($SyZNu&F*))1=!VT3_5b5tOUw>0`(@kPY~2h6bz$#kWPl zT_)sYi#}Af0oa%_={9%Uu=JY|22mTw28%r1l=mpw52gHD%&U)uylw0MY}7E=uiN=IoZ#q)9O%p*+RJ9k1nU7C2 zfR_dfxv25CY2E=K?r;%x4qJlWwKnz*DajI>RA)OfzO9NhfereUCI|pk_7duAoyNOW z!aMgkU&`mhDBA<{-f_J*7TtR{V!Gw4_Cl!C2^F0nGu6M9fh5yF8c3!mB_udOGAqIU1EHF)$p8QV diff --git a/docs/src/man/img/homvector.pdf b/docs/src/man/img/homvector.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7df9b5d0b343de559dfcef272e4050013fbf081e GIT binary patch literal 38810 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 Date: Fri, 20 Jun 2025 15:40:26 +0200 Subject: [PATCH 095/206] replace pdfs with svgs --- docs/src/man/img/Bmove_MF.pdf | Bin 58387 -> 0 bytes docs/src/man/img/Bmove_MF.svg | 803 ++++++++++++++ docs/src/man/img/Bmove_lit.pdf | Bin 64945 -> 0 bytes docs/src/man/img/Bmove_lit.svg | 832 ++++++++++++++ docs/src/man/img/Fmove.pdf | Bin 45783 -> 0 bytes docs/src/man/img/Fmove.svg | 988 +++++++++++++++++ docs/src/man/img/Fmove_CM.pdf | Bin 37686 -> 0 bytes docs/src/man/img/Fmove_CM.svg | 568 ++++++++++ docs/src/man/img/Fmove_CMD.pdf | Bin 37826 -> 0 bytes docs/src/man/img/Fmove_CMD.svg | 600 ++++++++++ docs/src/man/img/Fmove_D.pdf | Bin 37888 -> 0 bytes docs/src/man/img/Fmove_D.svg | 579 ++++++++++ docs/src/man/img/Fmove_MD.pdf | Bin 37887 -> 0 bytes docs/src/man/img/Fmove_MD.svg | 601 ++++++++++ docs/src/man/img/Nsymbol_coloring.pdf | Bin 37275 -> 0 bytes docs/src/man/img/Nsymbol_coloring.svg | 1456 +++++++++++++++++++++++++ docs/src/man/img/homvector.pdf | Bin 38810 -> 0 bytes docs/src/man/img/homvector.svg | 338 ++++++ docs/src/man/img/qdim_fs_MF.pdf | Bin 30636 -> 0 bytes docs/src/man/img/qdim_fs_MF.svg | 545 +++++++++ 20 files changed, 7310 insertions(+) delete mode 100644 docs/src/man/img/Bmove_MF.pdf create mode 100644 docs/src/man/img/Bmove_MF.svg delete mode 100644 docs/src/man/img/Bmove_lit.pdf create mode 100644 docs/src/man/img/Bmove_lit.svg delete mode 100644 docs/src/man/img/Fmove.pdf create mode 100644 docs/src/man/img/Fmove.svg delete mode 100644 docs/src/man/img/Fmove_CM.pdf create mode 100644 docs/src/man/img/Fmove_CM.svg delete mode 100644 docs/src/man/img/Fmove_CMD.pdf create mode 100644 docs/src/man/img/Fmove_CMD.svg delete mode 100644 docs/src/man/img/Fmove_D.pdf create mode 100644 docs/src/man/img/Fmove_D.svg delete mode 100644 docs/src/man/img/Fmove_MD.pdf create mode 100644 docs/src/man/img/Fmove_MD.svg delete mode 100644 docs/src/man/img/Nsymbol_coloring.pdf create mode 100644 docs/src/man/img/Nsymbol_coloring.svg delete mode 100644 docs/src/man/img/homvector.pdf create mode 100644 docs/src/man/img/homvector.svg delete mode 100644 docs/src/man/img/qdim_fs_MF.pdf create mode 100644 docs/src/man/img/qdim_fs_MF.svg diff --git a/docs/src/man/img/Bmove_MF.pdf b/docs/src/man/img/Bmove_MF.pdf deleted file mode 100644 index 1c8c7c2ab027dbd0f307287bb58e421ed0753ba0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58387 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 Bmk$5{ diff --git a/docs/src/man/img/Bmove_MF.svg b/docs/src/man/img/Bmove_MF.svg new file mode 100644 index 0000000..8c008f6 --- /dev/null +++ b/docs/src/man/img/Bmove_MF.svg @@ -0,0 +1,803 @@ + + + + diff --git a/docs/src/man/img/Bmove_lit.pdf b/docs/src/man/img/Bmove_lit.pdf deleted file mode 100644 index 3b63a5b3227bf52ec215cc51c3a896b926d051d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64945 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%0Af}RF`&{B5OQ6(9rQtwIV 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 + + + diff --git a/docs/src/man/img/Fmove.pdf b/docs/src/man/img/Fmove.pdf deleted file mode 100644 index 89e6ab5dbea88e3bbd3ec5883a56437dfcf2ca01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45783 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

nu0WGdM=BYjO&SEnR0E)ufHgx&);^$!LL=N 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 N;Y6UIkWi9D_& + + + diff --git a/docs/src/man/img/Fmove_CM.pdf b/docs/src/man/img/Fmove_CM.pdf deleted file mode 100644 index 346dace716b0ac8d6a5cadcc05027dd963f89fea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37686 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 diff --git a/docs/src/man/img/Fmove_CM.svg b/docs/src/man/img/Fmove_CM.svg new file mode 100644 index 0000000..04fa2d7 --- /dev/null +++ b/docs/src/man/img/Fmove_CM.svg @@ -0,0 +1,568 @@ + + + + diff --git a/docs/src/man/img/Fmove_CMD.pdf b/docs/src/man/img/Fmove_CMD.pdf deleted file mode 100644 index 4952361a820fadc147605e5bc60020fcae835228..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37826 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 z 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 + + + diff --git a/docs/src/man/img/Fmove_D.pdf b/docs/src/man/img/Fmove_D.pdf deleted file mode 100644 index 11e996980566ad32fe50bf092bf11dc2c5805b19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37888 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 j=mgJ2{x? + + + diff --git a/docs/src/man/img/Fmove_MD.pdf b/docs/src/man/img/Fmove_MD.pdf deleted file mode 100644 index 193e9face397ec6dc1dfb4492e02e86a054d0874..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37887 zcmc$_W0)mRvoG4VyQhuS=Cp0wwr$(CZBM(WZQDI<+qQA%zu&#jdC#-=hx6s$yVkRw zTA3M@RS}W#i-?LWQh8y~pA57tFr+=tgTxSvWLA1fKFY}#Ply4CbnkI<^Wa>0G+6XwX=!i-=npGvx%^Yk)82h zs(&5j4IFKp0RIR<$j;iu#?}eI44{*DG%>a?a<+2>FfjgQ4M3;%R}u^W#=pP6Vvw*k zHgW&k!St8+f3;2R{*KTC6ajRKc6QDHmVfXmK-f z7#J`z8Zt36v2Yl2Fd8s(7#f=z7;!K%8L$|0Fmv#7({mVbursi-)3b9Jaj-HQFdNZx z7}B#b7_l-jn3ys%@#_4e0w-rj69XF<_iQ6W;~g`7Lw$B=lJradDjGoF8_b|3I7;*o zfL2_!lt4Hf1Udy2uw)D9Ge(#jh9bhmOvjAU^;Ong3WkDo!SHF3#3} z?Z)Y^e*bnm0T}=Dynn4hAp>UvYdf=lGYr;$yVAdC{96X$>)2-?qeh>N&cixvc*QL@OY;-&km64-maX!H{Yc zh4%XF!9yHm4Y%7XQ2lyx>QURVXo)2rKRK4rua%H!OiC%z7e9yTu87&jKc0v#?_>;T znrl5O0e+_$KThc$;xk@C{F5>)QbsomaCO(eX33J6g1($-9H9c@d^Np( z;H^`a8tz=93zsfZVl2C8FD>lIegjQL!qKNOmu+wj@&;sI%}L4s%I3dZNyF>`yyl#UAK&NXZ)Up)oco0StQ zcDN`nl$>0T=iRW)GPGqVu~_;+^w6@t3SFk_Kwh|GWJnXzVPg1sd8#K0#h=jOr1Q&0 zSLO`Iy?l``ZvC`{}!mxD!^qva+kqNycTl#*~z(ijygKU=m2LiJzY>XdXj1N}KNg>wK z^UA<#US-yzQLaw4TrT>&<52td7}jQ*b4Ws6LG7|)d$*oc?VDv-qks_8*j4+I!zNMI znCCX4RfZSukCJ7C7BUN!4VikQ2I{UKIB{sh4^wZ4PSDvBu5uiBZ?6bgU`AfFC6WB= zYVjy1nx{72*+y}lv_j!-odV5o)t4h&dodEBCsLIA#V%gX)*U1^o?Wb{w?JYmFt)vQV)(lSU6ZTt`q4v0Qr~y^?jMurvlk2@^7tFuHPYD z`z+NfTzvwbUL1^sIV|cTsv2Vwghugh-HoQ55^MU~BCa-}*$KZM zuT~_URDW|w{R&|5k15d3!aVGKt&}FfLYnjZ@C=U9sOn9A^)zle*2Gr{-W7I~p4i{t zg`%WZgP`9L#3!~3X8XhYzT~00XCpLB8EY(N>p4wAObH>l8w^ek`;DW^ zke!~}(94*N<^&pEP6aRwTy9E=SF01ftR*9jOcofzL60h`&)j0w{@sRfcl~J8Op$u% zt@>qNQ)!V&qY+_N`QFh{SS}BId;d8YBUHa6q+7^19eEllO_dNN@ad1TBD6iP#DR@& zL1PKQnO<3JFFz%(Iiyr{BjupR`(EyC6RE+nnkQEVJ%E`MSLeDlzImXuh-g&gZZSgu46(@};J)Y@M9|{|V7Df8D!*pxr-Coc`~Zk&&L3nUw{=#zM>bH(dDZ;{Qekf9d}h zq$`>@*||6x{R8rhf9e1F`F{cUKfwQQ2>;LQ|K&^mN520vB>4;U|AZC)+g)F(PuSwJ zA$4A>-L!JX8{Er4@eYbw_qGX-ZW-pGy^vD+%e{W0ao|n|ZLFG;U_l}AYfd>@wpWJA z)N3aCm?m~{jl%jt=OrS~lLW#Ozm%iGr!zhKJ+r9&7xnENv@Hv--8qWV35 zMNk^(#OG2jWWXm^8g_QeTsynuu_3!Bk@KiQ#?XrSU%AGFh0Cl3GSc#h( zD$&C87`7^w!yu?GUrId@*rXuHe%eC%Ub$;uo+>O^8LQ-&pDx;YZn9{xAd#6*6B614 zDcV$txoi>2%+%ss-nV%+%U(qgz8Rf!LD}sGYlw2f-91Z28bTf_Jb z?d@Hianr1G={QU&zhjDzj@l|pLq&Z6S)TjTqB;#lUNdqnehd9CBm^;%Lut({CQAtE z0Am(AY!=u_$tnIMIqnWiWhC_VAeMgY208ex62lD+2U|l%{nk8}kIp3qP#O_5SMS1Q zi~twRykg*U>D|tCMFjv89s$YeG%IU?sv+Y9tY$L$9FA%AN}D1Q?>I97e(m&Q37T|3 zwC1Gd1WGg70IUKpv%ey>|i+LgzvML@|j3ndJfn6cw_V$1iymxWL) zIEVAv{TP;UGOle^8ab!t+|ub|#jm~g!s6~XKHiypDNZIG!wr`dww6X@jg0nMH`oh_ z11m!;pxIV_HtHgQEHD7#&_6J(?HQnS0aqNvq@p}KkSeY}&#aqiKXvB`pUzBb5qJ^b z-x?jbeX}y6rcg(wr~dwQJ%D6|mOJ%sW_p|)gN5;`i7mc$L%gs11JSHocTS0OzS=q; z+hBE}w~y2zTF;VQO?{cMOqWA+@;Yi(m+-OuDo)YNdf)7DY$1reZm~9O0F=V*lpCEN zIJQ2a(@;wzP&rU1e~7wVoqG7~`z-d*K}z zlm9%Gts_RVk({j8Hkf(WvL!t{L(x8pb2Y}v5T;DOl(@tL2jIoHfh#BL zEVITGJ5wrcOaci__R=5BZUPh|{Q*#O;uMM?Ad!Lo&cuXxl9E0}aWn7T zGwK)LW2Y4F|#o!=nRNU{`sNGLG9m>UNA6dO4Ed!S+b z2|$xqK&W^+{sH7@Ul zAaKksA@W}oz(7z4uOeV=Uc~fY06nBhyn}GU4_Q30S!D(gfBGL^H$K~+;ijCnIAMo+3&DK7c0Qd8G92z2w{gVoGZ=cc{ zBFy8J-(}(3o}O&aZ#}z!!aq1Xx-7Yv1n3Oh|1C%-*w02Edk6Xx9>gz$fd#CH2RRpr zTpDXuKOGhAo=DUy$h!atZ4MGU`b%ynkJ=D`1QZaU03=q%1Sk7(eS*ofa9Yb!`YoQ$ z*DDG}%m?5emJkAGJ@d{2wdk8FOjP2Xeee)kFB(?9$3!9_d!$fq;R z3h9Ree{Cznp6E4HLWcBubARD13Ix#a=YzPpelH93cd{6K$%hldfxEs+G5D=c`A%hW z!6C2+yASwo(gF$OhmZOhqyvL?7}z4&Mbr2R$xnWKI7z{?V*s2J(sr1KHwMk*VU;UP1Bg>$yhV>DbH|NEoRA*v++?ema$acLY{j{T+bQ|1 z3F-Ze=&E8icWqO$b*#*Qf-SFHE9nWGI6QFgH7Kj#Vg-RRQ;P~R5f-R%-Xt>HQ`13z zp3gJ&O1qD8c`0O@*k~}$fQgk! zmp2|?u~cQwA5LeJEV=3yu60rawYnw+igOLE^qMpE1D$hhrs>CY&(ZS;8Dizyo#8U> zIg0!mWg_VsU6{=c*n1E6HSPKi0@ZZtV}h#Z8b2{JYRAqFm1nURalGCOH{H4nIP*6W^WXdoBk+QX?I(6$vZR7M1_!OJF_3AZ(AlsWQGB<7=&){W>phu4wJaTFRm)P)yi6;4 zJo@8#S`#}*3JOt>L|8^_wYWIK{p!0O!?)=**1q0StGUoh@ZgI;4%0mB2A zRvVvHHB^xY&6!~PVFWH9a*aiL3lJM)wCzEI;*WEMd9(2+&dFA&EEhi@s7|b3Fi@raz93JxIxj9Uq2oY_iDv#FU z@ir9gTX2k4eVL=Mm?|R2L7k=2IMB^sn=ZR)AY>5hn)Vbm`}KQ4#*gFhi)4=c z(S3KRgwzf;iG7T=lSM9tocr`Lcs&YbKZk6jqpiS!Z)x^9L~A- zvsd5@-eksDMRL6b>uQGzzOH%R|APSOq0W(GlWWlomxwtA)gmg zo)j7tb~D+^vy&Tzgal>;B|vX425a-Dhd?T<4DM8Wf<&BR{>;!alT zGe6d7CUvT89kKKZDp!Ps%uKbG+gctH5+@1H6!DVs+JCHzF-rGf>UP&Dc!{X-e?JXX z2bBE0Y8iKk?$uo*trKN_?cVBYYoveQcX}^()6D0XNBE&FcJUPqjC{_h@*wFzh-K{E z6vO{;<)Hc)xyQjj{xT8s(&v?;C?Vy}fm&|C7D|4~B|~|zwOnJTcDo+_tNd$cz;OJc zb(a*Mi2Sip7Y`7CV^a`pd@(zhm+%MFlzNxPFO6j0>Gd! zv>CDX%;hd6lLSpslK&!NLHyPrmcSiUw`U$^q|O(>`f9v21M~BPHJd{8a#X4BV^ier zBw;xI^VRrFLSUlp?&5-@bEVWVGd8D&%JaRm)5L`R80Oyv zWO(Nq-MX8jk`Y;P9W-6pbmpU(bmqS5P26cC)Z*7yAQ-yfg^X?{zlfK{DTY^S_D9uL ze(TRk?*>j<>{KpKHc_{P-3htr2Wim<^N0M37rwT8+>r!|u?+q^O z%pPO%vTmy6N1kJ7%psG!k|if{KMuJOSs%toJvmFENLLM&cFyc^hoBbdr$|Na{U39D6$5E#X4Q9VME15Cyt}nu+>IJq zF5D=a_}g2Q=fZjh66MPr9WuI@eL^bOfkaTZa-J=|P_+AWZnF@4>bE5Ze*JvG6U|4R z*?|)mvVDM&(`Mck>0#uAhZVQ19Ev@b1L+?%9}5f(!3H|C8*Eo&!X+PBl7Lt#Prop{D9x*< z;o!v(9g)ZZC05KEAfMa%Y0e6CU#1gCRg>hl2!Fen1M3;J0^azMoO~16Ov<6%gj%l7 z(gI7o?RwG8l{_9KqY@3#PURye)+{7(th8vYgq|tFEmGeB!ZE!rw{JXFK~*DMmVv;f zsKkT#n5o!uU+d#%8{TgUHJK7_zNGcV8u{Iik6d@$FT(qpP{|fSht2#8F`gg=`D>`2 zwnNCQ!{b;Gr%C*L%I+hu&<9|N4D0h?&5p0V)TP$Zd~C?nuNg^Z=Lm{z(5XkFo-u)9 z3cG70CM)iV)|<#3#+m@T957o%lV6VfCsBh?SpJ(hu?1Ea5xdW3e7`@13}@B7tc3~k zz*4QjH;l{47sVWX}%b8q%8YHuvX`HxO41$!hu6(9W&Vj^67hoAo!*G`!es^Uy(QtZ0mlAF24;61|xqf z(pEij_vlJ+Y2__JIkE^{lLgkEA|S7CS_?@! z-M>;b&eT{VE9hvXFMUR|CG9jxo?0lZ)8y@p_Pp1r#OJbyq{g=~h%o_a)bLmqHXhRz z#WLaClv{sMLZ7>BkA+{WN+V#XQ<~S?uZ%L2yvt6YY8Xg$B&CUA;K#HwdKxKhTW0Sk zn#KNL5hhBv`AneP%sTS?6fMNTK0Tx~B00*9n`?&P@x_IyLHgU++-$&H zE=gt+T{A6i%n=eorOw|P&QmmP=sLPtm(tkkKR%YOz*(!8`G;E~Vo7;Mb$YVfNrjE8 z(JX6l5rN^y<)rolg2eB4kKkJNlg6UOl#@Cq2#Z#2;OIQ^UW)|JM zA%`_tgP?IyN09yoq1ax(*V}urZsO!YoQIzr^Di*as^`!A*AM*gf5!A zSW|3CZr7H`ONSK0HH$#0Z9~OjZsoc&*OWjsSNPH{TSu<_aYh)F8Nc1@X`x1@_sp0x ztbp}-DpUtU-5f80y9!A@L^8N;v}x8AlDOLMw9U!b?o|fgSXn?NHB{&B6BdMvR$tRm zIS8*vLTX2fW5=jb-HF$3cQFxdy&~Ulm%q%1$42l6D;EZgmG`+P&#bJTf!(zWNwLi} z(~mCh$2Me&t>b5JAE%?j#7e*r^Sp+&R)>-|rCp#GrsquhWPvy9#?QEKl_Bo^Id1S0 zt69Z{1scOT5v}d`-Y6>Gn7f*Lq<|Oklj-3-rUxvqIX2u+9LQiNx93vw5LN`=oqc>- zggQ$?>sZh-pL2Yu(}Rr0yI+rE^0Vy-nJg!QFZzBC>fdj`tt$Afd1)h_vL zC+veA7S^Qg53+Tf{Aeh({?D9_@pVHNrbocKgwAGGcY9t;sm{@idE9x5`{UT_3YM9( zuKWQx1yV3wUoY}Q^zm;=YUtjLNVH_z|lT^-D&T){j#31?d z(pmG+eO6W*;$p5GyYeVnSto5k=|UlAvDNvKSk&9FRT!nlC=h?jSYf~>&kF~pj#J)9 z2F(XwjyZy3ge}0fBGav=!>LBMqQ0LyL&l{ziR($j)MdOP`XIJJv$(3zD`C5E?#Tc?c$>P zDxG-*c}6>cBafOMW-A@$e&)X@1pPkr_@K6v{}}}JPMa$^q-tWcjg0ncUQW5m1Foj> zZQ8G79N@flqg}n&f@JJ3T_|N3H%GQ&Ld6$#X@*9fo<0n7t)WmUBiOY{s|-k%6@PG9EG zv6vO-=1D(Ig-0KTOxFtCiYlIJwRG5hOk!IVoP(WAX)2gW;Yme#GPD!;SZaB^M5Rnc z!Ha*QsI}B*#kMeK@mZk5)w4NTxgA`REt*`;qA$~uScbo?XCKOMcYlCc`jvs3x0A=w zON>VVrOjCsBJBE|{6tKGGTza2jXC^PoO-_%^G+XeVw)k`l#j}F)UmBK7{nm_z3)+2fTM9@5)%6;waz zwrSTo%UnC9kQZ;QYwKb(L)F%^Q6AO2hyux~H>GR2b1vb%{D~umu+6mnTYg9Awl#!x za++)Y#TgYUI;RC^5H^w48d(%oKtIRe03n80NIPzbxZ-hgw*U2HKqwTJhE4=Juu;fo zD7-XmRtMoT^SKdnksomt7fK}PmOgWo?zK`;UEcueG_uO4D{4vGiiOB+iH)QEqs;SS zr+F|Vy=Z?Qs@;EG7fWvBjh-L#_;w7!SfN3(*0QBKH>>!An+~n{xAQNi6>-wq=5yh+ zwo>GtYNzq(=!UpwxN-GO<=?EMm;0;xbUn^1b7Vxm!~*DdFJtslRcM2U!(Q33w=i7y zSo#Ai<_k}#e~88jU2+9rvuq8plhNzI0YSeKthsJ1`nr@lGj9(bWyc*EteS;QhX&9# z=LW%}ppn{4%e7sC^%6!uU|NfOb2LaRS&di?z4TSnP;j>jffKcANK?dQGdD(v{eqtZ z-Cc1>cI5LyQNLpu$wf<7Tsz7uvps)4FHua-9|?nR&kFQiZ{VC|qD{xbTt#2cz^5;T zf4qSnDjr^6a<_EKaia--rBE+QzDu{pMU(_yQtehOi{0P5zB*z&#bwb6*{DN$x=T1G z@>Q0??3LMbl;*2+ZNu2?%uH(yy1ErK-5-Gp3sGo}xJp&>x=q8x|gmoH+U<`>9nVCI_q(z)X+S-%HN64Vg7nUE&-YyylsMvs@<^AlN{h(+jtOFpF zKyo^KiwBxOccX8poPja5DURvTTz-E9h3I+qhWxb} za;ih1c3^8)<9@G9>V#P#+XSkO1VJ$!+)@5>Q+N}OcR+pQ;9jsE12Rm*fhi%ucv*Y) zP{j`Y8arlhONC+fmvpz7T4+{VH2hKU)#vgc`X8q3+E7bo-(;5l z$=Yq+F4xOXMb&xjOoJDiM3L?7qg#ftty$O?1B#N}LFV|3fk6Aw77{fP&u*c5B$SsM zm)xsqU`eZGh5j3&899E6+Mg){Z6WzYoTrxJO0H*@v{&6PB~^$`6|WJD;bZzNN{u8p z4B6F5gMAG{s|$!|B`nk~DGa~(k6MviPkA_%H&nAtO0*L;(4wgm{ZrfIH&Z(2^LR9= zW>Vwp=Nmg$e#H~EV2-us=bK@piE4uIZ!Cn73Lw( z*6@!YD<3&xIkM(aer=}r>K2$9KcXU2J3etv+>MwQ`;;YVR;MgKO<+YrC8HMi`U;`(FK!iKhO~=2uk^5na}yYGv?}$Z=~=L5mD|4*VZGOQ zo65t2QI~U-2#e`B2f?Q)9@&m5>-+eT3@*5b(m1>w`Qwl60k~^&Pm4F2J==ardL=BS zZ3ABd)u%na!ntY^D$gzVA0X20)raYQEiKK*nJ{k&PvxJZLpOZC1<#&U&Y{r4M8_eQ zEz|ZDE+d%nOIC1wd|-;FZP)rkY>OpT_mPz%je*!}>~u0oLNU7B zlQo;CjDym~0xI8=nsTc0uU=RO2v>%IO%)UNrS3{1zq08rbthXQdO7%>)GyTvX|%Br zWxYe0*3V@Kj~c&g)s{g7XzcI28h9$P1*dyTl=Z388@nB?M6dW{cgDx3UyPirtXqEBq-$ z(26A!3iBVPV@&d#o?gG3u5>i0Ju3Q^LEqJo_E`fA>R>RG_XJQXaJYfQCkp^}5P51bTdYENFg8g+swkl}YaRTfd`%oTVydWM1-uyS! zT8e=^8v)~2_HZB&0w9ls>}IW8gv4-r5X=I7NcOm21cdH~*$(WD(c$4~X=(I>c+}DT z?36dqAYDl8X88=bup{pMc>a7^5ZL@1yMCIe5cZ%lImj#95U9z-)3AX7pwKXEU~sX6 zDB4$qcsrN?Late1EkyJ1P-4HJM_*8|06$ttD0GN#>J5VHya1$8y=f#&xWm{`z%5iU z>MZgu1SGcQ3G{xaLm)rY+%7rNUZ@E22VpK!Fb`b5Uodg@4d~5~Aongm?h*dR_A?*+cQTMZ{VXu>0C0glIT*^#^$8fu#%+sq zIv>O?d?N(%2_!_IukV*jJt_SpaESB3H_n&UAdzQkrkgSx_*dfxT~Q>=IL-+*2^kC; zN(vBgAHcyPA8mK%dxpJ*Fr3fjBdnHn4jKFd>%y!nIO?s#bcT;)=d*#(yVnnbi66NP z7V_>Z>y#A$jTC(Y{>69ynKtnqcf?opQ7ip@9m#yv*7jL{{{`{E=Nit{5C07*kblL4 zYXJYC5NyK##kK(Q<>mIcixBR0^=-2_EC6+$AMH#euL(s%3y1PuEvCBIOqS4QBhrD)2ivW#AM0Kn_b*y~1y) zAU3!F*Vi_$ESLl-u#f)+sQ(5!5o{JiT3rdU^_k8UR3tco0=Exb{A88jB)lKU7eNyS z4DHWLImibw%>_P$(CB*|8wVs_9!m zN!hIYt`3ZL%Uk%SccFyrQ?YHvurP-DevMQ|K;($P)nu5>_K@Z@XXi^U(y!r2RB~qD z5AW-K^~7u5^%#dUvO+QRaw=R#(sbLx^$P}OyyQp(*-f&I1z*2KXJ6^NJp+ox_&I1R z7W4Bms;MO-;|`Or#|DNPtTnTClDdHhwJo#fFhbZmRs{=)3^wP(H3Z-Y-4tf0u1_DO zMx6^fqd;fwptNqMkbUz-llPT{K|0k;Ii7CEM76!PT!~}Y#bPy0w-aB^i8N1nqu+;} ztxdLGIc#l0a%?i|Z#HriwfVk<9~!TFYTuq$7!J9yyMsUdR7&P(D`4qO@2g+A zLbtf81oP?Nc?q9*7XxQY~iNnH;SRr2T&+%}A? z+t^TXC*h|sjIy_@=e4a-_DuGRiDl_0EW7-UK2ujApnHDh>5;tl(CX54Q%?A1%2RcV zuyZ0XCm1X=_RnsUTUsj;+D{MGDzxQ(Z=C(nHlZMkd(E$G8UOuYP9A8>CKsrS)FSenB#q4fLvqZl& zIWv2_PIi-CXOeJ*e(8<5w>78rc_1Q0YH8+2_$JqhNDIk?`500~#v5&;lDlp(9kq*7 zZHo8qTHd708!q^=ltj0B&SfZDMYFzor^a5re!)Ida7@urxvjD?32PST83;+sYOS%c z^D!*lxe}lBXo*nY6xm)Bz#_c^D?@v*<&3mx`4q|G{$;H!WuP|Y_sli)D?8Y>GMT!1 z`>djm){ROqTe3F3C8)q=YL(LjiSM2DxE1BZr#nqol`xCm3O`=z?ipK(i1H%<)t`4W zW3`y!f&p>W$B*+NV|Fxi|3wFI;J$${J9S2OWz^l?70A4mYh~6F6-2GFbcg!>QbJa& z4hY7vgTLcBnHp7uX7iwr`r-9{Q()D-v#D-wc;uEBUw%?iH zPA+Bw=B2aC^ABTl;`DJn^^Io1pOY%J7LdUrNUAol*m+({{JD}{Xra2LeTTh!5aEecv?ue^{7bwRRhMh=FmDPQV$`(t`5JQqhwjD zR?M#_7(Q0N2v+XQM%^$F7sui0=1P|Ux9wgEtEJNn3gn6=tDBcz7AbQ?5Icf{6sKd533^XY>;rgySAqC%0-<%<4_38K(W z7t+@sbd$&HS&12zJEHr+Orc1$ zicF6LzUHVR5q-hov@U-mnO&!y^j>B1Lv2y$>{8-6aEs4gK`5O1TogTdm(#8*t}-)$ z0gYU1-OFUL4;g!g8 z#$!c8A{-E2R~_9P5Uljny()K;CRH}j z&7Ty6)6xeogNlkN=OwaW_%u?Gxsu;Jq%T1#5{Ve?8{fg?`g{z zJQ8FLgKCe3bd{{fSoENmEcB1qNicRUj9fy354D)yq~SSB)gb3eeC!vF@|s#+!Jmc5Be%%!d zj{jK8ZFx_SN=x+(zxA_kv-p!y)J)ceGSI|w){^4Yr9kZ2>_^{z8g1gDNGGv$#oOCQ zp(2)5SwPw}UlI3Aj9S!DHv;qN8xYH)Waz)o4nOv@Z{b&BQ(oS>NuB~y-oKZj0algo*|x@W0FriCZ*I!KOJLn&{%mxe$|=_i;8jxF6vBH)Vd>uZ76Mx7~!Z1+%IPWr3Nw&^kw8Q1k4xRTb{_s4M!@8SLHRG zRWrk9Db{kKtbmJ{p=cnoyWPP#)(7iz-L*wBQHrCd>$?hk=c%_b5EnXI@i}LT znX9@3py0bz0_#iH6?T zT$Nf`?R20*X9xv_G9}j3b$3PxZv)i@o*TRl!^OmXl%sD<{d<^SCGD;b4d3y^LSXr< zJz(Bja;H)LZa=lh0hDQ8%42KIPfrWiDZlNotEl=ffgbV!i7mkncimJX?Y+Y|&1B6H zTry_nw162zY;kB8yfjaZ!cf(0F68ZtrVK%bddH2bTNI*+7}&wfOV3Yb79p~mr8A5U z!h++k8eq=>Nxklro_6kh%59hD^7|1M-sSNsQ?L?dXXaggXs_qBfR>{+dqH;aN6w^O zU-zS&bojJ!aCnIM@+G%4@HRjeA+uZ{b4VTGVj|uW|@P<#joUr)*K3Tx_;9!bte z*z;@LW#w1g!wrS*EF^I1{CsMCmU)Q{`Oefwo}A;N5_HgpnWk3JMQ@Uq^SZAXu-_9t zOsn>Uj|QnFzeyIHlunLMT_c9Zho6!#3dd|<Bub289Mxfq^znt4hu)k$O0EMy;g=qxG+HhKCpYy!Qj zSS6ihLswaqYA&)8g)P$Z)Q*h_y19q-=d$oK=iELrP|iw_{U#`mh=!;OTE6Wjxwu?u z*(iZ@TjOqV*I0Q;p4aDOfQ^R)RxhfUrOl#fR;apm*$ey8Z#23Tmrzd6p-&oQS%b7D zjr6G5U$Kx+jw(b)&IU?dxd^w5@~7A7S5bBQy$ube*Vbkel?VCabsXwhVCfG;wI#k6 z?c|t-1{upCFr=?D3sM!)h#lE7&K5Nil{|3^P9AevKJO_iA)hiLzbLEcy|^tGvKpE% z(XrsoB3?7N$E!yqNm=){i}Bu+UgRj-UBxhepDCtz&$kaGQia`U6!*FUifJ5$A2zy2 z4wMGJ%kM1im@*w6Fn$RJ!RorNuR3I1P*#bQF29a5^m!vIjdA_Qa1+`tsvkrd?o zwxv34JO$3tt!l859+#@qy)0f)*aEM`Cek6H6o#Of(y1+kvWNhN>tM~qw$e7Mri^US zj*ePVQngF@*_j=8X3nfGC)yC>Z$8^}9@QErm}O~CBmFrX_;X}DE{j+H0#t-N-FVO1 zx1E{_$uI9o$sa)<%w)bRye?6M>r?w!wPlyiUZKF*EMjh?SjrP$Ds{$S@UolV0xoQ{ zKIbq4Dw^->z+}hSckT1Xk!N8O?Nu5Y+)W_s3gDPHvjX9499Vj~B58jHv)MrW z7;}$je0t#6clmWb&1`&FHGRJok^|=aX2WBXU4mOwvd!?LuQ3nZN!6ChO<-Bm3-&A) zV{^Q1)7zClBOd4?jihP40%EV76@Ff8BJzyQ50hBzNy)Zqs$(mAdR;=9ag6V7zF?1Q z`%gWg38~o)hBW>yvyyVsJ}j>IX5-IE&Yv6N9$!3lANP|LM;*FrX%fc5F&U-W)N5~E z_b-@*(iWl)$Ud$;6~j+i9(PZPG(5(G#?Y-34?=S_pSa;8)CZ2U1IZViN3i}O+@<2c z2pX>w8pWA;SKH4Cr3s9E`5ygNt%cfd7~2#-i9D`|35qq%$+={_VD;>f#&jBS8w%u>uZ z6N#7$4_pP1tj8d{PR%>vcM-QJ!;Y+oSgG?}#|Bw2usz7rzHTIxr7;GP zZKQK0)jf@2>aLgJ7Y}Cj;B4;bR^lI|_0LFblY)mbDfL~{^rNG6i@(bsm#%unZNs21 zB3R(85g5AU-^U)igfoLkpD0w$1zf^|D#0}^$3X44iIyiAu4PDjh?6g|Bs>dWQ~P?x zD?A1uQyH3-URA>p1wIBgy}eUgwCR{!`uZu4#zL4T<2%J!T(}U`2Nv`;pTsIxidIoj zZCUX@$-K1#QY;M^NgwPB%GqW86<5zIY=QN^!Q(GA1X)c2+7F02vcSm%W3@jn_eFatMd9deZb2yb0*E-?z{CPDs_b!}N zyNFZm%j*iwGC|xpA?}n7E6s}5mk+WiUOXUzq)T!oAvfZ}dop+#m*=li?<6ztEkVs> zo}Jq`E-uY*lqBEwB3PhF7nrqAKPm2GTUg)3Y&9*t{X#HKlmgZLYjIl<5 zh(ME-em?=3UF^bwb-~Ktv>Y_7z{NX+PPh#TiNx4-fL;xvRcz7TRDDUlUs|lIm#fc1 zBt5a79Yo5IWToXP!Oe)S`bVc43%VElSAD-H4`j$n8I<8>ltx-g?9kS_bvov#I3Jb% z$3%p4lY45vv_q(!!zAW7k2iNjqz#<3oPv5nElxN*FoK4yl0>q<+?^}|o(XtkUl;?xJZudkmCCSUp#Q2O^eTdIh zNo5kQkYKW&u00$h_|Lfsr!{N9S~6uR6k%zU(HU{?1i-=O_>#LE=gl>* zAvyXRiG-UJVBEh1nPCod;j6o*=C3Jacf+KnA;>$Mhg8zsE9yyfuFoXf*z&2n(0$bY-XpiBhMSc6k{t@XcO zN9k3SH1THt#b6L#@Wm{Nc<8a-KWm-jp)|+nj-g7Rk6D)>i;~yLm|yTz;6Teo8)FLl z4&IZWl-lTat;*-7@Dz#A@I`MLQ{7T(8DXaROA7%~>wA5AR(CikH2YHU5AxBp>b(%` zb++GPk+BbFp3r|=KeWY|e1@SS6%j{`ot)~9Tui0~>CY>`%U;u}CXMAh=7R%^lq?!n ztvvscG#FY0>cRGG0gYJk`&B8@R+Do$3AC7PiSA3E_{yYVd;|IDt)D0#9*_1y06%S3 zL13cQZK0bVU;Yef2Q3-*+8^`bSaa*`Av!B#o^Xai;^|xNrUw8>=F%YXhNNKTTE;YmX@BI4E`^n3A;;(K1 z^<`}*3+ohkFy}h6+^3!`a<2gRZMkD)+pIRc5iG+__CH|y=;vNKLv-o|En)A39W1W) z_&>%P3E-juKRDrsXOBL=!pS{ihJycx#QuL93bL~NkD(w31H=EyC~`9VC;s@KPtA;SMa8#qOKe`1byPC+67O;%P?K>DM+A)eSm;Y1rV4=^cdjfFpe$( z+c>YoXMW?|6>`@L59o^i{K(@Nl=Z$3m~xl*@i(6ufZBXzAZ8G z;abDKFQSpbA?8~GI=>HGaHU#<+zH(FU&0XMhk87ED1t2>1u?e~{XT zGr)iz_T^rWjR6Imwa5Kkivyz&zY64khy7i}iwWIz-u4uC)oFg!FEdZq5ED=$87NBlS zwzm@H<)O*dZ;`_t zWFA=HrwaJVtpaI#0)!vDlB0Xyhj5bX{B z_Rp;15ANen`Mr+jk3HefP7tb=Vcm{-%I@oL45l?~kmt{_9leJ7&=+7C=XMO>x33l~ zo?o~MtRc8_^RG@760jE^#G?JBC!MqXgG12U&%HbfXc^eB0#a0C{X1bAU+-?Md?4RG zyfg^;uK~c?kMzGkcyv90G}d>0m~&t8bN>CG z)Yd=$H?PefU?{-$e|-miovrpRuD$%JdxkyyiGTZh^6(&sfDQc_c@Fgmunje^7Tk5I zrH*Io80f#mhk965bIOkRgQdg9u5 z6KjNh?d|s>57# z_DI`Rcr`FE@N|gJi_W6pR9&DpI83305XYk66({cuRnKXT54BB^+pbFxJu`Vo6BLbn zd4{qyv3nAC%dKE@(#2rj8K>@e{J>|(TZ&X8tl9Wz6DrLRiHkfqi6xOGCB z7&nEO{dMZa3F@8uo9!gbK0ZAv^qu2e4$m$tq5{i}uXfDZI#Z1kUwY-oiA`#6_|V{i zNP+mqV>NeE_%{C#w!PTD%d1!*qR{bO`I# z#9fxGJ_DxbE}3mkZ+G9|f2OrGuk|`4e2fO9qS%$Jztt8I77luJi5_-M zJZm}lrQ2_(<|2$~PuKcyy_3?xkx5|_rcr~j%jN7`Be2Le-4K1ma-+k$~S6 zUjKYl8unzC0xViMe3y@@8W^G52@cNN=k+Gq>4pY2XKsEFP2+n-yh;qGb`c{FCviQX zOvl};O?@=hFRp-hr_{#N0DR6#hV@xt^B)s4M^>n4MVeL-z7FVu)!R>rSXnT0CbNgV zYp14Rm4UI-culc(xdX;OIXd)d92@d~7uc@U=6Y?9CgLZv6GgW~c+Obb?u*_z{#=W+ zTPiT*UX-Dk5<`+APu`pcW50Z`rdbfdN4}x5-U$gz{EnZMjxzwso#HitfEU~|Ztwrh zavP~N6sZnUmn|RXD)hL$^?~!dQO8BsnMYpg4ZpSE3J>?MaqLS?$OKJ<~l_veR+pEDVN(mt? z3%j1R72p{xF)Qnrc2jXiqI+E*^S15!A=>MpV7Jeupa{xJ1ft;!eT$u3nyQztIk}s~ z`WEQZpP^;Z`s~jHN{D)e``tPjN)}rM!sHQpDK?m})`nnO-Bwss$WUC+ow=H}Y zkbZVOYI&<|C1+FCwBDqxkuKfBT5vkYr;eL1a7}Z9${GTWXt7SGy~^id?m}916liem z*g{V7(H~$>yIb7{@~!bCa8nHl{cuTLghG!${LsEIEvA6z=}L1gjcXcdTa7+73{$JD z6gn+?7Bv*SIp@4rX5+d)Rv|3uY_tW)-#B8x4zWcg9TmTE#B{BEp7Bp z>im$4Bx91{%%Rxm4eM`cmsp-D-uc!qTg!Wb-|IoM9Xjk{x~R;1=$oiMBb=DsvOw!8sxtO*>X%c< zSJ59KvSNC$1Hx6(L?BZ}Oo%fV%b$O~;FaP?3z|<&#E$wvgSych(F>Eq*MNZWZ?F~} z_$AkQSk!mcM=32&^4>PMLG}5U;T2%P9dC#sNvLU$)1=m!mVKM^3Xt+2E4#&!+G(ST z+&j2;uPQto6kn^U$$-U{K-q8p!l(uprtIRJO7vIvG4ITFsiWhG1j~H|KTKgMG@Oo- zfTM!w;fY7jKoxg>=!(v%E#n#qyWc#_eQF!xJN%^z)EvJN1ydqa_yPV zRTxd1CMtScohx=55Z?efqL77>_Hi%GWjl^W(M>SA8%BW93mSV@YU~t~q&2~w=oJXc z+U>dYlIqi-g&nP`6c3VfLP{-bZN)e2sxXdHT@|MeS8W~F>Zu>RYR|$K7m(z^Vof%R zJ2E1TEG*(}CbaQqBdG1;-+?Mg+I8zgej@E&&}%GnH8bs~9EG8=@sJks63sT4Y^6jNNLD{6wq8dj_4bvnrLhB%gSPiN6dA!`o#=#K{1>m{ua zOf}ysWxWFBGKnWRk;_Ca`m+Qzo5iY+DXZ zb5}7_mNNuwNq;4)ha?J_$1WVW{Hj5WVXJ;f1<|!u7U#A;dHtVzN{U@rLBPV()42Qw zxL`S(7E+NfYLTqQeo?{L*L|ldK`#wK^uAHik0%z~TpPwlh}4g&*)C2J6jF}GaFfMb zS+^0PYgY_SWNC+_ch5?`imy&NfO65=pKg_z7Ab`O&_1I-h7g6dC^gXs)Fky|V2jS* zJq`J1!MfyP^ERS5BDTYwSqjMFR%?JAs4~#4&Gouks3W);A3U@S&vvCNYm%)%xqK`_ z#s=#{6o?j3Vw%b9-7Ibpjg2Y1{VEU?PL66WM7*VnU&{2_$I;2rN8p-xhh^(RibQvl5k%imF3Xn-8c15`l$vRbqHH%3wcLTmB3JQrbpVLPF8A%}K z@XosjQ#p`TjcbF%HPA3Di?u3--<_iIkM03mV?(W*(wWCeF17y`IK||%ypU|wxu{3f zzTkHbyQWTDuu$PxsT|g;?ul4LZ0oQwy%yo>RYM8WaU~;4qn}J4T`+bgLek9nHfOcQP zFz%S|tl;L&_iR1y1K0aUc+49>_;2>za+LsB>(y6v{R5Dl2$I}478p77HEDXP(<6I2h09Q z*@$(nr4->z$1~ssOJ95M<}+pD0&>%Ul-<8th1%olm7I2Qol<_Iy;TZ0&112yop;4bCZQ!js#667$_Q}s z3pYLi`P+^@gTsRiIJpdY5$ZhlCwt2(zhQ@iXY0tKezaTxaA2?joOa;JF)p zWqtz!NG}|5HE?YF{8J1hjXY!}N;n%g!pWFC3AQQtsDEnHmLyP?|Fly^U!@6oSG&3P z=Ex#-#^ts#LsYBp)~3$FM%&`eX-%pg0a(bVeUtJG;0IVwQGxG>_?X@qB8F?DZq%a=|W4~(JgO5^_dHO7*ue*Qe;j;>d zo;VU0)QjM}KE9Z`M-Y;SI5<^V4ADhVRQ88zTJfnV)hWoDy_v_we)cvbDH@+vS&+d& zUZ0++Vv;QNuxT`OhW*U4kG~G5WR=k^{t>{=F21t>$oV*b!_4w z$40u&9BU}d7~Arn{}L(#O3Xwo=CW`6Vtn@-!)^ZN48`DpT)KsO>|1qgdt#p1ti8ba zhv&54S4cnF8?pyeGRbncy>M52SREQT4dXP24ovTAAJdi?b8e*RZQl;whFzJqa{1pg z;Yy{LM5)K9C10~!MR*8mMJ-i|-qi`z{C5zFM;@|vV1#Ls|MPJtwT(sH9h6ph>9{f) zi}Th#=m_~_?>|rGn-GhoYA}#p1^p}KV&%(dp=w>b7863P4)T`G>$59?*v2g>pqmVO z=HF7}j!Zotts+EuX)V1l8jmz`}TA@~>e z#ZSk~)^Ph8u!~C$pdF6_i+cl+O%62M3Yd;>8R_%T3Q^Kd*Xtr@Ja(5s-}J#WXI`z- zQy2NX83T{vZstM{y-KT0EMm|w>!w@uSUL{H_5?eBn=)Z+y(q_aT%hrT5B#YxrB^jQ zeqj&0Yu&9*>al}zMiR8I0#=siCcDdGsF$65w4~jk@0S5VC79YU+B^~7r@iByXJ3B> zPs;LAcOd;d+mUiS9S!wLdgESdg08@#q@;Y*)~fhC#%t$f-R#+P*GL4>eO}fI15y1Y zLIM;lYi!?91tof$A+082F-;2|VKmtWi|n!F|Mu7>%Zqj5kzTQ2;*amp-HB0QqN}{mI{uNlFy+RmVs3AuJ6f(kxBBOs@@4flRt^> zhCCng^t3B19BFF>G7PXoMij&`4s~u{>_}PBTw$&myn`+e73x;U4{yVqg(On~tAb$K z%oI|BKugE3Gz<8ZO~ z8Kjs^|5f_8FwUs{VS(V|?vRUin_JS^s1es6dA38G4ndl=Qed(Y#%3bZU8BShH>Mm< z_4KB68P1w<3~cE#v!%B6r@_b`IZvK3bet`T?FqCHK%3Ms#~AoWN@Mn2tGuVK3hPOI zp_jgST{b)2=H<0;uATvT_vpBmi15Bu04OYX(p-|et(EJBu$UQ17S+i1}~{ULyyb77xb*eExG3W2H82S z6n(c^>0_klYEXGz!lxFt(n=G5Hs!Imev9Z?3bzHk)FEcyw@=JB+z4m=-2%ZFs&fCLei&**tmV{!~{ zfz|cgii<|-aIX97#%NrW(UE#n0j%*ozt_CF9v%a4JjKzX)`4N{kroZawB%Yu9>R7O z;rPD5Gv0QIUxPiZr9_Ki6J)+Kj$G&s$cFDvh_;$Ouy<>ma7GmTyw&xc=sem8z$ULs zS8{3FW1aO^%wQemh@bQQJ4I*Wr6;7MbJ)S%M~ivha5oW5!!Z7dyd-ulP4o6#aRqTuNQG2}hN@cYlJQa$bFq~D z4Q7b+zO!Rz%g1-m*9}+qU=mBoS1aBNwZ}j`R)$l)=0;w<L67HGGRq&ZEp!TD zp0GAbICUYaG?XMba+ddz4f;)fdAyk5_`v^4Ficb2!qc9<*tJWK329`4*v0{GjkeDX zt5z4K_rR$_(L#1JE}_X%li-ANuNkuOewKNhs~OG|WLRP#pE>XdmBh*`vclkF_(uXng5#6eY!B$FlK4dv)`O#rkxj}m<9_cOlax8WjAT5 zeNMv$u@n^(W0(s?@OQVAW)S4I{Qsk!ws-gHQg(qLW({#M%aI>wN%AwJu*}6OB|*qy zTjD3b9iwS6<0?EU!sJ2l&QgiN9TCfs?VHBC*|fa=knA^5V6QS zryT5vCE!R^sdj7uSc!MrI+|*fTlJZg?Ajy;FT&pacN@EQDacoSN-~dW=P?z9c5qld zl^IdwL|u48k~@a)iz32zcf;AG30_oG+2}N&57cWCdZ5bSgby{dH-nttmf(%Zz`AaG z*1}4(9O=iGyuOQrzcuuh_V}_o7p6!K?xd6p#B&eRmU?&x0?5kRmAIBd22j>*;72OI zVJBLud5rs7dl*qX>=OaMA)wuvpJy$KJ$_$@@OaJ?iQrb`#GT0BHKrSz){G73A`p{+ z`dT(Z4?Xm)r6TvS@vEgt7Ed+u6>r-<{8s{X=fcRb)_?&&MJSHO1W%Psw!far>4SZq zY6lnMzVU+}vJ>ReMy{lgRgY1dW8n39yt6~V-V#-02bU8eyxwUz4truZU$w~Jzdk|~ z@LlkGbSqn`FP(8_$2zD#4)-U5(!(avK{xtAatYb@$b#eL!yHy8|7?hot0=X zBd_Rja{JcH?zpyJWX&P2JwoUju|4mN^OD;Kkb}FnF1~n8-0+WDMQ%aAe2ll&QjC#3 z5`0*_gmDEg0ZB-BOQkFeWBd!9mw5xgvR@vu;(WQ%)?_4t z*fH;3dhfw!+ZV$_-0Z6k_j~6T#cmaroMfu{Alv>5Y(Y+(oRFwPL+|U@lm`Re#BM?8 z@1=?TUa_giK3-z(P2>!Xa}&p1Y^Ybv53?LD49`N%z%E^_ojX`FZXlz;XJ#RHb&`>A z%OkPzGaBF@q;vv`-3(%9D*;y-vO_mQ2~-2+ZNu7y%WgAuY2!aJ%G@%}kHiXP(8Fn= zj$wJlITHmR6V~8Q!-SqzODTz#mY-)k8Leq{JajNzQunlO^o9mUIj&~21}L3*#R#;|(s3+F4=BbP zXg`>*7#vwx=3$qy?2Wg=X+Us~N148l87u$YvisebRQaw+m)cGI_f7I4-?d!Q_(SJ1 zB@LC=DWcIgv(T;=KXBS$GQ4I;j2D5^F6!?NVx}@BM+40RSJ1f3#Mzw=q!hXripM90 zMM3Pb6XY`_V4q|!E>oDe(#1#%B| zV`^26H%gRK?3t-~cs) zQzYrm{`Nb3Y*~ddeT*n;JU60!S^+w3zW6^H^^Z)hoi6&!`FlhzEVqF|xVr zRXktcGc78@3ye`}6r-3g&d+ObaJGHvRxc>CsI{KG+>N3S%0^uCG}kr;{&yKj-Wn$B zz#v3SkglU7pX1IPeN^H{2fJkSwDLEXVol%NgLbl6=yo*crzF0~U|2A><{G>X>OK{n z4m%?8I`QqUyg_042&4Xa$0I?U1Sxt2cdvkW%!fgw9?7u6=9Ld;u`RYg*4Fo&ee<%K zixr#|P#^v4ptU!mw$G#tue|dE%=ujF=vt|3sRT0W`ns?#{6)oJV*2-ZA8@I(@XKkF z73C1@sZ!=~j}3!v=xJeAeL41m27`OT5bV^$I)gtl(^FyWh5JmMFUYMOdV#ik82{3y zZyWuqn!Mv>nNLefNDp?`AS{_UdmxIn@c^_6pUyk(<+goB=bI0`6>K};VSZG8IyF+RjE zR~N<#>lK8x-Vf3246dVzKo5Q8f^gp&Q-@r`g7`+$jLHHTe;v@=v=*ld7&*75=oO?? zlp5%lsy9F_7wuRJ8#`o=0>TZcxjaAv{qE^{r|BzX$Zvj;OH0(H-*OM=hz090#Qvx; zSziWrx7wHr-^e2%aTYN+ zixpK9P&M(j;Pb~2n%Ey}w5Y_cakYX4a50@2yB9KX{xUW>Sl5N~J(p;xS~PaCEB#E( zj`3=+M@X?teAkc@FaOO=qqPui$#Stx9dC(Day|bvy%qamn)@UZm&0yE%DXOA2kexF-|$ynm1EgE zBYx%2m#t=V6XZYd-f-8DbSARG*rv#Rcb}T^z`=dh|YDK zudhiZ(GU8C-(XJp4KO@&b|AooV7wZIv49P$b*fCKs6Q7tgWHdQwWffFvQswEaa*vF zTI4~NAP_d!A;AqVB)uFv+cNsFAgPLQ)_pdDIUy8By^nKgZ0*ucKM)r1sg> zNb|G0oAU7=43@;ly!w6zlh5lgY+T0);Un}%s?!-8qX@EdiEHpwRkKsi>Y%YufZBO>B6Q?q5lzQBFq> zSm~4NDA_NwGvJJS@5scV#&n}8t*qVk*X~UsPw;>xNmRwwoj2UMG^vcS9ZEQUpqp-v z553bcSv}wSM)dWSD?;bWiM@@~ZAzV-f+1uRMN*IlmVyeDfR9;weN%X2K6;klM4EDK zlz@YbLWangvq{EPlzrIcuhuhdBSXVOXt@~oN0R?UXuf>09|b8E&~k7w$S)0f^npb) zhWjnUSA$Tmp&iTHO$O>*Hf%|t>QX0cf%!P-ca?zD*^=DP4paWmYa!QL)fU8&JCS1) z>nX39x@K|#r!oy8lgjAxpez%?t(NQp83D)_uG}Zjmkf}#b(O9};hf&ifcvSf3A+7# z>Ev{)EmuwtnO3CNxI+b5$wuVrS}8CeqoBWQz^W7H4k`l(+~VCj^8qElU*KHi^#3ls za15H4tH+FDwxidZ=;`{>_4YWIltj zA&{UV5lBjkeNif?c$ojP?d`YEXIAU1TJtLBZ1ybn%CmhVMkYj6Ct+5B0Vx0tEFydY z(DIXvfKfn3Mo2_PCObH53nnyF_)jg#URywskAXz!){nEiARmE6tqe}k=;t{BLSPIX z&YuJzz8ObCOil&{0UbH%Cyf}16ueyc`(LepFGPNjh=7ko`%1iC07ZHiIF{E;Uo1c# zG(SLMN($m9E?l|0kRk&*1kij~K5u^RI<_u>eLur;TrHoX1w(2?&))o){h5bs`W01_b2cg}v|e^MaA-*BPr?F76% z1mOZ0gShrV0|ows8uB2x{%Al15NrCe2<`Al*zgZQ{rd=J)kAlaga8^N820AWEn1sVQlp79~@RRD;23<(AMvm4?kMM8kE59!DUG%M$Z5q!+M z)?i(}iHp|dgF*vXk2Gii2O9SM`SocW8=OLo@CW}L`+4&fZK1J#evSe8bN;r=s-$89 zfIv${0S+E183vfAkDvGlU+^bm1QPJ0JNg&7BGyg_xWT_-IQCo@`SS|~u(x--5B{4m z1rQ-hi?aU(KYlY@JgifXKmW(R>=*XEhww{1^#^_Yr;D(T4)Aqi8U}!hvzr{ zC~o%~Wnzy3WEuP%@Z+flU~p~uI~7`zI>mdvbPyDBY=?|8mF=fj5nwOa`CFLYp3DLu zSU?a!vQBD5N=bkbd{Riwvd^D}gdm7b6t}pjh5U?|Q58Vi!|P zLlEgx>pS(=J~@IOGT3;-j#2OOE&VHNL%{-YDa6DX>YNbQsg1kh{it=4+IKJYmt$~? zI(7CvIFMBC)@ydWmiMS`%9k#VTfuW<(Z$(RJm6N&GvbQay`bR4Tgtf7eqlD=VbnM= zFNHiYOt3Q+5D1&XovMTovjh=%xfk8RI?Zhz+fwM)i6S;Y5nHxJ{!6p?Z3 z!_jKktwmWQ?HT()l>P5_obGT1!mZY6l>!)?P%Aw|!rzkJ-|+a}JpJ;dA2my^kwEg? zG*HB#ekSn!XlWsTgNfN84^50t3>ysXTexzUF!$fe3k&Y&!~Wr5MjSFAEL6yUwG6?z zGZ1?yn&@-o!5PEEmz!1Jp5%K$sZO~-irsB|O7vxFDa#8Sg&Z&z)LA%36$`3JZ}~J= zcRMO(S#dO4JGXpBxrslIr%)J#O|R<^b#}17nn%1_PZve^4?|`#wIJ?PCM@7Kiq~F6iI$&M8z3& zmP+yHEj%omb2l)brDjy(cbVxDg_LaMG?nzG7CQM6Mz?aY+Z`19mff<4q{mBsLB0&S zj;3^oK z^TX3RfDTRF=t;UR13xOoEj}Df@LV5BAJD^{-re&?b~#5?MAJ6>%7w(~zTnIh2svNicA;76 z)Oxs-Xgu8w2UVRd%Io_=&QG(7Ij8J;B967gR2}1aCC>2ii4>B@3hSF>{RBRaDH&k! ze-XEtSAmPrT_rz=a7aTHb+hcOL|Ax{EsG&xbzCbBI;tjjCqt(NQ5|!kq!585;jUP6 z{cv!Z!@$XV)x#JhI-^3G1&{pu`ZqOtp1yisvmE5UkSKq=@8ISKSHGMj^2fWRQ5!#5 z1yS4}^r!X5th7j2_GO3Ks3B-bN+@!n4kf$C<7Rm&N6vKS$>VzFSa>?s7lOR9+UuKB zusn2L>`ai-lHk27nk;a-L#p0Qb2+0&NxrG^5+uQ`m<>Y7PBa_V5ha zi4_NE9l8^X*4g7_-u_&X0QhSC#0Oo?w#(x#$G&THR8>+~lHYX;X3Xejw0n))j%v<= zzqWIjIbx>9Z4qw2K+p57dq4hPw^Q^V$<%dJOYL|x z-OwA}uNtA}jC|)nyap?_>ddtpNi|KtlJ~JgXE*%T2<%8GZLX?>6}E%JfS)fnbrrf? ziGIC}!8%63>&tMSGb1A7}l{-LvgqdM2FTl$3)9w}1kIB+iCZxMt{oA*9x zU7OQM2iAJ!syT}DJSHA2Yz4Yz6!?GIeK#|;XP+g87if-0zf9vo&x&oAxF?nPX4=<= zlr^gzwyEn{a$IW)&1}Igh4k**>xb z_NOmKMqgsLmp@b#+lF3g-nngwVIOoj)u2&*l~s8cR6${OT2WZVXthcGemS7&^bx;1 zLXzW}90nr+0Lf$y2qMQkVv$|A*NuTPgf=z}#OB(r%{!vbsvR*)u>+UMU5fFreN81f z{U)-%V`=O){eGmlx>?F54|W(qa%RMetsyqYQD+7L?;3bLs1e5}GkTAO3hMaz$~P>W z7_Fl2G+kFPSneTk#3W=u$Ffr$n=dHT1nOip%E`1UnZjx{@5yzu7;kbz8KF*YMW%Z; z84C)l%Ba29K;+H`$GVv(ku?3v+-xX#_K&p?gNkhWQbcJ;ebxrxkFuqhn2V}}`^K}C zkG5t7Z{h{-DxHiH)8a(0wt|>Ar9G5hRt`y zuiigR@Mpxcln|-_OgpFpDw!1Z>!&uTzYDzYX-d;L3b!=^ZFdHReE%zUqjycuj;QZkumF4uK zlutLQ(;tg2jqz>$@^pYoU;$g`yX}Ebo}}~CMp^Bf-`LPlj(>OOc+HyH6Z$dS>7AFvYH%sw743e^H5SH+qUx&?Jog#Fmet@ z9tdsug6bTm#uoDd4UJP(!QlJgm4VIr0-8J0tm19Z!>l{VxgKlC#?py6wwOSUng^xB zw9pS93^z#9_m0SE%Gg|%uyu0*sW3;4?M?0{g+$qCn}Iaf$QBJ!@t$JTWbal16R{?J zk|iI``N@Om1UOF&v;n3-4gzoTw0ohkAQ$K2zWO;)@({$N?*jS*5Tm*hl|>5Eq>PE| z&3IAKqB>2BWrnrLY#Gyc>kD~msND8nQ-rq($~LwAio|(`vZa@G%*Lgdyn_k>eOZQa zNFvChI&%WL?;6Sd;>pLkGA(Wd2>=Fb6<^Jp0lrPkoq%isL<ZTH35ehI7WH3&LE?2Zd9jDmQmok8-BBb0%!J(r z$=le--XkYba&kOUqg1xDPr1l8C3vyLak#= zxc04r`q!M8-!@CKOYfxq0RxSvLd+G67xj9R*NXAX^y*AzU$)M#@EnLHg#Es zJ&I`l-1=BXt}nqw_)*ri@hzTq?`H05>a@fu~=du_F8gm!imrEY`bmmg1Wl%`dz3X_$S6|Py1HI5E9qhv|pH5oxo=I=7LJNri4?0_6vwIJkl)b~)-EWyA z%Ut72_<5&V2Fv8K$(7bQ<;>PN@Gpog5AT5IQf|_*|HhLcff#n7{Q3%7h?bGjYDVb`%#U*b&e&nVq|Iz^Rb{>pn07VUY8 zPF_DU#bv}dHTl|p>I(lF^hvh<)8($@N6ItOf*PQ~e7JNMAR zeIF0RYunY{uWM(au>Nm$7P&ncHe9J4uxP#%Je}*60jrF*keJLUdSkZ{Ysx{YWbnm29 zUMy+i6ONe)w6qIB{X^-|M(CO6%$UOCI(s(u63!V*nCUL#3CO1vE!lDYZiq;aFefJRvUBeZR%0YUSS1!N z9^qFevd=DZvX9PnEt9P1$&-C!ROB0oczM}ZYpAuH-mYb7KC-!j(Kd19jW|qlc?UPD zI}Vd6@h}+rriI@#%~?gejUpS@XE!Wn8ojAhX)rTTZPCWt- z60j@{q@Df{%YXfuIXpGt(bGY(%Oe=D+R#?#sMFSP02g%WfOyc>G7{RL>+INT~rrL zs2IS9*lH$mLC`~O!wPcxbxkVtyvE`DuqdTuP}%e>>^)sVjwuOMvT2j}%5%BpcJz2h z=dnO^fe#{Gl2{YfLOB}?r>c4yxBac!5NeljE=g^oqMq&L@P&^hV$a4L6DRpVWlgm# zxvlsnu*kY{B&pP1bUwS$2lg_oze5%`0o1qOy3JTIB;lOLKe?(N9E^>A;szFa(YUMr z4E!3YnAaX}z7OZ?s;XSOeAruSbo8vSmK1I#k!A9cRgc{#ui%Qa+lbFr^m3WYT_MvH9i0s?OMWeZbUkKBxX((Vgv*1q6%$rL{KGqF9S)4dH^ss(JAv5I4J<>Y zvm1Lg%*fJilAE`0g{!+}`8maLdAi+Ki5rsYQ!)U}hegP0F zpqrI+x{apW#AZo1z>52E@-1@QIYv;8J%ll`aY&{O#BikL`ffMrbCqGy6_K9cH`Ptu*ms}R zrnkB3w2QsuSp=p4SHy z@#yKj14GE4C%qe~)>s+I8R734S+(2nXY+=ZjozS#F!%O5@146-F4A9FmeDOsS!?(8 zIt&j#TB&I7tTYbJ^~?{lcs^Da!|zkedjA@YmSgAJmyQa1LNJ@*V=}v))BL>ur^^f9 z_`@O54wl1=Lbo7i^ODBC6;GKh+>LBLdhN#7nY6-~)OIhGM6>#(ke=Si`!7WJD!&a6 zMKkAP+xu$&H|A(CIav^MMD{lh6#POfyx6*X^w1F%GuCe45?&TXWMl#TGe?(S&POeB z&~GN}bxm4CAR^o{@^aQ7Q}7llty#Z?GAV=gL_d282Gw(}mgGy{ zrjF8NALbs<2CpqIG~hy)mgQwM7-a3-+kA?J9vTft0@ zK;5#u-S#uibcbr^s@N6=-F@y!ITs^j5_#AGhW!c;*6Ecz>ts10C~oe0HJvUNS4`2~I6 zt@ss*KDz36vXy&F&O~5idX%{lOugTZzji2(k ze_47OmKu_oy2-!o%APvb#W$n)8qo+gz6qlN$7qJb zoMLTYjheWyD>>Y^j8!iY+kqE4GXvoh7@O)bmpi(}!D&-`k_`JGN2mz8 z-cp%EByo@Mhkr1;RHxRU^&9YykP*HJnR^B7T1Ha;A<^i!p_nh$zAL3f4M`lWR#H^E z4q=QQ)2}gBJ0h1Ia-}=d*j%fQr#@V1GnAqCPs))9gLCI^Zi2%2%>M~@(j1ymX@ybK zqI-fylCoe5#3`V!k>z+DdMyFz_7nIGHYT|EZMKV+ zOU%KsfL&EQx?B_rgbsx9JeQe0P}OZ(wB-sL5DQ2K-2ini2)gF(eIj?G+GTVl$pU&I zbPYxyG^d1?P>bGsp-`jA?2N&6$EGoVvIgjTu(%JAgS5n$YMxW7wO6N7c?VbacOAn@ zF;+}1{y^tuyNx1sV1M77%dEUIl@w#Hf{ju2@n$-hAafF4`E)yJRyXZnoO~RRRLmbt zs4X!`>GiRyzETymC=L~6p3&N|>gVPU(AS*jdQUyGO{`09-3*ZEH*1#!mQELNjR-oZ zUGX+=68^vDt~?sb_Wg?x*~${KOpzswF~*p&6C#vk-)GEVEHliE7&}?gtJfZ~i$p>S z*^|92A%v0jwI#bDTi@yX{k`XWJHLMCynp_l^DO7w_jO;_b>GkDx}N8p`?~I1y3LuG z!ZjWFCdV;a)26VxusK&wKd$1&)wojDHFmsp3PAPQxeE4M`3=2HBvY@UN5Gau;@)sB zM^p$nfwc!|3DH{%?zA>n(2yytG;8cx-ki(j>3+WyI*J8`qY$V4b$mCtgLUPXUi+!> z$DTsgNh{C2S_V*?-7G0YR(nsN9CxvS=u`*tlZm{khd#*4%C-=*o?B8k~ zvY9!iJ8dWs{TtXQ{6pA4;lIx0dYT&HW-IpZdDd~ zhKlF)jn71%9PVD^EHziP{w4vXYJN zoK+ihSeY}f;bhwiP!$kd?j$T|P`FXaJDrrpI`^D3zxhmM$4PUmQO8&Ur11t~=r%bI z`~0LN`dc3Ge4?2T+;(co3c98i-*BwLUOo0Y8fXn1+vyd|jy_3(sA&(SHdO{q23H)G z50VEccqKs@6iDcWd1)o1#X#?m26yR<6WH9t?GsX^;b8qn-TSi2#i6p-$7RPA1Bu(* zHazWDD?N9=8RBy))nmz@yuS;u7tW>7vCJx*(uHZ{KEAISPowc*LsE>ff+m-#3r6#a zqn42?^j*7&AHXM6yUv!w4NRk#8bwo*_t8A8rIr?S&EL>&pXD90!ikumPbPN24!~G>PF1O(t_Aq`3f#_MiEv7;-hC++)yeksroc4(9HVXO@Ei|&AJaE^(QMV z7H12*yW$g{NTmwph)_~^7&d!4-P^vuqbIV6`ILAB0V(H=?*(-7Zw)?z(S^}3si#{1hxat+Bntpt=kbSTIMloA|SbzCl z+EMb?7FG9iM}y$~LbDBn{%{8+w%}#a{lcN?)R7k1EXL+omf&=q4Jl5==A{q$vP?fb zR`VtXC1iuvDNHg_)|{3cKJK`~)lXURI_lODa|`Vg2Ir0$y}#XS`;7rW|FHom{OULV ze;7bf(s7|0n~(C$bkk_-fOoKxGnIU7_k zMR28hr5yQLXz=nSE3?$r-G|xeIUrs4ME|y9hEc#${$GhkQ{)-alDhuPHAv91)WqmF z#`+)mJy{;IMMDEx^m7Al?NpLo!Z_#~`SkDpvAli7gykzxifZDek6YJyb z7iHiMFVVM4FHe|H^@;9D9=3KF38waM8Y|hu-vaD89V6&Ym&AOgW1=ZIlY_+5oTYgj z8cV0anh>CIO2Sq;lF@`wuiyiHo)}#y5pyP&pV^a}H&cp6zM%6{WIsTfL0R`gy6DG* z&;);7+9=%%jb~ahJ!oy-J_(v_P^M;`90FF+>Xm*v7u#BEBV6ta6)vwo zs`*;p=T)V_AI%~Oufs2I!jTRb1V?{hgYK%#$B)yA5>J&zze}WIZ|jv;w^P|DfJJB{bnQ->iQXyX(E;G@JW0metC@zLRhNea59c2R`9e&lHk_ zWS^=%z&;>z-}Ji4G2fnVWRu*k$@y2Ek#S+-ZRcqHZZt-OMCvQ2KTU8A4~ET!su_;P^x=xPBK~TJW+rF?HU@n214p*!nb~df5m@@e?cPiNHL*zrm+KV{@E7dJJ^Gd`8$Te;->ptJ1o{`T+4{NV9 z8;x2R9k;cKERuOfeA1!feoOb3br>`Le9vZPclUyv2RkM#zO?kg3>ZJv-YvwygHu0f z$%O9aF+DPX22~{;e++^}vbXHiN*P%Uudklyre}?1Pf%QQ!#5qPkcIHiQ6q=tlid}| zz6|BbHE|=L<&JPuZX?XWU5hlVMRSH@_xA@f+kxC^bw@a09`|9Zo{@A)|0Z{dE4MV- z^=0hsX`TsMv1>+=wK5U4?dQ0q*&e;DfZZ;0^sX=jr5Cui(fdp682|AVXg>N3kRJEo zL390Depd8Z={Z;FD{*00hVw$BBNR4bH~3-sf-o<`&%3p&t0P)PT!Xu!oZhkQ9mT@3 zpuQtmyWeq)I(}<{-|roX<5Hj2+k2|rr!CK4IEdJOyUX&K6kj|CV+Y?e*Bs6D>bjg) zN1Hul-Rb?sZvjSRboV>gmvMjEA-=DcfyYN$*OHTDcVgk2d6&AMu?1@#u>_qTTwXKr9*o&G zeYdEqpL3D>fcz}I|KWo`tm!J@$@!d%g@ITuw2o$6ouBVf&!T=%A7e*O<*AUzQw#ck zl#>Rx+_Q;G+XXIax0JR>gD?A&ZU$!WkQeo31G8UK3&t1qi>OuGq(S!_@vK9YLh_;{ zx7w}Z9nuY#QDs7N;GRL}M1=3o!3y_c*(>(^0FTLQ(c)z#y}PQ|44&uYPSyFjDF)qs z(gyqH_A}$(7|Vazilz_I6^92%NCIT9;n4^p28Y!~5YYe$Z6z=WtN?<7K_Hj{OhMlI zZ;GGPh6q!%CBPR$bOpGQywG?&+L>ByfF}9k@F>E+xf$V5|2HFJQyoj7u8)TY5`o2{ zsSHhBF$4hh^g=mPIZFe~(Rcz?6@WZY4kD)j2SXL)WxznFj2sXG0)n9cTZx|v7-H_C z0aP_1wvqsMF9gw*fJOlB{!ddV5CQ~IwKB%zP(DsSh5U#4-#n;QcYKg;XeZ*o^)`!x0ED7%2~tSAZko)Rkc2NR%_e2@aM=D4^gFxS9$G zj)24DpfC^&?gWQI5D+I290^jCbArmtp`9V}YIeW4J|`p%tyo9QSH3h}UKw5*X5Ld_ f{~IfSUk_#i5rHTAQQtQ+SPsg3<%-TNUFLrQ<)mCh diff --git a/docs/src/man/img/Fmove_MD.svg b/docs/src/man/img/Fmove_MD.svg new file mode 100644 index 0000000..3cf3b0e --- /dev/null +++ b/docs/src/man/img/Fmove_MD.svg @@ -0,0 +1,601 @@ + + + + diff --git a/docs/src/man/img/Nsymbol_coloring.pdf b/docs/src/man/img/Nsymbol_coloring.pdf deleted file mode 100644 index 079bb95e6428cc6ed87e202b853e8f6b679330f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37275 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 S0OOm>$k2>SRn^tsjSB$(4jgU( diff --git a/docs/src/man/img/Nsymbol_coloring.svg b/docs/src/man/img/Nsymbol_coloring.svg new file mode 100644 index 0000000..2409403 --- /dev/null +++ b/docs/src/man/img/Nsymbol_coloring.svg @@ -0,0 +1,1456 @@ + + + + diff --git a/docs/src/man/img/homvector.pdf b/docs/src/man/img/homvector.pdf deleted file mode 100644 index 7df9b5d0b343de559dfcef272e4050013fbf081e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38810 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 + + + diff --git a/docs/src/man/img/qdim_fs_MF.pdf b/docs/src/man/img/qdim_fs_MF.pdf deleted file mode 100644 index 79d23d9ee6ea62711b147aa256ff5ff0b853beb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30636 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 diff --git a/docs/src/man/img/qdim_fs_MF.svg b/docs/src/man/img/qdim_fs_MF.svg new file mode 100644 index 0000000..24c186e --- /dev/null +++ b/docs/src/man/img/qdim_fs_MF.svg @@ -0,0 +1,545 @@ + + + + From 03b9d542636e778abb85563e14c247b79be81234 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 20 Jun 2025 15:41:12 +0200 Subject: [PATCH 096/206] change image display --- docs/src/man/fusioncats.md | 8 ++++++-- docs/src/man/multifusioncats.md | 32 ++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index e4b848d..62a984f 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -25,12 +25,16 @@ To extend the fusion ring to the **fusion category**, we need to add the followi This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C}, F)$ of $\mathcal{C}$ defining its monoidal product, unit object and monoidal associator, the latter also commonly called the **F-symbol**. In particular, the simple objects have their respective quantum dimensions $d_i = \dim(X_i)$ which form their own one-dimensional representation of the fusion algebra: $d_i d_j = \sum_k N_{ij}^k d_k$. In particular, the unit object always has quantum dimension 1, and all other quantum dimensions are larger or equal to one. These quantum dimensions are encoded in the F-symbol. The isomorphisms instead of the equalities are a technical detail, so we drop that notation. Vectors in these hom-spaces are graphically denoted as living in the trivalent junction +```@raw html + +``` -![homvector](img/homvector.pdf) With the F-symbol, we can perform F-moves: -![Fmove](img/Fmove.pdf) +```@raw html + +``` TensorKit requires the F-symbols to be unitary. This way, we can interpret the F-symbol $F^{ijk}_l$ as a unitary matrix, and the F-move as a unitary basis transformation. Unitarity is also useful from a diagrammatic point of view because the category is then equipped with a pivotal and spherical structure. This essentially means that morphisms can be drawn and moved around freely on a 2-sphere, such that vector spaces can be moved freely from domain (codomain) to codomain (domain). diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 2c212c8..118a1e3 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -7,7 +7,9 @@ We will mostly use the notation in [Lootens et al.](@cite Lootens_2023) for fusi $${}^\mathcal{D}\!F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) \rightarrow (\alpha \otimes \beta) \otimes \gamma$$ the **monoidal associator**. An F-move is now graphically portrayed as: -![Fmove_D](img/...) +```@raw html + +``` We can consider the **right module category** $\mathcal{M}$ over $\mathcal{D}$, which is a category (not necessarily fusion!) with (isomorphism classes of) simple objects $\mathcal{I}_\mathcal{M} = \{A,B,...\}$, a right action $$\triangleleft: \mathcal{M} \times \mathcal{D} \rightarrow \mathcal{M}$$ @@ -15,7 +17,9 @@ and the **right module associator** $${}^\triangleleft\!F^{A\alpha\beta}: A \triangleleft (\alpha \otimes \beta) \rightarrow (A \triangleleft \alpha) \triangleleft \beta.$$ An F-move with this module associator can be expressed as: -![Fmove_MD](img/Fmove_MD.pdf) +```@raw html + +``` The module structure of $\mathcal{M}$ is now defined as the triple $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$. The right module associator now satisfies a mixed pentagon equation with ${}^\mathcal{D}\!F$. @@ -25,13 +29,17 @@ while the **left module associator** is a natural isomorphism that acts as $${}^\triangleright\!F^{abA}: (a \otimes b) \triangleright A \rightarrow a \triangleright (b \triangleright A)$$ for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. The left module associator also fulfills a mixed pentagon equation with ${}^\mathcal{C}\!F$. An F-move with ${}^\mathcal{C}\!F$ takes on the form: -![Fmove_CM](img/Fmove_CM.pdf) +```@raw html + +``` We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, and $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as $${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F^{aA\alpha}: (a \triangleright A) \triangleleft \alpha \rightarrow a \triangleright (A \triangleleft \alpha)$$ for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. The bimodule associator fulfills a mixed pentagon equation with the module associators. An F-move with ${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F$ is given by: -![Fmove_CMD](img/Fmove_CMD.pdf) +```@raw html + +``` ## Opposite module categories Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). Then $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. A similar statement can be made starting from a left module category and getting an opposite right module category. In particular, given a $(\mathcal{C}, \mathcal{D})$-bimodule category $\mathcal{M}$ over the fusion categories $\mathcal{C}, \mathcal{D}$, we see immediately that $\mathcal{M}^{\text{op}}$ is a $(\mathcal{D}, \mathcal{C})$-bimodule category. @@ -72,7 +80,9 @@ Multifusion categories can also be interpreted as 2-categories. We still interpr The simplest non-trivial fusion diagram is a trivalent junction: -![Nsymbol_coloring](img/Nsymbol_coloring.pdf) +```@raw html + +``` The most general case is the top left figure, where all three regions have a different coloring. The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. However, as will be explained more in detail later, this most general trivalent junction with three colorings will never be needed. In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. This is displayed in the top middle and right. Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. This is shown in the bottom right. @@ -86,7 +96,9 @@ Linear algebra tells us that given a (finite-dimensional) vector space $V$ with In principle, choosing to bend e.g. codomain legs to the right and domain legs to left is an arbitrary choice, but would require to distinguish between left and right transposes. However, TensorKit.jl is implemented in a way that does not differentiate the two. In particular, we do not have to worry about this when considering categorical symmetries where, in principle, the left and right dual of an object are not equivalent. This is because this left-right symmetry is guaranteed when considering unitary fusion categories, which is what is done in TensorKit and necessarily in MultiTensorKit. For this reason, at the level of the fusion trees the topological move that is performed to bend the legs along the right is called a **B-move**. Graphically, one can show that this bend boils down to a particular F-move. The typical equation found in the literature is the following: -![Bmove_lit](img/Bmove_lit.pdf) +```@raw html + +``` ... The reason to only consider B-moves is rooted in the choice of canonical form of fusion trees within TensorKit, where fusions are iterated over from left to right and splittings from right to left. @@ -94,13 +106,17 @@ Importantly, we identify the dual vector space labeled by a module category with $$\mathcal{M}^* \simeq \mathcal{M}^\text{op}.$$ In the multifusion setting, this can also be seen graphically. By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: -![Bmove_MF](img/Bmove_MF.pdf) +```@raw html + +``` where by $\mathbb{1}_a$ we mean the right unit of $a$ (the left unit we would denote $^{}_a \mathbb{1}$). Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{a \bar{a} a}_{a}$ needs to be evaluated for these topological data. Graphically, we find that -![qdim_fs_MF](img/qdim_fs_MF.pdf) +```@raw html + +``` need to show other changed expressions like A-move, dimension, frobenius-schur indicator, what else outside of TensorKitSectors in terms of fusion tree manipulations? From f40e8ad35fd82f1a6e0b6955d5f4effd454bca79 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 20 Jun 2025 16:14:13 +0200 Subject: [PATCH 097/206] some more image fixes --- docs/src/man/fusioncats.md | 2 +- docs/src/man/multifusioncats.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 62a984f..28e29bf 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -26,7 +26,7 @@ This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C} Vectors in these hom-spaces are graphically denoted as living in the trivalent junction ```@raw html - + ``` diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 118a1e3..5a8963a 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -115,7 +115,7 @@ where by $\mathbb{1}_a$ we mean the right unit of $a$ (the left unit we would de Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{a \bar{a} a}_{a}$ needs to be evaluated for these topological data. Graphically, we find that ```@raw html - + ``` need to show other changed expressions like A-move, dimension, frobenius-schur indicator, what else outside of TensorKitSectors in terms of fusion tree manipulations? From 70cc3bffd46b3e919c59fcfc3d826a994b0062c8 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 20 Jun 2025 16:31:07 +0200 Subject: [PATCH 098/206] clean up existing docs --- docs/src/man/fusioncats.md | 12 +++++------ docs/src/man/multifusioncats.md | 37 +++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 28e29bf..689ec9d 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -7,7 +7,7 @@ Afterwards, the extension to multifusion categories is explained, and its relati # Fusion category theory -The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [TensorKit documentation](https://jutho.github.io/TensorKit.jl/stable/man/categories/) or the book Tensor Categories ([etingof2016tensor](@cite)). +The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [TensorKit documentation](https://jutho.github.io/TensorKit.jl/stable/man/categories/) or the book Tensor Categories [etingof2016tensor](@cite). Let us start simple and introduce the **fusion ring** $\mathcal{C}$ in a black-box manner. This ring * consists of finitely many simple objects $\{ X_1, X_2, ..., X_R \}$, with $R$ the rank of the fusion ring, @@ -19,8 +19,8 @@ To extend the fusion ring to the **fusion category**, we need to add the followi * Consider only the representatives of isomorphism classes of simple objects $\mathcal{I}_\mathcal{C}$, * The associator $F^{X_iX_jX_k}: (X_i \otimes X_j) \otimes X_k \xrightarrow{\sim} X_i \otimes (X_j \otimes X_k)$ which fulfills the famous pentagon equation, -* Morphisms between (simple) objects $\text{\text{Hom}}_\mathcal{C}(X_i, X_j)$, which are empty vector spaces unless the objects are isomorphic, the latter then giving $\mathbb{C}$, -* More general morphisms $\text{\text{Hom}}_\mathcal{C}(X_i \otimes X_j, X_k) \cong \mathbb{C}^{N_{ij}^k}$. +* Morphisms between (simple) objects $\text{Hom}_\mathcal{C}(X_i, X_j)$, which are empty vector spaces unless the objects are isomorphic, the latter then giving $\mathbb{C}$, +* More general morphisms $\text{Hom}_\mathcal{C}(X_i \otimes X_j, X_k) \cong \mathbb{C}^{N_{ij}^k}$. This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C}, F)$ of $\mathcal{C}$ defining its monoidal product, unit object and monoidal associator, the latter also commonly called the **F-symbol**. In particular, the simple objects have their respective quantum dimensions $d_i = \dim(X_i)$ which form their own one-dimensional representation of the fusion algebra: $d_i d_j = \sum_k N_{ij}^k d_k$. In particular, the unit object always has quantum dimension 1, and all other quantum dimensions are larger or equal to one. These quantum dimensions are encoded in the F-symbol. The isomorphisms instead of the equalities are a technical detail, so we drop that notation. @@ -45,9 +45,9 @@ Colloquially speaking, category theory attempts to generalise mathematical struc |$\mathsf{VecG}$|$\mathsf{RepG}$|Categorical generalisation| |:---:|:---:|:---:| -|$G$-graded vector spaces $V_1, V_2, ...$|Representations of $G$
$(V_1, \pi_1), (V_2, \pi_2), ...$|Objects| -|$G$-graded preserving linear maps
$\phi: V \rightarrow W$|Intertwiners $f: V_1 \rightarrow V_2$,
$f \circ \pi_1 = \pi_2 \circ f$|Morphisms $\text{Hom}_\mathcal{C}$| -1d subspaces $\mathbb{C}_{g_1}, \mathbb{C}_{g_2}$:
$\text{Hom}_{\mathsf{VecG}}(\mathbb{C}_{g_1},\mathbb{C}_{g_2}) = \delta_{g_1g_2}$|Irreps: $\text{Hom}_{\mathsf{RepG}}(\rho_i,\rho_j) = \delta_{ij} \mathbb{C}$ (Schur)|Simple objects: $\text{Hom}_{\mathcal{C}}(a,b) = \delta_{ab}\mathbb{C}$| +|$G$-graded vector spaces $V_1, V_2, ...$|Representations of $G$ $(V_1, \pi_1), (V_2, \pi_2), ...$|Objects| +|$G$-graded preserving linear maps $\phi: V \rightarrow W$|Intertwiners $f: V_1 \rightarrow V_2$, $f \circ \pi_1 = \pi_2 \circ f$|Morphisms $\text{Hom}_\mathcal{C}$| +1d subspaces $\mathbb{C}_{g_1}, \mathbb{C}_{g_2}$: $\text{Hom}_{\mathsf{VecG}}(\mathbb{C}_{g_1},\mathbb{C}_{g_2}) = \delta_{g_1g_2}$|Irreps: $\text{Hom}_{\mathsf{RepG}}(\rho_i,\rho_j) = \delta_{ij} \mathbb{C}$ (Schur)|Simple objects: $\text{Hom}_{\mathcal{C}}(a,b) = \delta_{ab}\mathbb{C}$| $G$-graded tensor product $(V \otimes W)_g = \oplus_{hk=g} V_h \otimes W_k$| $\pi_i \otimes \pi_j \simeq \oplus_i N_{ij}^k\rho_k$ | Direct sum, monoidal product, fusion rules, multiplicity| $\mathbb{C}_1 \otimes W \simeq W \simeq W \otimes \mathbb{C}_1$ | Trivial rep 1: $1 \otimes \rho = \rho = \rho \otimes 1$ | Monoidal unit $1_\mathcal{C}$ $\mathbb{C}_g \otimes \mathbb{C}_{g^{-1}} = \mathbb{C}_1 = \mathbb{C}_{g^{-1}} \otimes \mathbb{C}_g$ | $\pi \otimes \overline{\pi} = 1 \oplus ...$ | Dual object diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 5a8963a..b81b8e9 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -4,7 +4,9 @@ This section will explain how to go from a fusion category to a multifusion cate ## Module categories We will mostly use the notation in [Lootens et al.](@cite Lootens_2023) for fusion categories and module categories over these. We start from a fusion category $\mathcal{D}$ defined by the triple $(\otimes_\mathcal{D}, \mathbb{1}_\mathcal{D}, {}^\mathcal{D}\!F)$ with simple objects $\alpha, \beta, ... \in \mathcal{I}_\mathcal{D}$. We drop the $\mathcal{D}$ subscript when there is no ambiguity concerning the fusion category. We call its associator + $${}^\mathcal{D}\!F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) \rightarrow (\alpha \otimes \beta) \otimes \gamma$$ + the **monoidal associator**. An F-move is now graphically portrayed as: ```@raw html @@ -12,9 +14,13 @@ $${}^\mathcal{D}\!F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) ``` We can consider the **right module category** $\mathcal{M}$ over $\mathcal{D}$, which is a category (not necessarily fusion!) with (isomorphism classes of) simple objects $\mathcal{I}_\mathcal{M} = \{A,B,...\}$, a right action + $$\triangleleft: \mathcal{M} \times \mathcal{D} \rightarrow \mathcal{M}$$ + and the **right module associator** + $${}^\triangleleft\!F^{A\alpha\beta}: A \triangleleft (\alpha \otimes \beta) \rightarrow (A \triangleleft \alpha) \triangleleft \beta.$$ + An F-move with this module associator can be expressed as: ```@raw html @@ -24,9 +30,13 @@ An F-move with this module associator can be expressed as: The module structure of $\mathcal{M}$ is now defined as the triple $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$. The right module associator now satisfies a mixed pentagon equation with ${}^\mathcal{D}\!F$. Similarly, we can define a **left module category** $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ over a fusion category $(\otimes_\mathcal{C}, 1_\mathcal{C}, {}^\mathcal{C}\!F)$. The functor is now a left action of $\mathcal{C}$ on $\mathcal{M}$ + $$\triangleright: \mathcal{C} \times \mathcal{M} \rightarrow \mathcal{M},$$ + while the **left module associator** is a natural isomorphism that acts as + $${}^\triangleright\!F^{abA}: (a \otimes b) \triangleright A \rightarrow a \triangleright (b \triangleright A)$$ + for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. The left module associator also fulfills a mixed pentagon equation with ${}^\mathcal{C}\!F$. An F-move with ${}^\mathcal{C}\!F$ takes on the form: ```@raw html @@ -34,7 +44,9 @@ for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. The left module associator also ful ``` We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, and $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as + $${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F^{aA\alpha}: (a \triangleright A) \triangleleft \alpha \rightarrow a \triangleright (A \triangleleft \alpha)$$ + for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. The bimodule associator fulfills a mixed pentagon equation with the module associators. An F-move with ${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F$ is given by: ```@raw html @@ -44,34 +56,48 @@ for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \m Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). Then $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. A similar statement can be made starting from a left module category and getting an opposite right module category. In particular, given a $(\mathcal{C}, \mathcal{D})$-bimodule category $\mathcal{M}$ over the fusion categories $\mathcal{C}, \mathcal{D}$, we see immediately that $\mathcal{M}^{\text{op}}$ is a $(\mathcal{D}, \mathcal{C})$-bimodule category. Interestingly, due to the opposite actions + $$\triangleleft^{\text{op}}: \mathcal{D} \times \mathcal{M}^{\text{op}} \rightarrow \mathcal{M}^{\text{op}}$$ + and + $$\triangleright^{\text{op}}: \mathcal{M}^{\text{op}} \times \mathcal{C} \rightarrow \mathcal{M}^{\text{op}},$$ + there is a valid notion of multiplying a module category with its opposite: -$$ -\mathcal{M} \times \mathcal{M}^\text{op} \rightarrow \mathcal{C}, \quad \mathcal{M}^\text{op} \times \mathcal{M} \rightarrow \mathcal{D}. -$$ + +$$\mathcal{M} \times \mathcal{M}^{\text{op}} \rightarrow \mathcal{C}, \quad \mathcal{M}^{\text{op}} \times \mathcal{M} \rightarrow \mathcal{D}.$$ something something morita equivalence and invertible bimodule, maybe drinfeld center, maybe anyons, maybe domain walls ## Multifusion categories A fusion category has the important condition that $\mathsf{End}_\mathcal{C}(1_\mathcal{C}) \cong \mathbb{C}$, i.e., the unit of the fusion category is simple. If we drop this condition, then we consider a **multifusion category**. We assume the multifusion category itself to be indecomposable, meaning it is not the direct sum of two non-trivial multifusion categories. Let us call this multifusion category $\mathcal{C}$. It will be clear in a moment that this will not be ambiguous. Its unit can then be decomposed as -$$ 1_\mathcal{C} = \bigoplus_{i=1}^r 1_r,$$ + +$$1_\mathcal{C} = \bigoplus_{i=1}^r 1_r,$$ + i.e., it is decomposed into simple unit objects of the subcategories $\mathcal{C}_{ij} \coloneqq 1_i \otimes \mathcal{C} \otimes 1_j$. With this, we see that the multifusion category itself can be decomposed into its subcategories + $$\mathcal{C} = \bigoplus_{i,j=1}^r \mathcal{C}_{ij}.$$ + We call this an $r \times r$ multifusion category. We want to consider multifusion categories because **their structure encapsulates that of (bi-)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. In particular, the tensor product + $$\otimes_\mathcal{C}: \mathcal{C}_{ij} \times \mathcal{C}_{kl} \rightarrow \delta_{jk}\mathcal{C}_{il}$$ + takes on the same structure as the product of two matrix units. This is not a coincidence; there is a deep relation between multifusion categories and matrix algebras [etingof2016tensor; Section 4.3](@cite). Given a subcategory $\mathcal{C}_{ij}$, we can define the **left** unit as the unit object of the fusion category $\mathcal{C}_i$, while the **right** unit is the unit object of the fusion category $\mathcal{C}_j$. In other words, the left unit of $\mathcal{C}_{ij}$ is the unique object of the multifusion category $\mathcal{C}$ for which + $$1_i \otimes_\mathcal{C} M_{ij} = M_{ij} \quad \forall M_{ij} \in \mathcal{C}_{ij},$$ + and similarly for the right unit of $\mathcal{C}_{ij}$, + $$M_{ij} \otimes_\mathcal{C} 1_j = M_{ij} \quad \forall M_{ij} \in \mathcal{C}_{ij}.$$ We can also immediately see that for a (bi)module subcategory $\mathcal{C}_{ij}$, the opposite (bi)module subcategory $\mathcal{C}_{ij}^{\text{op}} \equiv \mathcal{C}_{ji}$, and as expected, + $$\mathcal{C}_{ij} \times \mathcal{C}_{ji} \rightarrow \mathcal{C}_i,$$ + just like what we concluded when considering opposite module categories outside of the multifusion structure. ### 2-category and coloring diagrammatic calculus with coloring and such and so @@ -103,7 +129,9 @@ For this reason, at the level of the fusion trees the topological move that is p ... The reason to only consider B-moves is rooted in the choice of canonical form of fusion trees within TensorKit, where fusions are iterated over from left to right and splittings from right to left. Importantly, we identify the dual vector space labeled by a module category with a vector space labeled by the opposite module category. Consequently, + $$\mathcal{M}^* \simeq \mathcal{M}^\text{op}.$$ + In the multifusion setting, this can also be seen graphically. By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: ```@raw html @@ -129,4 +157,5 @@ generalisation to Tambara-Yamagami where to say something about rewriting mpskit to be planar such that braidings with module legs are avoided? Without specifying any of the categories, the simplest non-trivial multifusion category is a $2\times 2$ one, and the categories can be organised in a matrix as + $$\mathcal{C} = \begin{pmatrix} \end{pmatrix}$$ \ No newline at end of file From 7222cc86905ffc1a414f2689ce744ffb96a11cf5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 20 Jun 2025 16:31:45 +0200 Subject: [PATCH 099/206] use math engine --- docs/make.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index fb3f7bb..6ec1264 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -6,13 +6,20 @@ pages = ["Home" => "index.md", "Library" => "lib/library.md", "Manual" => ["man/fusioncats.md", "man/multifusioncats.md"], "References" => "references.md"] - # bibliography bibpath = joinpath(@__DIR__, "src", "assets", "MTKrefs.bib") bib = CitationBibliography(bibpath; style=:authoryear) -makedocs(; sitename="MultiTensorKit Documentation", modules=[MultiTensorKit], +mathengine = MathJax3(Dict(:loader => Dict("load" => ["[tex]/physics"]), + :tex => Dict("inlineMath" => [["\$", "\$"], ["\\(", "\\)"]], + "tags" => "ams", + "packages" => ["base", "ams", "autoload", "physics", + "mathtools"]))) + +makedocs(; sitename="MultiTensorKit.jl", modules=[MultiTensorKit], + # assets=["assets/custom.css"], authors="Boris De Vos, Laurens Lootens and Lukas Devos", - pages=pages, pagesonly=true, plugins=[bib]) + pages=pages, pagesonly=true, plugins=[bib], + format=Documenter.HTML(; mathengine=mathengine)) deploydocs(; repo="https://github.com/QuantumKitHub/MultiTensorKit.jl") \ No newline at end of file From a5499434cb4b46cd8f52888b5519fe2cc2394960 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 26 Jun 2025 14:27:43 +0200 Subject: [PATCH 100/206] update code to account for new N- and F-symbols --- src/bimodulesector.jl | 77 +++++++++++++++++++++++-------------------- test/test_A4.jl | 7 ++-- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index e885822..2eea4da 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -3,7 +3,8 @@ struct BimoduleSector{Name} <: Sector j::Int label::Int function BimoduleSector{:A4}(i::Int, j::Int, label::Int) - i <= 12 && j <= 12 || throw(DomainError("object outside the matrix A4")) + i <= size(BimoduleSector{:A4}) && j <= size(BimoduleSector{:A4}) || + throw(DomainError("object outside the matrix A4")) return label <= _numlabels(BimoduleSector{:A4}, i, j) ? new{:A4}(i, j, label) : throw(DomainError("label outside category A4($i, $j)")) end @@ -21,12 +22,15 @@ function Base.convert(::Type{BimoduleSector{Name}}, d::NTuple{3,Int}) where {Nam return BimoduleSector{Name}(d...) end +Base.size(::Type{A4Object}) = 7 + Base.IteratorSize(::Type{<:SectorValues{<:BimoduleSector}}) = Base.SizeUnknown() # TODO: generalize? function Base.iterate(iter::SectorValues{A4Object}, (I, label)=(1, 1)) - I > 12 * 12 && return nothing - i, j = CartesianIndices((12, 12))[I].I + s = size(A4Object) + I > s * s && return nothing + i, j = CartesianIndices((s, s))[I].I maxlabel = _numlabels(A4Object, i, j) return if label > maxlabel iterate(iter, (I + 1, 1)) @@ -36,7 +40,8 @@ function Base.iterate(iter::SectorValues{A4Object}, (I, label)=(1, 1)) end function Base.length(::SectorValues{A4Object}) - return sum(_numlabels(A4Object, i, j) for i in 1:12, j in 1:12) + s = size(A4Object) + return sum(_numlabels(A4Object, i, j) for i in 1:s, j in 1:s) end TensorKitSectors.FusionStyle(::Type{A4Object}) = GenericFusion() @@ -60,21 +65,22 @@ end const artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.3") function extract_Nsymbol(::Type{A4Object}) - filename = joinpath(artifact_path, "A4", "Nsymbol.json") - isfile(filename) || throw(LoadError(filename, 0, "Nsymbol file not found for $Name")) - json_string = read(filename, String) - Narray = copy(JSON3.read(json_string)) - return map(reshape(Narray, 12, 12, 12)) do x - y = Dict{NTuple{3,Int},Int}() - for (k, v) in x - a, b, c = parse.(Int, split(string(k)[2:(end - 1)], ", ")) - y[(a, b, c)] = v - end - return y + filename = joinpath(artifact_path, "A4", "Nsymbol.txt") + isfile(filename) || throw(LoadError(filename, 0, "Nsymbol file not found for A4")) + Narray = readdlm(filename) # matrix with 7 columns + + data_dict = Dict{NTuple{3,Int},Dict{NTuple{3,Int},Int}}() + for row in eachrow(Narray) + i, j, k, a, b, c, N = Int.(@view(row[1:size(A4Object)])) + colordict = get!(data_dict, (i, j, k), Dict{NTuple{3,Int},Int}()) + push!(colordict, (a, b, c) => N) end + + return data_dict end -const Ncache = IdDict{Type{<:BimoduleSector},Array{Dict{NTuple{3,Int},Int},3}}() +const Ncache = IdDict{Type{<:BimoduleSector}, + Dict{NTuple{3,Int},Dict{NTuple{3,Int},Int}}}() function _get_Ncache(::Type{T}) where {T<:BimoduleSector} global Ncache @@ -102,7 +108,7 @@ end function extract_dual(::Type{A4Object}) N = _get_Ncache(A4Object) - ncats = size(N, 1) + ncats = size(A4Object) Is = zeros(Int, ncats) map(1:ncats) do i @@ -175,24 +181,22 @@ end function extract_Fsymbol(::Type{A4Object}) result = Dict{NTuple{4,Int},Dict{NTuple{6,Int},Array{ComplexF64,4}}}() - for i in 1:12 - filename = joinpath(artifact_path, "A4", "Fsymbol_$i.txt") - @assert isfile(filename) "cannot find $filename" - Farray_part = readdlm(filename) - for ((i, j, k, l), colordict) in convert_Fs(Farray_part) - result[(i, j, k, l)] = Dict{NTuple{6,Int},Array{ComplexF64,4}}() - for ((a, b, c, d, e, f), Fvals) in colordict - a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), - (k, l, c), (i, l, d), - (i, k, e), (j, l, f))) - result[(i, j, k, l)][(a, b, c, d, e, f)] = zeros(ComplexF64, - Nsymbol(a_ob, b_ob, e_ob), - Nsymbol(e_ob, c_ob, d_ob), - Nsymbol(b_ob, c_ob, f_ob), - Nsymbol(a_ob, f_ob, d_ob)) - for (I, v) in Fvals - result[(i, j, k, l)][(a, b, c, d, e, f)][I] = v - end + filename = joinpath(artifact_path, "A4", "Fsymbol.txt") + @assert isfile(filename) "cannot find $filename" + Farray = readdlm(filename) + for ((i, j, k, l), colordict) in convert_Fs(Farray) + result[(i, j, k, l)] = Dict{NTuple{6,Int},Array{ComplexF64,4}}() + for ((a, b, c, d, e, f), Fvals) in colordict + a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), + (k, l, c), (i, l, d), + (i, k, e), (j, l, f))) + result[(i, j, k, l)][(a, b, c, d, e, f)] = zeros(ComplexF64, + Nsymbol(a_ob, b_ob, e_ob), + Nsymbol(e_ob, c_ob, d_ob), + Nsymbol(b_ob, c_ob, f_ob), + Nsymbol(a_ob, f_ob, d_ob)) + for (I, v) in Fvals + result[(i, j, k, l)][(a, b, c, d, e, f)][I] = v end end end @@ -254,7 +258,8 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where dom = domain(W) if N₁ == 0 && Nβ‚‚ == 0 # 0x0-dimensional TensorMap is just a scalar, return all units # this is a problem in full contractions where the coloring outside is π’ž - return NTuple{12,A4Object}(one(A4Object(i, i, 1)) for i in 1:12) # have to return all units b/c no info on W in this case + return NTuple{size(A4Object),A4Object}(one(A4Object(i, i, 1)) + for i in 1:size(A4Object)) # have to return all units b/c no info on W in this case elseif N₁ == 0 @assert Nβ‚‚ != 0 "one of Type A4Object doesn't exist" return filter!(isone, collect(blocksectors(dom))) diff --git a/test/test_A4.jl b/test/test_A4.jl index 2d6afd3..652f1c7 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -3,6 +3,7 @@ using TensorKitSectors, TensorKit using Test, TestExtras I = A4Object +s = size(A4Object) @testset "Basic type properties" verbose = true begin Istr = TensorKitSectors.type_repr(I) @@ -10,7 +11,7 @@ I = A4Object @test eval(Meta.parse(TensorKitSectors.type_repr(I))) == I end -@testset "Fusion Category $i" for i in 1:12 +@testset "Fusion Category $i" for i in 1:s objects = A4Object.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) @testset "Basic properties" begin @@ -63,7 +64,7 @@ end end end -@testset "A4 Category ($i, $j) units and duals" for i in 1:12, j in 1:12 +@testset "A4 Category ($i, $j) units and duals" for i in 1:s, j in 1:s Cij_obs = A4Object.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) s = rand(Cij_obs, 1)[1] @@ -76,7 +77,7 @@ end @test dual(dual(s)) == s end -@testset "A4 Category ($i, $j) left and right units" for i in 1:12, j in 1:12 +@testset "A4 Category ($i, $j) left and right units" for i in 1:s, j in 1:s Cij_obs = A4Object.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) s = rand(Cij_obs, 1)[1] From f8c00de163e327d0cc6f8ad0550c5d81cf459288 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 26 Jun 2025 17:22:50 +0200 Subject: [PATCH 101/206] more text --- docs/src/man/Implementation.md | 92 ++++++++++++++++++++++++++++++++- docs/src/man/fusioncats.md | 2 +- docs/src/man/multifusioncats.md | 31 +++++++++-- 3 files changed, 117 insertions(+), 8 deletions(-) diff --git a/docs/src/man/Implementation.md b/docs/src/man/Implementation.md index 515c20b..1158530 100644 --- a/docs/src/man/Implementation.md +++ b/docs/src/man/Implementation.md @@ -1,2 +1,90 @@ -need to explain the label=1 thing not being the unit -explain the f-symbol and n-symbol storage system \ No newline at end of file +explain the f-symbol and n-symbol storage system + +# MultiTensorKit implementation: $\mathsf{Rep_{A_4}}$ as an example +This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate ... (not sure yet what we're going to show here). + +This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep_{A_4}}$. Since there are 12 module categories (technically only 8 up to equivalence), `A4Object` is a $r=12$ multifusion category. There are 3 fusion categories up to equivalence: +- $\mathsf{Vec A_4}$: the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$. It has thus 12 objects. +- $\mathsf{Rep_{A_4}}$: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. One is the trivial representation, two are one-dimension non-trivial and the last is three-dimensional. +- $\mathsf{Rep H}$: the representation category of some Hopf algebra which does not have a name. It has 6 simple objects. + +````julia +using TensorKit, MultiTensorKit, MPSKit, MPSKitModels +```` + +## Identifying the simple objects +We first need to select which fusion category we wish to use to grade the physical Hilbert space, and which fusion category to represent e.g. the symmetry category. Say we choose $\mathcal{D} = \mathsf{Vec A_4}$ for the physical Hilbert space and $\mathcal{C} = \mathcal{D}^*_{\mathcal{M}} = \mathsf{Rep_{A_4}}$ the symmetry category. This fixes the module category $\mathcal{M} = \mathsf{Vec}$. When referring to specific fusion and module categories, we will use this non-multifusion notation. + +The easiest way to identify which elements of the multifusion category correspond to the subcategories we wish to use is ... (not sure yet how to do this yet) + +Once we have identified the fusion and module categories, we now want to select the relevant objects we wish to place in our graded spaces. Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. Hence, the simplest way to find the unit object of a fusion subcategory is + +````julia +one(A4Object(i,i,1)) +```` + +Left and right units of subcategories are uniquely specified by their fusion rules. For example, the left unit of a subcategory $\mathcal{C}_{ij}$ is the simple object in $\mathcal{C}_i$ for which + +$$ ^{}_a \mathbb{1} \times a = a \quad \forall a \in \mathcal{C}_i.$$ + +A similar condition uniquely defines the right unit of a subcategory. For fusion subcategories, a necessary condition is that the left and right units coincide. + +Identifying the other simple objects of a (not necessarily fusion) category requires more work. We recommend a combination of the following to uniquely determine any simple object `a`: +- Check the dimension of the simple object: `dim(a)` +- Check the dual of the simple object: `dual(a)` +- Check how this simple object fuses with other (simple) objects: `Nsymbol(a,b,c)` + +The dual object of some simple object $a$ of an arbitrary subcategory $\mathcal{C}_{ij}$ is defined as the unique object $a^* \in \mathcal{C}_{ji}$ satisfying + +$$ ^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* \times a,$$ + +with multiplicity 1. +## Matrix product state simulations with MPSKit +TensorKit has been made compatible with the multifusion structure by keeping track of the relevant units in the fusion tree manipulations. With this, we can make `GradedSpace`s whose objects are in `A4Object`. With our example in mind, we first select the objects: + +````julia +D0 = one(A4Object(2,2,1)) # unit object of VecA4 +D1 = A4Object(2,2,2) # some self-dual object of VecA4 + +M = A4Object(1,2,1) # Vec + +C0 = one(A4Object(1,1,1)) # unit object of RepA4 +C1 = A4Object(1,1,1) # non-trivial 1d irrep +```` + +Afterwards, we build the physical and virtual space of the matrix product state: +````julia +P = Vect[A4Object](D0 => 1, D1 => 1) +V = Vect[A4Object](M => D) # D is the bond dimension +```` +### Infinite case +Now, using MPKSit, we can perform matrix product state calculations. We construct some nearest-neighbour Hamiltonian and find the MPS representation of the ground state. +````julia +h = ones(ComplexF64, P βŠ— P ← P βŠ— P) +H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(1))) +init = InfiniteMPS([P], [V]) + +gs, envs = find_groundstate(init, H, VUMPS()) +```` + +Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `Sector`. + +A couple of MPSKit functions require an additional keyword argument `sector` (note the lowercase "s") specifying which sector to target within the function. These are: +- `transfer_spectrum`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D}$), the sectors lie in the symmetry category $\mathcal{C}$. +- `correlation_length`: since this function calls `transfer_spectrum`, the same logic applies. +- `excitations` with `QuasiparticleAnsatz`: similar to the previous functions, charged excitations are selected by adding a charged auxiliary space to the eigenvectors representing the quasiparticle states. + +### Finite case +There are minor differences to pay attention to when simulating matrix product states with a finite length. The first noticeable difference is in the `FiniteMPS` constructor itself to build an initial state. We must pass on a left and right virtual space to the keyword arguments `left` and `right`, since these would by default try to place a trivial space of the `Sector`, which does not exist for `BimoduleSector` due to the semisimple unit. Performing parallel calculations to the previous section now looks like + +````julia +L = 10 # length of the MPS +init = FiniteMPS(L, P, V; left=V, right=V) # put Vec on the boundaries as well +H = @mpoham sum(h{i,j} for (i,j) in nearest_neighbours(FiniteChain(L))) + +gs, envs = find_groundstate(init, H, DMRG()) +```` + +`DMRG2` will run in a similar manner. Additional `sector` keywords are present for the following: +- `exact_diagonalization`: the `sector` keyword argument now requires an object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. +- `excitations` with `QuasiparticleAnsatz`: see infinite case. \ No newline at end of file diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 689ec9d..cde99dc 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -53,7 +53,7 @@ $\mathbb{C}_1 \otimes W \simeq W \simeq W \otimes \mathbb{C}_1$ | Trivial rep 1: $\mathbb{C}_g \otimes \mathbb{C}_{g^{-1}} = \mathbb{C}_1 = \mathbb{C}_{g^{-1}} \otimes \mathbb{C}_g$ | $\pi \otimes \overline{\pi} = 1 \oplus ...$ | Dual object $F:(V \otimes W) \otimes U \xrightarrow{\sim}V \otimes (W \otimes U)$|$F: (\pi_1 \otimes \pi_2) \otimes \pi_3 \xrightarrow{\sim} \pi_1 \otimes (\pi_2 \otimes \pi_3)$|F-symbol| -# Fusion categories in condensed matter physics +## Fusion categories in condensed matter physics - String-net models -> non-chiral topological order classification - Kitaev's appendix E -> anyonic excitations - Golden chain, anyonic spin chains diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index b81b8e9..499cfec 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -78,7 +78,17 @@ i.e., it is decomposed into simple unit objects of the subcategories $\mathcal{C $$\mathcal{C} = \bigoplus_{i,j=1}^r \mathcal{C}_{ij}.$$ -We call this an $r \times r$ multifusion category. +We call this an $r \times r$ multifusion category. Due to this structure, we represent a simple object in the multifusion category "Name" by + +````julia +struct BimoduleSector{Name} <: Sector + i::Int + j::Int + label::Int +end +```` + +`i` and `j` specify which subcategory $\mathcal{C}_{ij}$ we are considering, and `label` selects a particular simple object within that subcategory. We want to consider multifusion categories because **their structure encapsulates that of (bi-)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. In particular, the tensor product @@ -100,8 +110,6 @@ $$\mathcal{C}_{ij} \times \mathcal{C}_{ji} \rightarrow \mathcal{C}_i,$$ just like what we concluded when considering opposite module categories outside of the multifusion structure. ### 2-category and coloring -diagrammatic calculus with coloring and such and so - Multifusion categories can also be interpreted as 2-categories. We still interpret the objects of this 2-category the same way. The 1-morphisms are the subcategories themselves, and the 2-morphisms the morphisms of the multifusion category. The graphical calculus of monoidal 1-categories can be extended to 2-categories by use of *colorings*. We have previously differed between module strands and fusion strands by the color of the strand itself. However, in 2-categories the strands (1-morphisms) separate regions which are colored based on the objects they are representing. Since we draw the strands vertically, a single strand results in a left and right region, and the colorings will determine the fusion category which fuses from the left or right with that single strand. In particular, fusion strands necessarily have the same coloring on the left and right, while module strands have a mismatching coloring. The simplest non-trivial fusion diagram is a trivalent junction: @@ -112,8 +120,9 @@ The simplest non-trivial fusion diagram is a trivalent junction: The most general case is the top left figure, where all three regions have a different coloring. The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. However, as will be explained more in detail later, this most general trivalent junction with three colorings will never be needed. In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. This is displayed in the top middle and right. Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. This is shown in the bottom right. +With this coloring system, we can specify which associator must be called to perform a particular F-move. SHOW THE COLORS + ### Why opposite module categories end up being necessary in MultiTensorKit -something something B-move of module leg One of the common manipulations which can act on a tensor map is the transposition of vector spaces. We will refer to this as the bending of legs. One of the elementary bends is the **right bend**, where one of the tensor legs is bent along the right from the codomain to the domain, or vice versa. At the level of the tensor, a covariant index becomes contravariant, or vice versa. Similarly, a **left bend** can also be performed, bending the leg along the left. This guarantees that legs will not cross, preventing braidings which require extra data known as R-symbols. @@ -158,4 +167,16 @@ where to say something about rewriting mpskit to be planar such that braidings w Without specifying any of the categories, the simplest non-trivial multifusion category is a $2\times 2$ one, and the categories can be organised in a matrix as -$$\mathcal{C} = \begin{pmatrix} \end{pmatrix}$$ \ No newline at end of file +$$\mathcal{C} = \begin{pmatrix} \mathcal{C}_1 & \mathcal{M} \\ \mathcal{M}^{\text{op}} & \mathcal{C}_2\end{pmatrix}.$$ + +We already identified the off-diagonal elements with module categories over the fusion categories on the diagonal. Accordingly, $\mathcal{M}$ is a $(\mathcal{C}_1, \mathcal{C}_2)$-bimodule category, and $\mathcal{M}^{\text{op}}$ is the opposite module category and a $(\mathcal{C}_2, \mathcal{C}_1)$-bimodule category. + +If we take $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep} \mathbb{Z}_2$ and $\mathcal{M} = \mathsf{Vec}$, then the entire multifusion category is isomorphic to the $\mathsf{Ising}$ category [etingof2016tensor; Example 4.10.5](@cite). We identify the trivial representation of $\mathsf{Rep} \mathbb{Z}_2$ with the unit of $\mathsf{Ising}$, the sign representation with $\psi$ and the unique object of $\mathsf{Vec}$ with the duality object $\sigma$. One can easily check that the fusion rules of $\mathsf{Ising}$ match with those we expect within $\mathsf{Rep} \mathbb{Z}_2$ and with its module category $\mathsf{Vec}$. Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (and vice-versa) giving every object in $\mathcal{C}_1$ ($\mathcal{C}_2$) is consistent with $\sigma \times \sigma^* = 1 + \psi$. This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). + +This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep_G}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is isomorphic to the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep_G}$. + +## Module and multifusion categories in condensed matter physics +- boundaries of string-net models +- generalised anyonic spin chain +- moore-seiberg data -> modular invariant +- modules as (conformal) boundary conditions \ No newline at end of file From 2bbc946c5a9b76573e502c7a900a49ed3619f597 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 30 Jun 2025 17:54:42 +0200 Subject: [PATCH 102/206] expand on unitarity check explicitly + make less specific to A4 --- test/test_A4.jl | 124 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 15 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 652f1c7..596190c 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -3,16 +3,16 @@ using TensorKitSectors, TensorKit using Test, TestExtras I = A4Object -s = size(A4Object) +Istr = TensorKitSectors.type_repr(I) +r = size(I) -@testset "Basic type properties" verbose = true begin - Istr = TensorKitSectors.type_repr(I) +@testset "$Istr Basic type properties" verbose = true begin @test eval(Meta.parse(sprint(show, I))) == I @test eval(Meta.parse(TensorKitSectors.type_repr(I))) == I end -@testset "Fusion Category $i" for i in 1:s - objects = A4Object.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) +@testset "$Istr Fusion Category $i" for i in 1:r + objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) @testset "Basic properties" begin s = rand(objects, 3) @@ -48,15 +48,109 @@ end end end -@testset "Pentagon equation" begin - objects = collect(values(A4Object)) +for i in 1:r, j in 1:r # M x D (or Mop x C) + i != j || continue # skip if fusion category + @testset "$Istr right module category $i, $j" begin + mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) + fusion_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) + + @testset "Unitarity of module F-move $i, $j" begin + for A in mod_objects, Ξ± in fusion_objects, Ξ² in fusion_objects + (A.j == Ξ±.i && Ξ±.j == Ξ².i) || continue # skip if not compatible + for B in βŠ—(A, Ξ±, Ξ²) + Cs = collect(intersect(βŠ—(A, Ξ±), map(dual, βŠ—(Ξ², dual(B))))) + Ξ³s = collect(intersect(βŠ—(Ξ±, Ξ²), map(dual, βŠ—(dual(B), A)))) + Fblocks = Vector{Any}() + for C in Cs + for Ξ³ in Ξ³s + Fs = Fsymbol(A, Ξ±, Ξ², B, C, Ξ³) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + F = hvcat(length(Ξ³s), Fblocks...) + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) + end + end + end + end +end + +for i in 1:7, j in 1:7 # C x M (or D x Mop) + i != j || continue # skip if fusion category + @testset "$Istr left module category $i, $j unitarity check" begin + mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) + fusion_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) + + @testset "Unitarity of left module F-move" begin + for a in fusion_objects, b in fusion_objects, A in mod_objects # written for M as left C-module category + (a.j == b.i && b.j == A.i) || continue # skip if not compatible + for B in βŠ—(a, b, A) + cs = collect(intersect(βŠ—(a, b), map(dual, βŠ—(A, dual(B))))) # equivalent of es + Cs = collect(intersect(βŠ—(b, A), map(dual, βŠ—(dual(B), a)))) # equivalent of fs + Fblocks = Vector{Any}() + for c in cs + for C in Cs + Fs = Fsymbol(a, b, A, B, c, C) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + F = hvcat(length(Cs), Fblocks...) + isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) || + @show A, a, b, B, C, c, F + end + end + end + end +end + +for i in 1:7, j in 1:7 # bimodule check unitarity + i != j || continue # skip if fusion category + @testset "$Istr bimodule category $i, $j" begin + C_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) + mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) + D_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) + + @testset "Unitarity of bimodule F-move" begin + for a in C_objects, A in mod_objects, Ξ± in D_objects + (a.j == A.i && A.j == Ξ±.i) || continue # skip if not compatible + for B in βŠ—(a, A, Ξ±) + Cs = collect(intersect(βŠ—(a, A), map(dual, βŠ—(Ξ±, dual(B))))) # equivalent of es + Ds = collect(intersect(βŠ—(A, Ξ±), map(dual, βŠ—(dual(B), a)))) # equivalent of fs + Fblocks = Vector{Any}() + for C in Cs + for D in Ds + Fs = Fsymbol(a, A, Ξ±, B, C, D) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + count += 1 + F = hvcat(length(Ds), Fblocks...) + isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) || + @show A, a, Ξ±, B, C, D, F + end + end + end + end +end + +@testset "$Istr Pentagon equation" begin + objects = collect(values(I)) for a in objects for b in objects a.j == b.i || continue # skip if not compatible for c in objects b.j == c.i || continue # skip if not compatible for d in objects - c.j == d.i || continue # skip if not compatible + c.j == d.i || continue # skip if not compatible #TODO: check if this is right @test pentagon_equation(a, b, c, d; atol=1e-12, rtol=1e-12) end end @@ -64,24 +158,24 @@ end end end -@testset "A4 Category ($i, $j) units and duals" for i in 1:s, j in 1:s - Cij_obs = A4Object.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) +@testset "$Istr ($i, $j) units and duals" for i in 1:r, j in 1:r + Cij_obs = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) - s = rand(Cij_obs, 1)[1] + s = rand(Cij_obs) @test eval(Meta.parse(sprint(show, s))) == s @test @constinferred(hash(s)) == hash(deepcopy(s)) @test i == j ? isone(@constinferred(one(s))) : (isone(@constinferred(leftone(s))) && isone(@constinferred(rightone(s)))) @constinferred dual(s) - @test dual(s) == A4Object(j, i, MultiTensorKit._get_dual_cache(I)[2][i, j][s.label]) + @test dual(s) == I.(j, i, MultiTensorKit._get_dual_cache(I)[2][i, j][s.label]) @test dual(dual(s)) == s end -@testset "A4 Category ($i, $j) left and right units" for i in 1:s, j in 1:s - Cij_obs = A4Object.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) +@testset "$Istr ($i, $j) left and right units" for i in 1:r, j in 1:r + Cij_obs = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) s = rand(Cij_obs, 1)[1] - sp = Vect[A4Object](s => 1) + sp = Vect[I](s => 1) W = sp ← sp for T in (Float32, ComplexF64) t = @constinferred rand(T, W) From cc824ab2d18b835782fab6568a40a5e5d42e5f28 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 30 Jun 2025 18:07:55 +0200 Subject: [PATCH 103/206] update `Fsymbol` --- src/bimodulesector.jl | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 2eea4da..79adfa2 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -60,6 +60,10 @@ function _numlabels(::Type{T}, i, j) where {T<:BimoduleSector} return length(_get_dual_cache(T)[2][i, j]) end +# User-friendly functions +# ------------------- +#TODO: add functions to identify categories + # Data from files # --------------- const artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.3") @@ -240,12 +244,13 @@ function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, Nbcf = Nsymbol(b, c, f) Nafd = Nsymbol(a, f, d) + zero_array = zeros(sectorscalartype(I), Nabe, Necd, Nbcf, Nafd) Nabe > 0 && Necd > 0 && Nbcf > 0 && Nafd > 0 || - return zeros(sectorscalartype(I), Nabe, Necd, Nbcf, Nafd) + return zero_array i, j, k, l = a.i, a.j, b.j, c.j colordict = _get_Fcache(I)[i, j, k, l] - return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)] + return get!(colordict, (a.label, b.label, c.label, d.label, e.label, f.label), zero_array) end # interface with TensorKit where necessary @@ -273,6 +278,17 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where end end +#TODO: is this needed? +# function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T, +# S<:GradedSpace{<:BimoduleSector}} +# _vector = findall(!iszero, t.data) # should have 0 or 1 elements, since only one of the blocks could be non-zero +# if isempty(_vector) +# return zero(scalartype(t)) +# end +# unit = one(A4Object(only(_vector), only(_vector), 1)) +# return only(block(t, unit)) +# end + # TODO: definition for zero of GradedSpace? function dim(V::GradedSpace{<:BimoduleSector}) From 94eb6d1096cb8042f05ceda14d26d807aed11c10 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 30 Jun 2025 18:08:35 +0200 Subject: [PATCH 104/206] remove JSON dependency --- Project.toml | 2 -- src/MultiTensorKit.jl | 1 - 2 files changed, 3 deletions(-) diff --git a/Project.toml b/Project.toml index 52a149a..da80752 100644 --- a/Project.toml +++ b/Project.toml @@ -7,7 +7,6 @@ version = "0.1.0" Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" -JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" @@ -15,7 +14,6 @@ TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] Aqua = "0.8.9" Artifacts = "1.10, 1" -JSON3 = "1.14.1" SafeTestsets = "0.1" TensorKitSectors = "0.1.4" Test = "1.10" diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 41a4845..9f59e4b 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -3,7 +3,6 @@ module MultiTensorKit export BimoduleSector, A4Object export leftoneunit, rightoneunit -using JSON3 using DelimitedFiles using Artifacts using TensorKitSectors From 5bd5c123180ce82544d160aac8a8ba52ec0bf24a Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 1 Jul 2025 15:09:05 +0200 Subject: [PATCH 105/206] add pure module F-move unitarity check + clean up tests --- test/test_A4.jl | 53 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 596190c..acdeb3b 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -48,15 +48,14 @@ end end end -for i in 1:r, j in 1:r # M x D (or Mop x C) +for i in 1:r, j in 1:r i != j || continue # skip if fusion category @testset "$Istr right module category $i, $j" begin mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) fusion_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) - @testset "Unitarity of module F-move $i, $j" begin + @testset "Unitarity of module F-move $i, $j" begin # written as MxD, but with i<->j checks MopxC for A in mod_objects, Ξ± in fusion_objects, Ξ² in fusion_objects - (A.j == Ξ±.i && Ξ±.j == Ξ².i) || continue # skip if not compatible for B in βŠ—(A, Ξ±, Ξ²) Cs = collect(intersect(βŠ—(A, Ξ±), map(dual, βŠ—(Ξ², dual(B))))) Ξ³s = collect(intersect(βŠ—(Ξ±, Ξ²), map(dual, βŠ—(dual(B), A)))) @@ -78,7 +77,7 @@ for i in 1:r, j in 1:r # M x D (or Mop x C) end end -for i in 1:7, j in 1:7 # C x M (or D x Mop) +for i in 1:7, j in 1:7 # C x M (or D x Mop with i<->j) i != j || continue # skip if fusion category @testset "$Istr left module category $i, $j unitarity check" begin mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) @@ -86,7 +85,6 @@ for i in 1:7, j in 1:7 # C x M (or D x Mop) @testset "Unitarity of left module F-move" begin for a in fusion_objects, b in fusion_objects, A in mod_objects # written for M as left C-module category - (a.j == b.i && b.j == A.i) || continue # skip if not compatible for B in βŠ—(a, b, A) cs = collect(intersect(βŠ—(a, b), map(dual, βŠ—(A, dual(B))))) # equivalent of es Cs = collect(intersect(βŠ—(b, A), map(dual, βŠ—(dual(B), a)))) # equivalent of fs @@ -101,24 +99,22 @@ for i in 1:7, j in 1:7 # C x M (or D x Mop) end end F = hvcat(length(Cs), Fblocks...) - isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) || - @show A, a, b, B, C, c, F + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) end end end end end -for i in 1:7, j in 1:7 # bimodule check unitarity +for i in 1:7, j in 1:7 # bimodule check unitarity (C x M x D or D x Mop x C) i != j || continue # skip if fusion category @testset "$Istr bimodule category $i, $j" begin C_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) D_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) - @testset "Unitarity of bimodule F-move" begin + @testset "Unitarity of bimodule F-move" begin # written as CMD for a in C_objects, A in mod_objects, Ξ± in D_objects - (a.j == A.i && A.j == Ξ±.i) || continue # skip if not compatible for B in βŠ—(a, A, Ξ±) Cs = collect(intersect(βŠ—(a, A), map(dual, βŠ—(Ξ±, dual(B))))) # equivalent of es Ds = collect(intersect(βŠ—(A, Ξ±), map(dual, βŠ—(dual(B), a)))) # equivalent of fs @@ -132,16 +128,45 @@ for i in 1:7, j in 1:7 # bimodule check unitarity size(Fs, 3) * size(Fs, 4)))) end end - count += 1 F = hvcat(length(Ds), Fblocks...) - isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) || - @show A, a, Ξ±, B, C, D, F + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) end end end end end +for i in 1:7, j in 1:7 # M x Mop x M -> M (or Mop x M x Mop -> Mop) + i != j || continue # skip if not fusion category + @testset "$Istr Module category $i,$j and opposite $j,$i" begin + M_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) + Mop_objects = I.(j, i, MultiTensorKit._get_dual_cache(I)[2][j, i]) + C_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i,i]) + D_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) + + @testset "Unitarity of pure module F-move" begin + for A in M_objects, Aop in Mop_objects, B in M_objects # written for M x Mop x M -> M + for C in βŠ—(A, Aop, B) + cs = collect(intersect(βŠ—(A, Aop), map(dual, βŠ—(B, dual(C))))) # equivalent of es + Ξ³s = collect(intersect(βŠ—(Aop, B), map(dual, βŠ—(dual(C), A)))) # equivalent of fs + Fblocks = Vector{Any}() + for c in cs + for Ξ³ in Ξ³s + Fs = Fsymbol(A, Aop, B, C, c, Ξ³) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + F = hvcat(length(Ξ³s), Fblocks...) + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) + end + end + end + end +end + @testset "$Istr Pentagon equation" begin objects = collect(values(I)) for a in objects @@ -150,7 +175,7 @@ end for c in objects b.j == c.i || continue # skip if not compatible for d in objects - c.j == d.i || continue # skip if not compatible #TODO: check if this is right + c.j == d.i || continue # skip if not compatible @test pentagon_equation(a, b, c, d; atol=1e-12, rtol=1e-12) end end From bb6eee3db7e8af7c43f47f60b07db8360856784a Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 16 Jul 2025 09:33:56 -0400 Subject: [PATCH 106/206] adapt `TensorKit.scalar` --- src/bimodulesector.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 79adfa2..39e6a21 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -373,3 +373,14 @@ function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}; # want no defa end return ProductSpace(TupleTools.insertafter(P.spaces, i - 1, (u,))) end + +function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T, + S<:GradedSpace{<:BimoduleSector}} + inds = findall(!iszero ∘ last, blocks(t)) + isempty(inds) && return zero(scalartype(t)) + @assert length(inds) == 1 + + c = blocksectors(t)[only(inds)] + return only(block(t, c)) +end + From 71682dcc43e8bd9e0bf9d8035c1099c379fd42e2 Mon Sep 17 00:00:00 2001 From: Lukas Devos Date: Wed, 16 Jul 2025 09:51:33 -0400 Subject: [PATCH 107/206] Simplify by fixing `collect` --- src/bimodulesector.jl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 39e6a21..4e2a57e 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -376,11 +376,9 @@ end function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T, S<:GradedSpace{<:BimoduleSector}} - inds = findall(!iszero ∘ last, blocks(t)) + Bs = collect(blocks(t)) + inds = findall(!iszero ∘ last, Bs) isempty(inds) && return zero(scalartype(t)) - @assert length(inds) == 1 - - c = blocksectors(t)[only(inds)] - return only(block(t, c)) + return only(last(Bs[only(inds)])) end From ee71ed83040e69888e57cf327898d2afd0b37965 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 22 Jul 2025 13:54:12 -0400 Subject: [PATCH 108/206] add the other unitarity tests --- test/test_A4.jl | 85 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 7 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index acdeb3b..edaf0ff 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -141,11 +141,74 @@ for i in 1:7, j in 1:7 # M x Mop x M -> M (or Mop x M x Mop -> Mop) @testset "$Istr Module category $i,$j and opposite $j,$i" begin M_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) Mop_objects = I.(j, i, MultiTensorKit._get_dual_cache(I)[2][j, i]) - C_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i,i]) + C_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) D_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) + @testset "Unitarity of mixed module F-move I" begin # written for C x M x Mop -> C but also holds for D x Mop x M -> D + for Ξ± in C_objects, A in M_objects, Aop in Mop_objects + for Ξ² in βŠ—(Ξ±, A, Aop) + Cs = collect(intersect(βŠ—(Ξ±, A), map(dual, βŠ—(Aop, dual(Ξ²))))) # equivalent of es + Ξ³s = collect(intersect(βŠ—(Aop, A), map(dual, βŠ—(dual(Ξ²), Ξ±)))) # equivalent of fs + Fblocks = Vector{Any}() + for C in Cs + for Ξ³ in Ξ³s + Fs = Fsymbol(Ξ±, A, Aop, Ξ², C, Ξ³) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + F = hvcat(length(Ξ³s), Fblocks...) + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) + end + end + end + + @testset "Unitarity of mixed module F-move II" begin # written for M x Mop x C -> C but also holds for Mop x M x D -> D + for A in M_objects, Aop in Mop_objects, Ξ± in C_objects + for Ξ² in βŠ—(A, Aop, Ξ±) + Ξ³s = collect(intersect(βŠ—(A, Aop), map(dual, βŠ—(Ξ±, dual(Ξ²))))) # equivalent of es + Bops = collect(intersect(βŠ—(Aop, Ξ±), map(dual, βŠ—(dual(Ξ²), A)))) # equivalent of fs + Fblocks = Vector{Any}() + for Ξ³ in Ξ³s + for Bop in Bops + Fs = Fsymbol(A, Aop, Ξ±, Ξ², Ξ³, Bop) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + F = hvcat(length(Bops), Fblocks...) + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) + end + end + end + + @testset "Unitarity of mixed module F-move III" begin # written for Mop x C x M -> D, but also holds for M x D x Mop -> C + for Aop in Mop_objects, Ξ± in C_objects, A in M_objects + for a in βŠ—(Aop, Ξ±, A) + Bops = collect(intersect(βŠ—(Aop, Ξ±), map(dual, βŠ—(A, dual(a))))) # equivalent of es + Bs = collect(intersect(βŠ—(Ξ±, A), map(dual, βŠ—(dual(a), Aop)))) # equivalent of fs + Fblocks = Vector{Any}() + for Bop in Bops + for B in Bs + Fs = Fsymbol(Aop, Ξ±, A, a, Bop, B) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + F = hvcat(length(Bs), Fblocks...) + @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) + end + end + end + @testset "Unitarity of pure module F-move" begin - for A in M_objects, Aop in Mop_objects, B in M_objects # written for M x Mop x M -> M + for A in M_objects, Aop in Mop_objects, B in M_objects # written for M x Mop x M -> M but also holds for Mop x M x Mop -> Mop for C in βŠ—(A, Aop, B) cs = collect(intersect(βŠ—(A, Aop), map(dual, βŠ—(B, dual(C))))) # equivalent of es Ξ³s = collect(intersect(βŠ—(Aop, B), map(dual, βŠ—(dual(C), A)))) # equivalent of fs @@ -154,9 +217,9 @@ for i in 1:7, j in 1:7 # M x Mop x M -> M (or Mop x M x Mop -> Mop) for Ξ³ in Ξ³s Fs = Fsymbol(A, Aop, B, C, c, Ξ³) push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) end end F = hvcat(length(Ξ³s), Fblocks...) @@ -165,7 +228,15 @@ for i in 1:7, j in 1:7 # M x Mop x M -> M (or Mop x M x Mop -> Mop) end end end -end +end + +@testset "Triangle equation" begin + objects = collect(values(I)) + for a in objects, b in objects + a.j == b.i || continue # skip if not compatible + @test triangle_equation(a, b; atol=1e-12, rtol=1e-12) + end +end @testset "$Istr Pentagon equation" begin objects = collect(values(I)) @@ -233,4 +304,4 @@ end end @test @constinferred(removeunit(t2, $(numind(t2)))) == t end -end \ No newline at end of file +end From 4b067e5ee12ab240778044bcfe257113c08f569d Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 22 Jul 2025 14:41:48 -0400 Subject: [PATCH 109/206] fix test --- test/test_A4.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index edaf0ff..6e54328 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -148,7 +148,7 @@ for i in 1:7, j in 1:7 # M x Mop x M -> M (or Mop x M x Mop -> Mop) for Ξ± in C_objects, A in M_objects, Aop in Mop_objects for Ξ² in βŠ—(Ξ±, A, Aop) Cs = collect(intersect(βŠ—(Ξ±, A), map(dual, βŠ—(Aop, dual(Ξ²))))) # equivalent of es - Ξ³s = collect(intersect(βŠ—(Aop, A), map(dual, βŠ—(dual(Ξ²), Ξ±)))) # equivalent of fs + Ξ³s = collect(intersect(βŠ—(A, Aop), map(dual, βŠ—(dual(Ξ²), Ξ±)))) # equivalent of fs Fblocks = Vector{Any}() for C in Cs for Ξ³ in Ξ³s From 42de755f0b5ef71d0d4e0a96401846973b51fdf7 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 22 Jul 2025 15:20:00 -0400 Subject: [PATCH 110/206] add compats to Project.toml --- Project.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index da80752..640d3b2 100644 --- a/Project.toml +++ b/Project.toml @@ -14,8 +14,11 @@ TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] Aqua = "0.8.9" Artifacts = "1.10, 1" +BlockTensorKit = "0.1.10" +DelimitedFiles = "1.9" SafeTestsets = "0.1" -TensorKitSectors = "0.1.4" +TensorKit = "0.14.9" +TensorKitSectors = "0.1.7" Test = "1.10" TestExtras = "0.3" TupleTools = "1.1" From a86643b88318f34b86d3186f26834a15fe954be2 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 24 Jul 2025 16:13:41 -0400 Subject: [PATCH 111/206] remove diagonal checks in `left/rightoneunit` --- src/bimodulesector.jl | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 7e6197d..327bb07 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -278,19 +278,6 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where end end -#TODO: is this needed? -# function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T, -# S<:GradedSpace{<:BimoduleSector}} -# _vector = findall(!iszero, t.data) # should have 0 or 1 elements, since only one of the blocks could be non-zero -# if isempty(_vector) -# return zero(scalartype(t)) -# end -# unit = one(A4Object(only(_vector), only(_vector), 1)) -# return only(block(t, unit)) -# end - -# TODO: definition for zero of GradedSpace? - function dim(V::GradedSpace{<:BimoduleSector}) T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) return reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(T)) @@ -316,9 +303,6 @@ function rightoneunit(S::GradedSpace{<:BimoduleSector}) allequal(a.j for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same rightone")) - allequal(a.i for a in sectors(S)) || - throw(ArgumentError("sectors of $S are not all equal")) - sector = rightone(first(sectors(S))) return spacetype(S)(sector => 1) end @@ -332,9 +316,6 @@ function leftoneunit(S::GradedSpace{<:BimoduleSector}) allequal(a.i for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same leftone")) - allequal(a.j for a in sectors(S)) || - throw(ArgumentError("sectors of $S are not all equal")) - sector = leftone(first(sectors(S))) return spacetype(S)(sector => 1) end @@ -381,4 +362,3 @@ function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T, isempty(inds) && return zero(scalartype(t)) return only(last(Bs[only(inds)])) end - From 847c7621189b6a8d3afbc487f5040bafd7b59040 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 24 Jul 2025 16:14:12 -0400 Subject: [PATCH 112/206] pretty print `BimoduleSector` --- src/bimodulesector.jl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 327bb07..3be59ca 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -12,6 +12,17 @@ end BimoduleSector{Name}(data::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(data...) const A4Object = BimoduleSector{:A4} +Base.convert(::Type{<:BimoduleSector{Name}}, labels::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(labels...) + +function Base.show(io::IO, a::BimoduleSector{Name}) where {Name} + if get(io, :typeinfo, nothing) === typeof(a) + print(io, (a.i, a.j, a.label)) + else + print(io, typeof(a), (a.i, a.j, a.label)) + end + return nothing +end + # Utility implementations # ----------------------- function Base.isless(a::I, b::I) where {I<:BimoduleSector} From 6e9e9eb8ddfaebdbc4518908d4dc07accba4b9b5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 4 Aug 2025 17:02:57 +0200 Subject: [PATCH 113/206] add custom css for centering and color inverting (cannot use now for some reason) --- docs/src/assets/custom.css | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 docs/src/assets/custom.css diff --git a/docs/src/assets/custom.css b/docs/src/assets/custom.css new file mode 100644 index 0000000..4e38a20 --- /dev/null +++ b/docs/src/assets/custom.css @@ -0,0 +1,47 @@ +.center { + display: block; + margin-left: auto; + margin-right: auto; +} + +/* set fixed non-trivial inversion and hue rotation */ +:root { + --inversionFraction: 100%; + --hueRotation: -180deg; +} + +/* color-invert images */ +.color-invertible { + filter: invert(var(--inversionFraction)) hue-rotate(var(--hueRotation)) !important; + -ms-filter: invert(var(--inversionFraction)) !important; + -webkit-filter: invert(var(--inversionFraction)) hue-rotate(var(--hueRotation)) !important; +} +/* including the logo when we make one +.docs-logo { + filter: invert(var(--inversionFraction)) hue-rotate(var(--hueRotation)) !important; + -ms-filter: invert(var(--inversionFraction)) !important; + -webkit-filter: invert(var(--inversionFraction)) hue-rotate(var(--hueRotation)) !important; +} */ + +/* but disable for the two light themes */ +.theme--documenter-light .color-invertible { + filter: invert(0%) hue-rotate(0deg) !important; + -ms-filter: invert(var(0%)) !important; + -webkit-filter: invert(var(0%)) hue-rotate(0deg) !important; +} +.theme--catppuccin-latte .color-invertible { + filter: invert(0%) hue-rotate(0deg) !important; + -ms-filter: invert(var(0%)) !important; + -webkit-filter: invert(var(0%)) hue-rotate(0deg) !important; +} +/* for the logo as well */ +/* .theme--documenter-light .docs-logo { + filter: invert(0%) hue-rotate(0deg) !important; + -ms-filter: invert(var(0%)) !important; + -webkit-filter: invert(var(0%)) hue-rotate(0deg) !important; +} +.theme--catppuccin-latte .docs-logo { + filter: invert(0%) hue-rotate(0deg) !important; + -ms-filter: invert(var(0%)) !important; + -webkit-filter: invert(var(0%)) hue-rotate(0deg) !important; +} */ \ No newline at end of file From c6c18850def1a94536484ff6a7b25ffbe5144243 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 4 Aug 2025 18:10:42 +0200 Subject: [PATCH 114/206] braiding info + start of actual repa4 example --- docs/src/assets/MTKrefs.bib | 10 ++++ docs/src/man/Implementation.md | 84 +++++++++++++++++++++++++++------ docs/src/man/multifusioncats.md | 12 ++--- 3 files changed, 85 insertions(+), 21 deletions(-) diff --git a/docs/src/assets/MTKrefs.bib b/docs/src/assets/MTKrefs.bib index c7fe36c..7a95ca2 100644 --- a/docs/src/assets/MTKrefs.bib +++ b/docs/src/assets/MTKrefs.bib @@ -40,4 +40,14 @@ @misc{henriques2020 archivePrefix={arXiv}, primaryClass={math.OA}, url={https://arxiv.org/abs/2004.08271}, +} + +@misc{Lootens_2024, + title={Entanglement and the density matrix renormalisation group in the generalised Landau paradigm}, + author={Laurens Lootens and Clement Delcamp and Frank Verstraete}, + year={2024}, + eprint={2408.06334}, + archivePrefix={arXiv}, + primaryClass={quant-ph}, + url={https://arxiv.org/abs/2408.06334}, } \ No newline at end of file diff --git a/docs/src/man/Implementation.md b/docs/src/man/Implementation.md index 1158530..ef69e0f 100644 --- a/docs/src/man/Implementation.md +++ b/docs/src/man/Implementation.md @@ -1,9 +1,9 @@ explain the f-symbol and n-symbol storage system # MultiTensorKit implementation: $\mathsf{Rep_{A_4}}$ as an example -This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate ... (not sure yet what we're going to show here). +This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. -This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep_{A_4}}$. Since there are 12 module categories (technically only 8 up to equivalence), `A4Object` is a $r=12$ multifusion category. There are 3 fusion categories up to equivalence: +This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep_{A_4}}$. Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. There are 3 fusion categories up to equivalence: - $\mathsf{Vec A_4}$: the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$. It has thus 12 objects. - $\mathsf{Rep_{A_4}}$: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. One is the trivial representation, two are one-dimension non-trivial and the last is three-dimensional. - $\mathsf{Rep H}$: the representation category of some Hopf algebra which does not have a name. It has 6 simple objects. @@ -13,11 +13,20 @@ using TensorKit, MultiTensorKit, MPSKit, MPSKitModels ```` ## Identifying the simple objects -We first need to select which fusion category we wish to use to grade the physical Hilbert space, and which fusion category to represent e.g. the symmetry category. Say we choose $\mathcal{D} = \mathsf{Vec A_4}$ for the physical Hilbert space and $\mathcal{C} = \mathcal{D}^*_{\mathcal{M}} = \mathsf{Rep_{A_4}}$ the symmetry category. This fixes the module category $\mathcal{M} = \mathsf{Vec}$. When referring to specific fusion and module categories, we will use this non-multifusion notation. +We first need to select which fusion category we wish to use to grade the physical Hilbert space, and which fusion category to represent e.g. the symmetry category. In our case, we are interested in selecting $\mathcal{D} = \mathsf{Rep(A_4)}$ for the physical Hilbert space. We know the module categories over $\mathsf{Rep(G)}$ to be $\mathsf{Rep^\psi(H)}$ for a subgroup $\mathsf{H} and 2-cocycle $\psi$. Thus, the 7 module categories $\mathcal{M}$ one can choose over $\mathsf{Rep(A_4)}$ are +- $\mathsf{Rep(A_4)}$ itself as the regular module category, +- $\mathsf{Vec}$: the category of vector spaces, +- $\mathsf{Rep(\mathbb{Z}_2)}$, +- $\mathsf{Rep(\mathbb{Z}_3)}$, +- $\mathsf{Rep(\mathbb{Z}_2 \times \mathbb{Z}_2)}$, +- $\mathsf{Rep^\psi(\mathbb{Z}_2 \times \mathbb{Z}_2)}$, +- $\mathsf{Rep^\psi(A_4)}$. + +When referring to specific fusion and module categories, we will use this non-multifusion notation. The easiest way to identify which elements of the multifusion category correspond to the subcategories we wish to use is ... (not sure yet how to do this yet) -Once we have identified the fusion and module categories, we now want to select the relevant objects we wish to place in our graded spaces. Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. Hence, the simplest way to find the unit object of a fusion subcategory is +Now that we have identified the fusion and module categories, we want to select the relevant objects we wish to place in our graded spaces. Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. Hence, the simplest way to find the unit object of a fusion subcategory is ````julia one(A4Object(i,i,1)) @@ -39,24 +48,71 @@ The dual object of some simple object $a$ of an arbitrary subcategory $\mathcal{ $$ ^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* \times a,$$ with multiplicity 1. -## Matrix product state simulations with MPSKit -TensorKit has been made compatible with the multifusion structure by keeping track of the relevant units in the fusion tree manipulations. With this, we can make `GradedSpace`s whose objects are in `A4Object`. With our example in mind, we first select the objects: +## Hamiltonian +TensorKit has been made compatible with the multifusion structure by keeping track of the relevant units in the fusion tree manipulations. With this, we can make `GradedSpace`s whose objects are in `A4Object`: ````julia -D0 = one(A4Object(2,2,1)) # unit object of VecA4 -D1 = A4Object(2,2,2) # some self-dual object of VecA4 +D1 = A4Object(6, 6, 1) # unit in this case +D2 = A4Object(6, 6, 2) # non-trivial 1d irrep +D3 = A4Object(6, 6, 3) # non-trivial 1d irrep +D4 = A4Object(6, 6, 4) # 3d irrep -M = A4Object(1,2,1) # Vec +```` +Since we want to replicate a spin-1 Heisenberg model, it makes sense to use the 3-dimensional irrep to grade the physical space, and thus construct our Hamiltonian. We don't illustrate here how to derive the considered Hamiltonian in a $\mathsf{Rep(A_4)}$ basis, but simply give it. -C0 = one(A4Object(1,1,1)) # unit object of RepA4 -C1 = A4Object(1,1,1) # non-trivial 1d irrep +````julia +P = Vect[A4Object](D4 => 1) # physical space +T = ComplexF64 +# usual Heisenberg part +h1_L = TensorMap(zeros, T, P βŠ— P ← P) +h1_R = TensorMap(zeros, T, P ← P βŠ— P) +block(h1_L, D4) .= [0; 1] +block(h1_R, D4) .= [0 1;] +@plansor h1[-1 -2; -3 -4] := h1_L[-1 1; -3] * h1_R[-2; 1 -4] + +# biquadratic term +h2_L = TensorMap(zeros, T, P βŠ— Vect[A4Object](D1 => 1, D2 => 1, D3 => 1) ← P) +h2_R = TensorMap(ones, T, P ← Vect[A4Object](D1 => 1, D2 => 1, D3 => 1) βŠ— P) +block(h2_L, D4) .= [4 / 3; 1 / 3; 1 / 3] +@plansor h2[-1 -2; -3 -4] := h2_L[-1 1; -3] * h2_R[-2; 1 -4] + +# anti-commutation term +h3_L = TensorMap(zeros, T, P βŠ— P ← P) +h3_R = TensorMap(zeros, T, P ← P βŠ— P) +block(h3_L, D4) .= [1; 0] +block(h3_R, D4) .= [0 1;] +@plansor h3[-1 -2; -3 -4] := h3_L[-1 1; -3] * h3_R[-2; 1 -4] + +L = 60 +J1 = 1.0 # probing the A4 SPT phase first +J2 = 1.0 +lattice = FiniteChain(L) +H1 = @mpoham sum(-2 * h1{i,j} for (i, j) in nearest_neighbours(lattice)) +H2 = @mpoham sum(h2{i,j} for (i, j) in nearest_neighbours(lattice)) +H3 = @mpoham sum(2im * h3{i,j} for (i, j) in nearest_neighbours(lattice)) + +H = H1 + J1 * H2 + J3 * H3 ```` -Afterwards, we build the physical and virtual space of the matrix product state: + +## Constructing the matrix product state +For now, we will select $\mathsf{Vec}$ as the module category: ````julia -P = Vect[A4Object](D0 => 1, D1 => 1) -V = Vect[A4Object](M => D) # D is the bond dimension +M = A4Object(1, 6, 1) # Vec ```` + + Afterwards, we build the physical and virtual space of the matrix product state: +````julia +D = 40 # bond dimension +V = Vect[A4Object](M => D) +Vb = Vect[A4Object](M => 1) # non-degenerate boundary virtual space +init_mps = FiniteMPS(L, P, V; left=Vb, right=Vb) +```` +> [!IMPORTANT] +> We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for `BimoduleSector` due to the semisimple unit. + + + ### Infinite case Now, using MPKSit, we can perform matrix product state calculations. We construct some nearest-neighbour Hamiltonian and find the MPS representation of the ground state. ````julia diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 499cfec..bf8f9bf 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -90,7 +90,7 @@ end `i` and `j` specify which subcategory $\mathcal{C}_{ij}$ we are considering, and `label` selects a particular simple object within that subcategory. -We want to consider multifusion categories because **their structure encapsulates that of (bi-)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. In particular, the tensor product +We want to consider multifusion categories because **their structure encapsulates that of (bi-)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ (also known as a component category) is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. In particular, the tensor product $$\otimes_\mathcal{C}: \mathcal{C}_{ij} \times \mathcal{C}_{kl} \rightarrow \delta_{jk}\mathcal{C}_{il}$$ @@ -152,19 +152,17 @@ where by $\mathbb{1}_a$ we mean the right unit of $a$ (the left unit we would de Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{a \bar{a} a}_{a}$ needs to be evaluated for these topological data. Graphically, we find that ```@raw html - + ``` need to show other changed expressions like A-move, dimension, frobenius-schur indicator, what else outside of TensorKitSectors in terms of fusion tree manipulations? no figures up till now with arrows, will this even be necessary? maybe if we show B-moves with M->Mop -## Examples of multifusion categories -2x2 thing that is isomorphic to ising -generalisation to Tambara-Yamagami - -where to say something about rewriting mpskit to be planar such that braidings with module legs are avoided? +### Braiding +A very important aspect of MultiTensorKit is that all `BimoduleSector`s are defined to *not* support braiding: `TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding()`. We do this for two reasons. On the one hand, there is no natural 1-categorical way of defining braidings between the components of the multifusion category. It is possible that the diagonal fusion categories themselves are braided, but a "componentwise" braiding is unwise to support. On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. +## Examples of multifusion categories Without specifying any of the categories, the simplest non-trivial multifusion category is a $2\times 2$ one, and the categories can be organised in a matrix as $$\mathcal{C} = \begin{pmatrix} \mathcal{C}_1 & \mathcal{M} \\ \mathcal{M}^{\text{op}} & \mathcal{C}_2\end{pmatrix}.$$ From a5cdaca1c5db528866d17bd08b8523278e598ddf Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 4 Aug 2025 18:10:50 +0200 Subject: [PATCH 115/206] include repa4 example --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 6ec1264..9ae7d4c 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -3,7 +3,7 @@ using DocumenterCitations using MultiTensorKit pages = ["Home" => "index.md", "Library" => "lib/library.md", - "Manual" => ["man/fusioncats.md", "man/multifusioncats.md"], + "Manual" => ["man/fusioncats.md", "man/multifusioncats.md", "man/implementation.md"], "References" => "references.md"] # bibliography From 94d4d13fc12b3806b2dc63b3b9cfbabae24ae625 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 5 Aug 2025 13:45:56 +0200 Subject: [PATCH 116/206] add arrows to images + colored F-move --- docs/src/man/img/Bmove_MF.svg | 1752 +++++++++-------- docs/src/man/img/Bmove_lit.svg | 1548 +++++++-------- docs/src/man/img/Fmove.svg | 2051 ++++++++++--------- docs/src/man/img/Fmove_CM.svg | 1193 +++++------ docs/src/man/img/Fmove_CMD.svg | 1241 ++++++------ docs/src/man/img/Fmove_D.svg | 1197 +++++------ docs/src/man/img/Fmove_MD.svg | 1250 ++++++------ docs/src/man/img/Fmove_coloring.svg | 2336 ++++++++++++++++++++++ docs/src/man/img/Nsymbol_coloring.svg | 2628 +++++++++++-------------- docs/src/man/img/homvector.svg | 607 +++--- docs/src/man/img/qdim_fs_MF.svg | 921 ++++----- 11 files changed, 9488 insertions(+), 7236 deletions(-) create mode 100644 docs/src/man/img/Fmove_coloring.svg diff --git a/docs/src/man/img/Bmove_MF.svg b/docs/src/man/img/Bmove_MF.svg index 8c008f6..27513af 100644 --- a/docs/src/man/img/Bmove_MF.svg +++ b/docs/src/man/img/Bmove_MF.svg @@ -1,803 +1,963 @@ - +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 +KJbalKE2q0Jtolz2zsTsX+/OBY4SflqDNpAVvTvdtowZkUbfzZH63rJyUZs6ojY9r9iPxY/hhvzh ++++/m/riTyD02+J3O5Ob76puPfUMGsVSmzLUZlWoTZRrJHx6JF9Qs3HbNovenV78xCjaZartc1vf +W1YualNH1KbrM3tq8/uohvT9kLJPM3iGoe+Eg73WMmgUS23KUJtVoTZRqlXhmKfvPgE3439agzaQ +Fb479hewbbP93KeK6Mq0ht+yklGbOqI2XdFTm3cWavPnuNp0LnnyYLlUP1Ede8oZNIqlNmWozapQ +myiVvZI0+7bNofsEjPxs47ZtFr079kCfbZuVWu10B71ed03ts8rtA+fKtP21Ya836G5q8EaDvres +ijtKbWqG2nTZ19q8tzhl+cv333/vx+b92IW095fnNu8+sD7ENTcNGsVSmzLUZlWoTZRqKJybc9aW +xlwypXHbNovenVZu25x0NVoZPOn6lzXtCU5mVTpnc6S1wXcyHHk3aqjyRml+y2b/emUuc6A2dURt +uuxH4qfIlPzdmbmMvxTnr84X/Lb8wa9Vx55yBo1iqU0ZarMq1CZKtS6bm+u7z7/oVXtN27ZZ+O60 +cdtmV6PJ6X5vGjK03hdZ640Gq3XfFP99ickw6kapo+8tm7+89Mq7DdSmjqhNx1+sB+JBSkzGbtt0 +czRcq/aEp/EXQTFoFEttylCbVaE2UaaJcMjjDpKmkYP9xm3bLHx37C9QPaYv03geLOt63KOJM7k8 +3JzV76Qzf2dkY3bLNqyZvJqD2H1jYm1lbf4mxKjbn92S1a71hsSo9vRtxi2zVwesl3YbyqjNIw/v +7z/yaHn3kNqkNh1/tR6IuFPOuts3Y7dtOgtpF2r1F+uD36iuPdUMGsVSmzLUZlWoTZRpUzg3N3Cf +f5Gfbdy2zaJ3xx7ot2nb5nhDg0ZxdOy55YH3+K9ZD3ZXyTjdzYP+/Dkz8t6AmGwojzp9b1nZT6cS +avPI0f2ZR8q7h9Qmten4W2JNOls3Y7dtxsx92ucJMn4prUGjWGpThtqsCrWJMnWFdbjhPP2in0+N +27ZZ9O60btumTrFprwodBWeW5+e06qpZru0u6Z0/QN3A1O9Y+RyivrdspeQnVAm1+fC+5Vhpd5Da +pDZt31qPw3dxNen8g8du23QX0v6+sN/T/uhXqnNPMYNGsdSmDLVZFWoTZdoQ1uE0cZAk6oB+p9vt +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 +e/A46nUH1h96886xc3O9Ox+MLe+7qmZtZDmsW+7E82qGs9GqOjNL3M13Jo6Kr/GeBA4l0S7oiKuT +dmMK2F917T3GvYXJrCuBNyPsJ0vcNl/hZRgn0Y+Tc/nPmNdWYdEGVk5f3N7bO+594vBewumi9L1l +sdxX3prf6VrJum3TN9Tv3G46ojZdn1uPxHfR2zZt9+9l3K9p+90O1NdUx55yBo1iqU0ZarMi1GZp +wm+abxb/gQmGNfwOofVyOkOs40+DDZzx5rjrbsiL3LRZydrIcthrZ9dn8Wzfq17i4FTZmVliuJst +iy+kzbVtc66//F6P08CLP2bTX1Pp1ua8tEKLEq7670ycP0iaCBdfhnEYVcDOvY5bGCEsWn/l9MK7 +CSet5dPHY75N31sWx11KW+07fFGybdv09ep/O66JqE3Xt84sZigYfwm8OP7y2++S1rx79579fcYv +pDVpFEttylCbFfkjtVmW1dCWoHLOIxprQ83wKt4kfSauKqtrw16v1+0EhsLjTrfXG3QiBsdVrY0s +S9/fjDUaJu9YVHhmlmju+y3Fn/r5tm3OrS8/De15uYWFlvN+2hiEa3O4eEhd9U8i9Zz1ZLkW/Uvl +l2G0t0GGf5uTdMOYpJMWrbty+uLW3t5OaLrw8vHtx2LnD/W9ZbHc95sq3b4QIeu2TQ+1mQm16bEH +vvdDSXnfm9WUpqa3azP7YK+1DBrFUpsy1GZFblObpQlOyFQ9zWdP2NQ9vEqwqd9sa5TK1kaWZ2LF +87CbujBQ4ZlZom94ec/8nNs2V5xOXZjHHCxNblondt4YT0K12V8OZe/J8cJB8gmMxZdhXL467Vo4 +fZcIi9ZdOX1o9g+/fVHwCOp7y+K4S2nrviaU+B0o/rOZCbXpcS65eWdxJe2Dez/8LC1Nf170baY2 +TRrFUpsy1GZFqM0ShS5JX/E8n1V3Gl1OratkdkGsurWRtVN6ZpYo5Q36c2/bXD6v75xzEVb/aOmM +nOm7YWDac35t09hjdvcg5fzFIVnemrB+tX++4Yk9pz1KeL9GVrT2yukTJ+RnHNb3lsVwl9LWvY5f ++g7Uql7LUbRFbfr+GjG5md+PTG26DBrFUpsy1GZFqM0SjcMX2a72rBVdBcOrBBv+sF1n1a2NrJva +M7NEcZ/9xa/Mk3vbprNxc/HIG9vBNLRmLidr8xtqn4vJ6dB5A/TXk46n09aT5YWMNyLTWxPOWaCs +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 +uL7JqM0Yr/gvjXcynC3op3vel7/NdTYXGDSKpTZlqM2K+LX5LsdpmTZDtbne6q2b9qtZg+6ihmsj +i1B/zph+hj7MKOO2zW4p86gZXTlzYLt+NvVrZZdhzCetaA9b/7yHwh+czxvu7V3a2t6rLjbV3TJv +43A1SyyO2P+sR92/PmH99Vglv8t41GacP/zNe228fydlfvNnvzWn73+iOu60Y9AoltqUoTYrQm1W +Jbx1s/goXGMbaasedaPf2shC1J8zplveWD/jts2Nel+Cruxev359N701hZdhzCmtaE/OTzm8vDZ6 +yz4T8d5ONRc/UXrLvPc7qnlW2FOb3r+rvY72+Up+FajNWN/+e+Dl8cGd2A2cv975LvCFb3B+oCUG +jWKpTRlqsyLUZmU2QrnZ4nMSjpvX09qtjSxE/TljvCvMFl9OnW3b5qSyWayCRJdhzCm9aC8/tr0V +8U968dDW9vZjhys6QZDSW+at5a5mxvuCXZsXrL8ceSrwF5SO2kzwl38GhxXf3ft1qTR///Xe/eDX +vJl9aGcQg0ax1KYMtVmRd6jNqqyGtm6Wv5tMG/0G5rRuayOL0OCcMd47K4XPvZlx2+ZaGb+rCnWc +PaaOom3cLcsyIZ6fcwpa6yxBz1rv7hzV+O2nhqM2E73yt2nI99/f+eFHa5bz5x/v3Pn+Qfiz77Nj +M5JBo1hqU4barAi1WZ1O6FW/QRcIEepWN8irkF5rI4vQ4Jwx5U0sZdy2uVHVJFZRdbw1oe/5UBXe +Mu+ktNWcrczaqPn8sWPHLtgrCZ7U992nxqM2k332+UJvxnv7NdVVpyuDRrHUpgy1WRFqs0KD0Au/ +lgv/ymCN8+q6zl399J1Jcqg/Z8yqN4Nf+M5k27Y50fUVSHQZxrz0nWxXeMt61b7OHnlyP+Apzg9U +IWozzWefZ2vNW2zYjGPQKJbalKE2K0JtVmi8Hnrt13LlXwmsOzdQfSsqo+9MkkP9OWO8EzAXf1XI +tm1zqM27Nwouw1hL0TbulnknqqpqA/mzT9kH2iNPPXOk+E9DPGoz3Wev/DllgvPtT1lDm8CgUSy1 +KUNtVoTarNJq6OV/1KBrhAj0rTu3pvpmVEbfmSSbBueM8Ub6hV8Vsm3bnGjz5k0tl2FUULTNu2Xl +PQcTPHpM39eB9qA2s/nLX0NnDAp6/xbXPElm0CiW2pShNitCbVYqfBmUdj5m9pXuVlXfjKroO5Pk +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" /> diff --git a/docs/src/man/img/Bmove_lit.svg b/docs/src/man/img/Bmove_lit.svg index 70900ff..17667aa 100644 --- a/docs/src/man/img/Bmove_lit.svg +++ b/docs/src/man/img/Bmove_lit.svg @@ -1,832 +1,724 @@ - +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 +LjVTNlrBAAAAAElFTkSuQmCC" /> diff --git a/docs/src/man/img/Fmove.svg b/docs/src/man/img/Fmove.svg index 6743412..0ed24e1 100644 --- a/docs/src/man/img/Fmove.svg +++ b/docs/src/man/img/Fmove.svg @@ -1,988 +1,1071 @@ - +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" /> diff --git a/docs/src/man/img/Fmove_CM.svg b/docs/src/man/img/Fmove_CM.svg index 04fa2d7..acb224e 100644 --- a/docs/src/man/img/Fmove_CM.svg +++ b/docs/src/man/img/Fmove_CM.svg @@ -1,568 +1,643 @@ - +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK/7/ +qzXlLxEPjEQAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjUtMDgtMDVUMTA6MjM6NDErMDA6MDA4hLdb +AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI1LTA4LTA1VDEwOjIzOjQxKzAwOjAwSdkP5wAAACh0RVh0 +ZGF0ZTp0aW1lc3RhbXAAMjAyNS0wOC0wNVQxMDoyMzo0MSswMDowMB7MLjgAAAAndEVYdHBkZjpI +aVJlc0JvdW5kaW5nQm94ADIyMC44MzZ4NzQuMzEzKzArMLY+05sAAAATdEVYdHBkZjpWZXJzaW9u +AFBERi0xLjVTNlrBAAAAAElFTkSuQmCC" /> diff --git a/docs/src/man/img/Fmove_CMD.svg b/docs/src/man/img/Fmove_CMD.svg index 8188d12..5921d97 100644 --- a/docs/src/man/img/Fmove_CMD.svg +++ b/docs/src/man/img/Fmove_CMD.svg @@ -1,600 +1,659 @@ - +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADhn/3/XU3Tb +OxTQcgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyNS0wOC0wNVQxMDoyMzo1MyswMDowMGOxpuwAAAAl +dEVYdGRhdGU6bW9kaWZ5ADIwMjUtMDgtMDVUMTA6MjM6NTMrMDA6MDAS7B5QAAAAKHRFWHRkYXRl +OnRpbWVzdGFtcAAyMDI1LTA4LTA1VDEwOjIzOjUzKzAwOjAwRfk/jwAAACd0RVh0cGRmOkhpUmVz +Qm91bmRpbmdCb3gAMjIzLjYwOXg3NC4yMzYrMCswuGzkmQAAABN0RVh0cGRmOlZlcnNpb24AUERG +LTEuNVM2WsEAAAAASUVORK5CYII=" /> diff --git a/docs/src/man/img/Fmove_D.svg b/docs/src/man/img/Fmove_D.svg index 7f41906..0cce4f1 100644 --- a/docs/src/man/img/Fmove_D.svg +++ b/docs/src/man/img/Fmove_D.svg @@ -1,579 +1,634 @@ - +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFPr/ +AwCXSnVnsz/gAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI1LTA4LTA1VDEwOjI0OjE0KzAwOjAwwICN +4QAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNS0wOC0wNVQxMDoyNDoxNCswMDowMLHdNV0AAAAodEVY +dGRhdGU6dGltZXN0YW1wADIwMjUtMDgtMDVUMTA6MjQ6MTQrMDA6MDDmyBSCAAAAJ3RFWHRwZGY6 +SGlSZXNCb3VuZGluZ0JveAAyMTguMzEyeDc1Ljc0NyswKzD8rKWqAAAAE3RFWHRwZGY6VmVyc2lv +bgBQREYtMS41UzZawQAAAABJRU5ErkJggg==" /> diff --git a/docs/src/man/img/Fmove_MD.svg b/docs/src/man/img/Fmove_MD.svg index 3cf3b0e..8dc4fe3 100644 --- a/docs/src/man/img/Fmove_MD.svg +++ b/docs/src/man/img/Fmove_MD.svg @@ -1,601 +1,665 @@ - +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 +TkSuQmCC" /> diff --git a/docs/src/man/img/Fmove_coloring.svg b/docs/src/man/img/Fmove_coloring.svg new file mode 100644 index 0000000..804e15d --- /dev/null +++ b/docs/src/man/img/Fmove_coloring.svg @@ -0,0 +1,2336 @@ + + + + diff --git a/docs/src/man/img/Nsymbol_coloring.svg b/docs/src/man/img/Nsymbol_coloring.svg index 2409403..1fcf989 100644 --- a/docs/src/man/img/Nsymbol_coloring.svg +++ b/docs/src/man/img/Nsymbol_coloring.svg @@ -1,1456 +1,1208 @@ - +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACa/w/u3IUmUFWevwAAACV0 +RVh0ZGF0ZTpjcmVhdGUAMjAyNS0wOC0wNVQxMDoyNDo1MCswMDowMLCFpwgAAAAldEVYdGRhdGU6 +bW9kaWZ5ADIwMjUtMDgtMDVUMTA6MjQ6NTArMDA6MDDB2B+0AAAAKHRFWHRkYXRlOnRpbWVzdGFt +cAAyMDI1LTA4LTA1VDEwOjI0OjUwKzAwOjAwls0+awAAACh0RVh0cGRmOkhpUmVzQm91bmRpbmdC +b3gAMjAwLjE4NHgxNTIuOTI5KzArMLmBYyMAAAATdEVYdHBkZjpWZXJzaW9uAFBERi0xLjVTNlrB +AAAAAElFTkSuQmCC" /> diff --git a/docs/src/man/img/homvector.svg b/docs/src/man/img/homvector.svg index 7868fc9..afec038 100644 --- a/docs/src/man/img/homvector.svg +++ b/docs/src/man/img/homvector.svg @@ -1,338 +1,277 @@ - +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 +gg==" /> diff --git a/docs/src/man/img/qdim_fs_MF.svg b/docs/src/man/img/qdim_fs_MF.svg index 24c186e..9ec6610 100644 --- a/docs/src/man/img/qdim_fs_MF.svg +++ b/docs/src/man/img/qdim_fs_MF.svg @@ -1,545 +1,382 @@ - + From 7082cbf6612a092613a7d240ae5d4faa788b7c53 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 12:04:17 +0200 Subject: [PATCH 117/206] add pentagon image --- docs/src/man/img/pentagon_colored.svg | 3478 +++++++++++++++++++++++++ 1 file changed, 3478 insertions(+) create mode 100644 docs/src/man/img/pentagon_colored.svg diff --git a/docs/src/man/img/pentagon_colored.svg b/docs/src/man/img/pentagon_colored.svg new file mode 100644 index 0000000..15b59e1 --- /dev/null +++ b/docs/src/man/img/pentagon_colored.svg @@ -0,0 +1,3478 @@ + + + + From c063b4863f0b5b69052bb5e06915b3431ea1342c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 12:04:33 +0200 Subject: [PATCH 118/206] get assets working --- docs/make.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 9ae7d4c..14aeebe 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -17,9 +17,9 @@ mathengine = MathJax3(Dict(:loader => Dict("load" => ["[tex]/physics"]), "mathtools"]))) makedocs(; sitename="MultiTensorKit.jl", modules=[MultiTensorKit], - # assets=["assets/custom.css"], authors="Boris De Vos, Laurens Lootens and Lukas Devos", pages=pages, pagesonly=true, plugins=[bib], - format=Documenter.HTML(; mathengine=mathengine)) + format=Documenter.HTML(; prettyurls=true, mathengine=mathengine, + assets=["assets/custom.css"])) -deploydocs(; repo="https://github.com/QuantumKitHub/MultiTensorKit.jl") \ No newline at end of file +deploydocs(; repo="https://github.com/QuantumKitHub/MultiTensorKit.jl", push_preview = true) \ No newline at end of file From 2a19867146e2cf674a9fc997ffa9425b9d3c38a2 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 12:04:44 +0200 Subject: [PATCH 119/206] more docs --- docs/src/man/Implementation.md | 51 +++++++++++++++++++++++---------- docs/src/man/multifusioncats.md | 32 +++++++++++++++++---- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/docs/src/man/Implementation.md b/docs/src/man/Implementation.md index ef69e0f..e9d3677 100644 --- a/docs/src/man/Implementation.md +++ b/docs/src/man/Implementation.md @@ -1,12 +1,12 @@ explain the f-symbol and n-symbol storage system -# MultiTensorKit implementation: $\mathsf{Rep_{A_4}}$ as an example +# MultiTensorKit implementation: $\mathsf{Rep(A_4)}$ as an example This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep_{A_4}}$. Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. There are 3 fusion categories up to equivalence: -- $\mathsf{Vec A_4}$: the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$. It has thus 12 objects. -- $\mathsf{Rep_{A_4}}$: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. One is the trivial representation, two are one-dimension non-trivial and the last is three-dimensional. -- $\mathsf{Rep H}$: the representation category of some Hopf algebra which does not have a name. It has 6 simple objects. +- $\mathsf{Vec_{A_4}}$, the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$. It has thus 12 objects. +- $\mathsf{Rep(A_4)}$: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. One is the trivial representation, two are one-dimensional non-trivial and the last is three-dimensional. +- $\mathsf{Rep(H)}$: the representation category of some Hopf algebra which does not have a name. It has 6 simple objects. ````julia using TensorKit, MultiTensorKit, MPSKit, MPSKitModels @@ -48,7 +48,7 @@ The dual object of some simple object $a$ of an arbitrary subcategory $\mathcal{ $$ ^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* \times a,$$ with multiplicity 1. -## Hamiltonian +## Constructing the Hamiltonian and matrix product state TensorKit has been made compatible with the multifusion structure by keeping track of the relevant units in the fusion tree manipulations. With this, we can make `GradedSpace`s whose objects are in `A4Object`: ````julia @@ -56,9 +56,8 @@ D1 = A4Object(6, 6, 1) # unit in this case D2 = A4Object(6, 6, 2) # non-trivial 1d irrep D3 = A4Object(6, 6, 3) # non-trivial 1d irrep D4 = A4Object(6, 6, 4) # 3d irrep - ```` -Since we want to replicate a spin-1 Heisenberg model, it makes sense to use the 3-dimensional irrep to grade the physical space, and thus construct our Hamiltonian. We don't illustrate here how to derive the considered Hamiltonian in a $\mathsf{Rep(A_4)}$ basis, but simply give it. +Since we want to replicate a spin-1 Heisenberg model, it makes sense to use the 3-dimensional irrep to grade the physical space, and thus construct our Hamiltonian. We don't illustrate here how to derive the considered Hamiltonian in a $\mathsf{Rep(A_4)}$ basis, but simply give it. For now, we construct a finite-size spin chain; below we will repeat the calculation for an infinite system. ````julia P = Vect[A4Object](D4 => 1) # physical space @@ -84,8 +83,8 @@ block(h3_R, D4) .= [0 1;] @plansor h3[-1 -2; -3 -4] := h3_L[-1 1; -3] * h3_R[-2; 1 -4] L = 60 -J1 = 1.0 # probing the A4 SPT phase first -J2 = 1.0 +J1 = -2.0 # probing the A4 SSB phase first +J2 = -5.0 lattice = FiniteChain(L) H1 = @mpoham sum(-2 * h1{i,j} for (i, j) in nearest_neighbours(lattice)) H2 = @mpoham sum(h2{i,j} for (i, j) in nearest_neighbours(lattice)) @@ -94,14 +93,11 @@ H3 = @mpoham sum(2im * h3{i,j} for (i, j) in nearest_neighbours(lattice)) H = H1 + J1 * H2 + J3 * H3 ```` - -## Constructing the matrix product state -For now, we will select $\mathsf{Vec}$ as the module category: +For the matrix product state, we will select $\mathsf{Vec}$ as the module category for now: ````julia M = A4Object(1, 6, 1) # Vec ```` - - Afterwards, we build the physical and virtual space of the matrix product state: +and construct the finite MPS: ````julia D = 40 # bond dimension V = Vect[A4Object](M => D) @@ -109,7 +105,32 @@ Vb = Vect[A4Object](M => 1) # non-degenerate boundary virtual space init_mps = FiniteMPS(L, P, V; left=Vb, right=Vb) ```` > [!IMPORTANT] -> We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for `BimoduleSector` due to the semisimple unit. +> We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for any `BimoduleSector` due to the semisimple unit. + +## DMRG2 and the entanglement spectrum +We can now look to find the ground state of the Hamiltonian with two-site DMRG. We use this instead of the "usual" one-site DMRG because the two-site one will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. +````julia +dmrg2alg = DMRG2(;verbosity=2, tol=1e-8, trscheme=truncbelow(1e-4)) +ψ, _ = find_groundstate(init_mps, H, dmrg2alg) +```` +The truncation scheme keyword argument is mandatory when calling `DMRG2` in MPSKit. Here, we choose to truncate such that all singular values are larger than $10^{-4}$, while setting the default tolerance for convergence to $10^{-8}$. More information on this can be found in the [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl) documentation. + +Now that we've found the ground state, we can compute the entanglement spectrum in the middle of the chain. +````julia +spec = entanglement_spectrum(ψ, round(Int, L/2)) +```` +This returns a dictionary which maps the objects grading the virtual space to the singular values. In this case, there is one key corresponding to $\mathsf{Vec}$. We can also immediately return a plot of this data by the following: +````julia +using Plots # ! +entanglementplot(ψ;site=round(Int, L/2)) +```` +This plot will show the singular values per object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. #TODO: actually include the plot (or run everything as ipynb) + +## Search for the correct dual model + +Consider a quantum lattice model with its symmetries determing the phase diagram. For every phase in the phase diagram, the dual model for which the ground state maximally breaks all symmetries spontaneously is the one where the entanglement is minimised and the tensor network is represented most efficiently [Lootens_2024](@cite). Let us confirm this result, starting with the $\mathsf{Rep(A_4)}$ spontaneous symmetry breaking phase. + + diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index bf8f9bf..8077334 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -120,7 +120,11 @@ The simplest non-trivial fusion diagram is a trivalent junction: The most general case is the top left figure, where all three regions have a different coloring. The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. However, as will be explained more in detail later, this most general trivalent junction with three colorings will never be needed. In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. This is displayed in the top middle and right. Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. This is shown in the bottom right. -With this coloring system, we can specify which associator must be called to perform a particular F-move. SHOW THE COLORS +With this coloring system, we can specify which associator must be called to perform a particular F-move. Such an F-move would look like + +```@raw html + +``` ### Why opposite module categories end up being necessary in MultiTensorKit @@ -147,17 +151,33 @@ In the multifusion setting, this can also be seen graphically. By keeping track ``` -where by $\mathbb{1}_a$ we mean the right unit of $a$ (the left unit we would denote $^{}_a \mathbb{1}$). +where by $\mathbb{1}_j$ we mean the unit of $\mathcal{C}_j$. + +### More on the topological data: gauge choices and distilling properties of the subcategories + +The most generic F-move contains 4 colors. For that reason, MultiTensorKit will require the F-symbol data to provided as some data file (currently .txt) with 4 + 6 + 4 + 2 = 16 columns. The first 4 refer to the colors, the following 6 label the simple objects of the corresponding subcategories, the next 4 label multiplicities, and the final 2 provide the real and imaginary value of the F-symbol itself. + +In a similar manner, the N-symbols contain maximally three colors, so these data must provide 3 columns labeling the colors, 3 columns labeling the simple objects and a final column with the dimension of the corresponding vector space. -Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{a \bar{a} a}_{a}$ needs to be evaluated for these topological data. Graphically, we find that +Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{c \bar{c} c}_{c}$ needs to be evaluated for these topological data. Graphically, we find that ```@raw html - + ``` -need to show other changed expressions like A-move, dimension, frobenius-schur indicator, what else outside of TensorKitSectors in terms of fusion tree manipulations? +An important property of the F-symbols is that they must satisfy the **triangle identities**. In fusion category theory, this states that isomorphisms between (simple) objects $a$ and the tensor product between $a$ and the unit $\mathbb{1}$ exists, and that + +$$(a \otimes \mathbb{1}) \otimes b \cong a \otimes (\mathbb{1} \otimes b)$$ + +for $b$ in the same fusion category. This can be straightforwardly generalised to multifusion categories. This requires a particular gauging of these trivalent vertices. + +Besides the triangle identities, the (multi)fusion category must also fulfill the **pentagon equations**. These encapsulate the two identical manners to evaluating the fusion of four objects in the (multi)fusion category. Every fusion category's F-symbols must satisfy these individually, but also the (bi)module associators between bimodule and fusion categories. One can check that, for every pair of fusion categories, their bimodule category and opposite bimodule category, there are 32 pentagon equations to be satisfied. In the multifusion notation, they can be represented by + +```@raw html + +``` -no figures up till now with arrows, will this even be necessary? maybe if we show B-moves with M->Mop +We briefly mentioned earlier how unitary F-symbols are required within TensorKit, and thus necessarily MultiTensorKit. ### Braiding A very important aspect of MultiTensorKit is that all `BimoduleSector`s are defined to *not* support braiding: `TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding()`. We do this for two reasons. On the one hand, there is no natural 1-categorical way of defining braidings between the components of the multifusion category. It is possible that the diagonal fusion categories themselves are braided, but a "componentwise" braiding is unwise to support. On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. From a683b85b6aba6c6b7297ffc9aa5e2cc577416c10 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 12:16:12 +0200 Subject: [PATCH 120/206] rename --- docs/src/man/{Implementation.md => implementation.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/src/man/{Implementation.md => implementation.md} (100%) diff --git a/docs/src/man/Implementation.md b/docs/src/man/implementation.md similarity index 100% rename from docs/src/man/Implementation.md rename to docs/src/man/implementation.md From cd42e10914cb72a201545c1cdcf94b25b89af256 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 13:03:52 +0200 Subject: [PATCH 121/206] invert images + fix existing markdown errors --- docs/src/man/fusioncats.md | 4 +-- docs/src/man/implementation.md | 43 ++++++++++++++++++++------------- docs/src/man/multifusioncats.md | 24 +++++++++--------- 3 files changed, 40 insertions(+), 31 deletions(-) diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index cde99dc..3a8da52 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -26,14 +26,14 @@ This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C} Vectors in these hom-spaces are graphically denoted as living in the trivalent junction ```@raw html - + ``` With the F-symbol, we can perform F-moves: ```@raw html - + ``` TensorKit requires the F-symbols to be unitary. This way, we can interpret the F-symbol $F^{ijk}_l$ as a unitary matrix, and the F-move as a unitary basis transformation. Unitarity is also useful from a diagrammatic point of view because the category is then equipped with a pivotal and spherical structure. This essentially means that morphisms can be drawn and moved around freely on a 2-sphere, such that vector spaces can be moved freely from domain (codomain) to codomain (domain). diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index e9d3677..b0d5149 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -3,24 +3,26 @@ explain the f-symbol and n-symbol storage system # MultiTensorKit implementation: $\mathsf{Rep(A_4)}$ as an example This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. -This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep_{A_4}}$. Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. There are 3 fusion categories up to equivalence: -- $\mathsf{Vec_{A_4}}$, the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$. It has thus 12 objects. -- $\mathsf{Rep(A_4)}$: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. One is the trivial representation, two are one-dimensional non-trivial and the last is three-dimensional. -- $\mathsf{Rep(H)}$: the representation category of some Hopf algebra which does not have a name. It has 6 simple objects. +This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep(A_4)}$. Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. There are 3 fusion categories up to equivalence: +- ``\mathsf{Vec_{A_4}}``: the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$. It has thus 12 objects. +- ``\mathsf{Rep(A_4)}``: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. One is the trivial representation, two are one-dimensional non-trivial and the last is three-dimensional. +- ``\mathsf{Rep(H)}``: the representation category of some Hopf algebra which does not have a name. It has 6 simple objects. +For this example, we will require the following packages: ````julia using TensorKit, MultiTensorKit, MPSKit, MPSKitModels ```` ## Identifying the simple objects -We first need to select which fusion category we wish to use to grade the physical Hilbert space, and which fusion category to represent e.g. the symmetry category. In our case, we are interested in selecting $\mathcal{D} = \mathsf{Rep(A_4)}$ for the physical Hilbert space. We know the module categories over $\mathsf{Rep(G)}$ to be $\mathsf{Rep^\psi(H)}$ for a subgroup $\mathsf{H} and 2-cocycle $\psi$. Thus, the 7 module categories $\mathcal{M}$ one can choose over $\mathsf{Rep(A_4)}$ are -- $\mathsf{Rep(A_4)}$ itself as the regular module category, -- $\mathsf{Vec}$: the category of vector spaces, -- $\mathsf{Rep(\mathbb{Z}_2)}$, -- $\mathsf{Rep(\mathbb{Z}_3)}$, -- $\mathsf{Rep(\mathbb{Z}_2 \times \mathbb{Z}_2)}$, -- $\mathsf{Rep^\psi(\mathbb{Z}_2 \times \mathbb{Z}_2)}$, -- $\mathsf{Rep^\psi(A_4)}$. +We first need to select which fusion category we wish to use to grade the physical Hilbert space, and which fusion category to represent e.g. the symmetry category. In our case, we are interested in selecting $\mathcal{D} = \mathsf{Rep(A_4)}$ for the physical Hilbert space. We know the module categories over $\mathsf{Rep(G)}$ to be $\mathsf{Rep^\psi(H)}$ for a subgroup $\mathsf{H}$ and 2-cocycle $\psi$. Thus, the 7 module categories $\mathcal{M}$ one can choose over $\mathsf{Rep(A_4)}$ are + +- ``\mathsf{Rep(A_4)}`` itself as the regular module category, +- ``\mathsf{Vec}``: the category of vector spaces, +- ``\mathsf{Rep(\mathbb{Z}_2)}``, +- ``\mathsf{Rep(\mathbb{Z}_3)}``, +- ``\mathsf{Rep(\mathbb{Z}_2 \times \mathbb{Z}_2)}``, +- ``\mathsf{Rep^\psi(\mathbb{Z}_2 \times \mathbb{Z}_2)}``, +- ``\mathsf{Rep^\psi(A_4)}``. When referring to specific fusion and module categories, we will use this non-multifusion notation. @@ -34,7 +36,7 @@ one(A4Object(i,i,1)) Left and right units of subcategories are uniquely specified by their fusion rules. For example, the left unit of a subcategory $\mathcal{C}_{ij}$ is the simple object in $\mathcal{C}_i$ for which -$$ ^{}_a \mathbb{1} \times a = a \quad \forall a \in \mathcal{C}_i.$$ +$$^{}_a \mathbb{1} \times a = a \quad \forall a \in \mathcal{C}_i.$$ A similar condition uniquely defines the right unit of a subcategory. For fusion subcategories, a necessary condition is that the left and right units coincide. @@ -45,7 +47,7 @@ Identifying the other simple objects of a (not necessarily fusion) category requ The dual object of some simple object $a$ of an arbitrary subcategory $\mathcal{C}_{ij}$ is defined as the unique object $a^* \in \mathcal{C}_{ji}$ satisfying -$$ ^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* \times a,$$ +$$^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* \times a,$$ with multiplicity 1. ## Constructing the Hamiltonian and matrix product state @@ -104,8 +106,9 @@ V = Vect[A4Object](M => D) Vb = Vect[A4Object](M => 1) # non-degenerate boundary virtual space init_mps = FiniteMPS(L, P, V; left=Vb, right=Vb) ```` -> [!IMPORTANT] -> We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for any `BimoduleSector` due to the semisimple unit. + +!!! warning "Important" + We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for any `BimoduleSector` due to the semisimple unit. ## DMRG2 and the entanglement spectrum We can now look to find the ground state of the Hamiltonian with two-site DMRG. We use this instead of the "usual" one-site DMRG because the two-site one will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. @@ -128,7 +131,13 @@ This plot will show the singular values per object, as well as include the "effe ## Search for the correct dual model -Consider a quantum lattice model with its symmetries determing the phase diagram. For every phase in the phase diagram, the dual model for which the ground state maximally breaks all symmetries spontaneously is the one where the entanglement is minimised and the tensor network is represented most efficiently [Lootens_2024](@cite). Let us confirm this result, starting with the $\mathsf{Rep(A_4)}$ spontaneous symmetry breaking phase. +Consider a quantum lattice model with its symmetries determing the phase diagram. For every phase in the phase diagram, the dual model for which the ground state maximally breaks all symmetries spontaneously is the one where the entanglement is minimised and the tensor network is represented most efficiently [Lootens_2024](@cite). Let us confirm this result, starting with the $\mathsf{Rep(A_4)}$ spontaneous symmetry breaking phase. The code will look exactly the same as above, except the virtual space of the MPS will change to be graded by the other module categories: + +````julia +module_numlabels(i) = MultiTensorKit._numlabels(A4Object, i, 6) +V = Vect[A4Object](A4Object(i, 6, label) => D for label in 1:module_numlabels(i)) +Vb = Vect[A4Object](c => 1 for c in first(sectors(V))) # not all charges on boundary, play around with what is there +```` diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 8077334..fe77bff 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -10,7 +10,7 @@ $${}^\mathcal{D}\!F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) the **monoidal associator**. An F-move is now graphically portrayed as: ```@raw html - + ``` We can consider the **right module category** $\mathcal{M}$ over $\mathcal{D}$, which is a category (not necessarily fusion!) with (isomorphism classes of) simple objects $\mathcal{I}_\mathcal{M} = \{A,B,...\}$, a right action @@ -24,7 +24,7 @@ $${}^\triangleleft\!F^{A\alpha\beta}: A \triangleleft (\alpha \otimes \beta) \ri An F-move with this module associator can be expressed as: ```@raw html - + ``` The module structure of $\mathcal{M}$ is now defined as the triple $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$. The right module associator now satisfies a mixed pentagon equation with ${}^\mathcal{D}\!F$. @@ -40,7 +40,7 @@ $${}^\triangleright\!F^{abA}: (a \otimes b) \triangleright A \rightarrow a \tria for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. The left module associator also fulfills a mixed pentagon equation with ${}^\mathcal{C}\!F$. An F-move with ${}^\mathcal{C}\!F$ takes on the form: ```@raw html - + ``` We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, and $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as @@ -50,7 +50,7 @@ $${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F^{aA\alpha}: (a \triangle for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. The bimodule associator fulfills a mixed pentagon equation with the module associators. An F-move with ${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F$ is given by: ```@raw html - + ``` ## Opposite module categories Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). Then $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. A similar statement can be made starting from a left module category and getting an opposite right module category. In particular, given a $(\mathcal{C}, \mathcal{D})$-bimodule category $\mathcal{M}$ over the fusion categories $\mathcal{C}, \mathcal{D}$, we see immediately that $\mathcal{M}^{\text{op}}$ is a $(\mathcal{D}, \mathcal{C})$-bimodule category. @@ -115,7 +115,7 @@ Multifusion categories can also be interpreted as 2-categories. We still interpr The simplest non-trivial fusion diagram is a trivalent junction: ```@raw html - + ``` The most general case is the top left figure, where all three regions have a different coloring. The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. However, as will be explained more in detail later, this most general trivalent junction with three colorings will never be needed. In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. This is displayed in the top middle and right. Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. This is shown in the bottom right. @@ -123,7 +123,7 @@ The most general case is the top left figure, where all three regions have a dif With this coloring system, we can specify which associator must be called to perform a particular F-move. Such an F-move would look like ```@raw html - + ``` ### Why opposite module categories end up being necessary in MultiTensorKit @@ -136,7 +136,7 @@ In principle, choosing to bend e.g. codomain legs to the right and domain legs t For this reason, at the level of the fusion trees the topological move that is performed to bend the legs along the right is called a **B-move**. Graphically, one can show that this bend boils down to a particular F-move. The typical equation found in the literature is the following: ```@raw html - + ``` ... The reason to only consider B-moves is rooted in the choice of canonical form of fusion trees within TensorKit, where fusions are iterated over from left to right and splittings from right to left. @@ -148,7 +148,7 @@ $$\mathcal{M}^* \simeq \mathcal{M}^\text{op}.$$ In the multifusion setting, this can also be seen graphically. By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: ```@raw html - + ``` where by $\mathbb{1}_j$ we mean the unit of $\mathcal{C}_j$. @@ -162,7 +162,7 @@ In a similar manner, the N-symbols contain maximally three colors, so these data Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{c \bar{c} c}_{c}$ needs to be evaluated for these topological data. Graphically, we find that ```@raw html - + ``` An important property of the F-symbols is that they must satisfy the **triangle identities**. In fusion category theory, this states that isomorphisms between (simple) objects $a$ and the tensor product between $a$ and the unit $\mathbb{1}$ exists, and that @@ -174,7 +174,7 @@ for $b$ in the same fusion category. This can be straightforwardly generalised t Besides the triangle identities, the (multi)fusion category must also fulfill the **pentagon equations**. These encapsulate the two identical manners to evaluating the fusion of four objects in the (multi)fusion category. Every fusion category's F-symbols must satisfy these individually, but also the (bi)module associators between bimodule and fusion categories. One can check that, for every pair of fusion categories, their bimodule category and opposite bimodule category, there are 32 pentagon equations to be satisfied. In the multifusion notation, they can be represented by ```@raw html - + ``` We briefly mentioned earlier how unitary F-symbols are required within TensorKit, and thus necessarily MultiTensorKit. @@ -189,9 +189,9 @@ $$\mathcal{C} = \begin{pmatrix} \mathcal{C}_1 & \mathcal{M} \\ \mathcal{M}^{\tex We already identified the off-diagonal elements with module categories over the fusion categories on the diagonal. Accordingly, $\mathcal{M}$ is a $(\mathcal{C}_1, \mathcal{C}_2)$-bimodule category, and $\mathcal{M}^{\text{op}}$ is the opposite module category and a $(\mathcal{C}_2, \mathcal{C}_1)$-bimodule category. -If we take $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep} \mathbb{Z}_2$ and $\mathcal{M} = \mathsf{Vec}$, then the entire multifusion category is isomorphic to the $\mathsf{Ising}$ category [etingof2016tensor; Example 4.10.5](@cite). We identify the trivial representation of $\mathsf{Rep} \mathbb{Z}_2$ with the unit of $\mathsf{Ising}$, the sign representation with $\psi$ and the unique object of $\mathsf{Vec}$ with the duality object $\sigma$. One can easily check that the fusion rules of $\mathsf{Ising}$ match with those we expect within $\mathsf{Rep} \mathbb{Z}_2$ and with its module category $\mathsf{Vec}$. Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (and vice-versa) giving every object in $\mathcal{C}_1$ ($\mathcal{C}_2$) is consistent with $\sigma \times \sigma^* = 1 + \psi$. This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). +If we take $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep}(\mathbb{Z}_2)$ and $\mathcal{M} = \mathsf{Vec}$, then the entire multifusion category is isomorphic to the $\mathsf{Ising}$ category [etingof2016tensor; Example 4.10.5](@cite). We identify the trivial representation of $\mathsf{Rep}(\mathbb{Z}_2)$ with the unit of $\mathsf{Ising}$, the sign representation with $\psi$ and the unique object of $\mathsf{Vec}$ with the duality object $\sigma$. One can easily check that the fusion rules of $\mathsf{Ising}$ match with those we expect within $\mathsf{Rep}(\mathbb{Z}_2)$ and with its module category $\mathsf{Vec}$. Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (and vice-versa) giving every object in $\mathcal{C}_1$ ($\mathcal{C}_2$) is consistent with $\sigma \times \sigma^* = 1 + \psi$. This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). -This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep_G}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is isomorphic to the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep_G}$. +This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is isomorphic to the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. ## Module and multifusion categories in condensed matter physics - boundaries of string-net models From 9053fa4c0da2ded6ee4613380cd8e77f6fd4a5df Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 14:48:10 +0200 Subject: [PATCH 122/206] change ordering of pages --- docs/make.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 14aeebe..4e93ef2 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -2,8 +2,9 @@ using Documenter using DocumenterCitations using MultiTensorKit -pages = ["Home" => "index.md", "Library" => "lib/library.md", +pages = ["Home" => "index.md", "Manual" => ["man/fusioncats.md", "man/multifusioncats.md", "man/implementation.md"], + "Library" => "lib/library.md", "References" => "references.md"] # bibliography From 854daca5cee5cc8fc37ecf26d099834f8336ea0b Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 14:48:55 +0200 Subject: [PATCH 123/206] attempt to fix toc --- docs/src/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index 01474e4..63c1b2d 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -13,7 +13,7 @@ tensor network simulations of quantum many-body systems with aid of [MPSKit.jl]( ## Table of contents ```@contents -Pages = ["man/fusioncats.md", "man/multifusioncats.md","lib/library.md", "references.md"] +Pages = ["man/fusioncats.md","man/multifusioncats.md","lib/library.md", "references.md"] Depth = 2 ``` @@ -30,5 +30,5 @@ As the name suggests, MultiTensorKit is an extension of [TensorKit.jl](https://g [TensorKitSectors.jl](https://github.com/QuantumKitHub/TensorKitSectors.jl). Therefore, we recommend including TensorKit to your project. Additionally, MultiTensorKit was made to be functional with [MPSKit.jl](https://github.com/QuantumKitHub/MPSKit.jl) and [MPSKitModels.jl](https://github.com/QuantumKitHub/MPSKitModels.jl) for Matrix Product State (MPS) calculations, supporting symmetries -which go beyond TensorKit. +which go beyond TensorKit. All these packages are registered in JuliaRegistries and can be added through the package manager. From ec807b77e373879900c9bae49b5de5b689df235a Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 14:49:10 +0200 Subject: [PATCH 124/206] shorten references title --- docs/src/references.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/references.md b/docs/src/references.md index d0f92e9..4b47677 100644 --- a/docs/src/references.md +++ b/docs/src/references.md @@ -1,4 +1,4 @@ -# References used in documentation +# References ```@bibliography ``` \ No newline at end of file From 1ae9332f12f350324d7cf73e0387f2b0556bb2fe Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 14:49:37 +0200 Subject: [PATCH 125/206] second to last touches to example --- docs/src/man/implementation.md | 52 +++++++++++----------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index b0d5149..ed0248a 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -1,6 +1,6 @@ explain the f-symbol and n-symbol storage system -# MultiTensorKit implementation: $\mathsf{Rep(A_4)}$ as an example +# MultiTensorKit implementation: $\mathsf{Rep(A_4)}$ as a guiding example This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep(A_4)}$. Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. There are 3 fusion categories up to equivalence: @@ -10,7 +10,7 @@ This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is th For this example, we will require the following packages: ````julia -using TensorKit, MultiTensorKit, MPSKit, MPSKitModels +using TensorKit, MultiTensorKit, MPSKit, MPSKitModels, Plots ```` ## Identifying the simple objects @@ -113,10 +113,10 @@ init_mps = FiniteMPS(L, P, V; left=Vb, right=Vb) ## DMRG2 and the entanglement spectrum We can now look to find the ground state of the Hamiltonian with two-site DMRG. We use this instead of the "usual" one-site DMRG because the two-site one will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. ````julia -dmrg2alg = DMRG2(;verbosity=2, tol=1e-8, trscheme=truncbelow(1e-4)) +dmrg2alg = DMRG2(;verbosity=2, tol=1e-7, trscheme=truncbelow(1e-4)) ψ, _ = find_groundstate(init_mps, H, dmrg2alg) ```` -The truncation scheme keyword argument is mandatory when calling `DMRG2` in MPSKit. Here, we choose to truncate such that all singular values are larger than $10^{-4}$, while setting the default tolerance for convergence to $10^{-8}$. More information on this can be found in the [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl) documentation. +The truncation scheme keyword argument is mandatory when calling `DMRG2` in MPSKit. Here, we choose to truncate such that all singular values are larger than $10^{-4}$, while setting the default tolerance for convergence to $10^{-7}$. More information on this can be found in the [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl) documentation. To run one-site DMRG anyway, use `DMRG` which does not require a truncation scheme. Now that we've found the ground state, we can compute the entanglement spectrum in the middle of the chain. ````julia @@ -124,10 +124,9 @@ spec = entanglement_spectrum(ψ, round(Int, L/2)) ```` This returns a dictionary which maps the objects grading the virtual space to the singular values. In this case, there is one key corresponding to $\mathsf{Vec}$. We can also immediately return a plot of this data by the following: ````julia -using Plots # ! entanglementplot(ψ;site=round(Int, L/2)) ```` -This plot will show the singular values per object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. #TODO: actually include the plot (or run everything as ipynb) +This plot will show the singular values per object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. #TODO: actually include the plot ## Search for the correct dual model @@ -139,38 +138,21 @@ V = Vect[A4Object](A4Object(i, 6, label) => D for label in 1:module_numlabels(i) Vb = Vect[A4Object](c => 1 for c in first(sectors(V))) # not all charges on boundary, play around with what is there ```` +#TODO: show all the plots +!!! note "Additional functions and keyword arguments" + Certain commonly used functions within MPSKit require extra keyword arguments to be compatible with multifusion MPS simulations. In particular, the keyword argument `sector` (note the lowercase "s") appears in + - `transfer_spectrum`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the sectors lie in the symmetry category $\mathcal{C} = \mathcal{D^*_M}$. + - `correlation_length`: since this function calls `transfer_spectrum`, the same logic applies. + - `excitations` with `QuasiparticleAnsatz`: similar to the previous functions, charged excitations are selected by adding a charged auxiliary space to the eigenvectors representing the quasiparticle states. + - `exact_diagonalization`: the `sector` keyword argument now requires an object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. - - -### Infinite case -Now, using MPKSit, we can perform matrix product state calculations. We construct some nearest-neighbour Hamiltonian and find the MPS representation of the ground state. +## Differences with the infinite case +We can repeat the above calcalations also for an infinite system. The `lattice` variable will change, as well as the MPS constructor and the algorithm: ````julia -h = ones(ComplexF64, P βŠ— P ← P βŠ— P) -H = @mpoham -sum(h{i,j} for (i,j) in nearest_neighbours(InfiniteChain(1))) +lattice = InfiniteChain(1) init = InfiniteMPS([P], [V]) - -gs, envs = find_groundstate(init, H, VUMPS()) -```` - -Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `Sector`. - -A couple of MPSKit functions require an additional keyword argument `sector` (note the lowercase "s") specifying which sector to target within the function. These are: -- `transfer_spectrum`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D}$), the sectors lie in the symmetry category $\mathcal{C}$. -- `correlation_length`: since this function calls `transfer_spectrum`, the same logic applies. -- `excitations` with `QuasiparticleAnsatz`: similar to the previous functions, charged excitations are selected by adding a charged auxiliary space to the eigenvectors representing the quasiparticle states. - -### Finite case -There are minor differences to pay attention to when simulating matrix product states with a finite length. The first noticeable difference is in the `FiniteMPS` constructor itself to build an initial state. We must pass on a left and right virtual space to the keyword arguments `left` and `right`, since these would by default try to place a trivial space of the `Sector`, which does not exist for `BimoduleSector` due to the semisimple unit. Performing parallel calculations to the previous section now looks like - -````julia -L = 10 # length of the MPS -init = FiniteMPS(L, P, V; left=V, right=V) # put Vec on the boundaries as well -H = @mpoham sum(h{i,j} for (i,j) in nearest_neighbours(FiniteChain(L))) - -gs, envs = find_groundstate(init, H, DMRG()) +inf_alg = VUMPS(; verbosity=2, tol=1e-7) ```` -`DMRG2` will run in a similar manner. Additional `sector` keywords are present for the following: -- `exact_diagonalization`: the `sector` keyword argument now requires an object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. -- `excitations` with `QuasiparticleAnsatz`: see infinite case. \ No newline at end of file +Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `Sector`. It is also clear that boundary terms do not play a role in this case. \ No newline at end of file From f0cf1260033aeb7ed4600a64526005f5dcf049c1 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 15:20:39 +0200 Subject: [PATCH 126/206] some reshuffling --- docs/src/man/fusioncats.md | 2 +- docs/src/man/implementation.md | 4 +--- docs/src/man/multifusioncats.md | 23 ++++++++++++----------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 3a8da52..c9ed7b2 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -7,7 +7,7 @@ Afterwards, the extension to multifusion categories is explained, and its relati # Fusion category theory -The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [TensorKit documentation](https://jutho.github.io/TensorKit.jl/stable/man/categories/) or the book Tensor Categories [etingof2016tensor](@cite). +The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/) documentation or the book Tensor Categories [etingof2016tensor](@cite). Let us start simple and introduce the **fusion ring** $\mathcal{C}$ in a black-box manner. This ring * consists of finitely many simple objects $\{ X_1, X_2, ..., X_R \}$, with $R$ the rank of the fusion ring, diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index ed0248a..79d43ef 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -1,5 +1,3 @@ -explain the f-symbol and n-symbol storage system - # MultiTensorKit implementation: $\mathsf{Rep(A_4)}$ as a guiding example This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. @@ -47,7 +45,7 @@ Identifying the other simple objects of a (not necessarily fusion) category requ The dual object of some simple object $a$ of an arbitrary subcategory $\mathcal{C}_{ij}$ is defined as the unique object $a^* \in \mathcal{C}_{ji}$ satisfying -$$^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* \times a,$$ +$$^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* \times a$$ with multiplicity 1. ## Constructing the Hamiltonian and matrix product state diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index fe77bff..ee9d84c 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -155,29 +155,30 @@ where by $\mathbb{1}_j$ we mean the unit of $\mathcal{C}_j$. ### More on the topological data: gauge choices and distilling properties of the subcategories -The most generic F-move contains 4 colors. For that reason, MultiTensorKit will require the F-symbol data to provided as some data file (currently .txt) with 4 + 6 + 4 + 2 = 16 columns. The first 4 refer to the colors, the following 6 label the simple objects of the corresponding subcategories, the next 4 label multiplicities, and the final 2 provide the real and imaginary value of the F-symbol itself. +An important property of the F-symbols is that they must satisfy the **triangle identities**. In fusion category theory, this states that isomorphisms between (simple) objects $a$ and the tensor product between $a$ and the unit $\mathbb{1}$ exists, and that -In a similar manner, the N-symbols contain maximally three colors, so these data must provide 3 columns labeling the colors, 3 columns labeling the simple objects and a final column with the dimension of the corresponding vector space. +$$(a \otimes \mathbb{1}) \otimes b \cong a \otimes (\mathbb{1} \otimes b)$$ -Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{c \bar{c} c}_{c}$ needs to be evaluated for these topological data. Graphically, we find that +for $b$ in the same fusion category. This can be straightforwardly generalised to multifusion categories. This requires a particular partial gauging of these trivalent vertices. + +Besides the triangle identities, the (multi)fusion category must also fulfill the **pentagon equations**. These encapsulate the two identical manners to evaluating the fusion of four objects in the (multi)fusion category. Every fusion category's F-symbols must satisfy these individually, but also the (bi)module associators between bimodule and fusion categories. One can check that, for every pair of fusion categories, their bimodule category and opposite bimodule category, there are 32 pentagon equations to be satisfied. In the multifusion notation, they can be represented by ```@raw html - + ``` -An important property of the F-symbols is that they must satisfy the **triangle identities**. In fusion category theory, this states that isomorphisms between (simple) objects $a$ and the tensor product between $a$ and the unit $\mathbb{1}$ exists, and that - -$$(a \otimes \mathbb{1}) \otimes b \cong a \otimes (\mathbb{1} \otimes b)$$ +The most generic F-move contains 4 colors. For that reason, MultiTensorKit requires the F-symbol data to be provided as some data file (currently .txt) with 4 + 6 + 4 + 2 = 16 columns. The first 4 refer to the colors, the following 6 label the simple objects of the corresponding subcategories, the next 4 label multiplicities, and the final 2 provide the real and imaginary value of the F-symbol itself. -for $b$ in the same fusion category. This can be straightforwardly generalised to multifusion categories. This requires a particular gauging of these trivalent vertices. +In a similar manner, the N-symbols contain maximally three colors, so these data must provide 3 columns labeling the colors, 3 columns labeling the simple objects and a final column with the dimension of the corresponding vector space. -Besides the triangle identities, the (multi)fusion category must also fulfill the **pentagon equations**. These encapsulate the two identical manners to evaluating the fusion of four objects in the (multi)fusion category. Every fusion category's F-symbols must satisfy these individually, but also the (bi)module associators between bimodule and fusion categories. One can check that, for every pair of fusion categories, their bimodule category and opposite bimodule category, there are 32 pentagon equations to be satisfied. In the multifusion notation, they can be represented by +Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{c \bar{c} c}_{c}$ needs to be evaluated for these topological data, which is in fact another gauge fixing. Graphically, we find ```@raw html - + ``` +In principle, a gauge fixing can be done to set the Frobenius-Schur indicator to $\pm 1$. However, this assumption is no longer required within TensorKit and can be relaxed to just be a phase. -We briefly mentioned earlier how unitary F-symbols are required within TensorKit, and thus necessarily MultiTensorKit. +The above gauge fixing is a property of the unitary gauge. By choosing appropriate bases, one can transform the F-symbols of a (multi)fusion category to be unitary matrices. More details on the importance of unitary data can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/#ss_topologicalfusion) documentation. ### Braiding A very important aspect of MultiTensorKit is that all `BimoduleSector`s are defined to *not* support braiding: `TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding()`. We do this for two reasons. On the one hand, there is no natural 1-categorical way of defining braidings between the components of the multifusion category. It is possible that the diagonal fusion categories themselves are braided, but a "componentwise" braiding is unwise to support. On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. From 843444723563b4e600622ddc5382d6e98b43f250 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 15:24:38 +0200 Subject: [PATCH 127/206] add reference to text --- docs/src/man/multifusioncats.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index ee9d84c..f8b2452 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -110,7 +110,7 @@ $$\mathcal{C}_{ij} \times \mathcal{C}_{ji} \rightarrow \mathcal{C}_i,$$ just like what we concluded when considering opposite module categories outside of the multifusion structure. ### 2-category and coloring -Multifusion categories can also be interpreted as 2-categories. We still interpret the objects of this 2-category the same way. The 1-morphisms are the subcategories themselves, and the 2-morphisms the morphisms of the multifusion category. The graphical calculus of monoidal 1-categories can be extended to 2-categories by use of *colorings*. We have previously differed between module strands and fusion strands by the color of the strand itself. However, in 2-categories the strands (1-morphisms) separate regions which are colored based on the objects they are representing. Since we draw the strands vertically, a single strand results in a left and right region, and the colorings will determine the fusion category which fuses from the left or right with that single strand. In particular, fusion strands necessarily have the same coloring on the left and right, while module strands have a mismatching coloring. +Multifusion categories can also be interpreted as 2-categories. We still interpret the objects of this 2-category the same way. The 1-morphisms are the subcategories themselves, and the 2-morphisms the morphisms of the multifusion category. The graphical calculus of monoidal 1-categories can be extended to 2-categories by use of *colorings* [henriques2020](@cite). We have previously differed between module strands and fusion strands by the color of the strand itself. However, in 2-categories the strands (1-morphisms) separate regions which are colored based on the objects they are representing. Since we draw the strands vertically, a single strand results in a left and right region, and the colorings will determine the fusion category which fuses from the left or right with that single strand. In particular, fusion strands necessarily have the same coloring on the left and right, while module strands have a mismatching coloring. The simplest non-trivial fusion diagram is a trivalent junction: From 6b928757db20ae8c33eab95d86e0f6f27abd5fde Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 15:38:19 +0200 Subject: [PATCH 128/206] fix homvector image --- docs/src/man/img/homvector.svg | 611 ++++++++++++++++++--------------- 1 file changed, 338 insertions(+), 273 deletions(-) diff --git a/docs/src/man/img/homvector.svg b/docs/src/man/img/homvector.svg index afec038..d019e1a 100644 --- a/docs/src/man/img/homvector.svg +++ b/docs/src/man/img/homvector.svg @@ -1,277 +1,342 @@ - +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 +UY2kdbLrkWqRAHBEqpG0TnY9Ui0SAI5INZIWyqpHqkUCwFGpRtJCWfVItUgAOCrVSFqpcj1SLRIA +jkw1klaqXI9UiwSAI1ONpKUq1SPVIgHg6FQjaalK9Ui1SAA4OtVIWqt0PVItEgAaoBpJa5WuR6pF +AkADVCNpsVL1SLVIAGiEaiQtVqoeqRYJAI1QjaTVdtYj1SIBoCGqkbTaznqkWiQANEQ1kpZ7tx6p +FgkAjVGNpOXerUeqRQJAY1Qjab2t9Ui1SABokGokrbe1HqkWCQANUo3kBGysR/6b+I/FSABojhjJ +Sdjwh/q3xd9req8AoMs0anOq/rbpHQCAbhMjOVX/tukdAIBuEyMBAMggRgIAkEGMBAAggxgJAEAG +MRIAgAxiJAAAGcRIAAAyiJEAAGQQIwEAyCBGAgCQQYwEACCDGAkAQAYxEgCADGIkAAAZxEgAADKI +kQAAZBAjAQDIIEYCAJBBjAQAIIMYCQBABjESAIAMYiQAABnESAAAMoiRAABkECMBAMggRgIAkEGM +BAAggxgJAEAGMRIAgAxiJAAAGcRIAAAyiJEAAGQQIwEAyCBGAgCQQYwEACCDGAkAQAYxEgCADGIk +AAAZxEgAADKIkQAAZBAjAQDIIEYCAJBBjAQAIIMYCQBABjESAIAMYiQAABnESAAAMoiRAABkECMB +AMggRgIAkEGMBAAggxgJAEAGMRIAgAxiJAAAGcRIAAAyiJEAAGQQIwEAyCBGAgCQQYwEACCDGAkA +QAYxEgCADGIkAAAZxEgAADKIkQAAZBAjAQDIIEYCAJBBjAQAIIMYCQBABjESAIAMYiQAABnESAAA +MoiRAABkECMBAMggRgIAkEGMBAAggxgJAEAGMRIAgAxiJAAAGcRIAAAyiJEAAGQQIwEAyCBGAgCQ +QYwEACCDGAkAQAYxEgCADGIkAAAZxEgAADKIkQAAZBAjAQDIIEYCAJBBjAQAIIMYCQBABjESAIAM +YiQAABnESAAAMoiRAABkECMBAMggRgIAkEGM5DSM1u4ZN71LANBtqWh6D6CENIyXpTum8bGYNr1X +ANBlqpGchGIU9ws3p3ErRAJAs1QjORmpHw8xjIhHIRIAmidGAgCQQaM2AAAZxEgAADKIkQAAZBAj +AQDIIEYCAJBBjAQAIIMYCQBABjESAIAMYiQAABnESAAAMoiRAABkECMBAMggRgIAkEGMBAAggxgJ +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" /> From 1a82c4e8fb2e33f1cada900d68f0b9c38a99c4f0 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 16:14:09 +0200 Subject: [PATCH 129/206] fix module fmove images --- docs/src/man/img/Fmove_CM.svg | 1281 ++++++++++++++++--------------- docs/src/man/img/Fmove_CMD.svg | 1319 ++++++++++++++++---------------- docs/src/man/img/Fmove_D.svg | 1269 +++++++++++++++--------------- docs/src/man/img/Fmove_MD.svg | 1315 +++++++++++++++---------------- 4 files changed, 2617 insertions(+), 2567 deletions(-) diff --git a/docs/src/man/img/Fmove_CM.svg b/docs/src/man/img/Fmove_CM.svg index acb224e..b2faaa9 100644 --- a/docs/src/man/img/Fmove_CM.svg +++ b/docs/src/man/img/Fmove_CM.svg @@ -1,643 +1,654 @@ - +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 +SUVORK5CYII=" /> diff --git a/docs/src/man/img/Fmove_CMD.svg b/docs/src/man/img/Fmove_CMD.svg index 5921d97..27792b6 100644 --- a/docs/src/man/img/Fmove_CMD.svg +++ b/docs/src/man/img/Fmove_CMD.svg @@ -1,659 +1,678 @@ - +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABAh/z/AXiDBjc4V2HnAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI1LTA4LTA2 +VDE0OjEyOjU1KzAwOjAwnzBAjQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNS0wOC0wNlQxNDoxMjo1 +NSswMDowMO5t+DEAAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjUtMDgtMDZUMTQ6MTI6NTUrMDA6 +MDC5eNnuAAAAJ3RFWHRwZGY6SGlSZXNCb3VuZGluZ0JveAAyMjkuOTg3eDc0LjIzNiswKzCpeeow +AAAAE3RFWHRwZGY6VmVyc2lvbgBQREYtMS41UzZawQAAAABJRU5ErkJggg==" /> diff --git a/docs/src/man/img/Fmove_D.svg b/docs/src/man/img/Fmove_D.svg index 0cce4f1..1838d4c 100644 --- a/docs/src/man/img/Fmove_D.svg +++ b/docs/src/man/img/Fmove_D.svg @@ -1,634 +1,651 @@ - +4AB3vbvYhwAAnDXVCKRjcD26n5lcjy9uYx8NAHB+VCOQkpvFDZkZTcYXsY8JADgnqhFIyfD6fp9x +7OMCAM6FagTS0n9zA16Nx+PJVu9+E/vAAIAzoRqBpNzc34968/9511+/La9jHxkAcB5UI5CU4eh+ +tNo1YDg2sQcAnJZqBNIy2Lr5bvvZPWkTAQDgFFQjkJY3t2Bv8yO386zQIPaRAQDnQTUCaZnsuftu +x5O+55UAAKehGoG0jO7v+7GPAQA4Z6oRSMube3I0jH0QAMAZU41AWib2CQAAolKNQFqmQSBtOwAQ +j2oE0jL2OBIAICrVCKTlbraZ2EXswwAAzpZqBBIze7S5mT0AIBrVCKRl/tTCSezDAADOlmoE0jKf +2LODAAAQi2oEEjO591xzACAm1QikZTC/J0eebA4AxKEagcRcLW7K29gHAgCcKdUIpGXRtt9f2kIA +AIhCNQKJucpuytgHAgCcKdUIpOVicU/e92MfCQBwnlQjkJiJmxIAiEo1AmnpZfekXcYAgChUI5CY +/vKmvIh9KADAWVKNQELuxlfLW9IuYwDA6alGICWDy/sNthAAAE5LNQIpGcwb9tH16s4cxz4mAOCc +qEYgJb35HXk1ePDg1sweAHB6qhFIyXCeCBrNdwwYL29Km4wBAKehGoGk3M1b9uvF082Hq4CQth0A +OAXVCCTlYjS7/26WHxhY+wcAnJJqBJIy2H0mybJtv4p9cADAGVCNQFIWt+TNno+9cRf78ACAzlON +QFJ6e1NAVyb2AIATUY1AUu7mq/6uhpsfvsnuyUnsAwQAOk41AkkZLh5I0tv+uKV/AMBJqEYgLeO8 +nYavs5sy9hECAN2mGoGkLJb9jYY7n1lO7A1rvCwAQEWqEUjLZW4A6C67J3uHvyoAQFWqEUhKto3Y +vmcVuicBgPBUI5CWq7x1f29M3JMAQHCqEUhKr+i2y+7J2AcJAHSYagTS0i/aQmzsngQAQlONQFpG +RQ8qXNyTo9gHCQB0mGoEknKx6Msv9n527CmGAEBgqhFIS/HM3aSopQcAaIBqBNIyKezLF58dxD5K +AKC7VCOQlqvCvnyUvzkxAEAjVCOQlsW03s3eT94W7SwAANAE1QikpfAhJBcFjy8BAGiEagTScl80 +czcu2lkAAKAJqhFIS+HmAZem9QCA0FQjkJaie/LW7mIAQHCqEUjLpOCevJl/bhj7GAGALlONQFrG +BffklWQQABCcagTScpG/e0Bv9pmRph0ACEk1AokZ5T6ncGLdHwBwAqoRSEt/dudd735i3rRfxj4+ +AKDrVCOQlttRTgBovu7vLvbxAQBdpxqBxIz3T9+Nc+f7AAAapRqBxFzua88v7BwAAJyKagTSMpzd +lKONm/Ju5JYEAE5FNQKJuZ3flBerj1y4JQGAE1KNQGKG863EJou78vZ69p83sQ8LADgbqhFIzc18 +D4HRZDzuz1cCXto3AAA4IdUIJGY4nu8ntnBl2wAA4LRUI5Cci/F8eu/+cqxjBwAiUI1Agu56w+Nf +BACgNtUIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJOm/A9XOG4tasMI6AAAAJXRFWHRkYXRlOmNyZWF0ZQAy +MDI1LTA4LTA2VDE0OjEyOjQzKzAwOjAwMEp1KQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNS0wOC0w +NlQxNDoxMjo0MyswMDowMEEXzZUAAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjUtMDgtMDZUMTQ6 +MTI6NDMrMDA6MDAWAuxKAAAAJ3RFWHRwZGY6SGlSZXNCb3VuZGluZ0JveAAyMjMuNTY3eDc1Ljc0 +NyswKzDo/+9tAAAAE3RFWHRwZGY6VmVyc2lvbgBQREYtMS41UzZawQAAAABJRU5ErkJggg==" /> diff --git a/docs/src/man/img/Fmove_MD.svg b/docs/src/man/img/Fmove_MD.svg index 8dc4fe3..e360755 100644 --- a/docs/src/man/img/Fmove_MD.svg +++ b/docs/src/man/img/Fmove_MD.svg @@ -1,665 +1,668 @@ - +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 +REYtMS41UzZawQAAAABJRU5ErkJggg==" /> From 1ccb3344f553183037fe97cce22e0dbee844c140 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 17:20:28 +0200 Subject: [PATCH 130/206] more text and cleanup --- docs/src/man/fusioncats.md | 19 ++++++----- docs/src/man/multifusioncats.md | 56 ++++++++++++++++----------------- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index c9ed7b2..c67b58a 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -26,35 +26,34 @@ This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C} Vectors in these hom-spaces are graphically denoted as living in the trivalent junction ```@raw html - + ``` With the F-symbol, we can perform F-moves: ```@raw html - + ``` TensorKit requires the F-symbols to be unitary. This way, we can interpret the F-symbol $F^{ijk}_l$ as a unitary matrix, and the F-move as a unitary basis transformation. Unitarity is also useful from a diagrammatic point of view because the category is then equipped with a pivotal and spherical structure. This essentially means that morphisms can be drawn and moved around freely on a 2-sphere, such that vector spaces can be moved freely from domain (codomain) to codomain (domain). ## Examples -### $\mathsf{VecG}$ and $\mathsf{RepG}$ +### $\mathsf{Vec_G}$ and $\mathsf{Rep(G)}$ Colloquially speaking, category theory attempts to generalise mathematical structures and their relations in a way that different structures can be treated in an equal manner. This is noted in particular as fusion category theory encompasses not only finite and compact groups, but also their representations. We show a table sketching how these are put on equal footing categorically. -|$\mathsf{VecG}$|$\mathsf{RepG}$|Categorical generalisation| +|$\mathsf{Vec_G}$|$\mathsf{Rep(G)}$|Categorical generalisation| |:---:|:---:|:---:| |$G$-graded vector spaces $V_1, V_2, ...$|Representations of $G$ $(V_1, \pi_1), (V_2, \pi_2), ...$|Objects| |$G$-graded preserving linear maps $\phi: V \rightarrow W$|Intertwiners $f: V_1 \rightarrow V_2$, $f \circ \pi_1 = \pi_2 \circ f$|Morphisms $\text{Hom}_\mathcal{C}$| -1d subspaces $\mathbb{C}_{g_1}, \mathbb{C}_{g_2}$: $\text{Hom}_{\mathsf{VecG}}(\mathbb{C}_{g_1},\mathbb{C}_{g_2}) = \delta_{g_1g_2}$|Irreps: $\text{Hom}_{\mathsf{RepG}}(\rho_i,\rho_j) = \delta_{ij} \mathbb{C}$ (Schur)|Simple objects: $\text{Hom}_{\mathcal{C}}(a,b) = \delta_{ab}\mathbb{C}$| +1d subspaces $\mathbb{C}_{g_1}, \mathbb{C}_{g_2}$: $\text{Hom}_{\mathsf{Vec_G}}(\mathbb{C}_{g_1},\mathbb{C}_{g_2}) = \delta_{g_1g_2}$|Irreps: $\text{Hom}_{\mathsf{Rep(G)}}(\rho_i,\rho_j) = \delta_{ij} \mathbb{C}$ (Schur)|Simple objects: $\text{Hom}_{\mathcal{C}}(a,b) = \delta_{ab}\mathbb{C}$| $G$-graded tensor product $(V \otimes W)_g = \oplus_{hk=g} V_h \otimes W_k$| $\pi_i \otimes \pi_j \simeq \oplus_i N_{ij}^k\rho_k$ | Direct sum, monoidal product, fusion rules, multiplicity| $\mathbb{C}_1 \otimes W \simeq W \simeq W \otimes \mathbb{C}_1$ | Trivial rep 1: $1 \otimes \rho = \rho = \rho \otimes 1$ | Monoidal unit $1_\mathcal{C}$ $\mathbb{C}_g \otimes \mathbb{C}_{g^{-1}} = \mathbb{C}_1 = \mathbb{C}_{g^{-1}} \otimes \mathbb{C}_g$ | $\pi \otimes \overline{\pi} = 1 \oplus ...$ | Dual object $F:(V \otimes W) \otimes U \xrightarrow{\sim}V \otimes (W \otimes U)$|$F: (\pi_1 \otimes \pi_2) \otimes \pi_3 \xrightarrow{\sim} \pi_1 \otimes (\pi_2 \otimes \pi_3)$|F-symbol| -## Fusion categories in condensed matter physics -- String-net models -> non-chiral topological order classification -- Kitaev's appendix E -> anyonic excitations -- Golden chain, anyonic spin chains -- \ No newline at end of file +### $\mathsf{Fib}$ and $\mathsf{Ising}$ +Arguably the simplest fusion category besides the familiar groups or representations of groups is the Fibonacci fusion category. This contain 2 simple objects $1$ and $\tau$, with non-trivial fusion rule $\tau \otimes \tau = 1 \oplus \tau$. This fusion category is in fact **braided** as well, and actually **modular**. + +Another simple fusion category is the Ising category, commonly denoted $\mathsf{Ising}$. 3 simple objects form this category, namely $\{1, \psi, \sigma\}$, where $1$ and $\psi$ behave like the trivial charged representations of $\mathbb{Z}_2$, while $\sigma$ is the $\mathbb{Z}_2$ extension of this. The fusion rules reflect these: $1 \otimes \psi = \psi = \psi \otimes 1, \sigma \otimes X = \sigma = X \otimes \sigma$ for $X = 1, \psi$, and $\sigma \otimes \sigma = 1 \oplus \psi$. This fusion category is also **modular**. Both these modular fusion categories are already implemented in TensorKit. \ No newline at end of file diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index f8b2452..623dbf2 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -3,14 +3,14 @@ This section will explain how to go from a fusion category to a multifusion category, as well as why one would want to consider the latter. Multifusion categories naturally embed the structure of **bimodule categories**. To explain this, we must start by explaining module categories over fusion categories, following this up with (invertible) bimodule categories, and finishing off with the multifusion structure. ## Module categories -We will mostly use the notation in [Lootens et al.](@cite Lootens_2023) for fusion categories and module categories over these. We start from a fusion category $\mathcal{D}$ defined by the triple $(\otimes_\mathcal{D}, \mathbb{1}_\mathcal{D}, {}^\mathcal{D}\!F)$ with simple objects $\alpha, \beta, ... \in \mathcal{I}_\mathcal{D}$. We drop the $\mathcal{D}$ subscript when there is no ambiguity concerning the fusion category. We call its associator +We start from a fusion category $\mathcal{D}$ defined by the triple $(\otimes_\mathcal{D}, \mathbb{1}_\mathcal{D}, {}^\mathcal{D}\!F)$ with simple objects $\alpha, \beta, ... \in \mathcal{I}_\mathcal{D}$. We drop the $\mathcal{D}$ subscript when there is no ambiguity concerning the fusion category. We call its associator $${}^\mathcal{D}\!F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) \rightarrow (\alpha \otimes \beta) \otimes \gamma$$ the **monoidal associator**. An F-move is now graphically portrayed as: ```@raw html - + ``` We can consider the **right module category** $\mathcal{M}$ over $\mathcal{D}$, which is a category (not necessarily fusion!) with (isomorphism classes of) simple objects $\mathcal{I}_\mathcal{M} = \{A,B,...\}$, a right action @@ -24,7 +24,7 @@ $${}^\triangleleft\!F^{A\alpha\beta}: A \triangleleft (\alpha \otimes \beta) \ri An F-move with this module associator can be expressed as: ```@raw html - + ``` The module structure of $\mathcal{M}$ is now defined as the triple $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$. The right module associator now satisfies a mixed pentagon equation with ${}^\mathcal{D}\!F$. @@ -40,20 +40,20 @@ $${}^\triangleright\!F^{abA}: (a \otimes b) \triangleright A \rightarrow a \tria for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. The left module associator also fulfills a mixed pentagon equation with ${}^\mathcal{C}\!F$. An F-move with ${}^\mathcal{C}\!F$ takes on the form: ```@raw html - + ``` -We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, and $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as +We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as $${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F^{aA\alpha}: (a \triangleright A) \triangleleft \alpha \rightarrow a \triangleright (A \triangleleft \alpha)$$ for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. The bimodule associator fulfills a mixed pentagon equation with the module associators. An F-move with ${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F$ is given by: ```@raw html - + ``` ## Opposite module categories -Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). Then $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. A similar statement can be made starting from a left module category and getting an opposite right module category. In particular, given a $(\mathcal{C}, \mathcal{D})$-bimodule category $\mathcal{M}$ over the fusion categories $\mathcal{C}, \mathcal{D}$, we see immediately that $\mathcal{M}^{\text{op}}$ is a $(\mathcal{D}, \mathcal{C})$-bimodule category. +Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). Then, $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. A similar statement can be made starting from a left module category and getting an opposite right module category. In particular, given a $(\mathcal{C}, \mathcal{D})$-bimodule category $\mathcal{M}$ over the fusion categories $\mathcal{C}$ and $\mathcal{D}$, we see immediately that $\mathcal{M}^{\text{op}}$ is a $(\mathcal{D}, \mathcal{C})$-bimodule category. Interestingly, due to the opposite actions @@ -67,7 +67,13 @@ there is a valid notion of multiplying a module category with its opposite: $$\mathcal{M} \times \mathcal{M}^{\text{op}} \rightarrow \mathcal{C}, \quad \mathcal{M}^{\text{op}} \times \mathcal{M} \rightarrow \mathcal{D}.$$ -something something morita equivalence and invertible bimodule, maybe drinfeld center, maybe anyons, maybe domain walls +## Invertible bimodule categories and Morita equivalence + +The bimodule categories we consider are restricted to be **invertible**. This means that this bimodule category fulfills the condition $\mathcal{C} \equiv \mathcal{D}^*_\mathcal{M}$, or in other words the two fusion categories $\mathcal{C}$ and $\mathcal{D}$ are **Morita equivalent** (or each other's **Morita dual** with respect to $\mathcal{M}$). Morita equivalence between $\mathcal{C}$ and $\mathcal{D}$ can be shown to hold if and only if the bimodule category fulfills + +$$\mathcal{M} \boxtimes_\mathcal{D} \mathcal{M}^\text{op} \simeq \mathcal{C}, \quad \text{and} \quad \mathcal{M}^\text{op} \boxtimes_\mathcal{C} \mathcal{M} \simeq \mathcal{D},$$ + +where $\boxtimes_\mathcal{C}$ and $\boxtimes_\mathcal{D}$ denote the Deligne product relative to $\mathcal{C}$ and $\mathcal{D}$ respectively. This is precisely the invertibility property of the bimodule category. ## Multifusion categories A fusion category has the important condition that $\mathsf{End}_\mathcal{C}(1_\mathcal{C}) \cong \mathbb{C}$, i.e., the unit of the fusion category is simple. If we drop this condition, then we consider a **multifusion category**. We assume the multifusion category itself to be indecomposable, meaning it is not the direct sum of two non-trivial multifusion categories. Let us call this multifusion category $\mathcal{C}$. It will be clear in a moment that this will not be ambiguous. Its unit can then be decomposed as @@ -90,7 +96,7 @@ end `i` and `j` specify which subcategory $\mathcal{C}_{ij}$ we are considering, and `label` selects a particular simple object within that subcategory. -We want to consider multifusion categories because **their structure encapsulates that of (bi-)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ (also known as a component category) is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. In particular, the tensor product +We want to consider multifusion categories because **their structure encapsulates that of (bi)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ (also known as a component category) is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. In particular, the tensor product $$\otimes_\mathcal{C}: \mathcal{C}_{ij} \times \mathcal{C}_{kl} \rightarrow \delta_{jk}\mathcal{C}_{il}$$ @@ -98,32 +104,32 @@ takes on the same structure as the product of two matrix units. This is not a co Given a subcategory $\mathcal{C}_{ij}$, we can define the **left** unit as the unit object of the fusion category $\mathcal{C}_i$, while the **right** unit is the unit object of the fusion category $\mathcal{C}_j$. In other words, the left unit of $\mathcal{C}_{ij}$ is the unique object of the multifusion category $\mathcal{C}$ for which -$$1_i \otimes_\mathcal{C} M_{ij} = M_{ij} \quad \forall M_{ij} \in \mathcal{C}_{ij},$$ +$$1_i \otimes_\mathcal{C} m_{ij} = m_{ij} \quad \forall m_{ij} \in \mathcal{C}_{ij},$$ and similarly for the right unit of $\mathcal{C}_{ij}$, -$$M_{ij} \otimes_\mathcal{C} 1_j = M_{ij} \quad \forall M_{ij} \in \mathcal{C}_{ij}.$$ +$$m_{ij} \otimes_\mathcal{C} 1_j = m_{ij} \quad \forall m_{ij} \in \mathcal{C}_{ij}.$$ -We can also immediately see that for a (bi)module subcategory $\mathcal{C}_{ij}$, the opposite (bi)module subcategory $\mathcal{C}_{ij}^{\text{op}} \equiv \mathcal{C}_{ji}$, and as expected, +We can also immediately see that for a bimodule subcategory $\mathcal{C}_{ij}$, the opposite (bi)module subcategory $\mathcal{C}_{ij}^{\text{op}} \equiv \mathcal{C}_{ji}$, and as expected, $$\mathcal{C}_{ij} \times \mathcal{C}_{ji} \rightarrow \mathcal{C}_i,$$ just like what we concluded when considering opposite module categories outside of the multifusion structure. ### 2-category and coloring -Multifusion categories can also be interpreted as 2-categories. We still interpret the objects of this 2-category the same way. The 1-morphisms are the subcategories themselves, and the 2-morphisms the morphisms of the multifusion category. The graphical calculus of monoidal 1-categories can be extended to 2-categories by use of *colorings* [henriques2020](@cite). We have previously differed between module strands and fusion strands by the color of the strand itself. However, in 2-categories the strands (1-morphisms) separate regions which are colored based on the objects they are representing. Since we draw the strands vertically, a single strand results in a left and right region, and the colorings will determine the fusion category which fuses from the left or right with that single strand. In particular, fusion strands necessarily have the same coloring on the left and right, while module strands have a mismatching coloring. +Multifusion categories can also be interpreted as 2-categories. We still interpret the objects of this 2-category the same way. The 1-morphisms are the subcategories themselves, and the 2-morphisms the morphisms of the multifusion category. The graphical calculus of monoidal 1-categories can be extended to 2-categories by use of *colorings* [henriques2020](@cite). We have previously differed between module strands and fusion strands by the color of the strand itself. However, in 2-categories the strands (1-morphisms) separate regions which are colored based on the fusion categories they are representing. Since we draw the strands vertically, a single strand results in a left and right region, and the colorings will determine the fusion category which fuses from the left or right with that single strand. In particular, fusion strands necessarily have the same coloring on the left and right, while module strands have a mismatching coloring. The simplest non-trivial fusion diagram is a trivalent junction: ```@raw html - + ``` -The most general case is the top left figure, where all three regions have a different coloring. The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. However, as will be explained more in detail later, this most general trivalent junction with three colorings will never be needed. In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. This is displayed in the top middle and right. Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. This is shown in the bottom right. +The most general case is the top left figure, where all three regions have a different coloring. The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. However, this most general trivalent junction with three colorings will never be needed. In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. This is displayed in the top middle and right. Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. This is shown in the bottom right. With this coloring system, we can specify which associator must be called to perform a particular F-move. Such an F-move would look like ```@raw html - + ``` ### Why opposite module categories end up being necessary in MultiTensorKit @@ -132,14 +138,14 @@ One of the common manipulations which can act on a tensor map is the transpositi Linear algebra tells us that given a (finite-dimensional) vector space $V$ with a basis denoted $\{|e_i\rangle\}$, one can consider the **dual** vector space $V^*$, whose dual basis $\{\langle e_i^*|\}$ satisfies the property $\langle e_j^* | e_i \rangle = \delta_{ij}$. In the diagrammatic calculus, specifying whether a tensor map leg represents a vector space or its dual is done with an arrow. Following the TensorKit convention, legs with arrows pointing downwards are vector spaces, and arrows pointing upwards state that we are considering its dual. In particular, at the level of fusion trees we can also draw arrows on the strands to denote whether we are considering morphisms between objects or dual objects. -In principle, choosing to bend e.g. codomain legs to the right and domain legs to left is an arbitrary choice, but would require to distinguish between left and right transposes. However, TensorKit.jl is implemented in a way that does not differentiate the two. In particular, we do not have to worry about this when considering categorical symmetries where, in principle, the left and right dual of an object are not equivalent. This is because this left-right symmetry is guaranteed when considering unitary fusion categories, which is what is done in TensorKit and necessarily in MultiTensorKit. +In principle, choosing to bend, e.g., codomain legs to the right and domain legs to left is an arbitrary choice, but would require to distinguish between left and right transposes. However, TensorKit.jl is implemented in a way that does not differentiate the two. In particular, we do not have to worry about this when considering categorical symmetries where, in principle, the left and right dual of an object are not equivalent. This is because this left-right symmetry is guaranteed when considering unitary fusion categories, which is what is done in TensorKit and necessarily in MultiTensorKit. For this reason, at the level of the fusion trees the topological move that is performed to bend the legs along the right is called a **B-move**. Graphically, one can show that this bend boils down to a particular F-move. The typical equation found in the literature is the following: ```@raw html - + ``` -... The reason to only consider B-moves is rooted in the choice of canonical form of fusion trees within TensorKit, where fusions are iterated over from left to right and splittings from right to left. +The reason to only consider B-moves is rooted in the choice of canonical form of fusion trees within TensorKit, where fusions are iterated over from left to right and splittings from right to left. Importantly, we identify the dual vector space labeled by a module category with a vector space labeled by the opposite module category. Consequently, @@ -148,7 +154,7 @@ $$\mathcal{M}^* \simeq \mathcal{M}^\text{op}.$$ In the multifusion setting, this can also be seen graphically. By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: ```@raw html - + ``` where by $\mathbb{1}_j$ we mean the unit of $\mathcal{C}_j$. @@ -178,7 +184,7 @@ Besides the B-move (and closely related A-move, which we do not illustrate), we ``` In principle, a gauge fixing can be done to set the Frobenius-Schur indicator to $\pm 1$. However, this assumption is no longer required within TensorKit and can be relaxed to just be a phase. -The above gauge fixing is a property of the unitary gauge. By choosing appropriate bases, one can transform the F-symbols of a (multi)fusion category to be unitary matrices. More details on the importance of unitary data can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/#ss_topologicalfusion) documentation. +The above gauge fixing is a property of the unitary gauge. By choosing appropriate bases, one can transform the F-symbols of a (multi)fusion category to be unitary matrices. More details on the importance of unitary topological data can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/#ss_topologicalfusion) documentation. ### Braiding A very important aspect of MultiTensorKit is that all `BimoduleSector`s are defined to *not* support braiding: `TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding()`. We do this for two reasons. On the one hand, there is no natural 1-categorical way of defining braidings between the components of the multifusion category. It is possible that the diagonal fusion categories themselves are braided, but a "componentwise" braiding is unwise to support. On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. @@ -192,10 +198,4 @@ We already identified the off-diagonal elements with module categories over the If we take $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep}(\mathbb{Z}_2)$ and $\mathcal{M} = \mathsf{Vec}$, then the entire multifusion category is isomorphic to the $\mathsf{Ising}$ category [etingof2016tensor; Example 4.10.5](@cite). We identify the trivial representation of $\mathsf{Rep}(\mathbb{Z}_2)$ with the unit of $\mathsf{Ising}$, the sign representation with $\psi$ and the unique object of $\mathsf{Vec}$ with the duality object $\sigma$. One can easily check that the fusion rules of $\mathsf{Ising}$ match with those we expect within $\mathsf{Rep}(\mathbb{Z}_2)$ and with its module category $\mathsf{Vec}$. Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (and vice-versa) giving every object in $\mathcal{C}_1$ ($\mathcal{C}_2$) is consistent with $\sigma \times \sigma^* = 1 + \psi$. This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). -This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is isomorphic to the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. - -## Module and multifusion categories in condensed matter physics -- boundaries of string-net models -- generalised anyonic spin chain -- moore-seiberg data -> modular invariant -- modules as (conformal) boundary conditions \ No newline at end of file +This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is isomorphic to the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. \ No newline at end of file From 9082eb43b5a048513d167653cf0b21b411db7127 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 6 Aug 2025 17:26:03 +0200 Subject: [PATCH 131/206] add PR comment to workflow --- .github/workflows/PR_comment.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/PR_comment.yml diff --git a/.github/workflows/PR_comment.yml b/.github/workflows/PR_comment.yml new file mode 100644 index 0000000..ea00f15 --- /dev/null +++ b/.github/workflows/PR_comment.yml @@ -0,0 +1,17 @@ +name: Docs preview comment +on: + pull_request: + types: [labeled] + +permissions: + pull-requests: write +jobs: + pr_comment: + runs-on: ubuntu-latest + steps: + - name: Create PR comment + if: github.event_name == 'pull_request' && github.repository == github.event.pull_request.head.repo.full_name && github.event.label.name == 'documentation' + uses: thollander/actions-comment-pull-request@v3 + with: + message: 'After the build completes, the updated documentation will be available [here](https://quantumkithub.github.io/MultiTensorKit.jl/previews/PR${{ github.event.number }}/)' + comment-tag: 'preview-doc' \ No newline at end of file From decc1df41b24e15aa38319c2e506d3ab7c54045e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 7 Aug 2025 16:51:08 +0200 Subject: [PATCH 132/206] fix to example --- docs/src/man/implementation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 79d43ef..e9b72d8 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -133,7 +133,7 @@ Consider a quantum lattice model with its symmetries determing the phase diagram ````julia module_numlabels(i) = MultiTensorKit._numlabels(A4Object, i, 6) V = Vect[A4Object](A4Object(i, 6, label) => D for label in 1:module_numlabels(i)) -Vb = Vect[A4Object](c => 1 for c in first(sectors(V))) # not all charges on boundary, play around with what is there +Vb = Vect[A4Object](first(sectors(V)) => 1) # not all charges on boundary, play around with what is there ```` #TODO: show all the plots From a5ef9254d16e9154727038de2ef29ac06af2a0aa Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 7 Aug 2025 16:59:47 +0200 Subject: [PATCH 133/206] another minor fix --- docs/src/man/implementation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index e9b72d8..ca29013 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -83,7 +83,7 @@ block(h3_R, D4) .= [0 1;] @plansor h3[-1 -2; -3 -4] := h3_L[-1 1; -3] * h3_R[-2; 1 -4] L = 60 -J1 = -2.0 # probing the A4 SSB phase first +J1 = -2.0 # probing the A4 symmetric phase first J2 = -5.0 lattice = FiniteChain(L) H1 = @mpoham sum(-2 * h1{i,j} for (i, j) in nearest_neighbours(lattice)) From 7de0a8b19eb294a6023d5c80210553493c49290b Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 7 Aug 2025 17:18:02 +0200 Subject: [PATCH 134/206] add plot and some words to it --- .../man/img/A4_sym_entanglement_spectrum.svg | 464 ++++++++++++++++++ docs/src/man/implementation.md | 10 +- 2 files changed, 472 insertions(+), 2 deletions(-) create mode 100644 docs/src/man/img/A4_sym_entanglement_spectrum.svg diff --git a/docs/src/man/img/A4_sym_entanglement_spectrum.svg b/docs/src/man/img/A4_sym_entanglement_spectrum.svg new file mode 100644 index 0000000..8af3cb0 --- /dev/null +++ b/docs/src/man/img/A4_sym_entanglement_spectrum.svg @@ -0,0 +1,464 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index ca29013..58e561e 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -124,7 +124,7 @@ This returns a dictionary which maps the objects grading the virtual space to th ````julia entanglementplot(ψ;site=round(Int, L/2)) ```` -This plot will show the singular values per object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. #TODO: actually include the plot +This plot will show the singular values per object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. The next section will show this plot along with those when selecting the other module categories. ## Search for the correct dual model @@ -136,7 +136,13 @@ V = Vect[A4Object](A4Object(i, 6, label) => D for label in 1:module_numlabels(i) Vb = Vect[A4Object](first(sectors(V)) => 1) # not all charges on boundary, play around with what is there ```` -#TODO: show all the plots +```@raw html + +``` + +The plot shows the entanglement spectra of the various dual models in the middle of the ground state for the original Hamiltonian probing the $\mathsf{Rep(A_4)}$-symmetric phase, along with the ground state without symmetries. Every subtitle also mentions the memory required to store the same middle ground state tensor. This plot should be compared to [Lootens_2024; Figure 2](@cite). + +This can be repeated with other parameter values for $J_1$ and $J_2$ in the Hamiltonian to probe the $\mathsf{Rep(\mathbb{Z}_2 \times \mathbb{Z}_2)}$-symmetric or $\mathsf{Rep^\psi(A_4)}$ SPT phase. !!! note "Additional functions and keyword arguments" Certain commonly used functions within MPSKit require extra keyword arguments to be compatible with multifusion MPS simulations. In particular, the keyword argument `sector` (note the lowercase "s") appears in From c22b21529bc229e8bbfe344328d26560f4bcfe67 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 7 Aug 2025 17:39:53 +0200 Subject: [PATCH 135/206] fix `blocksectors` to not use `isone` --- src/bimodulesector.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 3be59ca..b417b1c 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -278,10 +278,10 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where for i in 1:size(A4Object)) # have to return all units b/c no info on W in this case elseif N₁ == 0 @assert Nβ‚‚ != 0 "one of Type A4Object doesn't exist" - return filter!(isone, collect(blocksectors(dom))) + return filter!(c -> c == leftone(c) == rightone(c), collect(blocksectors(dom))) elseif Nβ‚‚ == 0 @assert N₁ != 0 "one of Type A4Object doesn't exist" - return filter!(isone, collect(blocksectors(codom))) + return filter!(c -> c == leftone(c) == rightone(c), collect(blocksectors(codom))) elseif Nβ‚‚ <= N₁ # keep intersection return filter!(c -> hasblock(codom, c), collect(blocksectors(dom))) else @@ -291,7 +291,7 @@ end function dim(V::GradedSpace{<:BimoduleSector}) T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) - return reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(T)) + return reduce(+, dim(V, c) * rounddim(c) for c in sectors(V); init=zero(T)) end # limited oneunit From 6b528c9f32966760b30aa80b75dea1a9e6a21f34 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 7 Aug 2025 17:41:01 +0200 Subject: [PATCH 136/206] introduce `rounddim` for prettiness --- src/bimodulesector.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index b417b1c..330628a 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -289,6 +289,15 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where end end +function rounddim(c::I) where {I<:BimoduleSector} + _dim = dim(c) + if _dim β‰ˆ floor(_dim) + return floor(_dim) + else + return _dim + end +end + function dim(V::GradedSpace{<:BimoduleSector}) T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) return reduce(+, dim(V, c) * rounddim(c) for c in sectors(V); init=zero(T)) From 7a8d56a3a232701074ffdfcdb6acf0512cfe30c8 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 10:40:23 +0200 Subject: [PATCH 137/206] add link --- docs/src/man/fusioncats.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index c67b58a..f584678 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -56,4 +56,4 @@ $F:(V \otimes W) \otimes U \xrightarrow{\sim}V \otimes (W \otimes U)$|$F: (\pi_1 ### $\mathsf{Fib}$ and $\mathsf{Ising}$ Arguably the simplest fusion category besides the familiar groups or representations of groups is the Fibonacci fusion category. This contain 2 simple objects $1$ and $\tau$, with non-trivial fusion rule $\tau \otimes \tau = 1 \oplus \tau$. This fusion category is in fact **braided** as well, and actually **modular**. -Another simple fusion category is the Ising category, commonly denoted $\mathsf{Ising}$. 3 simple objects form this category, namely $\{1, \psi, \sigma\}$, where $1$ and $\psi$ behave like the trivial charged representations of $\mathbb{Z}_2$, while $\sigma$ is the $\mathbb{Z}_2$ extension of this. The fusion rules reflect these: $1 \otimes \psi = \psi = \psi \otimes 1, \sigma \otimes X = \sigma = X \otimes \sigma$ for $X = 1, \psi$, and $\sigma \otimes \sigma = 1 \oplus \psi$. This fusion category is also **modular**. Both these modular fusion categories are already implemented in TensorKit. \ No newline at end of file +Another simple fusion category is the Ising category, commonly denoted $\mathsf{Ising}$. 3 simple objects form this category, namely $\{1, \psi, \sigma\}$, where $1$ and $\psi$ behave like the trivial charged representations of $\mathbb{Z}_2$, while $\sigma$ is the $\mathbb{Z}_2$ extension of this. The fusion rules reflect these: $1 \otimes \psi = \psi = \psi \otimes 1, \sigma \otimes X = \sigma = X \otimes \sigma$ for $X = 1, \psi$, and $\sigma \otimes \sigma = 1 \oplus \psi$. This fusion category is also **modular**. Both these modular fusion categories are already implemented in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). \ No newline at end of file From 74508a379df24996c8b02e13022974cf62e746c2 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 10:40:46 +0200 Subject: [PATCH 138/206] correct keyword args blocks --- docs/src/man/implementation.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 58e561e..fa2a556 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -146,9 +146,7 @@ This can be repeated with other parameter values for $J_1$ and $J_2$ in the Hami !!! note "Additional functions and keyword arguments" Certain commonly used functions within MPSKit require extra keyword arguments to be compatible with multifusion MPS simulations. In particular, the keyword argument `sector` (note the lowercase "s") appears in - - `transfer_spectrum`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the sectors lie in the symmetry category $\mathcal{C} = \mathcal{D^*_M}$. - - `correlation_length`: since this function calls `transfer_spectrum`, the same logic applies. - - `excitations` with `QuasiparticleAnsatz`: similar to the previous functions, charged excitations are selected by adding a charged auxiliary space to the eigenvectors representing the quasiparticle states. + - `excitations` with `QuasiparticleAnsatz`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the charged excitations lie in the symmetry category $\mathcal{C} = \mathcal{D^*_M}$. - `exact_diagonalization`: the `sector` keyword argument now requires an object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. ## Differences with the infinite case @@ -159,4 +157,10 @@ init = InfiniteMPS([P], [V]) inf_alg = VUMPS(; verbosity=2, tol=1e-7) ```` -Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `Sector`. It is also clear that boundary terms do not play a role in this case. \ No newline at end of file +Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `Sector`. It is also clear that boundary terms do not play a role in this case. + +!!! note "More functions for infinite systems" + When dealing with an infinite system, additional information can be retrieved from the matrix product state. These also require a keyword argument `sector` to be specified. These are + - `transfer_spectrum`: similar to `excitations`, the (partial) transfer matrix spectrum is selected by adding a charged auxiliary space to the transfer matrix eigenvectors. + - `correlation_length`: since this function calls `transfer_spectrum`, the same logic applies. + - `excitations` in the infinite case also requires the keyword argument. \ No newline at end of file From 34eaaec3a5e9284fb0424abf5e0eedd6e08da2fb Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 10:41:13 +0200 Subject: [PATCH 139/206] correct docs on TY MF example --- docs/src/man/multifusioncats.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 623dbf2..414eea1 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -196,6 +196,6 @@ $$\mathcal{C} = \begin{pmatrix} \mathcal{C}_1 & \mathcal{M} \\ \mathcal{M}^{\tex We already identified the off-diagonal elements with module categories over the fusion categories on the diagonal. Accordingly, $\mathcal{M}$ is a $(\mathcal{C}_1, \mathcal{C}_2)$-bimodule category, and $\mathcal{M}^{\text{op}}$ is the opposite module category and a $(\mathcal{C}_2, \mathcal{C}_1)$-bimodule category. -If we take $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep}(\mathbb{Z}_2)$ and $\mathcal{M} = \mathsf{Vec}$, then the entire multifusion category is isomorphic to the $\mathsf{Ising}$ category [etingof2016tensor; Example 4.10.5](@cite). We identify the trivial representation of $\mathsf{Rep}(\mathbb{Z}_2)$ with the unit of $\mathsf{Ising}$, the sign representation with $\psi$ and the unique object of $\mathsf{Vec}$ with the duality object $\sigma$. One can easily check that the fusion rules of $\mathsf{Ising}$ match with those we expect within $\mathsf{Rep}(\mathbb{Z}_2)$ and with its module category $\mathsf{Vec}$. Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (and vice-versa) giving every object in $\mathcal{C}_1$ ($\mathcal{C}_2$) is consistent with $\sigma \times \sigma^* = 1 + \psi$. This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). +If we take $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep}(\mathbb{Z}_2)$ and $\mathcal{M} = \mathsf{Vec}$, then the entire multifusion category is Morita equivalent to $\mathsf{Rep}(\mathbb{Z}_2)$, and we view the $\mathbb{Z}_2$-extension of $\mathsf{Rep}(\mathbb{Z}_2)$ to be precisely the $\mathsf{Ising}$ category [etingof2009; Section 9](@cite) [etingof2016tensor; Example 4.10.5](@cite). We identify the trivial representation of $\mathsf{Rep}(\mathbb{Z}_2)$ with the unit of $\mathsf{Ising}$, the sign representation with $\psi$ and the unique object of $\mathsf{Vec}$ with the duality object $\sigma$. One can easily check that the fusion rules of $\mathsf{Ising}$ match with those we expect within $\mathsf{Rep}(\mathbb{Z}_2)$ and with its module category $\mathsf{Vec}$. Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (and vice-versa) giving every object in $\mathcal{C}_1$ ($\mathcal{C}_2$) is consistent with $\sigma \times \sigma^* = 1 + \psi$. This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). -This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is isomorphic to the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. \ No newline at end of file +This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is Morita equivalent to $\mathsf{Rep(G)}$ and can be evaluated as the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. \ No newline at end of file From a937e44bfd3e5b9980b3a76b9c3fbb7175798db0 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 10:43:55 +0200 Subject: [PATCH 140/206] add todo for visibility --- docs/src/man/implementation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index fa2a556..28abc23 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -24,7 +24,7 @@ We first need to select which fusion category we wish to use to grade the physic When referring to specific fusion and module categories, we will use this non-multifusion notation. -The easiest way to identify which elements of the multifusion category correspond to the subcategories we wish to use is ... (not sure yet how to do this yet) +The easiest way to identify which elements of the multifusion category correspond to the subcategories we wish to use is ... #TODO Now that we have identified the fusion and module categories, we want to select the relevant objects we wish to place in our graded spaces. Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. Hence, the simplest way to find the unit object of a fusion subcategory is From db4b577dd3522d077774d41bfa7fd7a0d8459588 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 12:50:22 +0200 Subject: [PATCH 141/206] introduce test setup file --- test/runtests.jl | 2 ++ test/setup.jl | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 test/setup.jl diff --git a/test/runtests.jl b/test/runtests.jl index d5cbe18..6b48268 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,6 +14,8 @@ const GROUP = uppercase(if isnothing(arg_id) istestfile(fn) = endswith(fn, ".jl") && startswith(basename(fn), "test_") && !contains(fn, "setup") +include("setup.jl") + @time begin # tests in groups based on folder structure for testgroup in filter(isdir, readdir(@__DIR__)) diff --git a/test/setup.jl b/test/setup.jl new file mode 100644 index 0000000..0fb5dbf --- /dev/null +++ b/test/setup.jl @@ -0,0 +1,29 @@ +using MultiTensorKit +using TensorKitSectors, TensorKit +using Test, TestExtras + +function unitarity_test(as::Vector{I}, bs::Vector{I}, cs::Vector{I}) where {I<:BimoduleSector} + @assert all(a.j == b.i for a in as, b in bs) + @assert all(b.j == c.i for b in bs, c in cs) + + for a in as, b in bs, c in cs + for d in βŠ—(a, b, c) + es = collect(intersect(βŠ—(a, b), map(dual, βŠ—(c, dual(d))))) + fs = collect(intersect(βŠ—(b, c), map(dual, βŠ—(dual(d), a)))) + Fblocks = Vector{Any}() + for e in es + for f in fs + Fs = Fsymbol(a, b, c, d, e, f) + push!(Fblocks, + reshape(Fs, + (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) + end + end + F = hvcat(length(fs), Fblocks...) + isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) || return false + end + end + return true +end + From 3ffaee59da288a0bb8a6c5239106c772d595740f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 14:09:47 +0200 Subject: [PATCH 142/206] refactor unitarity tests --- test/setup.jl | 6 +- test/test_A4.jl | 218 +++++++----------------------------------------- 2 files changed, 31 insertions(+), 193 deletions(-) diff --git a/test/setup.jl b/test/setup.jl index 0fb5dbf..cdd5c5b 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -2,10 +2,11 @@ using MultiTensorKit using TensorKitSectors, TensorKit using Test, TestExtras -function unitarity_test(as::Vector{I}, bs::Vector{I}, cs::Vector{I}) where {I<:BimoduleSector} +function unitarity_test(as::Vector{I}, bs::Vector{I}, + cs::Vector{I}) where {I<:BimoduleSector} @assert all(a.j == b.i for a in as, b in bs) @assert all(b.j == c.i for b in bs, c in cs) - + for a in as, b in bs, c in cs for d in βŠ—(a, b, c) es = collect(intersect(βŠ—(a, b), map(dual, βŠ—(c, dual(d))))) @@ -26,4 +27,3 @@ function unitarity_test(as::Vector{I}, bs::Vector{I}, cs::Vector{I}) where {I<:B end return true end - diff --git a/test/test_A4.jl b/test/test_A4.jl index 6e54328..b4d2ecf 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -1,7 +1,3 @@ -using MultiTensorKit -using TensorKitSectors, TensorKit -using Test, TestExtras - I = A4Object Istr = TensorKitSectors.type_repr(I) r = size(I) @@ -25,207 +21,49 @@ end @constinferred Bsymbol(s...) @constinferred Fsymbol(s..., s...) end - - @testset "Unitarity of F-move" begin - for a in objects, b in objects, c in objects - for d in βŠ—(a, b, c) - es = collect(intersect(βŠ—(a, b), map(dual, βŠ—(c, dual(d))))) - fs = collect(intersect(βŠ—(b, c), map(dual, βŠ—(dual(d), a)))) - Fblocks = Vector{Any}() - for e in es - for f in fs - Fs = Fsymbol(a, b, c, d, e, f) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(fs), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) - end - end - end end for i in 1:r, j in 1:r - i != j || continue # skip if fusion category - @testset "$Istr right module category $i, $j" begin - mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) - fusion_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) - - @testset "Unitarity of module F-move $i, $j" begin # written as MxD, but with i<->j checks MopxC - for A in mod_objects, Ξ± in fusion_objects, Ξ² in fusion_objects - for B in βŠ—(A, Ξ±, Ξ²) - Cs = collect(intersect(βŠ—(A, Ξ±), map(dual, βŠ—(Ξ², dual(B))))) - Ξ³s = collect(intersect(βŠ—(Ξ±, Ξ²), map(dual, βŠ—(dual(B), A)))) - Fblocks = Vector{Any}() - for C in Cs - for Ξ³ in Ξ³s - Fs = Fsymbol(A, Ξ±, Ξ², B, C, Ξ³) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(Ξ³s), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) - end + @testset "Unitarity of $Istr F-move ($i, $j)" begin + if i == j + @testset "Unitarity of fusion F-move ($i, $j)" begin + fusion_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) + @test unitarity_test(fusion_objects, fusion_objects, fusion_objects) end end - end -end -for i in 1:7, j in 1:7 # C x M (or D x Mop with i<->j) - i != j || continue # skip if fusion category - @testset "$Istr left module category $i, $j unitarity check" begin + i != j || continue # do this part only when off-diagonal mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) - fusion_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) + left_fusion_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) + right_fusion_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) - @testset "Unitarity of left module F-move" begin - for a in fusion_objects, b in fusion_objects, A in mod_objects # written for M as left C-module category - for B in βŠ—(a, b, A) - cs = collect(intersect(βŠ—(a, b), map(dual, βŠ—(A, dual(B))))) # equivalent of es - Cs = collect(intersect(βŠ—(b, A), map(dual, βŠ—(dual(B), a)))) # equivalent of fs - Fblocks = Vector{Any}() - for c in cs - for C in Cs - Fs = Fsymbol(a, b, A, B, c, C) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(Cs), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) - end - end + # C x C x M -> M or D x D x Mop -> Mop + @testset "Unitarity of left module F-move ($i, $j)" begin + @test unitarity_test(left_fusion_objects, left_fusion_objects, mod_objects) end - end -end - -for i in 1:7, j in 1:7 # bimodule check unitarity (C x M x D or D x Mop x C) - i != j || continue # skip if fusion category - @testset "$Istr bimodule category $i, $j" begin - C_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) - mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) - D_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) - @testset "Unitarity of bimodule F-move" begin # written as CMD - for a in C_objects, A in mod_objects, Ξ± in D_objects - for B in βŠ—(a, A, Ξ±) - Cs = collect(intersect(βŠ—(a, A), map(dual, βŠ—(Ξ±, dual(B))))) # equivalent of es - Ds = collect(intersect(βŠ—(A, Ξ±), map(dual, βŠ—(dual(B), a)))) # equivalent of fs - Fblocks = Vector{Any}() - for C in Cs - for D in Ds - Fs = Fsymbol(a, A, Ξ±, B, C, D) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(Ds), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) - end - end + # M x D x D -> M or Mop x C x C -> Mop + @testset "Unitarity of right module F-move ($i, $j)" begin + @test unitarity_test(mod_objects, right_fusion_objects, right_fusion_objects) end - end -end - -for i in 1:7, j in 1:7 # M x Mop x M -> M (or Mop x M x Mop -> Mop) - i != j || continue # skip if not fusion category - @testset "$Istr Module category $i,$j and opposite $j,$i" begin - M_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) - Mop_objects = I.(j, i, MultiTensorKit._get_dual_cache(I)[2][j, i]) - C_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) - D_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) - - @testset "Unitarity of mixed module F-move I" begin # written for C x M x Mop -> C but also holds for D x Mop x M -> D - for Ξ± in C_objects, A in M_objects, Aop in Mop_objects - for Ξ² in βŠ—(Ξ±, A, Aop) - Cs = collect(intersect(βŠ—(Ξ±, A), map(dual, βŠ—(Aop, dual(Ξ²))))) # equivalent of es - Ξ³s = collect(intersect(βŠ—(A, Aop), map(dual, βŠ—(dual(Ξ²), Ξ±)))) # equivalent of fs - Fblocks = Vector{Any}() - for C in Cs - for Ξ³ in Ξ³s - Fs = Fsymbol(Ξ±, A, Aop, Ξ², C, Ξ³) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(Ξ³s), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) - end - end + + # C x M x D -> M or D x Mop x C -> Mop + @testset "Unitarity of bimodule F-move ($i, $j)" begin + @test unitarity_test(left_fusion_objects, mod_objects, right_fusion_objects) end - @testset "Unitarity of mixed module F-move II" begin # written for M x Mop x C -> C but also holds for Mop x M x D -> D - for A in M_objects, Aop in Mop_objects, Ξ± in C_objects - for Ξ² in βŠ—(A, Aop, Ξ±) - Ξ³s = collect(intersect(βŠ—(A, Aop), map(dual, βŠ—(Ξ±, dual(Ξ²))))) # equivalent of es - Bops = collect(intersect(βŠ—(Aop, Ξ±), map(dual, βŠ—(dual(Ξ²), A)))) # equivalent of fs - Fblocks = Vector{Any}() - for Ξ³ in Ξ³s - for Bop in Bops - Fs = Fsymbol(A, Aop, Ξ±, Ξ², Ξ³, Bop) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(Bops), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) - end - end - end + @testset "Unitarity of mixed module F-move ($i, $j) and opposite ($j, $i)" begin + modop_objects = I.(j, i, MultiTensorKit._get_dual_cache(I)[2][j, i]) - @testset "Unitarity of mixed module F-move III" begin # written for Mop x C x M -> D, but also holds for M x D x Mop -> C - for Aop in Mop_objects, Ξ± in C_objects, A in M_objects - for a in βŠ—(Aop, Ξ±, A) - Bops = collect(intersect(βŠ—(Aop, Ξ±), map(dual, βŠ—(A, dual(a))))) # equivalent of es - Bs = collect(intersect(βŠ—(Ξ±, A), map(dual, βŠ—(dual(a), Aop)))) # equivalent of fs - Fblocks = Vector{Any}() - for Bop in Bops - for B in Bs - Fs = Fsymbol(Aop, Ξ±, A, a, Bop, B) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(Bs), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) - end - end - end + # C x M x Mop -> C or D x Mop x M -> D + @test unitarity_test(left_fusion_objects, mod_objects, modop_objects) + # M x Mop x C -> C or Mop x M x D -> D + @test unitarity_test(mod_objects, modop_objects, left_fusion_objects) + # Mop x C x M -> D or M x D x Mop -> C + @test unitarity_test(modop_objects, left_fusion_objects, mod_objects) - @testset "Unitarity of pure module F-move" begin - for A in M_objects, Aop in Mop_objects, B in M_objects # written for M x Mop x M -> M but also holds for Mop x M x Mop -> Mop - for C in βŠ—(A, Aop, B) - cs = collect(intersect(βŠ—(A, Aop), map(dual, βŠ—(B, dual(C))))) # equivalent of es - Ξ³s = collect(intersect(βŠ—(Aop, B), map(dual, βŠ—(dual(C), A)))) # equivalent of fs - Fblocks = Vector{Any}() - for c in cs - for Ξ³ in Ξ³s - Fs = Fsymbol(A, Aop, B, C, c, Ξ³) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end - end - F = hvcat(length(Ξ³s), Fblocks...) - @test isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) - end - end + # M x Mop x M -> M or Mop x M x Mop -> Mop + @test unitarity_test(mod_objects, modop_objects, mod_objects) end end end From 596781747a15faccc9c2bcad91404f481a052a37 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 14:14:54 +0200 Subject: [PATCH 143/206] acronym MTK --- test/setup.jl | 2 ++ test/test_A4.jl | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/test/setup.jl b/test/setup.jl index cdd5c5b..ae089ab 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -2,6 +2,8 @@ using MultiTensorKit using TensorKitSectors, TensorKit using Test, TestExtras +const MTK = MultiTensorKit + function unitarity_test(as::Vector{I}, bs::Vector{I}, cs::Vector{I}) where {I<:BimoduleSector} @assert all(a.j == b.i for a in as, b in bs) diff --git a/test/test_A4.jl b/test/test_A4.jl index b4d2ecf..f0c3e93 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -8,7 +8,7 @@ r = size(I) end @testset "$Istr Fusion Category $i" for i in 1:r - objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) + objects = I.(i, i, MTK._get_dual_cache(I)[2][i, i]) @testset "Basic properties" begin s = rand(objects, 3) @@ -27,15 +27,15 @@ for i in 1:r, j in 1:r @testset "Unitarity of $Istr F-move ($i, $j)" begin if i == j @testset "Unitarity of fusion F-move ($i, $j)" begin - fusion_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) + fusion_objects = I.(i, i, MTK._get_dual_cache(I)[2][i, i]) @test unitarity_test(fusion_objects, fusion_objects, fusion_objects) end end i != j || continue # do this part only when off-diagonal - mod_objects = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) - left_fusion_objects = I.(i, i, MultiTensorKit._get_dual_cache(I)[2][i, i]) - right_fusion_objects = I.(j, j, MultiTensorKit._get_dual_cache(I)[2][j, j]) + mod_objects = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) + left_fusion_objects = I.(i, i, MTK._get_dual_cache(I)[2][i, i]) + right_fusion_objects = I.(j, j, MTK._get_dual_cache(I)[2][j, j]) # C x C x M -> M or D x D x Mop -> Mop @testset "Unitarity of left module F-move ($i, $j)" begin @@ -53,7 +53,7 @@ for i in 1:r, j in 1:r end @testset "Unitarity of mixed module F-move ($i, $j) and opposite ($j, $i)" begin - modop_objects = I.(j, i, MultiTensorKit._get_dual_cache(I)[2][j, i]) + modop_objects = I.(j, i, MTK._get_dual_cache(I)[2][j, i]) # C x M x Mop -> C or D x Mop x M -> D @test unitarity_test(left_fusion_objects, mod_objects, modop_objects) @@ -93,7 +93,7 @@ end end @testset "$Istr ($i, $j) units and duals" for i in 1:r, j in 1:r - Cij_obs = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) + Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) s = rand(Cij_obs) @test eval(Meta.parse(sprint(show, s))) == s @@ -101,12 +101,12 @@ end @test i == j ? isone(@constinferred(one(s))) : (isone(@constinferred(leftone(s))) && isone(@constinferred(rightone(s)))) @constinferred dual(s) - @test dual(s) == I.(j, i, MultiTensorKit._get_dual_cache(I)[2][i, j][s.label]) + @test dual(s) == I.(j, i, MTK._get_dual_cache(I)[2][i, j][s.label]) @test dual(dual(s)) == s end @testset "$Istr ($i, $j) left and right units" for i in 1:r, j in 1:r - Cij_obs = I.(i, j, MultiTensorKit._get_dual_cache(I)[2][i, j]) + Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) s = rand(Cij_obs, 1)[1] sp = Vect[I](s => 1) From 547c262f97fe353078e4810f45d479891cc8b147 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 15:10:39 +0200 Subject: [PATCH 144/206] add `one` for type bimodulesector --- src/bimodulesector.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 330628a..b13fe6b 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -182,6 +182,10 @@ function Base.one(a::BimoduleSector) return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end +function Base.one(::Type{<:BimoduleSector}) + throw(ArgumentError("one of Type BimoduleSector doesn't exist")) +end + function TensorKitSectors.leftone(a::BimoduleSector) return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end From 94292f24101d4900cb88901b28ef57c72b266ad0 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 15:17:10 +0200 Subject: [PATCH 145/206] change error thrown for module one evaluation + format --- src/bimodulesector.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index b13fe6b..0b1061a 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -178,7 +178,7 @@ function extract_dual(::Type{A4Object}) end function Base.one(a::BimoduleSector) - a.i == a.j || error("unit object for module categories is ill-defined") + a.i == a.j || throw(DomainError("unit of module category ($(a.i), $(a.j)) of $(typeof(a)) is ill-defined")) return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end From 662efd808b57392b3a9f504258657ea2115b58d5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 15:57:48 +0200 Subject: [PATCH 146/206] finish up sector tests --- test/test_A4.jl | 122 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 95 insertions(+), 27 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index f0c3e93..2c26e9a 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -2,27 +2,104 @@ I = A4Object Istr = TensorKitSectors.type_repr(I) r = size(I) +println("----------------------") +println("| Sector tests |") +println("----------------------") + @testset "$Istr Basic type properties" verbose = true begin @test eval(Meta.parse(sprint(show, I))) == I @test eval(Meta.parse(TensorKitSectors.type_repr(I))) == I end -@testset "$Istr Fusion Category $i" for i in 1:r - objects = I.(i, i, MTK._get_dual_cache(I)[2][i, i]) - - @testset "Basic properties" begin - s = rand(objects, 3) - @test eval(Meta.parse(sprint(show, s[1]))) == s[1] - @test @constinferred(hash(s[1])) == hash(deepcopy(s[1])) - @test isone(@constinferred(one(s[1]))) - @constinferred dual(s[1]) - @constinferred dim(s[1]) - @constinferred frobeniusschur(s[1]) - @constinferred Bsymbol(s...) - @constinferred Fsymbol(s..., s...) +@testset "$Istr: Value iterator" begin + @test eltype(values(I)) == I + @test_throws ArgumentError one(I) + sprev = I(1, 1, 1) # first in SectorValues + for (i, s) in enumerate(values(I)) + @test !isless(s, sprev) # confirm compatibility with sort order + @test s == @constinferred (values(I)[i]) + @test findindex(values(I), s) == i + sprev = s + i >= 10 && break + end + @test I(1, 1, 1) == first(values(I)) + @test (@constinferred findindex(values(I), I(1, 1, 1))) == 1 + for s in collect(values(I)) + @test (@constinferred values(I)[findindex(values(I), s)]) == s + end +end + +@testset "$Istr ($i, $j) basic properties" for i in 1:r, j in 1:r + Cii_obs = I.(i, i, MTK._get_dual_cache(I)[2][i, i]) + Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) + Cji_obs = I.(j, i, MTK._get_dual_cache(I)[2][j, i]) + Cjj_obs = I.(j, j, MTK._get_dual_cache(I)[2][j, j]) + c, m, mop, d = rand(Cii_obs), rand(Cij_obs), rand(Cji_obs), rand(Cjj_obs) + + if i == j + @testset "Basic fusion properties" begin + s = rand(Cii_obs, 3) + @test eval(Meta.parse(sprint(show, s[1]))) == s[1] + @test @constinferred(hash(s[1])) == hash(deepcopy(s[1])) + @test isone(@constinferred(one(s[1]))) + u = I.(i, i, MTK._get_dual_cache(I)[1][i]) + @test u == @constinferred(leftone(u)) == @constinferred(rightone(u)) == + @constinferred(one(u)) + @test isone(@constinferred(one(s[1]))) + @constinferred dual(s[1]) + @test dual(s[1]) == I.(i, i, MTK._get_dual_cache(I)[2][i, i][s[1].label]) + @constinferred dim(s[1]) + @constinferred frobeniusschur(s[1]) + @constinferred Bsymbol(s...) + @constinferred Fsymbol(s..., s...) + end + else + @testset "Basic module properties" begin + @test eval(Meta.parse(sprint(show, m))) == m + @test @constinferred(hash(m)) == hash(deepcopy(m)) + + @test (isone(@constinferred(leftone(m))) && isone(@constinferred(rightone(m)))) + @test one(c) == leftone(m) == rightone(mop) + @test one(d) == rightone(m) == leftone(mop) + @test_throws DomainError one(m) + @test_throws DomainError one(mop) + + @constinferred dual(m) + @test dual(m) == I.(j, i, MTK._get_dual_cache(I)[2][i, j][m.label]) + @test dual(dual(m)) == m + + @constinferred dim(m) + @constinferred frobeniusschur(m) + @constinferred Bsymbol(m, mop, c) + @constinferred Fsymbol(mop, m, mop, mop, d, c) + end + + @testset "$Istr Fusion rules" begin + argerr = ArgumentError("invalid fusion channel") + # forbidden fusions + for obs in [(c, d), (d, c), (m, m), (mop, mop), (d, m), (m, c), (mop, d), (c, mop)] + @test_throws AssertionError("a.j == b.i") isempty(βŠ—(obs...)) + @test_throws argerr Nsymbol(obs..., rand([c, m, mop, d])) + end + + # allowed fusions + for obs in [(c, c), (d, d), (m, mop), (mop, m), (c, m), (mop, c), (m, d), (d, mop)] + @test !isempty(βŠ—(obs...)) + end + + @test Nsymbol(c, one(c), c) == Nsymbol(d, one(d), d) == 1 + + @test_throws argerr Nsymbol(m, mop, d) + @test_throws argerr Nsymbol(mop, m, c) + @test_throws argerr Fsymbol(m, mop, m, mop, c, d) + end end end +println("-----------------------------") +println("| F-symbol data tests |") +println("-----------------------------") + for i in 1:r, j in 1:r @testset "Unitarity of $Istr F-move ($i, $j)" begin if i == j @@ -46,7 +123,7 @@ for i in 1:r, j in 1:r @testset "Unitarity of right module F-move ($i, $j)" begin @test unitarity_test(mod_objects, right_fusion_objects, right_fusion_objects) end - + # C x M x D -> M or D x Mop x C -> Mop @testset "Unitarity of bimodule F-move ($i, $j)" begin @test unitarity_test(left_fusion_objects, mod_objects, right_fusion_objects) @@ -92,23 +169,14 @@ end end end -@testset "$Istr ($i, $j) units and duals" for i in 1:r, j in 1:r - Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) - - s = rand(Cij_obs) - @test eval(Meta.parse(sprint(show, s))) == s - @test @constinferred(hash(s)) == hash(deepcopy(s)) - @test i == j ? isone(@constinferred(one(s))) : - (isone(@constinferred(leftone(s))) && isone(@constinferred(rightone(s)))) - @constinferred dual(s) - @test dual(s) == I.(j, i, MTK._get_dual_cache(I)[2][i, j][s.label]) - @test dual(dual(s)) == s -end +println("-----------------------------") +println("| F-symbol data tests |") +println("-----------------------------") @testset "$Istr ($i, $j) left and right units" for i in 1:r, j in 1:r Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) - s = rand(Cij_obs, 1)[1] + s = rand(Cij_obs) sp = Vect[I](s => 1) W = sp ← sp for T in (Float32, ComplexF64) From f6b6a59353c27d295a6be36eb76072fb7e2d9565 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 17:40:16 +0200 Subject: [PATCH 147/206] start on multifusion space tests --- test/test_A4.jl | 181 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 178 insertions(+), 3 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 2c26e9a..28daf23 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -169,9 +169,184 @@ end end end -println("-----------------------------") -println("| F-symbol data tests |") -println("-----------------------------") +### start of TensorKit tests ### + +println("---------------------------------") +println("| Multifusion space tests |") +println("---------------------------------") + +i = 1 +j = 2 + +V = (Vect[I]((i, i, label) => 1 for label in MTK._numlabels(I, i, i)), + Vect[I]((i, i, 1) => 1, (i, i, 2) => 2), + Vect[I]((i, i, 1) => 1, (i, i, 2) => 1), + Vect[I]((i, i, label) => 1 for label in MTK._numlabels(I, i, i)), + Vect[I]((i, i, 1) => 2, (i, i, 3) => 3)) + +@timedtestset "Multifusion spaces " verbose = true begin + @timedtestset "GradedSpace: $(TK.type_repr(Vect[I]))" begin + gen = (values(I)[k] => (k + 1) for k in 1:length(values(I))) + + V = GradedSpace(gen) + @test eval(Meta.parse(TK.type_repr(typeof(V)))) == typeof(V) + @test eval(Meta.parse(sprint(show, V))) == V + @test eval(Meta.parse(sprint(show, V'))) == V' + @test V' == GradedSpace(gen; dual=true) + @test V == @constinferred GradedSpace(gen...) + @test V' == @constinferred GradedSpace(gen...; dual=true) + @test V == @constinferred GradedSpace(tuple(gen...)) + @test V' == @constinferred GradedSpace(tuple(gen...); dual=true) + @test V == @constinferred GradedSpace(Dict(gen)) + @test V' == @constinferred GradedSpace(Dict(gen); dual=true) + @test V == @inferred Vect[I](gen) + @test V' == @constinferred Vect[I](gen; dual=true) + @test V == @constinferred Vect[I](gen...) + @test V' == @constinferred Vect[I](gen...; dual=true) + @test V == @constinferred Vect[I](Dict(gen)) + @test V' == @constinferred Vect[I](Dict(gen); dual=true) + @test V == @constinferred typeof(V)(c => dim(V, c) for c in sectors(V)) + @test @constinferred(hash(V)) == hash(deepcopy(V)) != hash(V') + @test V == GradedSpace(reverse(collect(gen))...) + @test eval(Meta.parse(sprint(show, V))) == V + @test eval(Meta.parse(sprint(show, typeof(V)))) == typeof(V) + + @test isa(V, VectorSpace) + @test isa(V, ElementarySpace) + @test isa(InnerProductStyle(V), HasInnerProduct) + @test isa(InnerProductStyle(V), EuclideanInnerProduct) + @test isa(V, GradedSpace) + @test isa(V, GradedSpace{I}) + @test @constinferred(dual(V)) == @constinferred(conj(V)) == + @constinferred(adjoint(V)) != V + @test @constinferred(field(V)) == β„‚ + @test @constinferred(sectortype(V)) == I + slist = @constinferred sectors(V) + @test @constinferred(hassector(V, first(slist))) + @test @constinferred(dim(V)) == sum(dim(s) * dim(V, s) for s in slist) + @test @constinferred(reduceddim(V)) == sum(dim(V, s) for s in slist) + @constinferred dim(V, first(slist)) + + @test @constinferred(βŠ•(V, zero(V))) == V + @test @constinferred(βŠ•(V, V)) == Vect[I](c => 2dim(V, c) for c in sectors(V)) + @test @constinferred(βŠ•(V, V, V, V)) == Vect[I](c => 4dim(V, c) for c in sectors(V)) + + @testset "$Istr ($i, $j) spaces" for i in 1:r, j in 1:r + # space with a single sector + Wleft = @constinferred Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)) + Wright = @constinferred Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)) + WM = @constinferred Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) + WMop = @constinferred Vect[I]((j, i, label) => 1 for label in 1:MTK._numlabels(I, j, i)) + + @test @constinferred(oneunit(Wleft)) == leftoneunit(Wleft) == rightoneunit(Wleft) + @test @constinferred(oneunit(Wright)) == leftoneunit(Wright) == rightoneunit(Wright) + @test @constinferred(leftoneunit(βŠ•(Wleft, WM))) == oneunit(Wleft) + @test @constinferred(leftoneunit(βŠ•(Wright, WMop))) == oneunit(Wright) + @test @constinferred(rightoneunit(βŠ•(Wright, WM))) == oneunit(Wright) + @test @constinferred(rightoneunit(βŠ•(Wleft, WMop))) == oneunit(Wleft) + + @test_throws ArgumentError oneunit(I) + + if i != j # some tests specialised for modules + @test_throws ArgumentError oneunit(WM) + @test_throws ArgumentError oneunit(WMop) + + # sensible direct sums and fuses + ul, ur = one(I(i, i, 1)), one(I(j, j, 1)) + @test @constinferred(βŠ•(Wleft, WM)) == + Vect[I](c => 1 for c in sectors(V) if leftone(c) == ul == rightone(c) || (c.i == i && c.j == j)) + @test @constinferred(βŠ•(Wright, WMop)) == + Vect[I](c => 1 for c in sectors(V) if leftone(c) == ur == rightone(c) || (c.i == j && c.j == i)) + @test @constinferred(βŠ•(Wright, WM)) == + Vect[I](c => 1 for c in sectors(V) if rightone(c) == ur == leftone(c) || (c.i == i && c.j == j)) + @test @constinferred(βŠ•(Wleft, WMop)) == + Vect[I](c => 1 for c in sectors(V) if rightone(c) == ul == leftone(c) || (c.i == j && c.j == i)) + @test @constinferred(fuse(Wleft, WM)) == Vect[I](c => dim(Wleft) for c in sectors(WM)) # this might be wrong + @test @constinferred(fuse(Wright, WMop)) == Vect[I](c => dim(Wright) for c in sectors(WMop)) # same + + # less sensible fuse + @test @constinferred(fuse(Wleft, WMop)) == fuse(Wright, WM) == + Vect[I](c => 0 for c in sectors(V)) + + for W in [WM, WMop, Wright] + @test infimum(Wleft, W) == Vect[I](c => 0 for c in sectors(V)) + end + else + @test @constinferred(βŠ•(Wleft, Wright)) == + Vect[I](c => 2 for c in sectors(V) if c.i == c.j == i) + @test @constinferred(fuse(Wleft, WMop)) == fuse(Wright, WM) + end + + for W in [Wleft, Wright] + @test @constinferred(βŠ•(W, oneunit(W))) == + Vect[I](c => isone(c) + dim(W, c) for c in sectors(W)) + @test @constinferred(fuse(W, oneunit(W))) == W + end + end + + d = Dict{I,Int}() + for a in sectors(V), b in sectors(V) + a.j == b.i || continue # skip if not compatible + for c in a βŠ— b + d[c] = get(d, c, 0) + dim(V, a) * dim(V, b) * Nsymbol(a, b, c) + end + end + @test @constinferred(fuse(V, V)) == GradedSpace(d) + @test @constinferred(flip(V)) == + Vect[I](conj(c) => dim(V, c) for c in sectors(V))' + @test flip(V) β‰… V + @test flip(V) β‰Ύ V + @test flip(V) β‰Ώ V + @test @constinferred(βŠ•(V, V)) == @constinferred supremum(V, βŠ•(V, V)) + @test V == @constinferred infimum(V, βŠ•(V, V)) + @test V β‰Ί βŠ•(V, V) + @test !(V ≻ βŠ•(V, V)) + randlen = rand(1:length(values(I))) + s = rand(collect(values(I))[randlen:end]) # such that dim(V, s) > randlen + @test infimum(V, GradedSpace(s => randlen)) == + GradedSpace(s => randlen) + @test_throws SpaceMismatch (βŠ•(V, V')) + end + + # CONTINUE HERE + + @timedtestset "HomSpace with $(TK.type_repr(Vect[I])) " begin + for (V1, V2, V3, V4, V5) in (VIBC, VIBD, VIBM1, VIBM2, VIBMop1, VIBMop2) + W = HomSpace(V1 βŠ— V2, V3 βŠ— V4 βŠ— V5) + @test W == (V3 βŠ— V4 βŠ— V5 β†’ V1 βŠ— V2) + @test W == (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5) + @test W' == (V1 βŠ— V2 β†’ V3 βŠ— V4 βŠ— V5) + @test eval(Meta.parse(sprint(show, W))) == W + @test eval(Meta.parse(sprint(show, typeof(W)))) == typeof(W) + @test spacetype(W) == typeof(V1) + @test sectortype(W) == sectortype(V1) + @test W[1] == V1 + @test W[2] == V2 + @test W[3] == V3' + @test W[4] == V4' + @test W[5] == V5' + + @test @constinferred(hash(W)) == hash(deepcopy(W)) != hash(W') + @test W == deepcopy(W) + @test W == @constinferred permute(W, ((1, 2), (3, 4, 5))) + @test permute(W, ((2, 4, 5), (3, 1))) == (V2 βŠ— V4' βŠ— V5' ← V3 βŠ— V1') + @test (V1 βŠ— V2 ← V1 βŠ— V2) == @constinferred TK.compose(W, W') + + @test_throws ErrorException insertleftunit(W) + @test insertrightunit(W) == (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 βŠ— rightoneunit(V5)) + @test_throws ErrorException insertrightunit(W, 6) + @test_throws ErrorException insertleftunit(W, 6) + + @test (V1 βŠ— V2 βŠ— rightoneunit(V2) ← V3 βŠ— V4 βŠ— V5) == + @constinferred(insertrightunit(W, 2)) + @test (V1 βŠ— V2 ← leftoneunit(V3) βŠ— V3 βŠ— V4 βŠ— V5) == + @constinferred(insertleftunit(W, 3)) + @test @constinferred(removeunit(insertleftunit(W, 3), 3)) == W + @test_throws ErrorException @constinferred(insertrightunit(one(V1) ← V1, 0)) # should I specify it's the other error? + @test_throws ErrorException insertleftunit(one(V1) ← V1, 0) + end + end +end @testset "$Istr ($i, $j) left and right units" for i in 1:r, j in 1:r Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) From a2f1ec16ae0c52104232f75f7bbda8a4211ef442 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 8 Aug 2025 17:40:42 +0200 Subject: [PATCH 148/206] custom `zero` of `GradedSpace` and `fuse` --- src/bimodulesector.jl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 0b1061a..9cf3f2d 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -302,11 +302,24 @@ function rounddim(c::I) where {I<:BimoduleSector} end end -function dim(V::GradedSpace{<:BimoduleSector}) +function TensorKit.dim(V::GradedSpace{<:BimoduleSector}) T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) return reduce(+, dim(V, c) * rounddim(c) for c in sectors(V); init=zero(T)) end +Base.zero(S::Type{<:GradedSpace{<:BimoduleSector}}) = S() + +function TensorKit.fuse(V₁::GradedSpace{I}, Vβ‚‚::GradedSpace{I}) where {I<:BimoduleSector} + dims = SectorDict{I,Int}() + for a in sectors(V₁), b in sectors(Vβ‚‚) + a.j == b.i || continue # skip if not compatible + for c in a βŠ— b + dims[c] = get(dims, c, 0) + Nsymbol(a, b, c) * dim(V₁, a) * dim(Vβ‚‚, b) + end + end + return typeof(V₁)(dims) +end + # limited oneunit function Base.oneunit(S::GradedSpace{<:BimoduleSector}) allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || From 04bac3d1ff07ae75bbba5ef8e54987f88e59e4f8 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 11 Aug 2025 16:30:29 +0200 Subject: [PATCH 149/206] specify TensorKit module for `SectorDict` --- src/bimodulesector.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 9cf3f2d..a86327f 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -310,7 +310,7 @@ end Base.zero(S::Type{<:GradedSpace{<:BimoduleSector}}) = S() function TensorKit.fuse(V₁::GradedSpace{I}, Vβ‚‚::GradedSpace{I}) where {I<:BimoduleSector} - dims = SectorDict{I,Int}() + dims = TensorKit.SectorDict{I,Int}() for a in sectors(V₁), b in sectors(Vβ‚‚) a.j == b.i || continue # skip if not compatible for c in a βŠ— b From 4870e09f5a4be7c16298120a07fb696eb0b6b4cf Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 11 Aug 2025 16:33:33 +0200 Subject: [PATCH 150/206] potential overkill fusion tree stuff --- src/bimodulesector.jl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index a86327f..e190a52 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -399,3 +399,19 @@ function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T, isempty(inds) && return zero(scalartype(t)) return only(last(Bs[only(inds)])) end + +# is this even necessary? can let it error at TensorKit fusiontrees.jl:93 from the one(<:BimoduleSector) call +# but these errors are maybe more informative +function TensorKit.FusionTree(uncoupled::Tuple{<:I,Vararg{I}}) where {I<:BimoduleSector} + coupled = collect(βŠ—(uncoupled...)) + if length(coupled) == 0 # illegal fusion somewhere + throw(ArgumentError("Forbidden fusion with uncoupled sectors $uncoupled")) + else # allowed fusions require inner lines + error("fusion tree requires inner lines if `FusionStyle(I) <: MultipleFusion`") + end +end + +# this one might also be overkill, since `FusionTreeIterator`s don't check whether the fusion is allowed +function fusiontrees(uncoupled::Tuple{I,Vararg{I}}) where {I<:BimoduleSector} + return throw(ArgumentError("coupled sector must be provided for $I fusion")) +end \ No newline at end of file From 16104fc84de35cc0800b343284ae4b7b417383ec Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 12 Aug 2025 10:33:36 +0200 Subject: [PATCH 151/206] finish fusion tree tests (not debugged) + move around imports --- test/setup.jl | 56 +++++++++- test/test_A4.jl | 274 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 319 insertions(+), 11 deletions(-) diff --git a/test/setup.jl b/test/setup.jl index ae089ab..2669aeb 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -1,9 +1,11 @@ using MultiTensorKit -using TensorKitSectors, TensorKit -using Test, TestExtras +using TensorKitSectors +using Random const MTK = MultiTensorKit +Random.seed!(1234) + function unitarity_test(as::Vector{I}, bs::Vector{I}, cs::Vector{I}) where {I<:BimoduleSector} @assert all(a.j == b.i for a in as, b in bs) @@ -29,3 +31,53 @@ function unitarity_test(as::Vector{I}, bs::Vector{I}, end return true end + +all_objects(::Type{<:BimoduleSector}, i::Int, j::Int) = [I(i, j, k) for k in 1:MTK._numlabels(I, i, j)] + +function rand_object(I::Type{<:BimoduleSector}, i::Int, j::Int) + obs = all_objects(I, i, j) + ob = rand(obs) + if i == j + while ob == one(ob) # unit of any fusion cat avoided + ob = rand(obs) + end + end + return ob +end + +function random_fusion(I::Type{<:BimoduleSector}, i::Int, j::Int, N::Int) # for fusion tree tests + Cs = all_objects(I, i, i) + Ds = all_objects(I, j, j) + Ms = all_objects(I, i, j) + Mops = all_objects(I, j, i) + allobs = vcat(Cs, Ds, Ms, Mops) + + in = nothing + out = nothing + while in === nothing + out = ntuple(n -> rand(allobs), N) + try + in = rand(collect(βŠ—(out...))) + catch e + if isa(e, AssertionError) + in = nothing + else + rethrow(e) + end + end + end + return out +end + +# for fusion tree merge test +function safe_tensor_product(x::I, y::I) where {I<:BimoduleSector} + try + return x βŠ— y + catch e + if e isa AssertionError + return nothing + else + rethrow(e) + end + end +end \ No newline at end of file diff --git a/test/test_A4.jl b/test/test_A4.jl index 28daf23..82b8423 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -1,3 +1,11 @@ +using MultiTensorKit +using TensorKitSectors, TensorKit +using Test, TestExtras +using Random + +const MTK = MultiTensorKit +const TK = TensorKit + I = A4Object Istr = TensorKitSectors.type_repr(I) r = size(I) @@ -178,12 +186,6 @@ println("---------------------------------") i = 1 j = 2 -V = (Vect[I]((i, i, label) => 1 for label in MTK._numlabels(I, i, i)), - Vect[I]((i, i, 1) => 1, (i, i, 2) => 2), - Vect[I]((i, i, 1) => 1, (i, i, 2) => 1), - Vect[I]((i, i, label) => 1 for label in MTK._numlabels(I, i, i)), - Vect[I]((i, i, 1) => 2, (i, i, 3) => 3)) - @timedtestset "Multifusion spaces " verbose = true begin @timedtestset "GradedSpace: $(TK.type_repr(Vect[I]))" begin gen = (values(I)[k] => (k + 1) for k in 1:length(values(I))) @@ -308,10 +310,14 @@ V = (Vect[I]((i, i, label) => 1 for label in MTK._numlabels(I, i, i)), @test_throws SpaceMismatch (βŠ•(V, V')) end - # CONTINUE HERE + @timedtestset "HomSpace with $(TK.type_repr(Vect[I])) involving ($i, $j)" for i in 1:r, j in 1:r + V = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I]((i, j, 1) => 3), + Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j))) - @timedtestset "HomSpace with $(TK.type_repr(Vect[I])) " begin - for (V1, V2, V3, V4, V5) in (VIBC, VIBD, VIBM1, VIBM2, VIBMop1, VIBMop2) + for (V1, V2, V3, V4, V5) in (V,) W = HomSpace(V1 βŠ— V2, V3 βŠ— V4 βŠ— V5) @test W == (V3 βŠ— V4 βŠ— V5 β†’ V1 βŠ— V2) @test W == (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5) @@ -348,6 +354,256 @@ V = (Vect[I]((i, i, label) => 1 for label in MTK._numlabels(I, i, i)), end end +println("---------------------------------------") +println("| Multifusion fusion tree tests |") +println("---------------------------------------") + +@timedtestset "Fusion trees for $(TK.type_repr(I)) involving ($i, $j)" verbose = true for i in 1:r, j in 1:7 + N = 6 + Mop = rand_object(I, j, i) + M = rand_object(I, i, j) + C0 = one(I(i, i, 1)) + C1 = rand_object(I, i, i) + D0 = one(I(j, j, 1)) + D1 = rand_object(I, j, j) + out = (Mop, C0, C1, M, D0, D1) # should I try to make a non-hardcoded example? could vary number of Cs and Ds, as well as randomly fuse and check if allowed + isdual = ntuple(n -> rand(Bool), N) + in = rand(collect(βŠ—(out...))) # will be in π’žβ±Όβ±Ό with this choice of out + + numtrees = length(fusiontrees(out, in, isdual)) # will be 1 for i != j + @test numtrees == count(n -> true, fusiontrees(out, in, isdual)) + + it = @constinferred fusiontrees(out, in, isdual) + @constinferred Nothing iterate(it) + f, s = iterate(it) + @constinferred Nothing iterate(it, s) + @test f == @constinferred first(it) + @testset "Fusion tree $Istr: printing" begin + @test eval(Meta.parse(sprint(show, f))) == f + end + + @testset "Fusion tree $Istr: constructor properties" for u in (C0, D0) + @constinferred FusionTree((), u, (), (), ()) + @constinferred FusionTree((u,), u, (false,), (), ()) + @constinferred FusionTree((u, u), u, (false, false), (), (1,)) + @constinferred FusionTree((u, u, u), u, (false, false, false), (u,), (1, 1)) + @constinferred FusionTree((u, u, u, u), u, (false, false, false, false), (u, u), + (1, 1, 1)) + @test_throws MethodError FusionTree((u, u, u), u, (false, false), (u,), (1, 1)) + @test_throws MethodError FusionTree((u, u, u), u, (false, false, false), (u, u), + (1, 1)) + @test_throws MethodError FusionTree((u, u, u), u, (false, false, false), (u,), + (1, 1, 1)) + @test_throws MethodError FusionTree((u, u, u), u, (false, false, false), (), (1,)) + + f = FusionTree((u, u, u), u, (false, false, false), (u,), (1, 1)) + @test sectortype(f) == I + @test length(f) == 3 + @test FusionStyle(f) == FusionStyle(I) + @test BraidingStyle(f) == BraidingStyle(I) + + # SimpleFusion + errstr = "fusion tree requires inner lines if `FusionStyle(I) <: MultipleFusion`" + @test_throws errstr FusionTree((), u, ()) + @test_throws errstr FusionTree((u,), u, (false,)) + @test_throws errstr FusionTree((u, u), u, (false, false)) + @test_throws errstr FusionTree((u, u, u), u) + @test_throws errstr FusionTree((u, u, u, u)) # custom FusionTree constructor required here + end + + @testset "Fusion tree $Istr: insertat" begin + N = 4 + out2 = random_fusion(I, i, j, N) + in2 = rand(collect(βŠ—(out2...))) + isdual2 = ntuple(n -> rand(Bool), N) + f2 = rand(collect(fusiontrees(out2, in2, isdual2))) + for k in 1:N + out1, in1 = nothing, nothing + while in1 === nothing + try + out1 = random_fusion(I, i, j, N) # guaranteed good fusion + out1 = Base.setindex(out1, in2, k) # can lead to poor fusion + in1 = rand(collect(βŠ—(out1...))) + catch e + if isa(e, AssertionError) + in1 = nothing # keep trying till out1 is compatible with inserting in2 at k + else + rethrow(e) + end + end + end + isdual1 = ntuple(n -> rand(Bool), N) + isdual1 = Base.setindex(isdual1, false, k) + f1 = rand(collect(fusiontrees(out1, in1, isdual1))) + + trees = @constinferred TK.insertat(f1, k, f2) + @test norm(values(trees)) β‰ˆ 1 + + f1a, f1b = @constinferred TK.split(f1, $k) + @test length(TK.insertat(f1b, 1, f1a)) == 1 + @test first(TK.insertat(f1b, 1, f1a)) == (f1 => 1) + + # no braid tests for non-hardcoded example + end + end + # no planar trace tests + + @testset "Fusion tree $Istr: elementary artin braid" begin + N = length(out) + isdual = ntuple(n -> rand(Bool), N) + # no general artin braid test + + # not sure how useful this test is, it does the trivial braiding (choice of out) + f = rand(collect(it)) # in this case the 1 tree + d1 = TK.artin_braid(f, 2) # takes unit C0 with current out + d2 = empty(d1) + for (f1, coeff1) in d1 + for (f2, coeff2) in TK.artin_braid(f1, 3) + d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 + end + end + d1 = d2 + d2 = empty(d1) + for (f1, coeff1) in d1 + for (f2, coeff2) in TK.artin_braid(f1, 3; inv=true) + d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 + end + end + d1 = d2 + d2 = empty(d1) + for (f1, coeff1) in d1 + for (f2, coeff2) in TK.artin_braid(f1, 2; inv=true) + d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 + end + end + d1 = d2 + for (f1, coeff1) in d1 + if f1 == f + @test coeff1 β‰ˆ 1 + else + @test isapprox(coeff1, 0; atol=1.0e-12, rtol=1.0e-12) + end + end + end + + # no braiding and permuting test + @testset "Fusion tree $Istr: merging" begin + N = 3 + out1 = random_fusion(I, i, j, N) + out2 = random_fusion(I, i, j, N) + in1 = rand(collect(βŠ—(out1...))) + in2 = rand(collect(βŠ—(out2...))) + tp = safe_tensor_product(in1, in2) # messy solution but it works + while tp === nothing + out1 = random_fusion(I, i, j, N) + out2 = random_fusion(I, i, j, N) + in1 = rand(collect(βŠ—(out1...))) + in2 = rand(collect(βŠ—(out2...))) + tp = safe_tensor_product(in1, in2) + end + + f1 = rand(collect(fusiontrees(out1, in1))) + f2 = rand(collect(fusiontrees(out2, in2))) + + + @test dim(in1) * dim(in2) β‰ˆ sum(abs2(coeff) * dim(c) for c in in1 βŠ— in2 + for ΞΌ in 1:Nsymbol(in1, in2, c) + for (f, coeff) in TK.merge(f1, f2, c, ΞΌ)) + # no merge and braid interplay tests + end + + # hardcoded double fusion tree tests + N = 6 + out = (Mop, C0, C1, M, D0, D1) # same as above + out2 = (D0, D1, Mop, C0, C1, M) # different order that still fuses to D0 or D1 + + incoming = rand(collect(βŠ—(out...))) # will be in π’žβ±Όβ±Ό + while incoming βˆ‰ collect(βŠ—(out2...)) # when i = j these don't necessarily fuse to the same object, since Mop x M doesn't return all objects in π’žα΅’α΅’ + Mop = rand_object(I, j, i) + out2 = (D0, D1, Mop, C0, C1, M) + @show i,j + end + + f1 = rand(collect(fusiontrees(out, incoming, ntuple(n -> rand(Bool), N)))) + @info "before here?" + f2 = rand(collect(fusiontrees(out2, incoming, ntuple(n -> rand(Bool), N)))) + @info "or over here?" + + @testset "Double fusion tree $Istr: repartitioning" begin + for n in 0:(2 * N) + d = @constinferred TK.repartition(f1, f2, $n) + @test dim(incoming) β‰ˆ + sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) + d2 = Dict{typeof((f1, f2)),valtype(d)}() + for ((f1β€², f2β€²), coeff) in d + for ((f1β€²β€², f2β€²β€²), coeff2) in TK.repartition(f1β€², f2β€², N) + d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff2 * coeff + end + end + for ((f1β€², f2β€²), coeff2) in d2 + if f1 == f1β€² && f2 == f2β€² + @test coeff2 β‰ˆ 1 + else + @test isapprox(coeff2, 0; atol=1.0e-12, rtol=1.0e-12) + end + end + end + end + + # no double fusion tree permutation tests + @testset "Double fusion tree $Istr: transposition" begin + for n in 0:(2N) + i0 = rand(1:(2N)) + p = mod1.(i0 .+ (1:(2N)), 2N) + ip = mod1.(-i0 .+ (1:(2N)), 2N) + pβ€² = tuple(getindex.(Ref(vcat(1:N, (2N):-1:(N + 1))), p)...) + p1, p2 = pβ€²[1:n], pβ€²[(2N):-1:(n + 1)] + ipβ€² = tuple(getindex.(Ref(vcat(1:n, (2N):-1:(n + 1))), ip)...) + ip1, ip2 = ipβ€²[1:N], ipβ€²[(2N):-1:(N + 1)] + + d = @constinferred transpose(f1, f2, p1, p2) + @test dim(incoming) β‰ˆ + sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) + d2 = Dict{typeof((f1, f2)),valtype(d)}() + for ((f1β€², f2β€²), coeff) in d + dβ€² = transpose(f1β€², f2β€², ip1, ip2) + for ((f1β€²β€², f2β€²β€²), coeff2) in dβ€² + d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff2 * coeff + end + end + for ((f1β€², f2β€²), coeff2) in d2 + if f1 == f1β€² && f2 == f2β€² + @test coeff2 β‰ˆ 1 + else + @test abs(coeff2) < 1.0e-12 + end + end + end + end + + @testset "Double fusion tree $Istr: planar trace" begin + d1 = transpose(f1, f1, (N + 1, 1:N..., ((2N):-1:(N + 3))...), (N + 2,)) + f1front, = TK.split(f1, N - 1) + T = sectorscalartype(I) + d2 = Dict{typeof((f1front, f1front)),T}() + for ((f1β€², f2β€²), coeffβ€²) in d1 + for ((f1β€²β€², f2β€²β€²), coeffβ€²β€²) in + TK.planar_trace(f1β€², f2β€², (2:N...,), (1, ((2N):-1:(N + 3))...), (N + 1,), + (N + 2,)) + coeff = coeffβ€² * coeffβ€²β€² + d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff + end + end + for ((f1_, f2_), coeff) in d2 + if (f1_, f2_) == (f1front, f1front) + @test coeff β‰ˆ dim(f1.coupled) / dim(f1front.coupled) + else + @test abs(coeff) < 1.0e-12 + end + end + end +end + @testset "$Istr ($i, $j) left and right units" for i in 1:r, j in 1:r Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) From 3a1cf231955256fe938323e7a4c5e8867c71689b Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 12 Aug 2025 13:57:36 +0200 Subject: [PATCH 152/206] remove debug elements --- test/test_A4.jl | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 82b8423..8ed5940 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -183,9 +183,6 @@ println("---------------------------------") println("| Multifusion space tests |") println("---------------------------------") -i = 1 -j = 2 - @timedtestset "Multifusion spaces " verbose = true begin @timedtestset "GradedSpace: $(TK.type_repr(Vect[I]))" begin gen = (values(I)[k] => (k + 1) for k in 1:length(values(I))) @@ -358,7 +355,7 @@ println("---------------------------------------") println("| Multifusion fusion tree tests |") println("---------------------------------------") -@timedtestset "Fusion trees for $(TK.type_repr(I)) involving ($i, $j)" verbose = true for i in 1:r, j in 1:7 +@timedtestset "Fusion trees for $(TK.type_repr(I)) involving ($i, $j)" verbose = true for i in 1:r, j in 1:r N = 6 Mop = rand_object(I, j, i) M = rand_object(I, i, j) @@ -521,13 +518,10 @@ println("---------------------------------------") while incoming βˆ‰ collect(βŠ—(out2...)) # when i = j these don't necessarily fuse to the same object, since Mop x M doesn't return all objects in π’žα΅’α΅’ Mop = rand_object(I, j, i) out2 = (D0, D1, Mop, C0, C1, M) - @show i,j end f1 = rand(collect(fusiontrees(out, incoming, ntuple(n -> rand(Bool), N)))) - @info "before here?" f2 = rand(collect(fusiontrees(out2, incoming, ntuple(n -> rand(Bool), N)))) - @info "or over here?" @testset "Double fusion tree $Istr: repartitioning" begin for n in 0:(2 * N) @@ -551,6 +545,8 @@ println("---------------------------------------") end # no double fusion tree permutation tests + + # very slow for (1, 6), (3, 4), (3, 5), (3, 6), (5, 6), (6, 1), (6, 5), (7, 1), (7, 4), (7, 6) @testset "Double fusion tree $Istr: transposition" begin for n in 0:(2N) i0 = rand(1:(2N)) From 6ed09608c5ab841495dc21c7fddc5b66bdf85597 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 12 Aug 2025 14:23:34 +0200 Subject: [PATCH 153/206] add diagonal tensor tests --- test/test_A4.jl | 232 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/test/test_A4.jl b/test/test_A4.jl index 8ed5940..688e2b9 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -2,6 +2,7 @@ using MultiTensorKit using TensorKitSectors, TensorKit using Test, TestExtras using Random +using LinearAlgebra: LinearAlgebra const MTK = MultiTensorKit const TK = TensorKit @@ -600,6 +601,237 @@ println("---------------------------------------") end end +println("-------------------------------------------") +println("| Multifusion diagonal tensor tests |") +println("-------------------------------------------") + +V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) + +@timedtestset "DiagonalTensor" begin + @timedtestset "Basic properties and algebra" begin + for T in (Float32, Float64, ComplexF32, ComplexF64, BigFloat) + # constructors + t = @constinferred DiagonalTensorMap{T}(undef, V) + t = @constinferred DiagonalTensorMap(rand(T, reduceddim(V)), V) + t2 = @constinferred DiagonalTensorMap{T}(undef, space(t)) + @test space(t2) == space(t) + @test_throws ArgumentError DiagonalTensorMap{T}(undef, V^2 ← V) + t2 = @constinferred DiagonalTensorMap{T}(undef, domain(t)) + @test space(t2) == space(t) + @test_throws ArgumentError DiagonalTensorMap{T}(undef, V^2) + # properties + @test @constinferred(hash(t)) == hash(deepcopy(t)) + @test scalartype(t) == T + @test codomain(t) == ProductSpace(V) + @test domain(t) == ProductSpace(V) + @test space(t) == (V ← V) + @test space(t') == (V ← V) + @test dim(t) == dim(space(t)) + # blocks + bs = @constinferred blocks(t) + (c, b1), state = @constinferred Nothing iterate(bs) + @test c == first(blocksectors(V ← V)) + next = @constinferred Nothing iterate(bs, state) + b2 = @constinferred block(t, first(blocksectors(t))) + @test b1 == b2 + @test eltype(bs) === Pair{typeof(c),typeof(b1)} + @test typeof(b1) === TK.blocktype(t) + # basic linear algebra + @test isa(@constinferred(norm(t)), real(T)) + @test norm(t)^2 β‰ˆ dot(t, t) + Ξ± = rand(T) + @test norm(Ξ± * t) β‰ˆ abs(Ξ±) * norm(t) + @test norm(t + t, 2) β‰ˆ 2 * norm(t, 2) + @test norm(t + t, 1) β‰ˆ 2 * norm(t, 1) + @test norm(t + t, Inf) β‰ˆ 2 * norm(t, Inf) + p = 3 * rand(Float64) + @test norm(t + t, p) β‰ˆ 2 * norm(t, p) + @test norm(t) β‰ˆ norm(t') + + @test t == @constinferred(TensorMap(t)) + @test norm(t + TensorMap(t)) β‰ˆ 2 * norm(t) + + @test norm(zerovector!(t)) == 0 + @test norm(one!(t)) β‰ˆ sqrt(dim(V)) + @test one!(t) == id(V) + @test norm(one!(t) - id(V)) == 0 + + t1 = DiagonalTensorMap(rand(T, reduceddim(V)), V) + t2 = DiagonalTensorMap(rand(T, reduceddim(V)), V) + t3 = DiagonalTensorMap(rand(T, reduceddim(V)), V) + Ξ± = rand(T) + Ξ² = rand(T) + @test @constinferred(dot(t1, t2)) β‰ˆ conj(dot(t2, t1)) + @test dot(t2, t1) β‰ˆ conj(dot(t2', t1')) + @test dot(t3, Ξ± * t1 + Ξ² * t2) β‰ˆ Ξ± * dot(t3, t1) + Ξ² * dot(t3, t2) + end + end + + @timedtestset "Basic linear algebra: test via conversion" begin + for T in (Float32, ComplexF64) + t1 = DiagonalTensorMap(rand(T, reduceddim(V)), V) + t2 = DiagonalTensorMap(rand(T, reduceddim(V)), V) + @test norm(t1, 2) β‰ˆ norm(convert(TensorMap, t1), 2) + @test dot(t2, t1) β‰ˆ dot(convert(TensorMap, t2), convert(TensorMap, t1)) + Ξ± = rand(T) + @test convert(TensorMap, Ξ± * t1) β‰ˆ Ξ± * convert(TensorMap, t1) + @test convert(TensorMap, t1') β‰ˆ convert(TensorMap, t1)' + @test convert(TensorMap, t1 + t2) β‰ˆ + convert(TensorMap, t1) + convert(TensorMap, t2) + end + end + @timedtestset "Real and imaginary parts" begin + for T in (Float64, ComplexF64, ComplexF32) + t = DiagonalTensorMap(rand(T, reduceddim(V)), V) + + tr = @constinferred real(t) + @test scalartype(tr) <: Real + @test real(convert(TensorMap, t)) == convert(TensorMap, tr) + + ti = @constinferred imag(t) + @test scalartype(ti) <: Real + @test imag(convert(TensorMap, t)) == convert(TensorMap, ti) + + tc = @inferred complex(t) + @test scalartype(tc) <: Complex + @test complex(convert(TensorMap, t)) == convert(TensorMap, tc) + + tc2 = @inferred complex(tr, ti) + @test tc2 β‰ˆ tc + end + end + @timedtestset "Tensor conversion" begin + t = @constinferred DiagonalTensorMap(undef, V) + rand!(t.data) + # element type conversion + tc = complex(t) + @test convert(typeof(tc), t) == tc + @test typeof(convert(typeof(tc), t)) == typeof(tc) + # to and from generic TensorMap + td = DiagonalTensorMap(TensorMap(t)) + @test t == td + @test typeof(td) == typeof(t) + end + @timedtestset "Trace, Multiplication and inverse" begin + t1 = DiagonalTensorMap(rand(Float64, reduceddim(V)), V) + t2 = DiagonalTensorMap(rand(ComplexF64, reduceddim(V)), V) + @test tr(TensorMap(t1)) == @constinferred tr(t1) + @test tr(TensorMap(t2)) == @constinferred tr(t2) + @test TensorMap(@constinferred t1 * t2) β‰ˆ TensorMap(t1) * TensorMap(t2) + @test TensorMap(@constinferred t1 \ t2) β‰ˆ TensorMap(t1) \ TensorMap(t2) + @test TensorMap(@constinferred t1 / t2) β‰ˆ TensorMap(t1) / TensorMap(t2) + @test TensorMap(@constinferred inv(t1)) β‰ˆ inv(TensorMap(t1)) + @test TensorMap(@constinferred pinv(t1)) β‰ˆ pinv(TensorMap(t1)) + @test all(Base.Fix2(isa, DiagonalTensorMap), + (t1 * t2, t1 \ t2, t1 / t2, inv(t1), pinv(t1))) + # no V * V' * V ← V or V^2 ← V tests due to Nsymbol erroring where fusion is forbidden + end + @timedtestset "Tensor contraction " for i in 1:r + W = Vect[I]((i, i, label) => 2 for label in 1:MTK._numlabels(I, i, i)) + + d = DiagonalTensorMap(rand(ComplexF64, reduceddim(W)), W) + t = TensorMap(d) + A = randn(ComplexF64, W βŠ— W' βŠ— W, W) + B = randn(ComplexF64, W βŠ— W' βŠ— W, W βŠ— W') # empty for modules so untested + + @planar E1[-1 -2 -3; -4 -5] := B[-1 -2 -3; 1 -5] * d[1; -4] + @planar E2[-1 -2 -3; -4 -5] := B[-1 -2 -3; 1 -5] * t[1; -4] + @test E1 β‰ˆ E2 + @planar E1[-1 -2 -3; -4 -5] = B[-1 -2 -3; -4 1] * d'[-5; 1] + @planar E2[-1 -2 -3; -4 -5] = B[-1 -2 -3; -4 1] * t'[-5; 1] + @test E1 β‰ˆ E2 + @planar E1[-1 -2 -3; -4 -5] = B[1 -2 -3; -4 -5] * d[-1; 1] + @planar E2[-1 -2 -3; -4 -5] = B[1 -2 -3; -4 -5] * t[-1; 1] + @test E1 β‰ˆ E2 + @planar E1[-1 -2 -3; -4 -5] = B[-1 1 -3; -4 -5] * d[1; -2] + @planar E2[-1 -2 -3; -4 -5] = B[-1 1 -3; -4 -5] * t[1; -2] + @test E1 β‰ˆ E2 + @planar E1[-1 -2 -3; -4 -5] = B[-1 -2 1; -4 -5] * d'[-3; 1] + @planar E2[-1 -2 -3; -4 -5] = B[-1 -2 1; -4 -5] * t'[-3; 1] + @test E1 β‰ˆ E2 + end + @timedtestset "Factorization" begin + for T in (Float32, ComplexF64) + t = DiagonalTensorMap(rand(T, reduceddim(V)), V) + @testset "eig" begin + D, W = @constinferred eig(t) + @test t * W β‰ˆ W * D + t2 = t + t' + D2, V2 = @constinferred eigh(t2) + VdV2 = V2' * V2 + @test VdV2 β‰ˆ one(VdV2) + @test t2 * V2 β‰ˆ V2 * D2 + + @test rank(D) β‰ˆ rank(t) + @test cond(D) β‰ˆ cond(t) + @test all(((s, t),) -> isapprox(s, t), + zip(values(LinearAlgebra.eigvals(D)), + values(LinearAlgebra.eigvals(t)))) + end + @testset "leftorth with $alg" for alg in (TK.QR(), TK.QL()) + Q, R = @constinferred leftorth(t; alg=alg) + QdQ = Q' * Q + @test QdQ β‰ˆ one(QdQ) + @test Q * R β‰ˆ t + if alg isa Polar + @test isposdef(R) + end + end + @testset "rightorth with $alg" for alg in (TK.RQ(), TK.LQ()) + L, Q = @constinferred rightorth(t; alg=alg) + QQd = Q * Q' + @test QQd β‰ˆ one(QQd) + @test L * Q β‰ˆ t + if alg isa Polar + @test isposdef(L) + end + end + @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) + U, S, Vα΄΄ = @constinferred tsvd(t; alg=alg) + UdU = U' * U + @test UdU β‰ˆ one(UdU) + VdV = Vα΄΄ * Vα΄΄' + @test VdV β‰ˆ one(VdV) + @test U * S * Vα΄΄ β‰ˆ t + + @test rank(S) β‰ˆ rank(t) + @test cond(S) β‰ˆ cond(t) + @test all(((s, t),) -> isapprox(s, t), + zip(values(LinearAlgebra.svdvals(S)), + values(LinearAlgebra.svdvals(t)))) + end + end + end + @timedtestset "Tensor functions" begin + for T in (Float64, ComplexF64) + d = DiagonalTensorMap(rand(T, reduceddim(V)), V) + # rand is important for positive numbers in the real case, for log and sqrt + t = TensorMap(d) + @test @constinferred exp(d) β‰ˆ exp(t) + @test @constinferred log(d) β‰ˆ log(t) + @test @constinferred sqrt(d) β‰ˆ sqrt(t) + @test @constinferred sin(d) β‰ˆ sin(t) + @test @constinferred cos(d) β‰ˆ cos(t) + @test @constinferred tan(d) β‰ˆ tan(t) + @test @constinferred cot(d) β‰ˆ cot(t) + @test @constinferred sinh(d) β‰ˆ sinh(t) + @test @constinferred cosh(d) β‰ˆ cosh(t) + @test @constinferred tanh(d) β‰ˆ tanh(t) + @test @constinferred coth(d) β‰ˆ coth(t) + @test @constinferred asin(d) β‰ˆ asin(t) + @test @constinferred acos(d) β‰ˆ acos(t) + @test @constinferred atan(d) β‰ˆ atan(t) + @test @constinferred acot(d) β‰ˆ acot(t) + @test @constinferred asinh(d) β‰ˆ asinh(t) + @test @constinferred acosh(one(d) + d) β‰ˆ acosh(one(t) + t) + @test @constinferred atanh(d) β‰ˆ atanh(t) + @test @constinferred acoth(one(t) + d) β‰ˆ acoth(one(d) + t) + end + end +end + + + @testset "$Istr ($i, $j) left and right units" for i in 1:r, j in 1:r Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) From 679f6cfcf9378dad2718a0605a597db5587246d6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 12 Aug 2025 15:18:59 +0200 Subject: [PATCH 154/206] start of tensor tests (modules untested) --- test/test_A4.jl | 512 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 512 insertions(+) diff --git a/test/test_A4.jl b/test/test_A4.jl index 688e2b9..73ffe54 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -830,7 +830,519 @@ V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) end end +@timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r + VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](one(I(i, i, 1)) => 2), + Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) + ) + VD = (Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), + Vect[I](one(I(j, j, 1)) => 2), + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), + Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 3) + ) + + VM1 = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), + Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), + Vect[I](rand_object(I, i, j) => 4), + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 3) + ) + + VM2 = (Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), + Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), + Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), + Vect[I](rand_object(I, i, j) => 4), + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 3) + ) + + VMop1 = (Vect[I]((j, i, label) => 1 for label in 1:MTK._numlabels(I, j, i)), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), + Vect[I](rand_object(I, j, i) => 4), + Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) + ) + + VMop2 = (Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), + Vect[I]((j, i, label) => 1 for label in 1:MTK._numlabels(I, j, i)), + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), + Vect[I](rand_object(I, j, i) => 4), + Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) + ) + + Vcol = i != j ? (VC, VD, VM1, VM2, VMop1, VMop2) : (VC,) # avoid duplicate runs + + for V in Vcol + V1, V2, V3, V4, V5 = V + @timedtestset "Basic tensor properties" begin + W = V1 βŠ— V2 βŠ— V3 βŠ— V4 βŠ— V5 # fusion matters + for T in (Int, Float32, Float64, ComplexF32, ComplexF64, BigFloat) + t = @constinferred zeros(T, W) + if isempty(t.data) # non-diagonal sector fuses poorly + W = V3 βŠ— V4 βŠ— V5 + t = @constinferred zeros(T, W) # also empty because M isn't diagonal so can't fuse to empty space + end + @test @constinferred(hash(t)) == hash(deepcopy(t)) + @test scalartype(t) == T + @test norm(t) == 0 + @test codomain(t) == W + @test space(t) == (W ← one(W)) + @test domain(t) == one(W) + @test typeof(t) == TensorMap{T,spacetype(t),length(W),0,Vector{T}} + # blocks + bs = @constinferred blocks(t) + if !isempty(bs) + (c, b1), state = @constinferred Nothing iterate(bs) # errors if fusion gives empty data + # @test c == first(blocksectors(W)) # unit doesn't have label 1 + next = @constinferred Nothing iterate(bs, state) + b2 = @constinferred block(t, first(blocksectors(t))) + @test b1 == b2 + @test eltype(bs) === Pair{typeof(c),typeof(b1)} + @test typeof(b1) === TK.blocktype(t) + @test typeof(c) === sectortype(t) + end + end + end + @timedtestset "Tensor Dict conversion" begin + W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # rewritten to be compatible with module fusion + for T in (Int, Float32, ComplexF64) + t = @constinferred rand(T, W) + d = convert(Dict, t) + @test t == convert(TensorMap, d) + end + end + # no tensor array conversion tests: no fusion tensor + @timedtestset "Basic linear algebra" begin + W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 + for T in (Float32, ComplexF64) + t = @constinferred rand(T, W) # fusion matters here + @test scalartype(t) == T + @test space(t) == W + @test space(t') == W' + @test dim(t) == dim(space(t)) + @test codomain(t) == codomain(W) + @test domain(t) == domain(W) + # blocks for adjoint + bs = @constinferred blocks(t') + (c, b1), state = @constinferred Nothing iterate(bs) + @test c == first(blocksectors(W')) + next = @constinferred Nothing iterate(bs, state) + b2 = @constinferred block(t', first(blocksectors(t'))) + @test b1 == b2 + @test eltype(bs) === Pair{typeof(c),typeof(b1)} + @test typeof(b1) === TK.blocktype(t') + @test typeof(c) === sectortype(t) + # linear algebra + @test isa(@constinferred(norm(t)), real(T)) + @test norm(t)^2 β‰ˆ dot(t, t) + Ξ± = rand(T) + @test norm(Ξ± * t) β‰ˆ abs(Ξ±) * norm(t) + @test norm(t + t, 2) β‰ˆ 2 * norm(t, 2) + @test norm(t + t, 1) β‰ˆ 2 * norm(t, 1) + @test norm(t + t, Inf) β‰ˆ 2 * norm(t, Inf) + p = 3 * rand(Float64) + @test norm(t + t, p) β‰ˆ 2 * norm(t, p) + @test norm(t) β‰ˆ norm(t') + + t2 = @constinferred rand!(similar(t)) + Ξ² = rand(T) + @test @constinferred(dot(Ξ² * t2, Ξ± * t)) β‰ˆ conj(Ξ²) * Ξ± * conj(dot(t, t2)) + @test dot(t2, t) β‰ˆ conj(dot(t, t2)) + @test dot(t2, t) β‰ˆ conj(dot(t2', t')) + @test dot(t2, t) β‰ˆ dot(t', t2') + + if all(a.i == a.j for a in blocksectors(W)) # can't reverse fusion for these + i1 = @constinferred(isomorphism(T, V1 βŠ— V2, V2 βŠ— V1)) + i2 = @constinferred(isomorphism(Vector{T}, V2 βŠ— V1, V1 βŠ— V2)) + @test i1 * i2 == @constinferred(id(T, V1 βŠ— V2)) + @test i2 * i1 == @constinferred(id(Vector{T}, V2 βŠ— V1)) + end + for v in (V1, V2, V3, V4, V5) + wl = @constinferred(isometry(T, (leftoneunit(v) βŠ• leftoneunit(v)) βŠ— v, v)) + wr = @constinferred(isometry(T, v βŠ— (rightoneunit(v) βŠ• rightoneunit(v)), v)) + for w in (wl, wr) + @test dim(w) == 2 * dim(v ← v) + @test w' * w == id(Vector{T}, v) + @test w * w' == (w * w')^2 + end + end + end + end + @timedtestset "Trivial space insertion and removal" begin + W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 + for T in (Float32, ComplexF64) + t = @constinferred rand(T, W) # fusion matters here + t2 = @constinferred insertleftunit(t, 5) # default errors + + @test t2 == @constinferred insertrightunit(t, 4) # default doesn't error bc i==N then + @test numind(t2) == numind(t) + 1 + @test space(t2) == insertleftunit(space(t), 5) + @test scalartype(t2) === T + @test t.data === t2.data + @test @constinferred(removeunit(t2, $(numind(t2) - 1))) == t # -1 required + + t3 = @constinferred insertleftunit(t, 5; copy=true) # same here + @test t3 == @constinferred insertrightunit(t, 4; copy=true) + @test t.data !== t3.data + for (c, b) in blocks(t) + @test b == block(t3, c) + end + @test @constinferred(removeunit(t3, $(numind(t3) - 1))) == t + t4 = @constinferred insertrightunit(t, 3; dual=true) + @test numin(t4) == numin(t) + 1 && numout(t4) == numout(t) + for (c, b) in blocks(t) + @test b == block(t4, c) + end + @test @constinferred(removeunit(t4, 4)) == t + t5 = @constinferred insertleftunit(t, 4; dual=true) + @test numin(t5) == numin(t) + 1 && numout(t5) == numout(t) + for (c, b) in blocks(t) + @test b == block(t5, c) + end + @test @constinferred(removeunit(t5, 4)) == t + end + end + # no basic linear algebra tests via conversion: no fusion tensor + @timedtestset "Tensor conversion" begin + W = V1 βŠ— V2 + t = @constinferred randn(W ← W) # fusion matters here + @test typeof(convert(TensorMap, t')) == typeof(t) + tc = complex(t) + @test convert(typeof(tc), t) == tc + @test typeof(convert(typeof(tc), t)) == typeof(tc) + @test typeof(convert(typeof(tc), t')) == typeof(tc) + @test Base.promote_typeof(t, tc) == typeof(tc) + @test Base.promote_typeof(tc, t) == typeof(tc + t) + end + # no permutations test via inner product invariance: NoBraiding + # no permutations test via conversion: NoBraiding and no fusion tensor + @timedtestset "Full trace: test self-consistency" begin + t = rand(ComplexF64, V1 βŠ— V2 ← V1 βŠ— V2) + s = @constinferred tr(t) + @test conj(s) β‰ˆ tr(t') + try # needed for module cases: certain transposes with module legs will result in different colorings + @planar s2 = t[a b; a b] # no twist needed bc permute avoided + @test s β‰ˆ s2 + catch e + @test isa(e, SectorMismatch) + end + + try # TODO?: skip module traces + @planar t3[a; b] := t[a c; b c] + @planar s3 = t3[a; a] # this contraction order gives zero for VIBMop1 and VIBMop2 because it traces out the module legs + @test s β‰ˆ s3 + catch e + @test isa(e, SectorMismatch) + end + end + @timedtestset "Partial trace: test self-consistency" begin + t = rand(ComplexF64, V3 βŠ— V4 βŠ— V5 ← V3 βŠ— V4 βŠ— V5) # rewritten to be compatible with module fusion + @planar t2[a; b] := t[c a d; c b d] + @planar t4[a b; c d] := t[e a b; e c d] + @planar t5[a; b] := t4[a c; b c] + @test t2 β‰ˆ t5 + end + # no trace test via conversion: NoBraiding and no fusion tensor + @timedtestset "Trace and contraction" begin #TODO: find some version of this that works for off-diagonal case + t1 = rand(ComplexF64, V3 βŠ— V4 βŠ— V5) + t2 = rand(ComplexF64, V3 βŠ— V4 βŠ— V5) + t3 = t1 βŠ— t2' + # if all(a.i != a.j for a in blocksectors(t3)) + # replace!(x -> rand(ComplexF64), t3.data) # otherwise full of zeros in off-diagonal case + # end + if all(a.i == a.j for a in blocksectors(t3)) + @planar ta[b; a] := conj(t2[x, a, y]) * t1[x, b, y] # works for diagonal case + @planar tb[a; b] := t3[x a y; x b y] + @test ta β‰ˆ tb + end + end + # no tensor contraction test via conversion: NoBraiding and no fusion tensor + # no index flipping tests: NoBraiding + @timedtestset "Multiplication of isometries: test properties" begin + W2 = V4 βŠ— V5 + W1 = W2 βŠ— (rightoneunit(V5) βŠ• rightoneunit(V5)) + W3 = (leftoneunit(V4) βŠ• leftoneunit(V4)) βŠ— W2 + for W in (W1, W3) + for T in (Float64, ComplexF64) + t1 = @constinferred randisometry(T, W, W2) + t2 = randisometry(T, W2 ← W2) + @test t1' * t1 β‰ˆ one(t2) + @test t2' * t2 β‰ˆ one(t2) + @test t2 * t2' β‰ˆ one(t2) + P = t1 * t1' + @test P * P β‰ˆ P + end + end + end + @timedtestset "Multiplication and inverse: test compatibility" begin + W1 = V1 βŠ— V2 + W2 = V3 βŠ— V4 βŠ— V5 + for T in (Float64, ComplexF64) + t1 = rand(T, W1, W1) + t2 = rand(T, W2 ← W2) + t = rand(T, W1, W2) + @test t1 * (t1 \ t) β‰ˆ t + @test (t / t2) * t2 β‰ˆ t + @test t1 \ one(t1) β‰ˆ inv(t1) + @test one(t1) / t1 β‰ˆ pinv(t1) + @test_throws SpaceMismatch inv(t) + @test_throws SpaceMismatch t2 \ t + @test_throws SpaceMismatch t / t1 + tp = pinv(t) * t + @test tp β‰ˆ tp * tp + end + end + # no multiplication and inverse test via conversion: NoBraiding and no fusion tensor + @timedtestset "diag/diagm" begin + W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 + t = randn(ComplexF64, W) + d = LinearAlgebra.diag(t) + D = LinearAlgebra.diagm(codomain(t), domain(t), d) + @test LinearAlgebra.isdiag(D) + @test LinearAlgebra.diag(D) == d + end + @timedtestset "Factorization" begin + WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' # old left permute resulted in this space + WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' # old right permute + WmodR = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # new fusion order for right + WmodL = V1 βŠ— V2 βŠ— V5' ← V3 βŠ— V4 # new fusion order for left + + isdiag = all(c.i == c.j for c in blocksectors(WmodR)) # this blocksectors call should always work + for T in (Float32, ComplexF64) + # Test both a normal tensor and an adjoint one. + # adjoint takes other space for shape of matrix in RQ(pos) + tsR = isdiag ? (rand(T, WR), rand(T, WL)') : (rand(T, WmodR), rand(T, WmodL)') # shape of matrices require different spaces for left/right + tsL = isdiag ? (rand(T, WL), rand(T, WR)') : (rand(T, WmodR), rand(T, WmodL)') + for t in tsR + @testset "rightorth with $alg" for alg in + (TK.RQ(), TK.RQpos(), TK.LQ(), + TK.LQpos(), + TK.Polar(), TK.SVD(), TK.SDD()) + L, Q = @constinferred rightorth(t; alg=alg) + QQd = Q * Q' + @test QQd β‰ˆ one(QQd) + @test L * Q β‰ˆ t + if alg isa Polar + @test isposdef(L) + @test domain(L) == codomain(L) == space(t, 1) βŠ— space(t, 2) + end + end + @testset "rightnull with $alg" for alg in (TK.LQ(), TK.SVD(), TK.SDD()) + M = @constinferred rightnull(t; alg=alg) + MMd = M * M' + @test MMd β‰ˆ one(MMd) + @test norm(t * M') < 100 * eps(norm(t)) + end + end + # adjoints take other space for shape of matrix in QL(pos) + for t in tsL + @testset "leftorth with $alg" for alg in + (TK.QR(), TK.QRpos(), TK.QL(), TK.QLpos(), + TK.Polar(), TK.SVD(), TK.SDD()) + # skip QL because the monomorphism condition is hard to satisfy for off-diagonal case + # have to skip Polar as well as all tests fail with modules + (alg isa QL || alg isa QLpos || alg isa Polar) && !isdiag && continue + Q, R = @constinferred leftorth(t; alg=alg) + QdQ = Q' * Q + @test QdQ β‰ˆ one(QdQ) + @test Q * R β‰ˆ t + if alg isa Polar + @test isposdef(R) # this fails with modules + @test domain(R) == codomain(R) == space(t, 4)' βŠ— space(t, 5)' # this as well + end + end + @testset "leftnull with $alg" for alg in + (TK.QR(), TK.SVD(), TK.SDD()) + # less rows than columns so either fails or no data in off-diagonal case + !isdiag && continue + N = @constinferred leftnull(t; alg=alg) + NdN = N' * N + @test NdN β‰ˆ one(NdN) + @test norm(N' * t) < 100 * eps(norm(t)) + end + @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) + U, S, V = @constinferred tsvd(t; alg=alg) + UdU = U' * U + @test UdU β‰ˆ one(UdU) + VVd = V * V' + @test VVd β‰ˆ one(VVd) + @test U * S * V β‰ˆ t + + s = LinearAlgebra.svdvals(t) + sβ€² = LinearAlgebra.diag(S) + for (c, b) in s + @test b β‰ˆ sβ€²[c] + end + end + @testset "cond and rank" begin + d1 = dim(codomain(t)) + d2 = dim(domain(t)) + @test rank(t) == min(d1, d2) + if isdiag # leftnull doesn't work for off-diagonal case + M = leftnull(t) + @test rank(M) == max(d1, d2) - min(d1, d2) + end + t2 = unitary(T, V1 βŠ— V2, V1 βŠ— V2) + @test cond(t2) β‰ˆ one(real(T)) + @test rank(t2) == dim(V1 βŠ— V2) + t3 = randn(T, V1 βŠ— V2, V1 βŠ— V2) + t3 = (t3 + t3') / 2 + vals = LinearAlgebra.eigvals(t3) + Ξ»max = maximum(s -> maximum(abs, s), values(vals)) + Ξ»min = minimum(s -> minimum(abs, s), values(vals)) + @test cond(t3) β‰ˆ Ξ»max / Ξ»min + end + end + # how useful is this test? everything just works regardless of the space + @testset "empty tensor" begin + t = randn(T, V1 βŠ— V2, zero(V1)) + @testset "leftorth with $alg" for alg in + (TK.QR(), TK.QRpos(), TK.QL(), TK.QLpos(), + TK.Polar(), TK.SVD(), TK.SDD()) + Q, R = @constinferred leftorth(t; alg=alg) + @test Q == t + @test dim(Q) == dim(R) == 0 + end + @testset "leftnull with $alg" for alg in (TK.QR(), TK.SVD(), TK.SDD()) + N = @constinferred leftnull(t; alg=alg) + @test N' * N β‰ˆ id(domain(N)) + @test N * N' β‰ˆ id(codomain(N)) + end + @testset "rightorth with $alg" for alg in + (TK.RQ(), TK.RQpos(), TK.LQ(), + TK.LQpos(), + TK.Polar(), TK.SVD(), TK.SDD()) + L, Q = @constinferred rightorth(copy(t'); alg=alg) + @test Q == t' + @test dim(Q) == dim(L) == 0 + end + @testset "rightnull with $alg" for alg in (TK.LQ(), TK.SVD(), TK.SDD()) + M = @constinferred rightnull(copy(t'); alg=alg) + @test M * M' β‰ˆ id(codomain(M)) + @test M' * M β‰ˆ id(domain(M)) + end + @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) + U, S, V = @constinferred tsvd(t; alg=alg) + @test U == t + @test dim(U) == dim(S) == dim(V) + end + @testset "cond and rank" begin + @test rank(t) == 0 + W2 = zero(V1) * zero(V2) + t2 = rand(W2, W2) + @test rank(t2) == 0 + @test cond(t2) == 0.0 + end + end + t = rand(T, V1 βŠ— V2 ← V1 βŠ— V2) + @testset "eig and isposdef" begin + D, V = eigen(t) + @test t * V β‰ˆ V * D + + d = LinearAlgebra.eigvals(t; sortby=nothing) + dβ€² = LinearAlgebra.diag(D) + for (c, b) in d + @test b β‰ˆ dβ€²[c] + end + + # Somehow moving these test before the previous one gives rise to errors + # with T=Float32 on x86 platforms. Is this an OpenBLAS issue? + VdV = V' * V + VdV = (VdV + VdV') / 2 + @test isposdef(VdV) + + @test !isposdef(t) # unlikely for non-hermitian map + t2 = (t + t') + D, V = eigen(t2) + VdV = V' * V + @test VdV β‰ˆ one(VdV) + DΜƒ, VΜƒ = @constinferred eigh(t2) + @test D β‰ˆ DΜƒ + @test V β‰ˆ VΜƒ + Ξ» = minimum(minimum(real(LinearAlgebra.diag(b))) + for (c, b) in blocks(D)) + @test cond(VΜƒ) β‰ˆ one(real(T)) + @test isposdef(t2) == isposdef(Ξ») + @test isposdef(t2 - Ξ» * one(t2) + 0.1 * one(t2)) + @test !isposdef(t2 - Ξ» * one(t2) - 0.1 * one(t2)) + end + end + end + @timedtestset "Tensor truncation" begin + for T in (Float32, ComplexF64) + # Test both a normal tensor and an adjoint one. + ts = (randn(T, V1 βŠ— V2, V3 βŠ— V4 βŠ— V5), randn(T, V4 βŠ— V5, V3 βŠ— V1 βŠ— V2)') # rewritten for modules + for p in (1, 2, 3, Inf) + for t in ts + Uβ‚€, Sβ‚€, Vβ‚€ = tsvd(t) + t = rmul!(t, 1 / norm(Sβ‚€, p)) + U, S, V, Ο΅ = @constinferred tsvd(t; trunc=truncerr(5e-1), p=p) + Uβ€², Sβ€², Vβ€², Ο΅β€² = tsvd(t; trunc=truncerr(nextfloat(Ο΅)), p=p) + @test (U, S, V, Ο΅) == (Uβ€², Sβ€², Vβ€², Ο΅β€²) + Uβ€², Sβ€², Vβ€², Ο΅β€² = tsvd(t; trunc=truncdim(ceil(Int, dim(domain(S)))), + p=p) + @test (U, S, V, Ο΅) == (Uβ€², Sβ€², Vβ€², Ο΅β€²) + Uβ€², Sβ€², Vβ€², Ο΅β€² = tsvd(t; trunc=truncspace(space(S, 1)), p=p) + @test (U, S, V, Ο΅) == (Uβ€², Sβ€², Vβ€², Ο΅β€²) + # results with truncationcutoff cannot be compared because they don't take degeneracy into account, and thus truncate differently + U, S, V, Ο΅ = tsvd(t; trunc=truncbelow(1 / dim(domain(Sβ‚€))), p=p) + Uβ€², Sβ€², Vβ€², Ο΅β€² = tsvd(t; trunc=truncspace(space(S, 1)), p=p) + @test (U, S, V, Ο΅) == (Uβ€², Sβ€², Vβ€², Ο΅β€²) + end + end + end + end + # no tensor functions tests: NoBraiding and no fusion tensor + @timedtestset "Sylvester equation" begin + for T in (Float32, ComplexF64) + tA = rand(T, V1 βŠ— V2, V1 βŠ— V2) # rewritten for modules + tB = rand(T, V4 βŠ— V5, V4 βŠ— V5) + tA = 3 // 2 * leftorth(tA; alg=TK.Polar())[1] + tB = 1 // 5 * leftorth(tB; alg=TK.Polar())[1] + tC = rand(T, V1 βŠ— V2, V4 βŠ— V5) + t = @constinferred sylvester(tA, tB, tC) + @test codomain(t) == V1 βŠ— V2 + @test domain(t) == V4 βŠ— V5 + @test norm(tA * t + t * tB + tC) < + (norm(tA) + norm(tB) + norm(tC)) * eps(real(T))^(2 / 3) + # no reshape test: NoBraiding and no fusion tensor + end + end + @timedtestset "Tensor product: test via norm preservation" begin + for T in (Float32, ComplexF64) + t1 = rand(T, V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2) + if all(a.i != a.j for a in blocksectors(t1)) + t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') + else + t2 = rand(T, V3' βŠ— V1, V4 βŠ— V5 βŠ— V2') # keep a non-trivial permutation in diagonal case + end + t = @constinferred (t1 βŠ— t2) + @test norm(t) β‰ˆ norm(t1) * norm(t2) + end + end + # no tensor product test via conversion: NoBraiding and no fusion tensor + @timedtestset "Tensor product: test via tensor contraction" begin # works for diagonal case + W = V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2 + isdiag = all(a.i == a.j for a in blocksectors(W)) + for T in (Float32, ComplexF64) + if !isdiag + t1 = rand(T, W) + t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') # same as previous test + @planar tβ€²[1 2 3 6 7 8; 4 5 9 10] := t1[1 2 3; 4 5] * t2[6 7 8; 9 10] + else + t1 = rand(T, V2 βŠ— V3, V1) + t2 = rand(T, V2, V1 βŠ— V3) + @planar tβ€²[1 2 4; 3 5 6] := t1[1 2; 3] * t2[4; 5 6] + end + t = @constinferred (t1 βŠ— t2) + @test t β‰ˆ tβ€² + end + end + end +end @testset "$Istr ($i, $j) left and right units" for i in 1:r, j in 1:r Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) From 38001e16e37dcdf2b79f69b1ff3cbcec32c31c38 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 12 Aug 2025 16:21:41 +0200 Subject: [PATCH 155/206] almost finish up tensor tests --- test/test_A4.jl | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 73ffe54..a56d4e5 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -830,6 +830,10 @@ V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) end end +# no conversion tests because no fusion tensor +# no permute tests: NoBraiding() + +#TODO? test only for i>j? @timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), Vect[I](one(I(i, i, 1)) => 2), @@ -872,18 +876,14 @@ end Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) ) - Vcol = i != j ? (VC, VD, VM1, VM2, VMop1, VMop2) : (VC,) # avoid duplicate runs + Vcol = i != j ? (VM1, VM2, VMop1, VMop2) : (VC,) # avoid duplicate runs for V in Vcol V1, V2, V3, V4, V5 = V @timedtestset "Basic tensor properties" begin - W = V1 βŠ— V2 βŠ— V3 βŠ— V4 βŠ— V5 # fusion matters + W = i == j ? V1 βŠ— V2 βŠ— V3 βŠ— V4 βŠ— V5 : V3 βŠ— V4 βŠ— V5 # fusion matters for T in (Int, Float32, Float64, ComplexF32, ComplexF64, BigFloat) - t = @constinferred zeros(T, W) - if isempty(t.data) # non-diagonal sector fuses poorly - W = V3 βŠ— V4 βŠ— V5 - t = @constinferred zeros(T, W) # also empty because M isn't diagonal so can't fuse to empty space - end + t = @constinferred zeros(T, W) # empty for i != j b/c blocks are module-graded @test @constinferred(hash(t)) == hash(deepcopy(t)) @test scalartype(t) == T @test norm(t) == 0 @@ -905,6 +905,7 @@ end end end end + @timedtestset "Tensor Dict conversion" begin W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # rewritten to be compatible with module fusion for T in (Int, Float32, ComplexF64) @@ -913,7 +914,7 @@ end @test t == convert(TensorMap, d) end end - # no tensor array conversion tests: no fusion tensor + @timedtestset "Basic linear algebra" begin W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 for T in (Float32, ComplexF64) @@ -970,6 +971,7 @@ end end end end + @timedtestset "Trivial space insertion and removal" begin W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 for T in (Float32, ComplexF64) @@ -1004,7 +1006,7 @@ end @test @constinferred(removeunit(t5, 4)) == t end end - # no basic linear algebra tests via conversion: no fusion tensor + @timedtestset "Tensor conversion" begin W = V1 βŠ— V2 t = @constinferred randn(W ← W) # fusion matters here @@ -1016,8 +1018,7 @@ end @test Base.promote_typeof(t, tc) == typeof(tc) @test Base.promote_typeof(tc, t) == typeof(tc + t) end - # no permutations test via inner product invariance: NoBraiding - # no permutations test via conversion: NoBraiding and no fusion tensor + @timedtestset "Full trace: test self-consistency" begin t = rand(ComplexF64, V1 βŠ— V2 ← V1 βŠ— V2) s = @constinferred tr(t) @@ -1037,6 +1038,7 @@ end @test isa(e, SectorMismatch) end end + @timedtestset "Partial trace: test self-consistency" begin t = rand(ComplexF64, V3 βŠ— V4 βŠ— V5 ← V3 βŠ— V4 βŠ— V5) # rewritten to be compatible with module fusion @planar t2[a; b] := t[c a d; c b d] @@ -1044,7 +1046,7 @@ end @planar t5[a; b] := t4[a c; b c] @test t2 β‰ˆ t5 end - # no trace test via conversion: NoBraiding and no fusion tensor + @timedtestset "Trace and contraction" begin #TODO: find some version of this that works for off-diagonal case t1 = rand(ComplexF64, V3 βŠ— V4 βŠ— V5) t2 = rand(ComplexF64, V3 βŠ— V4 βŠ— V5) @@ -1058,8 +1060,7 @@ end @test ta β‰ˆ tb end end - # no tensor contraction test via conversion: NoBraiding and no fusion tensor - # no index flipping tests: NoBraiding + @timedtestset "Multiplication of isometries: test properties" begin W2 = V4 βŠ— V5 W1 = W2 βŠ— (rightoneunit(V5) βŠ• rightoneunit(V5)) @@ -1076,6 +1077,7 @@ end end end end + @timedtestset "Multiplication and inverse: test compatibility" begin W1 = V1 βŠ— V2 W2 = V3 βŠ— V4 βŠ— V5 @@ -1094,7 +1096,7 @@ end @test tp β‰ˆ tp * tp end end - # no multiplication and inverse test via conversion: NoBraiding and no fusion tensor + @timedtestset "diag/diagm" begin W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 t = randn(ComplexF64, W) @@ -1103,6 +1105,7 @@ end @test LinearAlgebra.isdiag(D) @test LinearAlgebra.diag(D) == d end + @timedtestset "Factorization" begin WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' # old left permute resulted in this space WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' # old right permute @@ -1179,10 +1182,10 @@ end @testset "cond and rank" begin d1 = dim(codomain(t)) d2 = dim(domain(t)) - @test rank(t) == min(d1, d2) + @test rank(t) β‰ˆ min(d1, d2) # reduced to approx if isdiag # leftnull doesn't work for off-diagonal case M = leftnull(t) - @test rank(M) == max(d1, d2) - min(d1, d2) + @test rank(M) β‰ˆ max(d1, d2) - min(d1, d2) # reduced to approx end t2 = unitary(T, V1 βŠ— V2, V1 βŠ— V2) @test cond(t2) β‰ˆ one(real(T)) @@ -1271,6 +1274,7 @@ end end end end + @timedtestset "Tensor truncation" begin for T in (Float32, ComplexF64) # Test both a normal tensor and an adjoint one. @@ -1295,7 +1299,7 @@ end end end end - # no tensor functions tests: NoBraiding and no fusion tensor + @timedtestset "Sylvester equation" begin for T in (Float32, ComplexF64) tA = rand(T, V1 βŠ— V2, V1 βŠ— V2) # rewritten for modules @@ -1311,6 +1315,7 @@ end # no reshape test: NoBraiding and no fusion tensor end end + @timedtestset "Tensor product: test via norm preservation" begin for T in (Float32, ComplexF64) t1 = rand(T, V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2) @@ -1323,8 +1328,8 @@ end @test norm(t) β‰ˆ norm(t1) * norm(t2) end end - # no tensor product test via conversion: NoBraiding and no fusion tensor - @timedtestset "Tensor product: test via tensor contraction" begin # works for diagonal case + + @timedtestset "Tensor product: test via tensor contraction" begin W = V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2 isdiag = all(a.i == a.j for a in blocksectors(W)) for T in (Float32, ComplexF64) From b4b838ec21b6b6c8f04be517fa173dab7940a373 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 13 Aug 2025 18:04:57 +0200 Subject: [PATCH 156/206] specify modules for some functions --- src/bimodulesector.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index e190a52..c3fd2fc 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -336,7 +336,7 @@ function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) end # oneunit for spaces whose elements all belong to the same sector -function rightoneunit(S::GradedSpace{<:BimoduleSector}) +function TensorKit.rightoneunit(S::GradedSpace{<:BimoduleSector}) allequal(a.j for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same rightone")) @@ -344,12 +344,12 @@ function rightoneunit(S::GradedSpace{<:BimoduleSector}) return spacetype(S)(sector => 1) end -function rightoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +function TensorKit.rightoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) @assert !isempty(S) "Cannot determine type of empty space" return SumSpace(rightoneunit(first(S.spaces))) end -function leftoneunit(S::GradedSpace{<:BimoduleSector}) +function TensorKit.leftoneunit(S::GradedSpace{<:BimoduleSector}) allequal(a.i for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same leftone")) @@ -357,7 +357,7 @@ function leftoneunit(S::GradedSpace{<:BimoduleSector}) return spacetype(S)(sector => 1) end -function leftoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +function TensorKit.leftoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) @assert !isempty(S) "Cannot determine type of empty space" return SumSpace(leftoneunit(first(S.spaces))) end @@ -412,6 +412,6 @@ function TensorKit.FusionTree(uncoupled::Tuple{<:I,Vararg{I}}) where {I<:Bimodul end # this one might also be overkill, since `FusionTreeIterator`s don't check whether the fusion is allowed -function fusiontrees(uncoupled::Tuple{I,Vararg{I}}) where {I<:BimoduleSector} +function TensorKit.fusiontrees(uncoupled::Tuple{I,Vararg{I}}) where {I<:BimoduleSector} return throw(ArgumentError("coupled sector must be provided for $I fusion")) end \ No newline at end of file From a7d13b3791cbbcd40c4c3d18bfc6fc8253357988 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 13 Aug 2025 18:06:35 +0200 Subject: [PATCH 157/206] don't use rounddim because it's messy with SVD with truncdim --- src/bimodulesector.jl | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index c3fd2fc..011c4e3 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -293,18 +293,9 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where end end -function rounddim(c::I) where {I<:BimoduleSector} - _dim = dim(c) - if _dim β‰ˆ floor(_dim) - return floor(_dim) - else - return _dim - end -end - function TensorKit.dim(V::GradedSpace{<:BimoduleSector}) T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) - return reduce(+, dim(V, c) * rounddim(c) for c in sectors(V); init=zero(T)) + return reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(T)) end Base.zero(S::Type{<:GradedSpace{<:BimoduleSector}}) = S() From dca461144672e8acd1aa227057e6afc71a9ee4b6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 13 Aug 2025 18:28:44 +0200 Subject: [PATCH 158/206] shorten tensor tests, fix and/or identify bugs --- test/test_A4.jl | 103 ++++++++++++------------------------------------ 1 file changed, 26 insertions(+), 77 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index a56d4e5..3273cd5 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -833,7 +833,6 @@ end # no conversion tests because no fusion tensor # no permute tests: NoBraiding() -#TODO? test only for i>j? @timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), Vect[I](one(I(i, i, 1)) => 2), @@ -841,42 +840,22 @@ end Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) ) - VD = (Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), - Vect[I](one(I(j, j, 1)) => 2), - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), - Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 3) - ) - VM1 = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), - Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), - Vect[I](rand_object(I, i, j) => 4), - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 3) + VM1 = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works + Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), # important that V4 is module-graded + Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + Vect[I](rand_object(I, i, j) => 1), + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) ) - VM2 = (Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), + VM2 = (Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), # second set where module is V1 here Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), - Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), - Vect[I](rand_object(I, i, j) => 4), - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 3) - ) - - VMop1 = (Vect[I]((j, i, label) => 1 for label in 1:MTK._numlabels(I, j, i)), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), - Vect[I](rand_object(I, j, i) => 4), - Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) - ) - - VMop2 = (Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), - Vect[I]((j, i, label) => 1 for label in 1:MTK._numlabels(I, j, i)), - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), - Vect[I](rand_object(I, j, i) => 4), - Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) + Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + Vect[I](rand_object(I, i, j) => 2), + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) ) - Vcol = i != j ? (VM1, VM2, VMop1, VMop2) : (VC,) # avoid duplicate runs + Vcol = i != j ? (VM1, VM2) : (VC,) # avoid duplicate runs for V in Vcol V1, V2, V3, V4, V5 = V @@ -1089,7 +1068,7 @@ end @test (t / t2) * t2 β‰ˆ t @test t1 \ one(t1) β‰ˆ inv(t1) @test one(t1) / t1 β‰ˆ pinv(t1) - @test_throws SpaceMismatch inv(t) + # @test_throws SpaceMismatch inv(t) # can coincidently fail b/c of rand_object @test_throws SpaceMismatch t2 \ t @test_throws SpaceMismatch t / t1 tp = pinv(t) * t @@ -1106,6 +1085,11 @@ end @test LinearAlgebra.diag(D) == d end + # some fail for (2, 2), (3, 3), (6, 6) + # rightorth RQ(pos) and Polar (fail) for 2nd space + # leftorth with QL(pos) and Polar for 1st space + # leftnull QR for 1st space + # cond and rank leftnull for 1st space @timedtestset "Factorization" begin WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' # old left permute resulted in this space WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' # old right permute @@ -1123,6 +1107,7 @@ end (TK.RQ(), TK.RQpos(), TK.LQ(), TK.LQpos(), TK.Polar(), TK.SVD(), TK.SDD()) + (alg isa RQ || alg isa RQpos || alg isa Polar) && !isdiag && continue L, Q = @constinferred rightorth(t; alg=alg) QQd = Q * Q' @test QQd β‰ˆ one(QQd) @@ -1182,14 +1167,14 @@ end @testset "cond and rank" begin d1 = dim(codomain(t)) d2 = dim(domain(t)) - @test rank(t) β‰ˆ min(d1, d2) # reduced to approx + # @test rank(t) β‰ˆ min(d1, d2) # reduced to approx due to numerical F-symbols FIXME: fails sometimes for modules if isdiag # leftnull doesn't work for off-diagonal case M = leftnull(t) @test rank(M) β‰ˆ max(d1, d2) - min(d1, d2) # reduced to approx end t2 = unitary(T, V1 βŠ— V2, V1 βŠ— V2) @test cond(t2) β‰ˆ one(real(T)) - @test rank(t2) == dim(V1 βŠ— V2) + @test rank(t2) β‰ˆ dim(V1 βŠ— V2) # reduced to approx t3 = randn(T, V1 βŠ— V2, V1 βŠ— V2) t3 = (t3 + t3') / 2 vals = LinearAlgebra.eigvals(t3) @@ -1330,13 +1315,16 @@ end end @timedtestset "Tensor product: test via tensor contraction" begin - W = V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2 + # W = V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2 + W = V4 ← V1 βŠ— V2 # less costly isdiag = all(a.i == a.j for a in blocksectors(W)) for T in (Float32, ComplexF64) if !isdiag t1 = rand(T, W) - t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') # same as previous test - @planar tβ€²[1 2 3 6 7 8; 4 5 9 10] := t1[1 2 3; 4 5] * t2[6 7 8; 9 10] + t2 = rand(T, V4' ← V2' βŠ— V1') + # t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') # same as previous test + # @planar tβ€²[1 2 3 6 7 8; 4 5 9 10] := t1[1 2 3; 4 5] * t2[6 7 8; 9 10] + @planar tβ€²[1 4; 2 3 5 6] := t1[1; 2 3] * t2[4; 5 6] else t1 = rand(T, V2 βŠ— V3, V1) t2 = rand(T, V2, V1 βŠ— V3) @@ -1347,43 +1335,4 @@ end end end end -end - -@testset "$Istr ($i, $j) left and right units" for i in 1:r, j in 1:r - Cij_obs = I.(i, j, MTK._get_dual_cache(I)[2][i, j]) - - s = rand(Cij_obs) - sp = Vect[I](s => 1) - W = sp ← sp - for T in (Float32, ComplexF64) - t = @constinferred rand(T, W) - - for a in 1:2 - tl = @constinferred insertleftunit(t, Val(a)) - @test numind(tl) == numind(t) + 1 - @test space(tl) == insertleftunit(space(t), a) - @test scalartype(tl) === T - @test t.data === tl.data - @test @constinferred(removeunit(tl, $(a))) == t - - tr = @constinferred insertrightunit(t, Val(a)) - @test numind(tr) == numind(t) + 1 - @test space(tr) == insertrightunit(space(t), a) - @test scalartype(tr) === T - @test t.data === tr.data - @test @constinferred(removeunit(tr, $(a + 1))) == t - end - - @test_throws ErrorException insertleftunit(t) # default should error here - @test insertrightunit(t) isa TensorMap - @test_throws ErrorException insertleftunit(t, numind(t) + 1) # same as default - @test_throws ErrorException insertrightunit(t, numind(t) + 1) # not same as default - - t2 = @constinferred insertrightunit(t; copy=true) - @test t.data !== t2.data - for (c, b) in blocks(t) - @test b == block(t2, c) - end - @test @constinferred(removeunit(t2, $(numind(t2)))) == t - end -end +end \ No newline at end of file From d274967941ef6f8f67e796d20bab06bc941add0a Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 13 Aug 2025 18:29:17 +0200 Subject: [PATCH 159/206] remove export `left/rightoneunit` --- src/MultiTensorKit.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 9f59e4b..d54caa6 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -1,7 +1,6 @@ module MultiTensorKit export BimoduleSector, A4Object -export leftoneunit, rightoneunit using DelimitedFiles using Artifacts From 0b4f890b47a2484f29d0fd62b2780f6e176d807e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 14 Aug 2025 10:30:30 +0200 Subject: [PATCH 160/206] `isone` for `BimoduleSector`s --- src/bimodulesector.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 011c4e3..8bcefe3 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -182,6 +182,8 @@ function Base.one(a::BimoduleSector) return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end +Base.isone(a::BimoduleSector) = leftone(a) == a == rightone(a) + function Base.one(::Type{<:BimoduleSector}) throw(ArgumentError("one of Type BimoduleSector doesn't exist")) end From ffbd4e0dd2cd48bbee97477eead4ea1393007b89 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 14 Aug 2025 10:32:27 +0200 Subject: [PATCH 161/206] make `isone` great again in `blocksectors` --- src/bimodulesector.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 8bcefe3..a9c4e4c 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -284,10 +284,10 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where for i in 1:size(A4Object)) # have to return all units b/c no info on W in this case elseif N₁ == 0 @assert Nβ‚‚ != 0 "one of Type A4Object doesn't exist" - return filter!(c -> c == leftone(c) == rightone(c), collect(blocksectors(dom))) + return filter!(isone, collect(blocksectors(dom))) elseif Nβ‚‚ == 0 @assert N₁ != 0 "one of Type A4Object doesn't exist" - return filter!(c -> c == leftone(c) == rightone(c), collect(blocksectors(codom))) + return filter!(isone, collect(blocksectors(codom))) elseif Nβ‚‚ <= N₁ # keep intersection return filter!(c -> hasblock(codom, c), collect(blocksectors(dom))) else From 000a976e1e973cc437fa3c2b808fc0f670e2faa7 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 14 Aug 2025 10:34:51 +0200 Subject: [PATCH 162/206] test for `isone` --- test/test_A4.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_A4.jl b/test/test_A4.jl index 3273cd5..512a035 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -67,6 +67,8 @@ end @test eval(Meta.parse(sprint(show, m))) == m @test @constinferred(hash(m)) == hash(deepcopy(m)) + @test isone(m) == false + @test isone(mop) == false @test (isone(@constinferred(leftone(m))) && isone(@constinferred(rightone(m)))) @test one(c) == leftone(m) == rightone(mop) @test one(d) == rightone(m) == leftone(mop) From 9f953d65fb361042eac6a853390d102ce575f420 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 18 Aug 2025 16:16:01 +0200 Subject: [PATCH 163/206] tensorkitsectors advanced compat --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 640d3b2..3419abc 100644 --- a/Project.toml +++ b/Project.toml @@ -18,7 +18,7 @@ BlockTensorKit = "0.1.10" DelimitedFiles = "1.9" SafeTestsets = "0.1" TensorKit = "0.14.9" -TensorKitSectors = "0.1.7" +TensorKitSectors = "0.1.7, 0.2" Test = "1.10" TestExtras = "0.3" TupleTools = "1.1" From 0be6bad583110f47a28aec3cade4f8b0cee4c901 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 22 Aug 2025 12:53:53 +0200 Subject: [PATCH 164/206] custom spaces for factorization tests for more compatible block sizes --- test/test_A4.jl | 402 ++++++++++++++++++++++++++---------------------- 1 file changed, 214 insertions(+), 188 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 512a035..1ad38b7 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -836,30 +836,34 @@ end # no permute tests: NoBraiding() @timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r + #TODO: refactor isdiag check + VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](one(I(i, i, 1)) => 2), - Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) - ) + Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? + Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) + ) + + VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects - VM1 = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works - Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), # important that V4 is module-graded + VM1 = (Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works + Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - Vect[I](rand_object(I, i, j) => 1), + VM, # important that V4 is module-graded Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) ) - VM2 = (Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), # second set where module is V1 here - Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), + VM2 = (Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here + Vect[I](one(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - Vect[I](rand_object(I, i, j) => 2), + VM, Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) ) Vcol = i != j ? (VM1, VM2) : (VC,) # avoid duplicate runs - for V in Vcol + for V in Vcol # TODO: add enumerate to keep track of potential erroring space V1, V2, V3, V4, V5 = V @timedtestset "Basic tensor properties" begin W = i == j ? V1 βŠ— V2 βŠ— V3 βŠ— V4 βŠ— V5 : V3 βŠ— V4 βŠ— V5 # fusion matters @@ -1087,181 +1091,6 @@ end @test LinearAlgebra.diag(D) == d end - # some fail for (2, 2), (3, 3), (6, 6) - # rightorth RQ(pos) and Polar (fail) for 2nd space - # leftorth with QL(pos) and Polar for 1st space - # leftnull QR for 1st space - # cond and rank leftnull for 1st space - @timedtestset "Factorization" begin - WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' # old left permute resulted in this space - WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' # old right permute - WmodR = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # new fusion order for right - WmodL = V1 βŠ— V2 βŠ— V5' ← V3 βŠ— V4 # new fusion order for left - - isdiag = all(c.i == c.j for c in blocksectors(WmodR)) # this blocksectors call should always work - for T in (Float32, ComplexF64) - # Test both a normal tensor and an adjoint one. - # adjoint takes other space for shape of matrix in RQ(pos) - tsR = isdiag ? (rand(T, WR), rand(T, WL)') : (rand(T, WmodR), rand(T, WmodL)') # shape of matrices require different spaces for left/right - tsL = isdiag ? (rand(T, WL), rand(T, WR)') : (rand(T, WmodR), rand(T, WmodL)') - for t in tsR - @testset "rightorth with $alg" for alg in - (TK.RQ(), TK.RQpos(), TK.LQ(), - TK.LQpos(), - TK.Polar(), TK.SVD(), TK.SDD()) - (alg isa RQ || alg isa RQpos || alg isa Polar) && !isdiag && continue - L, Q = @constinferred rightorth(t; alg=alg) - QQd = Q * Q' - @test QQd β‰ˆ one(QQd) - @test L * Q β‰ˆ t - if alg isa Polar - @test isposdef(L) - @test domain(L) == codomain(L) == space(t, 1) βŠ— space(t, 2) - end - end - @testset "rightnull with $alg" for alg in (TK.LQ(), TK.SVD(), TK.SDD()) - M = @constinferred rightnull(t; alg=alg) - MMd = M * M' - @test MMd β‰ˆ one(MMd) - @test norm(t * M') < 100 * eps(norm(t)) - end - end - # adjoints take other space for shape of matrix in QL(pos) - for t in tsL - @testset "leftorth with $alg" for alg in - (TK.QR(), TK.QRpos(), TK.QL(), TK.QLpos(), - TK.Polar(), TK.SVD(), TK.SDD()) - # skip QL because the monomorphism condition is hard to satisfy for off-diagonal case - # have to skip Polar as well as all tests fail with modules - (alg isa QL || alg isa QLpos || alg isa Polar) && !isdiag && continue - Q, R = @constinferred leftorth(t; alg=alg) - QdQ = Q' * Q - @test QdQ β‰ˆ one(QdQ) - @test Q * R β‰ˆ t - if alg isa Polar - @test isposdef(R) # this fails with modules - @test domain(R) == codomain(R) == space(t, 4)' βŠ— space(t, 5)' # this as well - end - end - @testset "leftnull with $alg" for alg in - (TK.QR(), TK.SVD(), TK.SDD()) - # less rows than columns so either fails or no data in off-diagonal case - !isdiag && continue - N = @constinferred leftnull(t; alg=alg) - NdN = N' * N - @test NdN β‰ˆ one(NdN) - @test norm(N' * t) < 100 * eps(norm(t)) - end - @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) - U, S, V = @constinferred tsvd(t; alg=alg) - UdU = U' * U - @test UdU β‰ˆ one(UdU) - VVd = V * V' - @test VVd β‰ˆ one(VVd) - @test U * S * V β‰ˆ t - - s = LinearAlgebra.svdvals(t) - sβ€² = LinearAlgebra.diag(S) - for (c, b) in s - @test b β‰ˆ sβ€²[c] - end - end - @testset "cond and rank" begin - d1 = dim(codomain(t)) - d2 = dim(domain(t)) - # @test rank(t) β‰ˆ min(d1, d2) # reduced to approx due to numerical F-symbols FIXME: fails sometimes for modules - if isdiag # leftnull doesn't work for off-diagonal case - M = leftnull(t) - @test rank(M) β‰ˆ max(d1, d2) - min(d1, d2) # reduced to approx - end - t2 = unitary(T, V1 βŠ— V2, V1 βŠ— V2) - @test cond(t2) β‰ˆ one(real(T)) - @test rank(t2) β‰ˆ dim(V1 βŠ— V2) # reduced to approx - t3 = randn(T, V1 βŠ— V2, V1 βŠ— V2) - t3 = (t3 + t3') / 2 - vals = LinearAlgebra.eigvals(t3) - Ξ»max = maximum(s -> maximum(abs, s), values(vals)) - Ξ»min = minimum(s -> minimum(abs, s), values(vals)) - @test cond(t3) β‰ˆ Ξ»max / Ξ»min - end - end - - # how useful is this test? everything just works regardless of the space - @testset "empty tensor" begin - t = randn(T, V1 βŠ— V2, zero(V1)) - @testset "leftorth with $alg" for alg in - (TK.QR(), TK.QRpos(), TK.QL(), TK.QLpos(), - TK.Polar(), TK.SVD(), TK.SDD()) - Q, R = @constinferred leftorth(t; alg=alg) - @test Q == t - @test dim(Q) == dim(R) == 0 - end - @testset "leftnull with $alg" for alg in (TK.QR(), TK.SVD(), TK.SDD()) - N = @constinferred leftnull(t; alg=alg) - @test N' * N β‰ˆ id(domain(N)) - @test N * N' β‰ˆ id(codomain(N)) - end - @testset "rightorth with $alg" for alg in - (TK.RQ(), TK.RQpos(), TK.LQ(), - TK.LQpos(), - TK.Polar(), TK.SVD(), TK.SDD()) - L, Q = @constinferred rightorth(copy(t'); alg=alg) - @test Q == t' - @test dim(Q) == dim(L) == 0 - end - @testset "rightnull with $alg" for alg in (TK.LQ(), TK.SVD(), TK.SDD()) - M = @constinferred rightnull(copy(t'); alg=alg) - @test M * M' β‰ˆ id(codomain(M)) - @test M' * M β‰ˆ id(domain(M)) - end - @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) - U, S, V = @constinferred tsvd(t; alg=alg) - @test U == t - @test dim(U) == dim(S) == dim(V) - end - @testset "cond and rank" begin - @test rank(t) == 0 - W2 = zero(V1) * zero(V2) - t2 = rand(W2, W2) - @test rank(t2) == 0 - @test cond(t2) == 0.0 - end - end - t = rand(T, V1 βŠ— V2 ← V1 βŠ— V2) - @testset "eig and isposdef" begin - D, V = eigen(t) - @test t * V β‰ˆ V * D - - d = LinearAlgebra.eigvals(t; sortby=nothing) - dβ€² = LinearAlgebra.diag(D) - for (c, b) in d - @test b β‰ˆ dβ€²[c] - end - - # Somehow moving these test before the previous one gives rise to errors - # with T=Float32 on x86 platforms. Is this an OpenBLAS issue? - VdV = V' * V - VdV = (VdV + VdV') / 2 - @test isposdef(VdV) - - @test !isposdef(t) # unlikely for non-hermitian map - t2 = (t + t') - D, V = eigen(t2) - VdV = V' * V - @test VdV β‰ˆ one(VdV) - DΜƒ, VΜƒ = @constinferred eigh(t2) - @test D β‰ˆ DΜƒ - @test V β‰ˆ VΜƒ - Ξ» = minimum(minimum(real(LinearAlgebra.diag(b))) - for (c, b) in blocks(D)) - @test cond(VΜƒ) β‰ˆ one(real(T)) - @test isposdef(t2) == isposdef(Ξ») - @test isposdef(t2 - Ξ» * one(t2) + 0.1 * one(t2)) - @test !isposdef(t2 - Ξ» * one(t2) - 0.1 * one(t2)) - end - end - end - @timedtestset "Tensor truncation" begin for T in (Float32, ComplexF64) # Test both a normal tensor and an adjoint one. @@ -1303,7 +1132,7 @@ end end end - @timedtestset "Tensor product: test via norm preservation" begin + @timedtestset "Tensor product: test via norm preservation" begin # OOMs over here with full spaces for T in (Float32, ComplexF64) t1 = rand(T, V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2) if all(a.i != a.j for a in blocksectors(t1)) @@ -1337,4 +1166,201 @@ end end end end + + # some fail for (2, 2), (3, 3), (6, 6) + # rightorth RQ(pos) and Polar (fail) for 2nd space + # leftorth with QL(pos) and Polar for 1st space + # leftnull QR for 1st space + # cond and rank leftnull for 1st space + + # factorization tests require equal objects in blocksectors of domain and codomain, so just put them all + VC_all = fill(Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), 5) + + VM1_all = (Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, + Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, + Vect[I](one(I(j, j, 1)) => 1, rand_object(I, j, j) => 2) + ) + + VM2_all = (VM, + Vect[I](one(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), + Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, + Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 2) + ) + + fact_Vs = (i != j) ? (VM1_all, VM2_all) : (VC_all,) + + @timedtestset "Factorization" for V in fact_Vs + V1, V2, V3, V4, V5 = V + WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' # old left permute resulted in this space + WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' # old right permute + WmodR = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # new fusion order for right + WmodL = V1 βŠ— V2 βŠ— V5' ← V3 βŠ— V4 # new fusion order for left + + isdiag = all(c.i == c.j for c in blocksectors(WmodR)) # this blocksectors call should always work #TODO: can't this just be i == j? + for T in (Float32, ComplexF64) + # Test both a normal tensor and an adjoint one. + # adjoint takes other space for shape of matrix in RQ(pos) + tsR = isdiag ? (rand(T, WR), rand(T, WL)') : (rand(T, WmodR), rand(T, WmodL)') # shape of matrices require different spaces for left/right + tsL = isdiag ? (rand(T, WL), rand(T, WR)') : (rand(T, WmodR), rand(T, WmodL)') + for t in tsR + @testset "rightorth with $alg" for alg in + (TK.RQ(), TK.RQpos(), TK.LQ(), + TK.LQpos(), + TK.Polar(), TK.SVD(), TK.SDD()) + (alg isa RQ || alg isa RQpos || alg isa Polar) && !isdiag && continue + L, Q = @constinferred rightorth(t; alg=alg) + QQd = Q * Q' + @test QQd β‰ˆ one(QQd) + @test L * Q β‰ˆ t + if alg isa Polar + @test isposdef(L) + @test domain(L) == codomain(L) == space(t, 1) βŠ— space(t, 2) + end + end + @testset "rightnull with $alg" for alg in (TK.LQ(), TK.SVD(), TK.SDD()) + M = @constinferred rightnull(t; alg=alg) + MMd = M * M' + @test MMd β‰ˆ one(MMd) + @test norm(t * M') < 100 * eps(norm(t)) + end + end + # adjoints take other space for shape of matrix in QL(pos) + for t in tsL + @testset "leftorth with $alg" for alg in + (TK.QR(), TK.QRpos(), TK.QL(), TK.QLpos(), + TK.Polar(), TK.SVD(), TK.SDD()) + # skip QL because the monomorphism condition is hard to satisfy for off-diagonal case + # have to skip Polar as well as all tests fail with modules + (alg isa QL || alg isa QLpos || alg isa Polar) && !isdiag && continue + Q, R = @constinferred leftorth(t; alg=alg) + QdQ = Q' * Q + @test QdQ β‰ˆ one(QdQ) + @test Q * R β‰ˆ t + if alg isa Polar + @test isposdef(R) # this fails with modules + @test domain(R) == codomain(R) == space(t, 4)' βŠ— space(t, 5)' # this as well + end + end + @testset "leftnull with $alg" for alg in + (TK.QR(), TK.SVD(), TK.SDD()) + # less rows than columns so either fails or no data in off-diagonal case + !isdiag && continue + N = @constinferred leftnull(t; alg=alg) + NdN = N' * N + @test NdN β‰ˆ one(NdN) + @test norm(N' * t) < 100 * eps(norm(t)) + end + @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) + U, S, V = @constinferred tsvd(t; alg=alg) + UdU = U' * U + @test UdU β‰ˆ one(UdU) + VVd = V * V' + @test VVd β‰ˆ one(VVd) + @test U * S * V β‰ˆ t + + s = LinearAlgebra.svdvals(t) + sβ€² = LinearAlgebra.diag(S) + for (c, b) in s + @test b β‰ˆ sβ€²[c] + end + end + # cond and rank tests were here + @testset "cond and rank" begin + d1 = dim(codomain(t)) + d2 = dim(domain(t)) + @test rank(t) β‰ˆ min(d1, d2) # reduced to approx + if isdiag # leftnull doesn't work for off-diagonal case + M = leftnull(t) + @test rank(M) β‰ˆ max(d1, d2) - min(d1, d2) # reduced to approx + end + t2 = unitary(T, V1 βŠ— V2, V1 βŠ— V2) + @test cond(t2) β‰ˆ one(real(T)) + @test rank(t2) β‰ˆ dim(V1 βŠ— V2) # reduced to approx + t3 = randn(T, V1 βŠ— V2, V1 βŠ— V2) + t3 = (t3 + t3') / 2 + vals = LinearAlgebra.eigvals(t3) + Ξ»max = maximum(s -> maximum(abs, s), values(vals)) + Ξ»min = minimum(s -> minimum(abs, s), values(vals)) + @test cond(t3) β‰ˆ Ξ»max / Ξ»min + end + end + + # how useful is this test? everything just works regardless of the space + @testset "empty tensor" begin + t = randn(T, V1 βŠ— V2, zero(V1)) + @testset "leftorth with $alg" for alg in + (TK.QR(), TK.QRpos(), TK.QL(), TK.QLpos(), + TK.Polar(), TK.SVD(), TK.SDD()) + Q, R = @constinferred leftorth(t; alg=alg) + @test Q == t + @test dim(Q) == dim(R) == 0 + end + @testset "leftnull with $alg" for alg in (TK.QR(), TK.SVD(), TK.SDD()) + N = @constinferred leftnull(t; alg=alg) + @test N' * N β‰ˆ id(domain(N)) + @test N * N' β‰ˆ id(codomain(N)) + end + @testset "rightorth with $alg" for alg in + (TK.RQ(), TK.RQpos(), TK.LQ(), + TK.LQpos(), + TK.Polar(), TK.SVD(), TK.SDD()) + L, Q = @constinferred rightorth(copy(t'); alg=alg) + @test Q == t' + @test dim(Q) == dim(L) == 0 + end + @testset "rightnull with $alg" for alg in (TK.LQ(), TK.SVD(), TK.SDD()) + M = @constinferred rightnull(copy(t'); alg=alg) + @test M * M' β‰ˆ id(codomain(M)) + @test M' * M β‰ˆ id(domain(M)) + end + @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) + U, S, V = @constinferred tsvd(t; alg=alg) + @test U == t + @test dim(U) == dim(S) == dim(V) + end + @testset "cond and rank" begin + @test rank(t) == 0 + W2 = zero(V1) * zero(V2) + t2 = rand(W2, W2) + @test rank(t2) == 0 + @test cond(t2) == 0.0 + end + end + t = rand(T, V1 βŠ— V2 ← V1 βŠ— V2) + @testset "eig and isposdef" begin + D, V = eigen(t) + @test t * V β‰ˆ V * D + + d = LinearAlgebra.eigvals(t; sortby=nothing) + dβ€² = LinearAlgebra.diag(D) + for (c, b) in d + @test b β‰ˆ dβ€²[c] + end + + # Somehow moving these test before the previous one gives rise to errors + # with T=Float32 on x86 platforms. Is this an OpenBLAS issue? + VdV = V' * V + VdV = (VdV + VdV') / 2 + @test isposdef(VdV) + + @test !isposdef(t) # unlikely for non-hermitian map + t2 = (t + t') + D, V = eigen(t2) + VdV = V' * V + @test VdV β‰ˆ one(VdV) + DΜƒ, VΜƒ = @constinferred eigh(t2) + @test D β‰ˆ DΜƒ + @test V β‰ˆ VΜƒ + Ξ» = minimum(minimum(real(LinearAlgebra.diag(b))) + for (c, b) in blocks(D)) + @test cond(VΜƒ) β‰ˆ one(real(T)) + @test isposdef(t2) == isposdef(Ξ») + @test isposdef(t2 - Ξ» * one(t2) + 0.1 * one(t2)) + @test !isposdef(t2 - Ξ» * one(t2) - 0.1 * one(t2)) + end + end + end end \ No newline at end of file From a1cc53ce905f54690349d40e2178eaf40d8e62d7 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 22 Aug 2025 12:55:00 +0200 Subject: [PATCH 165/206] round dim of space that's supposed to be integer --- test/test_A4.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 1ad38b7..c2facbf 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -263,8 +263,10 @@ println("---------------------------------") Vect[I](c => 1 for c in sectors(V) if rightone(c) == ur == leftone(c) || (c.i == i && c.j == j)) @test @constinferred(βŠ•(Wleft, WMop)) == Vect[I](c => 1 for c in sectors(V) if rightone(c) == ul == leftone(c) || (c.i == j && c.j == i)) - @test @constinferred(fuse(Wleft, WM)) == Vect[I](c => dim(Wleft) for c in sectors(WM)) # this might be wrong - @test @constinferred(fuse(Wright, WMop)) == Vect[I](c => dim(Wright) for c in sectors(WMop)) # same + # round needed below because of numerical F-symbols not being integer when they should be + # although this test might be stupid, because I'm assuming integer qdims bc everything's a group or irrep on the diagonal + @test @constinferred(fuse(Wleft, WM)) == Vect[I](c => round(Int, dim(Wleft)) for c in sectors(WM)) # this might be wrong + @test @constinferred(fuse(Wright, WMop)) == Vect[I](c => round(Int, dim(Wright)) for c in sectors(WMop)) # same # less sensible fuse @test @constinferred(fuse(Wleft, WMop)) == fuse(Wright, WM) == From 67cc8c8f526200b65f174c949013157779a04c48 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 22 Aug 2025 13:58:46 +0200 Subject: [PATCH 166/206] small refactor of diagonal check --- test/test_A4.jl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index c2facbf..46f5507 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -838,7 +838,7 @@ end # no permute tests: NoBraiding() @timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r - #TODO: refactor isdiag check + isdiag = i == j VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? @@ -863,12 +863,12 @@ end Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) ) - Vcol = i != j ? (VM1, VM2) : (VC,) # avoid duplicate runs + Vcol = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs for V in Vcol # TODO: add enumerate to keep track of potential erroring space V1, V2, V3, V4, V5 = V @timedtestset "Basic tensor properties" begin - W = i == j ? V1 βŠ— V2 βŠ— V3 βŠ— V4 βŠ— V5 : V3 βŠ— V4 βŠ— V5 # fusion matters + W = isdiag ? V1 βŠ— V2 βŠ— V3 βŠ— V4 βŠ— V5 : V3 βŠ— V4 βŠ— V5 # fusion matters for T in (Int, Float32, Float64, ComplexF32, ComplexF64, BigFloat) t = @constinferred zeros(T, W) # empty for i != j b/c blocks are module-graded @test @constinferred(hash(t)) == hash(deepcopy(t)) @@ -1150,7 +1150,6 @@ end @timedtestset "Tensor product: test via tensor contraction" begin # W = V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2 W = V4 ← V1 βŠ— V2 # less costly - isdiag = all(a.i == a.j for a in blocksectors(W)) for T in (Float32, ComplexF64) if !isdiag t1 = rand(T, W) @@ -1196,12 +1195,12 @@ end @timedtestset "Factorization" for V in fact_Vs V1, V2, V3, V4, V5 = V + # TODO: try ifelse/?: here WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' # old left permute resulted in this space WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' # old right permute WmodR = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # new fusion order for right WmodL = V1 βŠ— V2 βŠ— V5' ← V3 βŠ— V4 # new fusion order for left - isdiag = all(c.i == c.j for c in blocksectors(WmodR)) # this blocksectors call should always work #TODO: can't this just be i == j? for T in (Float32, ComplexF64) # Test both a normal tensor and an adjoint one. # adjoint takes other space for shape of matrix in RQ(pos) From 6e3fca53364c2960cc63e7cc9d906b5ce0312e23 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 22 Aug 2025 14:15:57 +0200 Subject: [PATCH 167/206] remove limited rightorth after new spaces --- test/test_A4.jl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 46f5507..b57e5c4 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -1195,11 +1195,10 @@ end @timedtestset "Factorization" for V in fact_Vs V1, V2, V3, V4, V5 = V - # TODO: try ifelse/?: here - WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' # old left permute resulted in this space - WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' # old right permute - WmodR = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # new fusion order for right - WmodL = V1 βŠ— V2 βŠ— V5' ← V3 βŠ— V4 # new fusion order for left + WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' + WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' + WmodR = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # custom fusion order for off-diagonal case + WmodL = V1 βŠ— V2 βŠ— V5' ← V3 βŠ— V4 for T in (Float32, ComplexF64) # Test both a normal tensor and an adjoint one. @@ -1211,7 +1210,6 @@ end (TK.RQ(), TK.RQpos(), TK.LQ(), TK.LQpos(), TK.Polar(), TK.SVD(), TK.SDD()) - (alg isa RQ || alg isa RQpos || alg isa Polar) && !isdiag && continue L, Q = @constinferred rightorth(t; alg=alg) QQd = Q * Q' @test QQd β‰ˆ one(QQd) From 5bd32a218582d0d1d7ce43f9bfd6509f6c98499e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 22 Aug 2025 14:42:56 +0200 Subject: [PATCH 168/206] generalise `Base.iterate` --- src/bimodulesector.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index a9c4e4c..da4f6b9 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -37,16 +37,16 @@ Base.size(::Type{A4Object}) = 7 Base.IteratorSize(::Type{<:SectorValues{<:BimoduleSector}}) = Base.SizeUnknown() -# TODO: generalize? -function Base.iterate(iter::SectorValues{A4Object}, (I, label)=(1, 1)) - s = size(A4Object) +function Base.iterate(iter::SectorValues{<:BimoduleSector}, (I, label)=(1, 1)) + A = eltype(iter) + s = size(A) I > s * s && return nothing i, j = CartesianIndices((s, s))[I].I - maxlabel = _numlabels(A4Object, i, j) + maxlabel = _numlabels(A, i, j) return if label > maxlabel iterate(iter, (I + 1, 1)) else - A4Object(i, j, label), (I, label + 1) + A(i, j, label), (I, label + 1) end end From b4c79c0c7e54919e22de4e8a5192f78ffbc65917 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 22 Aug 2025 15:02:23 +0200 Subject: [PATCH 169/206] correct the `BimoduleSector` inner constructor --- src/bimodulesector.jl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index da4f6b9..3b0bc69 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -1,14 +1,19 @@ +const ImplementedBimoduleSectors = [:A4] + struct BimoduleSector{Name} <: Sector i::Int j::Int label::Int - function BimoduleSector{:A4}(i::Int, j::Int, label::Int) - i <= size(BimoduleSector{:A4}) && j <= size(BimoduleSector{:A4}) || - throw(DomainError("object outside the matrix A4")) - return label <= _numlabels(BimoduleSector{:A4}, i, j) ? new{:A4}(i, j, label) : - throw(DomainError("label outside category A4($i, $j)")) + function BimoduleSector{Name}(i::Int, j::Int, label::Int) where {Name} + Name ∈ ImplementedBimoduleSectors || + throw(ArgumentError("BimoduleSector $Name not implemented")) + i <= size(BimoduleSector{Name}) && j <= size(BimoduleSector{Name}) || + throw(DomainError("object outside the matrix $Name")) + return label <= _numlabels(BimoduleSector{Name}, i, j) ? new{Name}(i, j, label) : + throw(DomainError("label outside category $Name($i, $j)")) end end + BimoduleSector{Name}(data::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(data...) const A4Object = BimoduleSector{:A4} From ff01886fa402d8ede2ede5db190a8bd781576375 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 22 Aug 2025 16:24:43 +0200 Subject: [PATCH 170/206] generalise `A4Object` to `BimoduleSector` where possible --- src/bimodulesector.jl | 50 +++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 3b0bc69..9ff3fe5 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -15,6 +15,7 @@ struct BimoduleSector{Name} <: Sector end BimoduleSector{Name}(data::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(data...) +BimoduleSectorName(::Type{BimoduleSector{Name}}) where {Name} = Name const A4Object = BimoduleSector{:A4} Base.convert(::Type{<:BimoduleSector{Name}}, labels::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(labels...) @@ -55,21 +56,21 @@ function Base.iterate(iter::SectorValues{<:BimoduleSector}, (I, label)=(1, 1)) end end -function Base.length(::SectorValues{A4Object}) - s = size(A4Object) - return sum(_numlabels(A4Object, i, j) for i in 1:s, j in 1:s) +function Base.length(::SectorValues{I}) where {I<:BimoduleSector} + s = size(I) + return sum(_numlabels(I, i, j) for i in 1:s, j in 1:s) end TensorKitSectors.FusionStyle(::Type{A4Object}) = GenericFusion() -TensorKitSectors.BraidingStyle(::Type{A4Object}) = NoBraiding() +TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding() TensorKitSectors.sectorscalartype(::Type{A4Object}) = ComplexF64 -function TensorKitSectors.:βŠ—(a::A4Object, b::A4Object) +function TensorKitSectors.:βŠ—(a::I, b::I) where {I<:BimoduleSector} @assert a.j == b.i - Ncache = _get_Ncache(A4Object)[a.i, a.j, b.j] - return A4Object[A4Object(a.i, b.j, c_l) - for (a_l, b_l, c_l) in keys(Ncache) - if (a_l == a.label && b_l == b.label)] + Ncache = _get_Ncache(I)[a.i, a.j, b.j] + return I[I(a.i, b.j, c_l) + for (a_l, b_l, c_l) in keys(Ncache) + if (a_l == a.label && b_l == b.label)] end function _numlabels(::Type{T}, i, j) where {T<:BimoduleSector} @@ -84,14 +85,15 @@ end # --------------- const artifact_path = joinpath(artifact"fusiondata", "MultiTensorKit.jl-data-v0.1.5") -function extract_Nsymbol(::Type{A4Object}) - filename = joinpath(artifact_path, "A4", "Nsymbol.txt") - isfile(filename) || throw(LoadError(filename, 0, "Nsymbol file not found for A4")) +function extract_Nsymbol(::Type{I}) where {I <: BimoduleSector} + name = string(BimoduleSectorName(I)) + filename = joinpath(artifact_path, name, "Nsymbol.txt") + isfile(filename) || throw(LoadError(filename, 0, "Nsymbol file not found for $name")) Narray = readdlm(filename) # matrix with 7 columns data_dict = Dict{NTuple{3,Int},Dict{NTuple{3,Int},Int}}() for row in eachrow(Narray) - i, j, k, a, b, c, N = Int.(@view(row[1:size(A4Object)])) + i, j, k, a, b, c, N = Int.(@view(row[1:size(I)])) colordict = get!(data_dict, (i, j, k), Dict{NTuple{3,Int},Int}()) push!(colordict, (a, b, c) => N) end @@ -109,7 +111,7 @@ function _get_Ncache(::Type{T}) where {T<:BimoduleSector} end end -function TensorKitSectors.Nsymbol(a::I, b::I, c::I) where {I<:A4Object} +function TensorKitSectors.Nsymbol(a::I, b::I, c::I) where {I<:BimoduleSector} # TODO: should this error or return 0? (a.j == b.i && a.i == c.i && b.j == c.j) || throw(ArgumentError("invalid fusion channel")) @@ -126,9 +128,9 @@ function _get_dual_cache(::Type{T}) where {T<:BimoduleSector} end end -function extract_dual(::Type{A4Object}) - N = _get_Ncache(A4Object) - ncats = size(A4Object) +function extract_dual(::Type{I}) where {I <: BimoduleSector} + N = _get_Ncache(I) + ncats = size(I) Is = zeros(Int, ncats) map(1:ncats) do i @@ -205,15 +207,16 @@ function Base.conj(a::BimoduleSector) return typeof(a)(a.j, a.i, _get_dual_cache(typeof(a))[2][a.i, a.j][a.label]) end -function extract_Fsymbol(::Type{A4Object}) +function extract_Fsymbol(::Type{I}) where {I <: BimoduleSector} result = Dict{NTuple{4,Int},Dict{NTuple{6,Int},Array{ComplexF64,4}}}() - filename = joinpath(artifact_path, "A4", "Fsymbol.txt") + name = string(BimoduleSectorName(I)) + filename = joinpath(artifact_path, name, "Fsymbol.txt") @assert isfile(filename) "cannot find $filename" Farray = readdlm(filename) for ((i, j, k, l), colordict) in convert_Fs(Farray) result[(i, j, k, l)] = Dict{NTuple{6,Int},Array{ComplexF64,4}}() for ((a, b, c, d, e, f), Fvals) in colordict - a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = A4Object.(((i, j, a), (j, k, b), + a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = I.(((i, j, a), (j, k, b), (k, l, c), (i, l, d), (i, k, e), (j, l, f))) result[(i, j, k, l)][(a, b, c, d, e, f)] = zeros(ComplexF64, @@ -221,8 +224,8 @@ function extract_Fsymbol(::Type{A4Object}) Nsymbol(e_ob, c_ob, d_ob), Nsymbol(b_ob, c_ob, f_ob), Nsymbol(a_ob, f_ob, d_ob)) - for (I, v) in Fvals - result[(i, j, k, l)][(a, b, c, d, e, f)][I] = v + for (K, v) in Fvals + result[(i, j, k, l)][(a, b, c, d, e, f)][K] = v end end end @@ -258,7 +261,7 @@ function _get_Fcache(::Type{T}) where {T<:BimoduleSector} end function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, - f::I) where {I<:A4Object} + f::I) where {I<:BimoduleSector} # required to keep track of multiplicities where F-move is partially unallowed # also deals with invalid fusion channels Nabe = Nsymbol(a, b, e) @@ -278,6 +281,7 @@ end # interface with TensorKit where necessary #----------------------------------------- +#TODO: generalise function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where {S<:Union{Vect[A4Object], SumSpace{Vect[A4Object]}},N₁,Nβ‚‚} From 49aec8d645b46e21c0d36ac53d24ea5cb1f81e55 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 25 Aug 2025 12:04:33 +0200 Subject: [PATCH 171/206] fix example image --- .../man/img/A4_sym_entanglement_spectrum.svg | 949 ++++++++++-------- 1 file changed, 522 insertions(+), 427 deletions(-) diff --git a/docs/src/man/img/A4_sym_entanglement_spectrum.svg b/docs/src/man/img/A4_sym_entanglement_spectrum.svg index 8af3cb0..c7fcead 100644 --- a/docs/src/man/img/A4_sym_entanglement_spectrum.svg +++ b/docs/src/man/img/A4_sym_entanglement_spectrum.svg @@ -1,464 +1,559 @@ - + - + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + From b27446d14b907df4e1bc18bffce18f841fed63da Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 1 Sep 2025 17:46:12 +0200 Subject: [PATCH 172/206] add Random to Project.toml for tests --- Project.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 3419abc..c33813c 100644 --- a/Project.toml +++ b/Project.toml @@ -16,6 +16,7 @@ Aqua = "0.8.9" Artifacts = "1.10, 1" BlockTensorKit = "0.1.10" DelimitedFiles = "1.9" +Random = "1.11.0" SafeTestsets = "0.1" TensorKit = "0.14.9" TensorKitSectors = "0.1.7, 0.2" @@ -26,9 +27,10 @@ julia = "1.10" [extras] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestExtras = "5ed8adda-3752-4e41-b88a-e8b09835ee3a" [targets] -test = ["Aqua", "SafeTestsets", "Test", "TestExtras"] +test = ["Aqua", "Random", "SafeTestsets", "Test", "TestExtras"] From fbc166e82c6b01c47427e8aaa94a6737acdf24d9 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 24 Sep 2025 15:24:17 +0200 Subject: [PATCH 173/206] remove `left/rightoneunit` coming from TensorKit (temporary) --- src/bimodulesector.jl | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 9ff3fe5..60b049d 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -282,6 +282,7 @@ end #----------------------------------------- #TODO: generalise +# is this blocksectors necessary with the productspace one? function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where {S<:Union{Vect[A4Object], SumSpace{Vect[A4Object]}},N₁,Nβ‚‚} @@ -304,6 +305,28 @@ function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where end end +#TODO: generalise +# function TensorKit.blocksectors(P::ProductSpace{S,N}) where {S<:Union{Vect[A4Object],SumSpace{Vect[A4Object]}},N} +# I = sectortype(S) # currently just A4Object +# bs = Vector{I}() +# if N == 0 +# return I[one(I(i, i, 1)) for i in 1:size(I)] +# elseif N == 1 +# for s in sectors(P) +# push!(bs, first(s)) +# end +# else +# for s in sectors(P) +# for c in βŠ—(s...) +# if !(c in bs) +# push!(bs, c) +# end +# end +# end +# end +# return sort!(bs) +# end + function TensorKit.dim(V::GradedSpace{<:BimoduleSector}) T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) return reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(T)) @@ -334,11 +357,11 @@ end function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) @assert !isempty(S) "Cannot determine type of empty space" - return SumSpace(oneunit(first(S.spaces))) + return SumSpace(oneunit(first(S.spaces))) # assuming diagonal SumSpace (like in MPSKit) end # oneunit for spaces whose elements all belong to the same sector -function TensorKit.rightoneunit(S::GradedSpace{<:BimoduleSector}) +function rightoneunit(S::GradedSpace{<:BimoduleSector}) allequal(a.j for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same rightone")) @@ -346,12 +369,12 @@ function TensorKit.rightoneunit(S::GradedSpace{<:BimoduleSector}) return spacetype(S)(sector => 1) end -function TensorKit.rightoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +function rightoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) @assert !isempty(S) "Cannot determine type of empty space" return SumSpace(rightoneunit(first(S.spaces))) end -function TensorKit.leftoneunit(S::GradedSpace{<:BimoduleSector}) +function leftoneunit(S::GradedSpace{<:BimoduleSector}) allequal(a.i for a in sectors(S)) || throw(ArgumentError("sectors of $S do not have the same leftone")) @@ -359,7 +382,7 @@ function TensorKit.leftoneunit(S::GradedSpace{<:BimoduleSector}) return spacetype(S)(sector => 1) end -function TensorKit.leftoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +function leftoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) @assert !isempty(S) "Cannot determine type of empty space" return SumSpace(leftoneunit(first(S.spaces))) end From 0719edcf3cbb78c96510a6c79463437d55eff912 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 24 Sep 2025 15:41:12 +0200 Subject: [PATCH 174/206] update compats --- Project.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index c33813c..1275662 100644 --- a/Project.toml +++ b/Project.toml @@ -14,12 +14,12 @@ TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] Aqua = "0.8.9" Artifacts = "1.10, 1" -BlockTensorKit = "0.1.10" +BlockTensorKit = "0.2.0" DelimitedFiles = "1.9" Random = "1.11.0" SafeTestsets = "0.1" -TensorKit = "0.14.9" -TensorKitSectors = "0.1.7, 0.2" +TensorKit = "0.14.11" +TensorKitSectors = "0.2.1" Test = "1.10" TestExtras = "0.3" TupleTools = "1.1" From 8fda727627a077b6bfdbf91e94950009e8d7619b Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 14:05:28 +0100 Subject: [PATCH 175/206] update compat for TensorKit v0.15 --- Project.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 1275662..3854e13 100644 --- a/Project.toml +++ b/Project.toml @@ -14,12 +14,12 @@ TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] Aqua = "0.8.9" Artifacts = "1.10, 1" -BlockTensorKit = "0.2.0" +BlockTensorKit = "0.3" DelimitedFiles = "1.9" Random = "1.11.0" SafeTestsets = "0.1" -TensorKit = "0.14.11" -TensorKitSectors = "0.2.1" +TensorKit = "0.15" +TensorKitSectors = "0.3" Test = "1.10" TestExtras = "0.3" TupleTools = "1.1" From 9e718a2d27536738f5de3a4a1fdc50cda5c56e69 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 14:39:27 +0100 Subject: [PATCH 176/206] renamings from TensorKit v0.15 + incoming renamings --- src/bimodulesector.jl | 46 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 60b049d..00243b0 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -184,22 +184,22 @@ function extract_dual(::Type{I}) where {I <: BimoduleSector} return Is, allduals end -function Base.one(a::BimoduleSector) +function TensorKitSectors.unit(a::BimoduleSector) a.i == a.j || throw(DomainError("unit of module category ($(a.i), $(a.j)) of $(typeof(a)) is ill-defined")) return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end -Base.isone(a::BimoduleSector) = leftone(a) == a == rightone(a) +# Base.isone(a::BimoduleSector) = leftone(a) == a == rightone(a) -function Base.one(::Type{<:BimoduleSector}) +function TensorKitSectors.unit(::Type{<:BimoduleSector}) throw(ArgumentError("one of Type BimoduleSector doesn't exist")) end -function TensorKitSectors.leftone(a::BimoduleSector) +function TensorKitSectors.leftunit(a::BimoduleSector) return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end -function TensorKitSectors.rightone(a::BimoduleSector) +function TensorKitSectors.rightunit(a::BimoduleSector) return typeof(a)(a.j, a.j, _get_dual_cache(typeof(a))[1][a.j]) end @@ -345,8 +345,8 @@ function TensorKit.fuse(V₁::GradedSpace{I}, Vβ‚‚::GradedSpace{I}) where {I<:Bi return typeof(V₁)(dims) end -# limited oneunit -function Base.oneunit(S::GradedSpace{<:BimoduleSector}) +# limited unitspace +function TensorKit.unitspace(S::GradedSpace{<:BimoduleSector}) allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || throw(ArgumentError("sectors of $S are not all equal")) first(sectors(S)).i == first(sectors(S)).j || @@ -355,44 +355,44 @@ function Base.oneunit(S::GradedSpace{<:BimoduleSector}) return spacetype(S)(sector => 1) end -function Base.oneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +function TensorKit.unitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) @assert !isempty(S) "Cannot determine type of empty space" return SumSpace(oneunit(first(S.spaces))) # assuming diagonal SumSpace (like in MPSKit) end # oneunit for spaces whose elements all belong to the same sector -function rightoneunit(S::GradedSpace{<:BimoduleSector}) +function rightunitspace(S::GradedSpace{<:BimoduleSector}) allequal(a.j for a in sectors(S)) || - throw(ArgumentError("sectors of $S do not have the same rightone")) + throw(ArgumentError("sectors of $S do not have the same rightunit")) - sector = rightone(first(sectors(S))) + sector = rightunit(first(sectors(S))) return spacetype(S)(sector => 1) end -function rightoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +function rightunitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) @assert !isempty(S) "Cannot determine type of empty space" - return SumSpace(rightoneunit(first(S.spaces))) + return SumSpace(rightunitspace(first(S.spaces))) end -function leftoneunit(S::GradedSpace{<:BimoduleSector}) +function leftunitspace(S::GradedSpace{<:BimoduleSector}) allequal(a.i for a in sectors(S)) || - throw(ArgumentError("sectors of $S do not have the same leftone")) + throw(ArgumentError("sectors of $S do not have the same leftunit")) - sector = leftone(first(sectors(S))) + sector = leftunit(first(sectors(S))) return spacetype(S)(sector => 1) end -function leftoneunit(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +function leftunitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) @assert !isempty(S) "Cannot determine type of empty space" - return SumSpace(leftoneunit(first(S.spaces))) + return SumSpace(leftunitspace(first(S.spaces))) end -function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}; +function TensorKit.insertrightunitspace(P::ProductSpace{V,N}, ::Val{i}; conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} i > N && error("cannot insert a sensible right unit onto $P at index $(i+1)") - # possible change to rightone of correct space for N = 0 - u = N > 0 ? rightoneunit(P[i]) : error("no unit object in $P") + # possible change to rightunit of correct space for N = 0 + u = N > 0 ? rightunitspace(P[i]) : error("no unit object in $P") if dual u = TensorKit.dual(u) end @@ -403,11 +403,11 @@ function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}; end # possible TODO: overwrite defaults at level of HomSpace and TensorMap? -function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}; # want no defaults? +function TensorKit.insertleftunitspace(P::ProductSpace{V,N}, ::Val{i}; # want no defaults? conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} i > N && error("cannot insert a sensible left unit onto $P at index $i") # do we want this to error in the diagonal case? - u = N > 0 ? leftoneunit(P[i]) : error("no unit object in $P") + u = N > 0 ? leftunitspace(P[i]) : error("no unit object in $P") if dual u = TensorKit.dual(u) end From ff6af7bddd40e1f7dc48bfd7be4bb30bddaa82e6 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Wed, 5 Nov 2025 15:51:03 +0100 Subject: [PATCH 177/206] add `allunits`, fix `dual`, revert `insertleft/rightunitspace` --- src/bimodulesector.jl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 00243b0..4b2bda4 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -191,6 +191,11 @@ end # Base.isone(a::BimoduleSector) = leftone(a) == a == rightone(a) +function TensorKitSectors.allunits(::Type{I}) where {I <: BimoduleSector} + s = size(I) + return I[I(i, i, _get_dual_cache(I)[1][i]) for i in 1:s] +end + function TensorKitSectors.unit(::Type{<:BimoduleSector}) throw(ArgumentError("one of Type BimoduleSector doesn't exist")) end @@ -203,7 +208,7 @@ function TensorKitSectors.rightunit(a::BimoduleSector) return typeof(a)(a.j, a.j, _get_dual_cache(typeof(a))[1][a.j]) end -function Base.conj(a::BimoduleSector) +function TensorKitSectors.dual(a::BimoduleSector) return typeof(a)(a.j, a.i, _get_dual_cache(typeof(a))[2][a.i, a.j][a.label]) end @@ -345,6 +350,8 @@ function TensorKit.fuse(V₁::GradedSpace{I}, Vβ‚‚::GradedSpace{I}) where {I<:Bi return typeof(V₁)(dims) end +#TODO: these might not be necessary anymore after TensorKit#291 + # limited unitspace function TensorKit.unitspace(S::GradedSpace{<:BimoduleSector}) allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || @@ -387,7 +394,8 @@ function leftunitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) return SumSpace(leftunitspace(first(S.spaces))) end -function TensorKit.insertrightunitspace(P::ProductSpace{V,N}, ::Val{i}; + +function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}; conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} i > N && error("cannot insert a sensible right unit onto $P at index $(i+1)") @@ -403,7 +411,7 @@ function TensorKit.insertrightunitspace(P::ProductSpace{V,N}, ::Val{i}; end # possible TODO: overwrite defaults at level of HomSpace and TensorMap? -function TensorKit.insertleftunitspace(P::ProductSpace{V,N}, ::Val{i}; # want no defaults? +function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}; # want no defaults? conj::Bool=false, dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} i > N && error("cannot insert a sensible left unit onto $P at index $i") # do we want this to error in the diagonal case? From 45e9074399fec9256d26f339f53b6592d5469cf5 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 21 Nov 2025 15:31:53 +0100 Subject: [PATCH 178/206] add LinearAlgebra for tests --- Project.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 3854e13..e6b2e9a 100644 --- a/Project.toml +++ b/Project.toml @@ -27,10 +27,11 @@ julia = "1.10" [extras] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" TestExtras = "5ed8adda-3752-4e41-b88a-e8b09835ee3a" [targets] -test = ["Aqua", "Random", "SafeTestsets", "Test", "TestExtras"] +test = ["Aqua", "LinearAlgebra", "Random", "SafeTestsets", "Test", "TestExtras"] From 2ebd2bb4c20b283b97457b09a32f7595db080087 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 22 Dec 2025 10:23:33 +0100 Subject: [PATCH 179/206] bump TK version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index e6b2e9a..ee8e86b 100644 --- a/Project.toml +++ b/Project.toml @@ -18,7 +18,7 @@ BlockTensorKit = "0.3" DelimitedFiles = "1.9" Random = "1.11.0" SafeTestsets = "0.1" -TensorKit = "0.15" +TensorKit = "0.16" TensorKitSectors = "0.3" Test = "1.10" TestExtras = "0.3" From 557c894b430d45dbbdf1f7088d441816725cdd1e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 22 Dec 2025 10:29:26 +0100 Subject: [PATCH 180/206] remove BlockTensorKit dep --- Project.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Project.toml b/Project.toml index ee8e86b..b06e5c0 100644 --- a/Project.toml +++ b/Project.toml @@ -5,7 +5,6 @@ version = "0.1.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" -BlockTensorKit = "5f87ffc2-9cf1-4a46-8172-465d160bd8cd" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" @@ -14,7 +13,6 @@ TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] Aqua = "0.8.9" Artifacts = "1.10, 1" -BlockTensorKit = "0.3" DelimitedFiles = "1.9" Random = "1.11.0" SafeTestsets = "0.1" From f1811367f074d871199d8a8a0e1e302230c827bf Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 22 Dec 2025 10:41:01 +0100 Subject: [PATCH 181/206] remove compiling BTK --- src/MultiTensorKit.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index d54caa6..3a4d727 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -9,9 +9,6 @@ using TensorKitSectors using TupleTools using TupleTools: insertafter -using BlockTensorKit -import BlockTensorKit: SumSpace - using TensorKit import TensorKit: hasblock, dim From faacc546311ff18428e3f727c423574619c7435e Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Mon, 22 Dec 2025 17:28:25 +0100 Subject: [PATCH 182/206] remove TK interface (mostly) --- src/bimodulesector.jl | 181 ++++++------------------------------------ 1 file changed, 23 insertions(+), 158 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 4b2bda4..1d01f8c 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -136,8 +136,8 @@ function extract_dual(::Type{I}) where {I <: BimoduleSector} map(1:ncats) do i Niii = N[i, i, i] nobji = maximum(first, keys(N[i, i, i])) - # want to return a leftone and rightone for each entry in multifusion cat - # leftone/rightone needs to at least be the unit object within a fusion cat + # want to return a leftunit and rightunit for each entry in multifusion cat + # leftunit/rightunit needs to at least be the unit object within a fusion cat Is[i] = findfirst(1:nobji) do a get(Niii, (a, a, a), 0) == 1 || return false # I x I -> I for othera in 1:nobji @@ -145,19 +145,19 @@ function extract_dual(::Type{I}) where {I <: BimoduleSector} get(Niii, (a, othera, othera), 0) == 1 || return false # I x a -> a end - # check leftone + # check leftunit map(1:ncats) do j nobjj = maximum(first, keys(N[j, j, j])) for b in 1:nobjj - get(N[i, j, j], (a, b, b), 0) == 1 || return false # I = leftone(b) + get(N[i, j, j], (a, b, b), 0) == 1 || return false # I = leftunit(b) end end - # check rightone + # check rightunit map(1:ncats) do k nobjk = maximum(first, keys(N[k, k, k])) for c in 1:nobjk - get(N[k, i, k], (c, a, c), 0) == 1 || return false # I = rightone(c) + get(N[k, i, k], (c, a, c), 0) == 1 || return false # I = rightunit(c) end end return true @@ -175,8 +175,8 @@ function extract_dual(::Type{I}) where {I <: BimoduleSector} Niji = N[i, j, i] # π’ž_ij x π’ž_ji -> C_ii Njij = N[j, i, j] # π’ž_ji x π’ž_ij -> C_jj for i_ob in 1:nobji, j_ob in 1:nobjj - get(Niji, (i_ob, j_ob, Is[i]), 0) == 1 || continue # leftone(c_ij) ∈ c_ij x c_ji - get(Njij, (j_ob, i_ob, Is[j]), 0) == 1 || continue # rightone(c_ij) ∈ c_ji x c_ij + get(Niji, (i_ob, j_ob, Is[i]), 0) == 1 || continue # leftunit(c_ij) ∈ c_ij x c_ji + get(Njij, (j_ob, i_ob, Is[j]), 0) == 1 || continue # rightunit(c_ij) ∈ c_ji x c_ij push!(allduals[i, j], j_ob) end end @@ -189,15 +189,13 @@ function TensorKitSectors.unit(a::BimoduleSector) return typeof(a)(a.i, a.i, _get_dual_cache(typeof(a))[1][a.i]) end -# Base.isone(a::BimoduleSector) = leftone(a) == a == rightone(a) - function TensorKitSectors.allunits(::Type{I}) where {I <: BimoduleSector} s = size(I) return I[I(i, i, _get_dual_cache(I)[1][i]) for i in 1:s] end function TensorKitSectors.unit(::Type{<:BimoduleSector}) - throw(ArgumentError("one of Type BimoduleSector doesn't exist")) + throw(ArgumentError("unit of Type BimoduleSector doesn't exist")) end function TensorKitSectors.leftunit(a::BimoduleSector) @@ -286,59 +284,7 @@ end # interface with TensorKit where necessary #----------------------------------------- -#TODO: generalise -# is this blocksectors necessary with the productspace one? -function TensorKit.blocksectors(W::TensorMapSpace{S,N₁,Nβ‚‚}) where - {S<:Union{Vect[A4Object], - SumSpace{Vect[A4Object]}},N₁,Nβ‚‚} - codom = codomain(W) - dom = domain(W) - if N₁ == 0 && Nβ‚‚ == 0 # 0x0-dimensional TensorMap is just a scalar, return all units - # this is a problem in full contractions where the coloring outside is π’ž - return NTuple{size(A4Object),A4Object}(one(A4Object(i, i, 1)) - for i in 1:size(A4Object)) # have to return all units b/c no info on W in this case - elseif N₁ == 0 - @assert Nβ‚‚ != 0 "one of Type A4Object doesn't exist" - return filter!(isone, collect(blocksectors(dom))) - elseif Nβ‚‚ == 0 - @assert N₁ != 0 "one of Type A4Object doesn't exist" - return filter!(isone, collect(blocksectors(codom))) - elseif Nβ‚‚ <= N₁ # keep intersection - return filter!(c -> hasblock(codom, c), collect(blocksectors(dom))) - else - return filter!(c -> hasblock(dom, c), collect(blocksectors(codom))) - end -end - -#TODO: generalise -# function TensorKit.blocksectors(P::ProductSpace{S,N}) where {S<:Union{Vect[A4Object],SumSpace{Vect[A4Object]}},N} -# I = sectortype(S) # currently just A4Object -# bs = Vector{I}() -# if N == 0 -# return I[one(I(i, i, 1)) for i in 1:size(I)] -# elseif N == 1 -# for s in sectors(P) -# push!(bs, first(s)) -# end -# else -# for s in sectors(P) -# for c in βŠ—(s...) -# if !(c in bs) -# push!(bs, c) -# end -# end -# end -# end -# return sort!(bs) -# end - -function TensorKit.dim(V::GradedSpace{<:BimoduleSector}) - T = Base.promote_op(*, Int, real(sectorscalartype(sectortype(V)))) - return reduce(+, dim(V, c) * dim(c) for c in sectors(V); init=zero(T)) -end - -Base.zero(S::Type{<:GradedSpace{<:BimoduleSector}}) = S() - +# TODO: can remove this once the otimes assert is removed function TensorKit.fuse(V₁::GradedSpace{I}, Vβ‚‚::GradedSpace{I}) where {I<:BimoduleSector} dims = TensorKit.SectorDict{I,Int}() for a in sectors(V₁), b in sectors(Vβ‚‚) @@ -351,100 +297,19 @@ function TensorKit.fuse(V₁::GradedSpace{I}, Vβ‚‚::GradedSpace{I}) where {I<:Bi end #TODO: these might not be necessary anymore after TensorKit#291 +# check after BlockTensorKit#38 -# limited unitspace -function TensorKit.unitspace(S::GradedSpace{<:BimoduleSector}) - allequal(a.i for a in sectors(S)) && allequal(a.j for a in sectors(S)) || - throw(ArgumentError("sectors of $S are not all equal")) - first(sectors(S)).i == first(sectors(S)).j || - throw(ArgumentError("sectors of $S are non-diagonal")) - sector = one(first(sectors(S))) - return spacetype(S)(sector => 1) -end - -function TensorKit.unitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) - @assert !isempty(S) "Cannot determine type of empty space" - return SumSpace(oneunit(first(S.spaces))) # assuming diagonal SumSpace (like in MPSKit) -end - -# oneunit for spaces whose elements all belong to the same sector -function rightunitspace(S::GradedSpace{<:BimoduleSector}) - allequal(a.j for a in sectors(S)) || - throw(ArgumentError("sectors of $S do not have the same rightunit")) - - sector = rightunit(first(sectors(S))) - return spacetype(S)(sector => 1) -end - -function rightunitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) - @assert !isempty(S) "Cannot determine type of empty space" - return SumSpace(rightunitspace(first(S.spaces))) -end - -function leftunitspace(S::GradedSpace{<:BimoduleSector}) - allequal(a.i for a in sectors(S)) || - throw(ArgumentError("sectors of $S do not have the same leftunit")) - - sector = leftunit(first(sectors(S))) - return spacetype(S)(sector => 1) -end - -function leftunitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) - @assert !isempty(S) "Cannot determine type of empty space" - return SumSpace(leftunitspace(first(S.spaces))) -end - - -function TensorKit.insertrightunit(P::ProductSpace{V,N}, ::Val{i}; - conj::Bool=false, - dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} - i > N && error("cannot insert a sensible right unit onto $P at index $(i+1)") - # possible change to rightunit of correct space for N = 0 - u = N > 0 ? rightunitspace(P[i]) : error("no unit object in $P") - if dual - u = TensorKit.dual(u) - end - if conj - u = TensorKit.conj(u) - end - return ProductSpace(TupleTools.insertafter(P.spaces, i, (u,))) -end - -# possible TODO: overwrite defaults at level of HomSpace and TensorMap? -function TensorKit.insertleftunit(P::ProductSpace{V,N}, ::Val{i}; # want no defaults? - conj::Bool=false, - dual::Bool=false) where {i,V<:GradedSpace{I},N} where {I<:BimoduleSector} - i > N && error("cannot insert a sensible left unit onto $P at index $i") # do we want this to error in the diagonal case? - u = N > 0 ? leftunitspace(P[i]) : error("no unit object in $P") - if dual - u = TensorKit.dual(u) - end - if conj - u = TensorKit.conj(u) - end - return ProductSpace(TupleTools.insertafter(P.spaces, i - 1, (u,))) -end - -function TensorKit.scalar(t::AbstractTensorMap{T,S,0,0}) where {T, - S<:GradedSpace{<:BimoduleSector}} - Bs = collect(blocks(t)) - inds = findall(!iszero ∘ last, Bs) - isempty(inds) && return zero(scalartype(t)) - return only(last(Bs[only(inds)])) -end +# function TensorKit.unitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +# @assert !isempty(S) "Cannot determine type of empty space" +# return SumSpace(oneunit(first(S.spaces))) # assuming diagonal SumSpace (like in MPSKit) +# end -# is this even necessary? can let it error at TensorKit fusiontrees.jl:93 from the one(<:BimoduleSector) call -# but these errors are maybe more informative -function TensorKit.FusionTree(uncoupled::Tuple{<:I,Vararg{I}}) where {I<:BimoduleSector} - coupled = collect(βŠ—(uncoupled...)) - if length(coupled) == 0 # illegal fusion somewhere - throw(ArgumentError("Forbidden fusion with uncoupled sectors $uncoupled")) - else # allowed fusions require inner lines - error("fusion tree requires inner lines if `FusionStyle(I) <: MultipleFusion`") - end -end +# function rightunitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +# @assert !isempty(S) "Cannot determine type of empty space" +# return SumSpace(rightunitspace(first(S.spaces))) +# end -# this one might also be overkill, since `FusionTreeIterator`s don't check whether the fusion is allowed -function TensorKit.fusiontrees(uncoupled::Tuple{I,Vararg{I}}) where {I<:BimoduleSector} - return throw(ArgumentError("coupled sector must be provided for $I fusion")) -end \ No newline at end of file +# function leftunitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) +# @assert !isempty(S) "Cannot determine type of empty space" +# return SumSpace(leftunitspace(first(S.spaces))) +# end \ No newline at end of file From c2ee53f0cef8efa7d62a05e4fadf7d2c90d87ee4 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 10:54:09 +0100 Subject: [PATCH 183/206] tinker with deps and compat --- Project.toml | 4 +--- src/MultiTensorKit.jl | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index b06e5c0..6b63f53 100644 --- a/Project.toml +++ b/Project.toml @@ -4,7 +4,6 @@ authors = ["Boris De Vos, Laurens Lootens and Lukas Devos"] version = "0.1.0" [deps] -Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" @@ -12,9 +11,8 @@ TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] Aqua = "0.8.9" -Artifacts = "1.10, 1" DelimitedFiles = "1.9" -Random = "1.11.0" +Random = "1" SafeTestsets = "0.1" TensorKit = "0.16" TensorKitSectors = "0.3" diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index 3a4d727..b5383cf 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -3,7 +3,8 @@ module MultiTensorKit export BimoduleSector, A4Object using DelimitedFiles -using Artifacts +using Pkg +using Pkg.Artifacts using TensorKitSectors using TupleTools From 4f1977552cf2e883104e377b290ed20e275134f8 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 10:57:28 +0100 Subject: [PATCH 184/206] more tinkering --- Project.toml | 4 ++-- src/MultiTensorKit.jl | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 6b63f53..04d74c0 100644 --- a/Project.toml +++ b/Project.toml @@ -5,20 +5,20 @@ version = "0.1.0" [deps] DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f" -TupleTools = "9d95972d-f1c8-5527-a6e0-b4b365fa01f6" [compat] Aqua = "0.8.9" DelimitedFiles = "1.9" +Pkg = "1" Random = "1" SafeTestsets = "0.1" TensorKit = "0.16" TensorKitSectors = "0.3" Test = "1.10" TestExtras = "0.3" -TupleTools = "1.1" julia = "1.10" [extras] diff --git a/src/MultiTensorKit.jl b/src/MultiTensorKit.jl index b5383cf..635ac69 100644 --- a/src/MultiTensorKit.jl +++ b/src/MultiTensorKit.jl @@ -7,9 +7,6 @@ using Pkg using Pkg.Artifacts using TensorKitSectors -using TupleTools -using TupleTools: insertafter - using TensorKit import TensorKit: hasblock, dim From 354cb96f179d98cc52e3b0a4a7a900865b70181c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 12:46:21 +0100 Subject: [PATCH 185/206] update tests --- test/runtests.jl | 1 + test/setup.jl | 71 ++- test/test_A4.jl | 1161 ++++++++++++++++++++++++++++------------------ 3 files changed, 741 insertions(+), 492 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 6b48268..f88fb64 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,6 +15,7 @@ istestfile(fn) = endswith(fn, ".jl") && startswith(basename(fn), "test_") && !contains(fn, "setup") include("setup.jl") +using .TestSetup @time begin # tests in groups based on folder structure diff --git a/test/setup.jl b/test/setup.jl index 2669aeb..3e5b063 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -1,3 +1,7 @@ +module TestSetup + +export unitarity_test, rand_object, random_fusion, eval_show + using MultiTensorKit using TensorKitSectors using Random @@ -6,8 +10,7 @@ const MTK = MultiTensorKit Random.seed!(1234) -function unitarity_test(as::Vector{I}, bs::Vector{I}, - cs::Vector{I}) where {I<:BimoduleSector} +function unitarity_test(as::Vector{I}, bs::Vector{I},cs::Vector{I}) where {I <: BimoduleSector} # abstractvector? @assert all(a.j == b.i for a in as, b in bs) @assert all(b.j == c.i for b in bs, c in cs) @@ -19,14 +22,12 @@ function unitarity_test(as::Vector{I}, bs::Vector{I}, for e in es for f in fs Fs = Fsymbol(a, b, c, d, e, f) - push!(Fblocks, - reshape(Fs, - (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) + push!(Fblocks, reshape(Fs, (size(Fs, 1) * size(Fs, 2), + size(Fs, 3) * size(Fs, 4)))) end end F = hvcat(length(fs), Fblocks...) - isapprox(F' * F, one(F); atol=1e-12, rtol=1e-12) || return false + isapprox(F' * F, one(F); atol = 1.0e-12, rtol = 1.0e-12) || return false end end return true @@ -37,47 +38,41 @@ all_objects(::Type{<:BimoduleSector}, i::Int, j::Int) = [I(i, j, k) for k in 1:M function rand_object(I::Type{<:BimoduleSector}, i::Int, j::Int) obs = all_objects(I, i, j) ob = rand(obs) - if i == j - while ob == one(ob) # unit of any fusion cat avoided - ob = rand(obs) - end + while isunit(ob) # unit of any fusion cat avoided + ob = rand(obs) end + return ob end -function random_fusion(I::Type{<:BimoduleSector}, i::Int, j::Int, N::Int) # for fusion tree tests +function random_fusion(I::Type{<:BimoduleSector}, i::Int, j::Int, ::Val{N}) where {N} # for fusion tree tests + N == 1 && return (rand_object(I, i, j),) + tail = random_fusion(I, i, j, Val(N - 1)) + counter = 0 + Cs = all_objects(I, i, i) Ds = all_objects(I, j, j) Ms = all_objects(I, i, j) Mops = all_objects(I, j, i) allobs = vcat(Cs, Ds, Ms, Mops) + s = rand(allobs) - in = nothing - out = nothing - while in === nothing - out = ntuple(n -> rand(allobs), N) - try - in = rand(collect(βŠ—(out...))) - catch e - if isa(e, AssertionError) - in = nothing - else - rethrow(e) - end - end + while isempty(βŠ—(s, first(tail))) && counter < 40 + counter += 1 + s = (counter < 40) ? rand(allobs) : leftunit(first(tail)) end - return out + return (s, tail...) end -# for fusion tree merge test -function safe_tensor_product(x::I, y::I) where {I<:BimoduleSector} - try - return x βŠ— y - catch e - if e isa AssertionError - return nothing - else - rethrow(e) - end - end -end \ No newline at end of file +""" + eval_show(x) + +Use `show` to generate a string representation of `x`, then parse and evaluate the resulting expression. +""" +function eval_show(x) + str = sprint(show, x; context = (:module => @__MODULE__)) + ex = Meta.parse(str) + return eval(ex) +end + +end # end of module TestSetup diff --git a/test/test_A4.jl b/test/test_A4.jl index b57e5c4..61569c1 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -22,7 +22,7 @@ end @testset "$Istr: Value iterator" begin @test eltype(values(I)) == I - @test_throws ArgumentError one(I) + @test_throws ArgumentError unit(I) sprev = I(1, 1, 1) # first in SectorValues for (i, s) in enumerate(values(I)) @test !isless(s, sprev) # confirm compatibility with sort order @@ -50,11 +50,11 @@ end s = rand(Cii_obs, 3) @test eval(Meta.parse(sprint(show, s[1]))) == s[1] @test @constinferred(hash(s[1])) == hash(deepcopy(s[1])) - @test isone(@constinferred(one(s[1]))) + @test isunit(@constinferred(unit(s[1]))) u = I.(i, i, MTK._get_dual_cache(I)[1][i]) - @test u == @constinferred(leftone(u)) == @constinferred(rightone(u)) == - @constinferred(one(u)) - @test isone(@constinferred(one(s[1]))) + @test u == @constinferred(leftunit(u)) == @constinferred(rightunit(u)) == + @constinferred(unit(u)) + @test isunit(@constinferred(unit(s[1]))) @constinferred dual(s[1]) @test dual(s[1]) == I.(i, i, MTK._get_dual_cache(I)[2][i, i][s[1].label]) @constinferred dim(s[1]) @@ -67,13 +67,13 @@ end @test eval(Meta.parse(sprint(show, m))) == m @test @constinferred(hash(m)) == hash(deepcopy(m)) - @test isone(m) == false - @test isone(mop) == false - @test (isone(@constinferred(leftone(m))) && isone(@constinferred(rightone(m)))) - @test one(c) == leftone(m) == rightone(mop) - @test one(d) == rightone(m) == leftone(mop) - @test_throws DomainError one(m) - @test_throws DomainError one(mop) + @test isunit(m) == false + @test isunit(mop) == false + @test (isunit(@constinferred(leftunit(m))) && isunit(@constinferred(rightunit(m)))) + @test unit(c) == leftunit(m) == rightunit(mop) + @test unit(d) == rightunit(m) == leftunit(mop) + @test_throws DomainError unit(m) + @test_throws DomainError unit(mop) @constinferred dual(m) @test dual(m) == I.(j, i, MTK._get_dual_cache(I)[2][i, j][m.label]) @@ -98,7 +98,7 @@ end @test !isempty(βŠ—(obs...)) end - @test Nsymbol(c, one(c), c) == Nsymbol(d, one(d), d) == 1 + @test Nsymbol(c, unit(c), c) == Nsymbol(d, unit(d), d) == 1 @test_throws argerr Nsymbol(m, mop, d) @test_throws argerr Nsymbol(mop, m, c) @@ -191,27 +191,42 @@ println("---------------------------------") gen = (values(I)[k] => (k + 1) for k in 1:length(values(I))) V = GradedSpace(gen) - @test eval(Meta.parse(TK.type_repr(typeof(V)))) == typeof(V) - @test eval(Meta.parse(sprint(show, V))) == V - @test eval(Meta.parse(sprint(show, V'))) == V' - @test V' == GradedSpace(gen; dual=true) + @test eval(Meta.parse(type_repr(typeof(V)))) == typeof(V) + @test eval_show(V) == V + @test eval_show(V') == V' + @test V' == GradedSpace(gen; dual = true) @test V == @constinferred GradedSpace(gen...) - @test V' == @constinferred GradedSpace(gen...; dual=true) + @test V' == @constinferred GradedSpace(gen...; dual = true) @test V == @constinferred GradedSpace(tuple(gen...)) - @test V' == @constinferred GradedSpace(tuple(gen...); dual=true) + @test V' == @constinferred GradedSpace(tuple(gen...); dual = true) @test V == @constinferred GradedSpace(Dict(gen)) - @test V' == @constinferred GradedSpace(Dict(gen); dual=true) + @test V' == @constinferred GradedSpace(Dict(gen); dual = true) @test V == @inferred Vect[I](gen) - @test V' == @constinferred Vect[I](gen; dual=true) + @test V' == @constinferred Vect[I](gen; dual = true) @test V == @constinferred Vect[I](gen...) - @test V' == @constinferred Vect[I](gen...; dual=true) + @test V' == @constinferred Vect[I](gen...; dual = true) @test V == @constinferred Vect[I](Dict(gen)) - @test V' == @constinferred Vect[I](Dict(gen); dual=true) - @test V == @constinferred typeof(V)(c => dim(V, c) for c in sectors(V)) + @test V' == @constinferred Vect[I](Dict(gen); dual = true) @test @constinferred(hash(V)) == hash(deepcopy(V)) != hash(V') @test V == GradedSpace(reverse(collect(gen))...) - @test eval(Meta.parse(sprint(show, V))) == V - @test eval(Meta.parse(sprint(show, typeof(V)))) == typeof(V) + @test eval_show(V) == V + @test eval_show(typeof(V)) == typeof(V) + + @test dim(@constinferred(zerospace(V))) == 0 + + W = @constinferred GradedSpace(unit => 1 for unit in allunits(I)) + dict = Dict(unit => 1 for unit in allunits(I)) + @test W == GradedSpace(dict) + @test W == GradedSpace(push!(dict, randsector(I) => 0)) + @test @constinferred(zerospace(V)) == GradedSpace(unit => 0 for unit in allunits(I)) + randunit = rand(collect(allunits(I))) + @test_throws ArgumentError("Sector $(randunit) appears multiple times") GradedSpace(randunit => 1, randunit => 3) + + @test isunitspace(W) + @test @constinferred(unitspace(V)) == W == unitspace(typeof(V)) + @test_throws ArgumentError leftunitspace(V) + @test_throws ArgumentError rightunitspace(V) + @test eval_show(W) == W @test isa(V, VectorSpace) @test isa(V, ElementarySpace) @@ -219,8 +234,7 @@ println("---------------------------------") @test isa(InnerProductStyle(V), EuclideanInnerProduct) @test isa(V, GradedSpace) @test isa(V, GradedSpace{I}) - @test @constinferred(dual(V)) == @constinferred(conj(V)) == - @constinferred(adjoint(V)) != V + @test @constinferred(dual(V)) == @constinferred(conj(V)) == @constinferred(adjoint(V)) != V @test @constinferred(field(V)) == β„‚ @test @constinferred(sectortype(V)) == I slist = @constinferred sectors(V) @@ -229,40 +243,38 @@ println("---------------------------------") @test @constinferred(reduceddim(V)) == sum(dim(V, s) for s in slist) @constinferred dim(V, first(slist)) - @test @constinferred(βŠ•(V, zero(V))) == V + @test @constinferred(βŠ•(V, zerospace(V))) == V @test @constinferred(βŠ•(V, V)) == Vect[I](c => 2dim(V, c) for c in sectors(V)) @test @constinferred(βŠ•(V, V, V, V)) == Vect[I](c => 4dim(V, c) for c in sectors(V)) + @test @constinferred(βŠ•(V, unitspace(V))) == Vect[I](c => isunit(c) + dim(V, c) for c in sectors(V)) + @test @constinferred(fuse(V, unitspace(V))) == V - @testset "$Istr ($i, $j) spaces" for i in 1:r, j in 1:r + @testset "$Istr ($i, $j) spaces" for i in 1:r, j in 1:r #TODO: look at these tests better # space with a single sector Wleft = @constinferred Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)) Wright = @constinferred Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)) WM = @constinferred Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) WMop = @constinferred Vect[I]((j, i, label) => 1 for label in 1:MTK._numlabels(I, j, i)) - @test @constinferred(oneunit(Wleft)) == leftoneunit(Wleft) == rightoneunit(Wleft) - @test @constinferred(oneunit(Wright)) == leftoneunit(Wright) == rightoneunit(Wright) - @test @constinferred(leftoneunit(βŠ•(Wleft, WM))) == oneunit(Wleft) - @test @constinferred(leftoneunit(βŠ•(Wright, WMop))) == oneunit(Wright) - @test @constinferred(rightoneunit(βŠ•(Wright, WM))) == oneunit(Wright) - @test @constinferred(rightoneunit(βŠ•(Wleft, WMop))) == oneunit(Wleft) - - @test_throws ArgumentError oneunit(I) + @test leftunitspace(Wleft) == rightunitspace(Wleft) + @test leftunitspace(Wright) == rightunitspace(Wright) + @test @constinferred(leftunitspace(βŠ•(Wleft, WM))) == leftunitspace(Wleft) + @test @constinferred(leftunitspace(βŠ•(Wright, WMop))) == leftunitspace(Wright) + @test @constinferred(rightunitspace(βŠ•(Wright, WM))) == rightunitspace(Wright) + @test @constinferred(rightunitspace(βŠ•(Wleft, WMop))) == rightunitspace(Wleft) if i != j # some tests specialised for modules - @test_throws ArgumentError oneunit(WM) - @test_throws ArgumentError oneunit(WMop) # sensible direct sums and fuses - ul, ur = one(I(i, i, 1)), one(I(j, j, 1)) + ul, ur = unit(I(i, i, 1)), unit(I(j, j, 1)) @test @constinferred(βŠ•(Wleft, WM)) == - Vect[I](c => 1 for c in sectors(V) if leftone(c) == ul == rightone(c) || (c.i == i && c.j == j)) + Vect[I](c => 1 for c in sectors(V) if leftunit(c) == ul == rightunit(c) || (c.i == i && c.j == j)) @test @constinferred(βŠ•(Wright, WMop)) == - Vect[I](c => 1 for c in sectors(V) if leftone(c) == ur == rightone(c) || (c.i == j && c.j == i)) + Vect[I](c => 1 for c in sectors(V) if leftunit(c) == ur == rightunit(c) || (c.i == j && c.j == i)) @test @constinferred(βŠ•(Wright, WM)) == - Vect[I](c => 1 for c in sectors(V) if rightone(c) == ur == leftone(c) || (c.i == i && c.j == j)) + Vect[I](c => 1 for c in sectors(V) if rightunit(c) == ur == leftunit(c) || (c.i == i && c.j == j)) @test @constinferred(βŠ•(Wleft, WMop)) == - Vect[I](c => 1 for c in sectors(V) if rightone(c) == ul == leftone(c) || (c.i == j && c.j == i)) + Vect[I](c => 1 for c in sectors(V) if rightunit(c) == ul == leftunit(c) || (c.i == j && c.j == i)) # round needed below because of numerical F-symbols not being integer when they should be # although this test might be stupid, because I'm assuming integer qdims bc everything's a group or irrep on the diagonal @test @constinferred(fuse(Wleft, WM)) == Vect[I](c => round(Int, dim(Wleft)) for c in sectors(WM)) # this might be wrong @@ -282,9 +294,9 @@ println("---------------------------------") end for W in [Wleft, Wright] - @test @constinferred(βŠ•(W, oneunit(W))) == - Vect[I](c => isone(c) + dim(W, c) for c in sectors(W)) - @test @constinferred(fuse(W, oneunit(W))) == W + @test @constinferred(βŠ•(W, rightunitspace(W))) == + Vect[I](c => isunit(c) + dim(W, c) for c in sectors(W)) + @test @constinferred(fuse(W, rightunitspace(W))) == W end end @@ -305,54 +317,54 @@ println("---------------------------------") @test V == @constinferred infimum(V, βŠ•(V, V)) @test V β‰Ί βŠ•(V, V) @test !(V ≻ βŠ•(V, V)) + randlen = rand(1:length(values(I))) s = rand(collect(values(I))[randlen:end]) # such that dim(V, s) > randlen - @test infimum(V, GradedSpace(s => randlen)) == - GradedSpace(s => randlen) + @test infimum(V, GradedSpace(s => randlen)) == GradedSpace(s => randlen) @test_throws SpaceMismatch (βŠ•(V, V')) end @timedtestset "HomSpace with $(TK.type_repr(Vect[I])) involving ($i, $j)" for i in 1:r, j in 1:r - V = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + V1, V2, V3, V4, V5 = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), # same as V1 Vect[I]((i, j, 1) => 3), Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j))) - - for (V1, V2, V3, V4, V5) in (V,) - W = HomSpace(V1 βŠ— V2, V3 βŠ— V4 βŠ— V5) - @test W == (V3 βŠ— V4 βŠ— V5 β†’ V1 βŠ— V2) - @test W == (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5) - @test W' == (V1 βŠ— V2 β†’ V3 βŠ— V4 βŠ— V5) - @test eval(Meta.parse(sprint(show, W))) == W - @test eval(Meta.parse(sprint(show, typeof(W)))) == typeof(W) - @test spacetype(W) == typeof(V1) - @test sectortype(W) == sectortype(V1) - @test W[1] == V1 - @test W[2] == V2 - @test W[3] == V3' - @test W[4] == V4' - @test W[5] == V5' - - @test @constinferred(hash(W)) == hash(deepcopy(W)) != hash(W') - @test W == deepcopy(W) - @test W == @constinferred permute(W, ((1, 2), (3, 4, 5))) - @test permute(W, ((2, 4, 5), (3, 1))) == (V2 βŠ— V4' βŠ— V5' ← V3 βŠ— V1') - @test (V1 βŠ— V2 ← V1 βŠ— V2) == @constinferred TK.compose(W, W') - - @test_throws ErrorException insertleftunit(W) - @test insertrightunit(W) == (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 βŠ— rightoneunit(V5)) - @test_throws ErrorException insertrightunit(W, 6) - @test_throws ErrorException insertleftunit(W, 6) - - @test (V1 βŠ— V2 βŠ— rightoneunit(V2) ← V3 βŠ— V4 βŠ— V5) == - @constinferred(insertrightunit(W, 2)) - @test (V1 βŠ— V2 ← leftoneunit(V3) βŠ— V3 βŠ— V4 βŠ— V5) == - @constinferred(insertleftunit(W, 3)) - @test @constinferred(removeunit(insertleftunit(W, 3), 3)) == W - @test_throws ErrorException @constinferred(insertrightunit(one(V1) ← V1, 0)) # should I specify it's the other error? - @test_throws ErrorException insertleftunit(one(V1) ← V1, 0) - end + W = HomSpace(V1 βŠ— V2, V3 βŠ— V4 βŠ— V5) + + @test W == (V3 βŠ— V4 βŠ— V5 β†’ V1 βŠ— V2) + @test W == (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5) + @test W' == (V1 βŠ— V2 β†’ V3 βŠ— V4 βŠ— V5) + @test eval(Meta.parse(sprint(show, W))) == W + @test eval(Meta.parse(sprint(show, typeof(W)))) == typeof(W) + @test spacetype(W) == typeof(V1) + @test sectortype(W) == sectortype(V1) + @test W[1] == V1 + @test W[2] == V2 + @test W[3] == V3' + @test W[4] == V4' + @test W[5] == V5' + + @test @constinferred(hash(W)) == hash(deepcopy(W)) != hash(W') + @test W == deepcopy(W) + @test W == @constinferred permute(W, ((1, 2), (3, 4, 5))) + @test permute(W, ((2, 4, 5), (3, 1))) == (V2 βŠ— V4' βŠ— V5' ← V3 βŠ— V1') + @test (V1 βŠ— V2 ← V1 βŠ— V2) == @constinferred TK.compose(W, W') + + @test (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 βŠ— rightunitspace(V5)) == + @constinferred(insertleftunit(W)) == + @constinferred(insertrightunit(W)) + @test @constinferred(removeunit(insertleftunit(W), $(numind(W) + 1))) == W + @test_throws BoundsError insertrightunit(W, 6) + @test_throws BoundsError insertleftunit(W, 0) + + @test (V1 βŠ— V2 βŠ— rightunitspace(V2) ← V3 βŠ— V4 βŠ— V5) == + @constinferred(insertrightunit(W, 2)) + @test (V1 βŠ— V2 ← leftunitspace(V3) βŠ— V3 βŠ— V4 βŠ— V5) == + @constinferred(insertleftunit(W, 3)) + @test @constinferred(removeunit(insertleftunit(W, 3), 3)) == W + @test_throws ArgumentError @constinferred(insertrightunit(one(V1) ← V1, 0)) # should I specify it's the other error? + @test_throws ArgumentError insertleftunit(one(V1) ← V1, 0) end end @@ -362,13 +374,7 @@ println("---------------------------------------") @timedtestset "Fusion trees for $(TK.type_repr(I)) involving ($i, $j)" verbose = true for i in 1:r, j in 1:r N = 6 - Mop = rand_object(I, j, i) - M = rand_object(I, i, j) - C0 = one(I(i, i, 1)) - C1 = rand_object(I, i, i) - D0 = one(I(j, j, 1)) - D1 = rand_object(I, j, j) - out = (Mop, C0, C1, M, D0, D1) # should I try to make a non-hardcoded example? could vary number of Cs and Ds, as well as randomly fuse and check if allowed + out = random_fusion(I, i, j, Val(N)) isdual = ntuple(n -> rand(Bool), N) in = rand(collect(βŠ—(out...))) # will be in π’žβ±Όβ±Ό with this choice of out @@ -384,18 +390,22 @@ println("---------------------------------------") @test eval(Meta.parse(sprint(show, f))) == f end + C0, D0 = unit(I(i, i, 1)), unit(I(j, j, 1)) @testset "Fusion tree $Istr: constructor properties" for u in (C0, D0) @constinferred FusionTree((), u, (), (), ()) @constinferred FusionTree((u,), u, (false,), (), ()) @constinferred FusionTree((u, u), u, (false, false), (), (1,)) @constinferred FusionTree((u, u, u), u, (false, false, false), (u,), (1, 1)) - @constinferred FusionTree((u, u, u, u), u, (false, false, false, false), (u, u), - (1, 1, 1)) + @constinferred FusionTree( + (u, u, u, u), u, (false, false, false, false), (u, u), (1, 1, 1) + ) @test_throws MethodError FusionTree((u, u, u), u, (false, false), (u,), (1, 1)) - @test_throws MethodError FusionTree((u, u, u), u, (false, false, false), (u, u), - (1, 1)) - @test_throws MethodError FusionTree((u, u, u), u, (false, false, false), (u,), - (1, 1, 1)) + @test_throws MethodError FusionTree( + (u, u, u), u, (false, false, false), (u, u), (1, 1) + ) + @test_throws MethodError FusionTree( + (u, u, u), u, (false, false, false), (u,), (1, 1, 1) + ) @test_throws MethodError FusionTree((u, u, u), u, (false, false, false), (), (1,)) f = FusionTree((u, u, u), u, (false, false, false), (u,), (1, 1)) @@ -404,36 +414,44 @@ println("---------------------------------------") @test FusionStyle(f) == FusionStyle(I) @test BraidingStyle(f) == BraidingStyle(I) - # SimpleFusion - errstr = "fusion tree requires inner lines if `FusionStyle(I) <: MultipleFusion`" - @test_throws errstr FusionTree((), u, ()) - @test_throws errstr FusionTree((u,), u, (false,)) - @test_throws errstr FusionTree((u, u), u, (false, false)) - @test_throws errstr FusionTree((u, u, u), u) - @test_throws errstr FusionTree((u, u, u, u)) # custom FusionTree constructor required here + if FusionStyle(I) isa UniqueFusion + @constinferred FusionTree((), u, ()) + @constinferred FusionTree((u,), u, (false,)) + @constinferred FusionTree((u, u), u, (false, false)) + @constinferred FusionTree((u, u, u), u) + if UnitStyle(I) isa SimpleUnit + @constinferred FusionTree((u, u, u, u)) + else + @test_throws ArgumentError FusionTree((u, u, u, u)) + end + @test_throws MethodError FusionTree((u, u), u, (false, false, false)) + else + @test_throws ArgumentError FusionTree((), u, ()) + @test_throws ArgumentError FusionTree((u,), u, (false,)) + @test_throws ArgumentError FusionTree((u, u), u, (false, false)) + @test_throws ArgumentError FusionTree((u, u, u), u) + if I <: ProductSector && UnitStyle(I) isa GenericUnit + @test_throws DomainError FusionTree((u, u, u, u)) + else + @test_throws ArgumentError FusionTree((u, u, u, u)) + end + end end @testset "Fusion tree $Istr: insertat" begin N = 4 - out2 = random_fusion(I, i, j, N) + out2 = random_fusion(I, i, j, Val(N)) in2 = rand(collect(βŠ—(out2...))) isdual2 = ntuple(n -> rand(Bool), N) f2 = rand(collect(fusiontrees(out2, in2, isdual2))) for k in 1:N - out1, in1 = nothing, nothing - while in1 === nothing - try - out1 = random_fusion(I, i, j, N) # guaranteed good fusion - out1 = Base.setindex(out1, in2, k) # can lead to poor fusion - in1 = rand(collect(βŠ—(out1...))) - catch e - if isa(e, AssertionError) - in1 = nothing # keep trying till out1 is compatible with inserting in2 at k - else - rethrow(e) - end - end + out1 = random_fusion(I, i, j, Val(N)) # guaranteed good fusion + out1 = Base.setindex(out1, in2, i) # can lead to poor fusion + while isempty(βŠ—(out1...)) # TODO: better way to do this? + out1 = random_fusion(I, i, j, Val(N)) + out1 = Base.setindex(out1, in2, i) end + in1 = rand(collect(βŠ—(out1...))) isdual1 = ntuple(n -> rand(Bool), N) isdual1 = Base.setindex(isdual1, false, k) f1 = rand(collect(fusiontrees(out1, in1, isdual1))) @@ -495,13 +513,13 @@ println("---------------------------------------") out2 = random_fusion(I, i, j, N) in1 = rand(collect(βŠ—(out1...))) in2 = rand(collect(βŠ—(out2...))) - tp = safe_tensor_product(in1, in2) # messy solution but it works - while tp === nothing - out1 = random_fusion(I, i, j, N) - out2 = random_fusion(I, i, j, N) + tp = βŠ—(in1, in2) # messy solution but it works + while isempty(tp) + out1 = random_fusion(I, i, j, Val(N)) + out2 = random_fusion(I, i, j, Val(N)) in1 = rand(collect(βŠ—(out1...))) in2 = rand(collect(βŠ—(out2...))) - tp = safe_tensor_product(in1, in2) + tp = βŠ—(in1, in2) end f1 = rand(collect(fusiontrees(out1, in1))) @@ -514,19 +532,20 @@ println("---------------------------------------") # no merge and braid interplay tests end - # hardcoded double fusion tree tests - N = 6 - out = (Mop, C0, C1, M, D0, D1) # same as above - out2 = (D0, D1, Mop, C0, C1, M) # different order that still fuses to D0 or D1 - - incoming = rand(collect(βŠ—(out...))) # will be in π’žβ±Όβ±Ό - while incoming βˆ‰ collect(βŠ—(out2...)) # when i = j these don't necessarily fuse to the same object, since Mop x M doesn't return all objects in π’žα΅’α΅’ - Mop = rand_object(I, j, i) - out2 = (D0, D1, Mop, C0, C1, M) + # double fusion tree tests + N = 4 + out = random_fusion(I, i, j, Val(N)) + out2 = random_fusion(I, i, j, Val(N)) + tp = βŠ—(out...) + tp2 = βŠ—(out2...) + while isempty(intersect(tp, tp2)) # guarantee fusion to same coloring + out2 = random_fusion(I, i, j, Val(N)) + tp2 = βŠ—(out2...) end - + @test_throws ArgumentError fusiontrees((out..., map(dual, out)...)) + incoming = rand(collect(intersect(tp, tp2))) f1 = rand(collect(fusiontrees(out, incoming, ntuple(n -> rand(Bool), N)))) - f2 = rand(collect(fusiontrees(out2, incoming, ntuple(n -> rand(Bool), N)))) + f2 = rand(collect(fusiontrees(out2, incoming, ntuple(n -> rand(Bool), N)))) # no permuting @testset "Double fusion tree $Istr: repartitioning" begin for n in 0:(2 * N) @@ -638,8 +657,8 @@ V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) next = @constinferred Nothing iterate(bs, state) b2 = @constinferred block(t, first(blocksectors(t))) @test b1 == b2 - @test eltype(bs) === Pair{typeof(c),typeof(b1)} - @test typeof(b1) === TK.blocktype(t) + @test eltype(bs) === Pair{typeof(c), typeof(b1)} + @test typeof(b1) === TensorKit.blocktype(t) # basic linear algebra @test isa(@constinferred(norm(t)), real(T)) @test norm(t)^2 β‰ˆ dot(t, t) @@ -658,7 +677,9 @@ V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) @test norm(zerovector!(t)) == 0 @test norm(one!(t)) β‰ˆ sqrt(dim(V)) @test one!(t) == id(V) - @test norm(one!(t) - id(V)) == 0 + if T != BigFloat # seems broken for now + @test norm(one!(t) - id(V)) == 0 + end t1 = DiagonalTensorMap(rand(T, reduceddim(V)), V) t2 = DiagonalTensorMap(rand(T, reduceddim(V)), V) @@ -680,8 +701,7 @@ V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) Ξ± = rand(T) @test convert(TensorMap, Ξ± * t1) β‰ˆ Ξ± * convert(TensorMap, t1) @test convert(TensorMap, t1') β‰ˆ convert(TensorMap, t1)' - @test convert(TensorMap, t1 + t2) β‰ˆ - convert(TensorMap, t1) + convert(TensorMap, t2) + @test convert(TensorMap, t1 + t2) β‰ˆ convert(TensorMap, t1) + convert(TensorMap, t2) end end @timedtestset "Real and imaginary parts" begin @@ -726,8 +746,9 @@ V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) @test TensorMap(@constinferred t1 / t2) β‰ˆ TensorMap(t1) / TensorMap(t2) @test TensorMap(@constinferred inv(t1)) β‰ˆ inv(TensorMap(t1)) @test TensorMap(@constinferred pinv(t1)) β‰ˆ pinv(TensorMap(t1)) - @test all(Base.Fix2(isa, DiagonalTensorMap), - (t1 * t2, t1 \ t2, t1 / t2, inv(t1), pinv(t1))) + @test all( + Base.Fix2(isa, DiagonalTensorMap), (t1 * t2, t1 \ t2, t1 / t2, inv(t1), pinv(t1)) + ) # no V * V' * V ← V or V^2 ← V tests due to Nsymbol erroring where fusion is forbidden end @timedtestset "Tensor contraction " for i in 1:r @@ -754,58 +775,6 @@ V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) @planar E2[-1 -2 -3; -4 -5] = B[-1 -2 1; -4 -5] * t'[-3; 1] @test E1 β‰ˆ E2 end - @timedtestset "Factorization" begin - for T in (Float32, ComplexF64) - t = DiagonalTensorMap(rand(T, reduceddim(V)), V) - @testset "eig" begin - D, W = @constinferred eig(t) - @test t * W β‰ˆ W * D - t2 = t + t' - D2, V2 = @constinferred eigh(t2) - VdV2 = V2' * V2 - @test VdV2 β‰ˆ one(VdV2) - @test t2 * V2 β‰ˆ V2 * D2 - - @test rank(D) β‰ˆ rank(t) - @test cond(D) β‰ˆ cond(t) - @test all(((s, t),) -> isapprox(s, t), - zip(values(LinearAlgebra.eigvals(D)), - values(LinearAlgebra.eigvals(t)))) - end - @testset "leftorth with $alg" for alg in (TK.QR(), TK.QL()) - Q, R = @constinferred leftorth(t; alg=alg) - QdQ = Q' * Q - @test QdQ β‰ˆ one(QdQ) - @test Q * R β‰ˆ t - if alg isa Polar - @test isposdef(R) - end - end - @testset "rightorth with $alg" for alg in (TK.RQ(), TK.LQ()) - L, Q = @constinferred rightorth(t; alg=alg) - QQd = Q * Q' - @test QQd β‰ˆ one(QQd) - @test L * Q β‰ˆ t - if alg isa Polar - @test isposdef(L) - end - end - @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) - U, S, Vα΄΄ = @constinferred tsvd(t; alg=alg) - UdU = U' * U - @test UdU β‰ˆ one(UdU) - VdV = Vα΄΄ * Vα΄΄' - @test VdV β‰ˆ one(VdV) - @test U * S * Vα΄΄ β‰ˆ t - - @test rank(S) β‰ˆ rank(t) - @test cond(S) β‰ˆ cond(t) - @test all(((s, t),) -> isapprox(s, t), - zip(values(LinearAlgebra.svdvals(S)), - values(LinearAlgebra.svdvals(t)))) - end - end - end @timedtestset "Tensor functions" begin for T in (Float64, ComplexF64) d = DiagonalTensorMap(rand(T, reduceddim(V)), V) @@ -837,30 +806,34 @@ end # no conversion tests because no fusion tensor # no permute tests: NoBraiding() +println("---------------------------------------") +println("Tensors with symmetry: $Istr") +println("---------------------------------------") + @timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r isdiag = i == j VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? - Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? + Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](one(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) + Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) ) VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects - VM1 = (Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works + VM1 = (Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors - Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), VM, # important that V4 is module-graded - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) + Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) ) VM2 = (Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here - Vect[I](one(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), - Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), VM, - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) + Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) ) Vcol = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs @@ -877,7 +850,7 @@ end @test codomain(t) == W @test space(t) == (W ← one(W)) @test domain(t) == one(W) - @test typeof(t) == TensorMap{T,spacetype(t),length(W),0,Vector{T}} + @test typeof(t) == TensorMap{T, spacetype(t), length(W), 0, Vector{T}} # blocks bs = @constinferred blocks(t) if !isempty(bs) @@ -919,8 +892,8 @@ end next = @constinferred Nothing iterate(bs, state) b2 = @constinferred block(t', first(blocksectors(t'))) @test b1 == b2 - @test eltype(bs) === Pair{typeof(c),typeof(b1)} - @test typeof(b1) === TK.blocktype(t') + @test eltype(bs) === Pair{typeof(c), typeof(b1)} + @test typeof(b1) === TensorKit.blocktype(t') @test typeof(c) === sectortype(t) # linear algebra @test isa(@constinferred(norm(t)), real(T)) @@ -941,21 +914,17 @@ end @test dot(t2, t) β‰ˆ conj(dot(t2', t')) @test dot(t2, t) β‰ˆ dot(t', t2') - if all(a.i == a.j for a in blocksectors(W)) # can't reverse fusion for these - i1 = @constinferred(isomorphism(T, V1 βŠ— V2, V2 βŠ— V1)) + if !isempty(blocksectors(V2 βŠ— V1)) + i1 = @constinferred(isomorphism(T, V1 βŠ— V2, V2 βŠ— V1)) # can't reverse fusion here when modules are involved i2 = @constinferred(isomorphism(Vector{T}, V2 βŠ— V1, V1 βŠ— V2)) @test i1 * i2 == @constinferred(id(T, V1 βŠ— V2)) @test i2 * i1 == @constinferred(id(Vector{T}, V2 βŠ— V1)) end - for v in (V1, V2, V3, V4, V5) - wl = @constinferred(isometry(T, (leftoneunit(v) βŠ• leftoneunit(v)) βŠ— v, v)) - wr = @constinferred(isometry(T, v βŠ— (rightoneunit(v) βŠ• rightoneunit(v)), v)) - for w in (wl, wr) - @test dim(w) == 2 * dim(v ← v) - @test w' * w == id(Vector{T}, v) - @test w * w' == (w * w')^2 - end - end + + w = @constinferred isometry(T, V1 βŠ— (rightunitspace(V1) βŠ• rightunitspace(V1)), V1) + @test dim(w) == 2 * dim(V1 ← V1) + @test w' * w == id(Vector{T}, V1) + @test w * w' == (w * w')^2 end end @@ -963,29 +932,31 @@ end W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 for T in (Float32, ComplexF64) t = @constinferred rand(T, W) # fusion matters here - t2 = @constinferred insertleftunit(t, 5) # default errors + t2 = @constinferred insertleftunit(t) + @test t2 == @constinferred insertrightunit(t) + @test space(t2) == insertleftunit(space(t)) + @test @constinferred(removeunit(t2, $(numind(t2)))) == t + t3 = @constinferred insertleftunit(t; copy = true) + @test t3 == @constinferred insertrightunit(t; copy = true) + @test @constinferred(removeunit(t3, $(numind(t3)))) == t - @test t2 == @constinferred insertrightunit(t, 4) # default doesn't error bc i==N then @test numind(t2) == numind(t) + 1 - @test space(t2) == insertleftunit(space(t), 5) @test scalartype(t2) === T @test t.data === t2.data - @test @constinferred(removeunit(t2, $(numind(t2) - 1))) == t # -1 required - t3 = @constinferred insertleftunit(t, 5; copy=true) # same here - @test t3 == @constinferred insertrightunit(t, 4; copy=true) @test t.data !== t3.data for (c, b) in blocks(t) @test b == block(t3, c) end - @test @constinferred(removeunit(t3, $(numind(t3) - 1))) == t - t4 = @constinferred insertrightunit(t, 3; dual=true) + + t4 = @constinferred insertrightunit(t, 3; dual = true) @test numin(t4) == numin(t) + 1 && numout(t4) == numout(t) for (c, b) in blocks(t) @test b == block(t4, c) end @test @constinferred(removeunit(t4, 4)) == t - t5 = @constinferred insertleftunit(t, 4; dual=true) + + t5 = @constinferred insertleftunit(t, 4; dual = true) @test numin(t5) == numin(t) + 1 && numout(t5) == numout(t) for (c, b) in blocks(t) @test b == block(t5, c) @@ -1007,27 +978,19 @@ end end @timedtestset "Full trace: test self-consistency" begin - t = rand(ComplexF64, V1 βŠ— V2 ← V1 βŠ— V2) - s = @constinferred tr(t) - @test conj(s) β‰ˆ tr(t') - try # needed for module cases: certain transposes with module legs will result in different colorings - @planar s2 = t[a b; a b] # no twist needed bc permute avoided - @test s β‰ˆ s2 - catch e - @test isa(e, SectorMismatch) - end - - try # TODO?: skip module traces - @planar t3[a; b] := t[a c; b c] - @planar s3 = t3[a; a] # this contraction order gives zero for VIBMop1 and VIBMop2 because it traces out the module legs - @test s β‰ˆ s3 - catch e - @test isa(e, SectorMismatch) - end + t = rand(ComplexF64, V1 βŠ— V2 ← V1 βŠ— V2) # avoid permutes + ss = @constinferred tr(t) + @test conj(ss) β‰ˆ tr(t') + @planar s2 = t[a b; a b] + @planar t3[a; b] := t[a c; b c] + @planar s3 = t3[a; a] + + @test ss β‰ˆ s2 + @test ss β‰ˆ s3 end @timedtestset "Partial trace: test self-consistency" begin - t = rand(ComplexF64, V3 βŠ— V4 βŠ— V5 ← V3 βŠ— V4 βŠ— V5) # rewritten to be compatible with module fusion + t = rand(ComplexF64, V3 βŠ— V4 βŠ— V5 ← V3 βŠ— V4 βŠ— V5) # compatible with module fusion @planar t2[a; b] := t[c a d; c b d] @planar t4[a b; c d] := t[e a b; e c d] @planar t5[a; b] := t4[a c; b c] @@ -1050,18 +1013,14 @@ end @timedtestset "Multiplication of isometries: test properties" begin W2 = V4 βŠ— V5 - W1 = W2 βŠ— (rightoneunit(V5) βŠ• rightoneunit(V5)) - W3 = (leftoneunit(V4) βŠ• leftoneunit(V4)) βŠ— W2 - for W in (W1, W3) - for T in (Float64, ComplexF64) - t1 = @constinferred randisometry(T, W, W2) - t2 = randisometry(T, W2 ← W2) - @test t1' * t1 β‰ˆ one(t2) - @test t2' * t2 β‰ˆ one(t2) - @test t2 * t2' β‰ˆ one(t2) - P = t1 * t1' - @test P * P β‰ˆ P - end + W1 = W2 βŠ— (rightunitspace(V5) βŠ• rightunitspace(V5)) + for T in (Float64, ComplexF64) + t1 = randisometry(T, W1, W2) + t2 = randisometry(T, W2 ← W2) + @test isisometric(t1) + @test isunitary(t2) + P = t1 * t1' + @test P * P β‰ˆ P end end @@ -1076,7 +1035,7 @@ end @test (t / t2) * t2 β‰ˆ t @test t1 \ one(t1) β‰ˆ inv(t1) @test one(t1) / t1 β‰ˆ pinv(t1) - # @test_throws SpaceMismatch inv(t) # can coincidently fail b/c of rand_object + @test_throws SpaceMismatch inv(t) @test_throws SpaceMismatch t2 \ t @test_throws SpaceMismatch t / t1 tp = pinv(t) * t @@ -1093,31 +1052,6 @@ end @test LinearAlgebra.diag(D) == d end - @timedtestset "Tensor truncation" begin - for T in (Float32, ComplexF64) - # Test both a normal tensor and an adjoint one. - ts = (randn(T, V1 βŠ— V2, V3 βŠ— V4 βŠ— V5), randn(T, V4 βŠ— V5, V3 βŠ— V1 βŠ— V2)') # rewritten for modules - for p in (1, 2, 3, Inf) - for t in ts - Uβ‚€, Sβ‚€, Vβ‚€ = tsvd(t) - t = rmul!(t, 1 / norm(Sβ‚€, p)) - U, S, V, Ο΅ = @constinferred tsvd(t; trunc=truncerr(5e-1), p=p) - Uβ€², Sβ€², Vβ€², Ο΅β€² = tsvd(t; trunc=truncerr(nextfloat(Ο΅)), p=p) - @test (U, S, V, Ο΅) == (Uβ€², Sβ€², Vβ€², Ο΅β€²) - Uβ€², Sβ€², Vβ€², Ο΅β€² = tsvd(t; trunc=truncdim(ceil(Int, dim(domain(S)))), - p=p) - @test (U, S, V, Ο΅) == (Uβ€², Sβ€², Vβ€², Ο΅β€²) - Uβ€², Sβ€², Vβ€², Ο΅β€² = tsvd(t; trunc=truncspace(space(S, 1)), p=p) - @test (U, S, V, Ο΅) == (Uβ€², Sβ€², Vβ€², Ο΅β€²) - # results with truncationcutoff cannot be compared because they don't take degeneracy into account, and thus truncate differently - U, S, V, Ο΅ = tsvd(t; trunc=truncbelow(1 / dim(domain(Sβ‚€))), p=p) - Uβ€², Sβ€², Vβ€², Ο΅β€² = tsvd(t; trunc=truncspace(space(S, 1)), p=p) - @test (U, S, V, Ο΅) == (Uβ€², Sβ€², Vβ€², Ο΅β€²) - end - end - end - end - @timedtestset "Sylvester equation" begin for T in (Float32, ComplexF64) tA = rand(T, V1 βŠ— V2, V1 βŠ— V2) # rewritten for modules @@ -1130,23 +1064,24 @@ end @test domain(t) == V4 βŠ— V5 @test norm(tA * t + t * tB + tC) < (norm(tA) + norm(tB) + norm(tC)) * eps(real(T))^(2 / 3) - # no reshape test: NoBraiding and no fusion tensor end end @timedtestset "Tensor product: test via norm preservation" begin # OOMs over here with full spaces for T in (Float32, ComplexF64) - t1 = rand(T, V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2) - if all(a.i != a.j for a in blocksectors(t1)) - t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') + if !isempty(blocksectors(V2 βŠ— V1)) + t1 = rand(T, V2 βŠ— V3 βŠ— V1, V1 βŠ— V2) + t2 = rand(T, V2 βŠ— V1 βŠ— V3, V1 βŠ— V1) else - t2 = rand(T, V3' βŠ— V1, V4 βŠ— V5 βŠ— V2') # keep a non-trivial permutation in diagonal case + t1 = rand(T, V3 βŠ— V4 βŠ— V5, V1 βŠ— V2) + t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') end t = @constinferred (t1 βŠ— t2) @test norm(t) β‰ˆ norm(t1) * norm(t2) end end + # TODO: should this test exist? @timedtestset "Tensor product: test via tensor contraction" begin # W = V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2 W = V4 ← V1 βŠ— V2 # less costly @@ -1168,6 +1103,71 @@ end end end + @timedtestset "Tensor absorption" begin + # absorbing small into large + if !isempty(blocksectors(V2 βŠ— V3)) + t1 = zeros(V1 βŠ• V1, V2 βŠ— V3) + t2 = rand(V1, V2 βŠ— V3) + else + t1 = zeros(V1 βŠ• V2, V3 βŠ— V4 βŠ— V5) + t2 = rand(V1, V3 βŠ— V4 βŠ— V5) + end + t3 = @constinferred absorb(t1, t2) + @test norm(t3) β‰ˆ norm(t2) + @test norm(t1) == 0 + t4 = @constinferred absorb!(t1, t2) + @test t1 === t4 + @test t3 β‰ˆ t4 + + # absorbing large into small + if !isempty(blocksectors(V2 βŠ— V3)) + t1 = rand(V1 βŠ• V1, V2 βŠ— V3) + t2 = zeros(V1, V2 βŠ— V3) + else + t1 = rand(V1 βŠ• V2, V3 βŠ— V4 βŠ— V5) + t2 = zeros(V1, V3 βŠ— V4 βŠ— V5) + end + t3 = @constinferred absorb(t2, t1) + @test norm(t3) < norm(t1) + @test norm(t2) == 0 + t4 = @constinferred absorb!(t2, t1) + @test t2 === t4 + @test t3 β‰ˆ t4 + end +end + +println("---------------------------------------") +println("Factorizations with symmetry: $Istr") +println("---------------------------------------") + +@timedtestset "Factorizations with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r + isdiag = i == j + + VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? + Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) + ) + + VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects + + VM1 = (Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works + Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, # important that V4 is module-graded + Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) + ) + + VM2 = (Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here + Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, + Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) + ) + + Vs = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs + # some fail for (2, 2), (3, 3), (6, 6) # rightorth RQ(pos) and Polar (fail) for 2nd space # leftorth with QL(pos) and Polar for 1st space @@ -1175,190 +1175,443 @@ end # cond and rank leftnull for 1st space # factorization tests require equal objects in blocksectors of domain and codomain, so just put them all - VC_all = fill(Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), 5) + # FIXME: not sure if still needed + # VC_all = fill(Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), 5) + + # VM1_all = (Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + # VM, + # Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + # VM, + # Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 2) + # ) + + # VM2_all = (VM, + # Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), + # Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + # VM, + # Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 2) + # ) + + # fact_Vs = (i != j) ? (VM1_all, VM2_all) : (VC_all,) + + @timedtestset "Factorization" for V in Vs + V1, V2, V3, V4, V5 = V + W = V1 βŠ— V2 + @assert !isempty(blocksectors(W)) + @assert !isempty(intersect(blocksectors(V4), blocksectors(W))) + + @testset "QR decomposition" begin + for T in eltypes, + t in ( + rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', + DiagonalTensorMap(rand(T, reduceddim(V1)), V1), + ) + + Q, R = @constinferred qr_full(t) + @test Q * R β‰ˆ t + @test isunitary(Q) - VM1_all = (Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, - Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, - Vect[I](one(I(j, j, 1)) => 1, rand_object(I, j, j) => 2) - ) + Q, R = @constinferred qr_compact(t) + @test Q * R β‰ˆ t + @test isisometric(Q) - VM2_all = (VM, - Vect[I](one(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), - Vect[I](one(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, - Vect[I](one(I(j, j, 1)) => 2, rand_object(I, j, j) => 2) - ) + Q, R = @constinferred left_orth(t) + @test Q * R β‰ˆ t + @test isisometric(Q) - fact_Vs = (i != j) ? (VM1_all, VM2_all) : (VC_all,) + N = @constinferred qr_null(t) + @test isisometric(N) + @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) - @timedtestset "Factorization" for V in fact_Vs - V1, V2, V3, V4, V5 = V - WL = V3 βŠ— V4 βŠ— V2 ← V1' βŠ— V5' - WR = V3 βŠ— V4 ← V2' βŠ— V1' βŠ— V5' - WmodR = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # custom fusion order for off-diagonal case - WmodL = V1 βŠ— V2 βŠ— V5' ← V3 βŠ— V4 + N = @constinferred left_null(t) + @test isisometric(N) + @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) + end - for T in (Float32, ComplexF64) - # Test both a normal tensor and an adjoint one. - # adjoint takes other space for shape of matrix in RQ(pos) - tsR = isdiag ? (rand(T, WR), rand(T, WL)') : (rand(T, WmodR), rand(T, WmodL)') # shape of matrices require different spaces for left/right - tsL = isdiag ? (rand(T, WL), rand(T, WR)') : (rand(T, WmodR), rand(T, WmodL)') - for t in tsR - @testset "rightorth with $alg" for alg in - (TK.RQ(), TK.RQpos(), TK.LQ(), - TK.LQpos(), - TK.Polar(), TK.SVD(), TK.SDD()) - L, Q = @constinferred rightorth(t; alg=alg) - QQd = Q * Q' - @test QQd β‰ˆ one(QQd) - @test L * Q β‰ˆ t - if alg isa Polar - @test isposdef(L) - @test domain(L) == codomain(L) == space(t, 1) βŠ— space(t, 2) - end - end - @testset "rightnull with $alg" for alg in (TK.LQ(), TK.SVD(), TK.SDD()) - M = @constinferred rightnull(t; alg=alg) - MMd = M * M' - @test MMd β‰ˆ one(MMd) - @test norm(t * M') < 100 * eps(norm(t)) - end + # empty tensor + for T in eltypes + t = rand(T, V1 βŠ— V2, zerospace(V1)) + + Q, R = @constinferred qr_full(t) + @test Q * R β‰ˆ t + @test isunitary(Q) + @test dim(R) == dim(t) == 0 + + Q, R = @constinferred qr_compact(t) + @test Q * R β‰ˆ t + @test isisometric(Q) + @test dim(Q) == dim(R) == dim(t) + + Q, R = @constinferred left_orth(t) + @test Q * R β‰ˆ t + @test isisometric(Q) + @test dim(Q) == dim(R) == dim(t) + + N = @constinferred qr_null(t) + @test isunitary(N) + @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) end - # adjoints take other space for shape of matrix in QL(pos) - for t in tsL - @testset "leftorth with $alg" for alg in - (TK.QR(), TK.QRpos(), TK.QL(), TK.QLpos(), - TK.Polar(), TK.SVD(), TK.SDD()) - # skip QL because the monomorphism condition is hard to satisfy for off-diagonal case - # have to skip Polar as well as all tests fail with modules - (alg isa QL || alg isa QLpos || alg isa Polar) && !isdiag && continue - Q, R = @constinferred leftorth(t; alg=alg) - QdQ = Q' * Q - @test QdQ β‰ˆ one(QdQ) - @test Q * R β‰ˆ t - if alg isa Polar - @test isposdef(R) # this fails with modules - @test domain(R) == codomain(R) == space(t, 4)' βŠ— space(t, 5)' # this as well - end - end - @testset "leftnull with $alg" for alg in - (TK.QR(), TK.SVD(), TK.SDD()) - # less rows than columns so either fails or no data in off-diagonal case - !isdiag && continue - N = @constinferred leftnull(t; alg=alg) - NdN = N' * N - @test NdN β‰ˆ one(NdN) - @test norm(N' * t) < 100 * eps(norm(t)) - end - @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) - U, S, V = @constinferred tsvd(t; alg=alg) - UdU = U' * U - @test UdU β‰ˆ one(UdU) - VVd = V * V' - @test VVd β‰ˆ one(VVd) - @test U * S * V β‰ˆ t - - s = LinearAlgebra.svdvals(t) - sβ€² = LinearAlgebra.diag(S) - for (c, b) in s - @test b β‰ˆ sβ€²[c] - end - end - # cond and rank tests were here - @testset "cond and rank" begin - d1 = dim(codomain(t)) - d2 = dim(domain(t)) - @test rank(t) β‰ˆ min(d1, d2) # reduced to approx - if isdiag # leftnull doesn't work for off-diagonal case - M = leftnull(t) - @test rank(M) β‰ˆ max(d1, d2) - min(d1, d2) # reduced to approx - end - t2 = unitary(T, V1 βŠ— V2, V1 βŠ— V2) - @test cond(t2) β‰ˆ one(real(T)) - @test rank(t2) β‰ˆ dim(V1 βŠ— V2) # reduced to approx - t3 = randn(T, V1 βŠ— V2, V1 βŠ— V2) - t3 = (t3 + t3') / 2 - vals = LinearAlgebra.eigvals(t3) - Ξ»max = maximum(s -> maximum(abs, s), values(vals)) - Ξ»min = minimum(s -> minimum(abs, s), values(vals)) - @test cond(t3) β‰ˆ Ξ»max / Ξ»min - end + end + + @testset "LQ decomposition" begin + for T in eltypes, + t in ( + rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', + DiagonalTensorMap(rand(T, reduceddim(V1)), V1), + ) + + L, Q = @constinferred lq_full(t) + @test L * Q β‰ˆ t + @test isunitary(Q) + + L, Q = @constinferred lq_compact(t) + @test L * Q β‰ˆ t + @test isisometric(Q; side = :right) + + L, Q = @constinferred right_orth(t) + @test L * Q β‰ˆ t + @test isisometric(Q; side = :right) + + Nα΄΄ = @constinferred lq_null(t) + @test isisometric(Nα΄΄; side = :right) + @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) end - # how useful is this test? everything just works regardless of the space - @testset "empty tensor" begin - t = randn(T, V1 βŠ— V2, zero(V1)) - @testset "leftorth with $alg" for alg in - (TK.QR(), TK.QRpos(), TK.QL(), TK.QLpos(), - TK.Polar(), TK.SVD(), TK.SDD()) - Q, R = @constinferred leftorth(t; alg=alg) - @test Q == t - @test dim(Q) == dim(R) == 0 - end - @testset "leftnull with $alg" for alg in (TK.QR(), TK.SVD(), TK.SDD()) - N = @constinferred leftnull(t; alg=alg) - @test N' * N β‰ˆ id(domain(N)) - @test N * N' β‰ˆ id(codomain(N)) - end - @testset "rightorth with $alg" for alg in - (TK.RQ(), TK.RQpos(), TK.LQ(), - TK.LQpos(), - TK.Polar(), TK.SVD(), TK.SDD()) - L, Q = @constinferred rightorth(copy(t'); alg=alg) - @test Q == t' - @test dim(Q) == dim(L) == 0 - end - @testset "rightnull with $alg" for alg in (TK.LQ(), TK.SVD(), TK.SDD()) - M = @constinferred rightnull(copy(t'); alg=alg) - @test M * M' β‰ˆ id(codomain(M)) - @test M' * M β‰ˆ id(domain(M)) - end - @testset "tsvd with $alg" for alg in (TK.SVD(), TK.SDD()) - U, S, V = @constinferred tsvd(t; alg=alg) - @test U == t - @test dim(U) == dim(S) == dim(V) - end - @testset "cond and rank" begin - @test rank(t) == 0 - W2 = zero(V1) * zero(V2) - t2 = rand(W2, W2) - @test rank(t2) == 0 - @test cond(t2) == 0.0 - end + for T in eltypes + # empty tensor + t = rand(T, zerospace(V1), V1 βŠ— V2) + + L, Q = @constinferred lq_full(t) + @test L * Q β‰ˆ t + @test isunitary(Q) + @test dim(L) == dim(t) == 0 + + L, Q = @constinferred lq_compact(t) + @test L * Q β‰ˆ t + @test isisometric(Q; side = :right) + @test dim(Q) == dim(L) == dim(t) + + L, Q = @constinferred right_orth(t) + @test L * Q β‰ˆ t + @test isisometric(Q; side = :right) + @test dim(Q) == dim(L) == dim(t) + + Nα΄΄ = @constinferred lq_null(t) + @test isunitary(Nα΄΄) + @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) + end + end + + @testset "Polar decomposition" begin + for T in eltypes, + t in ( + rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', + DiagonalTensorMap(rand(T, reduceddim(V1)), V1), + ) + + @assert domain(t) β‰Ύ codomain(t) + w, p = @constinferred left_polar(t) + @test w * p β‰ˆ t + @test isisometric(w) + @test isposdef(p) + + w, p = @constinferred left_orth(t; alg = :polar) + @test w * p β‰ˆ t + @test isisometric(w) + end + + for T in eltypes, + t in (rand(T, W, W), rand(T, W, W)', rand(T, V4, W), rand(T, W, V4)') + + @assert codomain(t) β‰Ύ domain(t) + p, wα΄΄ = @constinferred right_polar(t) + @test p * wα΄΄ β‰ˆ t + @test isisometric(wα΄΄; side = :right) + @test isposdef(p) + + p, wα΄΄ = @constinferred right_orth(t; alg = :polar) + @test p * wα΄΄ β‰ˆ t + @test isisometric(wα΄΄; side = :right) end - t = rand(T, V1 βŠ— V2 ← V1 βŠ— V2) - @testset "eig and isposdef" begin - D, V = eigen(t) - @test t * V β‰ˆ V * D - - d = LinearAlgebra.eigvals(t; sortby=nothing) - dβ€² = LinearAlgebra.diag(D) - for (c, b) in d - @test b β‰ˆ dβ€²[c] + end + + @testset "SVD" begin + for T in eltypes, + t in ( + rand(T, W, W), rand(T, W, W)', + rand(T, W, V4), rand(T, V4, W), + rand(T, W, V4)', rand(T, V4, W)', + DiagonalTensorMap(rand(T, reduceddim(V1)), V1), + ) + + u, s, vα΄΄ = @constinferred svd_full(t) + @test u * s * vα΄΄ β‰ˆ t + @test isunitary(u) + @test isunitary(vα΄΄) + + u, s, vα΄΄ = @constinferred svd_compact(t) + @test u * s * vα΄΄ β‰ˆ t + @test isisometric(u) + @test isposdef(s) + @test isisometric(vα΄΄; side = :right) + + sβ€² = @constinferred svd_vals(t) + @test sβ€² β‰ˆ diagview(s) + @test sβ€² isa TensorKit.SectorVector + + v, c = @constinferred left_orth(t; alg = :svd) + @test v * c β‰ˆ t + @test isisometric(v) + + c, vα΄΄ = @constinferred right_orth(t; alg = :svd) + @test c * vα΄΄ β‰ˆ t + @test isisometric(vα΄΄; side = :right) + + N = @constinferred left_null(t; alg = :svd) + @test isisometric(N) + @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) + + N = @constinferred left_null(t; trunc = (; atol = 100 * eps(norm(t)))) + @test isisometric(N) + @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) + + Nα΄΄ = @constinferred right_null(t; alg = :svd) + @test isisometric(Nα΄΄; side = :right) + @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) + + Nα΄΄ = @constinferred right_null(t; trunc = (; atol = 100 * eps(norm(t)))) + @test isisometric(Nα΄΄; side = :right) + @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) + end + + # empty tensor + for T in eltypes, t in (rand(T, W, zerospace(V1)), rand(T, zerospace(V1), W)) + U, S, Vα΄΄ = @constinferred svd_full(t) + @test U * S * Vα΄΄ β‰ˆ t + @test isunitary(U) + @test isunitary(Vα΄΄) + + U, S, Vα΄΄ = @constinferred svd_compact(t) + @test U * S * Vα΄΄ β‰ˆ t + @test dim(U) == dim(S) == dim(Vα΄΄) == dim(t) == 0 + end + end + + @testset "truncated SVD" begin + for T in eltypes, + t in ( + randn(T, W, W), randn(T, W, W)', + randn(T, W, V4), randn(T, V4, W), + randn(T, W, V4)', randn(T, V4, W)', + DiagonalTensorMap(randn(T, reduceddim(V1)), V1), + ) + + @constinferred normalize!(t) + + U, S, Vα΄΄, Ο΅ = @constinferred svd_trunc(t; trunc = notrunc()) + @test U * S * Vα΄΄ β‰ˆ t + @test Ο΅ β‰ˆ 0 + @test isisometric(U) + @test isisometric(Vα΄΄; side = :right) + + # dimension of S is a float for IsingBimodule + nvals = round(Int, dim(domain(S)) / 2) + trunc = truncrank(nvals) + U1, S1, Vα΄΄1, Ο΅1 = @constinferred svd_trunc(t; trunc) + @test t * Vα΄΄1' β‰ˆ U1 * S1 + @test isisometric(U1) + @test isisometric(Vα΄΄1; side = :right) + @test norm(t - U1 * S1 * Vα΄΄1) β‰ˆ Ο΅1 atol = eps(real(T))^(4 / 5) + @test dim(domain(S1)) <= nvals + + Ξ» = minimum(diagview(S1)) + trunc = trunctol(; atol = Ξ» - 10eps(Ξ»)) + U2, S2, Vα΄΄2, Ο΅2 = @constinferred svd_trunc(t; trunc) + @test t * Vα΄΄2' β‰ˆ U2 * S2 + @test isisometric(U2) + @test isisometric(Vα΄΄2; side = :right) + @test norm(t - U2 * S2 * Vα΄΄2) β‰ˆ Ο΅2 atol = eps(real(T))^(4 / 5) + @test minimum(diagview(S1)) >= Ξ» + @test U2 β‰ˆ U1 + @test S2 β‰ˆ S1 + @test Vα΄΄2 β‰ˆ Vα΄΄1 + @test Ο΅1 β‰ˆ Ο΅2 + + trunc = truncspace(space(S2, 1)) + U3, S3, Vα΄΄3, Ο΅3 = @constinferred svd_trunc(t; trunc) + @test t * Vα΄΄3' β‰ˆ U3 * S3 + @test isisometric(U3) + @test isisometric(Vα΄΄3; side = :right) + @test norm(t - U3 * S3 * Vα΄΄3) β‰ˆ Ο΅3 atol = eps(real(T))^(4 / 5) + @test space(S3, 1) β‰Ύ space(S2, 1) + + for trunc in (truncerror(; atol = Ο΅2), truncerror(; rtol = Ο΅2 / norm(t))) + U4, S4, Vα΄΄4, Ο΅4 = @constinferred svd_trunc(t; trunc) + @test t * Vα΄΄4' β‰ˆ U4 * S4 + @test isisometric(U4) + @test isisometric(Vα΄΄4; side = :right) + @test norm(t - U4 * S4 * Vα΄΄4) β‰ˆ Ο΅4 atol = eps(real(T))^(4 / 5) + @test Ο΅4 ≀ Ο΅2 end - # Somehow moving these test before the previous one gives rise to errors - # with T=Float32 on x86 platforms. Is this an OpenBLAS issue? - VdV = V' * V - VdV = (VdV + VdV') / 2 - @test isposdef(VdV) + trunc = truncrank(nvals) & trunctol(; atol = Ξ» - 10eps(Ξ»)) + U5, S5, Vα΄΄5, Ο΅5 = @constinferred svd_trunc(t; trunc) + @test t * Vα΄΄5' β‰ˆ U5 * S5 + @test isisometric(U5) + @test isisometric(Vα΄΄5; side = :right) + @test norm(t - U5 * S5 * Vα΄΄5) β‰ˆ Ο΅5 atol = eps(real(T))^(4 / 5) + @test minimum(diagview(S5)) >= Ξ» + @test dim(domain(S5)) ≀ nvals + end + end + + @testset "Eigenvalue decomposition" begin + for T in eltypes, + t in ( + rand(T, V1, V1), rand(T, W, W), rand(T, W, W)', + DiagonalTensorMap(rand(T, reduceddim(V1)), V1), + ) - @test !isposdef(t) # unlikely for non-hermitian map - t2 = (t + t') + d, v = @constinferred eig_full(t) + @test t * v β‰ˆ v * d + + dβ€² = @constinferred eig_vals(t) + @test dβ€² β‰ˆ diagview(d) + @test dβ€² isa TensorKit.SectorVector + + vdv = project_hermitian!(v' * v) + @test @constinferred isposdef(vdv) + t isa DiagonalTensorMap || @test !isposdef(t) # unlikely for non-hermitian map + + nvals = round(Int, dim(domain(t)) / 2) + d, v = @constinferred eig_trunc(t; trunc = truncrank(nvals)) + @test t * v β‰ˆ v * d + @test dim(domain(d)) ≀ nvals + + t2 = @constinferred project_hermitian(t) D, V = eigen(t2) - VdV = V' * V - @test VdV β‰ˆ one(VdV) - DΜƒ, VΜƒ = @constinferred eigh(t2) + @test isisometric(V) + DΜƒ, VΜƒ = @constinferred eigh_full(t2) @test D β‰ˆ DΜƒ @test V β‰ˆ VΜƒ - Ξ» = minimum(minimum(real(LinearAlgebra.diag(b))) - for (c, b) in blocks(D)) + Ξ» = minimum(real, diagview(D)) @test cond(VΜƒ) β‰ˆ one(real(T)) @test isposdef(t2) == isposdef(Ξ») @test isposdef(t2 - Ξ» * one(t2) + 0.1 * one(t2)) @test !isposdef(t2 - Ξ» * one(t2) - 0.1 * one(t2)) + + d, v = @constinferred eigh_full(t2) + @test t2 * v β‰ˆ v * d + @test isunitary(v) + + dβ€² = @constinferred eigh_vals(t2) + @test dβ€² β‰ˆ diagview(d) + @test dβ€² isa TensorKit.SectorVector + + Ξ» = minimum(real, diagview(d)) + @test cond(v) β‰ˆ one(real(T)) + @test isposdef(t2) == isposdef(Ξ») + @test isposdef(t2 - Ξ» * one(t) + 0.1 * one(t2)) + @test !isposdef(t2 - Ξ» * one(t) - 0.1 * one(t2)) + + d, v = @constinferred eigh_trunc(t2; trunc = truncrank(nvals)) + @test t2 * v β‰ˆ v * d + @test dim(domain(d)) ≀ nvals + end + end + + @testset "Condition number and rank" begin + for T in eltypes, + t in ( + rand(T, W, W), rand(T, W, W)', + rand(T, W, V4), rand(T, V4, W), + rand(T, W, V4)', rand(T, V4, W)', + DiagonalTensorMap(rand(T, reduceddim(V1)), V1), + ) + + d1, d2 = dim(codomain(t)), dim(domain(t)) + r = rank(t) + @test r == min(d1, d2) + @test typeof(r) == typeof(d1) + M = left_null(t) + @test @constinferred(rank(M)) + r β‰ˆ d1 + Mα΄΄ = right_null(t) + @test rank(Mα΄΄) + r β‰ˆ d2 + end + for T in eltypes + u = unitary(T, V1 βŠ— V2, V1 βŠ— V2) + @test @constinferred(cond(u)) β‰ˆ one(real(T)) + @test @constinferred(rank(u)) == dim(V1 βŠ— V2) + + t = rand(T, zerospace(V1), W) + @test rank(t) == 0 + t2 = rand(T, zerospace(V1) * zerospace(V2), zerospace(V1) * zerospace(V2)) + @test rank(t2) == 0 + @test cond(t2) == 0.0 + end + for T in eltypes, t in (rand(T, W, W), rand(T, W, W)') + project_hermitian!(t) + vals = @constinferred LinearAlgebra.eigvals(t) + Ξ»max = maximum(s -> maximum(abs, s), values(vals)) + Ξ»min = minimum(s -> minimum(abs, s), values(vals)) + @test cond(t) β‰ˆ Ξ»max / Ξ»min + end + end + + @testset "Hermitian projections" begin + for T in eltypes, + t in ( + rand(T, V1, V1), rand(T, W, W), rand(T, W, W)', + DiagonalTensorMap(rand(T, reduceddim(V1)), V1), + ) + normalize!(t) + noisefactor = eps(real(T))^(3 / 4) + + th = (t + t') / 2 + ta = (t - t') / 2 + tc = copy(t) + + thβ€² = @constinferred project_hermitian(t) + @test ishermitian(thβ€²) + @test thβ€² β‰ˆ th + @test t == tc + th_approx = th + noisefactor * ta + @test !ishermitian(th_approx) || (T <: Real && t isa DiagonalTensorMap) + @test ishermitian(th_approx; atol = 10 * noisefactor) + + taβ€² = project_antihermitian(t) + @test isantihermitian(taβ€²) + @test taβ€² β‰ˆ ta + @test t == tc + ta_approx = ta + noisefactor * th + @test !isantihermitian(ta_approx) + @test isantihermitian(ta_approx; atol = 10 * noisefactor) || (T <: Real && t isa DiagonalTensorMap) + end + end + + @testset "Isometric projections" begin + for T in eltypes, + t in ( + randn(T, W, W), randn(T, W, W)', + randn(T, W, V4), randn(T, V4, W)', + ) + t2 = project_isometric(t) + @test isisometric(t2) + t3 = project_isometric(t2) + @test t3 β‰ˆ t2 # stability of the projection + @test t2 * (t2' * t) β‰ˆ t + + tc = similar(t) + t3 = @constinferred project_isometric!(copy!(tc, t), t2) + @test t3 === t2 + @test isisometric(t2) + + # test that t2 is closer to A then any other isometry + for k in 1:10 + Ξ΄t = randn!(similar(t)) + t3 = project_isometric(t + Ξ΄t / 100) + @test norm(t - t3) > norm(t - t2) + end end end end From 0048ec05adec1543a93c84b3297b43aa4bc3f51c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 13:43:55 +0100 Subject: [PATCH 186/206] get setup included correctly --- test/runtests.jl | 1 - test/test_A4.jl | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index f88fb64..6b48268 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,7 +15,6 @@ istestfile(fn) = endswith(fn, ".jl") && startswith(basename(fn), "test_") && !contains(fn, "setup") include("setup.jl") -using .TestSetup @time begin # tests in groups based on folder structure diff --git a/test/test_A4.jl b/test/test_A4.jl index 61569c1..0d4a9c0 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -7,6 +7,9 @@ using LinearAlgebra: LinearAlgebra const MTK = MultiTensorKit const TK = TensorKit +@isdefined TestSetup || include("setup.jl") +using .TestSetup + I = A4Object Istr = TensorKitSectors.type_repr(I) r = size(I) From 15df3302bae60cf9cbd5e6268ccd04a0ea607985 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 13:48:23 +0100 Subject: [PATCH 187/206] small fix --- test/test_A4.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 0d4a9c0..6d7e34e 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -7,7 +7,7 @@ using LinearAlgebra: LinearAlgebra const MTK = MultiTensorKit const TK = TensorKit -@isdefined TestSetup || include("setup.jl") +@isdefined(TestSetup) || include("setup.jl") using .TestSetup I = A4Object From ad628dc5e0934faa75d795fa55c5328a0cb61512 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 14:01:49 +0100 Subject: [PATCH 188/206] abstractvector dispatch --- test/setup.jl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/setup.jl b/test/setup.jl index 3e5b063..8c5d2a5 100644 --- a/test/setup.jl +++ b/test/setup.jl @@ -10,7 +10,7 @@ const MTK = MultiTensorKit Random.seed!(1234) -function unitarity_test(as::Vector{I}, bs::Vector{I},cs::Vector{I}) where {I <: BimoduleSector} # abstractvector? +function unitarity_test(as::V, bs::V, cs::V) where {V <: AbstractVector{<:BimoduleSector}} @assert all(a.j == b.i for a in as, b in bs) @assert all(b.j == c.i for b in bs, c in cs) @@ -19,12 +19,9 @@ function unitarity_test(as::Vector{I}, bs::Vector{I},cs::Vector{I}) where {I <: es = collect(intersect(βŠ—(a, b), map(dual, βŠ—(c, dual(d))))) fs = collect(intersect(βŠ—(b, c), map(dual, βŠ—(dual(d), a)))) Fblocks = Vector{Any}() - for e in es - for f in fs - Fs = Fsymbol(a, b, c, d, e, f) - push!(Fblocks, reshape(Fs, (size(Fs, 1) * size(Fs, 2), - size(Fs, 3) * size(Fs, 4)))) - end + for e in es, f in fs + Fs = Fsymbol(a, b, c, d, e, f) + push!(Fblocks, reshape(Fs, (size(Fs, 1) * size(Fs, 2), size(Fs, 3) * size(Fs, 4)))) end F = hvcat(length(fs), Fblocks...) isapprox(F' * F, one(F); atol = 1.0e-12, rtol = 1.0e-12) || return false From 8e37a8bc606f0e8638019b0ec0994796a8ab9ded Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 14:01:55 +0100 Subject: [PATCH 189/206] format test --- test/test_A4.jl | 142 ++++++++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 65 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 6d7e34e..e12bc33 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -163,7 +163,7 @@ end objects = collect(values(I)) for a in objects, b in objects a.j == b.i || continue # skip if not compatible - @test triangle_equation(a, b; atol=1e-12, rtol=1e-12) + @test triangle_equation(a, b; atol = 1.0e-12, rtol = 1.0e-12) end end @@ -176,7 +176,7 @@ end b.j == c.i || continue # skip if not compatible for d in objects c.j == d.i || continue # skip if not compatible - @test pentagon_equation(a, b, c, d; atol=1e-12, rtol=1e-12) + @test pentagon_equation(a, b, c, d; atol = 1.0e-12, rtol = 1.0e-12) end end end @@ -303,7 +303,7 @@ println("---------------------------------") end end - d = Dict{I,Int}() + d = Dict{I, Int}() for a in sectors(V), b in sectors(V) a.j == b.i || continue # skip if not compatible for c in a βŠ— b @@ -312,7 +312,7 @@ println("---------------------------------") end @test @constinferred(fuse(V, V)) == GradedSpace(d) @test @constinferred(flip(V)) == - Vect[I](conj(c) => dim(V, c) for c in sectors(V))' + Vect[I](conj(c) => dim(V, c) for c in sectors(V))' @test flip(V) β‰… V @test flip(V) β‰Ύ V @test flip(V) β‰Ώ V @@ -328,11 +328,13 @@ println("---------------------------------") end @timedtestset "HomSpace with $(TK.type_repr(Vect[I])) involving ($i, $j)" for i in 1:r, j in 1:r - V1, V2, V3, V4, V5 = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), # same as V1 - Vect[I]((i, j, 1) => 3), - Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j))) + V1, V2, V3, V4, V5 = ( + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), # same as V1 + Vect[I]((i, j, 1) => 3), + Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), + ) W = HomSpace(V1 βŠ— V2, V3 βŠ— V4 βŠ— V5) @test W == (V3 βŠ— V4 βŠ— V5 β†’ V1 βŠ— V2) @@ -362,9 +364,9 @@ println("---------------------------------") @test_throws BoundsError insertleftunit(W, 0) @test (V1 βŠ— V2 βŠ— rightunitspace(V2) ← V3 βŠ— V4 βŠ— V5) == - @constinferred(insertrightunit(W, 2)) + @constinferred(insertrightunit(W, 2)) @test (V1 βŠ— V2 ← leftunitspace(V3) βŠ— V3 βŠ— V4 βŠ— V5) == - @constinferred(insertleftunit(W, 3)) + @constinferred(insertleftunit(W, 3)) @test @constinferred(removeunit(insertleftunit(W, 3), 3)) == W @test_throws ArgumentError @constinferred(insertrightunit(one(V1) ← V1, 0)) # should I specify it's the other error? @test_throws ArgumentError insertleftunit(one(V1) ← V1, 0) @@ -470,7 +472,7 @@ println("---------------------------------------") end end # no planar trace tests - + @testset "Fusion tree $Istr: elementary artin braid" begin N = length(out) isdual = ntuple(n -> rand(Bool), N) @@ -488,14 +490,14 @@ println("---------------------------------------") d1 = d2 d2 = empty(d1) for (f1, coeff1) in d1 - for (f2, coeff2) in TK.artin_braid(f1, 3; inv=true) + for (f2, coeff2) in TK.artin_braid(f1, 3; inv = true) d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 end end d1 = d2 d2 = empty(d1) for (f1, coeff1) in d1 - for (f2, coeff2) in TK.artin_braid(f1, 2; inv=true) + for (f2, coeff2) in TK.artin_braid(f1, 2; inv = true) d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 end end @@ -504,7 +506,7 @@ println("---------------------------------------") if f1 == f @test coeff1 β‰ˆ 1 else - @test isapprox(coeff1, 0; atol=1.0e-12, rtol=1.0e-12) + @test isapprox(coeff1, 0; atol = 1.0e-12, rtol = 1.0e-12) end end end @@ -529,9 +531,11 @@ println("---------------------------------------") f2 = rand(collect(fusiontrees(out2, in2))) - @test dim(in1) * dim(in2) β‰ˆ sum(abs2(coeff) * dim(c) for c in in1 βŠ— in2 - for ΞΌ in 1:Nsymbol(in1, in2, c) - for (f, coeff) in TK.merge(f1, f2, c, ΞΌ)) + @test dim(in1) * dim(in2) β‰ˆ sum( + abs2(coeff) * dim(c) for c in in1 βŠ— in2 + for ΞΌ in 1:Nsymbol(in1, in2, c) + for (f, coeff) in TK.merge(f1, f2, c, ΞΌ) + ) # no merge and braid interplay tests end @@ -554,8 +558,8 @@ println("---------------------------------------") for n in 0:(2 * N) d = @constinferred TK.repartition(f1, f2, $n) @test dim(incoming) β‰ˆ - sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) - d2 = Dict{typeof((f1, f2)),valtype(d)}() + sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) + d2 = Dict{typeof((f1, f2)), valtype(d)}() for ((f1β€², f2β€²), coeff) in d for ((f1β€²β€², f2β€²β€²), coeff2) in TK.repartition(f1β€², f2β€², N) d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff2 * coeff @@ -565,7 +569,7 @@ println("---------------------------------------") if f1 == f1β€² && f2 == f2β€² @test coeff2 β‰ˆ 1 else - @test isapprox(coeff2, 0; atol=1.0e-12, rtol=1.0e-12) + @test isapprox(coeff2, 0; atol = 1.0e-12, rtol = 1.0e-12) end end end @@ -586,8 +590,8 @@ println("---------------------------------------") d = @constinferred transpose(f1, f2, p1, p2) @test dim(incoming) β‰ˆ - sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) - d2 = Dict{typeof((f1, f2)),valtype(d)}() + sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) + d2 = Dict{typeof((f1, f2)), valtype(d)}() for ((f1β€², f2β€²), coeff) in d dβ€² = transpose(f1β€², f2β€², ip1, ip2) for ((f1β€²β€², f2β€²β€²), coeff2) in dβ€² @@ -603,16 +607,18 @@ println("---------------------------------------") end end end - + @testset "Double fusion tree $Istr: planar trace" begin d1 = transpose(f1, f1, (N + 1, 1:N..., ((2N):-1:(N + 3))...), (N + 2,)) f1front, = TK.split(f1, N - 1) T = sectorscalartype(I) - d2 = Dict{typeof((f1front, f1front)),T}() + d2 = Dict{typeof((f1front, f1front)), T}() for ((f1β€², f2β€²), coeffβ€²) in d1 for ((f1β€²β€², f2β€²β€²), coeffβ€²β€²) in - TK.planar_trace(f1β€², f2β€², (2:N...,), (1, ((2N):-1:(N + 3))...), (N + 1,), - (N + 2,)) + TK.planar_trace( + f1β€², f2β€², (2:N...,), (1, ((2N):-1:(N + 3))...), (N + 1,), + (N + 2,) + ) coeff = coeffβ€² * coeffβ€²β€² d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff end @@ -816,27 +822,30 @@ println("---------------------------------------") @timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r isdiag = i == j - VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? - Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) - ) + VC = ( + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? + Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3), + ) - VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects + VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects - VM1 = (Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works - Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, # important that V4 is module-graded - Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) + VM1 = ( + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works + Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, # important that V4 is module-graded + Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), ) - VM2 = (Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here - Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, - Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) + VM2 = ( + Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here + Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, + Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), ) Vcol = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs @@ -862,7 +871,7 @@ println("---------------------------------------") next = @constinferred Nothing iterate(bs, state) b2 = @constinferred block(t, first(blocksectors(t))) @test b1 == b2 - @test eltype(bs) === Pair{typeof(c),typeof(b1)} + @test eltype(bs) === Pair{typeof(c), typeof(b1)} @test typeof(b1) === TK.blocktype(t) @test typeof(c) === sectortype(t) end @@ -1059,8 +1068,8 @@ println("---------------------------------------") for T in (Float32, ComplexF64) tA = rand(T, V1 βŠ— V2, V1 βŠ— V2) # rewritten for modules tB = rand(T, V4 βŠ— V5, V4 βŠ— V5) - tA = 3 // 2 * leftorth(tA; alg=TK.Polar())[1] - tB = 1 // 5 * leftorth(tB; alg=TK.Polar())[1] + tA = 3 // 2 * leftorth(tA; alg = TK.Polar())[1] + tB = 1 // 5 * leftorth(tB; alg = TK.Polar())[1] tC = rand(T, V1 βŠ— V2, V4 βŠ— V5) t = @constinferred sylvester(tA, tB, tC) @test codomain(t) == V1 βŠ— V2 @@ -1146,27 +1155,30 @@ println("---------------------------------------") @timedtestset "Factorizations with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r isdiag = i == j - VC = (Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? - Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3) - ) + VC = ( + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? + Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), + Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), + Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3), + ) - VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects + VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects - VM1 = (Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works - Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, # important that V4 is module-graded - Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) + VM1 = ( + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works + Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, # important that V4 is module-graded + Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), ) - VM2 = (Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here - Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, - Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1) + VM2 = ( + Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here + Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), + Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), + VM, + Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), ) Vs = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs @@ -1618,4 +1630,4 @@ println("---------------------------------------") end end end -end \ No newline at end of file +end From 46e45146433688fdd33ff891c0c565f79aa3e68f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 14:02:42 +0100 Subject: [PATCH 190/206] comment out TK tests --- test/test_A4.jl | 2892 +++++++++++++++++++++++------------------------ 1 file changed, 1446 insertions(+), 1446 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index e12bc33..016d29d 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -185,1449 +185,1449 @@ end ### start of TensorKit tests ### -println("---------------------------------") -println("| Multifusion space tests |") -println("---------------------------------") - -@timedtestset "Multifusion spaces " verbose = true begin - @timedtestset "GradedSpace: $(TK.type_repr(Vect[I]))" begin - gen = (values(I)[k] => (k + 1) for k in 1:length(values(I))) - - V = GradedSpace(gen) - @test eval(Meta.parse(type_repr(typeof(V)))) == typeof(V) - @test eval_show(V) == V - @test eval_show(V') == V' - @test V' == GradedSpace(gen; dual = true) - @test V == @constinferred GradedSpace(gen...) - @test V' == @constinferred GradedSpace(gen...; dual = true) - @test V == @constinferred GradedSpace(tuple(gen...)) - @test V' == @constinferred GradedSpace(tuple(gen...); dual = true) - @test V == @constinferred GradedSpace(Dict(gen)) - @test V' == @constinferred GradedSpace(Dict(gen); dual = true) - @test V == @inferred Vect[I](gen) - @test V' == @constinferred Vect[I](gen; dual = true) - @test V == @constinferred Vect[I](gen...) - @test V' == @constinferred Vect[I](gen...; dual = true) - @test V == @constinferred Vect[I](Dict(gen)) - @test V' == @constinferred Vect[I](Dict(gen); dual = true) - @test @constinferred(hash(V)) == hash(deepcopy(V)) != hash(V') - @test V == GradedSpace(reverse(collect(gen))...) - @test eval_show(V) == V - @test eval_show(typeof(V)) == typeof(V) - - @test dim(@constinferred(zerospace(V))) == 0 - - W = @constinferred GradedSpace(unit => 1 for unit in allunits(I)) - dict = Dict(unit => 1 for unit in allunits(I)) - @test W == GradedSpace(dict) - @test W == GradedSpace(push!(dict, randsector(I) => 0)) - @test @constinferred(zerospace(V)) == GradedSpace(unit => 0 for unit in allunits(I)) - randunit = rand(collect(allunits(I))) - @test_throws ArgumentError("Sector $(randunit) appears multiple times") GradedSpace(randunit => 1, randunit => 3) - - @test isunitspace(W) - @test @constinferred(unitspace(V)) == W == unitspace(typeof(V)) - @test_throws ArgumentError leftunitspace(V) - @test_throws ArgumentError rightunitspace(V) - @test eval_show(W) == W - - @test isa(V, VectorSpace) - @test isa(V, ElementarySpace) - @test isa(InnerProductStyle(V), HasInnerProduct) - @test isa(InnerProductStyle(V), EuclideanInnerProduct) - @test isa(V, GradedSpace) - @test isa(V, GradedSpace{I}) - @test @constinferred(dual(V)) == @constinferred(conj(V)) == @constinferred(adjoint(V)) != V - @test @constinferred(field(V)) == β„‚ - @test @constinferred(sectortype(V)) == I - slist = @constinferred sectors(V) - @test @constinferred(hassector(V, first(slist))) - @test @constinferred(dim(V)) == sum(dim(s) * dim(V, s) for s in slist) - @test @constinferred(reduceddim(V)) == sum(dim(V, s) for s in slist) - @constinferred dim(V, first(slist)) - - @test @constinferred(βŠ•(V, zerospace(V))) == V - @test @constinferred(βŠ•(V, V)) == Vect[I](c => 2dim(V, c) for c in sectors(V)) - @test @constinferred(βŠ•(V, V, V, V)) == Vect[I](c => 4dim(V, c) for c in sectors(V)) - @test @constinferred(βŠ•(V, unitspace(V))) == Vect[I](c => isunit(c) + dim(V, c) for c in sectors(V)) - @test @constinferred(fuse(V, unitspace(V))) == V - - @testset "$Istr ($i, $j) spaces" for i in 1:r, j in 1:r #TODO: look at these tests better - # space with a single sector - Wleft = @constinferred Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)) - Wright = @constinferred Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)) - WM = @constinferred Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) - WMop = @constinferred Vect[I]((j, i, label) => 1 for label in 1:MTK._numlabels(I, j, i)) - - @test leftunitspace(Wleft) == rightunitspace(Wleft) - @test leftunitspace(Wright) == rightunitspace(Wright) - @test @constinferred(leftunitspace(βŠ•(Wleft, WM))) == leftunitspace(Wleft) - @test @constinferred(leftunitspace(βŠ•(Wright, WMop))) == leftunitspace(Wright) - @test @constinferred(rightunitspace(βŠ•(Wright, WM))) == rightunitspace(Wright) - @test @constinferred(rightunitspace(βŠ•(Wleft, WMop))) == rightunitspace(Wleft) - - if i != j # some tests specialised for modules - - # sensible direct sums and fuses - ul, ur = unit(I(i, i, 1)), unit(I(j, j, 1)) - @test @constinferred(βŠ•(Wleft, WM)) == - Vect[I](c => 1 for c in sectors(V) if leftunit(c) == ul == rightunit(c) || (c.i == i && c.j == j)) - @test @constinferred(βŠ•(Wright, WMop)) == - Vect[I](c => 1 for c in sectors(V) if leftunit(c) == ur == rightunit(c) || (c.i == j && c.j == i)) - @test @constinferred(βŠ•(Wright, WM)) == - Vect[I](c => 1 for c in sectors(V) if rightunit(c) == ur == leftunit(c) || (c.i == i && c.j == j)) - @test @constinferred(βŠ•(Wleft, WMop)) == - Vect[I](c => 1 for c in sectors(V) if rightunit(c) == ul == leftunit(c) || (c.i == j && c.j == i)) - # round needed below because of numerical F-symbols not being integer when they should be - # although this test might be stupid, because I'm assuming integer qdims bc everything's a group or irrep on the diagonal - @test @constinferred(fuse(Wleft, WM)) == Vect[I](c => round(Int, dim(Wleft)) for c in sectors(WM)) # this might be wrong - @test @constinferred(fuse(Wright, WMop)) == Vect[I](c => round(Int, dim(Wright)) for c in sectors(WMop)) # same - - # less sensible fuse - @test @constinferred(fuse(Wleft, WMop)) == fuse(Wright, WM) == - Vect[I](c => 0 for c in sectors(V)) - - for W in [WM, WMop, Wright] - @test infimum(Wleft, W) == Vect[I](c => 0 for c in sectors(V)) - end - else - @test @constinferred(βŠ•(Wleft, Wright)) == - Vect[I](c => 2 for c in sectors(V) if c.i == c.j == i) - @test @constinferred(fuse(Wleft, WMop)) == fuse(Wright, WM) - end - - for W in [Wleft, Wright] - @test @constinferred(βŠ•(W, rightunitspace(W))) == - Vect[I](c => isunit(c) + dim(W, c) for c in sectors(W)) - @test @constinferred(fuse(W, rightunitspace(W))) == W - end - end - - d = Dict{I, Int}() - for a in sectors(V), b in sectors(V) - a.j == b.i || continue # skip if not compatible - for c in a βŠ— b - d[c] = get(d, c, 0) + dim(V, a) * dim(V, b) * Nsymbol(a, b, c) - end - end - @test @constinferred(fuse(V, V)) == GradedSpace(d) - @test @constinferred(flip(V)) == - Vect[I](conj(c) => dim(V, c) for c in sectors(V))' - @test flip(V) β‰… V - @test flip(V) β‰Ύ V - @test flip(V) β‰Ώ V - @test @constinferred(βŠ•(V, V)) == @constinferred supremum(V, βŠ•(V, V)) - @test V == @constinferred infimum(V, βŠ•(V, V)) - @test V β‰Ί βŠ•(V, V) - @test !(V ≻ βŠ•(V, V)) - - randlen = rand(1:length(values(I))) - s = rand(collect(values(I))[randlen:end]) # such that dim(V, s) > randlen - @test infimum(V, GradedSpace(s => randlen)) == GradedSpace(s => randlen) - @test_throws SpaceMismatch (βŠ•(V, V')) - end - - @timedtestset "HomSpace with $(TK.type_repr(Vect[I])) involving ($i, $j)" for i in 1:r, j in 1:r - V1, V2, V3, V4, V5 = ( - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), # same as V1 - Vect[I]((i, j, 1) => 3), - Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), - ) - W = HomSpace(V1 βŠ— V2, V3 βŠ— V4 βŠ— V5) - - @test W == (V3 βŠ— V4 βŠ— V5 β†’ V1 βŠ— V2) - @test W == (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5) - @test W' == (V1 βŠ— V2 β†’ V3 βŠ— V4 βŠ— V5) - @test eval(Meta.parse(sprint(show, W))) == W - @test eval(Meta.parse(sprint(show, typeof(W)))) == typeof(W) - @test spacetype(W) == typeof(V1) - @test sectortype(W) == sectortype(V1) - @test W[1] == V1 - @test W[2] == V2 - @test W[3] == V3' - @test W[4] == V4' - @test W[5] == V5' - - @test @constinferred(hash(W)) == hash(deepcopy(W)) != hash(W') - @test W == deepcopy(W) - @test W == @constinferred permute(W, ((1, 2), (3, 4, 5))) - @test permute(W, ((2, 4, 5), (3, 1))) == (V2 βŠ— V4' βŠ— V5' ← V3 βŠ— V1') - @test (V1 βŠ— V2 ← V1 βŠ— V2) == @constinferred TK.compose(W, W') - - @test (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 βŠ— rightunitspace(V5)) == - @constinferred(insertleftunit(W)) == - @constinferred(insertrightunit(W)) - @test @constinferred(removeunit(insertleftunit(W), $(numind(W) + 1))) == W - @test_throws BoundsError insertrightunit(W, 6) - @test_throws BoundsError insertleftunit(W, 0) - - @test (V1 βŠ— V2 βŠ— rightunitspace(V2) ← V3 βŠ— V4 βŠ— V5) == - @constinferred(insertrightunit(W, 2)) - @test (V1 βŠ— V2 ← leftunitspace(V3) βŠ— V3 βŠ— V4 βŠ— V5) == - @constinferred(insertleftunit(W, 3)) - @test @constinferred(removeunit(insertleftunit(W, 3), 3)) == W - @test_throws ArgumentError @constinferred(insertrightunit(one(V1) ← V1, 0)) # should I specify it's the other error? - @test_throws ArgumentError insertleftunit(one(V1) ← V1, 0) - end -end - -println("---------------------------------------") -println("| Multifusion fusion tree tests |") -println("---------------------------------------") - -@timedtestset "Fusion trees for $(TK.type_repr(I)) involving ($i, $j)" verbose = true for i in 1:r, j in 1:r - N = 6 - out = random_fusion(I, i, j, Val(N)) - isdual = ntuple(n -> rand(Bool), N) - in = rand(collect(βŠ—(out...))) # will be in π’žβ±Όβ±Ό with this choice of out - - numtrees = length(fusiontrees(out, in, isdual)) # will be 1 for i != j - @test numtrees == count(n -> true, fusiontrees(out, in, isdual)) - - it = @constinferred fusiontrees(out, in, isdual) - @constinferred Nothing iterate(it) - f, s = iterate(it) - @constinferred Nothing iterate(it, s) - @test f == @constinferred first(it) - @testset "Fusion tree $Istr: printing" begin - @test eval(Meta.parse(sprint(show, f))) == f - end - - C0, D0 = unit(I(i, i, 1)), unit(I(j, j, 1)) - @testset "Fusion tree $Istr: constructor properties" for u in (C0, D0) - @constinferred FusionTree((), u, (), (), ()) - @constinferred FusionTree((u,), u, (false,), (), ()) - @constinferred FusionTree((u, u), u, (false, false), (), (1,)) - @constinferred FusionTree((u, u, u), u, (false, false, false), (u,), (1, 1)) - @constinferred FusionTree( - (u, u, u, u), u, (false, false, false, false), (u, u), (1, 1, 1) - ) - @test_throws MethodError FusionTree((u, u, u), u, (false, false), (u,), (1, 1)) - @test_throws MethodError FusionTree( - (u, u, u), u, (false, false, false), (u, u), (1, 1) - ) - @test_throws MethodError FusionTree( - (u, u, u), u, (false, false, false), (u,), (1, 1, 1) - ) - @test_throws MethodError FusionTree((u, u, u), u, (false, false, false), (), (1,)) - - f = FusionTree((u, u, u), u, (false, false, false), (u,), (1, 1)) - @test sectortype(f) == I - @test length(f) == 3 - @test FusionStyle(f) == FusionStyle(I) - @test BraidingStyle(f) == BraidingStyle(I) - - if FusionStyle(I) isa UniqueFusion - @constinferred FusionTree((), u, ()) - @constinferred FusionTree((u,), u, (false,)) - @constinferred FusionTree((u, u), u, (false, false)) - @constinferred FusionTree((u, u, u), u) - if UnitStyle(I) isa SimpleUnit - @constinferred FusionTree((u, u, u, u)) - else - @test_throws ArgumentError FusionTree((u, u, u, u)) - end - @test_throws MethodError FusionTree((u, u), u, (false, false, false)) - else - @test_throws ArgumentError FusionTree((), u, ()) - @test_throws ArgumentError FusionTree((u,), u, (false,)) - @test_throws ArgumentError FusionTree((u, u), u, (false, false)) - @test_throws ArgumentError FusionTree((u, u, u), u) - if I <: ProductSector && UnitStyle(I) isa GenericUnit - @test_throws DomainError FusionTree((u, u, u, u)) - else - @test_throws ArgumentError FusionTree((u, u, u, u)) - end - end - end - - @testset "Fusion tree $Istr: insertat" begin - N = 4 - out2 = random_fusion(I, i, j, Val(N)) - in2 = rand(collect(βŠ—(out2...))) - isdual2 = ntuple(n -> rand(Bool), N) - f2 = rand(collect(fusiontrees(out2, in2, isdual2))) - for k in 1:N - out1 = random_fusion(I, i, j, Val(N)) # guaranteed good fusion - out1 = Base.setindex(out1, in2, i) # can lead to poor fusion - while isempty(βŠ—(out1...)) # TODO: better way to do this? - out1 = random_fusion(I, i, j, Val(N)) - out1 = Base.setindex(out1, in2, i) - end - in1 = rand(collect(βŠ—(out1...))) - isdual1 = ntuple(n -> rand(Bool), N) - isdual1 = Base.setindex(isdual1, false, k) - f1 = rand(collect(fusiontrees(out1, in1, isdual1))) - - trees = @constinferred TK.insertat(f1, k, f2) - @test norm(values(trees)) β‰ˆ 1 - - f1a, f1b = @constinferred TK.split(f1, $k) - @test length(TK.insertat(f1b, 1, f1a)) == 1 - @test first(TK.insertat(f1b, 1, f1a)) == (f1 => 1) - - # no braid tests for non-hardcoded example - end - end - # no planar trace tests - - @testset "Fusion tree $Istr: elementary artin braid" begin - N = length(out) - isdual = ntuple(n -> rand(Bool), N) - # no general artin braid test - - # not sure how useful this test is, it does the trivial braiding (choice of out) - f = rand(collect(it)) # in this case the 1 tree - d1 = TK.artin_braid(f, 2) # takes unit C0 with current out - d2 = empty(d1) - for (f1, coeff1) in d1 - for (f2, coeff2) in TK.artin_braid(f1, 3) - d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 - end - end - d1 = d2 - d2 = empty(d1) - for (f1, coeff1) in d1 - for (f2, coeff2) in TK.artin_braid(f1, 3; inv = true) - d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 - end - end - d1 = d2 - d2 = empty(d1) - for (f1, coeff1) in d1 - for (f2, coeff2) in TK.artin_braid(f1, 2; inv = true) - d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 - end - end - d1 = d2 - for (f1, coeff1) in d1 - if f1 == f - @test coeff1 β‰ˆ 1 - else - @test isapprox(coeff1, 0; atol = 1.0e-12, rtol = 1.0e-12) - end - end - end - - # no braiding and permuting test - @testset "Fusion tree $Istr: merging" begin - N = 3 - out1 = random_fusion(I, i, j, N) - out2 = random_fusion(I, i, j, N) - in1 = rand(collect(βŠ—(out1...))) - in2 = rand(collect(βŠ—(out2...))) - tp = βŠ—(in1, in2) # messy solution but it works - while isempty(tp) - out1 = random_fusion(I, i, j, Val(N)) - out2 = random_fusion(I, i, j, Val(N)) - in1 = rand(collect(βŠ—(out1...))) - in2 = rand(collect(βŠ—(out2...))) - tp = βŠ—(in1, in2) - end - - f1 = rand(collect(fusiontrees(out1, in1))) - f2 = rand(collect(fusiontrees(out2, in2))) - - - @test dim(in1) * dim(in2) β‰ˆ sum( - abs2(coeff) * dim(c) for c in in1 βŠ— in2 - for ΞΌ in 1:Nsymbol(in1, in2, c) - for (f, coeff) in TK.merge(f1, f2, c, ΞΌ) - ) - # no merge and braid interplay tests - end - - # double fusion tree tests - N = 4 - out = random_fusion(I, i, j, Val(N)) - out2 = random_fusion(I, i, j, Val(N)) - tp = βŠ—(out...) - tp2 = βŠ—(out2...) - while isempty(intersect(tp, tp2)) # guarantee fusion to same coloring - out2 = random_fusion(I, i, j, Val(N)) - tp2 = βŠ—(out2...) - end - @test_throws ArgumentError fusiontrees((out..., map(dual, out)...)) - incoming = rand(collect(intersect(tp, tp2))) - f1 = rand(collect(fusiontrees(out, incoming, ntuple(n -> rand(Bool), N)))) - f2 = rand(collect(fusiontrees(out2, incoming, ntuple(n -> rand(Bool), N)))) # no permuting - - @testset "Double fusion tree $Istr: repartitioning" begin - for n in 0:(2 * N) - d = @constinferred TK.repartition(f1, f2, $n) - @test dim(incoming) β‰ˆ - sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) - d2 = Dict{typeof((f1, f2)), valtype(d)}() - for ((f1β€², f2β€²), coeff) in d - for ((f1β€²β€², f2β€²β€²), coeff2) in TK.repartition(f1β€², f2β€², N) - d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff2 * coeff - end - end - for ((f1β€², f2β€²), coeff2) in d2 - if f1 == f1β€² && f2 == f2β€² - @test coeff2 β‰ˆ 1 - else - @test isapprox(coeff2, 0; atol = 1.0e-12, rtol = 1.0e-12) - end - end - end - end - - # no double fusion tree permutation tests - - # very slow for (1, 6), (3, 4), (3, 5), (3, 6), (5, 6), (6, 1), (6, 5), (7, 1), (7, 4), (7, 6) - @testset "Double fusion tree $Istr: transposition" begin - for n in 0:(2N) - i0 = rand(1:(2N)) - p = mod1.(i0 .+ (1:(2N)), 2N) - ip = mod1.(-i0 .+ (1:(2N)), 2N) - pβ€² = tuple(getindex.(Ref(vcat(1:N, (2N):-1:(N + 1))), p)...) - p1, p2 = pβ€²[1:n], pβ€²[(2N):-1:(n + 1)] - ipβ€² = tuple(getindex.(Ref(vcat(1:n, (2N):-1:(n + 1))), ip)...) - ip1, ip2 = ipβ€²[1:N], ipβ€²[(2N):-1:(N + 1)] - - d = @constinferred transpose(f1, f2, p1, p2) - @test dim(incoming) β‰ˆ - sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) - d2 = Dict{typeof((f1, f2)), valtype(d)}() - for ((f1β€², f2β€²), coeff) in d - dβ€² = transpose(f1β€², f2β€², ip1, ip2) - for ((f1β€²β€², f2β€²β€²), coeff2) in dβ€² - d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff2 * coeff - end - end - for ((f1β€², f2β€²), coeff2) in d2 - if f1 == f1β€² && f2 == f2β€² - @test coeff2 β‰ˆ 1 - else - @test abs(coeff2) < 1.0e-12 - end - end - end - end - - @testset "Double fusion tree $Istr: planar trace" begin - d1 = transpose(f1, f1, (N + 1, 1:N..., ((2N):-1:(N + 3))...), (N + 2,)) - f1front, = TK.split(f1, N - 1) - T = sectorscalartype(I) - d2 = Dict{typeof((f1front, f1front)), T}() - for ((f1β€², f2β€²), coeffβ€²) in d1 - for ((f1β€²β€², f2β€²β€²), coeffβ€²β€²) in - TK.planar_trace( - f1β€², f2β€², (2:N...,), (1, ((2N):-1:(N + 3))...), (N + 1,), - (N + 2,) - ) - coeff = coeffβ€² * coeffβ€²β€² - d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff - end - end - for ((f1_, f2_), coeff) in d2 - if (f1_, f2_) == (f1front, f1front) - @test coeff β‰ˆ dim(f1.coupled) / dim(f1front.coupled) - else - @test abs(coeff) < 1.0e-12 - end - end - end -end - -println("-------------------------------------------") -println("| Multifusion diagonal tensor tests |") -println("-------------------------------------------") - -V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) - -@timedtestset "DiagonalTensor" begin - @timedtestset "Basic properties and algebra" begin - for T in (Float32, Float64, ComplexF32, ComplexF64, BigFloat) - # constructors - t = @constinferred DiagonalTensorMap{T}(undef, V) - t = @constinferred DiagonalTensorMap(rand(T, reduceddim(V)), V) - t2 = @constinferred DiagonalTensorMap{T}(undef, space(t)) - @test space(t2) == space(t) - @test_throws ArgumentError DiagonalTensorMap{T}(undef, V^2 ← V) - t2 = @constinferred DiagonalTensorMap{T}(undef, domain(t)) - @test space(t2) == space(t) - @test_throws ArgumentError DiagonalTensorMap{T}(undef, V^2) - # properties - @test @constinferred(hash(t)) == hash(deepcopy(t)) - @test scalartype(t) == T - @test codomain(t) == ProductSpace(V) - @test domain(t) == ProductSpace(V) - @test space(t) == (V ← V) - @test space(t') == (V ← V) - @test dim(t) == dim(space(t)) - # blocks - bs = @constinferred blocks(t) - (c, b1), state = @constinferred Nothing iterate(bs) - @test c == first(blocksectors(V ← V)) - next = @constinferred Nothing iterate(bs, state) - b2 = @constinferred block(t, first(blocksectors(t))) - @test b1 == b2 - @test eltype(bs) === Pair{typeof(c), typeof(b1)} - @test typeof(b1) === TensorKit.blocktype(t) - # basic linear algebra - @test isa(@constinferred(norm(t)), real(T)) - @test norm(t)^2 β‰ˆ dot(t, t) - Ξ± = rand(T) - @test norm(Ξ± * t) β‰ˆ abs(Ξ±) * norm(t) - @test norm(t + t, 2) β‰ˆ 2 * norm(t, 2) - @test norm(t + t, 1) β‰ˆ 2 * norm(t, 1) - @test norm(t + t, Inf) β‰ˆ 2 * norm(t, Inf) - p = 3 * rand(Float64) - @test norm(t + t, p) β‰ˆ 2 * norm(t, p) - @test norm(t) β‰ˆ norm(t') - - @test t == @constinferred(TensorMap(t)) - @test norm(t + TensorMap(t)) β‰ˆ 2 * norm(t) - - @test norm(zerovector!(t)) == 0 - @test norm(one!(t)) β‰ˆ sqrt(dim(V)) - @test one!(t) == id(V) - if T != BigFloat # seems broken for now - @test norm(one!(t) - id(V)) == 0 - end - - t1 = DiagonalTensorMap(rand(T, reduceddim(V)), V) - t2 = DiagonalTensorMap(rand(T, reduceddim(V)), V) - t3 = DiagonalTensorMap(rand(T, reduceddim(V)), V) - Ξ± = rand(T) - Ξ² = rand(T) - @test @constinferred(dot(t1, t2)) β‰ˆ conj(dot(t2, t1)) - @test dot(t2, t1) β‰ˆ conj(dot(t2', t1')) - @test dot(t3, Ξ± * t1 + Ξ² * t2) β‰ˆ Ξ± * dot(t3, t1) + Ξ² * dot(t3, t2) - end - end - - @timedtestset "Basic linear algebra: test via conversion" begin - for T in (Float32, ComplexF64) - t1 = DiagonalTensorMap(rand(T, reduceddim(V)), V) - t2 = DiagonalTensorMap(rand(T, reduceddim(V)), V) - @test norm(t1, 2) β‰ˆ norm(convert(TensorMap, t1), 2) - @test dot(t2, t1) β‰ˆ dot(convert(TensorMap, t2), convert(TensorMap, t1)) - Ξ± = rand(T) - @test convert(TensorMap, Ξ± * t1) β‰ˆ Ξ± * convert(TensorMap, t1) - @test convert(TensorMap, t1') β‰ˆ convert(TensorMap, t1)' - @test convert(TensorMap, t1 + t2) β‰ˆ convert(TensorMap, t1) + convert(TensorMap, t2) - end - end - @timedtestset "Real and imaginary parts" begin - for T in (Float64, ComplexF64, ComplexF32) - t = DiagonalTensorMap(rand(T, reduceddim(V)), V) - - tr = @constinferred real(t) - @test scalartype(tr) <: Real - @test real(convert(TensorMap, t)) == convert(TensorMap, tr) - - ti = @constinferred imag(t) - @test scalartype(ti) <: Real - @test imag(convert(TensorMap, t)) == convert(TensorMap, ti) - - tc = @inferred complex(t) - @test scalartype(tc) <: Complex - @test complex(convert(TensorMap, t)) == convert(TensorMap, tc) - - tc2 = @inferred complex(tr, ti) - @test tc2 β‰ˆ tc - end - end - @timedtestset "Tensor conversion" begin - t = @constinferred DiagonalTensorMap(undef, V) - rand!(t.data) - # element type conversion - tc = complex(t) - @test convert(typeof(tc), t) == tc - @test typeof(convert(typeof(tc), t)) == typeof(tc) - # to and from generic TensorMap - td = DiagonalTensorMap(TensorMap(t)) - @test t == td - @test typeof(td) == typeof(t) - end - @timedtestset "Trace, Multiplication and inverse" begin - t1 = DiagonalTensorMap(rand(Float64, reduceddim(V)), V) - t2 = DiagonalTensorMap(rand(ComplexF64, reduceddim(V)), V) - @test tr(TensorMap(t1)) == @constinferred tr(t1) - @test tr(TensorMap(t2)) == @constinferred tr(t2) - @test TensorMap(@constinferred t1 * t2) β‰ˆ TensorMap(t1) * TensorMap(t2) - @test TensorMap(@constinferred t1 \ t2) β‰ˆ TensorMap(t1) \ TensorMap(t2) - @test TensorMap(@constinferred t1 / t2) β‰ˆ TensorMap(t1) / TensorMap(t2) - @test TensorMap(@constinferred inv(t1)) β‰ˆ inv(TensorMap(t1)) - @test TensorMap(@constinferred pinv(t1)) β‰ˆ pinv(TensorMap(t1)) - @test all( - Base.Fix2(isa, DiagonalTensorMap), (t1 * t2, t1 \ t2, t1 / t2, inv(t1), pinv(t1)) - ) - # no V * V' * V ← V or V^2 ← V tests due to Nsymbol erroring where fusion is forbidden - end - @timedtestset "Tensor contraction " for i in 1:r - W = Vect[I]((i, i, label) => 2 for label in 1:MTK._numlabels(I, i, i)) - - d = DiagonalTensorMap(rand(ComplexF64, reduceddim(W)), W) - t = TensorMap(d) - A = randn(ComplexF64, W βŠ— W' βŠ— W, W) - B = randn(ComplexF64, W βŠ— W' βŠ— W, W βŠ— W') # empty for modules so untested - - @planar E1[-1 -2 -3; -4 -5] := B[-1 -2 -3; 1 -5] * d[1; -4] - @planar E2[-1 -2 -3; -4 -5] := B[-1 -2 -3; 1 -5] * t[1; -4] - @test E1 β‰ˆ E2 - @planar E1[-1 -2 -3; -4 -5] = B[-1 -2 -3; -4 1] * d'[-5; 1] - @planar E2[-1 -2 -3; -4 -5] = B[-1 -2 -3; -4 1] * t'[-5; 1] - @test E1 β‰ˆ E2 - @planar E1[-1 -2 -3; -4 -5] = B[1 -2 -3; -4 -5] * d[-1; 1] - @planar E2[-1 -2 -3; -4 -5] = B[1 -2 -3; -4 -5] * t[-1; 1] - @test E1 β‰ˆ E2 - @planar E1[-1 -2 -3; -4 -5] = B[-1 1 -3; -4 -5] * d[1; -2] - @planar E2[-1 -2 -3; -4 -5] = B[-1 1 -3; -4 -5] * t[1; -2] - @test E1 β‰ˆ E2 - @planar E1[-1 -2 -3; -4 -5] = B[-1 -2 1; -4 -5] * d'[-3; 1] - @planar E2[-1 -2 -3; -4 -5] = B[-1 -2 1; -4 -5] * t'[-3; 1] - @test E1 β‰ˆ E2 - end - @timedtestset "Tensor functions" begin - for T in (Float64, ComplexF64) - d = DiagonalTensorMap(rand(T, reduceddim(V)), V) - # rand is important for positive numbers in the real case, for log and sqrt - t = TensorMap(d) - @test @constinferred exp(d) β‰ˆ exp(t) - @test @constinferred log(d) β‰ˆ log(t) - @test @constinferred sqrt(d) β‰ˆ sqrt(t) - @test @constinferred sin(d) β‰ˆ sin(t) - @test @constinferred cos(d) β‰ˆ cos(t) - @test @constinferred tan(d) β‰ˆ tan(t) - @test @constinferred cot(d) β‰ˆ cot(t) - @test @constinferred sinh(d) β‰ˆ sinh(t) - @test @constinferred cosh(d) β‰ˆ cosh(t) - @test @constinferred tanh(d) β‰ˆ tanh(t) - @test @constinferred coth(d) β‰ˆ coth(t) - @test @constinferred asin(d) β‰ˆ asin(t) - @test @constinferred acos(d) β‰ˆ acos(t) - @test @constinferred atan(d) β‰ˆ atan(t) - @test @constinferred acot(d) β‰ˆ acot(t) - @test @constinferred asinh(d) β‰ˆ asinh(t) - @test @constinferred acosh(one(d) + d) β‰ˆ acosh(one(t) + t) - @test @constinferred atanh(d) β‰ˆ atanh(t) - @test @constinferred acoth(one(t) + d) β‰ˆ acoth(one(d) + t) - end - end -end - -# no conversion tests because no fusion tensor -# no permute tests: NoBraiding() - -println("---------------------------------------") -println("Tensors with symmetry: $Istr") -println("---------------------------------------") - -@timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r - isdiag = i == j - - VC = ( - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? - Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3), - ) - - VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects - - VM1 = ( - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works - Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, # important that V4 is module-graded - Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), - ) - - VM2 = ( - Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here - Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, - Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), - ) - - Vcol = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs - - for V in Vcol # TODO: add enumerate to keep track of potential erroring space - V1, V2, V3, V4, V5 = V - @timedtestset "Basic tensor properties" begin - W = isdiag ? V1 βŠ— V2 βŠ— V3 βŠ— V4 βŠ— V5 : V3 βŠ— V4 βŠ— V5 # fusion matters - for T in (Int, Float32, Float64, ComplexF32, ComplexF64, BigFloat) - t = @constinferred zeros(T, W) # empty for i != j b/c blocks are module-graded - @test @constinferred(hash(t)) == hash(deepcopy(t)) - @test scalartype(t) == T - @test norm(t) == 0 - @test codomain(t) == W - @test space(t) == (W ← one(W)) - @test domain(t) == one(W) - @test typeof(t) == TensorMap{T, spacetype(t), length(W), 0, Vector{T}} - # blocks - bs = @constinferred blocks(t) - if !isempty(bs) - (c, b1), state = @constinferred Nothing iterate(bs) # errors if fusion gives empty data - # @test c == first(blocksectors(W)) # unit doesn't have label 1 - next = @constinferred Nothing iterate(bs, state) - b2 = @constinferred block(t, first(blocksectors(t))) - @test b1 == b2 - @test eltype(bs) === Pair{typeof(c), typeof(b1)} - @test typeof(b1) === TK.blocktype(t) - @test typeof(c) === sectortype(t) - end - end - end - - @timedtestset "Tensor Dict conversion" begin - W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # rewritten to be compatible with module fusion - for T in (Int, Float32, ComplexF64) - t = @constinferred rand(T, W) - d = convert(Dict, t) - @test t == convert(TensorMap, d) - end - end - - @timedtestset "Basic linear algebra" begin - W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 - for T in (Float32, ComplexF64) - t = @constinferred rand(T, W) # fusion matters here - @test scalartype(t) == T - @test space(t) == W - @test space(t') == W' - @test dim(t) == dim(space(t)) - @test codomain(t) == codomain(W) - @test domain(t) == domain(W) - # blocks for adjoint - bs = @constinferred blocks(t') - (c, b1), state = @constinferred Nothing iterate(bs) - @test c == first(blocksectors(W')) - next = @constinferred Nothing iterate(bs, state) - b2 = @constinferred block(t', first(blocksectors(t'))) - @test b1 == b2 - @test eltype(bs) === Pair{typeof(c), typeof(b1)} - @test typeof(b1) === TensorKit.blocktype(t') - @test typeof(c) === sectortype(t) - # linear algebra - @test isa(@constinferred(norm(t)), real(T)) - @test norm(t)^2 β‰ˆ dot(t, t) - Ξ± = rand(T) - @test norm(Ξ± * t) β‰ˆ abs(Ξ±) * norm(t) - @test norm(t + t, 2) β‰ˆ 2 * norm(t, 2) - @test norm(t + t, 1) β‰ˆ 2 * norm(t, 1) - @test norm(t + t, Inf) β‰ˆ 2 * norm(t, Inf) - p = 3 * rand(Float64) - @test norm(t + t, p) β‰ˆ 2 * norm(t, p) - @test norm(t) β‰ˆ norm(t') - - t2 = @constinferred rand!(similar(t)) - Ξ² = rand(T) - @test @constinferred(dot(Ξ² * t2, Ξ± * t)) β‰ˆ conj(Ξ²) * Ξ± * conj(dot(t, t2)) - @test dot(t2, t) β‰ˆ conj(dot(t, t2)) - @test dot(t2, t) β‰ˆ conj(dot(t2', t')) - @test dot(t2, t) β‰ˆ dot(t', t2') - - if !isempty(blocksectors(V2 βŠ— V1)) - i1 = @constinferred(isomorphism(T, V1 βŠ— V2, V2 βŠ— V1)) # can't reverse fusion here when modules are involved - i2 = @constinferred(isomorphism(Vector{T}, V2 βŠ— V1, V1 βŠ— V2)) - @test i1 * i2 == @constinferred(id(T, V1 βŠ— V2)) - @test i2 * i1 == @constinferred(id(Vector{T}, V2 βŠ— V1)) - end - - w = @constinferred isometry(T, V1 βŠ— (rightunitspace(V1) βŠ• rightunitspace(V1)), V1) - @test dim(w) == 2 * dim(V1 ← V1) - @test w' * w == id(Vector{T}, V1) - @test w * w' == (w * w')^2 - end - end - - @timedtestset "Trivial space insertion and removal" begin - W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 - for T in (Float32, ComplexF64) - t = @constinferred rand(T, W) # fusion matters here - t2 = @constinferred insertleftunit(t) - @test t2 == @constinferred insertrightunit(t) - @test space(t2) == insertleftunit(space(t)) - @test @constinferred(removeunit(t2, $(numind(t2)))) == t - t3 = @constinferred insertleftunit(t; copy = true) - @test t3 == @constinferred insertrightunit(t; copy = true) - @test @constinferred(removeunit(t3, $(numind(t3)))) == t - - @test numind(t2) == numind(t) + 1 - @test scalartype(t2) === T - @test t.data === t2.data - - @test t.data !== t3.data - for (c, b) in blocks(t) - @test b == block(t3, c) - end - - t4 = @constinferred insertrightunit(t, 3; dual = true) - @test numin(t4) == numin(t) + 1 && numout(t4) == numout(t) - for (c, b) in blocks(t) - @test b == block(t4, c) - end - @test @constinferred(removeunit(t4, 4)) == t - - t5 = @constinferred insertleftunit(t, 4; dual = true) - @test numin(t5) == numin(t) + 1 && numout(t5) == numout(t) - for (c, b) in blocks(t) - @test b == block(t5, c) - end - @test @constinferred(removeunit(t5, 4)) == t - end - end - - @timedtestset "Tensor conversion" begin - W = V1 βŠ— V2 - t = @constinferred randn(W ← W) # fusion matters here - @test typeof(convert(TensorMap, t')) == typeof(t) - tc = complex(t) - @test convert(typeof(tc), t) == tc - @test typeof(convert(typeof(tc), t)) == typeof(tc) - @test typeof(convert(typeof(tc), t')) == typeof(tc) - @test Base.promote_typeof(t, tc) == typeof(tc) - @test Base.promote_typeof(tc, t) == typeof(tc + t) - end - - @timedtestset "Full trace: test self-consistency" begin - t = rand(ComplexF64, V1 βŠ— V2 ← V1 βŠ— V2) # avoid permutes - ss = @constinferred tr(t) - @test conj(ss) β‰ˆ tr(t') - @planar s2 = t[a b; a b] - @planar t3[a; b] := t[a c; b c] - @planar s3 = t3[a; a] - - @test ss β‰ˆ s2 - @test ss β‰ˆ s3 - end - - @timedtestset "Partial trace: test self-consistency" begin - t = rand(ComplexF64, V3 βŠ— V4 βŠ— V5 ← V3 βŠ— V4 βŠ— V5) # compatible with module fusion - @planar t2[a; b] := t[c a d; c b d] - @planar t4[a b; c d] := t[e a b; e c d] - @planar t5[a; b] := t4[a c; b c] - @test t2 β‰ˆ t5 - end - - @timedtestset "Trace and contraction" begin #TODO: find some version of this that works for off-diagonal case - t1 = rand(ComplexF64, V3 βŠ— V4 βŠ— V5) - t2 = rand(ComplexF64, V3 βŠ— V4 βŠ— V5) - t3 = t1 βŠ— t2' - # if all(a.i != a.j for a in blocksectors(t3)) - # replace!(x -> rand(ComplexF64), t3.data) # otherwise full of zeros in off-diagonal case - # end - if all(a.i == a.j for a in blocksectors(t3)) - @planar ta[b; a] := conj(t2[x, a, y]) * t1[x, b, y] # works for diagonal case - @planar tb[a; b] := t3[x a y; x b y] - @test ta β‰ˆ tb - end - end - - @timedtestset "Multiplication of isometries: test properties" begin - W2 = V4 βŠ— V5 - W1 = W2 βŠ— (rightunitspace(V5) βŠ• rightunitspace(V5)) - for T in (Float64, ComplexF64) - t1 = randisometry(T, W1, W2) - t2 = randisometry(T, W2 ← W2) - @test isisometric(t1) - @test isunitary(t2) - P = t1 * t1' - @test P * P β‰ˆ P - end - end - - @timedtestset "Multiplication and inverse: test compatibility" begin - W1 = V1 βŠ— V2 - W2 = V3 βŠ— V4 βŠ— V5 - for T in (Float64, ComplexF64) - t1 = rand(T, W1, W1) - t2 = rand(T, W2 ← W2) - t = rand(T, W1, W2) - @test t1 * (t1 \ t) β‰ˆ t - @test (t / t2) * t2 β‰ˆ t - @test t1 \ one(t1) β‰ˆ inv(t1) - @test one(t1) / t1 β‰ˆ pinv(t1) - @test_throws SpaceMismatch inv(t) - @test_throws SpaceMismatch t2 \ t - @test_throws SpaceMismatch t / t1 - tp = pinv(t) * t - @test tp β‰ˆ tp * tp - end - end - - @timedtestset "diag/diagm" begin - W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 - t = randn(ComplexF64, W) - d = LinearAlgebra.diag(t) - D = LinearAlgebra.diagm(codomain(t), domain(t), d) - @test LinearAlgebra.isdiag(D) - @test LinearAlgebra.diag(D) == d - end - - @timedtestset "Sylvester equation" begin - for T in (Float32, ComplexF64) - tA = rand(T, V1 βŠ— V2, V1 βŠ— V2) # rewritten for modules - tB = rand(T, V4 βŠ— V5, V4 βŠ— V5) - tA = 3 // 2 * leftorth(tA; alg = TK.Polar())[1] - tB = 1 // 5 * leftorth(tB; alg = TK.Polar())[1] - tC = rand(T, V1 βŠ— V2, V4 βŠ— V5) - t = @constinferred sylvester(tA, tB, tC) - @test codomain(t) == V1 βŠ— V2 - @test domain(t) == V4 βŠ— V5 - @test norm(tA * t + t * tB + tC) < - (norm(tA) + norm(tB) + norm(tC)) * eps(real(T))^(2 / 3) - end - end - - @timedtestset "Tensor product: test via norm preservation" begin # OOMs over here with full spaces - for T in (Float32, ComplexF64) - if !isempty(blocksectors(V2 βŠ— V1)) - t1 = rand(T, V2 βŠ— V3 βŠ— V1, V1 βŠ— V2) - t2 = rand(T, V2 βŠ— V1 βŠ— V3, V1 βŠ— V1) - else - t1 = rand(T, V3 βŠ— V4 βŠ— V5, V1 βŠ— V2) - t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') - end - t = @constinferred (t1 βŠ— t2) - @test norm(t) β‰ˆ norm(t1) * norm(t2) - end - end - - # TODO: should this test exist? - @timedtestset "Tensor product: test via tensor contraction" begin - # W = V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2 - W = V4 ← V1 βŠ— V2 # less costly - for T in (Float32, ComplexF64) - if !isdiag - t1 = rand(T, W) - t2 = rand(T, V4' ← V2' βŠ— V1') - # t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') # same as previous test - # @planar tβ€²[1 2 3 6 7 8; 4 5 9 10] := t1[1 2 3; 4 5] * t2[6 7 8; 9 10] - @planar tβ€²[1 4; 2 3 5 6] := t1[1; 2 3] * t2[4; 5 6] - else - t1 = rand(T, V2 βŠ— V3, V1) - t2 = rand(T, V2, V1 βŠ— V3) - @planar tβ€²[1 2 4; 3 5 6] := t1[1 2; 3] * t2[4; 5 6] - end - t = @constinferred (t1 βŠ— t2) - @test t β‰ˆ tβ€² - end - end - end - - @timedtestset "Tensor absorption" begin - # absorbing small into large - if !isempty(blocksectors(V2 βŠ— V3)) - t1 = zeros(V1 βŠ• V1, V2 βŠ— V3) - t2 = rand(V1, V2 βŠ— V3) - else - t1 = zeros(V1 βŠ• V2, V3 βŠ— V4 βŠ— V5) - t2 = rand(V1, V3 βŠ— V4 βŠ— V5) - end - t3 = @constinferred absorb(t1, t2) - @test norm(t3) β‰ˆ norm(t2) - @test norm(t1) == 0 - t4 = @constinferred absorb!(t1, t2) - @test t1 === t4 - @test t3 β‰ˆ t4 - - # absorbing large into small - if !isempty(blocksectors(V2 βŠ— V3)) - t1 = rand(V1 βŠ• V1, V2 βŠ— V3) - t2 = zeros(V1, V2 βŠ— V3) - else - t1 = rand(V1 βŠ• V2, V3 βŠ— V4 βŠ— V5) - t2 = zeros(V1, V3 βŠ— V4 βŠ— V5) - end - t3 = @constinferred absorb(t2, t1) - @test norm(t3) < norm(t1) - @test norm(t2) == 0 - t4 = @constinferred absorb!(t2, t1) - @test t2 === t4 - @test t3 β‰ˆ t4 - end -end - -println("---------------------------------------") -println("Factorizations with symmetry: $Istr") -println("---------------------------------------") - -@timedtestset "Factorizations with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r - isdiag = i == j - - VC = ( - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? - Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), - Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), - Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3), - ) - - VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects - - VM1 = ( - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works - Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, # important that V4 is module-graded - Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), - ) - - VM2 = ( - Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here - Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), - Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - VM, - Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), - ) - - Vs = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs - - # some fail for (2, 2), (3, 3), (6, 6) - # rightorth RQ(pos) and Polar (fail) for 2nd space - # leftorth with QL(pos) and Polar for 1st space - # leftnull QR for 1st space - # cond and rank leftnull for 1st space - - # factorization tests require equal objects in blocksectors of domain and codomain, so just put them all - # FIXME: not sure if still needed - # VC_all = fill(Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), 5) - - # VM1_all = (Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - # VM, - # Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - # VM, - # Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 2) - # ) - - # VM2_all = (VM, - # Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), - # Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), - # VM, - # Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 2) - # ) - - # fact_Vs = (i != j) ? (VM1_all, VM2_all) : (VC_all,) - - @timedtestset "Factorization" for V in Vs - V1, V2, V3, V4, V5 = V - W = V1 βŠ— V2 - @assert !isempty(blocksectors(W)) - @assert !isempty(intersect(blocksectors(V4), blocksectors(W))) - - @testset "QR decomposition" begin - for T in eltypes, - t in ( - rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', - DiagonalTensorMap(rand(T, reduceddim(V1)), V1), - ) - - Q, R = @constinferred qr_full(t) - @test Q * R β‰ˆ t - @test isunitary(Q) - - Q, R = @constinferred qr_compact(t) - @test Q * R β‰ˆ t - @test isisometric(Q) - - Q, R = @constinferred left_orth(t) - @test Q * R β‰ˆ t - @test isisometric(Q) - - N = @constinferred qr_null(t) - @test isisometric(N) - @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) - - N = @constinferred left_null(t) - @test isisometric(N) - @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) - end - - # empty tensor - for T in eltypes - t = rand(T, V1 βŠ— V2, zerospace(V1)) - - Q, R = @constinferred qr_full(t) - @test Q * R β‰ˆ t - @test isunitary(Q) - @test dim(R) == dim(t) == 0 - - Q, R = @constinferred qr_compact(t) - @test Q * R β‰ˆ t - @test isisometric(Q) - @test dim(Q) == dim(R) == dim(t) - - Q, R = @constinferred left_orth(t) - @test Q * R β‰ˆ t - @test isisometric(Q) - @test dim(Q) == dim(R) == dim(t) - - N = @constinferred qr_null(t) - @test isunitary(N) - @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) - end - end - - @testset "LQ decomposition" begin - for T in eltypes, - t in ( - rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', - DiagonalTensorMap(rand(T, reduceddim(V1)), V1), - ) - - L, Q = @constinferred lq_full(t) - @test L * Q β‰ˆ t - @test isunitary(Q) - - L, Q = @constinferred lq_compact(t) - @test L * Q β‰ˆ t - @test isisometric(Q; side = :right) - - L, Q = @constinferred right_orth(t) - @test L * Q β‰ˆ t - @test isisometric(Q; side = :right) - - Nα΄΄ = @constinferred lq_null(t) - @test isisometric(Nα΄΄; side = :right) - @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) - end - - for T in eltypes - # empty tensor - t = rand(T, zerospace(V1), V1 βŠ— V2) - - L, Q = @constinferred lq_full(t) - @test L * Q β‰ˆ t - @test isunitary(Q) - @test dim(L) == dim(t) == 0 - - L, Q = @constinferred lq_compact(t) - @test L * Q β‰ˆ t - @test isisometric(Q; side = :right) - @test dim(Q) == dim(L) == dim(t) - - L, Q = @constinferred right_orth(t) - @test L * Q β‰ˆ t - @test isisometric(Q; side = :right) - @test dim(Q) == dim(L) == dim(t) - - Nα΄΄ = @constinferred lq_null(t) - @test isunitary(Nα΄΄) - @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) - end - end - - @testset "Polar decomposition" begin - for T in eltypes, - t in ( - rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', - DiagonalTensorMap(rand(T, reduceddim(V1)), V1), - ) - - @assert domain(t) β‰Ύ codomain(t) - w, p = @constinferred left_polar(t) - @test w * p β‰ˆ t - @test isisometric(w) - @test isposdef(p) - - w, p = @constinferred left_orth(t; alg = :polar) - @test w * p β‰ˆ t - @test isisometric(w) - end - - for T in eltypes, - t in (rand(T, W, W), rand(T, W, W)', rand(T, V4, W), rand(T, W, V4)') - - @assert codomain(t) β‰Ύ domain(t) - p, wα΄΄ = @constinferred right_polar(t) - @test p * wα΄΄ β‰ˆ t - @test isisometric(wα΄΄; side = :right) - @test isposdef(p) - - p, wα΄΄ = @constinferred right_orth(t; alg = :polar) - @test p * wα΄΄ β‰ˆ t - @test isisometric(wα΄΄; side = :right) - end - end - - @testset "SVD" begin - for T in eltypes, - t in ( - rand(T, W, W), rand(T, W, W)', - rand(T, W, V4), rand(T, V4, W), - rand(T, W, V4)', rand(T, V4, W)', - DiagonalTensorMap(rand(T, reduceddim(V1)), V1), - ) - - u, s, vα΄΄ = @constinferred svd_full(t) - @test u * s * vα΄΄ β‰ˆ t - @test isunitary(u) - @test isunitary(vα΄΄) - - u, s, vα΄΄ = @constinferred svd_compact(t) - @test u * s * vα΄΄ β‰ˆ t - @test isisometric(u) - @test isposdef(s) - @test isisometric(vα΄΄; side = :right) - - sβ€² = @constinferred svd_vals(t) - @test sβ€² β‰ˆ diagview(s) - @test sβ€² isa TensorKit.SectorVector - - v, c = @constinferred left_orth(t; alg = :svd) - @test v * c β‰ˆ t - @test isisometric(v) - - c, vα΄΄ = @constinferred right_orth(t; alg = :svd) - @test c * vα΄΄ β‰ˆ t - @test isisometric(vα΄΄; side = :right) - - N = @constinferred left_null(t; alg = :svd) - @test isisometric(N) - @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) - - N = @constinferred left_null(t; trunc = (; atol = 100 * eps(norm(t)))) - @test isisometric(N) - @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) - - Nα΄΄ = @constinferred right_null(t; alg = :svd) - @test isisometric(Nα΄΄; side = :right) - @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) - - Nα΄΄ = @constinferred right_null(t; trunc = (; atol = 100 * eps(norm(t)))) - @test isisometric(Nα΄΄; side = :right) - @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) - end - - # empty tensor - for T in eltypes, t in (rand(T, W, zerospace(V1)), rand(T, zerospace(V1), W)) - U, S, Vα΄΄ = @constinferred svd_full(t) - @test U * S * Vα΄΄ β‰ˆ t - @test isunitary(U) - @test isunitary(Vα΄΄) - - U, S, Vα΄΄ = @constinferred svd_compact(t) - @test U * S * Vα΄΄ β‰ˆ t - @test dim(U) == dim(S) == dim(Vα΄΄) == dim(t) == 0 - end - end - - @testset "truncated SVD" begin - for T in eltypes, - t in ( - randn(T, W, W), randn(T, W, W)', - randn(T, W, V4), randn(T, V4, W), - randn(T, W, V4)', randn(T, V4, W)', - DiagonalTensorMap(randn(T, reduceddim(V1)), V1), - ) - - @constinferred normalize!(t) - - U, S, Vα΄΄, Ο΅ = @constinferred svd_trunc(t; trunc = notrunc()) - @test U * S * Vα΄΄ β‰ˆ t - @test Ο΅ β‰ˆ 0 - @test isisometric(U) - @test isisometric(Vα΄΄; side = :right) - - # dimension of S is a float for IsingBimodule - nvals = round(Int, dim(domain(S)) / 2) - trunc = truncrank(nvals) - U1, S1, Vα΄΄1, Ο΅1 = @constinferred svd_trunc(t; trunc) - @test t * Vα΄΄1' β‰ˆ U1 * S1 - @test isisometric(U1) - @test isisometric(Vα΄΄1; side = :right) - @test norm(t - U1 * S1 * Vα΄΄1) β‰ˆ Ο΅1 atol = eps(real(T))^(4 / 5) - @test dim(domain(S1)) <= nvals - - Ξ» = minimum(diagview(S1)) - trunc = trunctol(; atol = Ξ» - 10eps(Ξ»)) - U2, S2, Vα΄΄2, Ο΅2 = @constinferred svd_trunc(t; trunc) - @test t * Vα΄΄2' β‰ˆ U2 * S2 - @test isisometric(U2) - @test isisometric(Vα΄΄2; side = :right) - @test norm(t - U2 * S2 * Vα΄΄2) β‰ˆ Ο΅2 atol = eps(real(T))^(4 / 5) - @test minimum(diagview(S1)) >= Ξ» - @test U2 β‰ˆ U1 - @test S2 β‰ˆ S1 - @test Vα΄΄2 β‰ˆ Vα΄΄1 - @test Ο΅1 β‰ˆ Ο΅2 - - trunc = truncspace(space(S2, 1)) - U3, S3, Vα΄΄3, Ο΅3 = @constinferred svd_trunc(t; trunc) - @test t * Vα΄΄3' β‰ˆ U3 * S3 - @test isisometric(U3) - @test isisometric(Vα΄΄3; side = :right) - @test norm(t - U3 * S3 * Vα΄΄3) β‰ˆ Ο΅3 atol = eps(real(T))^(4 / 5) - @test space(S3, 1) β‰Ύ space(S2, 1) - - for trunc in (truncerror(; atol = Ο΅2), truncerror(; rtol = Ο΅2 / norm(t))) - U4, S4, Vα΄΄4, Ο΅4 = @constinferred svd_trunc(t; trunc) - @test t * Vα΄΄4' β‰ˆ U4 * S4 - @test isisometric(U4) - @test isisometric(Vα΄΄4; side = :right) - @test norm(t - U4 * S4 * Vα΄΄4) β‰ˆ Ο΅4 atol = eps(real(T))^(4 / 5) - @test Ο΅4 ≀ Ο΅2 - end - - trunc = truncrank(nvals) & trunctol(; atol = Ξ» - 10eps(Ξ»)) - U5, S5, Vα΄΄5, Ο΅5 = @constinferred svd_trunc(t; trunc) - @test t * Vα΄΄5' β‰ˆ U5 * S5 - @test isisometric(U5) - @test isisometric(Vα΄΄5; side = :right) - @test norm(t - U5 * S5 * Vα΄΄5) β‰ˆ Ο΅5 atol = eps(real(T))^(4 / 5) - @test minimum(diagview(S5)) >= Ξ» - @test dim(domain(S5)) ≀ nvals - end - end - - @testset "Eigenvalue decomposition" begin - for T in eltypes, - t in ( - rand(T, V1, V1), rand(T, W, W), rand(T, W, W)', - DiagonalTensorMap(rand(T, reduceddim(V1)), V1), - ) - - d, v = @constinferred eig_full(t) - @test t * v β‰ˆ v * d - - dβ€² = @constinferred eig_vals(t) - @test dβ€² β‰ˆ diagview(d) - @test dβ€² isa TensorKit.SectorVector - - vdv = project_hermitian!(v' * v) - @test @constinferred isposdef(vdv) - t isa DiagonalTensorMap || @test !isposdef(t) # unlikely for non-hermitian map - - nvals = round(Int, dim(domain(t)) / 2) - d, v = @constinferred eig_trunc(t; trunc = truncrank(nvals)) - @test t * v β‰ˆ v * d - @test dim(domain(d)) ≀ nvals - - t2 = @constinferred project_hermitian(t) - D, V = eigen(t2) - @test isisometric(V) - DΜƒ, VΜƒ = @constinferred eigh_full(t2) - @test D β‰ˆ DΜƒ - @test V β‰ˆ VΜƒ - Ξ» = minimum(real, diagview(D)) - @test cond(VΜƒ) β‰ˆ one(real(T)) - @test isposdef(t2) == isposdef(Ξ») - @test isposdef(t2 - Ξ» * one(t2) + 0.1 * one(t2)) - @test !isposdef(t2 - Ξ» * one(t2) - 0.1 * one(t2)) - - d, v = @constinferred eigh_full(t2) - @test t2 * v β‰ˆ v * d - @test isunitary(v) - - dβ€² = @constinferred eigh_vals(t2) - @test dβ€² β‰ˆ diagview(d) - @test dβ€² isa TensorKit.SectorVector - - Ξ» = minimum(real, diagview(d)) - @test cond(v) β‰ˆ one(real(T)) - @test isposdef(t2) == isposdef(Ξ») - @test isposdef(t2 - Ξ» * one(t) + 0.1 * one(t2)) - @test !isposdef(t2 - Ξ» * one(t) - 0.1 * one(t2)) - - d, v = @constinferred eigh_trunc(t2; trunc = truncrank(nvals)) - @test t2 * v β‰ˆ v * d - @test dim(domain(d)) ≀ nvals - end - end - - @testset "Condition number and rank" begin - for T in eltypes, - t in ( - rand(T, W, W), rand(T, W, W)', - rand(T, W, V4), rand(T, V4, W), - rand(T, W, V4)', rand(T, V4, W)', - DiagonalTensorMap(rand(T, reduceddim(V1)), V1), - ) - - d1, d2 = dim(codomain(t)), dim(domain(t)) - r = rank(t) - @test r == min(d1, d2) - @test typeof(r) == typeof(d1) - M = left_null(t) - @test @constinferred(rank(M)) + r β‰ˆ d1 - Mα΄΄ = right_null(t) - @test rank(Mα΄΄) + r β‰ˆ d2 - end - for T in eltypes - u = unitary(T, V1 βŠ— V2, V1 βŠ— V2) - @test @constinferred(cond(u)) β‰ˆ one(real(T)) - @test @constinferred(rank(u)) == dim(V1 βŠ— V2) - - t = rand(T, zerospace(V1), W) - @test rank(t) == 0 - t2 = rand(T, zerospace(V1) * zerospace(V2), zerospace(V1) * zerospace(V2)) - @test rank(t2) == 0 - @test cond(t2) == 0.0 - end - for T in eltypes, t in (rand(T, W, W), rand(T, W, W)') - project_hermitian!(t) - vals = @constinferred LinearAlgebra.eigvals(t) - Ξ»max = maximum(s -> maximum(abs, s), values(vals)) - Ξ»min = minimum(s -> minimum(abs, s), values(vals)) - @test cond(t) β‰ˆ Ξ»max / Ξ»min - end - end - - @testset "Hermitian projections" begin - for T in eltypes, - t in ( - rand(T, V1, V1), rand(T, W, W), rand(T, W, W)', - DiagonalTensorMap(rand(T, reduceddim(V1)), V1), - ) - normalize!(t) - noisefactor = eps(real(T))^(3 / 4) - - th = (t + t') / 2 - ta = (t - t') / 2 - tc = copy(t) - - thβ€² = @constinferred project_hermitian(t) - @test ishermitian(thβ€²) - @test thβ€² β‰ˆ th - @test t == tc - th_approx = th + noisefactor * ta - @test !ishermitian(th_approx) || (T <: Real && t isa DiagonalTensorMap) - @test ishermitian(th_approx; atol = 10 * noisefactor) - - taβ€² = project_antihermitian(t) - @test isantihermitian(taβ€²) - @test taβ€² β‰ˆ ta - @test t == tc - ta_approx = ta + noisefactor * th - @test !isantihermitian(ta_approx) - @test isantihermitian(ta_approx; atol = 10 * noisefactor) || (T <: Real && t isa DiagonalTensorMap) - end - end - - @testset "Isometric projections" begin - for T in eltypes, - t in ( - randn(T, W, W), randn(T, W, W)', - randn(T, W, V4), randn(T, V4, W)', - ) - t2 = project_isometric(t) - @test isisometric(t2) - t3 = project_isometric(t2) - @test t3 β‰ˆ t2 # stability of the projection - @test t2 * (t2' * t) β‰ˆ t - - tc = similar(t) - t3 = @constinferred project_isometric!(copy!(tc, t), t2) - @test t3 === t2 - @test isisometric(t2) - - # test that t2 is closer to A then any other isometry - for k in 1:10 - Ξ΄t = randn!(similar(t)) - t3 = project_isometric(t + Ξ΄t / 100) - @test norm(t - t3) > norm(t - t2) - end - end - end - end -end +# println("---------------------------------") +# println("| Multifusion space tests |") +# println("---------------------------------") + +# @timedtestset "Multifusion spaces " verbose = true begin +# @timedtestset "GradedSpace: $(TK.type_repr(Vect[I]))" begin +# gen = (values(I)[k] => (k + 1) for k in 1:length(values(I))) + +# V = GradedSpace(gen) +# @test eval(Meta.parse(type_repr(typeof(V)))) == typeof(V) +# @test eval_show(V) == V +# @test eval_show(V') == V' +# @test V' == GradedSpace(gen; dual = true) +# @test V == @constinferred GradedSpace(gen...) +# @test V' == @constinferred GradedSpace(gen...; dual = true) +# @test V == @constinferred GradedSpace(tuple(gen...)) +# @test V' == @constinferred GradedSpace(tuple(gen...); dual = true) +# @test V == @constinferred GradedSpace(Dict(gen)) +# @test V' == @constinferred GradedSpace(Dict(gen); dual = true) +# @test V == @inferred Vect[I](gen) +# @test V' == @constinferred Vect[I](gen; dual = true) +# @test V == @constinferred Vect[I](gen...) +# @test V' == @constinferred Vect[I](gen...; dual = true) +# @test V == @constinferred Vect[I](Dict(gen)) +# @test V' == @constinferred Vect[I](Dict(gen); dual = true) +# @test @constinferred(hash(V)) == hash(deepcopy(V)) != hash(V') +# @test V == GradedSpace(reverse(collect(gen))...) +# @test eval_show(V) == V +# @test eval_show(typeof(V)) == typeof(V) + +# @test dim(@constinferred(zerospace(V))) == 0 + +# W = @constinferred GradedSpace(unit => 1 for unit in allunits(I)) +# dict = Dict(unit => 1 for unit in allunits(I)) +# @test W == GradedSpace(dict) +# @test W == GradedSpace(push!(dict, randsector(I) => 0)) +# @test @constinferred(zerospace(V)) == GradedSpace(unit => 0 for unit in allunits(I)) +# randunit = rand(collect(allunits(I))) +# @test_throws ArgumentError("Sector $(randunit) appears multiple times") GradedSpace(randunit => 1, randunit => 3) + +# @test isunitspace(W) +# @test @constinferred(unitspace(V)) == W == unitspace(typeof(V)) +# @test_throws ArgumentError leftunitspace(V) +# @test_throws ArgumentError rightunitspace(V) +# @test eval_show(W) == W + +# @test isa(V, VectorSpace) +# @test isa(V, ElementarySpace) +# @test isa(InnerProductStyle(V), HasInnerProduct) +# @test isa(InnerProductStyle(V), EuclideanInnerProduct) +# @test isa(V, GradedSpace) +# @test isa(V, GradedSpace{I}) +# @test @constinferred(dual(V)) == @constinferred(conj(V)) == @constinferred(adjoint(V)) != V +# @test @constinferred(field(V)) == β„‚ +# @test @constinferred(sectortype(V)) == I +# slist = @constinferred sectors(V) +# @test @constinferred(hassector(V, first(slist))) +# @test @constinferred(dim(V)) == sum(dim(s) * dim(V, s) for s in slist) +# @test @constinferred(reduceddim(V)) == sum(dim(V, s) for s in slist) +# @constinferred dim(V, first(slist)) + +# @test @constinferred(βŠ•(V, zerospace(V))) == V +# @test @constinferred(βŠ•(V, V)) == Vect[I](c => 2dim(V, c) for c in sectors(V)) +# @test @constinferred(βŠ•(V, V, V, V)) == Vect[I](c => 4dim(V, c) for c in sectors(V)) +# @test @constinferred(βŠ•(V, unitspace(V))) == Vect[I](c => isunit(c) + dim(V, c) for c in sectors(V)) +# @test @constinferred(fuse(V, unitspace(V))) == V + +# @testset "$Istr ($i, $j) spaces" for i in 1:r, j in 1:r #TODO: look at these tests better +# # space with a single sector +# Wleft = @constinferred Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)) +# Wright = @constinferred Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)) +# WM = @constinferred Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) +# WMop = @constinferred Vect[I]((j, i, label) => 1 for label in 1:MTK._numlabels(I, j, i)) + +# @test leftunitspace(Wleft) == rightunitspace(Wleft) +# @test leftunitspace(Wright) == rightunitspace(Wright) +# @test @constinferred(leftunitspace(βŠ•(Wleft, WM))) == leftunitspace(Wleft) +# @test @constinferred(leftunitspace(βŠ•(Wright, WMop))) == leftunitspace(Wright) +# @test @constinferred(rightunitspace(βŠ•(Wright, WM))) == rightunitspace(Wright) +# @test @constinferred(rightunitspace(βŠ•(Wleft, WMop))) == rightunitspace(Wleft) + +# if i != j # some tests specialised for modules + +# # sensible direct sums and fuses +# ul, ur = unit(I(i, i, 1)), unit(I(j, j, 1)) +# @test @constinferred(βŠ•(Wleft, WM)) == +# Vect[I](c => 1 for c in sectors(V) if leftunit(c) == ul == rightunit(c) || (c.i == i && c.j == j)) +# @test @constinferred(βŠ•(Wright, WMop)) == +# Vect[I](c => 1 for c in sectors(V) if leftunit(c) == ur == rightunit(c) || (c.i == j && c.j == i)) +# @test @constinferred(βŠ•(Wright, WM)) == +# Vect[I](c => 1 for c in sectors(V) if rightunit(c) == ur == leftunit(c) || (c.i == i && c.j == j)) +# @test @constinferred(βŠ•(Wleft, WMop)) == +# Vect[I](c => 1 for c in sectors(V) if rightunit(c) == ul == leftunit(c) || (c.i == j && c.j == i)) +# # round needed below because of numerical F-symbols not being integer when they should be +# # although this test might be stupid, because I'm assuming integer qdims bc everything's a group or irrep on the diagonal +# @test @constinferred(fuse(Wleft, WM)) == Vect[I](c => round(Int, dim(Wleft)) for c in sectors(WM)) # this might be wrong +# @test @constinferred(fuse(Wright, WMop)) == Vect[I](c => round(Int, dim(Wright)) for c in sectors(WMop)) # same + +# # less sensible fuse +# @test @constinferred(fuse(Wleft, WMop)) == fuse(Wright, WM) == +# Vect[I](c => 0 for c in sectors(V)) + +# for W in [WM, WMop, Wright] +# @test infimum(Wleft, W) == Vect[I](c => 0 for c in sectors(V)) +# end +# else +# @test @constinferred(βŠ•(Wleft, Wright)) == +# Vect[I](c => 2 for c in sectors(V) if c.i == c.j == i) +# @test @constinferred(fuse(Wleft, WMop)) == fuse(Wright, WM) +# end + +# for W in [Wleft, Wright] +# @test @constinferred(βŠ•(W, rightunitspace(W))) == +# Vect[I](c => isunit(c) + dim(W, c) for c in sectors(W)) +# @test @constinferred(fuse(W, rightunitspace(W))) == W +# end +# end + +# d = Dict{I, Int}() +# for a in sectors(V), b in sectors(V) +# a.j == b.i || continue # skip if not compatible +# for c in a βŠ— b +# d[c] = get(d, c, 0) + dim(V, a) * dim(V, b) * Nsymbol(a, b, c) +# end +# end +# @test @constinferred(fuse(V, V)) == GradedSpace(d) +# @test @constinferred(flip(V)) == +# Vect[I](conj(c) => dim(V, c) for c in sectors(V))' +# @test flip(V) β‰… V +# @test flip(V) β‰Ύ V +# @test flip(V) β‰Ώ V +# @test @constinferred(βŠ•(V, V)) == @constinferred supremum(V, βŠ•(V, V)) +# @test V == @constinferred infimum(V, βŠ•(V, V)) +# @test V β‰Ί βŠ•(V, V) +# @test !(V ≻ βŠ•(V, V)) + +# randlen = rand(1:length(values(I))) +# s = rand(collect(values(I))[randlen:end]) # such that dim(V, s) > randlen +# @test infimum(V, GradedSpace(s => randlen)) == GradedSpace(s => randlen) +# @test_throws SpaceMismatch (βŠ•(V, V')) +# end + +# @timedtestset "HomSpace with $(TK.type_repr(Vect[I])) involving ($i, $j)" for i in 1:r, j in 1:r +# V1, V2, V3, V4, V5 = ( +# Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), +# Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)), +# Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), # same as V1 +# Vect[I]((i, j, 1) => 3), +# Vect[I]((j, j, label) => 1 for label in 1:MTK._numlabels(I, j, j)), +# ) +# W = HomSpace(V1 βŠ— V2, V3 βŠ— V4 βŠ— V5) + +# @test W == (V3 βŠ— V4 βŠ— V5 β†’ V1 βŠ— V2) +# @test W == (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5) +# @test W' == (V1 βŠ— V2 β†’ V3 βŠ— V4 βŠ— V5) +# @test eval(Meta.parse(sprint(show, W))) == W +# @test eval(Meta.parse(sprint(show, typeof(W)))) == typeof(W) +# @test spacetype(W) == typeof(V1) +# @test sectortype(W) == sectortype(V1) +# @test W[1] == V1 +# @test W[2] == V2 +# @test W[3] == V3' +# @test W[4] == V4' +# @test W[5] == V5' + +# @test @constinferred(hash(W)) == hash(deepcopy(W)) != hash(W') +# @test W == deepcopy(W) +# @test W == @constinferred permute(W, ((1, 2), (3, 4, 5))) +# @test permute(W, ((2, 4, 5), (3, 1))) == (V2 βŠ— V4' βŠ— V5' ← V3 βŠ— V1') +# @test (V1 βŠ— V2 ← V1 βŠ— V2) == @constinferred TK.compose(W, W') + +# @test (V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 βŠ— rightunitspace(V5)) == +# @constinferred(insertleftunit(W)) == +# @constinferred(insertrightunit(W)) +# @test @constinferred(removeunit(insertleftunit(W), $(numind(W) + 1))) == W +# @test_throws BoundsError insertrightunit(W, 6) +# @test_throws BoundsError insertleftunit(W, 0) + +# @test (V1 βŠ— V2 βŠ— rightunitspace(V2) ← V3 βŠ— V4 βŠ— V5) == +# @constinferred(insertrightunit(W, 2)) +# @test (V1 βŠ— V2 ← leftunitspace(V3) βŠ— V3 βŠ— V4 βŠ— V5) == +# @constinferred(insertleftunit(W, 3)) +# @test @constinferred(removeunit(insertleftunit(W, 3), 3)) == W +# @test_throws ArgumentError @constinferred(insertrightunit(one(V1) ← V1, 0)) # should I specify it's the other error? +# @test_throws ArgumentError insertleftunit(one(V1) ← V1, 0) +# end +# end + +# println("---------------------------------------") +# println("| Multifusion fusion tree tests |") +# println("---------------------------------------") + +# @timedtestset "Fusion trees for $(TK.type_repr(I)) involving ($i, $j)" verbose = true for i in 1:r, j in 1:r +# N = 6 +# out = random_fusion(I, i, j, Val(N)) +# isdual = ntuple(n -> rand(Bool), N) +# in = rand(collect(βŠ—(out...))) # will be in π’žβ±Όβ±Ό with this choice of out + +# numtrees = length(fusiontrees(out, in, isdual)) # will be 1 for i != j +# @test numtrees == count(n -> true, fusiontrees(out, in, isdual)) + +# it = @constinferred fusiontrees(out, in, isdual) +# @constinferred Nothing iterate(it) +# f, s = iterate(it) +# @constinferred Nothing iterate(it, s) +# @test f == @constinferred first(it) +# @testset "Fusion tree $Istr: printing" begin +# @test eval(Meta.parse(sprint(show, f))) == f +# end + +# C0, D0 = unit(I(i, i, 1)), unit(I(j, j, 1)) +# @testset "Fusion tree $Istr: constructor properties" for u in (C0, D0) +# @constinferred FusionTree((), u, (), (), ()) +# @constinferred FusionTree((u,), u, (false,), (), ()) +# @constinferred FusionTree((u, u), u, (false, false), (), (1,)) +# @constinferred FusionTree((u, u, u), u, (false, false, false), (u,), (1, 1)) +# @constinferred FusionTree( +# (u, u, u, u), u, (false, false, false, false), (u, u), (1, 1, 1) +# ) +# @test_throws MethodError FusionTree((u, u, u), u, (false, false), (u,), (1, 1)) +# @test_throws MethodError FusionTree( +# (u, u, u), u, (false, false, false), (u, u), (1, 1) +# ) +# @test_throws MethodError FusionTree( +# (u, u, u), u, (false, false, false), (u,), (1, 1, 1) +# ) +# @test_throws MethodError FusionTree((u, u, u), u, (false, false, false), (), (1,)) + +# f = FusionTree((u, u, u), u, (false, false, false), (u,), (1, 1)) +# @test sectortype(f) == I +# @test length(f) == 3 +# @test FusionStyle(f) == FusionStyle(I) +# @test BraidingStyle(f) == BraidingStyle(I) + +# if FusionStyle(I) isa UniqueFusion +# @constinferred FusionTree((), u, ()) +# @constinferred FusionTree((u,), u, (false,)) +# @constinferred FusionTree((u, u), u, (false, false)) +# @constinferred FusionTree((u, u, u), u) +# if UnitStyle(I) isa SimpleUnit +# @constinferred FusionTree((u, u, u, u)) +# else +# @test_throws ArgumentError FusionTree((u, u, u, u)) +# end +# @test_throws MethodError FusionTree((u, u), u, (false, false, false)) +# else +# @test_throws ArgumentError FusionTree((), u, ()) +# @test_throws ArgumentError FusionTree((u,), u, (false,)) +# @test_throws ArgumentError FusionTree((u, u), u, (false, false)) +# @test_throws ArgumentError FusionTree((u, u, u), u) +# if I <: ProductSector && UnitStyle(I) isa GenericUnit +# @test_throws DomainError FusionTree((u, u, u, u)) +# else +# @test_throws ArgumentError FusionTree((u, u, u, u)) +# end +# end +# end + +# @testset "Fusion tree $Istr: insertat" begin +# N = 4 +# out2 = random_fusion(I, i, j, Val(N)) +# in2 = rand(collect(βŠ—(out2...))) +# isdual2 = ntuple(n -> rand(Bool), N) +# f2 = rand(collect(fusiontrees(out2, in2, isdual2))) +# for k in 1:N +# out1 = random_fusion(I, i, j, Val(N)) # guaranteed good fusion +# out1 = Base.setindex(out1, in2, i) # can lead to poor fusion +# while isempty(βŠ—(out1...)) # TODO: better way to do this? +# out1 = random_fusion(I, i, j, Val(N)) +# out1 = Base.setindex(out1, in2, i) +# end +# in1 = rand(collect(βŠ—(out1...))) +# isdual1 = ntuple(n -> rand(Bool), N) +# isdual1 = Base.setindex(isdual1, false, k) +# f1 = rand(collect(fusiontrees(out1, in1, isdual1))) + +# trees = @constinferred TK.insertat(f1, k, f2) +# @test norm(values(trees)) β‰ˆ 1 + +# f1a, f1b = @constinferred TK.split(f1, $k) +# @test length(TK.insertat(f1b, 1, f1a)) == 1 +# @test first(TK.insertat(f1b, 1, f1a)) == (f1 => 1) + +# # no braid tests for non-hardcoded example +# end +# end +# # no planar trace tests + +# @testset "Fusion tree $Istr: elementary artin braid" begin +# N = length(out) +# isdual = ntuple(n -> rand(Bool), N) +# # no general artin braid test + +# # not sure how useful this test is, it does the trivial braiding (choice of out) +# f = rand(collect(it)) # in this case the 1 tree +# d1 = TK.artin_braid(f, 2) # takes unit C0 with current out +# d2 = empty(d1) +# for (f1, coeff1) in d1 +# for (f2, coeff2) in TK.artin_braid(f1, 3) +# d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 +# end +# end +# d1 = d2 +# d2 = empty(d1) +# for (f1, coeff1) in d1 +# for (f2, coeff2) in TK.artin_braid(f1, 3; inv = true) +# d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 +# end +# end +# d1 = d2 +# d2 = empty(d1) +# for (f1, coeff1) in d1 +# for (f2, coeff2) in TK.artin_braid(f1, 2; inv = true) +# d2[f2] = get(d2, f2, zero(coeff1)) + coeff2 * coeff1 +# end +# end +# d1 = d2 +# for (f1, coeff1) in d1 +# if f1 == f +# @test coeff1 β‰ˆ 1 +# else +# @test isapprox(coeff1, 0; atol = 1.0e-12, rtol = 1.0e-12) +# end +# end +# end + +# # no braiding and permuting test +# @testset "Fusion tree $Istr: merging" begin +# N = 3 +# out1 = random_fusion(I, i, j, N) +# out2 = random_fusion(I, i, j, N) +# in1 = rand(collect(βŠ—(out1...))) +# in2 = rand(collect(βŠ—(out2...))) +# tp = βŠ—(in1, in2) # messy solution but it works +# while isempty(tp) +# out1 = random_fusion(I, i, j, Val(N)) +# out2 = random_fusion(I, i, j, Val(N)) +# in1 = rand(collect(βŠ—(out1...))) +# in2 = rand(collect(βŠ—(out2...))) +# tp = βŠ—(in1, in2) +# end + +# f1 = rand(collect(fusiontrees(out1, in1))) +# f2 = rand(collect(fusiontrees(out2, in2))) + + +# @test dim(in1) * dim(in2) β‰ˆ sum( +# abs2(coeff) * dim(c) for c in in1 βŠ— in2 +# for ΞΌ in 1:Nsymbol(in1, in2, c) +# for (f, coeff) in TK.merge(f1, f2, c, ΞΌ) +# ) +# # no merge and braid interplay tests +# end + +# # double fusion tree tests +# N = 4 +# out = random_fusion(I, i, j, Val(N)) +# out2 = random_fusion(I, i, j, Val(N)) +# tp = βŠ—(out...) +# tp2 = βŠ—(out2...) +# while isempty(intersect(tp, tp2)) # guarantee fusion to same coloring +# out2 = random_fusion(I, i, j, Val(N)) +# tp2 = βŠ—(out2...) +# end +# @test_throws ArgumentError fusiontrees((out..., map(dual, out)...)) +# incoming = rand(collect(intersect(tp, tp2))) +# f1 = rand(collect(fusiontrees(out, incoming, ntuple(n -> rand(Bool), N)))) +# f2 = rand(collect(fusiontrees(out2, incoming, ntuple(n -> rand(Bool), N)))) # no permuting + +# @testset "Double fusion tree $Istr: repartitioning" begin +# for n in 0:(2 * N) +# d = @constinferred TK.repartition(f1, f2, $n) +# @test dim(incoming) β‰ˆ +# sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) +# d2 = Dict{typeof((f1, f2)), valtype(d)}() +# for ((f1β€², f2β€²), coeff) in d +# for ((f1β€²β€², f2β€²β€²), coeff2) in TK.repartition(f1β€², f2β€², N) +# d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff2 * coeff +# end +# end +# for ((f1β€², f2β€²), coeff2) in d2 +# if f1 == f1β€² && f2 == f2β€² +# @test coeff2 β‰ˆ 1 +# else +# @test isapprox(coeff2, 0; atol = 1.0e-12, rtol = 1.0e-12) +# end +# end +# end +# end + +# # no double fusion tree permutation tests + +# # very slow for (1, 6), (3, 4), (3, 5), (3, 6), (5, 6), (6, 1), (6, 5), (7, 1), (7, 4), (7, 6) +# @testset "Double fusion tree $Istr: transposition" begin +# for n in 0:(2N) +# i0 = rand(1:(2N)) +# p = mod1.(i0 .+ (1:(2N)), 2N) +# ip = mod1.(-i0 .+ (1:(2N)), 2N) +# pβ€² = tuple(getindex.(Ref(vcat(1:N, (2N):-1:(N + 1))), p)...) +# p1, p2 = pβ€²[1:n], pβ€²[(2N):-1:(n + 1)] +# ipβ€² = tuple(getindex.(Ref(vcat(1:n, (2N):-1:(n + 1))), ip)...) +# ip1, ip2 = ipβ€²[1:N], ipβ€²[(2N):-1:(N + 1)] + +# d = @constinferred transpose(f1, f2, p1, p2) +# @test dim(incoming) β‰ˆ +# sum(abs2(coef) * dim(f1.coupled) for ((f1, f2), coef) in d) +# d2 = Dict{typeof((f1, f2)), valtype(d)}() +# for ((f1β€², f2β€²), coeff) in d +# dβ€² = transpose(f1β€², f2β€², ip1, ip2) +# for ((f1β€²β€², f2β€²β€²), coeff2) in dβ€² +# d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff2 * coeff +# end +# end +# for ((f1β€², f2β€²), coeff2) in d2 +# if f1 == f1β€² && f2 == f2β€² +# @test coeff2 β‰ˆ 1 +# else +# @test abs(coeff2) < 1.0e-12 +# end +# end +# end +# end + +# @testset "Double fusion tree $Istr: planar trace" begin +# d1 = transpose(f1, f1, (N + 1, 1:N..., ((2N):-1:(N + 3))...), (N + 2,)) +# f1front, = TK.split(f1, N - 1) +# T = sectorscalartype(I) +# d2 = Dict{typeof((f1front, f1front)), T}() +# for ((f1β€², f2β€²), coeffβ€²) in d1 +# for ((f1β€²β€², f2β€²β€²), coeffβ€²β€²) in +# TK.planar_trace( +# f1β€², f2β€², (2:N...,), (1, ((2N):-1:(N + 3))...), (N + 1,), +# (N + 2,) +# ) +# coeff = coeffβ€² * coeffβ€²β€² +# d2[(f1β€²β€², f2β€²β€²)] = get(d2, (f1β€²β€², f2β€²β€²), zero(coeff)) + coeff +# end +# end +# for ((f1_, f2_), coeff) in d2 +# if (f1_, f2_) == (f1front, f1front) +# @test coeff β‰ˆ dim(f1.coupled) / dim(f1front.coupled) +# else +# @test abs(coeff) < 1.0e-12 +# end +# end +# end +# end + +# println("-------------------------------------------") +# println("| Multifusion diagonal tensor tests |") +# println("-------------------------------------------") + +# V = Vect[I](values(I)[k] => 1 for k in 1:length(values(I))) + +# @timedtestset "DiagonalTensor" begin +# @timedtestset "Basic properties and algebra" begin +# for T in (Float32, Float64, ComplexF32, ComplexF64, BigFloat) +# # constructors +# t = @constinferred DiagonalTensorMap{T}(undef, V) +# t = @constinferred DiagonalTensorMap(rand(T, reduceddim(V)), V) +# t2 = @constinferred DiagonalTensorMap{T}(undef, space(t)) +# @test space(t2) == space(t) +# @test_throws ArgumentError DiagonalTensorMap{T}(undef, V^2 ← V) +# t2 = @constinferred DiagonalTensorMap{T}(undef, domain(t)) +# @test space(t2) == space(t) +# @test_throws ArgumentError DiagonalTensorMap{T}(undef, V^2) +# # properties +# @test @constinferred(hash(t)) == hash(deepcopy(t)) +# @test scalartype(t) == T +# @test codomain(t) == ProductSpace(V) +# @test domain(t) == ProductSpace(V) +# @test space(t) == (V ← V) +# @test space(t') == (V ← V) +# @test dim(t) == dim(space(t)) +# # blocks +# bs = @constinferred blocks(t) +# (c, b1), state = @constinferred Nothing iterate(bs) +# @test c == first(blocksectors(V ← V)) +# next = @constinferred Nothing iterate(bs, state) +# b2 = @constinferred block(t, first(blocksectors(t))) +# @test b1 == b2 +# @test eltype(bs) === Pair{typeof(c), typeof(b1)} +# @test typeof(b1) === TensorKit.blocktype(t) +# # basic linear algebra +# @test isa(@constinferred(norm(t)), real(T)) +# @test norm(t)^2 β‰ˆ dot(t, t) +# Ξ± = rand(T) +# @test norm(Ξ± * t) β‰ˆ abs(Ξ±) * norm(t) +# @test norm(t + t, 2) β‰ˆ 2 * norm(t, 2) +# @test norm(t + t, 1) β‰ˆ 2 * norm(t, 1) +# @test norm(t + t, Inf) β‰ˆ 2 * norm(t, Inf) +# p = 3 * rand(Float64) +# @test norm(t + t, p) β‰ˆ 2 * norm(t, p) +# @test norm(t) β‰ˆ norm(t') + +# @test t == @constinferred(TensorMap(t)) +# @test norm(t + TensorMap(t)) β‰ˆ 2 * norm(t) + +# @test norm(zerovector!(t)) == 0 +# @test norm(one!(t)) β‰ˆ sqrt(dim(V)) +# @test one!(t) == id(V) +# if T != BigFloat # seems broken for now +# @test norm(one!(t) - id(V)) == 0 +# end + +# t1 = DiagonalTensorMap(rand(T, reduceddim(V)), V) +# t2 = DiagonalTensorMap(rand(T, reduceddim(V)), V) +# t3 = DiagonalTensorMap(rand(T, reduceddim(V)), V) +# Ξ± = rand(T) +# Ξ² = rand(T) +# @test @constinferred(dot(t1, t2)) β‰ˆ conj(dot(t2, t1)) +# @test dot(t2, t1) β‰ˆ conj(dot(t2', t1')) +# @test dot(t3, Ξ± * t1 + Ξ² * t2) β‰ˆ Ξ± * dot(t3, t1) + Ξ² * dot(t3, t2) +# end +# end + +# @timedtestset "Basic linear algebra: test via conversion" begin +# for T in (Float32, ComplexF64) +# t1 = DiagonalTensorMap(rand(T, reduceddim(V)), V) +# t2 = DiagonalTensorMap(rand(T, reduceddim(V)), V) +# @test norm(t1, 2) β‰ˆ norm(convert(TensorMap, t1), 2) +# @test dot(t2, t1) β‰ˆ dot(convert(TensorMap, t2), convert(TensorMap, t1)) +# Ξ± = rand(T) +# @test convert(TensorMap, Ξ± * t1) β‰ˆ Ξ± * convert(TensorMap, t1) +# @test convert(TensorMap, t1') β‰ˆ convert(TensorMap, t1)' +# @test convert(TensorMap, t1 + t2) β‰ˆ convert(TensorMap, t1) + convert(TensorMap, t2) +# end +# end +# @timedtestset "Real and imaginary parts" begin +# for T in (Float64, ComplexF64, ComplexF32) +# t = DiagonalTensorMap(rand(T, reduceddim(V)), V) + +# tr = @constinferred real(t) +# @test scalartype(tr) <: Real +# @test real(convert(TensorMap, t)) == convert(TensorMap, tr) + +# ti = @constinferred imag(t) +# @test scalartype(ti) <: Real +# @test imag(convert(TensorMap, t)) == convert(TensorMap, ti) + +# tc = @inferred complex(t) +# @test scalartype(tc) <: Complex +# @test complex(convert(TensorMap, t)) == convert(TensorMap, tc) + +# tc2 = @inferred complex(tr, ti) +# @test tc2 β‰ˆ tc +# end +# end +# @timedtestset "Tensor conversion" begin +# t = @constinferred DiagonalTensorMap(undef, V) +# rand!(t.data) +# # element type conversion +# tc = complex(t) +# @test convert(typeof(tc), t) == tc +# @test typeof(convert(typeof(tc), t)) == typeof(tc) +# # to and from generic TensorMap +# td = DiagonalTensorMap(TensorMap(t)) +# @test t == td +# @test typeof(td) == typeof(t) +# end +# @timedtestset "Trace, Multiplication and inverse" begin +# t1 = DiagonalTensorMap(rand(Float64, reduceddim(V)), V) +# t2 = DiagonalTensorMap(rand(ComplexF64, reduceddim(V)), V) +# @test tr(TensorMap(t1)) == @constinferred tr(t1) +# @test tr(TensorMap(t2)) == @constinferred tr(t2) +# @test TensorMap(@constinferred t1 * t2) β‰ˆ TensorMap(t1) * TensorMap(t2) +# @test TensorMap(@constinferred t1 \ t2) β‰ˆ TensorMap(t1) \ TensorMap(t2) +# @test TensorMap(@constinferred t1 / t2) β‰ˆ TensorMap(t1) / TensorMap(t2) +# @test TensorMap(@constinferred inv(t1)) β‰ˆ inv(TensorMap(t1)) +# @test TensorMap(@constinferred pinv(t1)) β‰ˆ pinv(TensorMap(t1)) +# @test all( +# Base.Fix2(isa, DiagonalTensorMap), (t1 * t2, t1 \ t2, t1 / t2, inv(t1), pinv(t1)) +# ) +# # no V * V' * V ← V or V^2 ← V tests due to Nsymbol erroring where fusion is forbidden +# end +# @timedtestset "Tensor contraction " for i in 1:r +# W = Vect[I]((i, i, label) => 2 for label in 1:MTK._numlabels(I, i, i)) + +# d = DiagonalTensorMap(rand(ComplexF64, reduceddim(W)), W) +# t = TensorMap(d) +# A = randn(ComplexF64, W βŠ— W' βŠ— W, W) +# B = randn(ComplexF64, W βŠ— W' βŠ— W, W βŠ— W') # empty for modules so untested + +# @planar E1[-1 -2 -3; -4 -5] := B[-1 -2 -3; 1 -5] * d[1; -4] +# @planar E2[-1 -2 -3; -4 -5] := B[-1 -2 -3; 1 -5] * t[1; -4] +# @test E1 β‰ˆ E2 +# @planar E1[-1 -2 -3; -4 -5] = B[-1 -2 -3; -4 1] * d'[-5; 1] +# @planar E2[-1 -2 -3; -4 -5] = B[-1 -2 -3; -4 1] * t'[-5; 1] +# @test E1 β‰ˆ E2 +# @planar E1[-1 -2 -3; -4 -5] = B[1 -2 -3; -4 -5] * d[-1; 1] +# @planar E2[-1 -2 -3; -4 -5] = B[1 -2 -3; -4 -5] * t[-1; 1] +# @test E1 β‰ˆ E2 +# @planar E1[-1 -2 -3; -4 -5] = B[-1 1 -3; -4 -5] * d[1; -2] +# @planar E2[-1 -2 -3; -4 -5] = B[-1 1 -3; -4 -5] * t[1; -2] +# @test E1 β‰ˆ E2 +# @planar E1[-1 -2 -3; -4 -5] = B[-1 -2 1; -4 -5] * d'[-3; 1] +# @planar E2[-1 -2 -3; -4 -5] = B[-1 -2 1; -4 -5] * t'[-3; 1] +# @test E1 β‰ˆ E2 +# end +# @timedtestset "Tensor functions" begin +# for T in (Float64, ComplexF64) +# d = DiagonalTensorMap(rand(T, reduceddim(V)), V) +# # rand is important for positive numbers in the real case, for log and sqrt +# t = TensorMap(d) +# @test @constinferred exp(d) β‰ˆ exp(t) +# @test @constinferred log(d) β‰ˆ log(t) +# @test @constinferred sqrt(d) β‰ˆ sqrt(t) +# @test @constinferred sin(d) β‰ˆ sin(t) +# @test @constinferred cos(d) β‰ˆ cos(t) +# @test @constinferred tan(d) β‰ˆ tan(t) +# @test @constinferred cot(d) β‰ˆ cot(t) +# @test @constinferred sinh(d) β‰ˆ sinh(t) +# @test @constinferred cosh(d) β‰ˆ cosh(t) +# @test @constinferred tanh(d) β‰ˆ tanh(t) +# @test @constinferred coth(d) β‰ˆ coth(t) +# @test @constinferred asin(d) β‰ˆ asin(t) +# @test @constinferred acos(d) β‰ˆ acos(t) +# @test @constinferred atan(d) β‰ˆ atan(t) +# @test @constinferred acot(d) β‰ˆ acot(t) +# @test @constinferred asinh(d) β‰ˆ asinh(t) +# @test @constinferred acosh(one(d) + d) β‰ˆ acosh(one(t) + t) +# @test @constinferred atanh(d) β‰ˆ atanh(t) +# @test @constinferred acoth(one(t) + d) β‰ˆ acoth(one(d) + t) +# end +# end +# end + +# # no conversion tests because no fusion tensor +# # no permute tests: NoBraiding() + +# println("---------------------------------------") +# println("Tensors with symmetry: $Istr") +# println("---------------------------------------") + +# @timedtestset "Tensors with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r +# isdiag = i == j + +# VC = ( +# Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), +# Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? +# Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), +# Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), +# Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3), +# ) + +# VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects + +# VM1 = ( +# Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works +# Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors +# Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), +# VM, # important that V4 is module-graded +# Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), +# ) + +# VM2 = ( +# Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here +# Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), +# Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), +# VM, +# Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), +# ) + +# Vcol = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs + +# for V in Vcol # TODO: add enumerate to keep track of potential erroring space +# V1, V2, V3, V4, V5 = V +# @timedtestset "Basic tensor properties" begin +# W = isdiag ? V1 βŠ— V2 βŠ— V3 βŠ— V4 βŠ— V5 : V3 βŠ— V4 βŠ— V5 # fusion matters +# for T in (Int, Float32, Float64, ComplexF32, ComplexF64, BigFloat) +# t = @constinferred zeros(T, W) # empty for i != j b/c blocks are module-graded +# @test @constinferred(hash(t)) == hash(deepcopy(t)) +# @test scalartype(t) == T +# @test norm(t) == 0 +# @test codomain(t) == W +# @test space(t) == (W ← one(W)) +# @test domain(t) == one(W) +# @test typeof(t) == TensorMap{T, spacetype(t), length(W), 0, Vector{T}} +# # blocks +# bs = @constinferred blocks(t) +# if !isempty(bs) +# (c, b1), state = @constinferred Nothing iterate(bs) # errors if fusion gives empty data +# # @test c == first(blocksectors(W)) # unit doesn't have label 1 +# next = @constinferred Nothing iterate(bs, state) +# b2 = @constinferred block(t, first(blocksectors(t))) +# @test b1 == b2 +# @test eltype(bs) === Pair{typeof(c), typeof(b1)} +# @test typeof(b1) === TK.blocktype(t) +# @test typeof(c) === sectortype(t) +# end +# end +# end + +# @timedtestset "Tensor Dict conversion" begin +# W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 # rewritten to be compatible with module fusion +# for T in (Int, Float32, ComplexF64) +# t = @constinferred rand(T, W) +# d = convert(Dict, t) +# @test t == convert(TensorMap, d) +# end +# end + +# @timedtestset "Basic linear algebra" begin +# W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 +# for T in (Float32, ComplexF64) +# t = @constinferred rand(T, W) # fusion matters here +# @test scalartype(t) == T +# @test space(t) == W +# @test space(t') == W' +# @test dim(t) == dim(space(t)) +# @test codomain(t) == codomain(W) +# @test domain(t) == domain(W) +# # blocks for adjoint +# bs = @constinferred blocks(t') +# (c, b1), state = @constinferred Nothing iterate(bs) +# @test c == first(blocksectors(W')) +# next = @constinferred Nothing iterate(bs, state) +# b2 = @constinferred block(t', first(blocksectors(t'))) +# @test b1 == b2 +# @test eltype(bs) === Pair{typeof(c), typeof(b1)} +# @test typeof(b1) === TensorKit.blocktype(t') +# @test typeof(c) === sectortype(t) +# # linear algebra +# @test isa(@constinferred(norm(t)), real(T)) +# @test norm(t)^2 β‰ˆ dot(t, t) +# Ξ± = rand(T) +# @test norm(Ξ± * t) β‰ˆ abs(Ξ±) * norm(t) +# @test norm(t + t, 2) β‰ˆ 2 * norm(t, 2) +# @test norm(t + t, 1) β‰ˆ 2 * norm(t, 1) +# @test norm(t + t, Inf) β‰ˆ 2 * norm(t, Inf) +# p = 3 * rand(Float64) +# @test norm(t + t, p) β‰ˆ 2 * norm(t, p) +# @test norm(t) β‰ˆ norm(t') + +# t2 = @constinferred rand!(similar(t)) +# Ξ² = rand(T) +# @test @constinferred(dot(Ξ² * t2, Ξ± * t)) β‰ˆ conj(Ξ²) * Ξ± * conj(dot(t, t2)) +# @test dot(t2, t) β‰ˆ conj(dot(t, t2)) +# @test dot(t2, t) β‰ˆ conj(dot(t2', t')) +# @test dot(t2, t) β‰ˆ dot(t', t2') + +# if !isempty(blocksectors(V2 βŠ— V1)) +# i1 = @constinferred(isomorphism(T, V1 βŠ— V2, V2 βŠ— V1)) # can't reverse fusion here when modules are involved +# i2 = @constinferred(isomorphism(Vector{T}, V2 βŠ— V1, V1 βŠ— V2)) +# @test i1 * i2 == @constinferred(id(T, V1 βŠ— V2)) +# @test i2 * i1 == @constinferred(id(Vector{T}, V2 βŠ— V1)) +# end + +# w = @constinferred isometry(T, V1 βŠ— (rightunitspace(V1) βŠ• rightunitspace(V1)), V1) +# @test dim(w) == 2 * dim(V1 ← V1) +# @test w' * w == id(Vector{T}, V1) +# @test w * w' == (w * w')^2 +# end +# end + +# @timedtestset "Trivial space insertion and removal" begin +# W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 +# for T in (Float32, ComplexF64) +# t = @constinferred rand(T, W) # fusion matters here +# t2 = @constinferred insertleftunit(t) +# @test t2 == @constinferred insertrightunit(t) +# @test space(t2) == insertleftunit(space(t)) +# @test @constinferred(removeunit(t2, $(numind(t2)))) == t +# t3 = @constinferred insertleftunit(t; copy = true) +# @test t3 == @constinferred insertrightunit(t; copy = true) +# @test @constinferred(removeunit(t3, $(numind(t3)))) == t + +# @test numind(t2) == numind(t) + 1 +# @test scalartype(t2) === T +# @test t.data === t2.data + +# @test t.data !== t3.data +# for (c, b) in blocks(t) +# @test b == block(t3, c) +# end + +# t4 = @constinferred insertrightunit(t, 3; dual = true) +# @test numin(t4) == numin(t) + 1 && numout(t4) == numout(t) +# for (c, b) in blocks(t) +# @test b == block(t4, c) +# end +# @test @constinferred(removeunit(t4, 4)) == t + +# t5 = @constinferred insertleftunit(t, 4; dual = true) +# @test numin(t5) == numin(t) + 1 && numout(t5) == numout(t) +# for (c, b) in blocks(t) +# @test b == block(t5, c) +# end +# @test @constinferred(removeunit(t5, 4)) == t +# end +# end + +# @timedtestset "Tensor conversion" begin +# W = V1 βŠ— V2 +# t = @constinferred randn(W ← W) # fusion matters here +# @test typeof(convert(TensorMap, t')) == typeof(t) +# tc = complex(t) +# @test convert(typeof(tc), t) == tc +# @test typeof(convert(typeof(tc), t)) == typeof(tc) +# @test typeof(convert(typeof(tc), t')) == typeof(tc) +# @test Base.promote_typeof(t, tc) == typeof(tc) +# @test Base.promote_typeof(tc, t) == typeof(tc + t) +# end + +# @timedtestset "Full trace: test self-consistency" begin +# t = rand(ComplexF64, V1 βŠ— V2 ← V1 βŠ— V2) # avoid permutes +# ss = @constinferred tr(t) +# @test conj(ss) β‰ˆ tr(t') +# @planar s2 = t[a b; a b] +# @planar t3[a; b] := t[a c; b c] +# @planar s3 = t3[a; a] + +# @test ss β‰ˆ s2 +# @test ss β‰ˆ s3 +# end + +# @timedtestset "Partial trace: test self-consistency" begin +# t = rand(ComplexF64, V3 βŠ— V4 βŠ— V5 ← V3 βŠ— V4 βŠ— V5) # compatible with module fusion +# @planar t2[a; b] := t[c a d; c b d] +# @planar t4[a b; c d] := t[e a b; e c d] +# @planar t5[a; b] := t4[a c; b c] +# @test t2 β‰ˆ t5 +# end + +# @timedtestset "Trace and contraction" begin #TODO: find some version of this that works for off-diagonal case +# t1 = rand(ComplexF64, V3 βŠ— V4 βŠ— V5) +# t2 = rand(ComplexF64, V3 βŠ— V4 βŠ— V5) +# t3 = t1 βŠ— t2' +# # if all(a.i != a.j for a in blocksectors(t3)) +# # replace!(x -> rand(ComplexF64), t3.data) # otherwise full of zeros in off-diagonal case +# # end +# if all(a.i == a.j for a in blocksectors(t3)) +# @planar ta[b; a] := conj(t2[x, a, y]) * t1[x, b, y] # works for diagonal case +# @planar tb[a; b] := t3[x a y; x b y] +# @test ta β‰ˆ tb +# end +# end + +# @timedtestset "Multiplication of isometries: test properties" begin +# W2 = V4 βŠ— V5 +# W1 = W2 βŠ— (rightunitspace(V5) βŠ• rightunitspace(V5)) +# for T in (Float64, ComplexF64) +# t1 = randisometry(T, W1, W2) +# t2 = randisometry(T, W2 ← W2) +# @test isisometric(t1) +# @test isunitary(t2) +# P = t1 * t1' +# @test P * P β‰ˆ P +# end +# end + +# @timedtestset "Multiplication and inverse: test compatibility" begin +# W1 = V1 βŠ— V2 +# W2 = V3 βŠ— V4 βŠ— V5 +# for T in (Float64, ComplexF64) +# t1 = rand(T, W1, W1) +# t2 = rand(T, W2 ← W2) +# t = rand(T, W1, W2) +# @test t1 * (t1 \ t) β‰ˆ t +# @test (t / t2) * t2 β‰ˆ t +# @test t1 \ one(t1) β‰ˆ inv(t1) +# @test one(t1) / t1 β‰ˆ pinv(t1) +# @test_throws SpaceMismatch inv(t) +# @test_throws SpaceMismatch t2 \ t +# @test_throws SpaceMismatch t / t1 +# tp = pinv(t) * t +# @test tp β‰ˆ tp * tp +# end +# end + +# @timedtestset "diag/diagm" begin +# W = V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 +# t = randn(ComplexF64, W) +# d = LinearAlgebra.diag(t) +# D = LinearAlgebra.diagm(codomain(t), domain(t), d) +# @test LinearAlgebra.isdiag(D) +# @test LinearAlgebra.diag(D) == d +# end + +# @timedtestset "Sylvester equation" begin +# for T in (Float32, ComplexF64) +# tA = rand(T, V1 βŠ— V2, V1 βŠ— V2) # rewritten for modules +# tB = rand(T, V4 βŠ— V5, V4 βŠ— V5) +# tA = 3 // 2 * leftorth(tA; alg = TK.Polar())[1] +# tB = 1 // 5 * leftorth(tB; alg = TK.Polar())[1] +# tC = rand(T, V1 βŠ— V2, V4 βŠ— V5) +# t = @constinferred sylvester(tA, tB, tC) +# @test codomain(t) == V1 βŠ— V2 +# @test domain(t) == V4 βŠ— V5 +# @test norm(tA * t + t * tB + tC) < +# (norm(tA) + norm(tB) + norm(tC)) * eps(real(T))^(2 / 3) +# end +# end + +# @timedtestset "Tensor product: test via norm preservation" begin # OOMs over here with full spaces +# for T in (Float32, ComplexF64) +# if !isempty(blocksectors(V2 βŠ— V1)) +# t1 = rand(T, V2 βŠ— V3 βŠ— V1, V1 βŠ— V2) +# t2 = rand(T, V2 βŠ— V1 βŠ— V3, V1 βŠ— V1) +# else +# t1 = rand(T, V3 βŠ— V4 βŠ— V5, V1 βŠ— V2) +# t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') +# end +# t = @constinferred (t1 βŠ— t2) +# @test norm(t) β‰ˆ norm(t1) * norm(t2) +# end +# end + +# # TODO: should this test exist? +# @timedtestset "Tensor product: test via tensor contraction" begin +# # W = V3 βŠ— V4 βŠ— V5 ← V1 βŠ— V2 +# W = V4 ← V1 βŠ— V2 # less costly +# for T in (Float32, ComplexF64) +# if !isdiag +# t1 = rand(T, W) +# t2 = rand(T, V4' ← V2' βŠ— V1') +# # t2 = rand(T, V5' βŠ— V4' βŠ— V3', V2' βŠ— V1') # same as previous test +# # @planar tβ€²[1 2 3 6 7 8; 4 5 9 10] := t1[1 2 3; 4 5] * t2[6 7 8; 9 10] +# @planar tβ€²[1 4; 2 3 5 6] := t1[1; 2 3] * t2[4; 5 6] +# else +# t1 = rand(T, V2 βŠ— V3, V1) +# t2 = rand(T, V2, V1 βŠ— V3) +# @planar tβ€²[1 2 4; 3 5 6] := t1[1 2; 3] * t2[4; 5 6] +# end +# t = @constinferred (t1 βŠ— t2) +# @test t β‰ˆ tβ€² +# end +# end +# end + +# @timedtestset "Tensor absorption" begin +# # absorbing small into large +# if !isempty(blocksectors(V2 βŠ— V3)) +# t1 = zeros(V1 βŠ• V1, V2 βŠ— V3) +# t2 = rand(V1, V2 βŠ— V3) +# else +# t1 = zeros(V1 βŠ• V2, V3 βŠ— V4 βŠ— V5) +# t2 = rand(V1, V3 βŠ— V4 βŠ— V5) +# end +# t3 = @constinferred absorb(t1, t2) +# @test norm(t3) β‰ˆ norm(t2) +# @test norm(t1) == 0 +# t4 = @constinferred absorb!(t1, t2) +# @test t1 === t4 +# @test t3 β‰ˆ t4 + +# # absorbing large into small +# if !isempty(blocksectors(V2 βŠ— V3)) +# t1 = rand(V1 βŠ• V1, V2 βŠ— V3) +# t2 = zeros(V1, V2 βŠ— V3) +# else +# t1 = rand(V1 βŠ• V2, V3 βŠ— V4 βŠ— V5) +# t2 = zeros(V1, V3 βŠ— V4 βŠ— V5) +# end +# t3 = @constinferred absorb(t2, t1) +# @test norm(t3) < norm(t1) +# @test norm(t2) == 0 +# t4 = @constinferred absorb!(t2, t1) +# @test t2 === t4 +# @test t3 β‰ˆ t4 +# end +# end + +# println("---------------------------------------") +# println("Factorizations with symmetry: $Istr") +# println("---------------------------------------") + +# @timedtestset "Factorizations with symmetry involving $Istr ($i, $j)" verbose = true for i in 1:r, j in 1:r +# isdiag = i == j + +# VC = ( +# Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), +# Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # avoids OOMs? +# Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 1), +# Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), +# Vect[I](unit(I(i, i, 1)) => 2, rand_object(I, i, i) => 3), +# ) + +# VM = Vect[I]((i, j, label) => 1 for label in 1:MTK._numlabels(I, i, j)) # all module objects + +# VM1 = ( +# Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), # written so V1 βŠ— V2 ← V3 βŠ— V4 βŠ— V5 works +# Vect[I](rand_object(I, i, j) => 2), # generally less blocksectors +# Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), +# VM, # important that V4 is module-graded +# Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), +# ) + +# VM2 = ( +# Vect[I](rand_object(I, i, j) => 2), # second set where module is V1 here +# Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), +# Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), +# VM, +# Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 1), +# ) + +# Vs = isdiag ? (VC,) : (VM1, VM2) # avoid duplicate runs + +# # some fail for (2, 2), (3, 3), (6, 6) +# # rightorth RQ(pos) and Polar (fail) for 2nd space +# # leftorth with QL(pos) and Polar for 1st space +# # leftnull QR for 1st space +# # cond and rank leftnull for 1st space + +# # factorization tests require equal objects in blocksectors of domain and codomain, so just put them all +# # FIXME: not sure if still needed +# # VC_all = fill(Vect[I]((i, i, label) => 1 for label in 1:MTK._numlabels(I, i, i)), 5) + +# # VM1_all = (Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), +# # VM, +# # Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), +# # VM, +# # Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 2) +# # ) + +# # VM2_all = (VM, +# # Vect[I](unit(I(j, j, 1)) => 1, rand_object(I, j, j) => 1), +# # Vect[I](unit(I(i, i, 1)) => 1, rand_object(I, i, i) => 1), +# # VM, +# # Vect[I](unit(I(j, j, 1)) => 2, rand_object(I, j, j) => 2) +# # ) + +# # fact_Vs = (i != j) ? (VM1_all, VM2_all) : (VC_all,) + +# @timedtestset "Factorization" for V in Vs +# V1, V2, V3, V4, V5 = V +# W = V1 βŠ— V2 +# @assert !isempty(blocksectors(W)) +# @assert !isempty(intersect(blocksectors(V4), blocksectors(W))) + +# @testset "QR decomposition" begin +# for T in eltypes, +# t in ( +# rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', +# DiagonalTensorMap(rand(T, reduceddim(V1)), V1), +# ) + +# Q, R = @constinferred qr_full(t) +# @test Q * R β‰ˆ t +# @test isunitary(Q) + +# Q, R = @constinferred qr_compact(t) +# @test Q * R β‰ˆ t +# @test isisometric(Q) + +# Q, R = @constinferred left_orth(t) +# @test Q * R β‰ˆ t +# @test isisometric(Q) + +# N = @constinferred qr_null(t) +# @test isisometric(N) +# @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) + +# N = @constinferred left_null(t) +# @test isisometric(N) +# @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) +# end + +# # empty tensor +# for T in eltypes +# t = rand(T, V1 βŠ— V2, zerospace(V1)) + +# Q, R = @constinferred qr_full(t) +# @test Q * R β‰ˆ t +# @test isunitary(Q) +# @test dim(R) == dim(t) == 0 + +# Q, R = @constinferred qr_compact(t) +# @test Q * R β‰ˆ t +# @test isisometric(Q) +# @test dim(Q) == dim(R) == dim(t) + +# Q, R = @constinferred left_orth(t) +# @test Q * R β‰ˆ t +# @test isisometric(Q) +# @test dim(Q) == dim(R) == dim(t) + +# N = @constinferred qr_null(t) +# @test isunitary(N) +# @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) +# end +# end + +# @testset "LQ decomposition" begin +# for T in eltypes, +# t in ( +# rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', +# DiagonalTensorMap(rand(T, reduceddim(V1)), V1), +# ) + +# L, Q = @constinferred lq_full(t) +# @test L * Q β‰ˆ t +# @test isunitary(Q) + +# L, Q = @constinferred lq_compact(t) +# @test L * Q β‰ˆ t +# @test isisometric(Q; side = :right) + +# L, Q = @constinferred right_orth(t) +# @test L * Q β‰ˆ t +# @test isisometric(Q; side = :right) + +# Nα΄΄ = @constinferred lq_null(t) +# @test isisometric(Nα΄΄; side = :right) +# @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) +# end + +# for T in eltypes +# # empty tensor +# t = rand(T, zerospace(V1), V1 βŠ— V2) + +# L, Q = @constinferred lq_full(t) +# @test L * Q β‰ˆ t +# @test isunitary(Q) +# @test dim(L) == dim(t) == 0 + +# L, Q = @constinferred lq_compact(t) +# @test L * Q β‰ˆ t +# @test isisometric(Q; side = :right) +# @test dim(Q) == dim(L) == dim(t) + +# L, Q = @constinferred right_orth(t) +# @test L * Q β‰ˆ t +# @test isisometric(Q; side = :right) +# @test dim(Q) == dim(L) == dim(t) + +# Nα΄΄ = @constinferred lq_null(t) +# @test isunitary(Nα΄΄) +# @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) +# end +# end + +# @testset "Polar decomposition" begin +# for T in eltypes, +# t in ( +# rand(T, W, W), rand(T, W, W)', rand(T, W, V4), rand(T, V4, W)', +# DiagonalTensorMap(rand(T, reduceddim(V1)), V1), +# ) + +# @assert domain(t) β‰Ύ codomain(t) +# w, p = @constinferred left_polar(t) +# @test w * p β‰ˆ t +# @test isisometric(w) +# @test isposdef(p) + +# w, p = @constinferred left_orth(t; alg = :polar) +# @test w * p β‰ˆ t +# @test isisometric(w) +# end + +# for T in eltypes, +# t in (rand(T, W, W), rand(T, W, W)', rand(T, V4, W), rand(T, W, V4)') + +# @assert codomain(t) β‰Ύ domain(t) +# p, wα΄΄ = @constinferred right_polar(t) +# @test p * wα΄΄ β‰ˆ t +# @test isisometric(wα΄΄; side = :right) +# @test isposdef(p) + +# p, wα΄΄ = @constinferred right_orth(t; alg = :polar) +# @test p * wα΄΄ β‰ˆ t +# @test isisometric(wα΄΄; side = :right) +# end +# end + +# @testset "SVD" begin +# for T in eltypes, +# t in ( +# rand(T, W, W), rand(T, W, W)', +# rand(T, W, V4), rand(T, V4, W), +# rand(T, W, V4)', rand(T, V4, W)', +# DiagonalTensorMap(rand(T, reduceddim(V1)), V1), +# ) + +# u, s, vα΄΄ = @constinferred svd_full(t) +# @test u * s * vα΄΄ β‰ˆ t +# @test isunitary(u) +# @test isunitary(vα΄΄) + +# u, s, vα΄΄ = @constinferred svd_compact(t) +# @test u * s * vα΄΄ β‰ˆ t +# @test isisometric(u) +# @test isposdef(s) +# @test isisometric(vα΄΄; side = :right) + +# sβ€² = @constinferred svd_vals(t) +# @test sβ€² β‰ˆ diagview(s) +# @test sβ€² isa TensorKit.SectorVector + +# v, c = @constinferred left_orth(t; alg = :svd) +# @test v * c β‰ˆ t +# @test isisometric(v) + +# c, vα΄΄ = @constinferred right_orth(t; alg = :svd) +# @test c * vα΄΄ β‰ˆ t +# @test isisometric(vα΄΄; side = :right) + +# N = @constinferred left_null(t; alg = :svd) +# @test isisometric(N) +# @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) + +# N = @constinferred left_null(t; trunc = (; atol = 100 * eps(norm(t)))) +# @test isisometric(N) +# @test norm(N' * t) β‰ˆ 0 atol = 100 * eps(norm(t)) + +# Nα΄΄ = @constinferred right_null(t; alg = :svd) +# @test isisometric(Nα΄΄; side = :right) +# @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) + +# Nα΄΄ = @constinferred right_null(t; trunc = (; atol = 100 * eps(norm(t)))) +# @test isisometric(Nα΄΄; side = :right) +# @test norm(t * Nα΄΄') β‰ˆ 0 atol = 100 * eps(norm(t)) +# end + +# # empty tensor +# for T in eltypes, t in (rand(T, W, zerospace(V1)), rand(T, zerospace(V1), W)) +# U, S, Vα΄΄ = @constinferred svd_full(t) +# @test U * S * Vα΄΄ β‰ˆ t +# @test isunitary(U) +# @test isunitary(Vα΄΄) + +# U, S, Vα΄΄ = @constinferred svd_compact(t) +# @test U * S * Vα΄΄ β‰ˆ t +# @test dim(U) == dim(S) == dim(Vα΄΄) == dim(t) == 0 +# end +# end + +# @testset "truncated SVD" begin +# for T in eltypes, +# t in ( +# randn(T, W, W), randn(T, W, W)', +# randn(T, W, V4), randn(T, V4, W), +# randn(T, W, V4)', randn(T, V4, W)', +# DiagonalTensorMap(randn(T, reduceddim(V1)), V1), +# ) + +# @constinferred normalize!(t) + +# U, S, Vα΄΄, Ο΅ = @constinferred svd_trunc(t; trunc = notrunc()) +# @test U * S * Vα΄΄ β‰ˆ t +# @test Ο΅ β‰ˆ 0 +# @test isisometric(U) +# @test isisometric(Vα΄΄; side = :right) + +# # dimension of S is a float for IsingBimodule +# nvals = round(Int, dim(domain(S)) / 2) +# trunc = truncrank(nvals) +# U1, S1, Vα΄΄1, Ο΅1 = @constinferred svd_trunc(t; trunc) +# @test t * Vα΄΄1' β‰ˆ U1 * S1 +# @test isisometric(U1) +# @test isisometric(Vα΄΄1; side = :right) +# @test norm(t - U1 * S1 * Vα΄΄1) β‰ˆ Ο΅1 atol = eps(real(T))^(4 / 5) +# @test dim(domain(S1)) <= nvals + +# Ξ» = minimum(diagview(S1)) +# trunc = trunctol(; atol = Ξ» - 10eps(Ξ»)) +# U2, S2, Vα΄΄2, Ο΅2 = @constinferred svd_trunc(t; trunc) +# @test t * Vα΄΄2' β‰ˆ U2 * S2 +# @test isisometric(U2) +# @test isisometric(Vα΄΄2; side = :right) +# @test norm(t - U2 * S2 * Vα΄΄2) β‰ˆ Ο΅2 atol = eps(real(T))^(4 / 5) +# @test minimum(diagview(S1)) >= Ξ» +# @test U2 β‰ˆ U1 +# @test S2 β‰ˆ S1 +# @test Vα΄΄2 β‰ˆ Vα΄΄1 +# @test Ο΅1 β‰ˆ Ο΅2 + +# trunc = truncspace(space(S2, 1)) +# U3, S3, Vα΄΄3, Ο΅3 = @constinferred svd_trunc(t; trunc) +# @test t * Vα΄΄3' β‰ˆ U3 * S3 +# @test isisometric(U3) +# @test isisometric(Vα΄΄3; side = :right) +# @test norm(t - U3 * S3 * Vα΄΄3) β‰ˆ Ο΅3 atol = eps(real(T))^(4 / 5) +# @test space(S3, 1) β‰Ύ space(S2, 1) + +# for trunc in (truncerror(; atol = Ο΅2), truncerror(; rtol = Ο΅2 / norm(t))) +# U4, S4, Vα΄΄4, Ο΅4 = @constinferred svd_trunc(t; trunc) +# @test t * Vα΄΄4' β‰ˆ U4 * S4 +# @test isisometric(U4) +# @test isisometric(Vα΄΄4; side = :right) +# @test norm(t - U4 * S4 * Vα΄΄4) β‰ˆ Ο΅4 atol = eps(real(T))^(4 / 5) +# @test Ο΅4 ≀ Ο΅2 +# end + +# trunc = truncrank(nvals) & trunctol(; atol = Ξ» - 10eps(Ξ»)) +# U5, S5, Vα΄΄5, Ο΅5 = @constinferred svd_trunc(t; trunc) +# @test t * Vα΄΄5' β‰ˆ U5 * S5 +# @test isisometric(U5) +# @test isisometric(Vα΄΄5; side = :right) +# @test norm(t - U5 * S5 * Vα΄΄5) β‰ˆ Ο΅5 atol = eps(real(T))^(4 / 5) +# @test minimum(diagview(S5)) >= Ξ» +# @test dim(domain(S5)) ≀ nvals +# end +# end + +# @testset "Eigenvalue decomposition" begin +# for T in eltypes, +# t in ( +# rand(T, V1, V1), rand(T, W, W), rand(T, W, W)', +# DiagonalTensorMap(rand(T, reduceddim(V1)), V1), +# ) + +# d, v = @constinferred eig_full(t) +# @test t * v β‰ˆ v * d + +# dβ€² = @constinferred eig_vals(t) +# @test dβ€² β‰ˆ diagview(d) +# @test dβ€² isa TensorKit.SectorVector + +# vdv = project_hermitian!(v' * v) +# @test @constinferred isposdef(vdv) +# t isa DiagonalTensorMap || @test !isposdef(t) # unlikely for non-hermitian map + +# nvals = round(Int, dim(domain(t)) / 2) +# d, v = @constinferred eig_trunc(t; trunc = truncrank(nvals)) +# @test t * v β‰ˆ v * d +# @test dim(domain(d)) ≀ nvals + +# t2 = @constinferred project_hermitian(t) +# D, V = eigen(t2) +# @test isisometric(V) +# DΜƒ, VΜƒ = @constinferred eigh_full(t2) +# @test D β‰ˆ DΜƒ +# @test V β‰ˆ VΜƒ +# Ξ» = minimum(real, diagview(D)) +# @test cond(VΜƒ) β‰ˆ one(real(T)) +# @test isposdef(t2) == isposdef(Ξ») +# @test isposdef(t2 - Ξ» * one(t2) + 0.1 * one(t2)) +# @test !isposdef(t2 - Ξ» * one(t2) - 0.1 * one(t2)) + +# d, v = @constinferred eigh_full(t2) +# @test t2 * v β‰ˆ v * d +# @test isunitary(v) + +# dβ€² = @constinferred eigh_vals(t2) +# @test dβ€² β‰ˆ diagview(d) +# @test dβ€² isa TensorKit.SectorVector + +# Ξ» = minimum(real, diagview(d)) +# @test cond(v) β‰ˆ one(real(T)) +# @test isposdef(t2) == isposdef(Ξ») +# @test isposdef(t2 - Ξ» * one(t) + 0.1 * one(t2)) +# @test !isposdef(t2 - Ξ» * one(t) - 0.1 * one(t2)) + +# d, v = @constinferred eigh_trunc(t2; trunc = truncrank(nvals)) +# @test t2 * v β‰ˆ v * d +# @test dim(domain(d)) ≀ nvals +# end +# end + +# @testset "Condition number and rank" begin +# for T in eltypes, +# t in ( +# rand(T, W, W), rand(T, W, W)', +# rand(T, W, V4), rand(T, V4, W), +# rand(T, W, V4)', rand(T, V4, W)', +# DiagonalTensorMap(rand(T, reduceddim(V1)), V1), +# ) + +# d1, d2 = dim(codomain(t)), dim(domain(t)) +# r = rank(t) +# @test r == min(d1, d2) +# @test typeof(r) == typeof(d1) +# M = left_null(t) +# @test @constinferred(rank(M)) + r β‰ˆ d1 +# Mα΄΄ = right_null(t) +# @test rank(Mα΄΄) + r β‰ˆ d2 +# end +# for T in eltypes +# u = unitary(T, V1 βŠ— V2, V1 βŠ— V2) +# @test @constinferred(cond(u)) β‰ˆ one(real(T)) +# @test @constinferred(rank(u)) == dim(V1 βŠ— V2) + +# t = rand(T, zerospace(V1), W) +# @test rank(t) == 0 +# t2 = rand(T, zerospace(V1) * zerospace(V2), zerospace(V1) * zerospace(V2)) +# @test rank(t2) == 0 +# @test cond(t2) == 0.0 +# end +# for T in eltypes, t in (rand(T, W, W), rand(T, W, W)') +# project_hermitian!(t) +# vals = @constinferred LinearAlgebra.eigvals(t) +# Ξ»max = maximum(s -> maximum(abs, s), values(vals)) +# Ξ»min = minimum(s -> minimum(abs, s), values(vals)) +# @test cond(t) β‰ˆ Ξ»max / Ξ»min +# end +# end + +# @testset "Hermitian projections" begin +# for T in eltypes, +# t in ( +# rand(T, V1, V1), rand(T, W, W), rand(T, W, W)', +# DiagonalTensorMap(rand(T, reduceddim(V1)), V1), +# ) +# normalize!(t) +# noisefactor = eps(real(T))^(3 / 4) + +# th = (t + t') / 2 +# ta = (t - t') / 2 +# tc = copy(t) + +# thβ€² = @constinferred project_hermitian(t) +# @test ishermitian(thβ€²) +# @test thβ€² β‰ˆ th +# @test t == tc +# th_approx = th + noisefactor * ta +# @test !ishermitian(th_approx) || (T <: Real && t isa DiagonalTensorMap) +# @test ishermitian(th_approx; atol = 10 * noisefactor) + +# taβ€² = project_antihermitian(t) +# @test isantihermitian(taβ€²) +# @test taβ€² β‰ˆ ta +# @test t == tc +# ta_approx = ta + noisefactor * th +# @test !isantihermitian(ta_approx) +# @test isantihermitian(ta_approx; atol = 10 * noisefactor) || (T <: Real && t isa DiagonalTensorMap) +# end +# end + +# @testset "Isometric projections" begin +# for T in eltypes, +# t in ( +# randn(T, W, W), randn(T, W, W)', +# randn(T, W, V4), randn(T, V4, W)', +# ) +# t2 = project_isometric(t) +# @test isisometric(t2) +# t3 = project_isometric(t2) +# @test t3 β‰ˆ t2 # stability of the projection +# @test t2 * (t2' * t) β‰ˆ t + +# tc = similar(t) +# t3 = @constinferred project_isometric!(copy!(tc, t), t2) +# @test t3 === t2 +# @test isisometric(t2) + +# # test that t2 is closer to A then any other isometry +# for k in 1:10 +# Ξ΄t = randn!(similar(t)) +# t3 = project_isometric(t + Ξ΄t / 100) +# @test norm(t - t3) > norm(t - t2) +# end +# end +# end +# end +# end From 8737431186de87ccea59b00b8b28d46372a559da Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 14:11:23 +0100 Subject: [PATCH 191/206] format src --- src/bimodulesector.jl | 93 +++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/src/bimodulesector.jl b/src/bimodulesector.jl index 1d01f8c..2e8f93c 100644 --- a/src/bimodulesector.jl +++ b/src/bimodulesector.jl @@ -10,15 +10,15 @@ struct BimoduleSector{Name} <: Sector i <= size(BimoduleSector{Name}) && j <= size(BimoduleSector{Name}) || throw(DomainError("object outside the matrix $Name")) return label <= _numlabels(BimoduleSector{Name}, i, j) ? new{Name}(i, j, label) : - throw(DomainError("label outside category $Name($i, $j)")) + throw(DomainError("label outside category $Name($i, $j)")) end end -BimoduleSector{Name}(data::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(data...) +BimoduleSector{Name}(data::NTuple{3, Int}) where {Name} = BimoduleSector{Name}(data...) BimoduleSectorName(::Type{BimoduleSector{Name}}) where {Name} = Name const A4Object = BimoduleSector{:A4} -Base.convert(::Type{<:BimoduleSector{Name}}, labels::NTuple{3,Int}) where {Name} = BimoduleSector{Name}(labels...) +Base.convert(::Type{<:BimoduleSector{Name}}, labels::NTuple{3, Int}) where {Name} = BimoduleSector{Name}(labels...) function Base.show(io::IO, a::BimoduleSector{Name}) where {Name} if get(io, :typeinfo, nothing) === typeof(a) @@ -31,11 +31,11 @@ end # Utility implementations # ----------------------- -function Base.isless(a::I, b::I) where {I<:BimoduleSector} +function Base.isless(a::I, b::I) where {I <: BimoduleSector} return isless((a.i, a.j, a.label), (b.i, b.j, b.label)) end Base.hash(a::BimoduleSector, h::UInt) = hash(a.i, hash(a.j, hash(a.label, h))) -function Base.convert(::Type{BimoduleSector{Name}}, d::NTuple{3,Int}) where {Name} +function Base.convert(::Type{BimoduleSector{Name}}, d::NTuple{3, Int}) where {Name} return BimoduleSector{Name}(d...) end @@ -43,7 +43,7 @@ Base.size(::Type{A4Object}) = 7 Base.IteratorSize(::Type{<:SectorValues{<:BimoduleSector}}) = Base.SizeUnknown() -function Base.iterate(iter::SectorValues{<:BimoduleSector}, (I, label)=(1, 1)) +function Base.iterate(iter::SectorValues{<:BimoduleSector}, (I, label) = (1, 1)) A = eltype(iter) s = size(A) I > s * s && return nothing @@ -56,7 +56,7 @@ function Base.iterate(iter::SectorValues{<:BimoduleSector}, (I, label)=(1, 1)) end end -function Base.length(::SectorValues{I}) where {I<:BimoduleSector} +function Base.length(::SectorValues{I}) where {I <: BimoduleSector} s = size(I) return sum(_numlabels(I, i, j) for i in 1:s, j in 1:s) end @@ -65,15 +65,16 @@ TensorKitSectors.FusionStyle(::Type{A4Object}) = GenericFusion() TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding() TensorKitSectors.sectorscalartype(::Type{A4Object}) = ComplexF64 -function TensorKitSectors.:βŠ—(a::I, b::I) where {I<:BimoduleSector} +function TensorKitSectors.:βŠ—(a::I, b::I) where {I <: BimoduleSector} @assert a.j == b.i Ncache = _get_Ncache(I)[a.i, a.j, b.j] - return I[I(a.i, b.j, c_l) - for (a_l, b_l, c_l) in keys(Ncache) - if (a_l == a.label && b_l == b.label)] + return I[ + I(a.i, b.j, c_l) for (a_l, b_l, c_l) in keys(Ncache) + if (a_l == a.label && b_l == b.label) + ] end -function _numlabels(::Type{T}, i, j) where {T<:BimoduleSector} +function _numlabels(::Type{T}, i, j) where {T <: BimoduleSector} return length(_get_dual_cache(T)[2][i, j]) end @@ -91,27 +92,26 @@ function extract_Nsymbol(::Type{I}) where {I <: BimoduleSector} isfile(filename) || throw(LoadError(filename, 0, "Nsymbol file not found for $name")) Narray = readdlm(filename) # matrix with 7 columns - data_dict = Dict{NTuple{3,Int},Dict{NTuple{3,Int},Int}}() + data_dict = Dict{NTuple{3, Int}, Dict{NTuple{3, Int}, Int}}() for row in eachrow(Narray) i, j, k, a, b, c, N = Int.(@view(row[1:size(I)])) - colordict = get!(data_dict, (i, j, k), Dict{NTuple{3,Int},Int}()) + colordict = get!(data_dict, (i, j, k), Dict{NTuple{3, Int}, Int}()) push!(colordict, (a, b, c) => N) end return data_dict end -const Ncache = IdDict{Type{<:BimoduleSector}, - Dict{NTuple{3,Int},Dict{NTuple{3,Int},Int}}}() +const Ncache = IdDict{Type{<:BimoduleSector}, Dict{NTuple{3, Int}, Dict{NTuple{3, Int}, Int}}}() -function _get_Ncache(::Type{T}) where {T<:BimoduleSector} +function _get_Ncache(::Type{T}) where {T <: BimoduleSector} global Ncache return get!(Ncache, T) do return extract_Nsymbol(T) end end -function TensorKitSectors.Nsymbol(a::I, b::I, c::I) where {I<:BimoduleSector} +function TensorKitSectors.Nsymbol(a::I, b::I, c::I) where {I <: BimoduleSector} # TODO: should this error or return 0? (a.j == b.i && a.i == c.i && b.j == c.j) || throw(ArgumentError("invalid fusion channel")) @@ -119,9 +119,9 @@ function TensorKitSectors.Nsymbol(a::I, b::I, c::I) where {I<:BimoduleSector} return get(_get_Ncache(I)[i, j, k], (a.label, b.label, c.label), 0) end -const Dualcache = IdDict{Type{<:BimoduleSector},Tuple{Vector{Int64},Matrix{Vector{Int64}}}}() +const Dualcache = IdDict{Type{<:BimoduleSector}, Tuple{Vector{Int64}, Matrix{Vector{Int64}}}}() -function _get_dual_cache(::Type{T}) where {T<:BimoduleSector} +function _get_dual_cache(::Type{T}) where {T <: BimoduleSector} global Dualcache return get!(Dualcache, T) do return extract_dual(T) @@ -171,7 +171,7 @@ function extract_dual(::Type{I}) where {I <: BimoduleSector} allduals[i, j] = Int[] nobjj = maximum(first, keys(N[j, j, j])) - # the nested vectors contain the duals of the objects in π’ž_ij, which are in C_ji + # the nested vectors contain the duals of the objects in π’ž_ij, which are in C_ji Niji = N[i, j, i] # π’ž_ij x π’ž_ji -> C_ii Njij = N[j, i, j] # π’ž_ji x π’ž_ij -> C_jj for i_ob in 1:nobji, j_ob in 1:nobjj @@ -211,22 +211,22 @@ function TensorKitSectors.dual(a::BimoduleSector) end function extract_Fsymbol(::Type{I}) where {I <: BimoduleSector} - result = Dict{NTuple{4,Int},Dict{NTuple{6,Int},Array{ComplexF64,4}}}() + result = Dict{NTuple{4, Int}, Dict{NTuple{6, Int}, Array{ComplexF64, 4}}}() name = string(BimoduleSectorName(I)) filename = joinpath(artifact_path, name, "Fsymbol.txt") @assert isfile(filename) "cannot find $filename" + Farray = readdlm(filename) for ((i, j, k, l), colordict) in convert_Fs(Farray) - result[(i, j, k, l)] = Dict{NTuple{6,Int},Array{ComplexF64,4}}() + result[(i, j, k, l)] = Dict{NTuple{6, Int}, Array{ComplexF64, 4}}() for ((a, b, c, d, e, f), Fvals) in colordict - a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = I.(((i, j, a), (j, k, b), - (k, l, c), (i, l, d), - (i, k, e), (j, l, f))) - result[(i, j, k, l)][(a, b, c, d, e, f)] = zeros(ComplexF64, - Nsymbol(a_ob, b_ob, e_ob), - Nsymbol(e_ob, c_ob, d_ob), - Nsymbol(b_ob, c_ob, f_ob), - Nsymbol(a_ob, f_ob, d_ob)) + a_ob, b_ob, c_ob, d_ob, e_ob, f_ob = I.( + ((i, j, a), (j, k, b), (k, l, c), (i, l, d), (i, k, e), (j, l, f)) + ) + result[(i, j, k, l)][(a, b, c, d, e, f)] = zeros( + ComplexF64, Nsymbol(a_ob, b_ob, e_ob), Nsymbol(e_ob, c_ob, d_ob), + Nsymbol(b_ob, c_ob, f_ob), Nsymbol(a_ob, f_ob, d_ob) + ) for (K, v) in Fvals result[(i, j, k, l)][(a, b, c, d, e, f)][K] = v end @@ -236,35 +236,34 @@ function extract_Fsymbol(::Type{I}) where {I <: BimoduleSector} end function convert_Fs(Farray_part::Matrix{Float64}) # Farray_part is a matrix with 16 columns - data_dict = Dict{NTuple{4,Int}, - Dict{NTuple{6,Int},Vector{Pair{CartesianIndex{4},ComplexF64}}}}() - # want to make a Dict with keys (i,j,k,l) and vals - # a Dict with keys (a,b,c,d,e,f) and vals + data_dict = Dict{NTuple{4, Int}, Dict{NTuple{6, Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}}() + # want to make a Dict with keys (i,j,k,l) and vals + # a Dict with keys (a,b,c,d,e,f) and vals # a pair of (mu, nu, rho, sigma) and the F value for row in eachrow(Farray_part) i, j, k, l, a, b, c, d, e, f, mu, nu, rho, sigma = Int.(@view(row[1:14])) v = complex(row[15], row[16]) - colordict = get!(data_dict, (i, j, k, l), - Dict{NTuple{6,Int},Vector{Pair{CartesianIndex{4},ComplexF64}}}()) - Fdict = get!(colordict, (a, b, c, d, e, f), - Vector{Pair{CartesianIndex{4},ComplexF64}}()) + colordict = get!( + data_dict, (i, j, k, l), Dict{NTuple{6, Int}, Vector{Pair{CartesianIndex{4}, ComplexF64}}}() + ) + Fdict = get!( + colordict, (a, b, c, d, e, f), Vector{Pair{CartesianIndex{4}, ComplexF64}}() + ) push!(Fdict, CartesianIndex(mu, nu, rho, sigma) => v) end return data_dict end -const Fcache = IdDict{Type{<:BimoduleSector}, - Dict{NTuple{4,Int64},Dict{NTuple{6,Int64},Array{ComplexF64,4}}}}() +const Fcache = IdDict{Type{<:BimoduleSector}, Dict{NTuple{4, Int64}, Dict{NTuple{6, Int64}, Array{ComplexF64, 4}}}}() -function _get_Fcache(::Type{T}) where {T<:BimoduleSector} +function _get_Fcache(::Type{T}) where {T <: BimoduleSector} global Fcache return get!(Fcache, T) do return extract_Fsymbol(T) end end -function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, - f::I) where {I<:BimoduleSector} +function TensorKitSectors.Fsymbol(a::I, b::I, c::I, d::I, e::I, f::I) where {I <: BimoduleSector} # required to keep track of multiplicities where F-move is partially unallowed # also deals with invalid fusion channels Nabe = Nsymbol(a, b, e) @@ -285,8 +284,8 @@ end #----------------------------------------- # TODO: can remove this once the otimes assert is removed -function TensorKit.fuse(V₁::GradedSpace{I}, Vβ‚‚::GradedSpace{I}) where {I<:BimoduleSector} - dims = TensorKit.SectorDict{I,Int}() +function TensorKit.fuse(V₁::GradedSpace{I}, Vβ‚‚::GradedSpace{I}) where {I <: BimoduleSector} + dims = TensorKit.SectorDict{I, Int}() for a in sectors(V₁), b in sectors(Vβ‚‚) a.j == b.i || continue # skip if not compatible for c in a βŠ— b @@ -312,4 +311,4 @@ end # function leftunitspace(S::SumSpace{<:GradedSpace{<:BimoduleSector}}) # @assert !isempty(S) "Cannot determine type of empty space" # return SumSpace(leftunitspace(first(S.spaces))) -# end \ No newline at end of file +# end From 11aa36853bccb7875d9871883c06786321c1e318 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 14:26:45 +0100 Subject: [PATCH 192/206] basic properties edit --- test/test_A4.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index 016d29d..f1e94ad 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -61,9 +61,13 @@ end @constinferred dual(s[1]) @test dual(s[1]) == I.(i, i, MTK._get_dual_cache(I)[2][i, i][s[1].label]) @constinferred dim(s[1]) - @constinferred frobeniusschur(s[1]) + @constinferred frobenius_schur_phase(s[1]) + @constinferred frobenius_schur_indicator(s[1]) + @constinferred Nsymbol(s...) + @constinferred Asymbol(s...) @constinferred Bsymbol(s...) - @constinferred Fsymbol(s..., s...) + F = @constinferred Fsymbol(s..., s...) + @test eltype(F) <: @testinferred sectorscalartype(I) end else @testset "Basic module properties" begin @@ -83,7 +87,9 @@ end @test dual(dual(m)) == m @constinferred dim(m) - @constinferred frobeniusschur(m) + @constinferred frobenius_schur_phase(m) + @constinferred frobenius_schur_indicator(m) + @constinferred Asymbol(m, mop, c) @constinferred Bsymbol(m, mop, c) @constinferred Fsymbol(mop, m, mop, mop, d, c) end From e5d99a5dfaf21e1bb863cb80692fb28d6726b949 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 23 Dec 2025 17:11:18 +0100 Subject: [PATCH 193/206] remove `Asymbol` test for modules --- test/test_A4.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_A4.jl b/test/test_A4.jl index f1e94ad..9b2cada 100644 --- a/test/test_A4.jl +++ b/test/test_A4.jl @@ -89,7 +89,6 @@ end @constinferred dim(m) @constinferred frobenius_schur_phase(m) @constinferred frobenius_schur_indicator(m) - @constinferred Asymbol(m, mop, c) @constinferred Bsymbol(m, mop, c) @constinferred Fsymbol(mop, m, mop, mop, d, c) end From ee3a8e63bc82948a8837d99793817e11ab44eb93 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 10 Feb 2026 10:24:01 +0100 Subject: [PATCH 194/206] start of extension explanation --- docs/src/man/extension.md | 71 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 docs/src/man/extension.md diff --git a/docs/src/man/extension.md b/docs/src/man/extension.md new file mode 100644 index 0000000..b6af46a --- /dev/null +++ b/docs/src/man/extension.md @@ -0,0 +1,71 @@ +# MultiTensorKit as an extension to TensorKit + +This section will explain the internal changes to TensorKit which are required to extend the compatibility with fusion categories to multifusion ones. +Users who are unfamiliar with TensorKit are kindly guided towards the [TensorKit tutorial](https://jutho.github.io/TensorKit.jl/stable/man/tutorial/). + +## As a `Sector` +MultiTensorKit is at its core an extension to [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl), as it simply provides a new `Sector`, i.e. simple objects of a multifusion category, named `BimoduleSector`. + +````julia +struct BimoduleSector{Name} <: Sector + i::Int + j::Int + label::Int +end +```` + +`i` and `j` specify which subcategory $\mathcal{C}_{ij}$ we are considering, and `label` selects a particular simple object within that subcategory. +`Name` selects which multifusion category to work with, and is a `Symbol`. +As of now, only `:A4` is available, referring to the multifusion category consisting of $\mathsf{Rep(A_4)}$ as the largest fusion category, and all its Morita dual fusion categories and corresponding bimodule categories. +The fusion of these `BimoduleSector`s is then defined by the fusion rules of the multifusion category. +In particular, +````julia +a = BimoduleSector{:A4}(i, j, label1) +b = BimoduleSector{:A4}(k, l, label2) +a βŠ— b # empty unless j == k +```` + +The fusion rules are read in via the artifact labeled "fusiondata", and are extracted at runtime when calling the fusion of two `BimoduleSector`s (or `Nsymbol`) for the first time. +These data are cached in a hash table for later use. + +A consequence of the multifusion structure is the colorings used in the graphical calculus of fusions. +A natural introduction is the notion of a *left* and *right* unit of some (simple) object in the multifusion category. +Clearly, for the usual case of just one fusion category, these both coincide with the unique unit object. +Via the fusion rules, the left and right units of all `BimoduleSector`s along with their duals are also extracted and cached. +Since the most general fusion rule possible is one with multiplicities involved, the entire `BimoduleSector` is set to have `TensorKitSectors.FusionStyle(::Type{<:BimoduleSector}) = GenericFusion()`. + +Going beyond the ring structure, the F-symbols are also read in from the artifact, and are stored in a hash table for later use. +The F-symbols are then used to perform F-moves on `BimoduleSector`s, which is required to perform recouplings of fusion trees when doing e.g. contractions of tensors with these categories grading the vector spaces. + +Due to the nature of the multifusion category, it is currently not possible to define a non-trivial braiding on the `BimoduleSector`s, so these are set to be non-braided: `TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding()`. +This is especially important when working with matrix product states, as all algorithms are required to remain planar, since no (half-)braiding is available to perform crossings of fusion trees. + +## As a symmetry in TensorKit +Since `BimoduleSector`s are `Sector`s, they can be used as symmetries in TensorKit. +This way, we can construct symmetric tensors with the symmetries of the multifusion category, which are more general than those of the fusion categories. +In particular, the vector spaces graded by these `BimoduleSector`s are not only graded by the simple objects of the fusion categories, but also by the simple objects of the bimodule categories. +This allows for more general tensor network simulations of quantum many-body systems with symmetries which go beyond those of fusion categories. + +Certain changes within TensorKit were required to make it compatible with the multifusion categorical structure. +In particular, the presence of a simple unit object for every fusion category on the diagonal of the multifusion category, along with the off-diagonal nature of the simple objects of the bimodule categories, required some internal changes to the way unit objects were treated in TensorKit. +Most notably, the unit object is no longer unique, and thus it is of utmost importance that the correct unit object is considered when performing tensor contractions at the level of the fusion trees. +This is achieved precisely through colorings and the use of `leftunit` and `rightunit`. +For this reason, every fusion tree manipulation which previously involved "the" unit object, now involves the `leftunit` and `rightunit` of some neighboring sector in the manipulation to identify the correct color. +An important example of this is explained in the previous section [opposite module categories], namely the mapping of a splitting vertex to a fusion vertex through the B-move. + +# MultiTensorKit compatibility with MPSKit + +This section will briefly explain the changes within MPSKit which are required to make it compatible with MultiTensorKit. +For a more practical explanation, users are kindly guided towards the next section [implementation]. + +The main change within MPSKit is very similar to the fusion tree manipulations in TensorKit, namely the use of `leftunit` and `rightunit` to identify the correct unit object. +In the case of MPSKit, trivial spaces are used everywhere, from the boundary of a finite MPS to the virtual spaces of a Hamiltonian written in MPO form. +Additionally, multiple tensor contractions made use of braiding tensors to perform crossings of legs of the MPS/MPOs. +Since no (half-)braiding is available for the `BimoduleSector`s, all algorithms had to be made planar, and thus all braiding tensors were removed. +Since all braidings were trivial, this was dealt with by simply removing the braiding tensors and replacing the crossing of legs with a termination and reintroduction of the legs without crossing. +This is achieved through `TensorKit.removeunit` and `TensorKit.insertleftunit`/`TensorKit.insertrightunit`, which remove and insert spaces with the correct unit object, respectively, based on the grading of neighboring vector spaces. +At the level of the MPS, the correct unit object can be identified through the use of `leftunit` and `rightunit`. +When the virtual space of the MPS is graded by a diagonal `BimoduleSector`, i.ea unitary fusion category, then these all coincide with the unique unit object of that fusion category. +However, when the virtual space is graded by an off-diagonal `BimoduleSector`, i.e. a bimodule category, then the left and right units are different, and thus it is important to identify the correct one when performing MPS algorithms. +For example, Hamiltonians should always have the same coloring as the right unit of the MPS, since they are contracted at the physical level of the MPS. +Similarly, excitations of an MPS are labeled by `BimoduleSector`s with the same coloring as the left unit of the MPS, since the auxiliary charge leg of the excitation is attached on the other side of the MPS to the virtual level. \ No newline at end of file From 6e8b7be33af751e157893781807901951a5ac948 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 10 Feb 2026 10:24:25 +0100 Subject: [PATCH 195/206] minor changes --- docs/make.jl | 3 ++- docs/src/index.md | 4 ++-- docs/src/man/implementation.md | 30 +++++++++++++++--------------- docs/src/man/multifusioncats.md | 6 +++--- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 4e93ef2..8356949 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,9 +1,10 @@ using Documenter using DocumenterCitations +# using TensorKitSectors, TensorKit using MultiTensorKit pages = ["Home" => "index.md", - "Manual" => ["man/fusioncats.md", "man/multifusioncats.md", "man/implementation.md"], + "Manual" => ["man/fusioncats.md", "man/multifusioncats.md", "man/extension.md", "man/implementation.md"], "Library" => "lib/library.md", "References" => "references.md"] diff --git a/docs/src/index.md b/docs/src/index.md index 63c1b2d..f9e9a9b 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -5,7 +5,7 @@ ## Package summary MultiTensorKit.jl provides the user a package to work with multifusion categories, the extension of regular fusion categories where the unit is no longer simple and unique. Multifusion categories naturally embed the structure of module categories over fusion categories. Hence, MultiTensorKit.jl allows not only the fusion of objects within the same -fusion category (as TensorKit.jl), but also the fusion with and between module categories over these fusion categories. +fusion category (as TensorKit.jl), but also the fusion with and between module categories over these fusion categories. MultiTensorKit.jl is built to be compatible with TensorKit, thus allowing the construction of symmetric tensors with new symmetries due to the module structure. Through this, tensor network simulations of quantum many-body systems with aid of [MPSKit.jl](https://github.com/QuantumKitHub/MPSKit.jl) can be performed. @@ -30,5 +30,5 @@ As the name suggests, MultiTensorKit is an extension of [TensorKit.jl](https://g [TensorKitSectors.jl](https://github.com/QuantumKitHub/TensorKitSectors.jl). Therefore, we recommend including TensorKit to your project. Additionally, MultiTensorKit was made to be functional with [MPSKit.jl](https://github.com/QuantumKitHub/MPSKit.jl) and [MPSKitModels.jl](https://github.com/QuantumKitHub/MPSKitModels.jl) for Matrix Product State (MPS) calculations, supporting symmetries -which go beyond TensorKit. All these packages are registered in JuliaRegistries and can be added through the package manager. +which go beyond TensorKit. In particular, TensorKit v0.16.0 and MPSKit v0.13.9 contain the necessary functionality to deal with the multifusion categorical structure provided by MultiTensorKit. All these packages are registered in JuliaRegistries and can be added through the package manager. diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 28abc23..66face2 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -29,7 +29,7 @@ The easiest way to identify which elements of the multifusion category correspon Now that we have identified the fusion and module categories, we want to select the relevant objects we wish to place in our graded spaces. Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. Hence, the simplest way to find the unit object of a fusion subcategory is ````julia -one(A4Object(i,i,1)) +unit(A4Object(i,i,1)) ```` Left and right units of subcategories are uniquely specified by their fusion rules. For example, the left unit of a subcategory $\mathcal{C}_{ij}$ is the simple object in $\mathcal{C}_i$ for which @@ -41,7 +41,7 @@ A similar condition uniquely defines the right unit of a subcategory. For fusion Identifying the other simple objects of a (not necessarily fusion) category requires more work. We recommend a combination of the following to uniquely determine any simple object `a`: - Check the dimension of the simple object: `dim(a)` - Check the dual of the simple object: `dual(a)` -- Check how this simple object fuses with other (simple) objects: `Nsymbol(a,b,c)` +- Check how this simple object fuses with other (simple) objects: `Nsymbol(a, b, c)` The dual object of some simple object $a$ of an arbitrary subcategory $\mathcal{C}_{ij}$ is defined as the unique object $a^* \in \mathcal{C}_{ji}$ satisfying @@ -63,24 +63,24 @@ Since we want to replicate a spin-1 Heisenberg model, it makes sense to use the P = Vect[A4Object](D4 => 1) # physical space T = ComplexF64 # usual Heisenberg part -h1_L = TensorMap(zeros, T, P βŠ— P ← P) -h1_R = TensorMap(zeros, T, P ← P βŠ— P) +h1_L = zeros(T, P βŠ— P ← P) +h1_R = zeros(T, P ← P βŠ— P) block(h1_L, D4) .= [0; 1] block(h1_R, D4) .= [0 1;] -@plansor h1[-1 -2; -3 -4] := h1_L[-1 1; -3] * h1_R[-2; 1 -4] +@planar h1[-1 -2; -3 -4] := h1_L[-1 1; -3] * h1_R[-2; 1 -4] # biquadratic term -h2_L = TensorMap(zeros, T, P βŠ— Vect[A4Object](D1 => 1, D2 => 1, D3 => 1) ← P) -h2_R = TensorMap(ones, T, P ← Vect[A4Object](D1 => 1, D2 => 1, D3 => 1) βŠ— P) +h2_L = zeros(T, P βŠ— Vect[A4Object](D1 => 1, D2 => 1, D3 => 1) ← P) +h2_R = ones(T, P ← Vect[A4Object](D1 => 1, D2 => 1, D3 => 1) βŠ— P) block(h2_L, D4) .= [4 / 3; 1 / 3; 1 / 3] -@plansor h2[-1 -2; -3 -4] := h2_L[-1 1; -3] * h2_R[-2; 1 -4] +@planar h2[-1 -2; -3 -4] := h2_L[-1 1; -3] * h2_R[-2; 1 -4] # anti-commutation term -h3_L = TensorMap(zeros, T, P βŠ— P ← P) -h3_R = TensorMap(zeros, T, P ← P βŠ— P) +h3_L = zeros(T, P βŠ— P ← P) +h3_R = zeros(T, P ← P βŠ— P) block(h3_L, D4) .= [1; 0] block(h3_R, D4) .= [0 1;] -@plansor h3[-1 -2; -3 -4] := h3_L[-1 1; -3] * h3_R[-2; 1 -4] +@planar h3[-1 -2; -3 -4] := h3_L[-1 1; -3] * h3_R[-2; 1 -4] L = 60 J1 = -2.0 # probing the A4 symmetric phase first @@ -106,7 +106,7 @@ init_mps = FiniteMPS(L, P, V; left=Vb, right=Vb) ```` !!! warning "Important" - We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for any `BimoduleSector` due to the semisimple unit. + We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for any `BimoduleSector` due to the semisimple unit. ## DMRG2 and the entanglement spectrum We can now look to find the ground state of the Hamiltonian with two-site DMRG. We use this instead of the "usual" one-site DMRG because the two-site one will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. @@ -132,7 +132,7 @@ Consider a quantum lattice model with its symmetries determing the phase diagram ````julia module_numlabels(i) = MultiTensorKit._numlabels(A4Object, i, 6) -V = Vect[A4Object](A4Object(i, 6, label) => D for label in 1:module_numlabels(i)) +V = Vect[A4Object]((i, 6, label) => D for label in 1:module_numlabels(i)) Vb = Vect[A4Object](first(sectors(V)) => 1) # not all charges on boundary, play around with what is there ```` @@ -157,10 +157,10 @@ init = InfiniteMPS([P], [V]) inf_alg = VUMPS(; verbosity=2, tol=1e-7) ```` -Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `Sector`. It is also clear that boundary terms do not play a role in this case. +Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `BimoduleSector`. It is also clear that boundary terms do not play a role in this case. !!! note "More functions for infinite systems" - When dealing with an infinite system, additional information can be retrieved from the matrix product state. These also require a keyword argument `sector` to be specified. These are + When dealing with an infinite system, additional information can be retrieved from the matrix product state. These also require a keyword argument `sector` to be specified, as otherwise the correct unit object is placed by default. These are - `transfer_spectrum`: similar to `excitations`, the (partial) transfer matrix spectrum is selected by adding a charged auxiliary space to the transfer matrix eigenvectors. - `correlation_length`: since this function calls `transfer_spectrum`, the same logic applies. - `excitations` in the infinite case also requires the keyword argument. \ No newline at end of file diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 414eea1..227f230 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -43,11 +43,11 @@ for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. The left module associator also ful ``` -We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as +We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{\bowtie}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as -$${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F^{aA\alpha}: (a \triangleright A) \triangleleft \alpha \rightarrow a \triangleright (A \triangleleft \alpha)$$ +$${}^{\bowtie}\!F^{aA\alpha}: (a \triangleright A) \triangleleft \alpha \rightarrow a \triangleright (A \triangleleft \alpha)$$ -for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. The bimodule associator fulfills a mixed pentagon equation with the module associators. An F-move with ${}^{{\triangleright \hspace{-1.2mu}\triangleleft}}\!F$ is given by: +for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. The bimodule associator fulfills a mixed pentagon equation with the module associators. An F-move with ${}^{\bowtie}\!F$ is given by: ```@raw html From db7b204a27e99916f12ddb207e2b195104b0d376 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 10 Feb 2026 10:31:46 +0100 Subject: [PATCH 196/206] line breaks per sentence --- docs/src/index.md | 19 ++-- docs/src/man/fusioncats.md | 39 ++++++-- docs/src/man/implementation.md | 91 ++++++++++++----- docs/src/man/multifusioncats.md | 170 ++++++++++++++++++++++++-------- 4 files changed, 235 insertions(+), 84 deletions(-) diff --git a/docs/src/index.md b/docs/src/index.md index f9e9a9b..a08ae7c 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -4,10 +4,12 @@ ## Package summary MultiTensorKit.jl provides the user a package to work with multifusion categories, the extension of regular fusion categories where the unit is no longer simple and unique. -Multifusion categories naturally embed the structure of module categories over fusion categories. Hence, MultiTensorKit.jl allows not only the fusion of objects within the same +Multifusion categories naturally embed the structure of module categories over fusion categories. +Hence, MultiTensorKit.jl allows not only the fusion of objects within the same fusion category (as TensorKit.jl), but also the fusion with and between module categories over these fusion categories. -MultiTensorKit.jl is built to be compatible with TensorKit, thus allowing the construction of symmetric tensors with new symmetries due to the module structure. Through this, +MultiTensorKit.jl is built to be compatible with TensorKit, thus allowing the construction of symmetric tensors with new symmetries due to the module structure. +Through this, tensor network simulations of quantum many-body systems with aid of [MPSKit.jl](https://github.com/QuantumKitHub/MPSKit.jl) can be performed. ## Table of contents @@ -19,7 +21,8 @@ Depth = 2 ## Installation -MultiTensorKit.jl is currently not registered to the Julia General Registry. You can install the package as +MultiTensorKit.jl is currently not registered to the Julia General Registry. +You can install the package as ``` pkg> add https://github.com/QuantumKitHub/MultiTensorKit.jl.git ``` @@ -27,8 +30,12 @@ pkg> add https://github.com/QuantumKitHub/MultiTensorKit.jl.git ## Usage As the name suggests, MultiTensorKit is an extension of [TensorKit.jl](https://github.com/Jutho/TensorKit.jl) and -[TensorKitSectors.jl](https://github.com/QuantumKitHub/TensorKitSectors.jl). Therefore, we recommend including TensorKit -to your project. Additionally, MultiTensorKit was made to be functional with [MPSKit.jl](https://github.com/QuantumKitHub/MPSKit.jl) +[TensorKitSectors.jl](https://github.com/QuantumKitHub/TensorKitSectors.jl). +Therefore, we recommend including TensorKit +to your project. +Additionally, MultiTensorKit was made to be functional with [MPSKit.jl](https://github.com/QuantumKitHub/MPSKit.jl) and [MPSKitModels.jl](https://github.com/QuantumKitHub/MPSKitModels.jl) for Matrix Product State (MPS) calculations, supporting symmetries -which go beyond TensorKit. In particular, TensorKit v0.16.0 and MPSKit v0.13.9 contain the necessary functionality to deal with the multifusion categorical structure provided by MultiTensorKit. All these packages are registered in JuliaRegistries and can be added through the package manager. +which go beyond TensorKit. +In particular, TensorKit v0.16.0 and MPSKit v0.13.9 contain the necessary functionality to deal with the multifusion categorical structure provided by MultiTensorKit. +All these packages are registered in JuliaRegistries and can be added through the package manager. diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index f584678..184b717 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -1,15 +1,19 @@ # Introduction The manual has been divided into different sections in an attempt to break down the information the user requires to use MultiTensorKit.jl. -We start off with a short summary of fusion category theory. Users familiar with TensorKit.jl may have read the [Optional introduction to category theory](https://jutho.github.io/TensorKit.jl/stable/man/categories/) in the documentation of TensorKit; this section can then largely be skipped. Be aware that notation may differ from the literature. +We start off with a short summary of fusion category theory. +Users familiar with TensorKit.jl may have read the [Optional introduction to category theory](https://jutho.github.io/TensorKit.jl/stable/man/categories/) in the documentation of TensorKit; this section can then largely be skipped. +Be aware that notation may differ from the literature. -Afterwards, the extension to multifusion categories is explained, and its relation to (bi)module categories over fusion categories is shown. +Afterwards, the extension to multifusion categories is explained, and its relation to (bi)module categories over fusion categories is shown. # Fusion category theory -The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/) documentation or the book Tensor Categories [etingof2016tensor](@cite). +The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. +More details can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/) documentation or the book Tensor Categories [etingof2016tensor](@cite). -Let us start simple and introduce the **fusion ring** $\mathcal{C}$ in a black-box manner. This ring +Let us start simple and introduce the **fusion ring** $\mathcal{C}$ in a black-box manner. +This ring * consists of finitely many simple objects $\{ X_1, X_2, ..., X_R \}$, with $R$ the rank of the fusion ring, * which can be fused with one another: $X_i \otimes X_j \cong \sum_k N_{ij}^k X_k,$ introducing the **N-symbol** $N_{ij}^k \in \mathbb{N}$ in the fusion rules, * contains a *unique* unit object $1_\mathcal{C}$ which satisfies $1_\mathcal{C} \otimes X_i \cong X_i \otimes 1_\mathcal{C} \cong X_i$ for all objects $X_i \in \mathcal{C}$, @@ -22,7 +26,11 @@ To extend the fusion ring to the **fusion category**, we need to add the followi * Morphisms between (simple) objects $\text{Hom}_\mathcal{C}(X_i, X_j)$, which are empty vector spaces unless the objects are isomorphic, the latter then giving $\mathbb{C}$, * More general morphisms $\text{Hom}_\mathcal{C}(X_i \otimes X_j, X_k) \cong \mathbb{C}^{N_{ij}^k}$. -This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C}, F)$ of $\mathcal{C}$ defining its monoidal product, unit object and monoidal associator, the latter also commonly called the **F-symbol**. In particular, the simple objects have their respective quantum dimensions $d_i = \dim(X_i)$ which form their own one-dimensional representation of the fusion algebra: $d_i d_j = \sum_k N_{ij}^k d_k$. In particular, the unit object always has quantum dimension 1, and all other quantum dimensions are larger or equal to one. These quantum dimensions are encoded in the F-symbol. The isomorphisms instead of the equalities are a technical detail, so we drop that notation. +This way, we can describe fusion categories by a triple $(\otimes, 1_\mathcal{C}, F)$ of $\mathcal{C}$ defining its monoidal product, unit object and monoidal associator, the latter also commonly called the **F-symbol**. +In particular, the simple objects have their respective quantum dimensions $d_i = \dim(X_i)$ which form their own one-dimensional representation of the fusion algebra: $d_i d_j = \sum_k N_{ij}^k d_k$. +In particular, the unit object always has quantum dimension 1, and all other quantum dimensions are larger or equal to one. +These quantum dimensions are encoded in the F-symbol. +The isomorphisms instead of the equalities are a technical detail, so we drop that notation. Vectors in these hom-spaces are graphically denoted as living in the trivalent junction ```@raw html @@ -36,12 +44,17 @@ With the F-symbol, we can perform F-moves: ``` -TensorKit requires the F-symbols to be unitary. This way, we can interpret the F-symbol $F^{ijk}_l$ as a unitary matrix, and the F-move as a unitary basis transformation. Unitarity is also useful from a diagrammatic point of view because the category is then equipped with a pivotal and spherical structure. This essentially means that morphisms can be drawn and moved around freely on a 2-sphere, such that vector spaces can be moved freely from domain (codomain) to codomain (domain). +TensorKit requires the F-symbols to be unitary. +This way, we can interpret the F-symbol $F^{ijk}_l$ as a unitary matrix, and the F-move as a unitary basis transformation. +Unitarity is also useful from a diagrammatic point of view because the category is then equipped with a pivotal and spherical structure. +This essentially means that morphisms can be drawn and moved around freely on a 2-sphere, such that vector spaces can be moved freely from domain (codomain) to codomain (domain). ## Examples ### $\mathsf{Vec_G}$ and $\mathsf{Rep(G)}$ -Colloquially speaking, category theory attempts to generalise mathematical structures and their relations in a way that different structures can be treated in an equal manner. This is noted in particular as fusion category theory encompasses not only finite and compact groups, but also their representations. We show a table sketching how these are put on equal footing categorically. +Colloquially speaking, category theory attempts to generalise mathematical structures and their relations in a way that different structures can be treated in an equal manner. +This is noted in particular as fusion category theory encompasses not only finite and compact groups, but also their representations. +We show a table sketching how these are put on equal footing categorically. |$\mathsf{Vec_G}$|$\mathsf{Rep(G)}$|Categorical generalisation| |:---:|:---:|:---:| @@ -54,6 +67,12 @@ $\mathbb{C}_g \otimes \mathbb{C}_{g^{-1}} = \mathbb{C}_1 = \mathbb{C}_{g^{-1}} \ $F:(V \otimes W) \otimes U \xrightarrow{\sim}V \otimes (W \otimes U)$|$F: (\pi_1 \otimes \pi_2) \otimes \pi_3 \xrightarrow{\sim} \pi_1 \otimes (\pi_2 \otimes \pi_3)$|F-symbol| ### $\mathsf{Fib}$ and $\mathsf{Ising}$ -Arguably the simplest fusion category besides the familiar groups or representations of groups is the Fibonacci fusion category. This contain 2 simple objects $1$ and $\tau$, with non-trivial fusion rule $\tau \otimes \tau = 1 \oplus \tau$. This fusion category is in fact **braided** as well, and actually **modular**. - -Another simple fusion category is the Ising category, commonly denoted $\mathsf{Ising}$. 3 simple objects form this category, namely $\{1, \psi, \sigma\}$, where $1$ and $\psi$ behave like the trivial charged representations of $\mathbb{Z}_2$, while $\sigma$ is the $\mathbb{Z}_2$ extension of this. The fusion rules reflect these: $1 \otimes \psi = \psi = \psi \otimes 1, \sigma \otimes X = \sigma = X \otimes \sigma$ for $X = 1, \psi$, and $\sigma \otimes \sigma = 1 \oplus \psi$. This fusion category is also **modular**. Both these modular fusion categories are already implemented in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). \ No newline at end of file +Arguably the simplest fusion category besides the familiar groups or representations of groups is the Fibonacci fusion category. +This contain 2 simple objects $1$ and $\tau$, with non-trivial fusion rule $\tau \otimes \tau = 1 \oplus \tau$. +This fusion category is in fact **braided** as well, and actually **modular**. + +Another simple fusion category is the Ising category, commonly denoted $\mathsf{Ising}$. +3 simple objects form this category, namely $\{1, \psi, \sigma\}$, where $1$ and $\psi$ behave like the trivial charged representations of $\mathbb{Z}_2$, while $\sigma$ is the $\mathbb{Z}_2$ extension of this. +The fusion rules reflect these: $1 \otimes \psi = \psi = \psi \otimes 1, \sigma \otimes X = \sigma = X \otimes \sigma$ for $X = 1, \psi$, and $\sigma \otimes \sigma = 1 \oplus \psi$. +This fusion category is also **modular**. +Both these modular fusion categories are already implemented in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). \ No newline at end of file diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 66face2..0c3ff09 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -1,10 +1,19 @@ # MultiTensorKit implementation: $\mathsf{Rep(A_4)}$ as a guiding example -This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. - -This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep(A_4)}$. Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. There are 3 fusion categories up to equivalence: -- ``\mathsf{Vec_{A_4}}``: the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$. It has thus 12 objects. -- ``\mathsf{Rep(A_4)}``: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. One is the trivial representation, two are one-dimensional non-trivial and the last is three-dimensional. -- ``\mathsf{Rep(H)}``: the representation category of some Hopf algebra which does not have a name. It has 6 simple objects. +This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. +In particular, we will be making a generalised anyonic spin chain. +We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). +The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. + +This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep(A_4)}$. +Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. +There are 3 fusion categories up to equivalence: +- ``\mathsf{Vec_{A_4}}``: the category of $\mathsf{A_4}$-graded vector spaces. +The group $\mathsf{A}_4$ is order $4!/2 = 12$. +It has thus 12 objects. +- ``\mathsf{Rep(A_4)}``: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. +One is the trivial representation, two are one-dimensional non-trivial and the last is three-dimensional. +- ``\mathsf{Rep(H)}``: the representation category of some Hopf algebra which does not have a name. +It has 6 simple objects. For this example, we will require the following packages: ````julia @@ -12,7 +21,10 @@ using TensorKit, MultiTensorKit, MPSKit, MPSKitModels, Plots ```` ## Identifying the simple objects -We first need to select which fusion category we wish to use to grade the physical Hilbert space, and which fusion category to represent e.g. the symmetry category. In our case, we are interested in selecting $\mathcal{D} = \mathsf{Rep(A_4)}$ for the physical Hilbert space. We know the module categories over $\mathsf{Rep(G)}$ to be $\mathsf{Rep^\psi(H)}$ for a subgroup $\mathsf{H}$ and 2-cocycle $\psi$. Thus, the 7 module categories $\mathcal{M}$ one can choose over $\mathsf{Rep(A_4)}$ are +We first need to select which fusion category we wish to use to grade the physical Hilbert space, and which fusion category to represent e.g. the symmetry category. +In our case, we are interested in selecting $\mathcal{D} = \mathsf{Rep(A_4)}$ for the physical Hilbert space. +We know the module categories over $\mathsf{Rep(G)}$ to be $\mathsf{Rep^\psi(H)}$ for a subgroup $\mathsf{H}$ and 2-cocycle $\psi$. +Thus, the 7 module categories $\mathcal{M}$ one can choose over $\mathsf{Rep(A_4)}$ are - ``\mathsf{Rep(A_4)}`` itself as the regular module category, - ``\mathsf{Vec}``: the category of vector spaces, @@ -26,19 +38,24 @@ When referring to specific fusion and module categories, we will use this non-mu The easiest way to identify which elements of the multifusion category correspond to the subcategories we wish to use is ... #TODO -Now that we have identified the fusion and module categories, we want to select the relevant objects we wish to place in our graded spaces. Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. Hence, the simplest way to find the unit object of a fusion subcategory is +Now that we have identified the fusion and module categories, we want to select the relevant objects we wish to place in our graded spaces. +Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. +Hence, the simplest way to find the unit object of a fusion subcategory is ````julia unit(A4Object(i,i,1)) ```` -Left and right units of subcategories are uniquely specified by their fusion rules. For example, the left unit of a subcategory $\mathcal{C}_{ij}$ is the simple object in $\mathcal{C}_i$ for which +Left and right units of subcategories are uniquely specified by their fusion rules. +For example, the left unit of a subcategory $\mathcal{C}_{ij}$ is the simple object in $\mathcal{C}_i$ for which $$^{}_a \mathbb{1} \times a = a \quad \forall a \in \mathcal{C}_i.$$ -A similar condition uniquely defines the right unit of a subcategory. For fusion subcategories, a necessary condition is that the left and right units coincide. +A similar condition uniquely defines the right unit of a subcategory. +For fusion subcategories, a necessary condition is that the left and right units coincide. -Identifying the other simple objects of a (not necessarily fusion) category requires more work. We recommend a combination of the following to uniquely determine any simple object `a`: +Identifying the other simple objects of a (not necessarily fusion) category requires more work. +We recommend a combination of the following to uniquely determine any simple object `a`: - Check the dimension of the simple object: `dim(a)` - Check the dual of the simple object: `dual(a)` - Check how this simple object fuses with other (simple) objects: `Nsymbol(a, b, c)` @@ -49,7 +66,8 @@ $$^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* with multiplicity 1. ## Constructing the Hamiltonian and matrix product state -TensorKit has been made compatible with the multifusion structure by keeping track of the relevant units in the fusion tree manipulations. With this, we can make `GradedSpace`s whose objects are in `A4Object`: +TensorKit has been made compatible with the multifusion structure by keeping track of the relevant units in the fusion tree manipulations. +With this, we can make `GradedSpace`s whose objects are in `A4Object`: ````julia D1 = A4Object(6, 6, 1) # unit in this case @@ -57,7 +75,9 @@ D2 = A4Object(6, 6, 2) # non-trivial 1d irrep D3 = A4Object(6, 6, 3) # non-trivial 1d irrep D4 = A4Object(6, 6, 4) # 3d irrep ```` -Since we want to replicate a spin-1 Heisenberg model, it makes sense to use the 3-dimensional irrep to grade the physical space, and thus construct our Hamiltonian. We don't illustrate here how to derive the considered Hamiltonian in a $\mathsf{Rep(A_4)}$ basis, but simply give it. For now, we construct a finite-size spin chain; below we will repeat the calculation for an infinite system. +Since we want to replicate a spin-1 Heisenberg model, it makes sense to use the 3-dimensional irrep to grade the physical space, and thus construct our Hamiltonian. +We don't illustrate here how to derive the considered Hamiltonian in a $\mathsf{Rep(A_4)}$ basis, but simply give it. +For now, we construct a finite-size spin chain; below we will repeat the calculation for an infinite system. ````julia P = Vect[A4Object](D4 => 1) # physical space @@ -109,26 +129,36 @@ init_mps = FiniteMPS(L, P, V; left=Vb, right=Vb) We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for any `BimoduleSector` due to the semisimple unit. ## DMRG2 and the entanglement spectrum -We can now look to find the ground state of the Hamiltonian with two-site DMRG. We use this instead of the "usual" one-site DMRG because the two-site one will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. +We can now look to find the ground state of the Hamiltonian with two-site DMRG. +We use this instead of the "usual" one-site DMRG because the two-site one will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. ````julia dmrg2alg = DMRG2(;verbosity=2, tol=1e-7, trscheme=truncbelow(1e-4)) ψ, _ = find_groundstate(init_mps, H, dmrg2alg) ```` -The truncation scheme keyword argument is mandatory when calling `DMRG2` in MPSKit. Here, we choose to truncate such that all singular values are larger than $10^{-4}$, while setting the default tolerance for convergence to $10^{-7}$. More information on this can be found in the [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl) documentation. To run one-site DMRG anyway, use `DMRG` which does not require a truncation scheme. +The truncation scheme keyword argument is mandatory when calling `DMRG2` in MPSKit. +Here, we choose to truncate such that all singular values are larger than $10^{-4}$, while setting the default tolerance for convergence to $10^{-7}$. +More information on this can be found in the [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl) documentation. +To run one-site DMRG anyway, use `DMRG` which does not require a truncation scheme. Now that we've found the ground state, we can compute the entanglement spectrum in the middle of the chain. ````julia spec = entanglement_spectrum(ψ, round(Int, L/2)) ```` -This returns a dictionary which maps the objects grading the virtual space to the singular values. In this case, there is one key corresponding to $\mathsf{Vec}$. We can also immediately return a plot of this data by the following: +This returns a dictionary which maps the objects grading the virtual space to the singular values. +In this case, there is one key corresponding to $\mathsf{Vec}$. +We can also immediately return a plot of this data by the following: ````julia entanglementplot(ψ;site=round(Int, L/2)) ```` -This plot will show the singular values per object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. The next section will show this plot along with those when selecting the other module categories. +This plot will show the singular values per object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. +The next section will show this plot along with those when selecting the other module categories. ## Search for the correct dual model -Consider a quantum lattice model with its symmetries determing the phase diagram. For every phase in the phase diagram, the dual model for which the ground state maximally breaks all symmetries spontaneously is the one where the entanglement is minimised and the tensor network is represented most efficiently [Lootens_2024](@cite). Let us confirm this result, starting with the $\mathsf{Rep(A_4)}$ spontaneous symmetry breaking phase. The code will look exactly the same as above, except the virtual space of the MPS will change to be graded by the other module categories: +Consider a quantum lattice model with its symmetries determing the phase diagram. +For every phase in the phase diagram, the dual model for which the ground state maximally breaks all symmetries spontaneously is the one where the entanglement is minimised and the tensor network is represented most efficiently [Lootens_2024](@cite). +Let us confirm this result, starting with the $\mathsf{Rep(A_4)}$ spontaneous symmetry breaking phase. +The code will look exactly the same as above, except the virtual space of the MPS will change to be graded by the other module categories: ````julia module_numlabels(i) = MultiTensorKit._numlabels(A4Object, i, 6) @@ -140,27 +170,36 @@ Vb = Vect[A4Object](first(sectors(V)) => 1) # not all charges on boundary, play ``` -The plot shows the entanglement spectra of the various dual models in the middle of the ground state for the original Hamiltonian probing the $\mathsf{Rep(A_4)}$-symmetric phase, along with the ground state without symmetries. Every subtitle also mentions the memory required to store the same middle ground state tensor. This plot should be compared to [Lootens_2024; Figure 2](@cite). +The plot shows the entanglement spectra of the various dual models in the middle of the ground state for the original Hamiltonian probing the $\mathsf{Rep(A_4)}$-symmetric phase, along with the ground state without symmetries. +Every subtitle also mentions the memory required to store the same middle ground state tensor. +This plot should be compared to [Lootens_2024; Figure 2](@cite). This can be repeated with other parameter values for $J_1$ and $J_2$ in the Hamiltonian to probe the $\mathsf{Rep(\mathbb{Z}_2 \times \mathbb{Z}_2)}$-symmetric or $\mathsf{Rep^\psi(A_4)}$ SPT phase. !!! note "Additional functions and keyword arguments" - Certain commonly used functions within MPSKit require extra keyword arguments to be compatible with multifusion MPS simulations. In particular, the keyword argument `sector` (note the lowercase "s") appears in - - `excitations` with `QuasiparticleAnsatz`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the charged excitations lie in the symmetry category $\mathcal{C} = \mathcal{D^*_M}$. - - `exact_diagonalization`: the `sector` keyword argument now requires an object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. + Certain commonly used functions within MPSKit require extra keyword arguments to be compatible with multifusion MPS simulations. +In particular, the keyword argument `sector` (note the lowercase "s") appears in + - `excitations` with `QuasiparticleAnsatz`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. +Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the charged excitations lie in the symmetry category $\mathcal{C} = \mathcal{D^*_M}$. + - `exact_diagonalization`: the `sector` keyword argument now requires an object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. +This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. ## Differences with the infinite case -We can repeat the above calcalations also for an infinite system. The `lattice` variable will change, as well as the MPS constructor and the algorithm: +We can repeat the above calcalations also for an infinite system. +The `lattice` variable will change, as well as the MPS constructor and the algorithm: ````julia lattice = InfiniteChain(1) init = InfiniteMPS([P], [V]) inf_alg = VUMPS(; verbosity=2, tol=1e-7) ```` -Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `BimoduleSector`. It is also clear that boundary terms do not play a role in this case. +Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `BimoduleSector`. +It is also clear that boundary terms do not play a role in this case. !!! note "More functions for infinite systems" - When dealing with an infinite system, additional information can be retrieved from the matrix product state. These also require a keyword argument `sector` to be specified, as otherwise the correct unit object is placed by default. These are - - `transfer_spectrum`: similar to `excitations`, the (partial) transfer matrix spectrum is selected by adding a charged auxiliary space to the transfer matrix eigenvectors. + When dealing with an infinite system, additional information can be retrieved from the matrix product state. + These also require a keyword argument `sector` to be specified, as otherwise the correct unit object is placed by default. + These are + - `transfer_spectrum`: similar to `excitations`, the (partial) transfer matrix spectrum is selected by adding a charged auxiliary space to the transfer matrix eigenvectors. - `correlation_length`: since this function calls `transfer_spectrum`, the same logic applies. - `excitations` in the infinite case also requires the keyword argument. \ No newline at end of file diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 227f230..541952a 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -1,13 +1,18 @@ # Extending to multifusion category theory -This section will explain how to go from a fusion category to a multifusion category, as well as why one would want to consider the latter. Multifusion categories naturally embed the structure of **bimodule categories**. To explain this, we must start by explaining module categories over fusion categories, following this up with (invertible) bimodule categories, and finishing off with the multifusion structure. +This section will explain how to go from a fusion category to a multifusion category, as well as why one would want to consider the latter. +Multifusion categories naturally embed the structure of **bimodule categories**. +To explain this, we must start by explaining module categories over fusion categories, following this up with (invertible) bimodule categories, and finishing off with the multifusion structure. ## Module categories -We start from a fusion category $\mathcal{D}$ defined by the triple $(\otimes_\mathcal{D}, \mathbb{1}_\mathcal{D}, {}^\mathcal{D}\!F)$ with simple objects $\alpha, \beta, ... \in \mathcal{I}_\mathcal{D}$. We drop the $\mathcal{D}$ subscript when there is no ambiguity concerning the fusion category. We call its associator +We start from a fusion category $\mathcal{D}$ defined by the triple $(\otimes_\mathcal{D}, \mathbb{1}_\mathcal{D}, {}^\mathcal{D}\!F)$ with simple objects $\alpha, \beta, ... \in \mathcal{I}_\mathcal{D}$. +We drop the $\mathcal{D}$ subscript when there is no ambiguity concerning the fusion category. +We call its associator $${}^\mathcal{D}\!F^{\alpha \beta \gamma}: \alpha \otimes (\beta \otimes \gamma) \rightarrow (\alpha \otimes \beta) \otimes \gamma$$ - the **monoidal associator**. An F-move is now graphically portrayed as: + the **monoidal associator**. + An F-move is now graphically portrayed as: ```@raw html @@ -27,9 +32,11 @@ An F-move with this module associator can be expressed as: ``` -The module structure of $\mathcal{M}$ is now defined as the triple $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$. The right module associator now satisfies a mixed pentagon equation with ${}^\mathcal{D}\!F$. +The module structure of $\mathcal{M}$ is now defined as the triple $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$. +The right module associator now satisfies a mixed pentagon equation with ${}^\mathcal{D}\!F$. -Similarly, we can define a **left module category** $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ over a fusion category $(\otimes_\mathcal{C}, 1_\mathcal{C}, {}^\mathcal{C}\!F)$. The functor is now a left action of $\mathcal{C}$ on $\mathcal{M}$ +Similarly, we can define a **left module category** $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ over a fusion category $(\otimes_\mathcal{C}, 1_\mathcal{C}, {}^\mathcal{C}\!F)$. +The functor is now a left action of $\mathcal{C}$ on $\mathcal{M}$ $$\triangleright: \mathcal{C} \times \mathcal{M} \rightarrow \mathcal{M},$$ @@ -37,23 +44,33 @@ while the **left module associator** is a natural isomorphism that acts as $${}^\triangleright\!F^{abA}: (a \otimes b) \triangleright A \rightarrow a \triangleright (b \triangleright A)$$ -for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. The left module associator also fulfills a mixed pentagon equation with ${}^\mathcal{C}\!F$. An F-move with ${}^\mathcal{C}\!F$ takes on the form: +for $\mathcal{I}_\mathcal{C} = \{a,b,...\}$. +The left module associator also fulfills a mixed pentagon equation with ${}^\mathcal{C}\!F$. +An F-move with ${}^\mathcal{C}\!F$ takes on the form: ```@raw html ``` -We can combine the concepts of left and right module categories as follows. Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{\bowtie}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as +We can combine the concepts of left and right module categories as follows. +Say there are two fusion categories $\mathcal{C}$ and $\mathcal{D}$. +A $(\mathcal{C}, \mathcal{D})$-**bimodule category** is a module category, now defined through a sextuple $(\mathcal{M}, \triangleright, \triangleleft, {}^\triangleright\!F, {}^\triangleleft\!F, {}^{\bowtie}\!F)$ such that $(\mathcal{M}, \triangleright, {}^\triangleright\!F)$ is a left $\mathcal{C}$-module category, $(\mathcal{M}, \triangleleft, {}^\triangleleft\!F)$ is a right $\mathcal{D}$-module category, and with additional structure such that the **bimodule associator** acts as $${}^{\bowtie}\!F^{aA\alpha}: (a \triangleright A) \triangleleft \alpha \rightarrow a \triangleright (A \triangleleft \alpha)$$ -for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. The bimodule associator fulfills a mixed pentagon equation with the module associators. An F-move with ${}^{\bowtie}\!F$ is given by: +for $a \in \mathcal{I}_\mathcal{C}, \alpha \in \mathcal{I}_\mathcal{D}, A \in \mathcal{I}_\mathcal{M}$. +The bimodule associator fulfills a mixed pentagon equation with the module associators. +An F-move with ${}^{\bowtie}\!F$ is given by: ```@raw html ``` ## Opposite module categories -Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). Then, $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. A similar statement can be made starting from a left module category and getting an opposite right module category. In particular, given a $(\mathcal{C}, \mathcal{D})$-bimodule category $\mathcal{M}$ over the fusion categories $\mathcal{C}$ and $\mathcal{D}$, we see immediately that $\mathcal{M}^{\text{op}}$ is a $(\mathcal{D}, \mathcal{C})$-bimodule category. +Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. +We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). +Then, $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. +A similar statement can be made starting from a left module category and getting an opposite right module category. +In particular, given a $(\mathcal{C}, \mathcal{D})$-bimodule category $\mathcal{M}$ over the fusion categories $\mathcal{C}$ and $\mathcal{D}$, we see immediately that $\mathcal{M}^{\text{op}}$ is a $(\mathcal{D}, \mathcal{C})$-bimodule category. Interestingly, due to the opposite actions @@ -69,22 +86,32 @@ $$\mathcal{M} \times \mathcal{M}^{\text{op}} \rightarrow \mathcal{C}, \quad \mat ## Invertible bimodule categories and Morita equivalence -The bimodule categories we consider are restricted to be **invertible**. This means that this bimodule category fulfills the condition $\mathcal{C} \equiv \mathcal{D}^*_\mathcal{M}$, or in other words the two fusion categories $\mathcal{C}$ and $\mathcal{D}$ are **Morita equivalent** (or each other's **Morita dual** with respect to $\mathcal{M}$). Morita equivalence between $\mathcal{C}$ and $\mathcal{D}$ can be shown to hold if and only if the bimodule category fulfills +The bimodule categories we consider are restricted to be **invertible**. +This means that this bimodule category fulfills the condition $\mathcal{C} \equiv \mathcal{D}^*_\mathcal{M}$, or in other words the two fusion categories $\mathcal{C}$ and $\mathcal{D}$ are **Morita equivalent** (or each other's **Morita dual** with respect to $\mathcal{M}$). +Morita equivalence between $\mathcal{C}$ and $\mathcal{D}$ can be shown to hold if and only if the bimodule category fulfills $$\mathcal{M} \boxtimes_\mathcal{D} \mathcal{M}^\text{op} \simeq \mathcal{C}, \quad \text{and} \quad \mathcal{M}^\text{op} \boxtimes_\mathcal{C} \mathcal{M} \simeq \mathcal{D},$$ -where $\boxtimes_\mathcal{C}$ and $\boxtimes_\mathcal{D}$ denote the Deligne product relative to $\mathcal{C}$ and $\mathcal{D}$ respectively. This is precisely the invertibility property of the bimodule category. +where $\boxtimes_\mathcal{C}$ and $\boxtimes_\mathcal{D}$ denote the Deligne product relative to $\mathcal{C}$ and $\mathcal{D}$ respectively. +This is precisely the invertibility property of the bimodule category. ## Multifusion categories -A fusion category has the important condition that $\mathsf{End}_\mathcal{C}(1_\mathcal{C}) \cong \mathbb{C}$, i.e., the unit of the fusion category is simple. If we drop this condition, then we consider a **multifusion category**. We assume the multifusion category itself to be indecomposable, meaning it is not the direct sum of two non-trivial multifusion categories. Let us call this multifusion category $\mathcal{C}$. It will be clear in a moment that this will not be ambiguous. Its unit can then be decomposed as +A fusion category has the important condition that $\mathsf{End}_\mathcal{C}(1_\mathcal{C}) \cong \mathbb{C}$, i.e., the unit of the fusion category is simple. +If we drop this condition, then we consider a **multifusion category**. +We assume the multifusion category itself to be indecomposable, meaning it is not the direct sum of two non-trivial multifusion categories. +Let us call this multifusion category $\mathcal{C}$. +It will be clear in a moment that this will not be ambiguous. +Its unit can then be decomposed as $$1_\mathcal{C} = \bigoplus_{i=1}^r 1_r,$$ -i.e., it is decomposed into simple unit objects of the subcategories $\mathcal{C}_{ij} \coloneqq 1_i \otimes \mathcal{C} \otimes 1_j$. With this, we see that the multifusion category itself can be decomposed into its subcategories +i.e., it is decomposed into simple unit objects of the subcategories $\mathcal{C}_{ij} \coloneqq 1_i \otimes \mathcal{C} \otimes 1_j$. +With this, we see that the multifusion category itself can be decomposed into its subcategories $$\mathcal{C} = \bigoplus_{i,j=1}^r \mathcal{C}_{ij}.$$ -We call this an $r \times r$ multifusion category. Due to this structure, we represent a simple object in the multifusion category "Name" by +We call this an $r \times r$ multifusion category. +Due to this structure, we represent a simple object in the multifusion category "Name" by ````julia struct BimoduleSector{Name} <: Sector @@ -96,13 +123,18 @@ end `i` and `j` specify which subcategory $\mathcal{C}_{ij}$ we are considering, and `label` selects a particular simple object within that subcategory. -We want to consider multifusion categories because **their structure encapsulates that of (bi)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ (also known as a component category) is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. In particular, the tensor product +We want to consider multifusion categories because **their structure encapsulates that of (bi)module categories**. +Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ (also known as a component category) is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. +That way, as long as we know how the simple objects of the fusion and module categories fuse with one another, and we can determine all the monoidal and module associators, we can treat the multifusion category as one large fusion category with limited fusion rules. +In particular, the tensor product $$\otimes_\mathcal{C}: \mathcal{C}_{ij} \times \mathcal{C}_{kl} \rightarrow \delta_{jk}\mathcal{C}_{il}$$ -takes on the same structure as the product of two matrix units. This is not a coincidence; there is a deep relation between multifusion categories and matrix algebras [etingof2016tensor; Section 4.3](@cite). +takes on the same structure as the product of two matrix units. +This is not a coincidence; there is a deep relation between multifusion categories and matrix algebras [etingof2016tensor; Section 4.3](@cite). -Given a subcategory $\mathcal{C}_{ij}$, we can define the **left** unit as the unit object of the fusion category $\mathcal{C}_i$, while the **right** unit is the unit object of the fusion category $\mathcal{C}_j$. In other words, the left unit of $\mathcal{C}_{ij}$ is the unique object of the multifusion category $\mathcal{C}$ for which +Given a subcategory $\mathcal{C}_{ij}$, we can define the **left** unit as the unit object of the fusion category $\mathcal{C}_i$, while the **right** unit is the unit object of the fusion category $\mathcal{C}_j$. +In other words, the left unit of $\mathcal{C}_{ij}$ is the unique object of the multifusion category $\mathcal{C}$ for which $$1_i \otimes_\mathcal{C} m_{ij} = m_{ij} \quad \forall m_{ij} \in \mathcal{C}_{ij},$$ @@ -116,7 +148,14 @@ $$\mathcal{C}_{ij} \times \mathcal{C}_{ji} \rightarrow \mathcal{C}_i,$$ just like what we concluded when considering opposite module categories outside of the multifusion structure. ### 2-category and coloring -Multifusion categories can also be interpreted as 2-categories. We still interpret the objects of this 2-category the same way. The 1-morphisms are the subcategories themselves, and the 2-morphisms the morphisms of the multifusion category. The graphical calculus of monoidal 1-categories can be extended to 2-categories by use of *colorings* [henriques2020](@cite). We have previously differed between module strands and fusion strands by the color of the strand itself. However, in 2-categories the strands (1-morphisms) separate regions which are colored based on the fusion categories they are representing. Since we draw the strands vertically, a single strand results in a left and right region, and the colorings will determine the fusion category which fuses from the left or right with that single strand. In particular, fusion strands necessarily have the same coloring on the left and right, while module strands have a mismatching coloring. +Multifusion categories can also be interpreted as 2-categories. +We still interpret the objects of this 2-category the same way. +The 1-morphisms are the subcategories themselves, and the 2-morphisms the morphisms of the multifusion category. +The graphical calculus of monoidal 1-categories can be extended to 2-categories by use of *colorings* [henriques2020](@cite). +We have previously differed between module strands and fusion strands by the color of the strand itself. +However, in 2-categories the strands (1-morphisms) separate regions which are colored based on the fusion categories they are representing. +Since we draw the strands vertically, a single strand results in a left and right region, and the colorings will determine the fusion category which fuses from the left or right with that single strand. +In particular, fusion strands necessarily have the same coloring on the left and right, while module strands have a mismatching coloring. The simplest non-trivial fusion diagram is a trivalent junction: @@ -124,9 +163,17 @@ The simplest non-trivial fusion diagram is a trivalent junction: ``` -The most general case is the top left figure, where all three regions have a different coloring. The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. However, this most general trivalent junction with three colorings will never be needed. In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. This is displayed in the top middle and right. Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. This is shown in the bottom right. +The most general case is the top left figure, where all three regions have a different coloring. +The top middle region having the same coloring from the top left and top right strands follow from the delta function in the tensor product definition. +However, this most general trivalent junction with three colorings will never be needed. +In short, we will always be considering a single bimodule category $\mathcal{C}_{ij}$ at a time, and the only other non-diagonal subcategory which fuses with this is its opposite $\mathcal{C}_{ji}$. +This is displayed in the top middle and right. +Similarly, two colorings are required when considering the fusion between a fusion and module strand, shown in the bottom left and middle figure. +The simplest trivalent junctions boil down to fusions within fusion categories, which is obviously drawn with just one color. +This is shown in the bottom right. -With this coloring system, we can specify which associator must be called to perform a particular F-move. Such an F-move would look like +With this coloring system, we can specify which associator must be called to perform a particular F-move. +Such an F-move would look like ```@raw html @@ -134,68 +181,107 @@ With this coloring system, we can specify which associator must be called to per ### Why opposite module categories end up being necessary in MultiTensorKit -One of the common manipulations which can act on a tensor map is the transposition of vector spaces. We will refer to this as the bending of legs. One of the elementary bends is the **right bend**, where one of the tensor legs is bent along the right from the codomain to the domain, or vice versa. At the level of the tensor, a covariant index becomes contravariant, or vice versa. Similarly, a **left bend** can also be performed, bending the leg along the left. This guarantees that legs will not cross, preventing braidings which require extra data known as R-symbols. - -Linear algebra tells us that given a (finite-dimensional) vector space $V$ with a basis denoted $\{|e_i\rangle\}$, one can consider the **dual** vector space $V^*$, whose dual basis $\{\langle e_i^*|\}$ satisfies the property $\langle e_j^* | e_i \rangle = \delta_{ij}$. In the diagrammatic calculus, specifying whether a tensor map leg represents a vector space or its dual is done with an arrow. Following the TensorKit convention, legs with arrows pointing downwards are vector spaces, and arrows pointing upwards state that we are considering its dual. In particular, at the level of fusion trees we can also draw arrows on the strands to denote whether we are considering morphisms between objects or dual objects. - -In principle, choosing to bend, e.g., codomain legs to the right and domain legs to left is an arbitrary choice, but would require to distinguish between left and right transposes. However, TensorKit.jl is implemented in a way that does not differentiate the two. In particular, we do not have to worry about this when considering categorical symmetries where, in principle, the left and right dual of an object are not equivalent. This is because this left-right symmetry is guaranteed when considering unitary fusion categories, which is what is done in TensorKit and necessarily in MultiTensorKit. - -For this reason, at the level of the fusion trees the topological move that is performed to bend the legs along the right is called a **B-move**. Graphically, one can show that this bend boils down to a particular F-move. The typical equation found in the literature is the following: +One of the common manipulations which can act on a tensor map is the transposition of vector spaces. +We will refer to this as the bending of legs. +One of the elementary bends is the **right bend**, where one of the tensor legs is bent along the right from the codomain to the domain, or vice versa. +At the level of the tensor, a covariant index becomes contravariant, or vice versa. +Similarly, a **left bend** can also be performed, bending the leg along the left. +This guarantees that legs will not cross, preventing braidings which require extra data known as R-symbols. + +Linear algebra tells us that given a (finite-dimensional) vector space $V$ with a basis denoted $\{|e_i\rangle\}$, one can consider the **dual** vector space $V^*$, whose dual basis $\{\langle e_i^*|\}$ satisfies the property $\langle e_j^* | e_i \rangle = \delta_{ij}$. +In the diagrammatic calculus, specifying whether a tensor map leg represents a vector space or its dual is done with an arrow. +Following the TensorKit convention, legs with arrows pointing downwards are vector spaces, and arrows pointing upwards state that we are considering its dual. +In particular, at the level of fusion trees we can also draw arrows on the strands to denote whether we are considering morphisms between objects or dual objects. + +In principle, choosing to bend, e.g., codomain legs to the right and domain legs to left is an arbitrary choice, but would require to distinguish between left and right transposes. +However, TensorKit.jl is implemented in a way that does not differentiate the two. +In particular, we do not have to worry about this when considering categorical symmetries where, in principle, the left and right dual of an object are not equivalent. +This is because this left-right symmetry is guaranteed when considering unitary fusion categories, which is what is done in TensorKit and necessarily in MultiTensorKit. + +For this reason, at the level of the fusion trees the topological move that is performed to bend the legs along the right is called a **B-move**. +Graphically, one can show that this bend boils down to a particular F-move. +The typical equation found in the literature is the following: ```@raw html ``` -The reason to only consider B-moves is rooted in the choice of canonical form of fusion trees within TensorKit, where fusions are iterated over from left to right and splittings from right to left. +The reason to only consider B-moves is rooted in the choice of canonical form of fusion trees within TensorKit, where fusions are iterated over from left to right and splittings from right to left. -Importantly, we identify the dual vector space labeled by a module category with a vector space labeled by the opposite module category. Consequently, +Importantly, we identify the dual vector space labeled by a module category with a vector space labeled by the opposite module category. +Consequently, $$\mathcal{M}^* \simeq \mathcal{M}^\text{op}.$$ -In the multifusion setting, this can also be seen graphically. By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: +In the multifusion setting, this can also be seen graphically. +By keeping track of the colorings and the directions of the arrows of the legs, one can see that we need to slightly modify the expression for the B-move to the following: ```@raw html ``` -where by $\mathbb{1}_j$ we mean the unit of $\mathcal{C}_j$. +where by $\mathbb{1}_j$ we mean the unit of $\mathcal{C}_j$. ### More on the topological data: gauge choices and distilling properties of the subcategories -An important property of the F-symbols is that they must satisfy the **triangle identities**. In fusion category theory, this states that isomorphisms between (simple) objects $a$ and the tensor product between $a$ and the unit $\mathbb{1}$ exists, and that +An important property of the F-symbols is that they must satisfy the **triangle identities**. +In fusion category theory, this states that isomorphisms between (simple) objects $a$ and the tensor product between $a$ and the unit $\mathbb{1}$ exists, and that $$(a \otimes \mathbb{1}) \otimes b \cong a \otimes (\mathbb{1} \otimes b)$$ -for $b$ in the same fusion category. This can be straightforwardly generalised to multifusion categories. This requires a particular partial gauging of these trivalent vertices. +for $b$ in the same fusion category. +This can be straightforwardly generalised to multifusion categories. +This requires a particular partial gauging of these trivalent vertices. -Besides the triangle identities, the (multi)fusion category must also fulfill the **pentagon equations**. These encapsulate the two identical manners to evaluating the fusion of four objects in the (multi)fusion category. Every fusion category's F-symbols must satisfy these individually, but also the (bi)module associators between bimodule and fusion categories. One can check that, for every pair of fusion categories, their bimodule category and opposite bimodule category, there are 32 pentagon equations to be satisfied. In the multifusion notation, they can be represented by +Besides the triangle identities, the (multi)fusion category must also fulfill the **pentagon equations**. +These encapsulate the two identical manners to evaluating the fusion of four objects in the (multi)fusion category. +Every fusion category's F-symbols must satisfy these individually, but also the (bi)module associators between bimodule and fusion categories. +One can check that, for every pair of fusion categories, their bimodule category and opposite bimodule category, there are 32 pentagon equations to be satisfied. +In the multifusion notation, they can be represented by ```@raw html ``` -The most generic F-move contains 4 colors. For that reason, MultiTensorKit requires the F-symbol data to be provided as some data file (currently .txt) with 4 + 6 + 4 + 2 = 16 columns. The first 4 refer to the colors, the following 6 label the simple objects of the corresponding subcategories, the next 4 label multiplicities, and the final 2 provide the real and imaginary value of the F-symbol itself. +The most generic F-move contains 4 colors. +For that reason, MultiTensorKit requires the F-symbol data to be provided as some data file (currently .txt) with 4 + 6 + 4 + 2 = 16 columns. +The first 4 refer to the colors, the following 6 label the simple objects of the corresponding subcategories, the next 4 label multiplicities, and the final 2 provide the real and imaginary value of the F-symbol itself. In a similar manner, the N-symbols contain maximally three colors, so these data must provide 3 columns labeling the colors, 3 columns labeling the simple objects and a final column with the dimension of the corresponding vector space. -Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. We already know that an F-move of the form $F^{c \bar{c} c}_{c}$ needs to be evaluated for these topological data, which is in fact another gauge fixing. Graphically, we find +Besides the B-move (and closely related A-move, which we do not illustrate), we can also see how the quantum dimension and Frobenius-Schur indicator expressions get modified. +We already know that an F-move of the form $F^{c \bar{c} c}_{c}$ needs to be evaluated for these topological data, which is in fact another gauge fixing. +Graphically, we find ```@raw html ``` -In principle, a gauge fixing can be done to set the Frobenius-Schur indicator to $\pm 1$. However, this assumption is no longer required within TensorKit and can be relaxed to just be a phase. +In principle, a gauge fixing can be done to set the Frobenius-Schur indicator to $\pm 1$. +However, this assumption is no longer required within TensorKit and can be relaxed to just be a phase. -The above gauge fixing is a property of the unitary gauge. By choosing appropriate bases, one can transform the F-symbols of a (multi)fusion category to be unitary matrices. More details on the importance of unitary topological data can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/#ss_topologicalfusion) documentation. +The above gauge fixing is a property of the unitary gauge. +By choosing appropriate bases, one can transform the F-symbols of a (multi)fusion category to be unitary matrices. +More details on the importance of unitary topological data can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/#ss_topologicalfusion) documentation. ### Braiding -A very important aspect of MultiTensorKit is that all `BimoduleSector`s are defined to *not* support braiding: `TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding()`. We do this for two reasons. On the one hand, there is no natural 1-categorical way of defining braidings between the components of the multifusion category. It is possible that the diagonal fusion categories themselves are braided, but a "componentwise" braiding is unwise to support. On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. +A very important aspect of MultiTensorKit is that all `BimoduleSector`s are defined to *not* support braiding: `TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding()`. +We do this for two reasons. +On the one hand, there is no natural 1-categorical way of defining braidings between the components of the multifusion category. +It is possible that the diagonal fusion categories themselves are braided, but a "componentwise" braiding is unwise to support. +On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. ## Examples of multifusion categories Without specifying any of the categories, the simplest non-trivial multifusion category is a $2\times 2$ one, and the categories can be organised in a matrix as $$\mathcal{C} = \begin{pmatrix} \mathcal{C}_1 & \mathcal{M} \\ \mathcal{M}^{\text{op}} & \mathcal{C}_2\end{pmatrix}.$$ -We already identified the off-diagonal elements with module categories over the fusion categories on the diagonal. Accordingly, $\mathcal{M}$ is a $(\mathcal{C}_1, \mathcal{C}_2)$-bimodule category, and $\mathcal{M}^{\text{op}}$ is the opposite module category and a $(\mathcal{C}_2, \mathcal{C}_1)$-bimodule category. +We already identified the off-diagonal elements with module categories over the fusion categories on the diagonal. +Accordingly, $\mathcal{M}$ is a $(\mathcal{C}_1, \mathcal{C}_2)$-bimodule category, and $\mathcal{M}^{\text{op}}$ is the opposite module category and a $(\mathcal{C}_2, \mathcal{C}_1)$-bimodule category. -If we take $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep}(\mathbb{Z}_2)$ and $\mathcal{M} = \mathsf{Vec}$, then the entire multifusion category is Morita equivalent to $\mathsf{Rep}(\mathbb{Z}_2)$, and we view the $\mathbb{Z}_2$-extension of $\mathsf{Rep}(\mathbb{Z}_2)$ to be precisely the $\mathsf{Ising}$ category [etingof2009; Section 9](@cite) [etingof2016tensor; Example 4.10.5](@cite). We identify the trivial representation of $\mathsf{Rep}(\mathbb{Z}_2)$ with the unit of $\mathsf{Ising}$, the sign representation with $\psi$ and the unique object of $\mathsf{Vec}$ with the duality object $\sigma$. One can easily check that the fusion rules of $\mathsf{Ising}$ match with those we expect within $\mathsf{Rep}(\mathbb{Z}_2)$ and with its module category $\mathsf{Vec}$. Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (and vice-versa) giving every object in $\mathcal{C}_1$ ($\mathcal{C}_2$) is consistent with $\sigma \times \sigma^* = 1 + \psi$. This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). +If we take $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep}(\mathbb{Z}_2)$ and $\mathcal{M} = \mathsf{Vec}$, then the entire multifusion category is Morita equivalent to $\mathsf{Rep}(\mathbb{Z}_2)$, and we view the $\mathbb{Z}_2$-extension of $\mathsf{Rep}(\mathbb{Z}_2)$ to be precisely the $\mathsf{Ising}$ category [etingof2009; Section 9](@cite) [etingof2016tensor; Example 4.10.5](@cite). +We identify the trivial representation of $\mathsf{Rep}(\mathbb{Z}_2)$ with the unit of $\mathsf{Ising}$, the sign representation with $\psi$ and the unique object of $\mathsf{Vec}$ with the duality object $\sigma$. +One can easily check that the fusion rules of $\mathsf{Ising}$ match with those we expect within $\mathsf{Rep}(\mathbb{Z}_2)$ and with its module category $\mathsf{Vec}$. +Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (and vice-versa) giving every object in $\mathcal{C}_1$ ($\mathcal{C}_2$) is consistent with $\sigma \times \sigma^* = 1 + \psi$. +This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). -This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is Morita equivalent to $\mathsf{Rep(G)}$ and can be evaluated as the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. \ No newline at end of file +This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is Morita equivalent to $\mathsf{Rep(G)}$ and can be evaluated as the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. +To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. \ No newline at end of file From 85327e49d483d61fbe9c1dc0bb50a87dfeedc47f Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 10 Feb 2026 10:38:26 +0100 Subject: [PATCH 197/206] remove code reference on theory page --- docs/src/man/multifusioncats.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 541952a..add4daf 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -111,17 +111,6 @@ With this, we see that the multifusion category itself can be decomposed into it $$\mathcal{C} = \bigoplus_{i,j=1}^r \mathcal{C}_{ij}.$$ We call this an $r \times r$ multifusion category. -Due to this structure, we represent a simple object in the multifusion category "Name" by - -````julia -struct BimoduleSector{Name} <: Sector - i::Int - j::Int - label::Int -end -```` - -`i` and `j` specify which subcategory $\mathcal{C}_{ij}$ we are considering, and `label` selects a particular simple object within that subcategory. We want to consider multifusion categories because **their structure encapsulates that of (bi)module categories**. Every diagonal category $\mathcal{C}_{ii} \coloneqq \mathcal{C}_i$ (also known as a component category) is a fusion category, and every off-diagonal category $\mathcal{C}_{ij}$ is an invertible $(\mathcal{C}_{i}, \mathcal{C}_{j})$-bimodule category. @@ -263,11 +252,11 @@ By choosing appropriate bases, one can transform the F-symbols of a (multi)fusio More details on the importance of unitary topological data can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/#ss_topologicalfusion) documentation. ### Braiding -A very important aspect of MultiTensorKit is that all `BimoduleSector`s are defined to *not* support braiding: `TensorKitSectors.BraidingStyle(::Type{<:BimoduleSector}) = NoBraiding()`. +Sectors provided by MultiTensorKit do *not* support braiding. We do this for two reasons. On the one hand, there is no natural 1-categorical way of defining braidings between the components of the multifusion category. It is possible that the diagonal fusion categories themselves are braided, but a "componentwise" braiding is unwise to support. -On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. +On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. More information on this can be found in the next section [#TODO: add reference to extension page] ## Examples of multifusion categories Without specifying any of the categories, the simplest non-trivial multifusion category is a $2\times 2$ one, and the categories can be organised in a matrix as @@ -284,4 +273,6 @@ Additionally, the fusion between $\mathsf{Vec}$ and $\mathsf{Vec}^\text{op}$ (an This particular example can be found in [TensorKitSectors](https://github.com/QuantumKitHub/TensorKitSectors.jl). This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is Morita equivalent to $\mathsf{Rep(G)}$ and can be evaluated as the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. -To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. \ No newline at end of file +To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. + +The example $\mathcal{C}_1 = \mathsf{Rep(A_4)}$ is worked out more in detail on the [#TODO add reference to implementation page]. \ No newline at end of file From 0e5354bb8c6a86286c7502e9ab98ea926b002e14 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Tue, 10 Feb 2026 10:38:43 +0100 Subject: [PATCH 198/206] todos and renamings --- docs/src/man/extension.md | 4 ++-- docs/src/man/implementation.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/man/extension.md b/docs/src/man/extension.md index b6af46a..b85e95d 100644 --- a/docs/src/man/extension.md +++ b/docs/src/man/extension.md @@ -51,12 +51,12 @@ In particular, the presence of a simple unit object for every fusion category on Most notably, the unit object is no longer unique, and thus it is of utmost importance that the correct unit object is considered when performing tensor contractions at the level of the fusion trees. This is achieved precisely through colorings and the use of `leftunit` and `rightunit`. For this reason, every fusion tree manipulation which previously involved "the" unit object, now involves the `leftunit` and `rightunit` of some neighboring sector in the manipulation to identify the correct color. -An important example of this is explained in the previous section [opposite module categories], namely the mapping of a splitting vertex to a fusion vertex through the B-move. +An important example of this is explained in the previous section [#TODO: add opposite module categories reference], namely the mapping of a splitting vertex to a fusion vertex through the B-move. # MultiTensorKit compatibility with MPSKit This section will briefly explain the changes within MPSKit which are required to make it compatible with MultiTensorKit. -For a more practical explanation, users are kindly guided towards the next section [implementation]. +For a more practical explanation, users are kindly guided towards the next section [#TODO: add implementation reference]. The main change within MPSKit is very similar to the fusion tree manipulations in TensorKit, namely the use of `leftunit` and `rightunit` to identify the correct unit object. In the case of MPSKit, trivial spaces are used everywhere, from the boundary of a finite MPS to the virtual spaces of a Hamiltonian written in MPO form. diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 0c3ff09..6657e8d 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -1,4 +1,4 @@ -# MultiTensorKit implementation: $\mathsf{Rep(A_4)}$ as a guiding example +# Symmetric tensor networks: $\mathsf{Rep(A_4)}$ as a guiding example This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). From 4282ebda898bcffdbb091328d2feceddf9c44030 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 12 Feb 2026 10:41:51 +0100 Subject: [PATCH 199/206] fix toc --- docs/src/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/index.md b/docs/src/index.md index a08ae7c..d112e44 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -15,7 +15,7 @@ tensor network simulations of quantum many-body systems with aid of [MPSKit.jl]( ## Table of contents ```@contents -Pages = ["man/fusioncats.md","man/multifusioncats.md","lib/library.md", "references.md"] +Pages = ["man/fusioncats.md", "man/multifusioncats.md", "man/extension.md", "man/implementation.md", "lib/library.md", "references.md"] Depth = 2 ``` From 436e622fb7c708097c6a41a1c91d19d5adb4a671 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 12 Feb 2026 10:42:36 +0100 Subject: [PATCH 200/206] more on extension + references within package --- docs/src/man/extension.md | 25 ++++++++++++++++++++----- docs/src/man/fusioncats.md | 4 ++-- docs/src/man/implementation.md | 4 +--- docs/src/man/multifusioncats.md | 8 ++++---- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/docs/src/man/extension.md b/docs/src/man/extension.md index b85e95d..d9ebf0f 100644 --- a/docs/src/man/extension.md +++ b/docs/src/man/extension.md @@ -1,4 +1,4 @@ -# MultiTensorKit as an extension to TensorKit +# [MultiTensorKit as an extension to TensorKit](@id extension) This section will explain the internal changes to TensorKit which are required to extend the compatibility with fusion categories to multifusion ones. Users who are unfamiliar with TensorKit are kindly guided towards the [TensorKit tutorial](https://jutho.github.io/TensorKit.jl/stable/man/tutorial/). @@ -30,9 +30,16 @@ These data are cached in a hash table for later use. A consequence of the multifusion structure is the colorings used in the graphical calculus of fusions. A natural introduction is the notion of a *left* and *right* unit of some (simple) object in the multifusion category. +These are called with the functions `TensorKitSectors.leftunit` and `TensorKitSectors.rightunit`. Clearly, for the usual case of just one fusion category, these both coincide with the unique unit object. +For this reason, the `TensorKitSectors.UnitStyle` trait is introduced to differentiate between fusion categories and multifusion categories, returning `SimpleUnit()` and `GenericUnit()`, respectively. +This trait is used to specialise certain functions within TensorKit (see below). +`TensorKitSectors.allunits` is also introduced to return all the simple unit objects of the (multi)fusion category. +This function must be defined for every multifusion category to be compatible with TensorKit. Via the fusion rules, the left and right units of all `BimoduleSector`s along with their duals are also extracted and cached. -Since the most general fusion rule possible is one with multiplicities involved, the entire `BimoduleSector` is set to have `TensorKitSectors.FusionStyle(::Type{<:BimoduleSector}) = GenericFusion()`. +The fusion behavior that must be imposed for the entire `BimoduleSector` is the most general one that appears in the fusion between any two `BimoduleSector`s. +In particular, if one of the diagonal fusion categories has fusion rules with multiplicities, then the entire `BimoduleSector` must be set to have `TensorKitSectors.FusionStyle(::Type{<:BimoduleSector}) = GenericFusion()`. +This is the case for the $A_4$ `BimoduleSector`, since $\mathsf{Rep(A_4)}$ is one of the diagonal fusion categories and has fusion rules with multiplicities. Going beyond the ring structure, the F-symbols are also read in from the artifact, and are stored in a hash table for later use. The F-symbols are then used to perform F-moves on `BimoduleSector`s, which is required to perform recouplings of fusion trees when doing e.g. contractions of tensors with these categories grading the vector spaces. @@ -48,15 +55,23 @@ This allows for more general tensor network simulations of quantum many-body sys Certain changes within TensorKit were required to make it compatible with the multifusion categorical structure. In particular, the presence of a simple unit object for every fusion category on the diagonal of the multifusion category, along with the off-diagonal nature of the simple objects of the bimodule categories, required some internal changes to the way unit objects were treated in TensorKit. -Most notably, the unit object is no longer unique, and thus it is of utmost importance that the correct unit object is considered when performing tensor contractions at the level of the fusion trees. +Most notably, the unit object is no longer unique, and thus it is of utmost importance that the correct one is considered when performing tensor contractions at the level of the fusion trees. This is achieved precisely through colorings and the use of `leftunit` and `rightunit`. For this reason, every fusion tree manipulation which previously involved "the" unit object, now involves the `leftunit` and `rightunit` of some neighboring sector in the manipulation to identify the correct color. -An important example of this is explained in the previous section [#TODO: add opposite module categories reference], namely the mapping of a splitting vertex to a fusion vertex through the B-move. +An important example of this is explained in the previous section on [Opposite module categories](@ref opposite_module_categories), namely the mapping of a splitting vertex to a fusion vertex via a B-move. + +When manipulating spaces graded by `BimoduleSector`s, one needs to also be careful of which unit spaces can compose with other graded spaces on which side. +This introduces the functions `TensorKit.leftunitspace` and `TensorKit.rightunitspace`, which check whether the coloring of the (in general) composite object grading the space is uniform, then return the one-dimensional space with the unique left/right unit object consistent with that coloring. +Clearly, `leftunitspace` and `rightunitspace` coincide for fusion categories; this defaults to `TensorKit.unitspace`. +For multifusion categories, the latter function returns the space with the semisimple unit object grading it. +`leftunitspace` and `rightunitspace` are used with the functions `TensorKit.insertleftunit` and `TensorKit.insertrightunit`. +There, based on the index where a unit space is wished to be inserted, a `leftunitspace` or `rightunitspace` is added such that the resulting space remains consistent with the fusion rules of the multifusion category. +Similarly, `TensorKit.removeunit` is used to remove unit spaces, and will explicitly check whether the space contains only unit objects of any color with `TensorKit.isunitspace`. # MultiTensorKit compatibility with MPSKit This section will briefly explain the changes within MPSKit which are required to make it compatible with MultiTensorKit. -For a more practical explanation, users are kindly guided towards the next section [#TODO: add implementation reference]. +For a more practical explanation, users are kindly guided towards the [Example section](@ref implementation). The main change within MPSKit is very similar to the fusion tree manipulations in TensorKit, namely the use of `leftunit` and `rightunit` to identify the correct unit object. In the case of MPSKit, trivial spaces are used everywhere, from the boundary of a finite MPS to the virtual spaces of a Hamiltonian written in MPO form. diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index 184b717..c1e765b 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -1,4 +1,4 @@ -# Introduction +# [Introduction](@id intro) The manual has been divided into different sections in an attempt to break down the information the user requires to use MultiTensorKit.jl. We start off with a short summary of fusion category theory. @@ -7,7 +7,7 @@ Be aware that notation may differ from the literature. Afterwards, the extension to multifusion categories is explained, and its relation to (bi)module categories over fusion categories is shown. -# Fusion category theory +# [Fusion category theory](@id fusion_cat_theory) The aim of this section is to explain the bare minimum required to proceed to the next section on multifusion category theory and bimodule categories. More details can be found in the [TensorKit](https://jutho.github.io/TensorKit.jl/stable/man/categories/) documentation or the book Tensor Categories [etingof2016tensor](@cite). diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 6657e8d..80763e8 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -1,4 +1,4 @@ -# Symmetric tensor networks: $\mathsf{Rep(A_4)}$ as a guiding example +# [Symmetric tensor networks: $\mathsf{Rep(A_4)}$ as a guiding example](@id implementation) This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). @@ -36,8 +36,6 @@ Thus, the 7 module categories $\mathcal{M}$ one can choose over $\mathsf{Rep(A_4 When referring to specific fusion and module categories, we will use this non-multifusion notation. -The easiest way to identify which elements of the multifusion category correspond to the subcategories we wish to use is ... #TODO - Now that we have identified the fusion and module categories, we want to select the relevant objects we wish to place in our graded spaces. Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. Hence, the simplest way to find the unit object of a fusion subcategory is diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index add4daf..5cf5dec 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -1,4 +1,4 @@ -# Extending to multifusion category theory +# [Extending to multifusion category theory](@id multifusion_cat_theory) This section will explain how to go from a fusion category to a multifusion category, as well as why one would want to consider the latter. Multifusion categories naturally embed the structure of **bimodule categories**. @@ -65,7 +65,7 @@ An F-move with ${}^{\bowtie}\!F$ is given by: ```@raw html ``` -## Opposite module categories +## [Opposite module categories](@id opposite_module_categories) Consider a fusion category $\mathcal{D}$ and a *right* module category $\mathcal{M}$ over $\mathcal{D}$. We can define $\mathcal{M}^{\text{op}}$ to be the opposite category of $\mathcal{M}$ [etingof2009](@cite). Then, $\mathcal{M}^{\text{op}}$ is a *left* module category over $\mathcal{D}$. @@ -256,7 +256,7 @@ Sectors provided by MultiTensorKit do *not* support braiding. We do this for two reasons. On the one hand, there is no natural 1-categorical way of defining braidings between the components of the multifusion category. It is possible that the diagonal fusion categories themselves are braided, but a "componentwise" braiding is unwise to support. -On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. More information on this can be found in the next section [#TODO: add reference to extension page] +On the other hand, it is entirely possible to write matrix product state manipulations in a planar manner (which has been done in [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl)), thus avoiding the need of a braiding tensor. More information on this can be found in [MultiTensorKit as an extension to TensorKit](@ref extension). ## Examples of multifusion categories Without specifying any of the categories, the simplest non-trivial multifusion category is a $2\times 2$ one, and the categories can be organised in a matrix as @@ -275,4 +275,4 @@ This particular example can be found in [TensorKitSectors](https://github.com/Qu This construction can be generalised to $\mathcal{C}_1 = \mathcal{C}_2 = \mathsf{Rep(G)}$ with $\mathsf{G}$ a finite abelian group, such that the entire multifusion category is Morita equivalent to $\mathsf{Rep(G)}$ and can be evaluated as the Tambara-Yamagami category $\mathsf{TY}(\mathsf{G})$ (with positive Frobenius-Schur indicator for our purposes), and $\mathsf{Vec}$ will represent the duality object which squares to all invertible objects of the original group. To be exact, one of the diagonal fusion categories should be $\mathsf{Vec_G}$ for the correct Morita dual relation, but it is known for abelian groups that this is isomorphic to $\mathsf{Rep(G)}$. -The example $\mathcal{C}_1 = \mathsf{Rep(A_4)}$ is worked out more in detail on the [#TODO add reference to implementation page]. \ No newline at end of file +The example $\mathcal{C}_1 = \mathsf{Rep(A_4)}$ is worked out more in detail in the [guiding example](@ref implementation). \ No newline at end of file From ce1e6b8014ba879ef430affe95e465525e46c188 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 12 Feb 2026 12:53:12 +0100 Subject: [PATCH 201/206] clarify with image --- docs/src/man/extension.md | 24 ++- docs/src/man/img/anyonchain_excitation.svg | 210 +++++++++++++++++++++ 2 files changed, 227 insertions(+), 7 deletions(-) create mode 100644 docs/src/man/img/anyonchain_excitation.svg diff --git a/docs/src/man/extension.md b/docs/src/man/extension.md index d9ebf0f..4321143 100644 --- a/docs/src/man/extension.md +++ b/docs/src/man/extension.md @@ -36,6 +36,7 @@ For this reason, the `TensorKitSectors.UnitStyle` trait is introduced to differe This trait is used to specialise certain functions within TensorKit (see below). `TensorKitSectors.allunits` is also introduced to return all the simple unit objects of the (multi)fusion category. This function must be defined for every multifusion category to be compatible with TensorKit. + Via the fusion rules, the left and right units of all `BimoduleSector`s along with their duals are also extracted and cached. The fusion behavior that must be imposed for the entire `BimoduleSector` is the most general one that appears in the fusion between any two `BimoduleSector`s. In particular, if one of the diagonal fusion categories has fusion rules with multiplicities, then the entire `BimoduleSector` must be set to have `TensorKitSectors.FusionStyle(::Type{<:BimoduleSector}) = GenericFusion()`. @@ -68,19 +69,28 @@ For multifusion categories, the latter function returns the space with the semis There, based on the index where a unit space is wished to be inserted, a `leftunitspace` or `rightunitspace` is added such that the resulting space remains consistent with the fusion rules of the multifusion category. Similarly, `TensorKit.removeunit` is used to remove unit spaces, and will explicitly check whether the space contains only unit objects of any color with `TensorKit.isunitspace`. -# MultiTensorKit compatibility with MPSKit +## MultiTensorKit compatibility with MPSKit This section will briefly explain the changes within MPSKit which are required to make it compatible with MultiTensorKit. For a more practical explanation, users are kindly guided towards the [Example section](@ref implementation). The main change within MPSKit is very similar to the fusion tree manipulations in TensorKit, namely the use of `leftunit` and `rightunit` to identify the correct unit object. -In the case of MPSKit, trivial spaces are used everywhere, from the boundary of a finite MPS to the virtual spaces of a Hamiltonian written in MPO form. -Additionally, multiple tensor contractions made use of braiding tensors to perform crossings of legs of the MPS/MPOs. +In the case of MPSKit, trivial spaces are used everywhere, from the boundary of a finite matrix product state to the virtual spaces of a Hamiltonian written as an matrix product operator. +Additionally, multiple tensor contractions made use of braiding tensors to perform crossings of legs of the MPSs/MPOs. Since no (half-)braiding is available for the `BimoduleSector`s, all algorithms had to be made planar, and thus all braiding tensors were removed. -Since all braidings were trivial, this was dealt with by simply removing the braiding tensors and replacing the crossing of legs with a termination and reintroduction of the legs without crossing. -This is achieved through `TensorKit.removeunit` and `TensorKit.insertleftunit`/`TensorKit.insertrightunit`, which remove and insert spaces with the correct unit object, respectively, based on the grading of neighboring vector spaces. -At the level of the MPS, the correct unit object can be identified through the use of `leftunit` and `rightunit`. +Since all braidings were trivial, this was dealt with by simply removing the braiding tensors and replacing the crossing of legs with a termination and reintroduction of the legs without crossing by aid of `removeunit`, `insertleftunit` and `insertrightunit`. + +At the level of the MPS, the correct unit object can be identified through the use of `leftunit(ψ::AbstractMPS)` and `rightunit(ψ::AbstractMPS)`. When the virtual space of the MPS is graded by a diagonal `BimoduleSector`, i.ea unitary fusion category, then these all coincide with the unique unit object of that fusion category. However, when the virtual space is graded by an off-diagonal `BimoduleSector`, i.e. a bimodule category, then the left and right units are different, and thus it is important to identify the correct one when performing MPS algorithms. For example, Hamiltonians should always have the same coloring as the right unit of the MPS, since they are contracted at the physical level of the MPS. -Similarly, excitations of an MPS are labeled by `BimoduleSector`s with the same coloring as the left unit of the MPS, since the auxiliary charge leg of the excitation is attached on the other side of the MPS to the virtual level. \ No newline at end of file +Similarly, excitations of an MPS are labeled by `BimoduleSector`s with the same coloring as the left unit of the MPS, since the auxiliary charge leg of the excitation is attached on the other side of the MPS to the virtual level. +This is illustrated in the following figure. + +```@raw html + +``` + +Here, $\mathcal{D}$ is the fusion category grading the physical space of the MPS, $\mathcal{R}$ is the right $\mathcal{D}$-module category grading the virtual space of the MPS. +$\mathcal{E}$ is the Morita dual fusion category of $\mathcal{D}$ with respect to $\mathcal{R}$, which is the category labelling the excitations of the MPS. +In this case, the left unit of the MPS is in $\mathcal{E}$, and the right unit in $\mathcal{D}$. \ No newline at end of file diff --git a/docs/src/man/img/anyonchain_excitation.svg b/docs/src/man/img/anyonchain_excitation.svg new file mode 100644 index 0000000..a7f1d03 --- /dev/null +++ b/docs/src/man/img/anyonchain_excitation.svg @@ -0,0 +1,210 @@ + + + + From 10a39d53572ebfbce8c5902a9e4dede1d3fb6ae3 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 12 Feb 2026 12:53:29 +0100 Subject: [PATCH 202/206] proofread implementation --- docs/src/man/implementation.md | 47 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 80763e8..69fb80c 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -1,5 +1,6 @@ # [Symmetric tensor networks: $\mathsf{Rep(A_4)}$ as a guiding example](@id implementation) This tutorial is dedicated to explaining how MultiTensorKit was implemented to be compatible with with TensorKit and MPSKit for matrix product state simulations. +This section should be largely self-contained and is meant to be a practical guide to using MultiTensorKit. In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. @@ -7,13 +8,9 @@ The model considered there is a spin-1 Heisenberg model with additional terms to This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep(A_4)}$. Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. There are 3 fusion categories up to equivalence: -- ``\mathsf{Vec_{A_4}}``: the category of $\mathsf{A_4}$-graded vector spaces. -The group $\mathsf{A}_4$ is order $4!/2 = 12$. -It has thus 12 objects. -- ``\mathsf{Rep(A_4)}``: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. -One is the trivial representation, two are one-dimensional non-trivial and the last is three-dimensional. -- ``\mathsf{Rep(H)}``: the representation category of some Hopf algebra which does not have a name. -It has 6 simple objects. +- ``\mathsf{Vec_{A_4}}``: the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$ and has thus 12 simple objects. +- ``\mathsf{Rep(A_4)}``: the irreducible representations of the group $\mathsf{A}_4$, of which there are 4. One is the trivial representation, two are one-dimensional non-trivial and the last is three-dimensional. +- ``\mathsf{Rep(H)}``: the representation category of some Hopf algebra which does not have a name. It has 6 simple objects. For this example, we will require the following packages: ````julia @@ -37,11 +34,11 @@ Thus, the 7 module categories $\mathcal{M}$ one can choose over $\mathsf{Rep(A_4 When referring to specific fusion and module categories, we will use this non-multifusion notation. Now that we have identified the fusion and module categories, we want to select the relevant objects we wish to place in our graded spaces. -Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label=1` corresponds to the unit object. +Unfortunately, due to the nature of how the N-symbol and F-symbol data are generated, the objects of the fusion subcategories are not ordered such that `label = 1` corresponds to the unit object. Hence, the simplest way to find the unit object of a fusion subcategory is ````julia -unit(A4Object(i,i,1)) +unit(A4Object(i, i, 1)) ```` Left and right units of subcategories are uniquely specified by their fusion rules. @@ -64,8 +61,8 @@ $$^{}_a \mathbb{1} \in a \times a^* \quad \text{and} \quad \mathbb{1}_a \in a^* with multiplicity 1. ## Constructing the Hamiltonian and matrix product state -TensorKit has been made compatible with the multifusion structure by keeping track of the relevant units in the fusion tree manipulations. -With this, we can make `GradedSpace`s whose objects are in `A4Object`: +TensorKit has been made compatible with the multifusion structure. +With this, we can make `GradedSpace`s whose objects are in `A4Object`: ````julia D1 = A4Object(6, 6, 1) # unit in this case @@ -120,17 +117,17 @@ and construct the finite MPS: D = 40 # bond dimension V = Vect[A4Object](M => D) Vb = Vect[A4Object](M => 1) # non-degenerate boundary virtual space -init_mps = FiniteMPS(L, P, V; left=Vb, right=Vb) +init_mps = FiniteMPS(L, P, V; left = Vb, right = Vb) ```` !!! warning "Important" We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for any `BimoduleSector` due to the semisimple unit. -## DMRG2 and the entanglement spectrum +## Two-site DMRG and the entanglement spectrum We can now look to find the ground state of the Hamiltonian with two-site DMRG. -We use this instead of the "usual" one-site DMRG because the two-site one will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. +We use this instead of the "usual" one-site DMRG because the two-site algorithm will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. ````julia -dmrg2alg = DMRG2(;verbosity=2, tol=1e-7, trscheme=truncbelow(1e-4)) +dmrg2alg = DMRG2(; verbosity = 2, tol = 1e-7, trscheme = truncbelow(1e-4)) ψ, _ = find_groundstate(init_mps, H, dmrg2alg) ```` The truncation scheme keyword argument is mandatory when calling `DMRG2` in MPSKit. @@ -146,16 +143,16 @@ This returns a dictionary which maps the objects grading the virtual space to th In this case, there is one key corresponding to $\mathsf{Vec}$. We can also immediately return a plot of this data by the following: ````julia -entanglementplot(ψ;site=round(Int, L/2)) +entanglementplot(ψ; site = round(Int, L/2)) ```` -This plot will show the singular values per object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. +This plot will show the singular values per simple object, as well as include the "effective" bond dimension, which is simply the dimension of the virtual space where we cut the system. The next section will show this plot along with those when selecting the other module categories. ## Search for the correct dual model -Consider a quantum lattice model with its symmetries determing the phase diagram. +Consider a quantum lattice model with its symmetries determining the phase diagram. For every phase in the phase diagram, the dual model for which the ground state maximally breaks all symmetries spontaneously is the one where the entanglement is minimised and the tensor network is represented most efficiently [Lootens_2024](@cite). -Let us confirm this result, starting with the $\mathsf{Rep(A_4)}$ spontaneous symmetry breaking phase. +Let us confirm this result, starting with the $A_4$-symmetric phase whose ideal dual model is in the $\mathsf{Rep(A_4)}$ spontaneous symmetry breaking phase. The code will look exactly the same as above, except the virtual space of the MPS will change to be graded by the other module categories: ````julia @@ -163,12 +160,12 @@ module_numlabels(i) = MultiTensorKit._numlabels(A4Object, i, 6) V = Vect[A4Object]((i, 6, label) => D for label in 1:module_numlabels(i)) Vb = Vect[A4Object](first(sectors(V)) => 1) # not all charges on boundary, play around with what is there ```` - +#TODO: fix the figure ```@raw html ``` -The plot shows the entanglement spectra of the various dual models in the middle of the ground state for the original Hamiltonian probing the $\mathsf{Rep(A_4)}$-symmetric phase, along with the ground state without symmetries. +The plot shows the entanglement spectra of the various dual models in the middle of the ground state for the original Hamiltonian probing the $A_4$-symmetric phase, along with the ground state without symmetries. Every subtitle also mentions the memory required to store the same middle ground state tensor. This plot should be compared to [Lootens_2024; Figure 2](@cite). @@ -176,11 +173,11 @@ This can be repeated with other parameter values for $J_1$ and $J_2$ in the Hami !!! note "Additional functions and keyword arguments" Certain commonly used functions within MPSKit require extra keyword arguments to be compatible with multifusion MPS simulations. -In particular, the keyword argument `sector` (note the lowercase "s") appears in + In particular, the keyword argument `sector` (note the lowercase "s") appears in - `excitations` with `QuasiparticleAnsatz`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. -Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the charged excitations lie in the symmetry category $\mathcal{C} = \mathcal{D^*_M}$. + Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the charged excitations lie in the symmetry category $\mathcal{C} = \mathcal{D^*_M}$. - `exact_diagonalization`: the `sector` keyword argument now requires an object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. -This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. + This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. ## Differences with the infinite case We can repeat the above calcalations also for an infinite system. @@ -188,7 +185,7 @@ The `lattice` variable will change, as well as the MPS constructor and the algor ````julia lattice = InfiniteChain(1) init = InfiniteMPS([P], [V]) -inf_alg = VUMPS(; verbosity=2, tol=1e-7) +inf_alg = VUMPS(; verbosity = 2, tol = 1e-7) ```` Besides `VUMPS`, `IDMRG` and `IDMRG2` are as easy to run with the `A4Object` `BimoduleSector`. From 6dd16a54f33168728e3171bd2de7edd98fb168bc Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 12 Feb 2026 16:39:59 +0100 Subject: [PATCH 203/206] change intro header --- docs/src/man/fusioncats.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/src/man/fusioncats.md b/docs/src/man/fusioncats.md index c1e765b..e38a766 100644 --- a/docs/src/man/fusioncats.md +++ b/docs/src/man/fusioncats.md @@ -1,5 +1,3 @@ -# [Introduction](@id intro) - The manual has been divided into different sections in an attempt to break down the information the user requires to use MultiTensorKit.jl. We start off with a short summary of fusion category theory. Users familiar with TensorKit.jl may have read the [Optional introduction to category theory](https://jutho.github.io/TensorKit.jl/stable/man/categories/) in the documentation of TensorKit; this section can then largely be skipped. From 071704b56eaf50ccaaabf067d0cc3d88f73e3f9c Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 12 Feb 2026 16:40:33 +0100 Subject: [PATCH 204/206] figures with julia colors --- docs/src/man/extension.md | 2 +- docs/src/man/img/Bmove_MF.svg | 1862 ++- docs/src/man/img/Bmove_lit.svg | 1443 +-- docs/src/man/img/Fmove.svg | 2129 ++-- docs/src/man/img/Fmove_CM.svg | 1295 +-- docs/src/man/img/Fmove_CMD.svg | 1346 +-- docs/src/man/img/Fmove_D.svg | 1292 +-- docs/src/man/img/Fmove_MD.svg | 1319 +-- docs/src/man/img/Fmove_coloring.svg | 4618 ++++---- docs/src/man/img/Nsymbol_coloring.svg | 2128 ++-- docs/src/man/img/anyonchain_excitation.svg | 406 +- docs/src/man/img/homvector.svg | 667 +- docs/src/man/img/pentagon_colored.svg | 11449 +++++++++++++------ docs/src/man/img/qdim_fs_MF.svg | 704 +- docs/src/man/multifusioncats.md | 3 +- 15 files changed, 17556 insertions(+), 13107 deletions(-) diff --git a/docs/src/man/extension.md b/docs/src/man/extension.md index 4321143..5b89c22 100644 --- a/docs/src/man/extension.md +++ b/docs/src/man/extension.md @@ -88,7 +88,7 @@ Similarly, excitations of an MPS are labeled by `BimoduleSector`s with the same This is illustrated in the following figure. ```@raw html - + ``` Here, $\mathcal{D}$ is the fusion category grading the physical space of the MPS, $\mathcal{R}$ is the right $\mathcal{D}$-module category grading the virtual space of the MPS. diff --git a/docs/src/man/img/Bmove_MF.svg b/docs/src/man/img/Bmove_MF.svg index 27513af..d7b2c30 100644 --- a/docs/src/man/img/Bmove_MF.svg +++ b/docs/src/man/img/Bmove_MF.svg @@ -1,963 +1,915 @@ - +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBsDzf3 +Y28BAACAs3V9V9ePY28CAACAM3VR792OvQsAAADO02VMnfXV2NvgP74B+dpix7BW86kAAAAldEVY +dGRhdGU6Y3JlYXRlADIwMjYtMDItMTJUMTU6MTQ6MDArMDA6MDBCmvl8AAAAJXRFWHRkYXRlOm1v +ZGlmeQAyMDI2LTAyLTEyVDE1OjE0OjAwKzAwOjAwM8dBwAAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAA +MjAyNi0wMi0xMlQxNToxNDowMCswMDowMGTSYB8AAAAndEVYdHBkZjpIaVJlc0JvdW5kaW5nQm94 +ADI2Ni41MjF4NzcuOTYyKzArMDXLp2IAAAATdEVYdHBkZjpWZXJzaW9uAFBERi0xLjVTNlrBAAAA +AElFTkSuQmCC" /> diff --git a/docs/src/man/img/Bmove_lit.svg b/docs/src/man/img/Bmove_lit.svg index 17667aa..7f2051e 100644 --- a/docs/src/man/img/Bmove_lit.svg +++ b/docs/src/man/img/Bmove_lit.svg @@ -3,722 +3,729 @@ +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 +YII=" /> diff --git a/docs/src/man/img/Fmove.svg b/docs/src/man/img/Fmove.svg index 0ed24e1..455b368 100644 --- a/docs/src/man/img/Fmove.svg +++ b/docs/src/man/img/Fmove.svg @@ -3,1069 +3,1072 @@ +AAAAAKidmA4AAAAAAABqJ6YDAAAAAACA2onpAAAAAAAAoHZiOgAAAAAAAKidmA4AAAAAAABqJ6YD +AAAAAACA2onpAAAAAAAAoHZiOgAAAAAAAKidmA4AAAAAAABqJ6YDAAAAAACA2onpAAAAAAAAoHZi +OgAAAAAAAKidmA4AAAAAAABqJ6YDAAAAAACA2onpAAAAAAAAoHZiOgAAAAAAAKidmA4AAAAAAABq +J6YDAAAAAACA2onpAAAAAAAAoHZiOgAAAAAAAKidmA4AAAAAAABqJ6YDAAAAAACA2onpAAAAAAAA +oHZiOgAAAAAAAKidmA4AAAAAAABqJ6YDAAAAAACA2onpAAAAAAAAoHZiOgAAAAAAAKidmA4AAAAA +AABqJ6YDAAAAAACA2onpAAAAAAAAoHZiOgAAAAAAAKidmA4AAAAAAABqJ6YDAAAAAACA2onpAAAA +AAAAoHZiOgAAAAAAAKidmA4AAAAAAABqJ6YDAAAAAACA2onpAAAAAAAAoHZiOgAAAAAAgCOlbuqn +TtOj4DKJ6QAAAAAAAI6SevEZH/E3DZoeCZdITAcAAAAAAHCENIzPWFbSiek4gpgOAAAAAADgYOk1 +3tYfaHvJEf5//ZErGE9Cz18AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjYtMDItMTJUMTU6MzU6MjQr +MDA6MDBDXgjtAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI2LTAyLTEyVDE1OjM1OjI0KzAwOjAwMgOw +UQAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNi0wMi0xMlQxNTozNToyNCswMDowMGUWkY4AAAAm +dEVYdHBkZjpIaVJlc0JvdW5kaW5nQm94ADI1NC43OXg3Ny4yMjQrMCsw7u2utAAAABN0RVh0cGRm +OlZlcnNpb24AUERGLTEuNVM2WsEAAAAASUVORK5CYII=" /> diff --git a/docs/src/man/img/Fmove_CM.svg b/docs/src/man/img/Fmove_CM.svg index b2faaa9..fc5cc83 100644 --- a/docs/src/man/img/Fmove_CM.svg +++ b/docs/src/man/img/Fmove_CM.svg @@ -2,653 +2,662 @@ +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOr0/wdyFFoohq91BwAAACV0RVh0ZGF0ZTpj +cmVhdGUAMjAyNi0wMi0xMlQxNDoxNzo1MSswMDowMJqsnioAAAAldEVYdGRhdGU6bW9kaWZ5ADIw +MjYtMDItMTJUMTQ6MTc6NTErMDA6MDDr8SaWAAAAKHRFWHRkYXRlOnRpbWVzdGFtcAAyMDI2LTAy +LTEyVDE0OjE3OjUxKzAwOjAwvOQHSQAAACd0RVh0cGRmOkhpUmVzQm91bmRpbmdCb3gAMjIzLjc1 +NXg3NC4zMTMrMCswHhnesgAAABN0RVh0cGRmOlZlcnNpb24AUERGLTEuNVM2WsEAAAAASUVORK5C +YII=" /> diff --git a/docs/src/man/img/Fmove_CMD.svg b/docs/src/man/img/Fmove_CMD.svg index 27792b6..2db2f12 100644 --- a/docs/src/man/img/Fmove_CMD.svg +++ b/docs/src/man/img/Fmove_CMD.svg @@ -2,677 +2,687 @@ +AAAAAAAAAAAAAAAAAAAAAAAAAAAAtMj/HzlevEQ7FTYiAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI2 +LTAyLTEyVDE0OjE5OjIzKzAwOjAwGT+2qQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNi0wMi0xMlQx +NDoxOToyMyswMDowMGhiDhUAAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjYtMDItMTJUMTQ6MTk6 +MjQrMDA6MDD60BFEAAAAJ3RFWHRwZGY6SGlSZXNCb3VuZGluZ0JveAAyMjkuOTg3eDc0LjIzNisw +KzCpeeowAAAAE3RFWHRwZGY6VmVyc2lvbgBQREYtMS41UzZawQAAAABJRU5ErkJggg==" /> diff --git a/docs/src/man/img/Fmove_D.svg b/docs/src/man/img/Fmove_D.svg index 1838d4c..a66cdac 100644 --- a/docs/src/man/img/Fmove_D.svg +++ b/docs/src/man/img/Fmove_D.svg @@ -2,650 +2,658 @@ +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAo/f8B +umuGGh/w7V0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjYtMDItMTJUMTM6MTE6MzErMDA6MDAsruGy +AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI2LTAyLTEyVDEzOjExOjMxKzAwOjAwXfNZDgAAACh0RVh0 +ZGF0ZTp0aW1lc3RhbXAAMjAyNi0wMi0xMlQxMzoxMTozMSswMDowMArmeNEAAAAndEVYdHBkZjpI +aVJlc0JvdW5kaW5nQm94ADIyMy41Njd4NzUuNzQ3KzArMOj/720AAAATdEVYdHBkZjpWZXJzaW9u +AFBERi0xLjVTNlrBAAAAAElFTkSuQmCC" /> diff --git a/docs/src/man/img/Fmove_MD.svg b/docs/src/man/img/Fmove_MD.svg index e360755..d2c7733 100644 --- a/docs/src/man/img/Fmove_MD.svg +++ b/docs/src/man/img/Fmove_MD.svg @@ -2,667 +2,672 @@ +lfj/A2CnmgzB6ecUAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI2LTAyLTEyVDE0OjE1OjE4KzAwOjAw +j4sFPgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNi0wMi0xMlQxNDoxNToxOCswMDowMP7WvYIAAAAo +dEVYdGRhdGU6dGltZXN0YW1wADIwMjYtMDItMTJUMTQ6MTU6MTgrMDA6MDCpw5xdAAAAJnRFWHRw +ZGY6SGlSZXNCb3VuZGluZ0JveAAyMjQuMjJ4NzUuNjY5KzArMMYRy+4AAAATdEVYdHBkZjpWZXJz +aW9uAFBERi0xLjVTNlrBAAAAAElFTkSuQmCC" /> diff --git a/docs/src/man/img/Fmove_coloring.svg b/docs/src/man/img/Fmove_coloring.svg index 804e15d..a78e3b3 100644 --- a/docs/src/man/img/Fmove_coloring.svg +++ b/docs/src/man/img/Fmove_coloring.svg @@ -3,2334 +3,2292 @@ +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 +AAAAAAAAAIAyuWi7mFYxABgfYTEAuKSLtotpFQMAAAAAAAAAAKBMLtouplUMAMZHWAwAxuC87WJa +xQAAAAAAAAAAACij87aLaRUDgPESFgOAMXjm6Rvxf10ZfbKqVQwAAAAAAAAAAIAyOm+7mFYxABgv +YTEAGJOb/7d/OdL9Fp54QqsYAAAAAAAAAAAApfWdb//FyPfVKgYA4yUsBgBj8s//s+sj3e/pf/5/ +LHqoAAAAAAAAAAAAMDFPPXmt6CEAwNwSFgOAKVt44omihwAAAAAAAAAAAAAAQAkJiwEAAAAAAAAA +AAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkI +iwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAA +AAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACU +gLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAA +AAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAA +QAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAA +AAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAA +AACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEA +AAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAA +AAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAY +AAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAA +AAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkI +iwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAA +AAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACU +gLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAAAAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwEAAAAA +AAAAAAAAAACUgLAYAAAAAAAAAAAAAAAAQAkIiwHAmDzzL26MdL8b168XPVQAAAAAAAAAAACYqGee +Hr6m7oUvP1v0MAGgdB4regCM1+6P78ZT/+lTRQ8DYG49/Z//n+LT//nf9739sX/2z+I3//7fx/r3 +7xY9VIC59etGo+ghAAAAAAAAAFPw3uE78eFHHxQ9DIC59Z/8H/6Toff57Pe/t54OoEAf/4f/WPQQ +mABhsZIxsQW42v5///v/Hv/D/+s3RQ8DAAAAAAAAAKD0Pvn04/jk04+LHgYAA/y68f8peggAUDpf +KHoAAAAAAAAAAAAAAAAAAFyesBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAA +AAAAAAAAAABACaScc9FjAAAAAAAAAAAAAAAAAOCSNIsBAAAAAAAAAAAAAAAAlICwGAAAAAAAAAAA +AAAAAEAJCIsBAAAAAAAAAAAAAAAAlICwGAAAAAAAAAAAAAAAAEAJCIsBAAAAAAAAAAAAAAAAlICw +GAAAAAAAAAAAAAAAAEAJCIsBAAAAAAAAAAAAAAAAlICwGAAAAAAAAAAAAAAAAEAJCIsBAAAAAAAA +AAAAAAAAlICwGAAAAAAAAAAAAAAAAEAJCIsBAAAAAAAAAAAAAAAAlICwGAAAAAAAAAAAAAAAAEAJ +CIsBAAAAAAAAAAAAAAAAlICwGAAAAAAAAAAAAAAAAEAJCIsBAAAAAAAAAAAAAAAAlICwGAAAAAAA +AAAAAAAAAEAJCIsBAAAAAAAAAAAAAAAAlICwGAAAAAAAAAAAAAAAAEAJCIsBAAAAAAAAAAAAAAAA +lICwGAAAAAAAAAAAAAAAAEAJCIsBAAAAAAAAAAAAAAAAlICwGAAAAAAAAAAAAAAAAEAJCIsBAAAA +AAAAAAAAAAAAlICwGAAAAAAAAAAAAAAAAEAJCIsBAAAAAAAAAAAAAAAAlICwGAAAAAAAAAAAAAAA +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 +CQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAA +AAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAA +AJSAsBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABACQiLAQAA +AAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAA +AABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgA +AAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAA +AAAAAJSAsBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABACQiL +AQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAA +AAAAAABACQiLAQAAAAAAAAAAAAAAAJSAsBgAAAAAAAAAAAAAAABTlVJaTCmtppQWih4LlImwGAAA +AAAAAAAAAAAAAFOTUlqOiFpEHEbEb1NK60WPCcpCWAwAAAAAAAAAAAAAAICpSCltRiso1t0oJiwG +YyIsBgAAAAAAAAAAwP+/nTkmAgAEYiCYSMA1FnCLgW8o6HbbmzkAAIDv2u4kZ0jr9QXMLnjW5qkO +iRFtAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI2LTAyLTEyVDE0OjM0OjQ3KzAwOjAwho2pTAAAACV0 +RVh0ZGF0ZTptb2RpZnkAMjAyNi0wMi0xMlQxNDozNDo0NyswMDowMPfQEfAAAAAodEVYdGRhdGU6 +dGltZXN0YW1wADIwMjYtMDItMTJUMTQ6MzQ6NDcrMDA6MDCgxTAvAAAAJ3RFWHRwZGY6SGlSZXNC +b3VuZGluZ0JveAAyNDkuNjI1eDc3LjQ3MyswKzCHkdXuAAAAE3RFWHRwZGY6VmVyc2lvbgBQREYt +MS41UzZawQAAAABJRU5ErkJggg==" /> diff --git a/docs/src/man/img/Nsymbol_coloring.svg b/docs/src/man/img/Nsymbol_coloring.svg index 1fcf989..616bfa2 100644 --- a/docs/src/man/img/Nsymbol_coloring.svg +++ b/docs/src/man/img/Nsymbol_coloring.svg @@ -2,993 +2,985 @@ +AAAAoPn/njm61FpCauMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjYtMDItMTJUMTQ6MzY6NDMrMDA6 +MDB2N11iAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI2LTAyLTEyVDE0OjM2OjQ0KzAwOjAwws3bUAAA +ACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNi0wMi0xMlQxNDozNjo0NCswMDowMJXY+o8AAAAodEVY +dHBkZjpIaVJlc0JvdW5kaW5nQm94ADIwMC4xODR4MTUyLjkyOSswKzC5gWMjAAAAE3RFWHRwZGY6 +VmVyc2lvbgBQREYtMS41UzZawQAAAABJRU5ErkJggg==" /> diff --git a/docs/src/man/img/anyonchain_excitation.svg b/docs/src/man/img/anyonchain_excitation.svg index a7f1d03..241b1be 100644 --- a/docs/src/man/img/anyonchain_excitation.svg +++ b/docs/src/man/img/anyonchain_excitation.svg @@ -4,207 +4,211 @@ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABvUAAAItCAMAAAA+KAZ/AAAAIGNIUk0AAHomAACAhAAA+gAAAIDo AAB1MAAA6mAAADqYAAAXcJy6UTwAAAE+UExURf///8s8M8s8M8s8M8s8M8s8M8s8M8s8M8s8M8s8 M8s8M8s8M8s8M8s8M8s8M5VYspVYspVYspVYspVYspVYspVYspVYspVYspVYspVYspVYspVYspVY -so5bqo5bqY9bq41bqJNZr5FarY1cqI5cqZVYspVYspVYso1cqI5cqZVYspZYs5VYs55TnL1EVZVY -spZYs0h6UmVudlF3XZdZtJVYspZZs5ZZs5ZYs5VYsrBLdaFTmJVYspVYsiKLIiKLIiKLIiKLIiKL +spVYspZYs5VYs45bqo5bqY9bq41bqJNZr5VYspZYs5FarY1cqI5cqZVYspVYspVYso1cqI5cqZ5T +nL1EVZZZs5ZYs5VYskh6UmVudpZZs5VYspVYslF3XZdZtJVYsrBLdaFTmCKLIiKLIiKLIiKLIiKL IiKLIiKLIiKLIiKLIiKLIiKLIiKLIiKLIiKLIiKMIiKLIiKLIiKLIiKLIiKLIiKMIiKMIiKLIiKL IiKMIss8M5VYsrlFXatNf7JJbsc+O5lWqsBCTJxUoaNRkLVHZqdPiEF9SFdzZEx4VlJ2XlJ2XSKL -Iv///8z+EPYAAABXdFJOUwBEiJm77t0zzCIRqndmVSJEM1WImbvdZneq7swR2vf58MPL9PO/3/rw -2tb10cToxOPNdadctHVQp/JpUM3mu0SIESJVmczuM3eqZt1Q2ubXzff1dcfWj9etdGwAAAABYktH -RACIBR1IAAAACXBIWXMAAAPoAAAD6ADCfGL9AAAAB3RJTUUH6gIMCzIfJzDI+QAAKplJREFUeNrt -3Xl/HOlWH3CpJXmXrbG8zNhOSEgI2QMhQFZbXsZrSAIBLAIECJdk3v8riKTeu6u6S93PUVWd/n7/ -uB9mrtwuHc49v3r6qWVvDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAL+4ODw6PvQ7cOB/ttHw8AxLg9 -uPN90a1B20cFAMXdHdz6XunOvbYPDQCK2r//vdZh2wcHAAXtH35fxeYeAGncnVnnHR0eTi5mmbC1 -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 -b38X37lQm3k29YB5KzLPpl4Z9ZkXsKm3t3ewe+/Xq8+83m7qnT4l1t/7+7/2D/5h2weR2q//o1/7 -x7/e9kFU+I1/8pv18+I3f6Ptw7uOf/prv/bP2j6GKv/8X9RX+Pxflv/7/tX0C85/XfaTuzom/s1v -rajwb7V9dNf05Oo86PGzcwCa+LNp6v2vto+FDZy+2nvU9jEA9MWfT0PvL/6y7YNhE6d7P7V9CAB9 -8b+nqffnbR8LG3mx1/YRAPTFX1nq9Z/UA2jor6ep9zdtHwsb2nux/WcA7IS/nC71/qrtY2FDe6dt -HwFAX/yNCzj77uXenhsXAJr5a5ey9N3J6mdHADDj//zNX3z//mdWen31dPgEtUcnBPrtv/3bv/3V -r/7u4j//bduHktTvXNT2//7q/1385++0fShL/t3vrvgf4O+1fXSNXdT27371q4v//O22j2TJ7//7 -/1Bf4d8N+Sv/438q/5ldHhO/95/rK/xffr/to7seTw29Ea9/GXvT9qEkdTap8Fnbh1JhxTMM+/Oe -oUmFX7d9JBVWfV3Vm6dEdntMnDytrfBPbR8bHdTtds6g26m3Kvd68/jpTqfeqtzrzRsBuj4m6nPv -x7YPje7pejv3X9dTb0Xu9eVVQx1PvRW515e3v3V/TNTmXl9OLLg53W/nvut+6tXn3knbB9ZM51Ov -Pvd68qbvPoyJmtx71pMTC25OH9q53/qQenW515OtvR6kXm3u9WNrrx9jojr3bO2xoB/t3Gf9SL2a -3OvH1l4vUq8m9/qxtdeXMVGZe7b2mNeXdu6vvqRede71YmuvJ6lXnXu92Nrrz5ioyr1enFhwc/rT -zn3Vn9SrzL2Tto+pgd6kXmXu9WFrr09jYjn3bO0xp0/t3E99Sr2K3OvD1l6PUq8q93qwtdevMbGU -e7b2mNWvdu6jfqXecu71YGuvV6m3nHs92Nrr25hYzD1be8zoWzv3T99Sbyn3ur+117PUW8q97m/t -9W9MLORe908suDn9a+e+6V/qLebeSduHs07vUm8x9zq/tdfHMTGXe7b2mOpjO/dLH1NvPvc6v7XX -w9RbyL2ub+31c0zM5p6tPSb62c590s/Um8u9rm/t9TL15nKv61t7fR0TM7lna4+xvrZzf/Q19WZz -r+Nbez1Nvdnc6/jWXn/HxDT3On5iwc3pbzv3RX9Tbyb3Tto+kpV6m3ozudftrb0+j4lx7tnaY6TP -7dwPfU69Se51e2uvx6k3zb1Ob+31e0yMcs/WHkP9buc+6HfqjXOv01t7vU69ce51emuv72NimHu2 -9rjS93buvr6n3ij3ury11/PUG+Vel7f2+j8mrnKvyycW3Jz+t3PX9T/1hrl30vZB1Ot96g1zr8Nb -exnGxEXu2drjUoZ27rYMqXeZex3e2kuQele5192tvRxj4uSprT32srRzl+VIvYvcO2n7CGqlSL2L -3JN60U4etX0EdECWdu6uLKnXYUlSr8OMCRLRztGkXjipF82YIBHtHE3qhZN60YwJEtHO0aReOKkX -zZggEe0cTeqFk3rRjAkS0c7RpF44qRfNmCAR7RxN6oWTetGMCRLRztGkXjipF82YIBHtHE3qhZN6 -0YwJEtHO0aReOKkXzZggEe0cTeqFk3rRjAkS0c7RpF44qRfNmCAR7RxN6oWTetGMCRLRztGkXjip -F82YIBHtHE3qhZN60YwJEtHO0aReOKkXzZggEe0cTeqFk3rRjAkS0c7RpF44qRfNmCAR7RxN6oWT -etGMCRLRztGkXjipF82YIBHtHE3qhZN60YwJEtHO0aReOKkXzZggEe0cTeqFk3rRjAkS0c7RpF44 -qRfNmCAR7RxN6oWTetGMCRLRztGkXjipF82YIBHtHE3qhZN60YwJEtHO0aReOKkXzZggEe0cTeqF -k3rRjAkS0c7RpF44qRfNmCAR7RxN6oWTetGMCRLRztGkXjipF82YIBHtHE3qhZN60YwJEtHO0aRe -OKkXzZggEe0cTeqFk3rRjAkS0c7RpF44qRfNmCAR7RxN6oWTetGMCRLRztGkXjipF82YIBHtHE3q -hZN60YwJEtHO0aReOKkXzZggEe0cTeqFk3rRjAkS0c7RpF44qRfNmCAR7RxN6oWTetGMCRLRztGk -XjipF82YIBHtHE3qhZN60YwJEtHO0aReOKkXzZggEe0cTeqFk3rRjAkS0c7RpF44qRfNmCAR7RxN -6oWTetGMCRLRztGkXjipF82YIBHtHE3qhZN60YwJEtHO0aReOKkXzZggEe0cTeqFk3rRjAkS0c7R -pF44qRfNmCAR7RxN6oWTetGMCRLRztGkXjipF82YIBHtHE3qhZN60YwJEtHO0aReOKkXzZggEe0c -TeqFk3rRjAkS0c7RpF44qRfNmCAR7RxN6oWTetGMCRLRztGkXjipF82YIBHtHE3qhZN60YwJEtHO -0aReOKkXzZggEe0cTeqFk3rRjAkS0c7RpF44qRfNmCAR7RxN6oWTetGMCRLRztGkXjipF82YIJHA -dn77Zsbbtn/R1gSmngoPBaaeEl8xJkikeDu/e3/24fXPv1T6+Pr1h7P3n9r+nW9W8dRT4UXFU0+J -FxgTJFK0nd99/vLxlwZen71v+/e+OUVTT4WrFE09Ja5gTJBIuXZ+9/nnJq089uVr27/6DSmXeipc -o1zqKXE1Y4JESrXz19fX6eUrH8924lv8UqmnwrVKpZ4S1zEmSKRMO3/9du1m3pmGLpN6KrxCmdRT -4nrGBImUaOf3c8388fXkM7+9vrKyodsuQLgSqafCK5VIPSVexZggke3b+d34I37+cPbm6kM+LY/5 -T2++nn2pPNP7Ofu1WtunngqvsX3qKfFqxgSJbN3O74eXY335Ov0W4s34Iz8v/Ozb92fLW9kfk1+o -tXXqqfA6W6eeEq9hTJDItu08nOkf3s3+uzerPvLd16WOzn2Z1rapp8JrbZt6SryOMUEiW7bzh6p+ -/LrmIz992KV+3jL1VHi9LVNPidcyJkhku3au7ObpnK+99OrdfEN/zPyl/Xapp8INbJd6SryeMUEi -W7Xzh+pRM2nnFX/0zdye9c9tlyHQVqmnwk1slXpK3IAxQSLbtPPnmj84/sxvq/7w2y+z/XzWdh3i -bJN6KtzINqmnxE0YEySyRTt/qmva181m0OzXFx/z3oe6ReqpcDNbpJ4SN2JMkMgW7fy6bpaPHy17 -tuYDZvt53c/21xapp8LNbJF6StyIMUEim7fz6MLjn5dPvxq36My3F9/W/WxvbZ56KtzQ5qmnxM0Y -EySyeTu/ruvmT40/8e3MC0fSXp+1eeqpcEObp54SN2NMkMjG7fz28s9UPh/vTfMO/Tpt589rf7in -Nk49FW5q49RT4oaMCRLZuJ0vTtW+VT8LvckVyWPTC5M/tF2JKBunngo3tXHqKXFDxgSJbP7Vxad3 -Nf/FuJ2b3F3zdeOB1Rubf8Opwg1t/isqcTPGBImUe0ny0kc2OS17O/nrP7ZdiSjl3qU+ocLzAmai -EleWw5gggYB2/nadIT+9PqvtSkQJSD0VnheQeko8x5ggkYB2vtYHnqVv54DUU+HqehRMPSWeY0yQ -SPl2nlyb1eg5Cm/St3P51FPhBeVTT4nnGRMkUr6dP48+r9kNpZ/St3P51FPhBeVTT4nnGRMkUr6d -x1O+4TXG478+7fPUy6eeCtf8huVST4nnGRMkUr6dx5/Y8H7S4gOra8qnngrX/IblfkUlrq6HMUEC -5dt5/HkNnx00/vG0t5+WTz0VrvkNy81EJZ5nTJBI8XaefAPf8OfHP572UUPFU0+F637DYqmnxAuM -CRIp3s5frzeA3pU+h+yc4qmnwouKp54SLzAmSKR4O3+43ogfX5Kc95kLxVNPhRcVTz0lXmBMkEjx -dv75eh83Puf70nYhwhRPPRVeVDz1lHiBMUEipdt5/MS8pidl40z42nYhwpROPRVeUjr1lHiRMUEi -pdv5/TVPykZ//8dGT2jopdKpp8JLSqeeEtf8hsYEGZRu5/GMb3qt1eg1yYkvSC6deiq8pHTqKfEi -Y4JESrfz+Pv6d81+/M31fryPSqeeCi8pnXpKvMiYIJHC7Tz+vr7Z0/UmkZD5iQuFU0+FlxVOPSVe -YkyQSOF2fn/NAf+t5AlkNxVOPRVeVjj1lHiJMUEihdt5POLfN/vxrzvwdX3h1FPhZYVTT4mXGBMk -UridR9/XN70gefi3574yq3DqqfCywqmnxDW/ozFBCmXbefzgoIZnZaNN6tzP1iubeipcoWzqKfEy -Y4JEyrbz+BEKDW8m/bngCXpnlU09Fa5QNvWUeJkxQSJl2/nL6LOafRfxeSe+uCibeipcoWzqKfEy -Y4JEyrbz6GbSZk9ceDf86YYv2OqtsqmnwhXKpp4SLzMmSKRoO48vSG70zcXbn6/zLUd/FU09Fa5S -NPWUuIIxQSJF23n0+pBmX0Z8KLb+6baiqafCVYqmnhJXMCZIpGg7j24mbXRp1lnzH+23oqmnwlWK -pp4SVzAmSKRkO38afVKTe0+/7kw3l0w9Fa5UMvWUuIoxQSIl23k035vce7pDp3AlU0+FK5VMPSWu -YkyQSMl2/tZ4uH/YoR3qkqmnwpVKpp4SVzEmSKRgO49fB7L2GuPhZVkfGz6Er+8Kpp4KVyuYekpc -yZggkYLtPLo06+d1P/f+6gacn3flBpyCqafC1QqmnhJXMiZIpGA7j+49XfOFxNvhgxk+7MyjFgqm -ngpXK5h6SlzJmCCRcu08vvd0dZ+efdy1ry3KpZ4K1yiXekpczZggkXLtPHq43soLrr4Od7K/7NIZ -XLnUU+Ea5VJPiasZEyRSrJ3Hbw+p/x7+7dmwmb/t1iuRi6WeCtcplnpKXMOYoJeqT5zWtfO7ph9/ -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" /> +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 +UERGLTEuNVM2WsEAAAAASUVORK5CYII=" /> diff --git a/docs/src/man/img/homvector.svg b/docs/src/man/img/homvector.svg index d019e1a..d11f63e 100644 --- a/docs/src/man/img/homvector.svg +++ b/docs/src/man/img/homvector.svg @@ -3,340 +3,343 @@ +ADKIkQAAZBAjAQDI8P8DOz1DLXfjxq0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjYtMDItMTJUMTU6 +MzM6NDMrMDA6MDBNiE+jAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI2LTAyLTEyVDE1OjMzOjQzKzAw +OjAwPNX3HwAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNi0wMi0xMlQxNTozMzo0MyswMDowMGvA +1sAAAAAmdEVYdHBkZjpIaVJlc0JvdW5kaW5nQm94ADk0LjY1NXg1Ny44MDgrMCswzmLQjwAAABN0 +RVh0cGRmOlZlcnNpb24AUERGLTEuNVM2WsEAAAAASUVORK5CYII=" /> diff --git a/docs/src/man/img/pentagon_colored.svg b/docs/src/man/img/pentagon_colored.svg index 15b59e1..1d008a9 100644 --- a/docs/src/man/img/pentagon_colored.svg +++ b/docs/src/man/img/pentagon_colored.svg @@ -1,3478 +1,7977 @@ - + diff --git a/docs/src/man/img/qdim_fs_MF.svg b/docs/src/man/img/qdim_fs_MF.svg index 9ec6610..38d13b7 100644 --- a/docs/src/man/img/qdim_fs_MF.svg +++ b/docs/src/man/img/qdim_fs_MF.svg @@ -2,73 +2,46 @@ +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 +AABJRU5ErkJggg==" /> diff --git a/docs/src/man/multifusioncats.md b/docs/src/man/multifusioncats.md index 5cf5dec..c5d8122 100644 --- a/docs/src/man/multifusioncats.md +++ b/docs/src/man/multifusioncats.md @@ -208,7 +208,8 @@ By keeping track of the colorings and the directions of the arrows of the legs, ``` -where by $\mathbb{1}_j$ we mean the unit of $\mathcal{C}_j$. +where by $\mathbb{1}_k$ we mean the unit of $\mathcal{C}_k$. +Note how we keep the color subscripts for the dual object, but in reality they switch since the arrow direction is reversed. ### More on the topological data: gauge choices and distilling properties of the subcategories From 91be42541f830416d62dfe42d6397b3b6933b3aa Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Thu, 12 Feb 2026 18:24:39 +0100 Subject: [PATCH 205/206] more cleanup --- docs/src/man/implementation.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 69fb80c..2709307 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -105,7 +105,7 @@ H1 = @mpoham sum(-2 * h1{i,j} for (i, j) in nearest_neighbours(lattice)) H2 = @mpoham sum(h2{i,j} for (i, j) in nearest_neighbours(lattice)) H3 = @mpoham sum(2im * h3{i,j} for (i, j) in nearest_neighbours(lattice)) -H = H1 + J1 * H2 + J3 * H3 +H = H1 + J1 * H2 + J2 * H3 ```` For the matrix product state, we will select $\mathsf{Vec}$ as the module category for now: @@ -127,7 +127,7 @@ init_mps = FiniteMPS(L, P, V; left = Vb, right = Vb) We can now look to find the ground state of the Hamiltonian with two-site DMRG. We use this instead of the "usual" one-site DMRG because the two-site algorithm will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. ````julia -dmrg2alg = DMRG2(; verbosity = 2, tol = 1e-7, trscheme = truncbelow(1e-4)) +dmrg2alg = DMRG2(; verbosity = 2, tol = 1e-7, trscheme = trunctol(; atol = 1e-4)) ψ, _ = find_groundstate(init_mps, H, dmrg2alg) ```` The truncation scheme keyword argument is mandatory when calling `DMRG2` in MPSKit. @@ -137,10 +137,12 @@ To run one-site DMRG anyway, use `DMRG` which does not require a truncation sche Now that we've found the ground state, we can compute the entanglement spectrum in the middle of the chain. ````julia -spec = entanglement_spectrum(ψ, round(Int, L/2)) +entanglement_spectrum(ψ, round(Int, L/2)) ```` -This returns a dictionary which maps the objects grading the virtual space to the singular values. -In this case, there is one key corresponding to $\mathsf{Vec}$. +This returns a `TensorKit.SectorVector` containing the singular values. +This can be sliced to find the singular values corresponding to a particular simple object. +More information on that can be found in the docstring of `MPSKit.entanglement_spectrum`. +In this case, all singular values correspond to $\mathsf{Vec}$. We can also immediately return a plot of this data by the following: ````julia entanglementplot(ψ; site = round(Int, L/2)) @@ -172,12 +174,10 @@ This plot should be compared to [Lootens_2024; Figure 2](@cite). This can be repeated with other parameter values for $J_1$ and $J_2$ in the Hamiltonian to probe the $\mathsf{Rep(\mathbb{Z}_2 \times \mathbb{Z}_2)}$-symmetric or $\mathsf{Rep^\psi(A_4)}$ SPT phase. !!! note "Additional functions and keyword arguments" - Certain commonly used functions within MPSKit require extra keyword arguments to be compatible with multifusion MPS simulations. + Certain commonly used functions within MPSKit can pass extra keyword arguments compatible with multifusion MPS simulations. In particular, the keyword argument `sector` (note the lowercase "s") appears in - - `excitations` with `QuasiparticleAnsatz`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. - Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the charged excitations lie in the symmetry category $\mathcal{C} = \mathcal{D^*_M}$. - - `exact_diagonalization`: the `sector` keyword argument now requires an object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. - This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. + - `excitations` with `QuasiparticleAnsatz`: the sector is selected by adding an auxiliary space to the *domain* of each eigenvector of the transfer matrix. Since in a full contraction the domain of the eigenvector lies in the opposite side of the physical space (labeled by objects in $\mathcal{D} = \mathsf{Rep(A_4)}$), the excitations lie in the Morita dual category $\mathcal{E} = \mathcal{D^*_M}$. This will default to the unit of $\mathcal{E}$ if not specified. + - `exact_diagonalization`: the `sector` keyword argument now requires a simple object in $\mathcal{D}$, since this is the fusion category which specifies the bond algebra from which the Hamiltonian is constructed. This is equivalent to adding a charged leg on the leftmost (or rightmost) virtual space of the MPS in conventional MPS cases. This will default to the unit of $\mathcal{D}$ if not specified. ## Differences with the infinite case We can repeat the above calcalations also for an infinite system. @@ -197,4 +197,4 @@ It is also clear that boundary terms do not play a role in this case. These are - `transfer_spectrum`: similar to `excitations`, the (partial) transfer matrix spectrum is selected by adding a charged auxiliary space to the transfer matrix eigenvectors. - `correlation_length`: since this function calls `transfer_spectrum`, the same logic applies. - - `excitations` in the infinite case also requires the keyword argument. \ No newline at end of file + - `excitations` with `QuasiparticleAnsatz`. \ No newline at end of file From 6eec41416d411ed558ee922ba1b788b9c2238fc4 Mon Sep 17 00:00:00 2001 From: Boris De Vos Date: Fri, 13 Feb 2026 10:09:30 +0100 Subject: [PATCH 206/206] fix figure and other text --- .../man/img/A4_sym_entanglement_spectrum.svg | 1031 ++++++++--------- docs/src/man/implementation.md | 11 +- 2 files changed, 519 insertions(+), 523 deletions(-) diff --git a/docs/src/man/img/A4_sym_entanglement_spectrum.svg b/docs/src/man/img/A4_sym_entanglement_spectrum.svg index c7fcead..7f1de43 100644 --- a/docs/src/man/img/A4_sym_entanglement_spectrum.svg +++ b/docs/src/man/img/A4_sym_entanglement_spectrum.svg @@ -1,559 +1,554 @@ - + - + - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/man/implementation.md b/docs/src/man/implementation.md index 2709307..47c1381 100644 --- a/docs/src/man/implementation.md +++ b/docs/src/man/implementation.md @@ -5,7 +5,7 @@ In particular, we will be making a generalised anyonic spin chain. We will demonstrate how to reproduce the entanglement spectra found in [Lootens_2024](@cite). The model considered there is a spin-1 Heisenberg model with additional terms to break the usual $\mathsf{U_1}$ symmetry to $\mathsf{Rep(A_4)}$, while having a non-trivial phase diagram and relatively easy Hamiltonian to write down. -This will be done with the `A4Object = BimoduleSector{A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep(A_4)}$. +This will be done with the `A4Object = BimoduleSector{:A4}` `Sector`, which is the multifusion category which contains the structure of the module categories over $\mathsf{Rep(A_4)}$. Since there are 7 module categories, `A4Object` is a $r=7$ multifusion category. There are 3 fusion categories up to equivalence: - ``\mathsf{Vec_{A_4}}``: the category of $\mathsf{A_4}$-graded vector spaces. The group $\mathsf{A}_4$ is order $4!/2 = 12$ and has thus 12 simple objects. @@ -121,17 +121,18 @@ init_mps = FiniteMPS(L, P, V; left = Vb, right = Vb) ```` !!! warning "Important" - We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place a trivial space of the `Sector`, which does not exist for any `BimoduleSector` due to the semisimple unit. + We must pass on a left and right virtual space to the keyword arguments `left` and `right` of the `FiniteMPS` constructor, since these would by default try to place the unit space of the `Sector`, which for any `BimoduleSector` consists of the semisimple unit. As of now, this will error at the level of the N-symbol call as the colors of the various components do not all match. ## Two-site DMRG and the entanglement spectrum We can now look to find the ground state of the Hamiltonian with two-site DMRG. We use this instead of the "usual" one-site DMRG because the two-site algorithm will smartly fill up the blocks of the local tensor during the sweep, allowing one to initialise as a product state in one block and more likely avoid local minima, a common occurence in symmetric tensor network simulations. ````julia -dmrg2alg = DMRG2(; verbosity = 2, tol = 1e-7, trscheme = trunctol(; atol = 1e-4)) +dmrg2alg = DMRG2(; verbosity = 2, tol = 1e-7, trscheme = trunctol(; atol = 1e-4 / sqrt(dim(M)))) ψ, _ = find_groundstate(init_mps, H, dmrg2alg) ```` The truncation scheme keyword argument is mandatory when calling `DMRG2` in MPSKit. Here, we choose to truncate such that all singular values are larger than $10^{-4}$, while setting the default tolerance for convergence to $10^{-7}$. +The extra factor is required to cancel the normalisation of the singular values by the quantum dimensions. More information on this can be found in the [MPSKit](https://github.com/QuantumKitHub/MPSKit.jl) documentation. To run one-site DMRG anyway, use `DMRG` which does not require a truncation scheme. @@ -162,7 +163,7 @@ module_numlabels(i) = MultiTensorKit._numlabels(A4Object, i, 6) V = Vect[A4Object]((i, 6, label) => D for label in 1:module_numlabels(i)) Vb = Vect[A4Object](first(sectors(V)) => 1) # not all charges on boundary, play around with what is there ```` -#TODO: fix the figure + ```@raw html ``` @@ -171,7 +172,7 @@ The plot shows the entanglement spectra of the various dual models in the middle Every subtitle also mentions the memory required to store the same middle ground state tensor. This plot should be compared to [Lootens_2024; Figure 2](@cite). -This can be repeated with other parameter values for $J_1$ and $J_2$ in the Hamiltonian to probe the $\mathsf{Rep(\mathbb{Z}_2 \times \mathbb{Z}_2)}$-symmetric or $\mathsf{Rep^\psi(A_4)}$ SPT phase. +This can be repeated with other parameter values for $J_1$ and $J_2$ in the Hamiltonian to probe the $\mathbb{Z}_2 \times \mathbb{Z}_2$-symmetric or $A_4$ SPT phase. !!! note "Additional functions and keyword arguments" Certain commonly used functions within MPSKit can pass extra keyword arguments compatible with multifusion MPS simulations.