Skip to content

Commit c9ba5bc

Browse files
committed
some spaces restructuring
1 parent bb4a08c commit c9ba5bc

7 files changed

Lines changed: 119 additions & 98 deletions

File tree

src/spaces/cartesianspace.jl

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
"""
22
struct CartesianSpace <: ElementarySpace
3+
CartesianSpace(d::Integer = 0; dual = false)
4+
ℝ^d
35
4-
A real Euclidean space `ℝ^d`, which is therefore self-dual. `CartesianSpace` has no
5-
additonal structure and is completely characterised by its dimension `d`. This is the
6+
A real Euclidean space ``ℝ^d``. `CartesianSpace` has no additonal structure and
7+
is completely characterised by its dimension `d`. A `dual` keyword argument is
8+
accepted for compatibility with other space constructors, but is ignored
9+
since the dual of a Cartesian space is isomorphic to itself. This is the
610
vector space that is implicitly assumed in most of matrix algebra.
711
"""
812
struct CartesianSpace <: ElementarySpace
@@ -29,23 +33,23 @@ function CartesianSpace(dims::AbstractDict; kwargs...)
2933
end
3034
CartesianSpace(g::Base.Generator; kwargs...) = CartesianSpace(g...; kwargs...)
3135

32-
field(::Type{CartesianSpace}) =
33-
InnerProductStyle(::Type{CartesianSpace}) = EuclideanInnerProduct()
34-
35-
Base.conj(V::CartesianSpace) = V
36-
isdual(V::CartesianSpace) = false
37-
3836
# convenience constructor
3937
Base.getindex(::RealNumbers) = CartesianSpace
4038
Base.:^(::RealNumbers, d::Int) = CartesianSpace(d)
4139

4240
# Corresponding methods:
4341
#------------------------
42+
field(::Type{CartesianSpace}) =
43+
InnerProductStyle(::Type{CartesianSpace}) = EuclideanInnerProduct()
44+
4445
dim(V::CartesianSpace, ::Trivial = Trivial()) = V.d
4546
Base.axes(V::CartesianSpace, ::Trivial = Trivial()) = Base.OneTo(dim(V))
46-
hassector(V::CartesianSpace, ::Trivial) = dim(V) != 0
47-
sectors(V::CartesianSpace) = OneOrNoneIterator(dim(V) != 0, Trivial())
48-
sectortype(::Type{CartesianSpace}) = Trivial
47+
48+
dual(V::CartesianSpace) = V
49+
Base.conj(V::CartesianSpace) = dual(V)
50+
isdual(V::CartesianSpace) = false
51+
isconj(V::CartesianSpace) = false
52+
flip(V::CartesianSpace) = V
4953

5054
unitspace(::Type{CartesianSpace}) = CartesianSpace(1)
5155
zerospace(::Type{CartesianSpace}) = CartesianSpace(0)
@@ -56,9 +60,12 @@ function ⊖(V::CartesianSpace, W::CartesianSpace)
5660
end
5761

5862
fuse(V₁::CartesianSpace, V₂::CartesianSpace) = CartesianSpace(V₁.d * V₂.d)
59-
flip(V::CartesianSpace) = V
6063

6164
infimum(V₁::CartesianSpace, V₂::CartesianSpace) = CartesianSpace(min(V₁.d, V₂.d))
6265
supremum(V₁::CartesianSpace, V₂::CartesianSpace) = CartesianSpace(max(V₁.d, V₂.d))
6366

67+
hassector(V::CartesianSpace, ::Trivial) = dim(V) != 0
68+
sectors(V::CartesianSpace) = OneOrNoneIterator(dim(V) != 0, Trivial())
69+
sectortype(::Type{CartesianSpace}) = Trivial
70+
6471
Base.show(io::IO, V::CartesianSpace) = print(io, "ℝ^$(V.d)")

src/spaces/complexspace.jl

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
"""
22
struct ComplexSpace <: ElementarySpace
3+
ComplexSpace(d::Integer = 0; dual = false)
4+
ℂ^d
35
4-
A standard complex vector space ℂ^d with Euclidean inner product and no additional
6+
A standard complex vector space ``ℂ^d`` with Euclidean inner product and no additional
57
structure. It is completely characterised by its dimension and whether its the normal space
68
or its dual (which is canonically isomorphic to the conjugate space).
79
"""
@@ -30,23 +32,23 @@ function ComplexSpace(dims::AbstractDict; kwargs...)
3032
end
3133
ComplexSpace(g::Base.Generator; kwargs...) = ComplexSpace(g...; kwargs...)
3234

33-
field(::Type{ComplexSpace}) =
34-
InnerProductStyle(::Type{ComplexSpace}) = EuclideanInnerProduct()
35-
3635
# convenience constructor
3736
Base.getindex(::ComplexNumbers) = ComplexSpace
3837
Base.:^(::ComplexNumbers, d::Int) = ComplexSpace(d)
3938

4039
# Corresponding methods:
4140
#------------------------
41+
field(::Type{ComplexSpace}) =
42+
InnerProductStyle(::Type{ComplexSpace}) = EuclideanInnerProduct()
43+
4244
dim(V::ComplexSpace, s::Trivial = Trivial()) = V.d
43-
isdual(V::ComplexSpace) = V.dual
4445
Base.axes(V::ComplexSpace, ::Trivial = Trivial()) = Base.OneTo(dim(V))
45-
hassector(V::ComplexSpace, ::Trivial) = dim(V) != 0
46-
sectors(V::ComplexSpace) = OneOrNoneIterator(dim(V) != 0, Trivial())
47-
sectortype(::Type{ComplexSpace}) = Trivial
4846

49-
Base.conj(V::ComplexSpace) = ComplexSpace(dim(V), !isdual(V))
47+
dual(V::ComplexSpace) = ComplexSpace(dim(V), !isdual(V))
48+
Base.conj(V::ComplexSpace) = dual(V)
49+
isdual(V::ComplexSpace) = V.dual
50+
isconj(V::ComplexSpace) = true
51+
flip(V::ComplexSpace) = dual(V)
5052

5153
unitspace(::Type{ComplexSpace}) = ComplexSpace(1)
5254
zerospace(::Type{ComplexSpace}) = ComplexSpace(0)
@@ -62,7 +64,6 @@ function ⊖(V::ComplexSpace, W::ComplexSpace)
6264
end
6365

6466
fuse(V₁::ComplexSpace, V₂::ComplexSpace) = ComplexSpace(V₁.d * V₂.d)
65-
flip(V::ComplexSpace) = dual(V)
6667

6768
function infimum(V₁::ComplexSpace, V₂::ComplexSpace)
6869
return isdual(V₁) == isdual(V₂) ?
@@ -75,4 +76,8 @@ function supremum(V₁::ComplexSpace, V₂::ComplexSpace)
7576
throw(SpaceMismatch("Supremum of space and dual space does not exist"))
7677
end
7778

79+
hassector(V::ComplexSpace, ::Trivial) = dim(V) != 0
80+
sectors(V::ComplexSpace) = OneOrNoneIterator(dim(V) != 0, Trivial())
81+
sectortype(::Type{ComplexSpace}) = Trivial
82+
7883
Base.show(io::IO, V::ComplexSpace) = print(io, isdual(V) ? "(ℂ^$(V.d))'" : "ℂ^$(V.d)")

src/spaces/generalspace.jl

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""
22
struct GeneralSpace{𝔽} <: ElementarySpace
3+
GeneralSpace{𝔽}(d::Integer = 0; dual::Bool = false, conj::Bool = false)
34
45
A finite-dimensional space over an arbitrary field `𝔽` without additional structure.
56
It is thus characterized by its dimension, and whether or not it is the dual and/or
@@ -23,23 +24,25 @@ function GeneralSpace{𝔽}(d::Int = 0; dual::Bool = false, conj::Bool = false)
2324
return GeneralSpace{𝔽}(d, dual, conj)
2425
end
2526

26-
dim(V::GeneralSpace, s::Trivial = Trivial()) = V.d
27-
isdual(V::GeneralSpace) = V.dual
28-
isconj(V::GeneralSpace) = V.conj
27+
# Corresponding methods:
28+
#------------------------
29+
field(::Type{GeneralSpace{𝔽}}) where {𝔽} = 𝔽
30+
InnerProductStyle(::Type{<:GeneralSpace}) = NoInnerProduct()
2931

32+
dim(V::GeneralSpace, s::Trivial = Trivial()) = V.d
3033
Base.axes(V::GeneralSpace, ::Trivial = Trivial()) = Base.OneTo(dim(V))
31-
hassector(V::GeneralSpace, ::Trivial) = dim(V) != 0
32-
sectors(V::GeneralSpace) = OneOrNoneIterator(dim(V) != 0, Trivial())
33-
sectortype(::Type{<:GeneralSpace}) = Trivial
3434

35-
field(::Type{GeneralSpace{𝔽}}) where {𝔽} = 𝔽
36-
InnerProductStyle(::Type{<:GeneralSpace}) = NoInnerProduct()
35+
dual(V::GeneralSpace{𝔽}) where {𝔽} = GeneralSpace{𝔽}(dim(V), !isdual(V), isconj(V))
36+
Base.conj(V::GeneralSpace{𝔽}) where {𝔽} = 𝔽 ==? V : GeneralSpace{𝔽}(dim(V), isdual(V), !isconj(V))
37+
isdual(V::GeneralSpace) = V.dual
38+
isconj(V::GeneralSpace) = 𝔽 ==? false : V.conj
3739

3840
unitspace(::Type{GeneralSpace{𝔽}}) where {𝔽} = GeneralSpace{𝔽}(1, false, false)
3941
zerospace(::Type{GeneralSpace{𝔽}}) where {𝔽} = GeneralSpace{𝔽}(0, false, false)
4042

41-
dual(V::GeneralSpace{𝔽}) where {𝔽} = GeneralSpace{𝔽}(dim(V), !isdual(V), isconj(V))
42-
Base.conj(V::GeneralSpace{𝔽}) where {𝔽} = GeneralSpace{𝔽}(dim(V), isdual(V), !isconj(V))
43+
hassector(V::GeneralSpace, ::Trivial) = dim(V) != 0
44+
sectors(V::GeneralSpace) = OneOrNoneIterator(dim(V) != 0, Trivial())
45+
sectortype(::Type{<:GeneralSpace}) = Trivial
4346

4447
function Base.show(io::IO, V::GeneralSpace{𝔽}) where {𝔽}
4548
isconj(V) && print(io, "conj(")

src/spaces/gradedspace.jl

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
"""
22
struct GradedSpace{I<:Sector, D} <: ElementarySpace
3-
dims::D
4-
dual::Bool
5-
end
3+
GradedSpace{I,D}(dims; dual::Bool = false) where {I<:Sector, D}
64
7-
A complex Euclidean space with a direct sum structure corresponding to labels in a set `I`,
8-
the objects of which have the structure of a monoid with respect to a monoidal product `⊗`.
9-
In practice, we restrict the label set to be a set of superselection sectors of type
10-
`I<:Sector`, e.g. the set of distinct irreps of a finite or compact group, or the
11-
isomorphism classes of simple objects of a unitary and pivotal (pre-)fusion category.
5+
A complex Euclidean space with a grading, i.e. a direct sum structure corresponding
6+
to labels in a set `I`, the objects of which have the structure of a monoid with
7+
respect to a monoidal product `⊗`. In practice, we restrict the label set to be a set
8+
of superselection sectors of type `I<:Sector`, e.g. the set of distinct irreps of a
9+
finite or compact group, or the isomorphism classes of simple objects of a unitary
10+
and pivotal (pre-, multi-) fusion category.
1211
1312
Here `dims` represents the degeneracy or multiplicity of every sector.
1413
15-
The data structure `D` of `dims` will depend on the result `Base.IteratorSize(values(I))`;
16-
if the result is of type `HasLength` or `HasShape`, `dims` will be stored in a
14+
The data structure `D` of `dims` will depend on the result `Base.IteratorSize(values(I))`.
15+
If the result is of type `HasLength` or `HasShape`, `dims` will be stored in a
1716
`NTuple{N,Int}` with `N = length(values(I))`. This requires that a sector `s::I` can be
1817
transformed into an index via `s == getindex(values(I), i)` and
1918
`i == findindex(values(I), s)`. If `Base.IteratorElsize(values(I))` results `IsInfinite()`
@@ -85,12 +84,11 @@ end
8584
GradedSpace(g::Base.Generator; dual::Bool = false) = GradedSpace(g...; dual = dual)
8685
GradedSpace(g::AbstractDict; dual::Bool = false) = GradedSpace(g...; dual = dual)
8786

88-
Base.hash(V::GradedSpace, h::UInt) = hash(V.dual, hash(V.dims, h))
89-
9087
# Corresponding methods:
91-
# properties
88+
#------------------------
9289
field(::Type{<:GradedSpace}) =
9390
InnerProductStyle(::Type{<:GradedSpace}) = EuclideanInnerProduct()
91+
9492
function dim(V::GradedSpace)
9593
return reduce(
9694
+, dim(V, c) * dim(c) for c in sectors(V);
@@ -103,27 +101,6 @@ end
103101
function dim(V::GradedSpace{I, <:Tuple}, c::I) where {I <: Sector}
104102
return V.dims[findindex(values(I), isdual(V) ? dual(c) : c)]
105103
end
106-
107-
function sectors(V::GradedSpace{I, <:AbstractDict}) where {I <: Sector}
108-
return SectorSet{I}(s -> isdual(V) ? dual(s) : s, keys(V.dims))
109-
end
110-
function sectors(V::GradedSpace{I, NTuple{N, Int}}) where {I <: Sector, N}
111-
return SectorSet{I}(Iterators.filter(n -> V.dims[n] != 0, 1:N)) do n
112-
return isdual(V) ? dual(values(I)[n]) : values(I)[n]
113-
end
114-
end
115-
116-
hassector(V::GradedSpace{I}, s::I) where {I <: Sector} = dim(V, s) != 0
117-
118-
Base.conj(V::GradedSpace) = typeof(V)(V.dims, !V.dual)
119-
isdual(V::GradedSpace) = V.dual
120-
121-
# equality / comparison
122-
function Base.:(==)(V₁::GradedSpace, V₂::GradedSpace)
123-
return sectortype(V₁) == sectortype(V₂) && (V₁.dims == V₂.dims) && V₁.dual == V₂.dual
124-
end
125-
126-
# axes
127104
Base.axes(V::GradedSpace) = Base.OneTo(dim(V))
128105
function Base.axes(V::GradedSpace{I}, c::I) where {I <: Sector}
129106
offset = 0
@@ -134,9 +111,20 @@ function Base.axes(V::GradedSpace{I}, c::I) where {I <: Sector}
134111
return (offset + 1):(offset + dim(c) * dim(V, c))
135112
end
136113

114+
dual(V::GradedSpace) = typeof(V)(V.dims, !V.dual)
115+
Base.conj(V::GradedSpace) = dual(V)
116+
isdual(V::GradedSpace) = V.dual
117+
isconj(V::GradedSpace) = isdual(V)
118+
function flip(V::GradedSpace{I}) where {I <: Sector}
119+
return if isdual(V)
120+
typeof(V)(c => dim(V, c) for c in sectors(V))
121+
else
122+
typeof(V)(dual(c) => dim(V, c) for c in sectors(V))'
123+
end
124+
end
125+
137126
unitspace(S::Type{<:GradedSpace{I}}) where {I <: Sector} = S(unit(I) => 1)
138127
zerospace(S::Type{<:GradedSpace{I}}) where {I <: Sector} = S(unit(I) => 0)
139-
140128
# TODO: the following methods can probably be implemented more efficiently for
141129
# `FiniteGradedSpace`, but we don't expect them to be used often in hot loops, so
142130
# these generic definitions (which are still quite efficient) are good for now.
@@ -151,22 +139,13 @@ function ⊕(V₁::GradedSpace{I}, V₂::GradedSpace{I}) where {I <: Sector}
151139
end
152140
return typeof(V₁)(dims; dual = dual1)
153141
end
154-
155142
function (V::GradedSpace{I}, W::GradedSpace{I}) where {I <: Sector}
156143
dual = isdual(V)
157144
V W && dual == isdual(W) ||
158145
throw(SpaceMismatch("$(W) is not a subspace of $(V)"))
159146
return typeof(V)(c => dim(V, c) - dim(W, c) for c in sectors(V); dual)
160147
end
161148

162-
function flip(V::GradedSpace{I}) where {I <: Sector}
163-
return if isdual(V)
164-
typeof(V)(c => dim(V, c) for c in sectors(V))
165-
else
166-
typeof(V)(dual(c) => dim(V, c) for c in sectors(V))'
167-
end
168-
end
169-
170149
function fuse(V₁::GradedSpace{I}, V₂::GradedSpace{I}) where {I <: Sector}
171150
dims = SectorDict{I, Int}()
172151
for a in sectors(V₁), b in sectors(V₂)
@@ -186,7 +165,6 @@ function infimum(V₁::GradedSpace{I}, V₂::GradedSpace{I}) where {I <: Sector}
186165
for c in intersect(sectors(V₁), sectors(V₂)); dual = Visdual
187166
)
188167
end
189-
190168
function supremum(V₁::GradedSpace{I}, V₂::GradedSpace{I}) where {I <: Sector}
191169
Visdual = isdual(V₁)
192170
Visdual == isdual(V₂) ||
@@ -197,6 +175,21 @@ function supremum(V₁::GradedSpace{I}, V₂::GradedSpace{I}) where {I <: Sector
197175
)
198176
end
199177

178+
hassector(V::GradedSpace{I}, s::I) where {I <: Sector} = dim(V, s) != 0
179+
function sectors(V::GradedSpace{I, <:AbstractDict}) where {I <: Sector}
180+
return SectorSet{I}(s -> isdual(V) ? dual(s) : s, keys(V.dims))
181+
end
182+
function sectors(V::GradedSpace{I, NTuple{N, Int}}) where {I <: Sector, N}
183+
return SectorSet{I}(Iterators.filter(n -> V.dims[n] != 0, 1:N)) do n
184+
return isdual(V) ? dual(values(I)[n]) : values(I)[n]
185+
end
186+
end
187+
188+
Base.hash(V::GradedSpace, h::UInt) = hash(V.dual, hash(V.dims, h))
189+
function Base.:(==)(V₁::GradedSpace, V₂::GradedSpace)
190+
return sectortype(V₁) == sectortype(V₂) && (V₁.dims == V₂.dims) && V₁.dual == V₂.dual
191+
end
192+
200193
function Base.show(io::IO, V::GradedSpace{I}) where {I <: Sector}
201194
print(io, type_repr(typeof(V)), "(")
202195
separator = ""

src/spaces/homspace.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
"""
22
struct HomSpace{S<:ElementarySpace, P1<:CompositeSpace{S}, P2<:CompositeSpace{S}}
3-
codomain::P1
4-
domain::P2
5-
end
3+
HomSpace(codomain::CompositeSpace{S}, domain::CompositeSpace{S}) where {S<:ElementarySpace}
64
75
Represents the linear space of morphisms with codomain of type `P1` and domain of type `P2`.
8-
Note that HomSpace is not a subtype of VectorSpace, i.e. we restrict the latter to denote
9-
certain categories and their objects, and keep HomSpace distinct.
6+
Note that `HomSpace`` is not a subtype of [`VectorSpace`](@ref), i.e. we restrict the latter
7+
to denote categories and their objects, and keep `HomSpace` distinct.
108
"""
119
struct HomSpace{S <: ElementarySpace, P1 <: CompositeSpace{S}, P2 <: CompositeSpace{S}}
1210
codomain::P1

src/spaces/productspace.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""
22
struct ProductSpace{S<:ElementarySpace, N} <: CompositeSpace{S}
3+
ProductSpace(spaces::NTuple{N, S}) where {S<:ElementarySpace, N}
34
4-
A `ProductSpace` is a tensor product space of `N` vector spaces of type
5-
`S<:ElementarySpace`. Only tensor products between [`ElementarySpace`](@ref) objects of the
6-
same type are allowed.
5+
A `ProductSpace` is a tensor product space of `N` vector spaces of type `S<:ElementarySpace`.
6+
Only tensor products between [`ElementarySpace`](@ref) objects of the same type are allowed.
77
"""
88
struct ProductSpace{S <: ElementarySpace, N} <: CompositeSpace{S}
99
spaces::NTuple{N, S}

0 commit comments

Comments
 (0)