Quantum numbers

Quantum numbers can be considered as the conserved labels for the bases of a Hilbert space when a quantum system hosts some symmetries. Here we only implement Abelian quantum numbers because non-Abelian ones are far more complicated yet much less used. In practice, quantum numbers can be integers or half integers, therefore, we use real numbers to denote them in this module for simplicity. Independent quantum numbers, such as the particle number and the spin z-component, can coexist at the same time. We use type AbelianNumber to represent the complete set of independent ones for a single basis of a Hilbert space, and type AbelianNumbers to represent the whole quantum numbers for the total bases.

AbelianNumber

The abstract type for the complete set of independent quantum numbers for a single basis.

Main features include:

  • function periods: get the periods of the quantum numbers
  • arithmetic operations: +, -, *, ^, ,
  • hashable: concrete instances can be used as keys for a dict or a set
  • iterable: concrete instances are iterable over their values
  • comparable: two concrete instances can be compared

For convenience, 3 kinds of quantum numbers are predefined in this module, i.e.

  • Sz: for spin z-component reserved systems
  • ParticleNumber: for particle number reserved systems
  • SpinfulParticle: for both particle number and spin-z component reserved systems

Users who want to define their own $Z_N$-like quantum numbers must handle the periodicity in the construction function, otherwise, wrong results will be get when arithmetic operations, such as + or -, are involved. It is recommended to use the macro @abeliannumber to define your own concrete AbelianNumbers.

AbelianNumbers

The whole quantum numbers for the total bases.

By design, a AbelianNumbers{QN} has one type parameter:

  • QN<:AbelianNumber: the type of the quantum numbers contained in it

And 3 attributes:

  • form::Char: Its form, whose value must be one of the followings
    • 'G': the general form, which has no restriction for its contents
    • 'U': the unitary form, which requires no duplicates in its contents
    • 'C': the canonical form, which requires both no duplicates and ascending-order in its contents
    Usually, G-formed and U-formed AbelianNumberses can be transformed to the corresponding C-formed ones by the sort function.
  • contents::Vector{QN}: The quantum numbers contained in it. To achieve high efficiency, it is required to be an homogenous array of a certain kind of concrete AbelianNumber.
  • indptr::Vector{Int}: The indptr of the quantum numbers contained in it, which is similar to the colptr attribute of a CSC sparse matrix and records the compression info of its contents.

Main features include:

  • function eltype: get the concrete type of the quantum numbers it contains
  • index access: get the contents directly by the getindex function
  • arithmetic operations: +, -, *, ^, ,
  • iterable: various iteration supports, including functions such as iterate, keys, values and pairs

For a complete summation of its features, please refer to the manual.

Manual

OrderedCollections.OrderedDictMethod
OrderedDict(qns::AbelianNumbers, choice::Symbol) -> OrderedDict
OrderedDict(qns::AbelianNumbers, ::Val{:indptr}) -> OrderedDict{qns|>eltype, UnitRange{Int}}
OrderedDict(qns::AbelianNumbers, ::Val{:counts}) -> OrderedDict{qns|>eltype, Int}

Convert an AbelianNumbers to an ordered dict.

source
QuantumLattices.QuantumNumbers.AbelianNumbersMethod
AbelianNumbers(form::Char, contents::Vector{<:AbelianNumber}, indptr::Vector{Int}, choice::Symbol)
AbelianNumbers(form::Char, contents::Vector{<:AbelianNumber}, counts::Vector{Int}, ::Val{:counts})
AbelianNumbers(form::Char, contents::Vector{<:AbelianNumber}, indptr::Vector{Int}, ::Val{:indptr})

Construct an AbelianNumbers from a vector of concrete quantum numbers and an vector containing their counts or indptr.

source
QuantumLattices.QuantumNumbers.Momentum₃Type
Momentum₃{N}(k₁::Integer, k₂::Integer, k₃::Integer) where N
Momentum₃{N₁, N₂, N₃}(k₁::Integer, k₂::Integer, k₃::Integer) where {N₁, N₂, N₃}

Three dimensional momentum.

source
QuantumLattices.QuantumNumbers.@abeliannumberMacro
@abeliannumber typename T fields periods

Construct a concrete AbelianNumber with the type name being typename, fieldtype specified by T, fieldnames specified by fields, and periods specified by periods.

source
Base.:*Method
*(factor::Integer, qns::AbelianNumbers) -> AbelianNumbers
*(qns::AbelianNumbers, factor::Integer) -> AbelianNumbers

Overloaded * operator for the multiplication between an integer and an AbelianNumbers.

source
Base.:*Method
*(factor::Integer, qn::AbelianNumber) -> typeof(qn)
*(qn::AbelianNumber, factor::Integer) -> typeof(qn)

Overloaded * operator for the multiplication between an integer and an AbelianNumber.

source
Base.:+Method
+(qns::AbelianNumbers) -> AbelianNumbers
+(qn::QN, qns::AbelianNumbers{QN}) where {QN<:AbelianNumber} -> AbelianNumbers{QN}
+(qns::AbelianNumbers{QN}, qn::QN) where {QN<:AbelianNumber} -> AbelianNumbers{QN}

Overloaded + operator for AbelianNumber/AbelianNumbers.

Note
  1. The addition between an AbelianNumbers and an AbelianNumber is just a global shift of the contents of the AbelianNumbers by the AbelianNumber, therefore, the result is an AbelianNumbers.
  2. + cannot be used between two AbelianNumbers because the result is ambiguous. Instead, use for direct sum and for direct product.
  3. To ensure type stability, an AbelianNumber and an AbelianNumbers can be added together if and only if the former's type is the same with the latter's eltype.
source
Base.:+Method
+(qn::AbelianNumber) -> typeof(qn)
+(qn::QN, qns::QN...) where {QN<:AbelianNumber} -> QN

Overloaded + operator for AbelianNumber.

Note

To ensure type stability, two AbelianNumber can be added together if and only if they are of the same type.

source
Base.:-Method
-(qns::AbelianNumbers) -> AbelianNumbers
-(qn::QN, qns::AbelianNumbers{QN}) where {QN<:AbelianNumber} -> AbelianNumbers{QN}
-(qns::AbelianNumbers{QN}, qn::QN) where {QN<:AbelianNumber} -> AbelianNumbers{QN}

Overloaded - operator for AbelianNumber/AbelianNumbers.

Note
  1. The subtraction between an AbelianNumbers and an AbelianNumber is just a global shift of the contents of the AbelianNumbers by the AbelianNumber, therefore, the result is an AbelianNumbers.
  2. - cannot be used between two AbelianNumbers because the result is ambiguous. Instead, use with signs for direct sum and with signs for direct product.
  3. To ensure type stability, an AbelianNumber can be subtracted by an AbelianNumbers or vice versa if and only if the former's type is the same with the latter's eltype.
source
Base.:-Method
-(qn::AbelianNumber) -> typeof(qn)
-(qn₁::QN, qn₂::QN) where {QN<:AbelianNumber} -> QN

Overloaded - operator for AbelianNumber.

Note

To ensure type stability, an AbelianNumber can be subtracted by another AbelianNumber if and only if they are of the same type.

source
Base.:^Method
^(qn::AbelianNumber, power::Integer) -> typeof(qn)

Overloaded ^ operator for AbelianNumber.

source
Base.:^Method
^(qns::AbelianNumbers, power::Integer) -> AbelianNumbers

Overloaded ^ operator for AbelianNumbers.

This operation translates into the direct product of power copies of qns.

source
Base.countMethod
count(qns::AbelianNumbers, i::Integer) -> Int

Get the number of duplicates of the ith quantum number.

source
Base.cumsumMethod
cumsum(qns::AbelianNumbers, i::Integer) -> Int

Get the accumulative number of the duplicate quantum numbers up to the ith in the contents.

source
Base.filterMethod
filter(target::QN, qns::AbelianNumbers{QN}) where {QN<:AbelianNumber} -> AbelianNumbers{QN}
filter(targets::Tuple{Vararg{QN}}, qns::AbelianNumbers{QN}) where {QN<:AbelianNumber} -> AbelianNumbers{QN}

Find a subset of an AbelianNumbers by picking out the target quantum numbers.

source
Base.findallMethod
findall(target::Union{QN, Tuple{Vararg{QN}}}, qns::AbelianNumbers{QN}, choice::Symbol) where {QN<:AbelianNumber} -> Vector{Int}
findall(target::Union{QN, Tuple{Vararg{QN}}}, qns::AbelianNumbers{QN}, ::Val{:compression}) where {QN<:AbelianNumber} -> Vector{Int})
findall(target::Union{QN, Tuple{Vararg{QN}}}, qns::AbelianNumbers{QN}, ::Val{:expansion}) where {QN<:AbelianNumber} -> Vector{Int}

Find all the indices of the target quantum numbers in the contents or the expansion of an AbelianNumbers.

source
Base.getindexMethod
getindex(qns::AbelianNumbers, slice::UnitRange{Int}) -> AbelianNumbers
getindex(qns::AbelianNumbers, indices::Vector{Int}) -> AbelianNumbers

Overloaded [] operator.

Note

For an AbelianNumbers, all the getindex functions act on its contents, i.e. its compressed data, but not on its expansion, i.e. the uncompressed data. This definition is consistent with the length of an AbelianNumbers.

source
Base.keysMethod
keys(qns::AbelianNumbers) -> Vector{qns|>eltype}

Iterate over the concrete AbelianNumbers contained in an AbelianNumbers.

source
Base.kronMethod
kron(qns::AbelianNumber...; signs=positives(qns))-> eltype(qns)

Get the direct product of some AbelianNumbers.

Note

Physically, the direct product of a couple of AbelianNumbers are defined through the direct product of the bases of the Hilbert spaces they represent. Apparently, the result is still an AbelianNumber whose dimension is 1. At the same time, each component of the result is obtained by a summation of the corresponding components of the inputs with the correct signs. This is a direct consequence of the Abelian nature of our quantum numbers.

source
Base.kronMethod
kron(qnses::AbelianNumbers{QN}...; signs=positives(qnses)) where {QN<:AbelianNumber} -> AbelianNumbers{QN}

Get the direct product of some AbelianNumberses.

Note

Physically, the direct product of a couple of AbelianNumberses are defined by the direct product of the bases of the Hilbert spaces they represent. Therefore, the dimension of the result equals the product of those of the inputs. Meanwhile, each quantum number in the contents of the result is obtained by a summation of the corresponding quantum numbers of the inputs with the correct signs. This is a direct consequence of the Abelian nature of our quantum numbers.

source
Base.pairsMethod
pairs(qns::AbelianNumbers, choice::Symbol)
pairs(qns::AbelianNumbers, ::Val{:indptr})
pairs(qns::AbelianNumbers, ::Val{:counts})

Iterate over the AbelianNumber=>slice or AbelianNumber=>count pairs.

source
Base.prodMethod
prod(qnses::AbelianNumbers{QN}...; signs=positives(qnses)) where {QN<:AbelianNumber} -> AbelianNumbers{QN}, Dict{QN, Dict{NTuple{length(qnses), QN}, UnitRange{Int}}}

Unitary Kronecker product of several AbelianNumberses. The product result as well as the records of the product will be returned.

Note
  1. All input AbelianNumbers must be 'U' formed or 'C' formed.
  2. Since duplicate quantum number are not allowed in 'U' formed and 'C' formed AbelianNumberses, in general, there exists a merge process of duplicate quantum numbers in the result. Therefore, records are needed to keep track of this process, which will be returned along with the product result. The records are stored in a Dict{QN, Dict{NTuple{NTuple{length(qnses), QN}, UnitRange{Int}}} typed dict, in which, for each nonduplicate quantum number qn in the result, there exist a record Dict((qn₁, qn₂, ...)=>start:stop, ...) telling what quantum numbers (qn₁, qn₂, ...) a merged duplicate qn comes from and what slice start:stop this merged duplicate corresponds in the result.
source
Base.rangeMethod
range(qns::AbelianNumbers, i::Integer) -> UnitRange{Int}

Get the slice of duplicates of the ith quantum number.

source
Base.sortMethod
sort(qns::AbelianNumbers) -> Tuple{AbelianNumbers, Vector{Int}}

Sort the quantum numbers of an AbelianNumbers, return the sorted AbelianNumbers and the permutation array that sorts the expansion of the original AbelianNumbers.

source
Base.unionMethod
union(qns::AbelianNumber...; signs=positives(qns)) -> AbelianNumbers
union(qnses::AbelianNumbers{QN}...; signs=positives(qnses)) where {QN<:AbelianNumber} -> AbelianNumbers{QN}

Get the direct sum of some AbelianNumbers or AbelianNumberses.

Note
  1. Physically, the direct sum of a couple of AbelianNumbers or AbelianNumberses is defined by the direct sum of the bases of the Hilbert spaces they represent. Therefore, the dimension of the result equals the summation of those of the inputs. As a consequence, even for AbelianNumbers, the result will be an AbelianNumbers because the dimension of the result is greater than 1.
  2. Signs of AbelianNumbers or AbelianNumberses can be provided when getting their direct sums.
source
Base.valuesMethod
values(qns::AbelianNumbers, choice::Symbol)
values(qns::AbelianNumbers, ::Val{:indptr})
values(qns::AbelianNumbers, ::Val{:counts})

Iterate over the slices/counts of the AbelianNumbers.

source
QuantumLattices.:⊕Method
⊕(qns::AbelianNumber...) -> AbelianNumbers{qns|>eltype}
⊕(qnses::AbelianNumbers...) -> qnses|>eltype

Get the direct sum of some AbelianNumbers or AbelianNumberses.

source
QuantumLattices.:⊗Method
⊗(qnses::AbelianNumbers...) -> eltype(qnses)

Get the direct product of some AbelianNumberses.

source
QuantumLattices.QuantumNumbers.findindexMethod
findindex(position::Integer, qns::AbelianNumbers, guess::Integer=1) -> Int

Find the index of a quantum number in the contents of an AbelianNumbers beginning at guess whose position in the expansion is position.

source
QuantumLattices.QuantumNumbers.regularize!Method
regularize!(::Type{QN}, array::AbstractVector{<:Real}) where {QN<:AbelianNumber} -> typeof(array)
regularize!(::Type{QN}, array::AbstractMatrix{<:Real}) where {QN<:AbelianNumber} -> typeof(array)

Regularize the elements of an array in place so that it can represent quantum numbers.

source
QuantumLattices.QuantumNumbers.regularizeMethod
regularize(::Type{QN}, array::Union{AbstractVector{<:Real}, AbstractMatrix{<:Real}}) where {QN<:AbelianNumber} -> typeof(array)

Regularize the elements of an array and return a copy that can represent quantum numbers.

source
QuantumLattices.decomposeMethod
decompose(target::QN, qnses::AbelianNumbers{QN}...; signs=positives(qnses), method=:montecarlo, nmax=20) where {QN<:AbelianNumber} -> Vector{NTuple{length(qnses), Int}}

Find a couple of decompositions of target with respect to qnses.

Note

A tuple of integers (i₁, i₂, ...) is called a decomposition of a given target with respect to the given qnses if and only if they satisfy the "decomposition rule":

\[\sum_\text{j} \text{signs}[\text{j}]\times\text{qnses}[\text{j}][\text{i}_{\text{j}}]==\text{target}\]

This equation is in fact a set of restricted linear Diophantine equations. Indeed, our quantum numbers are always discrete Abelian ones and all instances of a concrete AbelianNumber forms a module over the ring of integers. Therefore, each quantum number can be represented as a integral multiple of the unit element of the Abelian module, which results in the final reduction of the above equation to a set of linear Diophantine equations. Then finding a decomposition is equivalent to find a solution of the reduced linear Diophantine equations, with the restriction that the quantum numbers constructed from the solution should be in the corresponding qnses. Here we provide two methods to find such decompositions, one is by brute force, and the other is by Monte Carlo simulations.

source
QuantumLattices.dimensionMethod
dimension(::Type{<:QuantumNumber}) -> Int
dimension(::QuantumNumber) -> Int

The dimension of the Hilbert space an QuantumNumber represents. Apparently, this is always 1.

source
QuantumLattices.expandMethod
expand(qns::AbelianNumbers, choice::Symbol)
expand(qns::AbelianNumbers, ::Val{:contents}) -> Vector{eltype(qns)}
expand(qns::AbelianNumbers, ::Val{:indices}) -> Vector{Int}

Expand the contents or indices of an AbelianNumbers to the uncompressed form.

source
QuantumLattices.permuteMethod
permute(qns::AbelianNumbers, permutation::Vector{Int}, choice::Symbol) -> AbelianNumbers
permute(qns::AbelianNumbers, permutation::Vector{Int}, ::Val{:compression}) -> AbelianNumbers
permute(qns::AbelianNumbers, permutation::Vector{Int}, ::Val{:expansion}) -> AbelianNumbers

Reorder the quantum numbers contained in an AbelianNumbers with a permutation and return the new one.

For :compression case, the permutation is for the compressed contents of the original AbelianNumbers while for :expansion case, the permutation is for the expanded contents of the original AbelianNumbers.

source