Skip to content

Commit

Permalink
1) Change values for SimpleAbelianQuantumNumber;
Browse files Browse the repository at this point in the history
2) Add `value` for `SimpleAbelianQuantumNumber` and `AbelianQuantumNumberProd`;
3) Fix a bug of showing `AbelianQuantumNumberProd`.
  • Loading branch information
waltergu committed Dec 13, 2024
1 parent c0f9321 commit bb13f1c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 27 deletions.
79 changes: 64 additions & 15 deletions src/QuantumNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ using DataStructures: OrderedDict
using HalfIntegers: HalfInt
using LinearAlgebra: norm
using Printf: @printf
using QuantumLattices: id, value
using QuantumLattices: id
using Random: seed!
using ..Toolkit: VectorSpace, VectorSpaceCartesian, VectorSpaceDirectProducted, VectorSpaceDirectSummed, VectorSpaceStyle, efficientoperations, subscript

import ..QuantumLattices: , , , decompose, dimension, rank
import ..QuantumLattices: , , , decompose, dimension, rank, value
import ..Toolkit: shape

export Abelian, AbelianQuantumNumber, AbelianQuantumNumberProd, AbelianGradedSpace, AbelianGradedSpaceProd, AbelianGradedSpaceSum, Graded, Momenta, RepresentationSpace, SimpleAbelianQuantumNumber
Expand All @@ -28,8 +28,6 @@ abstract type AbelianQuantumNumber end
@inline Base.isequal(qn₁::QN, qn₂::QN) where {QN<:AbelianQuantumNumber} = isequal(efficientoperations, qn₁, qn₂)
@inline Base.:<(qn₁::QN, qn₂::QN) where {QN<:AbelianQuantumNumber} = <(efficientoperations, qn₁, qn₂)
@inline Base.isless(qn₁::QN, qn₂::QN) where {QN<:AbelianQuantumNumber} = isless(efficientoperations, qn₁, qn₂)
@inline Base.hash(qn::AbelianQuantumNumber, h::UInt) = hash(values(qn), h)
@inline Base.show(io::IO, ::Type{T}) where {T<:AbelianQuantumNumber} = @printf io "%s" nameof(T)
@inline Base.iterate(qn::AbelianQuantumNumber) = (qn, nothing)
@inline Base.iterate(::AbelianQuantumNumber, ::Nothing) = nothing

Expand Down Expand Up @@ -90,11 +88,26 @@ Overloaded `+` operator for `AbelianQuantumNumber`.
Abstract type of simple Abelian quantum numbers. That is, it contains only one label.
"""
abstract type SimpleAbelianQuantumNumber <: AbelianQuantumNumber end
@inline Base.values(qn::SimpleAbelianQuantumNumber) = getfield(qn, 1)
@inline Base.show(io::IO, qn::SimpleAbelianQuantumNumber) = @printf io "%s(%s)" typeof(qn) values(qn)
@inline Base.hash(qn::SimpleAbelianQuantumNumber, h::UInt) = hash(value(qn), h)
@inline Base.show(io::IO, qn::SimpleAbelianQuantumNumber) = @printf io "%s(%s)" typeof(qn) value(qn)
@inline Base.show(io::IO, ::Type{T}) where {T<:SimpleAbelianQuantumNumber} = @printf io "%s" nameof(T)
@inline Base.zero(::Type{QN}) where {QN<:SimpleAbelianQuantumNumber} = QN(zero(fieldtype(QN, 1)))
@inline periods(::Type{QN}) where {QN<:SimpleAbelianQuantumNumber} = (period(QN),)

"""
value(qn::SimpleAbelianQuantumNumber) -> Number
Get the value of a simple Abelian quantum number.
"""
@inline value(qn::SimpleAbelianQuantumNumber) = getfield(qn, 1)

"""
values(qn::SimpleAbelianQuantumNumber) -> Tuple{Number}
Get the value of a simple Abelian quantum number and return it as the sole element of a tuple.
"""
@inline Base.values(qn::SimpleAbelianQuantumNumber) = (value(qn),)

"""
+(qn₁::QN, qn₂::QN, qns::QN...) where {QN<:SimpleAbelianQuantumNumber} -> QN
Expand All @@ -103,7 +116,7 @@ Overloaded `+` operator for `SimpleAbelianQuantumNumber`.
!!! note
To ensure type stability, two `SimpleAbelianQuantumNumber` can be added together if and only if they are of the same type.
"""
@inline Base.:+(qn₁::QN, qn₂::QN, qns::QN...) where {QN<:SimpleAbelianQuantumNumber} = QN(sum(map(values, (qn₁, qn₂, qns...))))
@inline Base.:+(qn₁::QN, qn₂::QN, qns::QN...) where {QN<:SimpleAbelianQuantumNumber} = QN(sum(map(value, (qn₁, qn₂, qns...))))

"""
-(qn::SimpleAbelianQuantumNumber) -> typeof(qn)
Expand All @@ -114,8 +127,8 @@ Overloaded `-` operator for `SimpleAbelianQuantumNumber`.
!!! note
To ensure type stability, a `SimpleAbelianQuantumNumber` can be subtracted by another `SimpleAbelianQuantumNumber` if and only if they are of the same type.
"""
@inline Base.:-(qn::SimpleAbelianQuantumNumber) = typeof(qn)(-values(qn))
@inline Base.:-(qn₁::QN, qn₂::QN) where {QN<:SimpleAbelianQuantumNumber} = QN(values(qn₁)-values(qn₂))
@inline Base.:-(qn::SimpleAbelianQuantumNumber) = typeof(qn)(-value(qn))
@inline Base.:-(qn₁::QN, qn₂::QN) where {QN<:SimpleAbelianQuantumNumber} = QN(value(qn₁)-value(qn₂))

"""
period(qn::SimpleAbelianQuantumNumber) -> Number
Expand Down Expand Up @@ -187,14 +200,18 @@ Deligne tensor product of simple Abelian quantum numbers.
struct AbelianQuantumNumberProd{T<:Tuple{Vararg{SimpleAbelianQuantumNumber}}} <: AbelianQuantumNumber
contents::T
end
@inline Base.values(qn::AbelianQuantumNumberProd) = map(values, qn.contents)
@inline Base.hash(qn::AbelianQuantumNumberProd, h::UInt) = hash(values(qn), h)
@inline Base.show(io::IO, qn::AbelianQuantumNumberProd) = @printf io "Abelian[%s]%s" join(fieldtypes(fieldtype(typeof(qn), :contents)), "") values(qn)
@inline Base.show(io::IO, ::Type{T}) where {T<:AbelianQuantumNumberProd} = @printf io "%s" join(fieldtypes(fieldtype(T, :contents)), "")
@inline Base.zero(::Type{AbelianQuantumNumberProd{T}}) where {T<:Tuple{Vararg{SimpleAbelianQuantumNumber}}} = AbelianQuantumNumberProd(map(zero, fieldtypes(T)))
@inline Base.length(qn::AbelianQuantumNumberProd) = rank(qn)
@inline Base.firstindex(::AbelianQuantumNumberProd) = 1
@inline Base.lastindex(qn::AbelianQuantumNumberProd) = length(qn)
@inline Base.getindex(qn::AbelianQuantumNumberProd, i::Integer) = qn.contents[i]
@inline periods(::Type{AbelianQuantumNumberProd{T}}) where {T<:Tuple{Vararg{SimpleAbelianQuantumNumber}}} = map(period, fieldtypes(T))

"""
AbelianQuantumNumberProd(contents::SimpleAbelianQuantumNumber...)
AbelianQuantumNumberProd(contents::Tuple{Vararg{SimpleAbelianQuantumNumber}})
Construct a Deligne tensor product of simple Abelian quantum numbers.
"""
@inline AbelianQuantumNumberProd(contents::SimpleAbelianQuantumNumber...) = AbelianQuantumNumberProd(contents)

"""
Expand All @@ -206,6 +223,36 @@ Construct a Deligne tensor product of simple Abelian quantum numbers by their va
@inline AbelianQuantumNumberProd{T}(vs::Vararg{Number, N}) where {N, T<:NTuple{N, SimpleAbelianQuantumNumber}} = AbelianQuantumNumberProd{T}(vs)
@inline AbelianQuantumNumberProd{T}(vs::NTuple{N, Number}) where {N, T<:NTuple{N, SimpleAbelianQuantumNumber}} = AbelianQuantumNumberProd(map((T, v)->T(v), fieldtypes(T), vs))

"""
values(qn::AbelianQuantumNumberProd) -> NTuple{rank(qn), Number}
Get the values of the simple Abelian quantum numbers in a Deligne tensor product.
"""
@inline Base.values(qn::AbelianQuantumNumberProd) = map(value, qn.contents)

"""
value(qn::AbelianQuantumNumberProd, i::Integer) -> Number
Get the value of the ith simple Abelian quantum number in a Deligne tensor product.
"""
@inline value(qn::AbelianQuantumNumberProd, i::Integer) = values(qn)[i]

"""
length(qn::AbelianQuantumNumberProd) -> Int
Get the length of a Deligne tensor product.
"""
@inline Base.length(qn::AbelianQuantumNumberProd) = rank(qn)
@inline Base.firstindex(::AbelianQuantumNumberProd) = 1
@inline Base.lastindex(qn::AbelianQuantumNumberProd) = length(qn)

"""
getindex(qn::AbelianQuantumNumberProd, i::Integer) -> SimpleAbelianQuantumNumber
Get the ith simple Abelian quantum number in a Deligne tensor product.
"""
@inline Base.getindex(qn::AbelianQuantumNumberProd, i::Integer) = qn.contents[i]

"""
rank(qn::AbelianQuantumNumberProd) -> Int
rank(::Type{<:AbelianQuantumNumberProd}) -> Int
Expand Down Expand Up @@ -431,11 +478,13 @@ end
function Base.show(io::IO, gs::AbelianGradedSpace)
@printf io "Graded{%s}(" eltype(gs)
for (i, qn) in enumerate(keys(gs.contents))
@printf io "%s=>%s" values(qn) dimension(gs, i)
@printf io "%s=>%s" _value_(qn) dimension(gs, i)
i<length(gs) && @printf io "%s" ", "
end
@printf io "%s%s" ")" gs.dual ? "'" : ""
end
@inline _value_(qn::SimpleAbelianQuantumNumber) = value(qn)
@inline _value_(qn::AbelianQuantumNumberProd) = values(qn)

"""
const Graded = AbelianGradedSpace
Expand Down
24 changes: 12 additions & 12 deletions test/QuantumNumbers.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Base.Iterators: product
using QuantumLattices: , , , decompose, dimension, rank
using QuantumLattices: , , , decompose, dimension, rank, value
using QuantumLattices.QuantumNumbers

@testset "AbelianQuantumNumber" begin
n = (1)
@test values(n) == 1
@test value(n)==1 && values(n)==(1,)
@test n==(1) && isequal(n, (1))
@test n<(2) && isless(n, (2))
@test periods(n) == periods(typeof(n)) == (Inf,)
Expand All @@ -21,7 +21,7 @@ using QuantumLattices.QuantumNumbers

sz = 𝕊ᶻ(1/2)
sp = n sz
@test values(sp) == (1, 1/2)
@test values(sp) == (1, 1/2) && value(sp, 1)==1 && value(sp, 2)==1/2
@test sp == Abelian[ℕ 𝕊ᶻ](1, 1/2) == Abelian[ℕ 𝕊ᶻ]((1, 1/2)) == AbelianQuantumNumberProd(n, sz)
@test hash(sp, UInt(1)) == hash((n.charge, sz.charge), UInt(1))
@test string(sp) == "Abelian[ℕ ⊠ 𝕊ᶻ](1, 1/2)"
Expand Down Expand Up @@ -94,15 +94,15 @@ end
@test collect(pairs(qns, dimension))==[(1)=>4, (2)=>12, (3)=>1, (4)=>2] && collect(pairs(qns, range))==[(1)=>1:4, (2)=>5:16, (3)=>17:17, (4)=>18:19]
@test [findindex(i, qns, guess) for (i, guess) in zip(1:dimension(qns), [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4])] == [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 4]

qns = qns'
@test string(qns)=="Graded{ℕ}(1=>4, 2=>12, 3=>1, 4=>2)'"
@test qns[1]==(-1) && qns[2]==(-2) && qns[3]==(-3) && qns[4]==(-4)
@test qns[2:-1:1] == qns[[(-2), (-1)]] == Graded{ℕ}(1=>4, 2=>12; dual=true)
@test (-1)qns && (-2)qns && (-3)qns && (-4)qns && (-5)qns
@test dimension(qns)==19 && dimension(qns, 1)==dimension(qns, (-1))==4 && dimension(qns, 2)==dimension(qns, (-2))==12 && dimension(qns, 3)==dimension(qns, (-3))==1 && dimension(qns, 4)==dimension(qns, (-4))==2
@test range(qns, 1)==range(qns, (-1))==1:4 && range(qns, 2)==range(qns, (-2))==5:16 && range(qns, 3)==range(qns, (-3))==17:17 && range(qns, 4)==range(qns, (-4))==18:19
@test cumsum(qns, 0)==0 && cumsum(qns, 1)==cumsum(qns, (-1))==4 && cumsum(qns, 2)==cumsum(qns, (-2))==16 && cumsum(qns, 3)==cumsum(qns, (-3))==17 && cumsum(qns, 4)==cumsum(qns, (-4))==19
@test collect(pairs(qns, dimension))==[(-1)=>4, (-2)=>12, (-3)=>1, (-4)=>2] && collect(pairs(qns, range))==[(-1)=>1:4, (-2)=>5:16, (-3)=>17:17, (-4)=>18:19]
qns = AbelianGradedSpace([(1)𝕊ᶻ(1//2), (2)𝕊ᶻ(1//2), (3)𝕊ᶻ(1//2), (4)𝕊ᶻ(1//2)], [4, 12, 1, 2]; ordercheck=true, duplicatecheck=true, degeneracycheck=true)'
@test string(qns)=="Graded{ℕ ⊠ 𝕊ᶻ}((1, 1/2)=>4, (2, 1/2)=>12, (3, 1/2)=>1, (4, 1/2)=>2)'"
@test qns[1]==(-1)𝕊ᶻ(-1//2) && qns[2]==(-2)𝕊ᶻ(-1//2) && qns[3]==(-3)𝕊ᶻ(-1//2) && qns[4]==(-4)𝕊ᶻ(-1//2)
@test qns[2:-1:1] == qns[[(-2)𝕊ᶻ(-1//2), (-1)𝕊ᶻ(-1//2)]] == Graded{ℕ ⊠ 𝕊ᶻ}((1, 1/2)=>4, (2, 1/2)=>12; dual=true)
@test (-1)𝕊ᶻ(-1//2)qns && (-2)𝕊ᶻ(-1//2)qns && (-3)𝕊ᶻ(-1//2)qns && (-4)𝕊ᶻ(-1//2)qns && (-5)𝕊ᶻ(-1//2)qns
@test dimension(qns)==19 && dimension(qns, 1)==dimension(qns, (-1)𝕊ᶻ(-1//2))==4 && dimension(qns, 2)==dimension(qns, (-2)𝕊ᶻ(-1//2))==12 && dimension(qns, 3)==dimension(qns, (-3)𝕊ᶻ(-1//2))==1 && dimension(qns, 4)==dimension(qns, (-4)𝕊ᶻ(-1//2))==2
@test range(qns, 1)==range(qns, (-1)𝕊ᶻ(-1//2))==1:4 && range(qns, 2)==range(qns, (-2)𝕊ᶻ(-1//2))==5:16 && range(qns, 3)==range(qns, (-3)𝕊ᶻ(-1//2))==17:17 && range(qns, 4)==range(qns, (-4)𝕊ᶻ(-1//2))==18:19
@test cumsum(qns, 0)==0 && cumsum(qns, 1)==cumsum(qns, (-1)𝕊ᶻ(-1//2))==4 && cumsum(qns, 2)==cumsum(qns, (-2)𝕊ᶻ(-1//2))==16 && cumsum(qns, 3)==cumsum(qns, (-3)𝕊ᶻ(-1//2))==17 && cumsum(qns, 4)==cumsum(qns, (-4)𝕊ᶻ(-1//2))==19
@test collect(pairs(qns, dimension))==[(-1)𝕊ᶻ(-1//2)=>4, (-2)𝕊ᶻ(-1//2)=>12, (-3)𝕊ᶻ(-1//2)=>1, (-4)𝕊ᶻ(-1//2)=>2] && collect(pairs(qns, range))==[(-1)𝕊ᶻ(-1//2)=>1:4, (-2)𝕊ᶻ(-1//2)=>5:16, (-3)𝕊ᶻ(-1//2)=>17:17, (-4)𝕊ᶻ(-1//2)=>18:19]
@test [findindex(i, qns, guess) for (i, guess) in zip(1:dimension(qns), [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4])] == [1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 4]
end

Expand Down

0 comments on commit bb13f1c

Please sign in to comment.