Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
6b4eb48
change TensorKitSectors compat
borisdevos Sep 25, 2025
8d2a356
add `unitspace`
borisdevos Sep 25, 2025
1803c59
one -> unit + left/rightone -> left/rightunit + isone -> isunit when …
borisdevos Sep 25, 2025
3dab6ba
change conj to dual for sectors
borisdevos Sep 25, 2025
3a2e67c
export new functions from TensorKitSectors
borisdevos Sep 25, 2025
09cee6d
introduce `zerospace` to replace `zero` of a space
borisdevos Sep 25, 2025
9bdd092
add `oneunit` for type of space
borisdevos Sep 25, 2025
d2da757
format
borisdevos Sep 25, 2025
084ab72
minor changes from #263
borisdevos Sep 26, 2025
d4d6fe7
use the const `TK` in tests where appropriate
borisdevos Sep 26, 2025
26c6c83
format
borisdevos Sep 26, 2025
21b3bc4
`otimes` between tensormaps to account for `sectorscalartype`
borisdevos Sep 26, 2025
d159d77
generalise `unitspace` and `zerospace`
borisdevos Sep 30, 2025
a0e474f
have `dim` of graded space depend on sectorscalartype
borisdevos Sep 30, 2025
732b8d1
introduce `left/rightunitspace`
borisdevos Sep 30, 2025
28952fc
generalise `blocksectors` of homspace
borisdevos Sep 30, 2025
bde5b9c
generalise `scalar`
borisdevos Sep 30, 2025
4838054
some exports
borisdevos Sep 30, 2025
4b68caf
rename `insertleft/rightunit` and `removeunit` to `insertleft/rightun…
borisdevos Sep 30, 2025
a8046b2
undo the renaming in the changelog
borisdevos Sep 30, 2025
aacafc1
update `insertleft/rightunitspace`
borisdevos Sep 30, 2025
50e408d
add fixme
borisdevos Sep 30, 2025
def9a5e
Merge branch 'main' of https://github.com/Jutho/TensorKit.jl into bd/…
borisdevos Nov 3, 2025
6cc0618
fix bad merge conflict choices
borisdevos Nov 3, 2025
1ce9609
remove TensorKit shortcuts where they don't exist
borisdevos Nov 3, 2025
617fc6c
another merge fix
borisdevos Nov 3, 2025
61fa786
more merge changes + add `IsingBimodule` to sectorlist
borisdevos Nov 3, 2025
db80ca8
make spaces tests multifusion-friendly
borisdevos Nov 3, 2025
6e990e2
apply tensors test changes from #263
borisdevos Nov 3, 2025
b114f64
avoid `one` call in `rank` of tensormap
borisdevos Nov 3, 2025
313df53
use `sum` in `dim` of `GradedSpace`
borisdevos Nov 3, 2025
bd97efd
change one more `oneunit` to `unitspace`
borisdevos Nov 3, 2025
e24f01d
changes to `(left/right)unitspace` and `zerospace`
borisdevos Nov 4, 2025
9ffa2dc
remove module specification
borisdevos Nov 5, 2025
6065d25
Revert "remove module specification"
borisdevos Nov 5, 2025
b8a3253
keep `init` in `dim` and deal with repercussions in src
borisdevos Nov 5, 2025
f54f613
change `removeunitspace` to look for any unit instead of all
borisdevos Nov 5, 2025
d3a0dd0
add `IsingBimodule` spaces and help functions for fusiontree tests
borisdevos Nov 5, 2025
2735ab1
rewrite and reorganise fusiontree tests
borisdevos Nov 5, 2025
a6eb01b
rewrite and reorganise factorisation tests
borisdevos Nov 5, 2025
3622b92
rewrite and reorganise tensor tests
borisdevos Nov 5, 2025
d014244
another float dim thingie correction
borisdevos Nov 5, 2025
ae92cc1
remove comment
borisdevos Nov 5, 2025
428afee
bring back `insertleft/rightunit` and `removeunit`
borisdevos Nov 5, 2025
f73b24a
remove dupe exports
borisdevos Nov 5, 2025
9cc5696
fix `dim` and revert unnecessary Int converts
borisdevos Nov 5, 2025
34a40c5
change blocksectors of empty productspace
borisdevos Nov 5, 2025
496a701
fix gradedspace tests for product sectors including multifusion
borisdevos Nov 5, 2025
d870644
bring back `Int` for truncrank dimensions
borisdevos Nov 5, 2025
41ec7c5
bump TensorKitSectors compat
borisdevos Nov 6, 2025
31f7e0b
suggestions to dim and pinv
borisdevos Nov 7, 2025
bfcacdf
fix doc error
borisdevos Nov 10, 2025
e53d9c4
add docstring to `unitspace`
borisdevos Nov 10, 2025
97eea7e
fix `allequal` version dep
borisdevos Nov 10, 2025
d76cb14
format
borisdevos Nov 10, 2025
2d2d700
move code around + docstring extension
borisdevos Nov 10, 2025
b58fb34
introduce `isunitspace` + use in `removeunit`
borisdevos Nov 10, 2025
f178770
`isunit` change
borisdevos Nov 10, 2025
3e9698a
clean up some tests + reduce git diff
borisdevos Nov 10, 2025
6710e88
have `blocksectors` always return a vector
borisdevos Nov 10, 2025
f37421e
rename + add todo
borisdevos Nov 10, 2025
5347835
rewrite spaces tests to not specialise to fusion or multifusion
borisdevos Nov 10, 2025
700f653
potential fix to isometry test
borisdevos Nov 10, 2025
658a5b1
keep `@tensor` for symmetric braiding test
borisdevos Nov 10, 2025
bdc937f
keep `@tensor` tests + add todo
borisdevos Nov 10, 2025
149ce17
fix return type of rank + test
borisdevos Nov 12, 2025
ee61281
more isunits
borisdevos Nov 12, 2025
2ba0306
clean up `random_fusion` + remove redundant setup function
borisdevos Nov 12, 2025
b64ca37
assert spaces are suitable for factorization tests + deal with float dim
borisdevos Nov 12, 2025
1eefd43
get `insertleft/rightunit` working without explicit indices + edit so…
borisdevos Nov 12, 2025
015fb0f
reduce git diff
borisdevos Nov 12, 2025
a548b36
variable renames
borisdevos Nov 12, 2025
7d7996b
tests for `is/left/rightunitspace`
borisdevos Nov 12, 2025
0a840c3
format
borisdevos Nov 12, 2025
e1ebb2c
get some trace tests working for multifusion + remove some todos
borisdevos Nov 12, 2025
8305383
Merge branch 'main' of https://github.com/Jutho/TensorKit.jl into bd/…
borisdevos Nov 13, 2025
d04ba25
revert `isunit` change to `isone`
borisdevos Nov 13, 2025
847a9e0
fix full trace test for fermions
borisdevos Nov 13, 2025
f53b0ef
return error for `fusiontrees` without coupled sector for `GenericUnit`
borisdevos Nov 14, 2025
dbea001
get double fusion tree tests working for `GenericUnit`
borisdevos Nov 14, 2025
4fceb03
suggested source changes
borisdevos Nov 16, 2025
9e90f78
factorisations test changes
borisdevos Nov 16, 2025
14698c4
let full and partial trace tests run for every sector
borisdevos Nov 16, 2025
326fcd1
deal with merge conflicts
borisdevos Nov 16, 2025
6aaa460
accidently removed part of test
borisdevos Nov 16, 2025
f125a4a
Update test/tensors/factorizations.jl
borisdevos Nov 16, 2025
f548497
code suggestions
borisdevos Nov 26, 2025
c009bcc
get rid of try-catch block
borisdevos Nov 26, 2025
8f6c338
Merge branch 'main' into bd/multifusion
borisdevos Nov 26, 2025
c9f8010
code suggestions
borisdevos Nov 27, 2025
faf6837
format
borisdevos Nov 27, 2025
7917adc
deal with different error type thrown
borisdevos Nov 27, 2025
679ec5b
Merge branch 'main' of https://github.com/Jutho/TensorKit.jl into bd/…
borisdevos Dec 1, 2025
baa5991
make spaces compatible in isometric projections
borisdevos Dec 1, 2025
7a16987
Update test/symmetries/spaces.jl
borisdevos Dec 1, 2025
cbf541b
help `random_fusion` in while loop
borisdevos Dec 2, 2025
bf1dd5e
Merge branch 'main' into bd/multifusion
borisdevos Dec 2, 2025
1f2cf55
`isa`'s, CI friendliness, braiding conditions and todos
borisdevos Dec 3, 2025
9fc7aa8
import `HasBraiding` manually
borisdevos Dec 3, 2025
41e73c1
Revert "import `HasBraiding` manually"
borisdevos Dec 3, 2025
b33bc67
export `HasBraiding` in TensorKit
borisdevos Dec 3, 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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Random = "1"
SafeTestsets = "0.1"
ScopedValues = "1.3.0"
Strided = "2"
TensorKitSectors = "=0.3.0, 0.3.2"
TensorKitSectors = "0.3.3"
TensorOperations = "5.1"
Test = "1"
TestExtras = "0.2,0.3"
Expand Down
7 changes: 5 additions & 2 deletions src/TensorKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ module TensorKit
export Sector, AbstractIrrep, Irrep
export FusionStyle, UniqueFusion, MultipleFusion, MultiplicityFreeFusion, SimpleFusion, GenericFusion
export UnitStyle, SimpleUnit, GenericUnit
export BraidingStyle, SymmetricBraiding, Bosonic, Fermionic, Anyonic, NoBraiding
export BraidingStyle, SymmetricBraiding, Bosonic, Fermionic, Anyonic, NoBraiding, HasBraiding
export Trivial, Z2Irrep, Z3Irrep, Z4Irrep, ZNIrrep, U1Irrep, SU2Irrep, CU1Irrep
export ProductSector
export FermionParity, FermionNumber, FermionSpin
export FibonacciAnyon, IsingAnyon
export FibonacciAnyon, IsingAnyon, IsingBimodule

# Export common vector space, fusion tree and tensor types
export VectorSpace, Field, ElementarySpace # abstract vector spaces
Expand All @@ -34,7 +34,10 @@ export SpaceMismatch, SectorMismatch, IndexError # error types
# Export general vector space methods
export space, field, dual, dim, reduceddim, dims, fuse, flip, isdual
export unitspace, zerospace, oplus, ominus
export leftunitspace, rightunitspace, isunitspace
export insertleftunit, insertrightunit, removeunit

# partial order for vector spaces
export infimum, supremum, isisomorphic, ismonomorphic, isepimorphic

# Reexport methods for sectors and properties thereof
Expand Down
6 changes: 6 additions & 0 deletions src/auxiliary/auxiliary.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,9 @@ function _copyto!(A::StridedView{<:Any, 1}, B::StridedView{<:Any, 2})

return A
end

@static if VERSION < v"1.11" # TODO: remove once support for v1.10 is dropped
_allequal(f, xs) = allequal(Base.Generator(f, xs))
else
_allequal(f, xs) = allequal(f, xs)
end
2 changes: 1 addition & 1 deletion src/fusiontrees/fusiontrees.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function FusionTree{I}(
uncoupled::NTuple{N}, coupled = unit(I), isdual = ntuple(Returns(false), N)
) where {I <: Sector, N}
FusionStyle(I) isa UniqueFusion ||
error("fusion tree requires inner lines if `FusionStyle(I) <: MultipleFusion`")
throw(ArgumentError("fusion tree requires inner lines if `FusionStyle(I) <: MultipleFusion`"))
return FusionTree{I}(
map(s -> convert(I, s), uncoupled), convert(I, coupled), isdual,
_abelianinner(map(s -> convert(I, s), (uncoupled..., dual(coupled))))
Expand Down
3 changes: 3 additions & 0 deletions src/fusiontrees/iterator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ function fusiontrees(uncoupled::Tuple{Vararg{I}}, coupled::I) where {I <: Sector
return fusiontrees(uncoupled, coupled, isdual)
end
function fusiontrees(uncoupled::Tuple{I, Vararg{I}}) where {I <: Sector}
UnitStyle(I) isa GenericUnit && throw(
ArgumentError("Must specify coupled sector when UnitStyle is GenericUnit.")
)
coupled = unit(I)
isdual = ntuple(n -> false, length(uncoupled))
return fusiontrees(uncoupled, coupled, isdual)
Expand Down
13 changes: 7 additions & 6 deletions src/spaces/gradedspace.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,8 @@ field(::Type{<:GradedSpace}) = ℂ
InnerProductStyle(::Type{<:GradedSpace}) = EuclideanInnerProduct()

function dim(V::GradedSpace)
return reduce(
+, dim(V, c) * dim(c) for c in sectors(V);
init = zero(dim(unit(sectortype(V))))
)
init = 0 * dim(first(allunits(sectortype(V))))
return sum(c -> dim(c) * dim(V, c), sectors(V); init = init)
end
function dim(V::GradedSpace{I, <:AbstractDict}, c::I) where {I <: Sector}
return get(V.dims, isdual(V) ? dual(c) : c, 0)
Expand Down Expand Up @@ -123,8 +121,11 @@ function flip(V::GradedSpace{I}) where {I <: Sector}
end
end

unitspace(S::Type{<:GradedSpace{I}}) where {I <: Sector} = S(unit(I) => 1)
zerospace(S::Type{<:GradedSpace{I}}) where {I <: Sector} = S(unit(I) => 0)
function unitspace(S::Type{<:GradedSpace{I}}) where {I <: Sector}
return S(unit => 1 for unit in allunits(I))
end
zerospace(S::Type{<:GradedSpace}) = S()

# TODO: the following methods can probably be implemented more efficiently for
# `FiniteGradedSpace`, but we don't expect them to be used often in hot loops, so
# these generic definitions (which are still quite efficient) are good for now.
Expand Down
23 changes: 15 additions & 8 deletions src/spaces/homspace.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,16 @@ function blocksectors(W::HomSpace)
N₁ = length(codom)
N₂ = length(dom)
I = sectortype(W)
# TODO: is sort! still necessary now that blocksectors of ProductSpace is sorted?
if N₂ <= N₁
return sort!(filter!(c -> hasblock(codom, c), blocksectors(dom)))
if N₁ == N₂ == 0
return allunits(I)
elseif N₁ == 0
return filter!(isunit, collect(blocksectors(dom))) # module space cannot end in empty space
elseif N₂ == 0
return filter!(isunit, collect(blocksectors(codom)))
elseif N₂ <= N₁
return filter!(c -> hasblock(codom, c), collect(blocksectors(dom)))
else
return sort!(filter!(c -> hasblock(dom, c), blocksectors(codom)))
return filter!(c -> hasblock(dom, c), collect(blocksectors(codom)))
end
end

Expand Down Expand Up @@ -227,7 +232,7 @@ function TensorOperations.tensorcontract(
end

"""
insertleftunit(W::HomSpace, i=numind(W) + 1; conj=false, dual=false)
insertleftunit(W::HomSpace, i = numind(W) + 1; conj = false, dual = false)

Insert a trivial vector space, isomorphic to the underlying field, at position `i`,
which can be specified as an `Int` or as `Val(i)` for improved type stability.
Expand All @@ -237,7 +242,8 @@ See also [`insertrightunit`](@ref insertrightunit(::HomSpace, ::Val{i}) where {i
[`removeunit`](@ref removeunit(::HomSpace, ::Val{i}) where {i}).
"""
function insertleftunit(
W::HomSpace, ::Val{i} = Val(numind(W) + 1); conj::Bool = false, dual::Bool = false
W::HomSpace, ::Val{i} = Val(numind(W) + 1);
conj::Bool = false, dual::Bool = false
) where {i}
if i ≤ numout(W)
return insertleftunit(codomain(W), Val(i); conj, dual) ← domain(W)
Expand All @@ -247,7 +253,7 @@ function insertleftunit(
end

"""
insertrightunit(W::HomSpace, i=numind(W); conj=false, dual=false)
insertrightunit(W::HomSpace, i = numind(W); conj = false, dual = false)

Insert a trivial vector space, isomorphic to the underlying field, after position `i`,
which can be specified as an `Int` or as `Val(i)` for improved type stability.
Expand All @@ -257,7 +263,8 @@ See also [`insertleftunit`](@ref insertleftunit(::HomSpace, ::Val{i}) where {i})
[`removeunit`](@ref removeunit(::HomSpace, ::Val{i}) where {i}).
"""
function insertrightunit(
W::HomSpace, ::Val{i} = Val(numind(W)); conj::Bool = false, dual::Bool = false
W::HomSpace, ::Val{i} = Val(numind(W));
conj::Bool = false, dual::Bool = false
) where {i}
if i ≤ numout(W)
return insertrightunit(codomain(W), Val(i); conj, dual) ← domain(W)
Expand Down
43 changes: 31 additions & 12 deletions src/spaces/productspace.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
struct ProductSpace{S<:ElementarySpace, N} <: CompositeSpace{S}
ProductSpace(spaces::NTuple{N, S}) where {S<:ElementarySpace, N}
struct ProductSpace{S <: ElementarySpace, N} <: CompositeSpace{S}
ProductSpace(spaces::NTuple{N, S}) where {S <: ElementarySpace, N}

A `ProductSpace` is a tensor product space of `N` vector spaces of type `S <: ElementarySpace`.
Only tensor products between [`ElementarySpace`](@ref) objects of the same type are allowed.
Expand Down Expand Up @@ -87,7 +87,7 @@ end

# more specific methods
"""
sectors(P::ProductSpace{S, N}) where {S<:ElementarySpace}
sectors(P::ProductSpace{S, N}) where {S <: ElementarySpace}

Return an iterator over all possible combinations of sectors (represented as an
`NTuple{N, sectortype(S)}`) that can appear within the tensor product space `P`.
Expand Down Expand Up @@ -151,7 +151,7 @@ function blocksectors(P::ProductSpace{S, N}) where {S, N}
end
bs = Vector{I}()
if N == 0
push!(bs, unit(I))
append!(bs, allunits(I))
elseif N == 1
for s in sectors(P)
push!(bs, first(s))
Expand Down Expand Up @@ -196,7 +196,7 @@ hasblock(P::ProductSpace, c::Sector) = !isempty(fusiontrees(P, c))
blockdim(P::ProductSpace, c::Sector)

Return the total dimension of a coupled sector `c` in the product space, by summing over
all `dim(P, s)` for all tuples of sectors `s::NTuple{N, <:Sector}` that can fuse to `c`,
all `dim(P, s)` for all tuples of sectors `s::NTuple{N, Sector}` that can fuse to `c`,
counted with the correct multiplicity (i.e. number of ways in which `s` can fuse to `c`).

See also [`hasblock`](@ref) and [`blocksectors`](@ref).
Expand Down Expand Up @@ -228,8 +228,8 @@ end

# unit element with respect to the monoidal structure of taking tensor products
"""
one(::S) where {S<:ElementarySpace} -> ProductSpace{S, 0}
one(::ProductSpace{S}) where {S<:ElementarySpace} -> ProductSpace{S, 0}
one(::S) where {S <: ElementarySpace} -> ProductSpace{S, 0}
one(::ProductSpace{S}) where {S <: ElementarySpace} -> ProductSpace{S, 0}

Return a tensor product of zero spaces of type `S`, i.e. this is the unit object under the
tensor product operation, such that `V ⊗ one(V) == V`.
Expand All @@ -248,7 +248,7 @@ fuse(P::ProductSpace{S, 0}) where {S <: ElementarySpace} = unitspace(S)
fuse(P::ProductSpace{S}) where {S <: ElementarySpace} = fuse(P.spaces...)

"""
insertleftunit(P::ProductSpace, i::Int=length(P) + 1; conj=false, dual=false)
insertleftunit(P::ProductSpace, i::Int = length(P) + 1; conj = false, dual = false)

Insert a trivial vector space, isomorphic to the underlying field, at position `i`,
which can be specified as an `Int` or as `Val(i)` for improved type stability.
Expand All @@ -260,7 +260,18 @@ function insertleftunit(
P::ProductSpace, ::Val{i} = Val(length(P) + 1);
conj::Bool = false, dual::Bool = false
) where {i}
u = unitspace(spacetype(P))
N = length(P)
I = sectortype(P)
if UnitStyle(I) isa SimpleUnit
u = unitspace(spacetype(P))
else
N > 0 || throw(ArgumentError("cannot insert a sensible unit space in the empty product space"))
if i == N + 1
u = rightunitspace(P[N])
else
u = leftunitspace(P[i])
end
end
if dual
u = TensorKit.dual(u)
end
Expand All @@ -271,7 +282,7 @@ function insertleftunit(
end

"""
insertrightunit(P::ProductSpace, i=lenght(P); conj=false, dual=false)
insertrightunit(P::ProductSpace, i = length(P); conj = false, dual = false)

Insert a trivial vector space, isomorphic to the underlying field, after position `i`,
which can be specified as an `Int` or as `Val(i)` for improved type stability.
Expand All @@ -283,7 +294,14 @@ function insertrightunit(
P::ProductSpace, ::Val{i} = Val(length(P));
conj::Bool = false, dual::Bool = false
) where {i}
u = unitspace(spacetype(P))
N = length(P)
I = sectortype(P)
if UnitStyle(I) isa SimpleUnit
u = unitspace(spacetype(P))
else
N > 0 || throw(ArgumentError("cannot insert a sensible unit space in the empty product space"))
u = rightunitspace(P[i])
end
if dual
u = TensorKit.dual(u)
end
Expand All @@ -305,7 +323,8 @@ and [`insertrightunit`](@ref insertrightunit(::ProductSpace, ::Val{i}) where {i}
"""
function removeunit(P::ProductSpace, ::Val{i}) where {i}
1 ≤ i ≤ length(P) || _boundserror(P, i)
isisomorphic(P[i], unitspace(P[i])) || _nontrivialspaceerror(P, i)
I = sectortype(P)
isunitspace(P[i]) || _nontrivialspaceerror(P, i)
return ProductSpace{spacetype(P)}(TupleTools.deleteat(P.spaces, i))
end

Expand Down
73 changes: 69 additions & 4 deletions src/spaces/vectorspaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ generally, objects in linear monoidal categories.
abstract type VectorSpace end

"""
field(a) -> Type{𝔽<:Field}
field(::Type{T}) -> Type{𝔽<:Field}
field(a) -> Type{𝔽 <: Field}
field(::Type{T}) -> Type{𝔽 <: Field}

Return the type of field over which object `a` (e.g. a vector space or a tensor) is defined.
This also works in type domain.
Expand Down Expand Up @@ -130,10 +130,13 @@ Always returns `false` for spaces where `V == conj(V)`, i.e. vector spaces over
""" isconj(::ElementarySpace)

"""
unitspace(V::S) where {S<:ElementarySpace} -> S
unitspace(V::S) where {S <: ElementarySpace} -> S

Return the corresponding vector space of type `S` that represents the trivial
one-dimensional space, i.e. the space that is isomorphic to the corresponding field.
For vector spaces where `I = sectortype(S)` has a semi-simple unit structure
(`UnitStyle(I) == GenericUnit()`), this returns a multi-dimensional space corresponding to all unit sectors:
`dim(unitspace(V), s) == 1` for all `s in allunits(I)`.

!!! note
`unitspace(V)`is different from `one(V)`. The latter returns the empty product space
Expand All @@ -144,7 +147,7 @@ Base.oneunit(V::ElementarySpace) = unitspace(V)
Base.oneunit(::Type{V}) where {V <: ElementarySpace} = unitspace(V)

"""
zerospace(V::S) where {S<:ElementarySpace} -> S
zerospace(V::S) where {S <: ElementarySpace} -> S

Return the corresponding vector space of type `S` that represents the zero-dimensional or empty space.
This is the zero element of the direct sum of vector spaces.
Expand All @@ -154,6 +157,68 @@ zerospace(V::ElementarySpace) = zerospace(typeof(V))
Base.zero(V::ElementarySpace) = zerospace(V)
Base.zero(::Type{V}) where {V <: ElementarySpace} = zerospace(V)

"""
leftunitspace(V::S) where {S <: ElementarySpace} -> S

Return the corresponding vector space of type `S` that represents the trivial
one-dimensional space, i.e. the space that is isomorphic to the corresponding field. For vector spaces
of type `GradedSpace{I}`, this one-dimensional space contains the unique left unit of the objects in `Sector` `I` present
in the vector space.
"""
function leftunitspace(V::ElementarySpace)
I = sectortype(V)
if UnitStyle(I) isa SimpleUnit
return unitspace(typeof(V))
else
!isempty(sectors(V)) || throw(ArgumentError("Cannot determine the left unit of an empty space"))
_allequal(leftunit, sectors(V)) ||
throw(ArgumentError("sectors of $V do not have the same left unit"))

sector = leftunit(first(sectors(V)))
return spacetype(V)(sector => 1)
end
end

"""
rightunitspace(V::S) where {S <: ElementarySpace} -> S

Return the corresponding vector space of type `ElementarySpace` that represents the trivial
one-dimensional space, i.e. the space that is isomorphic to the corresponding field. For vector spaces
of type `GradedSpace{I}`, this corresponds to the right unit of the objects in `Sector` `I` present
in the vector space.
"""
function rightunitspace(V::ElementarySpace)
I = sectortype(V)
if UnitStyle(I) isa SimpleUnit
return unitspace(typeof(V))
else
!isempty(sectors(V)) || throw(ArgumentError("Cannot determine the right unit of an empty space"))
_allequal(rightunit, sectors(V)) ||
throw(ArgumentError("sectors of $V do not have the same right unit"))

sector = rightunit(first(sectors(V)))
return spacetype(V)(sector => 1)
end
end

"""
isunitspace(V::S) where {S <: ElementarySpace} -> Bool

Return whether the elementary space `V` is a unit space, i.e. is isomorphic to the
trivial one-dimensional space. For vector spaces of type `GradedSpace{I}` where `Sector` `I` has a
semi-simple unit structure, this returns `true` if `V` is isomorphic to either the left, right or
semi-simple unit space.
"""
function isunitspace(V::ElementarySpace)
I = sectortype(V)
return if isa(UnitStyle(I), SimpleUnit)
isisomorphic(V, unitspace(V))
else
(dim(V) == 0 || !all(isunit, sectors(V))) && return false
return true
end
end

"""
⊕(V₁::S, V₂::S, V₃::S...) where {S<:ElementarySpace} -> S
oplus(V₁::S, V₂::S, V₃::S...) where {S<:ElementarySpace} -> S
Expand Down
2 changes: 1 addition & 1 deletion src/tensors/diagonal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ function LinearAlgebra.pinv(d::DiagonalTensorMap; kwargs...)
if iszero(atol)
rtol = get(kwargs, :rtol, zero(real(T)))
else
rtol = sqrt(eps(real(float(oneunit(T))))) * length(d.data)
rtol = sqrt(eps(real(float(one(T))))) * length(d.data)
end
pdata = let tol = max(atol, rtol * maximum(abs, d.data))
map(x -> abs(x) < tol ? zero(x) : pinv(x), d.data)
Expand Down
2 changes: 1 addition & 1 deletion src/tensors/indexmanipulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ function has_shared_twist(t, inds)
if BraidingStyle(I) == NoBraiding()
for i in inds
cs = sectors(space(t, i))
all(isone, cs) || throw(SectorMismatch(lazy"Cannot twist sectors $cs"))
all(isunit, cs) || throw(SectorMismatch(lazy"Cannot twist sectors $cs"))
end
return true
elseif BraidingStyle(I) == Bosonic()
Expand Down
2 changes: 1 addition & 1 deletion src/tensors/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ function LinearAlgebra.rank(
t::AbstractTensorMap;
atol::Real = 0, rtol::Real = atol > 0 ? 0 : _default_rtol(t)
)
r = dim(one(sectortype(t))) * 0
r = 0 * dim(first(allunits(sectortype(t))))
dim(t) == 0 && return r
S = LinearAlgebra.svdvals(t)
tol = max(atol, rtol * maximum(first, values(S)))
Expand Down
Loading
Loading