Skip to content
Draft
Show file tree
Hide file tree
Changes from 77 commits
Commits
Show all changes
151 commits
Select commit Hold shift + click to select a range
5473e0f
define leftone and rightone of BimoduleSector
borisdevos Feb 24, 2025
85541aa
make left/rightone a new method of TensorKitSectors left/rightone
borisdevos Feb 24, 2025
cf06437
define leftone and rightone of BimoduleSector
borisdevos Feb 24, 2025
4390d8d
make left/rightone a new method of TensorKitSectors left/rightone
borisdevos Feb 24, 2025
09acafc
add tests
borisdevos Mar 10, 2025
6cb34fa
test reading data from txt
borisdevos Mar 10, 2025
5c5effd
Merge branch 'boris-multitensorkit' of https://github.com/QuantumKitH…
borisdevos Mar 10, 2025
a45be26
rewrite extract_Fsymbol to read txt info
borisdevos Mar 11, 2025
eaa05c9
tests to run locally for my smooth brain
borisdevos Mar 11, 2025
599b74e
start on adding missing elements of extract_Fsymbol
borisdevos Mar 14, 2025
b9b0994
change extract_dual to get duals of module cats as well
borisdevos Mar 14, 2025
2683ad1
update one, leftone, rightone, conj functions with new extract_dual
borisdevos Mar 14, 2025
c425551
add test to check units and duals
borisdevos Mar 14, 2025
87c11b3
remove TODO about duals for modules
borisdevos Mar 14, 2025
66e6ef2
add missing elements of extract_Fsymbol
borisdevos Mar 14, 2025
adcc5fe
change Fcache definition
borisdevos Mar 14, 2025
10ee1b6
fix extract_Fsymbol to output something useful
borisdevos Mar 14, 2025
6236465
go back to correct definition Fcache
borisdevos Mar 14, 2025
d366a40
Revert "go back to correct definition Fcache"
borisdevos Mar 14, 2025
383218b
output correct dictionary in extract_Fsymbol
borisdevos Mar 14, 2025
54b64cd
fix Fcache to new output extract_Fsymbol
borisdevos Mar 14, 2025
16e683b
add sectorscalartype
borisdevos Mar 14, 2025
f8d45c3
have a functioning Fsymbol
borisdevos Mar 14, 2025
c0caddf
add bounds to what A4Object can be defined as
borisdevos Mar 17, 2025
df9eb3e
remove JSON3 dependency
borisdevos Mar 17, 2025
7743a00
more local tests
borisdevos Mar 17, 2025
07dfc6c
actually remove all JSON3 deps
borisdevos Mar 17, 2025
71f6916
Revert "actually remove all JSON3 deps"
borisdevos Mar 17, 2025
1f37a92
Revert "remove JSON3 dependency"
borisdevos Mar 17, 2025
c50f31a
remove Fsymbol code that was JSON dependent
borisdevos Mar 17, 2025
0d50452
add TensorKit dependency
borisdevos Mar 17, 2025
013c3d8
define length of SectorValues of A4Object + typo in Base.iterate of S…
borisdevos Mar 17, 2025
fb74131
export TensorKit hasblock
borisdevos Mar 24, 2025
9250470
custom TensorKit.blocksectors
borisdevos Mar 24, 2025
0c7d618
start of TensorKit tests
borisdevos Mar 24, 2025
a6c9aaf
some tests for bram
borisdevos Mar 25, 2025
471ce1e
update localtests
borisdevos Mar 25, 2025
b1afb01
add custom `scalar` for `TensorMap`s of `A4Object`
borisdevos Mar 27, 2025
0cb5b18
comments and changes in tests
borisdevos Mar 27, 2025
303876e
start of MPSKit tests
borisdevos Mar 27, 2025
5c1330e
quick fix to Fsymbol to return 0 when expected to be 0
borisdevos Apr 7, 2025
a77b77d
get blocksectors working
borisdevos Apr 8, 2025
5809f77
add BlockTensorKit dependency
borisdevos Apr 8, 2025
3661102
many many (temporary) dependencies
borisdevos Apr 8, 2025
4e2c0d5
edit Fsymbol to return correctly shaped zero arrays
borisdevos Apr 9, 2025
c1255d6
temporary BenchmarkTools dep
borisdevos Apr 9, 2025
75ec5c0
more tinkering
borisdevos Apr 9, 2025
50c4614
tests done for QPA infinite
borisdevos Apr 9, 2025
afb8272
add custom `dim` of `GradedSpace` for `A4Object` to return floats as …
borisdevos Apr 9, 2025
def64ea
define `oneunit` of `A4Object`-graded vector spaces where possible
borisdevos Apr 9, 2025
c686b9b
finite tests
borisdevos Apr 10, 2025
50a14d6
remove unnecessary check in specialised blocksectors
borisdevos Apr 10, 2025
86525d2
clean up dim and oneunit to accept `GradedSpace{<:BimoduleSector}`
borisdevos Apr 10, 2025
fedb1e4
clean up `oneunit` of `SumSpace` to accept `SumSpace{<:GradedSpace{<:…
borisdevos Apr 10, 2025
d5862b6
Fix `dim`
lkdvos Apr 10, 2025
722ea95
performance improvements
lkdvos Apr 10, 2025
d5b3006
fix `convert_Fs` to not contain elaborate (useless) identity function
borisdevos Apr 11, 2025
76df51b
`FiniteExcited` and `changebonds` tests
borisdevos Apr 11, 2025
b5155bf
time evolution test + `(In)FiniteMPOHamiltonian` constructor w/o `Loc…
borisdevos Apr 11, 2025
2e64e63
add custom `insertleftunit` and `insertrightunit` to evaluate a valid…
borisdevos Apr 17, 2025
0f6d4d2
Merge branch 'boris-multitensorkit' of https://github.com/QuantumKitH…
lkdvos Apr 22, 2025
52063d9
replace `map` with `for` loop
lkdvos Apr 22, 2025
a700577
Test all pentagons
lkdvos Apr 22, 2025
ed8019d
more local tests
borisdevos Apr 23, 2025
0b3d668
update `artifact_path`
borisdevos Apr 23, 2025
3cce841
Merge branch 'main' of https://github.com/QuantumKitHub/MultiTensorKi…
borisdevos Apr 23, 2025
0995d18
add file to test caching
borisdevos May 14, 2025
287bb39
add TensorKit tests
borisdevos May 14, 2025
f96812f
debugging fun + progress
borisdevos Jun 4, 2025
87e7502
remove commented code
borisdevos Jun 4, 2025
c584a89
change `IteratorSize` to actually evaluate `SizeUnknown`
borisdevos Jun 9, 2025
55c8708
change `blocksectors` definition to be flexible with `GradedSpace` type
borisdevos Jun 9, 2025
480d944
remove debug elements + clean up error messages
borisdevos Jun 10, 2025
96962c0
clean up A4 tests
borisdevos Jun 13, 2025
d5c6b32
clean up deps and add compat
borisdevos Jun 13, 2025
564c026
delete local test files
borisdevos Jun 13, 2025
24e0f4b
format
borisdevos Jun 13, 2025
d161568
apply some suggested changes
borisdevos Jun 16, 2025
801a774
TupleTools changes
borisdevos Jun 16, 2025
aaeb4c3
change `insertleft/rightunit` to evaluate `left/rightoneunit`s
borisdevos Jun 18, 2025
e08a712
add tests for left and right units
borisdevos Jun 18, 2025
213e23e
one more suggested change
borisdevos Jun 18, 2025
a70b569
Merge branch 'main' of https://github.com/QuantumKitHub/MultiTensorKi…
borisdevos Jun 26, 2025
a549943
update code to account for new N- and F-symbols
borisdevos Jun 26, 2025
2bbc946
expand on unitarity check explicitly + make less specific to A4
borisdevos Jun 30, 2025
cc824ab
update `Fsymbol`
borisdevos Jun 30, 2025
94eb6d1
remove JSON dependency
borisdevos Jun 30, 2025
5bd5c12
add pure module F-move unitarity check + clean up tests
borisdevos Jul 1, 2025
bb6eee3
adapt `TensorKit.scalar`
lkdvos Jul 16, 2025
71682dc
Simplify by fixing `collect`
lkdvos Jul 16, 2025
4b1b23a
Merge branch 'main' of https://github.com/QuantumKitHub/MultiTensorKi…
borisdevos Jul 17, 2025
8afa784
Merge https://github.com/QuantumKitHub/MultiTensorKit.jl into boris-m…
borisdevos Jul 18, 2025
ee71ed8
add the other unitarity tests
borisdevos Jul 22, 2025
4b067e5
fix test
borisdevos Jul 22, 2025
42de755
add compats to Project.toml
borisdevos Jul 22, 2025
a86643b
remove diagonal checks in `left/rightoneunit`
borisdevos Jul 24, 2025
847c762
pretty print `BimoduleSector`
borisdevos Jul 24, 2025
c22b215
fix `blocksectors` to not use `isone`
borisdevos Aug 7, 2025
6b528c9
introduce `rounddim` for prettiness
borisdevos Aug 7, 2025
db4b577
introduce test setup file
borisdevos Aug 8, 2025
3ffaee5
refactor unitarity tests
borisdevos Aug 8, 2025
5967817
acronym MTK
borisdevos Aug 8, 2025
547c262
add `one` for type bimodulesector
borisdevos Aug 8, 2025
94292f2
change error thrown for module one evaluation + format
borisdevos Aug 8, 2025
662efd8
finish up sector tests
borisdevos Aug 8, 2025
f6b6a59
start on multifusion space tests
borisdevos Aug 8, 2025
a2f1ec1
custom `zero` of `GradedSpace` and `fuse`
borisdevos Aug 8, 2025
04bac3d
specify TensorKit module for `SectorDict`
borisdevos Aug 11, 2025
4870e09
potential overkill fusion tree stuff
borisdevos Aug 11, 2025
16104fc
finish fusion tree tests (not debugged) + move around imports
borisdevos Aug 12, 2025
3a1cf23
remove debug elements
borisdevos Aug 12, 2025
6ed0960
add diagonal tensor tests
borisdevos Aug 12, 2025
679f6cf
start of tensor tests (modules untested)
borisdevos Aug 12, 2025
38001e1
almost finish up tensor tests
borisdevos Aug 12, 2025
b4b838e
specify modules for some functions
borisdevos Aug 13, 2025
a7d13b3
don't use rounddim because it's messy with SVD with truncdim
borisdevos Aug 13, 2025
dca4611
shorten tensor tests, fix and/or identify bugs
borisdevos Aug 13, 2025
d274967
remove export `left/rightoneunit`
borisdevos Aug 13, 2025
0b4f890
`isone` for `BimoduleSector`s
borisdevos Aug 14, 2025
ffbd4e0
make `isone` great again in `blocksectors`
borisdevos Aug 14, 2025
000a976
test for `isone`
borisdevos Aug 14, 2025
9f953d6
tensorkitsectors advanced compat
borisdevos Aug 18, 2025
0be6bad
custom spaces for factorization tests for more compatible block sizes
borisdevos Aug 22, 2025
a1cc53c
round dim of space that's supposed to be integer
borisdevos Aug 22, 2025
67cc8c8
small refactor of diagonal check
borisdevos Aug 22, 2025
6e3fca5
remove limited rightorth after new spaces
borisdevos Aug 22, 2025
5bd32a2
generalise `Base.iterate`
borisdevos Aug 22, 2025
b4c79c0
correct the `BimoduleSector` inner constructor
borisdevos Aug 22, 2025
ff01886
generalise `A4Object` to `BimoduleSector` where possible
borisdevos Aug 22, 2025
b27446d
add Random to Project.toml for tests
borisdevos Sep 1, 2025
fbc166e
remove `left/rightoneunit` coming from TensorKit (temporary)
borisdevos Sep 24, 2025
0719edc
update compats
borisdevos Sep 24, 2025
8fda727
update compat for TensorKit v0.15
borisdevos Nov 5, 2025
9e718a2
renamings from TensorKit v0.15 + incoming renamings
borisdevos Nov 5, 2025
ff6af7b
add `allunits`, fix `dual`, revert `insertleft/rightunitspace`
borisdevos Nov 5, 2025
45e9074
add LinearAlgebra for tests
borisdevos Nov 21, 2025
2ebd2bb
bump TK version
borisdevos Dec 22, 2025
557c894
remove BlockTensorKit dep
borisdevos Dec 22, 2025
f181136
remove compiling BTK
borisdevos Dec 22, 2025
faacc54
remove TK interface (mostly)
borisdevos Dec 22, 2025
c2ee53f
tinker with deps and compat
borisdevos Dec 23, 2025
4f19775
more tinkering
borisdevos Dec 23, 2025
354cb96
update tests
borisdevos Dec 23, 2025
0048ec0
get setup included correctly
borisdevos Dec 23, 2025
15df330
small fix
borisdevos Dec 23, 2025
ad628dc
abstractvector dispatch
borisdevos Dec 23, 2025
8e37a8b
format test
borisdevos Dec 23, 2025
46e4514
comment out TK tests
borisdevos Dec 23, 2025
8737431
format src
borisdevos Dec 23, 2025
11aa368
basic properties edit
borisdevos Dec 23, 2025
e5d99a5
remove `Asymbol` test for modules
borisdevos Dec 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ 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"
TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec"
TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f"
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"
TensorKitSectors = "0.1.4"
Test = "1.10"
TestExtras = "0.3"
julia = "1.10"
Expand Down
10 changes: 10 additions & 0 deletions src/MultiTensorKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,19 @@ module MultiTensorKit
export BimoduleSector, A4Object

using JSON3
using DelimitedFiles
using Artifacts
using TensorKitSectors

using TupleTools
import TupleTools: insertafter

using BlockTensorKit
import BlockTensorKit: SumSpace

using TensorKit
import TensorKit: hasblock, dim

include("bimodulesector.jl")

end
247 changes: 191 additions & 56 deletions src/bimodulesector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ struct BimoduleSector{Name} <: Sector
i::Int
j::Int
label::Int
function BimoduleSector{:A4}(i::Int, j::Int, label::Int)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels a bit strange to have this as an inner constructor, dedicated to the A4 type. Would it not be equally sensible to have this outside of the struct definition?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want BimoduleSector{:A4} to be its own struct then? I need the new function to actually create the objects, no?

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...)
const A4Object = BimoduleSector{:A4}
Expand All @@ -16,23 +21,27 @@ 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?
# TODO: numlabels?
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
A4Object(i, j, label), (I, label + 1)
end
end

function Base.length(::SectorValues{A4Object})
return sum(_numlabels(A4Object, i, j) for i in 1:12, j in 1:12)
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
Expand All @@ -42,8 +51,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
Expand Down Expand Up @@ -82,8 +91,7 @@ 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},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
Expand All @@ -95,74 +103,122 @@ 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))

# 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
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

# 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
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
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]))
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
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the long term, I would still really prefer to have one always correspond to the label=1, either by relabeling the data when we read them in, or (better), storing the data in that form.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. At the level of the data seems better so it's a one-time thing. I will think of a way to do this for another time.

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])
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

function TensorKitSectors.leftone(a::BimoduleSector)
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))[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})
return mapreduce((x, y) -> cat(x, y; dims=1), 1:12) do i
filename = joinpath(artifact_path, "A4", "Fsymbol_$i.json")
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"
json_string = read(filename, String)
Farray_part = copy(JSON3.read(json_string))
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)], ", "))
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)))
map!(result, reshape(v, size(result))) do cmplxdict
return complex(cmplxdict[:re], cmplxdict[:im])
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

y[(a, b, c, d, e, f)] = result
end
end
end
return result
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)
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)
end
return data_dict
end

const Fcache = IdDict{Type{<:BimoduleSector},
Array{Dict{NTuple{6,Int},Array{ComplexF64,4}},4}}()
Dict{NTuple{4,Int64},Dict{NTuple{6,Int64},Array{ComplexF64,4}}}}()

function _get_Fcache(::Type{T}) where {T<:BimoduleSector}
global Fcache
Expand All @@ -173,16 +229,95 @@ 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
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
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, j, k, l]
return colordict[(a.label, b.label, c.label, d.label, e.label, f.label)]
end

# interface with TensorKit where necessary
#-----------------------------------------

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{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₁ # keep intersection
return filter!(c -> hasblock(codom, c), collect(blocksectors(dom)))
else
return filter!(c -> hasblock(dom, c), collect(blocksectors(codom)))
end
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))
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)) ||
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{<: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

# 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 $P")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a bit fishy, I think the whole point of insertrightunit is to have the ability to construct a space through rightone, ie avoiding oneunit altogether since this might not be defined. In some sense, I would almost expect a rightoneunit or something like that to appear here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defining a rightoneunit at the level of the GradedSpace is easy enough. I have the following in mind:

function rightoneunit(S::GradedSpace{<:BimoduleSector})
    allequal(a.j for a in sectors(S)) ||
        throw(ArgumentError("sectors of $S do not have the same rightone"))

    sector = rightone(first(sectors(S)))
    return spacetype(S)(sector => 1)
end

This works perfectly fine for a space like rsp = Vect[A4Object](A4Object(1,1,1)=>1, A4Object(2,1,1)=>1), returning Vect[A4Object](A4Object(1,1,4)=>1) (again, unfortunately the label=1 isn't the unit, but 4 in this particular case). Replacing oneunit with rightoneunit within insertrightunit for P = rsp ← rsp then returns rsp ← (rsp ⊗ Vect[A4Object](A4Object(1, 1, 4)=>1)) as expected.

However, at the level of a TensorMap, this errors at Nsymbol because it wants to build a fusion tree with a=A4Object(1,1,1), b=A4Object(1,1,4), c = A4Object(2,1,1). Since I don't see any purpose for something like rightoneunit other than precisely cases like this where there are fusion and module sectors mixed in the GradedSpace, I'm wondering if such a definition is useful. Of course, definitions like this and leftoneunit could be used within oneunit to check extremely rigorously that you're considering a fusion sector.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, your initial rsp is already ill-defined right, you want to always have i and j be the same throughout a single ElementarySpace anyways to have something that makes sense. (Otherwise you'd have a direct sum of things with different colorings, which I don't think we want to support).

In that sense, if rsp = Vect[A4Object]((2, 1, 1) => 1, (2, 1, 2) => 1), you'd get the space you say, and I think the Nsymbols now have to work out. The idea being that inserting a unit boils down to inserting a trivial leg in the region of a given color, which doesn't alter the color, so should work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I misunderstood what you precisely wanted to accomplish with a rightoneunit. It does seem somewhat redundant though, since for i=j the right unit and the unit coincide (a check that's done within oneunit). The only upside I see is that it is more informative in terms of errors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont mean i and j have to be equal to eachother, I mean that all i have to be the same, and separately all j have to be the same

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 $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
Loading
Loading