Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
fb4693f
add todo for function split
borisdevos Mar 17, 2025
13bcf82
add comment for possible change in function merge
borisdevos Mar 17, 2025
09467c6
change one to leftone in bendright
borisdevos Mar 17, 2025
2878e08
change one to leftone in foldright
borisdevos Mar 17, 2025
10744b2
change one to f.coupled in elementary_trace
borisdevos Mar 17, 2025
1ed1ed1
progress on correct units in trace
borisdevos Mar 25, 2025
c31b99c
change dim of GradedSpace to not evaluate one
borisdevos Mar 25, 2025
a33d028
use a function that's actually exported in dimension of `GradedSpace`
borisdevos Mar 26, 2025
0e3c5df
update TensorOperations scalartype determination
lkdvos Apr 10, 2025
124def4
Merge pull request #1 from lkdvos/fork
borisdevos Apr 11, 2025
9635362
Revert "use a function that's actually exported in dimension of `Grad…
borisdevos Apr 14, 2025
4bc1e7c
Revert "change dim of GradedSpace to not evaluate one"
borisdevos Apr 14, 2025
24be2ea
irrelevant typos, but must be corrected
borisdevos Apr 16, 2025
13af986
another minor typo
borisdevos Apr 16, 2025
095dcda
minor typos
borisdevos May 6, 2025
fbfb564
then vs than is hard
borisdevos May 6, 2025
d7cae4f
remove debug elements
borisdevos May 7, 2025
a14fc70
Merge branch 'master' of https://github.com/Jutho/TensorKit.jl into b…
borisdevos May 7, 2025
4fe82f9
change TensorOperations scalartype promotion to base off field of num…
borisdevos May 8, 2025
55a00c0
typo in docs
borisdevos Jun 13, 2025
0113f73
remove some debug comments
borisdevos Jun 13, 2025
8e8b760
more rigorous check in `merge`
borisdevos Jun 18, 2025
78b135e
replace `one` evaluation in `split` with `leftone`
borisdevos Jun 18, 2025
440b42b
typos in docs
borisdevos Jun 18, 2025
00825af
typo in `_fusiontree_iterate`
borisdevos Jun 18, 2025
aad8fc8
apply suggestions related to tensor types
borisdevos Jul 4, 2025
c0ef01e
remove excess variable
borisdevos Jul 4, 2025
c189284
apply `split` suggestion
borisdevos Jul 4, 2025
bdbd2e6
format
borisdevos Jul 7, 2025
e23e092
change units in `elementary_trace`
borisdevos Jul 15, 2025
06671f3
import IsingBimod + remove dupe exports
borisdevos Jul 16, 2025
a18f73d
add first requirements for `IsingBimod`-graded vector spaces
borisdevos Jul 16, 2025
979036a
Merge branch 'master' of https://github.com/Jutho/TensorKit.jl into b…
borisdevos Jul 17, 2025
279a15f
fix variable expression to not be variable because it's not variable
borisdevos Jul 17, 2025
83d73ce
Merge branch 'master' of https://github.com/Jutho/TensorKit.jl into b…
borisdevos Jul 18, 2025
d7fb9f4
add `dim` for `Vect[IsingBimod]` + typos in fields
borisdevos Jul 18, 2025
9521574
start of multifusion tests
borisdevos Jul 18, 2025
19ba225
finish up multifusion space tests
borisdevos Jul 23, 2025
5fef11e
remove equal sectors check in `left/rightoneunit`
borisdevos Jul 23, 2025
2d9663b
add `left/rightoneunit` for any `GradedSpace`
borisdevos Jul 24, 2025
0061588
start on `DiagonalTensor` tests
borisdevos Jul 25, 2025
abb6301
start of fusion tree tests
borisdevos Jul 25, 2025
64982d6
custom `FusionTree` constructor for only uncoupled provided
borisdevos Jul 25, 2025
520f81d
finish fusion tree and `DiagonalTensor` tests
borisdevos Jul 30, 2025
60bc1fc
minor changes
borisdevos Jul 30, 2025
490aa4f
export `left/rightoneunit`
borisdevos Jul 30, 2025
8ab417d
make `artin_braid` excessively multifusion-compatible
borisdevos Jul 30, 2025
6348815
add `zero` and `fusiontrees` constructor for `IsingBimod`
borisdevos Jul 30, 2025
2a7d871
start of `HomSpace` tests
borisdevos Jul 30, 2025
a6bf085
start of tensor tests
borisdevos Jul 30, 2025
159143e
remove todo
borisdevos Jul 30, 2025
42fd12b
remove version check
borisdevos Jul 30, 2025
5393d87
remove tests that will inherently fail + comments on future changes
borisdevos Jul 31, 2025
5898bc0
rewrite tensor factorisation tests to not use `permute`
borisdevos Jul 31, 2025
6351cf0
rewrite tensor product test via contraction to not permute + be planar
borisdevos Jul 31, 2025
2d107a5
rewrite partial and full trace tests to not use `permute` and friends
borisdevos Jul 31, 2025
1d3c170
give all objects of `IsingBimod` a name + attempt at non-diagonal spaces
borisdevos Jul 31, 2025
bae646a
add off-diagonal spaces + make (most) tests compatible with off-diago…
borisdevos Aug 4, 2025
99b8d1c
change `blocksectors` to not evaluate `isone` (see comment!)
borisdevos Aug 4, 2025
a8e8b81
import `leftone` and `rightone` to tests + remove `pentagon/hexagon_e…
borisdevos Aug 4, 2025
45ff559
respecify TensorKit method for factorisation algorithms in multifusion
borisdevos Aug 4, 2025
260ef92
rewrite trace and factorisation tests to not use permute + assert sym…
borisdevos Aug 4, 2025
cd8e37b
format with v1
borisdevos Aug 4, 2025
772452f
add TensorKitSectors to extras for tests
borisdevos Aug 4, 2025
fd55983
define `left/rightoneunit` correctly
borisdevos Aug 4, 2025
04d6162
remove some comments
borisdevos Aug 4, 2025
5d34b60
fix docstring
borisdevos Aug 4, 2025
d25510a
actually include the multifusion tests
borisdevos Aug 4, 2025
a3857da
fix fermion parity full trace test
borisdevos Aug 4, 2025
de2bcae
fix quote escape in @constinferred + move misplaced tensormaps
borisdevos Aug 4, 2025
3ea5293
uncomment tests
borisdevos Aug 6, 2025
6c20fc6
add custom `scalar` to deal with semisimple unit
borisdevos Aug 7, 2025
3dd1257
move around include file ordering
borisdevos Aug 7, 2025
69e7423
remove debug elements
borisdevos Aug 7, 2025
ae10a73
remove fixme
borisdevos Aug 7, 2025
7f01306
add `left/rightoneunit` test for other `Sector`s
borisdevos Aug 7, 2025
8d2e94f
typo
borisdevos Aug 12, 2025
6501e5f
otimes between tensor maps change to account for `sectorscalartype`
borisdevos Aug 13, 2025
07bcc51
export `left/rightone`
borisdevos Aug 26, 2025
52fa8d4
redefine `left/rightoneunit` for the usual `GradedSpace`s
borisdevos Aug 26, 2025
41013ec
add `left/rightoneunit` test on empty space
borisdevos Aug 26, 2025
c71b15c
add check to `left/rightoneunit` of `IsingBimod` spaces when empty
borisdevos Aug 26, 2025
ddc1612
return vector in `IsingBimod` `blocksectors`
borisdevos Aug 26, 2025
17f1e1b
use `isone` again in `blocksectors`
borisdevos Aug 26, 2025
e8f6a76
use `isone` again in `artin_braid`
borisdevos Aug 26, 2025
df0115e
Revert "add TensorKitSectors to extras for tests"
borisdevos Aug 26, 2025
ac56fae
remove import TKS to tests + use `isone` again
borisdevos Aug 26, 2025
599cabd
Merge branch 'master' of https://github.com/Jutho/TensorKit.jl into b…
borisdevos Aug 26, 2025
0612656
fix argument errors in tests + tests for empty space
borisdevos Aug 26, 2025
698d652
renaming to `IsingBimodule`
borisdevos Aug 26, 2025
9b5ba0b
format
borisdevos Aug 26, 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
10 changes: 7 additions & 3 deletions src/TensorKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export BraidingStyle, SymmetricBraiding, Bosonic, Fermionic, Anyonic, NoBraiding
export Trivial, Z2Irrep, Z3Irrep, Z4Irrep, ZNIrrep, U1Irrep, SU2Irrep, CU1Irrep
export ProductSector
export FermionParity, FermionNumber, FermionSpin
export FibonacciAnyon, IsingAnyon
export FibonacciAnyon, IsingAnyon, IsingBimodule
export leftone, rightone

export VectorSpace, Field, ElementarySpace # abstract vector spaces
export InnerProductStyle, NoInnerProduct, HasInnerProduct, EuclideanInnerProduct
Expand All @@ -32,7 +33,7 @@ export SpaceMismatch, SectorMismatch, IndexError # error types

# general vector space methods
export space, field, dual, dim, reduceddim, dims, fuse, flip, isdual, oplus,
insertleftunit, insertrightunit, removeunit
leftoneunit, rightoneunit, insertleftunit, insertrightunit, removeunit

# partial order for vector spaces
export infimum, supremum, isisomorphic, ismonomorphic, isepimorphic
Expand All @@ -41,7 +42,6 @@ export infimum, supremum, isisomorphic, ismonomorphic, isepimorphic
export sectortype, sectors, hassector, Nsymbol, Fsymbol, Rsymbol, Bsymbol,
frobeniusschur, twist, otimes, sectorscalartype
export fusiontrees, braid, permute, transpose
export ZNSpace, SU2Irrep, U1Irrep, CU1Irrep
# other fusion tree manipulations, should not be exported:
# export insertat, split, merge, repartition, artin_braid,
# bendleft, bendright, foldleft, foldright, cycleclockwise, cycleanticlockwise
Expand Down Expand Up @@ -229,6 +229,10 @@ include("planar/planaroperations.jl")
# deprecations: to be removed in version 1.0 or sooner
include("auxiliary/deprecate.jl")

# Additional methods for IsingBimodule Sector
# ----------------------------------------
include("spaces/multifusionspace.jl")

# Extensions
# ----------
function __init__()
Expand Down
6 changes: 3 additions & 3 deletions src/fusiontrees/manipulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -786,13 +786,13 @@ function elementary_trace(f::FusionTree{I,N}, i) where {I<:Sector,N}
vertices_ = TupleTools.front(f.vertices)
f_ = FusionTree(uncoupled_, coupled_, isdual_, inner_, vertices_)
fs = FusionTree((b,), b, (!f.isdual[1],), (), ())
for (f_′, coeff) in merge(fs, f_, unit, 1) # coloring gets reversed here, should be the other unit
for (f_′, coeff) in merge(fs, f_, unit, 1)
f_′.innerlines[1] == unit || continue
uncoupled′ = Base.tail(Base.tail(f_′.uncoupled))
isdual′ = Base.tail(Base.tail(f_′.isdual))
inner′ = N <= 4 ? () : Base.tail(Base.tail(f_′.innerlines))
vertices′ = N <= 3 ? () : Base.tail(Base.tail(f_′.vertices))
f′ = FusionTree(uncoupled′, unit, isdual′, inner′, vertices′) # and this one?
f′ = FusionTree(uncoupled′, unit, isdual′, inner′, vertices′)
coeff *= sqrtdim(b)
if !(f.isdual[N])
coeff *= conj(frobeniusschur(b))
Expand Down Expand Up @@ -835,7 +835,7 @@ function artin_braid(f::FusionTree{I,N}, i; inv::Bool=false) where {I<:Sector,N}
vertices = f.vertices
oneT = one(sectorscalartype(I))

if isone(uncoupled[i]) || isone(uncoupled[i + 1])
if isone(a) || isone(b)
# braiding with trivial sector: simple and always possible
inner′ = inner
vertices′ = vertices
Expand Down
17 changes: 17 additions & 0 deletions src/spaces/gradedspace.jl
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,23 @@ function Base.axes(V::GradedSpace{I}, c::I) where {I<:Sector}
end

Base.oneunit(S::Type{<:GradedSpace{I}}) where {I<:Sector} = S(one(I) => 1)

"""
leftoneunit(S::GradedSpace{I}) where {I<:Sector} -> GradedSpace{I}

Return the corresponding vector space of type `GradedSpace{I}` that represents the trivial
one-dimensional space consisting of the left unit of the objects in `Sector` `I`.
"""
leftoneunit(S::GradedSpace{I}) where {I<:Sector} = oneunit(typeof(S))
Copy link
Member

Choose a reason for hiding this comment

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

What was wrong with the previous implementations? This looks like it will always fail for multifusion things

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 wanted left/rightoneunit to also work on empty spaces, because oneunit does so. This will indeed fail for multifusion things, hence the specialisation.

Copy link
Member

Choose a reason for hiding this comment

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

I see, but what do you think about this then:

function leftoneunit(V::GradedSpace{I}) where {I<:Sector}
    s = sectors(V)
    u = leftoneunit(isempty(s) ? I : first(s))
    return spacetype(V)(u => 1)
end


"""
rightoneunit(S::GradedSpace{I}) where {I<:Sector} -> GradedSpace{I}

Return the corresponding vector space of type `GradedSpace{I}` that represents the trivial
one-dimensional space consisting of the right unit of the objects in `Sector` `I`.
"""
rightoneunit(S::GradedSpace{I}) where {I<:Sector} = oneunit(typeof(S))

Base.zero(S::Type{<:GradedSpace{I}}) where {I<:Sector} = S(one(I) => 0)

# TODO: the following methods can probably be implemented more efficiently for
Expand Down
111 changes: 111 additions & 0 deletions src/spaces/multifusionspace.jl
Copy link
Member

Choose a reason for hiding this comment

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

It's not great if we have to specialize everything specifically for Vect[IsingBimodule], since this would mean we have to redo all that work for any multifusion category. In that sense, we would either need a fusion type that specifies this, such that we can specialize properly, or write these methods in a generic way that works for everything

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'm not sure what you mean by redoing all that work. IsingBimodule should be the only multifusion category tested within TensorKit itself. This infrastructure already exists in MultiTensorKit (albeit in a PR for now), which will support all the other multifusion categories.

Copy link
Member

Choose a reason for hiding this comment

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

What I mean is that if all we are testing is the specializations that are written solely for IsingBimodule, which is used mainly for testing, this doesn't actually help all that much, since it would have to be both reimplemented and retested for other multifusion categories as well

Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# additional interface to deal with IsingBimodule Sector
#------------------------------------------------------------------------------

function dim(V::Vect[IsingBimodule])
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

function scalar(t::AbstractTensorMap{T,Vect[IsingBimodule],0,0}) where {T}
Bs = collect(blocks(t))
inds = findall(!iszero ∘ last, Bs)
isempty(inds) && return zero(scalartype(t))
return only(last(Bs[only(inds)]))
end

# no custom fuse: we choose to return empty graded space when fusion is forbidden

function Base.oneunit(S::Vect[IsingBimodule])
!isempty(sectors(S)) || throw(ArgumentError("Cannot determine type of empty space"))
allequal(a.row for a in sectors(S)) && allequal(a.col for a in sectors(S)) ||
throw(ArgumentError("sectors of $S are not all equal"))
first(sectors(S)).row == first(sectors(S)).col ||
throw(ArgumentError("sectors of $S are non-diagonal"))
sector = one(first(sectors(S)))
return spacetype(S)(sector => 1)
end

Base.zero(S::Type{Vect[IsingBimodule]}) = Vect[IsingBimodule]()

function blocksectors(W::TensorMapSpace{Vect[IsingBimodule],N₁,N₂}) where {N₁,N₂}
codom = codomain(W)
dom = domain(W)
if N₁ == 0 && N₂ == 0
return [IsingBimodule(1, 1, 0), IsingBimodule(2, 2, 0)]
elseif N₁ == 0
@assert N₂ != 0 "one of Type IsingBimodule doesn't exist"
return filter!(isone, collect(blocksectors(dom))) # is this what we want? doesn't allow M/Mop to end at empty space
elseif N₂ == 0
@assert N₁ != 0 "one of Type IsingBimodule 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

function rightoneunit(S::Vect[IsingBimodule])
!isempty(sectors(S)) || throw(ArgumentError("Cannot determine type of empty space"))
allequal(a.col 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

function leftoneunit(S::Vect[IsingBimodule])
!isempty(sectors(S)) || throw(ArgumentError("Cannot determine type of empty space"))
allequal(a.row for a in sectors(S)) ||
throw(ArgumentError("sectors of $S do not have the same leftone"))

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

function insertrightunit(P::ProductSpace{Vect[IsingBimodule],N}, ::Val{i};
conj::Bool=false,
dual::Bool=false) where {i,N}
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
if conj
u = TensorKit.conj(u)
end
return ProductSpace(TupleTools.insertafter(P.spaces, i, (u,)))
end

# TODO?: overwrite defaults at level of HomSpace and TensorMap?
function insertleftunit(P::ProductSpace{Vect[IsingBimodule],N}, ::Val{i}; # want no defaults?
conj::Bool=false,
dual::Bool=false) where {i,N}
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
if conj
u = TensorKit.conj(u)
end
return ProductSpace(TupleTools.insertafter(P.spaces, i - 1, (u,)))
end

# is this even necessary? can let it error at fusiontrees.jl:93 from the one(IsingBimodule) call
# but these errors are maybe more informative
function FusionTree(uncoupled::Tuple{IsingBimodule,Vararg{IsingBimodule}})
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{IsingBimodule,Vararg{IsingBimodule}})
return throw(ArgumentError("coupled sector must be provided for IsingBimodule fusion"))
end
13 changes: 10 additions & 3 deletions src/tensors/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,17 @@ function ⊗(t1::AbstractTensorMap, t2::AbstractTensorMap)
throw(SpaceMismatch("spacetype(t1) ≠ spacetype(t2)"))
cod1, cod2 = codomain(t1), codomain(t2)
dom1, dom2 = domain(t1), domain(t2)
cod = cod1 ⊗ cod2
dom = dom1 ⊗ dom2
p12 = ((codomainind(t1)..., (codomainind(t2) .+ numind(t1))...),
(domainind(t1)..., (domainind(t2) .+ numind(t1))...))

T = promote_type(scalartype(t1), scalartype(t2))
t = zerovector!(similar(t1, T, cod ← dom))
TC = promote_type(sectorscalartype(sectortype(t1)), T)
t = TO.tensoralloc_contract(TC,
t1, ((codomainind(t1)..., domainind(t1)...), ()), false,
t2, ((), (codomainind(t2)..., domainind(t2)...)), false,
p12, Val(false))

zerovector!(t)
for (f1l, f1r) in fusiontrees(t1)
for (f2l, f2r) in fusiontrees(t2)
c1 = f1l.coupled # = f1r.coupled
Expand Down
8 changes: 4 additions & 4 deletions test/fusiontrees.jl
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ ti = time()
end
end
end
@testset "Fusion tree $Istr: elementy artin braid" begin
@testset "Fusion tree $Istr: elementary artin braid" begin
N = length(out)
isdual = ntuple(n -> rand(Bool), N)
for in in ⊗(out...)
Expand Down Expand Up @@ -268,7 +268,7 @@ ti = time()
end
end
@testset "Fusion tree $Istr: braiding and permuting" begin
f = rand(collect(fusiontrees(out, in, isdual)))
f = rand(collect(it))
p = tuple(randperm(N)...)
ip = invperm(p)

Expand Down Expand Up @@ -379,7 +379,7 @@ ti = time()
f1 = rand(collect(fusiontrees(out, incoming, ntuple(n -> rand(Bool), N))))
f2 = rand(collect(fusiontrees(out[randperm(N)], incoming, ntuple(n -> rand(Bool), N))))

@testset "Double fusion tree $Istr: repartioning" begin
@testset "Double fusion tree $Istr: repartitioning" begin
for n in 0:(2 * N)
d = @constinferred TK.repartition(f1, f2, $n)
@test dim(incoming) ≈
Expand Down Expand Up @@ -548,7 +548,7 @@ ti = time()
@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 = typeof(Fsymbol(one(I), one(I), one(I), one(I), one(I), one(I))[1, 1, 1, 1])
T = sectorscalartype(I)
d2 = Dict{typeof((f1front, f1front)),T}()
for ((f1′, f2′), coeff′) in d1
for ((f1′′, f2′′), coeff′′) in
Expand Down
Loading
Loading