Skip to content

Commit 5ed7e56

Browse files
committed
docs update, further tests update
1 parent eef8196 commit 5ed7e56

File tree

3 files changed

+84
-82
lines changed

3 files changed

+84
-82
lines changed

docs/src/man/intro.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,10 @@ rules"
244244
``λ_{V^*}^{-1} ∘ (ϵ_V ⊗ \mathrm{id}_{V^*}) ∘ (\mathrm{id}_{V^*} ⊗ η_V) ∘ ρ_{V^*}^{-1} = \mathrm{id}_{V^*}``
245245

246246
Given a morphism ``t::W→V``, we can now identify it with ``(t ⊗ \mathrm{id}_{W^*}) ∘ η_W``
247-
to obtain a morphism ``I→V⊗W^*``. For the category ``Vect``, this is the identification
248-
between linear maps ``W→V`` and tensors in ``V⊗W^*``. In particular, for complex vector
249-
spaces, using a bra-ket notation and a generic basis ``{|n⟩}`` for ``V`` and dual basis
250-
``{⟨m|}`` for ``V^*`` (such that ``⟨m|n⟩ = δ_{m,n}``), the unit is
247+
to obtain a morphism ``I→V⊗W^*``. For the category ``\mathbf{Vect}``, this is the
248+
identification between linear maps ``W→V`` and tensors in ``V⊗W^*``. In particular, for
249+
complex vector spaces, using a bra-ket notation and a generic basis ``{|n⟩}`` for ``V`` and
250+
dual basis ``{⟨m|}`` for ``V^*`` (such that ``⟨m|n⟩ = δ_{m,n}``), the unit is
251251
``η_V:ℂ → V ⊗ V^*:λ → λ ∑_n |n⟩ ⊗ ⟨n|`` and the co-unit is
252252
``⁠ϵ_V:V^* ⊗ V → ℂ: ⟨m| ⊗ |n⟩ → δ_{m,n}``. Note that this does not require an inner
253253
product, i.e. no mapping from ``|n⟩`` to ``⟨n|`` was defined. Furthermore, note that we
@@ -264,7 +264,7 @@ It does makes sense to define or identify
264264

265265
In general categories, one can distinguish between a left and right dual, but we always
266266
assume that both objects are naturally isomorphic. Equivalently, ``V^{**} ≂ V`` and the
267-
category is said to be **pivotal**. For every morphism `f:W→V`, there is then a well
267+
category is said to be **pivotal**. For every morphism ``f:W→V``, there is then a well
268268
defined notion of a transpose (also called adjoint mate) ``f^*:V^* → W^*`` as
269269

270270
``f^* = λ_{W^*} ∘ (ϵ_V ⊗ \mathrm{id}_{W^*}) ∘ (\mathrm{id}_{V^*} ⊗ f ⊗ \mathrm{id}_{W^*}) ∘ (\mathrm{id}_{V^*} ⊗ η_{W}) ∘ ρ_{V^*}^{-1}``
@@ -273,18 +273,19 @@ defined notion of a transpose (also called adjoint mate) ``f^*:V^* → W^*`` as
273273

274274
and both definitions coincide (which is not the case if the category is not pivotal). In a graphical representation, this means that boxes (representing tensor maps or morphisms more generally) can be rotated. The transpose corresponds to a 180˚ rotation (either way).
275275

276-
A braiding ``σ_{V,V^*}`` provides a particular way to construct an exact pairing
277-
``ϵ_{V^*} = ϵ_V ∘ σ_{V,V^*} : V⊗V^* → I`` and ``η_{V^*} = σ_{V^*,V}^{-1} \circ η_V: I→ V^*⊗V``,
278-
but this mapping is not canonical for general braidings, so that a braided autonomous
279-
category is not automatically pivotal. A category that is both braided and pivotal
280-
automatically has a twist (and is thus balanced), vice versa a balanced autonomous category
281-
is automatically pivotal. However, the graphical representation using ribbons is only
282-
consistent if we furthermore have
276+
A braiding ``σ_{V,V^*}`` provides a particular way to construct an maps
277+
``ϵ_{V^*} = ϵ_V ∘ σ_{V,V^*} : V⊗V^* → I`` and
278+
``η_{V^*} = σ_{V^*,V}^{-1} \circ η_V: I→ V^*⊗V``, but these maps are not canonical for
279+
general braidings, so that a braided autonomous category is not automatically pivotal. A
280+
category that is both braided and pivotal automatically has a twist (and is thus balanced),
281+
vice versa a balanced autonomous category is automatically pivotal. However, the graphical
282+
representation using ribbons is only consistent if we furthermore have
283283
``θ_{V^*} = θ_V^*`` (i.e. the transpose), in which case the category is said to be
284284
**tortile** or also a **ribbon category**.
285285

286286
In the case of a symmetric braiding, most of these difficulties go away and the pivotal
287-
structure follows
287+
structure follows. A symmetric monoidal category with duals is known as a **compact closed
288+
category**.
288289

289290
### Adjoints
290291

docs/src/man/spaces.md

Lines changed: 64 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ codomain of the map. The starting point is an abstract type `VectorSpace`
1010
```julia
1111
abstract type VectorSpace end
1212
```
13-
which serves in a sense as the category ``Vect``. All instances of subtypes of `VectorSpace`
14-
will represent vector spaces. In particular, we define two abstract subtypes
13+
which serves in a sense as the category ``\mathbf{Vect}``. All instances of subtypes of
14+
`VectorSpace` will represent vector spaces. In particular, we define two abstract subtypes
1515
```julia
1616
abstract type ElementarySpace{𝕜} <: VectorSpace end
1717
const IndexSpace = ElementarySpace
@@ -68,19 +68,18 @@ objects of the same concrete type (i.e. with the same type parameters in case of
6868
parametric type). In particular, every `ElementarySpace` should implement the following
6969
methods
7070

71-
* `dim(::ElementarySpace) -> ::Int`
72-
return the dimension of the space as an `Int`
71+
* `dim(::ElementarySpace) -> ::Int` returns the dimension of the space as an `Int`
7372

74-
* `dual{S<:ElementarySpace}(::S) -> ::S`
75-
return the [dual space](http://en.wikipedia.org/wiki/Dual_space) `dual(V)`, using an
76-
instance of the same concrete type (i.e. not via type parameters); this should satisfy
73+
* `dual{S<:ElementarySpace}(::S) -> ::S` returns the
74+
[dual space](http://en.wikipedia.org/wiki/Dual_space) `dual(V)`, using an instance of
75+
the same concrete type (i.e. not via type parameters); this should satisfy
7776
`dual(dual(V)==V`
7877

79-
* `conj{S<:ElementarySpace}(::S) -> ::S`
80-
return the [complex conjugate space](http://en.wikipedia.org/wiki/Complex_conjugate_vector_space)
78+
* `conj{S<:ElementarySpace}(::S) -> ::S` returns the
79+
[complex conjugate space](http://en.wikipedia.org/wiki/Complex_conjugate_vector_space)
8180
`conj(V)`, using an instance of the same concrete type (i.e. not via type parameters);
8281
this should satisfy `conj(conj(V))==V` and we automatically have
83-
`conj{F<:Real}(V::ElementarySpace{F}) = V`.
82+
`conj(V::ElementarySpace{}) = V`.
8483

8584
For convenience, the dual of a space `V` can also be obtained as `V'`.
8685

@@ -98,17 +97,18 @@ We furthermore define the abstract type
9897
```julia
9998
abstract InnerProductSpace{𝕜} <: ElementarySpace{𝕜}
10099
```
101-
to contain all vector spaces `V` which have an inner product and thus a canonical mapping from
102-
`dual(V)` to `V` (for `𝕜 ⊆ ℝ`) or from `dual(V)` to `conj(V)` (otherwise). This mapping
103-
is provided by the metric, but no further support for working with metrics is currently implemented.
100+
to contain all vector spaces `V` which have an inner product and thus a canonical mapping
101+
from `dual(V)` to `V` (for `𝕜 ⊆ ℝ`) or from `dual(V)` to `conj(V)` (otherwise). This
102+
mapping is provided by the metric, but no further support for working with metrics is
103+
currently implemented.
104104

105105
Finally there is
106106
```julia
107107
abstract EuclideanSpace{𝕜} <: InnerProductSpace{𝕜}
108108
```
109109
to contain all spaces `V` with a standard Euclidean inner product (i.e. where the metric is
110-
the identity). These spaces have the natural isomorphisms `dual(V) == V` (for ` 𝕜<:Real`) or
111-
`dual(V) == conj(V)` (for ` 𝕜<:Complex`). In particular, we have two concrete types
110+
the identity). These spaces have the natural isomorphisms `dual(V) == V` (for ` 𝕜<:Real`)
111+
or `dual(V) == conj(V)` (for ` 𝕜<:Complex`). In particular, we have two concrete types
112112
```julia
113113
immutable CartesianSpace <: EuclideanSpace{ℝ}
114114
d::Int
@@ -118,10 +118,10 @@ immutable ComplexSpace <: EuclideanSpace{ℂ}
118118
dual::Bool
119119
end
120120
```
121-
to represent the Euclidean spaces $ℝ^d$ or $ℂ^d$ without further inner structure. They can be
122-
created using the syntax `ℝ^d` and `ℂ^d`, or `(ℂ^d)'`for the dual space of the latter. Note
123-
that the brackets are required because of the precedence rules, since `d' == d` for `d::Integer``.
124-
Some examples
121+
to represent the Euclidean spaces $ℝ^d$ or $ℂ^d$ without further inner structure. They can
122+
be created using the syntax `ℝ^d` and `ℂ^d`, or `(ℂ^d)'`for the dual space of the latter.
123+
Note that the brackets are required because of the precedence rules, since `d' == d` for
124+
`d::Integer`. Some examples:
125125
```@repl tensorkit
126126
dim(ℝ^10)
127127
(ℝ^10)' == ℝ^10
@@ -136,19 +136,19 @@ an inner structure corresponding to the irreducible representations of a group.
136136

137137
## Composite spaces
138138

139-
Composite spaces are vector spaces that are built up out of individual elementary vector spaces.
140-
The most prominent (and currently only) example is a tensor product of `N` elementary spaces
141-
of the same type `S`, which is implemented as
139+
Composite spaces are vector spaces that are built up out of individual elementary vector
140+
spaces. The most prominent (and currently only) example is a tensor product of `N` elementary spaces of the same type `S`, which is implemented as
142141
```julia
143142
struct ProductSpace{S<:ElementarySpace, N} <: CompositeSpace{S}
144143
spaces::NTuple{N, S}
145144
end
146145
```
147146
Given some `V1::S`, `V2::S`, `V3::S` of the same type `S<:ElementarySpace`, we can easily
148-
construct `ProductSpace{S,3}((V1,V2,V3))` as `ProductSpace(V1,V2,V3)` or using `V1 ⊗ V2 ⊗ V3`,
149-
where `` is simply obtained by typing `\otimes`+TAB. In fact, for convenience, even the regular
150-
multiplication operator `*` acts as tensor product between vector spaces, and as a consequence
151-
so does raising a vector space to a positive integer power, i.e.
147+
construct `ProductSpace{S,3}((V1,V2,V3))` as `ProductSpace(V1,V2,V3)` or using
148+
`V1 ⊗ V2 ⊗ V3`, where `` is simply obtained by typing `\otimes`+TAB. In fact, for
149+
convenience, also the regular multiplication operator `*` acts as tensor product between
150+
vector spaces, and as a consequence so does raising a vector space to a positive integer
151+
power, i.e.
152152
```@repl tensorkit
153153
V1 = ℂ^2
154154
V2 = ℂ^3
@@ -158,51 +158,52 @@ dim(V1 ⊗ V2)
158158
dims(V1 ⊗ V2)
159159
dual(V1 ⊗ V2)
160160
```
161-
Here, the new function `dims` maps `dim` to the individual spaces in a `ProductSpace` and returns
162-
the result as a tuple. Note that the rationale for the last result was explained in the subsection
163-
[Duals](@ref) of [Properties of monoidal categories](@ref).
161+
Here, the new function `dims` maps `dim` to the individual spaces in a `ProductSpace` and
162+
returns the result as a tuple. Note that the rationale for the last result was explained in
163+
the subsection [Duals](@ref) of [Properties of monoidal categories](@ref).
164164

165165
Following Julia's Base library, the function `one` applied to a `ProductSpace{S,N}` returns
166166
the multiplicative identity, which is `ProductSpace{S,0}`. The same result is obtained when
167-
acting on an instance `V` of `S::ElementarySpace` directly, however note that `V ⊗ one(V)` will
168-
yield a `ProductSpace{S,1}(V)` and not `V` itself. Similar to Julia Base, `one` also works in
169-
the type domain.
170-
171-
In the future, other `CompositeSpace` types could be added. For example, the wave function of
172-
an `N`-particle quantum system in first quantization would require the introduction of a `SymmetricSpace{S,N}`
173-
or a `AntiSymmetricSpace{S,N}` for bosons or fermions respectively, which correspond to the
174-
symmetric (permutation invariant) or antisymmetric subspace of `V^N`, where `V::S` represents
175-
the Hilbert space of the single particle system. Other domains, like general relativity, might
176-
also benefit from tensors living in a subspace with certain symmetries under specific index
177-
permutations.
167+
acting on an instance `V` of `S::ElementarySpace` directly, however note that `V ⊗ one(V)`
168+
will yield a `ProductSpace{S,1}(V)` and not `V` itself. Similar to Julia Base, `one` also
169+
works in the type domain.
170+
171+
In the future, other `CompositeSpace` types could be added. For example, the wave function
172+
of an `N`-particle quantum system in first quantization would require the introduction of a
173+
`SymmetricSpace{S,N}` or a `AntiSymmetricSpace{S,N}` for bosons or fermions respectively,
174+
which correspond to the symmetric (permutation invariant) or antisymmetric subspace of
175+
`V^N`, where `V::S` represents the Hilbert space of the single particle system. Other
176+
domains, like general relativity, might also benefit from tensors living in a subspace with
177+
certain symmetries under specific index permutations.
178178

179179
## Some more functionality
180-
Some more convenience functions are provided for the euclidean spaces [`CartesianSpace`](@ref)
181-
and [`ComplexSpace`](@ref), as well as for [`RepresentationSpace`](@ref) discussed in the next
182-
section. All functions below that act on more than a single elementary space, are only defined
183-
when the different spaces are of the same concrete subtype `S<:ElementarySpace`
184-
185-
The function `fuse(V1, V2, ...)` or `fuse(V1 ⊗ V2 ⊗ ...)` returns an elementary space that is
186-
isomorphic to `V1 ⊗ V2 ⊗ ...`, in the sense that a unitary tensor map can be constructed between
187-
those spaces, e.g. from `W = V1 ⊗ V2 ⊗ ...` to `V = fuse(V1 ⊗ V2 ⊗ ...)`. The function `flip(V1)`
188-
returns a space that is isomorphic to `V1` but has `isdual(flip(V1)) == isdual(V1')`, i.e. if
189-
`V1` is a normal space than `flip(V1)` is a dual space. Again, isomorphism here implies that
190-
a unitary map (but there is no canonical choice) can be constructed between both spaces. `flip(V1)`
191-
is different from `dual(V1)` in the case of [`RepresentationSpace`](@ref). It is useful to
192-
flip a tensor index from a ket to a bra (or vice versa), by contracting that index with a unitary
193-
map from `V1` to `map(V1)`. We refer to `[Index operations](@ref)` for further information.
194-
Some examples
180+
Some more convenience functions are provided for the euclidean spaces
181+
[`CartesianSpace`](@ref) and [`ComplexSpace`](@ref), as well as for
182+
[`RepresentationSpace`](@ref) discussed in the next section. All functions below that act
183+
on more than a single elementary space, are only defined when the different spaces are of
184+
the same concrete subtype `S<:ElementarySpace`
185+
186+
The function `fuse(V1, V2, ...)` or `fuse(V1 ⊗ V2 ⊗ ...)` returns an elementary space that
187+
is isomorphic to `V1 ⊗ V2 ⊗ ...`, in the sense that a unitary tensor map can be constructed
188+
between those spaces, e.g. from `W = V1 ⊗ V2 ⊗ ...` to `V = fuse(V1 ⊗ V2 ⊗ ...)`. The
189+
function `flip(V1)` returns a space that is isomorphic to `V1` but has
190+
`isdual(flip(V1)) == isdual(V1')`, i.e. if `V1` is a normal space than `flip(V1)` is a dual
191+
space. Again, isomorphism here implies that a unitary map (but there is no canonical
192+
choice) can be constructed between both spaces. `flip(V1)` is different from `dual(V1)` in
193+
the case of [`RepresentationSpace`](@ref). It is useful to flip a tensor index from a ket
194+
to a bra (or vice versa), by contracting that index with a unitary map from `V1` to
195+
`flip(V1)`. We refer to `[Index operations](@ref)` for further information. Some examples:
195196
```@repl tensorkit
196197
fuse(ℝ^5, ℝ^3)
197198
fuse(ℂ^3, (ℂ^5)', ℂ^2)
198199
flip(ℂ^4)
199200
```
200201

201202
We also define the direct sum `V1` and `V2` as `V1 ⊕ V2`, where `` is obtained by typing
202-
`\oplus`+TAB. This is possible only if `isdual(V1) == isdual(V2)`. With a little pun on Julia
203-
Base, `oneunit` applied to an elementary space (in the value or type domain) returns the one-dimensional
204-
space, which is isomorphic to the scalar field of the spaceitself. Some examples illustrate
205-
this better
203+
`\oplus`+TAB. This is possible only if `isdual(V1) == isdual(V2)`. With a little pun on
204+
Julia Base, `oneunit` applied to an elementary space (in the value or type domain) returns
205+
the one-dimensional space, which is isomorphic to the scalar field of the spaceitself. Some
206+
examples illustrate this better
206207
```@repl tensorkit
207208
ℝ^5 ⊕ ℝ^3
208209
ℂ^5 ⊕ ℂ^3
@@ -214,13 +215,13 @@ oneunit((ℂ^3)')
214215
(ℂ^5)' ⊕ oneunit((ℂ^5)')
215216
```
216217

217-
For two spaces `V1` and `V2`, `min(V1,V2)` returns the space with the smallest dimension, whereas
218-
`max(V1,V2)` returns the space with the largest dimension, as illustrated by
218+
For two spaces `V1` and `V2`, `min(V1,V2)` returns the space with the smallest dimension,
219+
whereas `max(V1,V2)` returns the space with the largest dimension, as illustrated by
219220
```@repl tensorkit
220221
min(ℝ^5, ℝ^3)
221222
max(ℂ^5, ℂ^3)
222223
max(ℂ^5, (ℂ^3)')
223224
```
224225
Again, we impose `isdual(V1) == isdual(V2)`. Again, the use of these methods is to construct
225-
unitary or isometric tensors that map between different spaces, which will be elaborated upon
226-
in the section on Tensors
226+
unitary or isometric tensors that map between different spaces, which will be elaborated
227+
upon in the section on Tensors.

test/runtests.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ using TupleTools
99
using TupleTools: StaticLength
1010

1111
smallset(::Type{ZNIrrep{N}}) where {N} = map(ZNIrrep{N}, 1:N)
12-
smallset(::Type{CU₁}) = map(t->CU₁(t[1],t[2]), [(0,0),(0,1),(1//2,2),(1,2),(3//2,2),(2,2),(5//2,2),(3,2),(7//2,2),(4,2),(9//2,2),(5,2)])
12+
smallset(::Type{CU₁}) =
13+
map(t->CU₁(t[1],t[2]), [(0,0), (0,1), (1//2,2), (1,2), (3//2,2), (2,2), (5//2,2),
14+
(3,2), (7//2,2), (4,2), (9//2,2), (5,2)])
1315
smallset(::Type{U₁}) = map(U₁, -10:10)
1416
smallset(::Type{SU₂}) = map(SU₂, 1//2:1//2:2) # no zero, such that always non-trivial
15-
smallset(::Type{ProductSector{Tuple{G1,G2}}}) where {G1,G2} = rand([i × j for i in smallset(G1), j in smallset(G2)], 5)
17+
smallset(::Type{ProductSector{Tuple{G1,G2}}}) where {G1,G2} =
18+
rand([i × j for i in smallset(G1), j in smallset(G2) if dim(i)*dim(j) <= 6], 5)
1619

1720
randsector(::Type{ZNIrrep{N}}) where {N} = rand(smallset(ZNIrrep{N}))
1821
randsector(::Type{CU₁}) = rand(smallset(CU₁))
1922
randsector(::Type{U₁}) = rand(smallset(U₁))
2023
randsector(::Type{SU₂}) = rand(smallset(SU₂))
2124
randsector(::Type{ProductSector{Tuple{G1,G2}}}) where {G1,G2} =
22-
randsector(G1) × randsector(G2)
25+
rand([i × j for i in smallset(G1), j in smallset(G2) if dim(i)*dim(j) <= 6])
2326
randsector(::Type{ProductSector{Tuple{G1,G2,G3}}}) where {G1,G2,G3} =
2427
randsector(G1) × randsector(G2) × randsector(G3)
25-
# special case: make sure dimensions are not too big
26-
randsector(P::Type{SU₂×SU₂}) =
27-
rand(collect(i × j for i in map(SU₂, 1//2:1//2:1), j in map(SU₂, 1//2:1//2:1)))
2828

2929
include("sectors.jl")
3030
include("spaces.jl")

0 commit comments

Comments
 (0)