Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs update I #101

Merged
merged 11 commits into from
Jan 26, 2024
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ Depth = 3
## Library outline

```@contents
Pages = ["lib/spaces.md","lib/sectors.md","lib/tensors.md"]
Pages = ["lib/sectors.md","lib/spaces.md","lib/tensors.md"]
Depth = 2
```
49 changes: 28 additions & 21 deletions docs/src/lib/sectors.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Symmetry sectors an fusion trees
# Symmetry sectors and fusion trees

```@meta
CurrentModule = TensorKit
Expand All @@ -11,10 +11,12 @@ SectorValues
FusionStyle
BraidingStyle
AbstractIrrep
Trivial
ZNIrrep
U1Irrep
SU2Irrep
CU1Irrep
ProductSector
FermionParity
FibonacciAnyon
FusionTree
Expand Down Expand Up @@ -42,27 +44,32 @@ TensorKit.vertex_ind2label
⊠(::Sector, ::Sector)
```

## Methods for manipulating fusion trees or pairs of fusion-splitting trees
The main method for manipulating a fusion-splitting tree pair is
```@docs
braid(f1::FusionTree{G}, f2::FusionTree{G}, levels1::IndexTuple, levels2::IndexTuple,
p1::IndexTuple{N₁}, p2::IndexTuple{N₂}) where {G<:Sector,N₁,N₂}
```
which, for `FusionStyle(G) isa SymmetricBraiding`, simplifies to
```@docs
permute(f1::FusionTree{G}, f2::FusionTree{G},
p1::IndexTuple{N₁}, p2::IndexTuple{N₂}) where {G<:Sector,N₁,N₂}
```
These operations are implemented by composing the following more elementary manipulations
## Methods for manipulating fusion trees

For manipulating single fusion trees, the following internal methods are defined:
```@docs
braid(f::FusionTree{G,N}, levels::NTuple{N,Int}, p::NTuple{N,Int}) where {G<:Sector, N}
permute(f::FusionTree{G,N}, p::NTuple{N,Int}) where {G<:Sector, N}
TensorKit.repartition
TensorKit.artin_braid
insertat
split
merge
elementary_trace
planar_trace(f::FusionTree{I,N}, q1::IndexTuple{N₃}, q2::IndexTuple{N₃}) where {I<:Sector,N,N₃}
artin_braid
braid(f::FusionTree{I,N}, levels::NTuple{N,Int}, p::NTuple{N,Int}) where {I<:Sector,N}
permute(f::FusionTree{I,N}, p::NTuple{N,Int}) where {I<:Sector,N}
```
Finally, there are some additional manipulations for internal use

These can be composed to manipulate fusion-splitting tree pairs, for which the following
methods are defined:

```@docs
TensorKit.insertat
TensorKit.split
TensorKit.merge
bendright
bendleft
foldright
foldleft
cycleclockwise
cycleanticlockwise
repartition
transpose
braid(f₁::FusionTree{I}, f₂::FusionTree{I}, levels1::IndexTuple, levels2::IndexTuple, p1::IndexTuple{N₁}, p2::IndexTuple{N₂}) where {I<:Sector,N₁,N₂}
permute(f₁::FusionTree{I}, f₂::FusionTree{I}, p1::IndexTuple{N₁}, p2::IndexTuple{N₂}) where {I<:Sector,N₁,N₂}
```
92 changes: 85 additions & 7 deletions docs/src/lib/tensors.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,23 @@ CurrentModule = TensorKit

## Type hierarchy

The type hierarchy of tensors is as follows:

```@docs
AbstractTensorMap
AbstractTensor
TensorMap
AdjointTensorMap
BraidingTensor
```

Some aliases are provided for convenience:

```@docs
AbstractTensor
Tensor
TrivialTensorMap
TrivialTensor
```

## Specific `TensorMap` constructors
Expand All @@ -22,20 +34,86 @@ unitary
isometry
```

Additionally, several special-purpose methods exist to generate data according to specific distributions:

```@docs
randuniform
randnormal
randisometry
```

## Accessing properties and data

The following methods exist to obtain type information:

```@docs
spacetype
sectortype
storagetype
tensormaptype
```

To obtain information about the indices, you can use:
```@docs
domain
codomain
space
numin
numout
numind
codomainind
domainind
allind
```

To obtain information about the data, the following methods exist:
```@docs
blocksectors
blockdim
block
blocks
fusiontrees
hasblock
```

## `TensorMap` operations

The operations that can be performed on a `TensorMap` can be organized into *index
manipulations*, *(planar) traces* and *(planar) contractions*.

### Index manipulations

A general index manipulation of a `TensorMap` object can be built up by considering some
transformation of the fusion trees, along with a permutation of the stored data. They come
in three flavours, which are either of the type `transform(!)` which are exported, or of the
type `add_transform!`, for additional expert-mode options that allows for addition and
scaling, as well as the selection of a custom backend.

```@docs
permute(t::TensorMap{S}, p1::IndexTuple, p2::IndexTuple) where {S}
permute!
braid
braid!
permute(t::AbstractTensorMap{S}, (p₁, p₂)::Index2Tuple{N₁,N₂}; copy::Bool=false) where {S,N₁,N₂}
braid(t::AbstractTensorMap{S}, (p₁, p₂)::Index2Tuple, levels::IndexTuple; copy::Bool=false) where {S}
transpose
twist
```
```@docs
permute!(tdst::AbstractTensorMap{S,N₁,N₂}, tsrc::AbstractTensorMap{S}, p::Index2Tuple{N₁,N₂}) where {S,N₁,N₂}
braid!
transpose!
twist!
add!
trace!
contract!
```
```@docs
add_permute!
add_braid!
add_transpose!
add_transform!
```

### Traces and contractions

```@docs
trace_permute!
contract!
```

## `TensorMap` factorizations

Expand Down
2 changes: 1 addition & 1 deletion docs/src/man/tensors.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ as the internal structure of the representation space when the corresponding sec
abelian sectors are `Irrep[SU₂]` and `Irrep[CU₁]`, for which the internal structure is the
natural one.

There are some tools available to facilate finding the proper range of sector `c` in space
There are some tools available to facilitate finding the proper range of sector `c` in space
`V`, namely `axes(V, c)`. This also works on a `ProductSpace`, with a tuple of sectors. An
example
```@repl tensors
Expand Down
8 changes: 4 additions & 4 deletions src/TensorKit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export FusionStyle, UniqueFusion, MultipleFusion, MultiplicityFreeFusion,
SimpleFusion, GenericFusion
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

Expand Down Expand Up @@ -50,9 +51,8 @@ export fℤ₂, fU₁, fSU₂
export ℤ₂Space, ℤ₃Space, ℤ₄Space, U₁Space, CU₁Space, SU₂Space

# tensor maps
export domain, codomain, numind, numout, numin, spacetype, storagetype, scalartype
export domainind, codomainind, allind
export tensormaptype
export domain, codomain, numind, numout, numin, domainind, codomainind, allind
export spacetype, sectortype, storagetype, scalartype, tensormaptype
export blocksectors, blockdim, block, blocks

# random methods for constructor
Expand All @@ -71,7 +71,7 @@ export leftorth, rightorth, leftnull, rightnull,
leftorth!, rightorth!, leftnull!, rightnull!,
tsvd!, tsvd, eigen, eigen!, eig, eig!, eigh, eigh!, exp, exp!,
isposdef, isposdef!, ishermitian, sylvester
export braid!, permute!, transpose!, twist!
export braid, braid!, permute, permute!, transpose, transpose!, twist, twist!
export catdomain, catcodomain

export OrthogonalFactorizationAlgorithm, QR, QRpos, QL, QLpos, LQ, LQpos, RQ, RQpos,
Expand Down
23 changes: 23 additions & 0 deletions src/auxiliary/random.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
"""
randuniform([::Type{T}=Float64], dims::Dims{N}) -> Array{T,N}

Create an array of size `dims` with random entries uniformly distributed in the allowed
values of `T`.
Copy link
Owner

Choose a reason for hiding this comment

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

uniform is typically understood to be the uniform distribution on [0,1]. It is definitely not uniform over all values of T (which would not even be well defined).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah I got confused by not reading the docstring of rand far enough:

help?> rand
search: rand randn transcode macroexpand @macroexpand @macroexpand1

  rand([rng=default_rng()], [S], [dims...])

  Pick a random element or array of random elements from the set of values
  specified by S; S can be

    •  an indexable collection (for example 1:9 or ('x', "y", :z)),

    •  an AbstractDict or AbstractSet object,

    •  a string (considered as a collection of characters), or

    •  a type: the set of values to pick from is then equivalent to
       typemin(S):typemax(S) for integers (this is not applicable to
       BigInt), to [0, 1) for floating point numbers and to [0, 1)+i[0,
       1) for complex floating point numbers;

I am wondering though if this method really makes sense, as it is just a copy of rand

Copy link
Owner

Choose a reason for hiding this comment

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

Maybe not, but this also applies to randnormal which is just equal to randn.


See also [`randnormal`](@ref), [`randisometry`](@ref) and[`randhaar`](@ref).
"""
randuniform(dims::Base.Dims) = randuniform(Float64, dims)
randuniform(::Type{T}, dims::Base.Dims) where {T<:Number} = rand(T, dims)

"""
randnormal([::Type{T}=Float64], dims::Dims{N}) -> Array{T,N}

Create an array of size `dims` with random entries normally distributed.
Copy link
Owner

Choose a reason for hiding this comment

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

The normal distribution with mean zero and standard deviation one is typically called the standard normal distribution, so maybe we should try to get this in.


See also [`randuniform`](@ref), [`randisometry`](@ref) and[`randhaar`](@ref).
"""
randnormal(dims::Base.Dims) = randnormal(Float64, dims)
randnormal(::Type{T}, dims::Base.Dims) where {T<:Number} = randn(T, dims)

"""
randisometry([::Type{T}=Float64], dims::Dims{2}) -> Array{T,2}
randhaar([::Type{T}=Float64], dims::Dims{2}) -> Array{T,2}

Create a random isometry of size `dims`.
Copy link
Owner

Choose a reason for hiding this comment

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

I guess here you can mention the Haar measure or uniform measure over the compact manifold of isometric matrices.


See also [`randuniform`](@ref) and [`randnormal`](@ref).
"""
randisometry(dims::Base.Dims{2}) = randisometry(Float64, dims)
function randisometry(::Type{T}, dims::Base.Dims{2}) where {T<:Number}
return dims[1] >= dims[2] ? _leftorth!(randnormal(T, dims), QRpos(), 0)[1] :
Expand Down
19 changes: 17 additions & 2 deletions src/fusiontrees/manipulations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,14 @@ function planar_trace(f₁::FusionTree{I}, f₂::FusionTree{I},
return newtrees
end

"""
planar_trace(f::FusionTree{I,N}, q1::IndexTuple{N₃}, q2::IndexTuple{N₃}) where {I<:Sector,N,N₃}
-> <:AbstractDict{FusionTree{I,N-2*N₃}, <:Number}

Perform a planar trace of the uncoupled indices of the fusion tree `f` at `q1` with those at
`q2`, which are required to be pairwise neighbouring. The result is returned as a dictionary
Copy link
Owner

Choose a reason for hiding this comment

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

pairwise neighbouring might be a bit confusing, as there are different ways in which traces of several indices can be planar:

It could for example be that q2[1] = q1[1]+1 and q2[2] = q1[2]+1, but also that q2[2] = q1[2]-3 , namely with q2[2] = q2[1] +1 = q1[1]+2 = q1[2] + 3

of output trees and corresponding coefficients.
"""
function planar_trace(f::FusionTree{I,N},
q1::IndexTuple{N₃}, q2::IndexTuple{N₃}) where {I<:Sector,N,N₃}
u = one(I)
Expand Down Expand Up @@ -652,6 +660,13 @@ function planar_trace(f::FusionTree{I,N},
end

# trace two neighbouring indices of a single fusion tree
"""
elementary_trace(f::FusionTree{I,N}, i) where {I<:Sector,N} -> <:AbstractDict{FusionTree{I,N-2}, <:Number}

Perform an elementary trace of neighbouring uncoupled indices `i` and
`i+1` on a fusion tree `f`, and returns the result as a dictionary of output trees and
corresponding coefficients.
"""
function elementary_trace(f::FusionTree{I,N}, i) where {I<:Sector,N}
(N > 1 && 1 <= i <= N) ||
throw(ArgumentError("Cannot trace outputs i=$i and i+1 out of only $N outputs"))
Expand Down Expand Up @@ -745,7 +760,7 @@ end
# -> manipulations that depend on a braiding
# -> requires both Fsymbol and Rsymbol
"""
artin_braid(f::FusionTree, i; inv::Bool = false) -> <:AbstractDict{typeof(t), <:Number}
artin_braid(f::FusionTree, i; inv::Bool = false) -> <:AbstractDict{typeof(f), <:Number}

Perform an elementary braid (Artin generator) of neighbouring uncoupled indices `i` and
`i+1` on a fusion tree `f`, and returns the result as a dictionary of output trees and
Expand All @@ -755,7 +770,7 @@ The keyword `inv` determines whether index `i` will braid above or below index `
applying `artin_braid(f′, i; inv = true)` to all the outputs `f′` of
`artin_braid(f, i; inv = false)` and collecting the results should yield a single fusion
tree with non-zero coefficient, namely `f` with coefficient `1`. This keyword has no effect
if `BraidingStyle(sectortype(f)) isa SymmetricBraiding`.
if `BraidingStyle(sectortype(f)) isa SymmetricBraiding`.
"""
function artin_braid(f::FusionTree{I,N}, i; inv::Bool=false) where {I<:Sector,N}
1 <= i < N ||
Expand Down
2 changes: 1 addition & 1 deletion src/sectors/irreps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Base.isless(c1::ZNIrrep{N}, c2::ZNIrrep{N}) where {N} = isless(c1.n, c2.n)
U1Irrep(j::Real)
Irrep[U₁](j::Real)

Represents irreps of the group ``U₁```. The irrep is labelled by a charge, which should be
Represents irreps of the group ``U₁``. The irrep is labelled by a charge, which should be
an integer for a linear representation. However, it is often useful to allow half integers
to represent irreps of ``U₁`` subgroups of ``SU₂``, such as the Sz of spin-1/2 system.
Hence, the charge is stored as a `HalfInt` from the package HalfIntegers.jl, but can be
Expand Down
7 changes: 7 additions & 0 deletions src/sectors/product.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
#==============================================================================#
const SectorTuple = Tuple{Vararg{Sector}}

"""
ProductSector{T<:SectorTuple}

Represents the Deligne tensor product of sectors. The type parameter `T` is a tuple of the
component sectors. The recommended way to construct a `ProductSector` is using the
[`deligneproduct`](@ref) (`⊠`) operator on the components.
"""
struct ProductSector{T<:SectorTuple} <: Sector
sectors::T
end
Expand Down
12 changes: 8 additions & 4 deletions src/sectors/sectors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,20 @@
Base.values(::Type{I}) where {I<:Sector} = SectorValues{I}()

# Define a sector for ungraded vector spaces
struct Trivial <: Sector
end
"""
Trivial

Singleton type to represent the trivial sector, i.e. the unit element of the group
Copy link
Owner

Choose a reason for hiding this comment

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

This can get a bit confusing. The trivial group has only a unit element, but Trivial() typically (in our use case) refers to the only irrep of the trivial group, which is of course the trivial irrep and acts as the unit element in the category Rep[trivial group]. But I also don't immediately know the best way to phrase this.

Copy link
Owner

Choose a reason for hiding this comment

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

Maybe it could also be mentioned that this is the unit object of the category Vect of ordinary vector spaces (not as the first sentence).

(category) with a single object.
"""
struct Trivial <: Sector end
Base.show(io::IO, ::Trivial) = print(io, "Trivial()")

Base.IteratorSize(::Type{SectorValues{Trivial}}) = HasLength()
Base.length(::SectorValues{Trivial}) = 1
Base.iterate(::SectorValues{Trivial}, i=false) = return i ? nothing : (Trivial(), true)
function Base.getindex(::SectorValues{Trivial}, i::Int)
return i == 1 ? Trivial() :
throw(BoundsError(values(Trivial), i))
return i == 1 ? Trivial() : throw(BoundsError(values(Trivial), i))

Check warning on line 78 in src/sectors/sectors.jl

View check run for this annotation

Codecov / codecov/patch

src/sectors/sectors.jl#L78

Added line #L78 was not covered by tests
end
findindex(::SectorValues{Trivial}, c::Trivial) = 1

Expand Down
Loading
Loading