Graded arrays
Graded spaces
gradedrange builds a graded space from sector => multiplicity pairs.
using GradedArrays: U1, gradedrange
g = gradedrange([U1(0) => 1, U1(1) => 2])3-element GradedOneTo{U1, …} with indices gradedrange([U1(0) => 1, U1(1) => 2]):
sectors: [U1(0), U1(1)]
1
2
3The total length of the space is 3, and sectors returns the list of sectors.
using GradedArrays: sectors
length(g), sectors(g)(3, U1[U1(0), U1(1)])GradedArrays.gradedrange — Function
gradedrange(xs::AbstractVector{<:Pair})Construct a non-dual graded range from sector => multiplicity pairs, keyed by anything Sector accepts, NamedTuple keys for sector products included. Wrap the result in dual for a dual axis.
Examples
gradedrange([U1(0) => 2, U1(1) => 3]) # non-dual
dual(gradedrange([U1(0) => 2, U1(1) => 3])) # dualGradedArrays.GradedOneTo — Type
GradedOneToA graded axis: a range carrying a sector for each of its blocks, as returned by gradedrange. Wrap it in dual for a dual axis.
GradedArrays.sectors — Function
sectors(g)The sector of each block of a graded axis, in block order.
Duality
A graded space carries a duality, and dual flips it.
using GradedArrays: dual, isdual
dg = dual(g)
isdual(g), isdual(dg)(false, true)conj is an alternative for dual.
conj(g) == dual(g)trueArrays over graded spaces
Array constructors accept graded spaces and return a GradedArray, which only stores the symmetry-allowed blocks.
a = randn(g, dual(g))3×3 GradedArray (codomain 2, domain 0):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Codomain Dim 2: dual(gradedrange([U1(0) => 1, U1(1) => 2]))
3×1 FusedGradedMatrix{Float64, U1, Vector{Float64}, …} with 1 stored block at sectors [U1(0)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 5, U1(1) => 2, U1(-1) => 2])
Domain Dim 1: fusedgradedrange([U1(0) => 1])
0.246305361930569
-0.004515426479395512
-0.30410279949849156
-0.2291972304387741
0.7403995461725066
─────────────────────
⋅
⋅
─────────────────────
⋅
⋅ zeros, ones, and fill work the same way.
zeros(g, dual(g))3×3 GradedArray (codomain 2, domain 0):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Codomain Dim 2: dual(gradedrange([U1(0) => 1, U1(1) => 2]))
3×1 FusedGradedMatrix{Float64, U1, Vector{Float64}, …} with 1 stored block at sectors [U1(0)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 5, U1(1) => 2, U1(-1) => 2])
Domain Dim 1: fusedgradedrange([U1(0) => 1])
0.0
0.0
0.0
0.0
0.0
───
⋅
⋅
───
⋅
⋅ fill(2.0, g, dual(g))3×3 GradedArray (codomain 2, domain 0):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Codomain Dim 2: dual(gradedrange([U1(0) => 1, U1(1) => 2]))
3×1 FusedGradedMatrix{Float64, U1, Vector{Float64}, …} with 1 stored block at sectors [U1(0)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 5, U1(1) => 2, U1(-1) => 2])
Domain Dim 1: fusedgradedrange([U1(0) => 1])
2.0
2.0
2.0
2.0
2.0
───
⋅
⋅
───
⋅
⋅ You can also specify an element type.
randn(ComplexF64, g, dual(g))3×3 GradedArray (codomain 2, domain 0):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Codomain Dim 2: dual(gradedrange([U1(0) => 1, U1(1) => 2]))
3×1 FusedGradedMatrix{ComplexF64, U1, Vector{ComplexF64}, …} with 1 stored block at sectors [U1(0)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 5, U1(1) => 2, U1(-1) => 2])
Domain Dim 1: fusedgradedrange([U1(0) => 1])
-0.07755053334598172 + 0.6486512472323949im
0.06603840097447106 - 0.4661221653521081im
-0.007822209954645597 + 0.01667349224092823im
-0.055275536427532 + 0.8973137754717658im
0.40320068044509566 - 0.17064096984563543im
─────────────────────────────────────────────
⋅
⋅
─────────────────────────────────────────────
⋅
⋅ Codomain and domain
A graded array partitions its indices into a codomain and a domain, and stores the block diagonal matrix corresponding to that bipartitioning. matricize fuses the codomain and domain according to a specified bipartitioning.
using TensorAlgebra: matricize
matricize(a, (1,), (2,))2×2 FusedGradedMatrix{Float64, U1, Vector{Float64}, …} with 2 stored blocks at sectors [U1(0), U1(1)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 1, U1(1) => 2])
Domain Dim 1: fusedgradedrange([U1(0) => 1, U1(1) => 2])
0.246305361930569 │ ⋅ ⋅
───────────────────┼────────────────────────────────────────────
⋅ │ -0.004515426479395512 -0.2291972304387741
⋅ │ -0.30410279949849156 0.7403995461725066You can specify the codomain/domain split in graded array constructors, where the domain is implicitly dualized. For example, randn((g,), (g,)) has axes (g, dual(g)) with one axis in the codomain and one in the domain.
b = randn((g,), (g,))3×3 GradedArray (codomain 1, domain 1):
Codomain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
Domain Dim 1: gradedrange([U1(0) => 1, U1(1) => 2])
2×2 FusedGradedMatrix{Float64, U1, Vector{Float64}, …} with 2 stored blocks at sectors [U1(0), U1(1)]:
Codomain Dim 1: fusedgradedrange([U1(0) => 1, U1(1) => 2])
Domain Dim 1: fusedgradedrange([U1(0) => 1, U1(1) => 2])
-2.434518773387828 │ ⋅ ⋅
────────────────────┼─────────────────────────────────────────
⋅ │ -0.9415058070239324 0.4544431964670878
⋅ │ 2.7060851208495182 0.3663025760372419axes(b) == axes(a)trueWhen printing, by convention domain axes are implicitly dual. The format and conventions are compatible with those of TensorKit.jl.
GradedArrays.GradedArray — Type
GradedArrayAn array over graded axes, storing only the symmetry-allowed blocks. Its legs are split into a codomain and a domain group, so it can also be read as a map between spaces, and it is stored as a block-diagonal matrix over the coupled sectors, with the codomain legs fused to its rows and the domain legs to its columns.
GradedArrays.FusedGradedMatrix — Type
FusedGradedMatrixThe block-diagonal matrix a graded array matricizes to, as returned by matricize. Its two axes are the fused codomain and domain.
GradedArrays.FusedGradedVector — Type
FusedGradedVectorA graded vector of per-sector values, as returned by the value-only factorizations svd_vals, eig_vals and eigh_vals.