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 systemsParticleNumber
: for particle number reserved systemsSpinfulParticle
: 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 AbelianNumber
s.
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 itscontents
'U'
: the unitary form, which requires no duplicates in itscontents
'C'
: the canonical form, which requires both no duplicates and ascending-order in itscontents
AbelianNumbers
es can be transformed to the corresponding C-formed ones by thesort
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 concreteAbelianNumber
.indptr::Vector{Int}
: The indptr of the quantum numbers contained in it, which is similar to thecolptr
attribute of a CSC sparse matrix and records the compression info of itscontents
.
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
andpairs
For a complete summation of its features, please refer to the manual.
Manual
OrderedCollections.OrderedDict
— MethodOrderedDict(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.
QuantumLattices.QuantumNumbers.AbelianNumber
— TypeAbelianNumber{T<:Real} <: QuantumNumber{T}
Abstract type for all concrete quantum numbers for a single basis.
QuantumLattices.QuantumNumbers.AbelianNumbers
— TypeAbelianNumbers(qn::AbelianNumber, count::Int=1)
Construct an AbelianNumbers
with one unique quantum number which occurs count
times.
QuantumLattices.QuantumNumbers.AbelianNumbers
— TypeAbelianNumbers{QN<:AbelianNumber} <: VectorSpace{QN}
The whole quantum numbers of the total bases of a Hilbert space.
QuantumLattices.QuantumNumbers.AbelianNumbers
— MethodAbelianNumbers(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.
QuantumLattices.QuantumNumbers.AbelianNumbers
— MethodAbelianNumbers(form::Char, contents::Vector{<:AbelianNumber})
Construct an AbelianNumbers
with a set of quantum numbers whose counts are all one.
QuantumLattices.QuantumNumbers.AbelianNumbers
— MethodAbelianNumbers(od::OrderedDict{<:AbelianNumber, <:Integer})
Construct an AbelianNumbers
from an ordered dict containing concrete quantum numbers and their counts.
QuantumLattices.QuantumNumbers.AbelianNumbers
— MethodAbelianNumbers(od::OrderedDict{<:AbelianNumber, <:UnitRange{<:Integer}})
Construct an AbelianNumbers
from an ordered dict containing concrete quantum numbers and their slices.
QuantumLattices.QuantumNumbers.Momenta
— TypeMomenta{P<:Momentum} <: VectorSpace{P}
The allowed set of momenta.
QuantumLattices.QuantumNumbers.Momentum
— TypeMomentum <: AbelianNumber{Int}
Abstract type for momentum.
QuantumLattices.QuantumNumbers.Momentum₁
— TypeMomentum₁{N}(k::Integer) where N
One dimensional momentum.
QuantumLattices.QuantumNumbers.Momentum₂
— TypeMomentum₂{N}(k₁::Integer, k₂::Integer) where N
Momentum₂{N₁, N₂}(k₁::Integer, k₂::Integer) where {N₁, N₂}
Two dimensional momentum.
QuantumLattices.QuantumNumbers.Momentum₃
— TypeMomentum₃{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.
QuantumLattices.QuantumNumbers.ParticleNumber
— TypeParticleNumber(N::Real)
The concrete AbelianNumber
of a quantum system with particle number N
conserved.
QuantumLattices.QuantumNumbers.QuantumNumber
— TypeQuantumNumber
Abstract type for all quantum numbers.
QuantumLattices.QuantumNumbers.SpinfulParticle
— TypeSpinfulParticle(N::Real, Sz::Real)
The concrete AbelianNumber
of a quantum system with both particle number N
and spin z-component Sz
conserved.
QuantumLattices.QuantumNumbers.Sz
— TypeSz(Sz::Real)
The concrete AbelianNumber
of a quantum system with spin z-component Sz
conserved.
QuantumLattices.QuantumNumbers.@abeliannumber
— Macro@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
.
Base.:*
— Method*(factor::Integer, qns::AbelianNumbers) -> AbelianNumbers
*(qns::AbelianNumbers, factor::Integer) -> AbelianNumbers
Overloaded *
operator for the multiplication between an integer and an AbelianNumbers
.
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
.
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
.
- The addition between an
AbelianNumbers
and anAbelianNumber
is just a global shift of the contents of theAbelianNumbers
by theAbelianNumber
, therefore, the result is anAbelianNumbers
. +
cannot be used between twoAbelianNumbers
because the result is ambiguous. Instead, use⊕
for direct sum and⊗
for direct product.- To ensure type stability, an
AbelianNumber
and anAbelianNumbers
can be added together if and only if the former's type is the same with the latter's eltype.
Base.:+
— Method+(qn::AbelianNumber) -> typeof(qn)
+(qn::QN, qns::QN...) where {QN<:AbelianNumber} -> QN
Overloaded +
operator for AbelianNumber
.
To ensure type stability, two AbelianNumber
can be added together if and only if they are of the same type.
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
.
- The subtraction between an
AbelianNumbers
and anAbelianNumber
is just a global shift of the contents of theAbelianNumbers
by theAbelianNumber
, therefore, the result is anAbelianNumbers
. -
cannot be used between twoAbelianNumbers
because the result is ambiguous. Instead, use⊕
with signs for direct sum and⊗
with signs for direct product.- To ensure type stability, an
AbelianNumber
can be subtracted by anAbelianNumbers
or vice versa if and only if the former's type is the same with the latter's eltype.
Base.:-
— Method-(qn::AbelianNumber) -> typeof(qn)
-(qn₁::QN, qn₂::QN) where {QN<:AbelianNumber} -> QN
Overloaded -
operator for AbelianNumber
.
To ensure type stability, an AbelianNumber
can be subtracted by another AbelianNumber
if and only if they are of the same type.
Base.:^
— Method^(qn::AbelianNumber, power::Integer) -> typeof(qn)
Overloaded ^
operator for AbelianNumber
.
Base.:^
— Method^(qns::AbelianNumbers, power::Integer) -> AbelianNumbers
Overloaded ^
operator for AbelianNumbers
.
This operation translates into the direct product of power
copies of qns
.
Base.count
— Methodcount(qns::AbelianNumbers, i::Integer) -> Int
Get the number of duplicates of the ith quantum number.
Base.cumsum
— Methodcumsum(qns::AbelianNumbers, i::Integer) -> Int
Get the accumulative number of the duplicate quantum numbers up to the ith in the contents.
Base.filter
— Methodfilter(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.
Base.findall
— Methodfindall(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
.
Base.getindex
— Methodgetindex(qns::AbelianNumbers, slice::UnitRange{Int}) -> AbelianNumbers
getindex(qns::AbelianNumbers, indices::Vector{Int}) -> AbelianNumbers
Overloaded []
operator.
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
.
Base.keys
— Methodkeys(qns::AbelianNumbers) -> Vector{qns|>eltype}
Iterate over the concrete AbelianNumber
s contained in an AbelianNumbers
.
Base.kron
— Methodkron(qns::AbelianNumber...; signs=positives(qns))-> eltype(qns)
Get the direct product of some AbelianNumber
s.
Physically, the direct product of a couple of AbelianNumber
s 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.
Base.kron
— Methodkron(qnses::AbelianNumbers{QN}...; signs=positives(qnses)) where {QN<:AbelianNumber} -> AbelianNumbers{QN}
Get the direct product of some AbelianNumbers
es.
Physically, the direct product of a couple of AbelianNumbers
es 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.
Base.pairs
— Methodpairs(qns::AbelianNumbers, choice::Symbol)
pairs(qns::AbelianNumbers, ::Val{:indptr})
pairs(qns::AbelianNumbers, ::Val{:counts})
Iterate over the AbelianNumber=>slice
or AbelianNumber=>count
pairs.
Base.prod
— Methodprod(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 AbelianNumbers
es. The product result as well as the records of the product will be returned.
- All input
AbelianNumbers
must be 'U' formed or 'C' formed. - Since duplicate quantum number are not allowed in 'U' formed and 'C' formed
AbelianNumbers
es, 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 aDict{QN, Dict{NTuple{NTuple{length(qnses), QN}, UnitRange{Int}}}
typed dict, in which, for each nonduplicate quantum numberqn
in the result, there exist a recordDict((qn₁, qn₂, ...)=>start:stop, ...)
telling what quantum numbers(qn₁, qn₂, ...)
a merged duplicateqn
comes from and what slicestart:stop
this merged duplicate corresponds in the result.
Base.range
— Methodrange(qns::AbelianNumbers, i::Integer) -> UnitRange{Int}
Get the slice of duplicates of the ith quantum number.
Base.sort
— Methodsort(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
.
Base.union
— Methodunion(qns::AbelianNumber...; signs=positives(qns)) -> AbelianNumbers
union(qnses::AbelianNumbers{QN}...; signs=positives(qnses)) where {QN<:AbelianNumber} -> AbelianNumbers{QN}
Get the direct sum of some AbelianNumber
s or AbelianNumbers
es.
- Physically, the direct sum of a couple of
AbelianNumber
s orAbelianNumbers
es 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 forAbelianNumber
s, the result will be anAbelianNumbers
because the dimension of the result is greater than 1. - Signs of
AbelianNumber
s orAbelianNumbers
es can be provided when getting their direct sums.
Base.values
— Methodvalues(qns::AbelianNumbers, choice::Symbol)
values(qns::AbelianNumbers, ::Val{:indptr})
values(qns::AbelianNumbers, ::Val{:counts})
Iterate over the slices/counts of the AbelianNumbers
.
QuantumLattices.:⊕
— Method⊕(qns::AbelianNumber...) -> AbelianNumbers{qns|>eltype}
⊕(qnses::AbelianNumbers...) -> qnses|>eltype
Get the direct sum of some AbelianNumber
s or AbelianNumbers
es.
QuantumLattices.:⊗
— Method⊗(qnses::AbelianNumbers...) -> eltype(qnses)
Get the direct product of some AbelianNumbers
es.
QuantumLattices.:⊗
— Method⊗(qns::AbelianNumber...) -> eltype(qns)
Get the direct product of some AbelianNumber
s.
QuantumLattices.QuantumNumbers.findindex
— Methodfindindex(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
.
QuantumLattices.QuantumNumbers.periods
— Methodperiods(qn::AbelianNumber)
The periods of the components of a concrete AbelianNumber
.
QuantumLattices.QuantumNumbers.positives
— Methodpositives(inputs::NTuple{N, Any}) where N -> NTuple{N, Int}
Return a tuple of all positive signs.
QuantumLattices.QuantumNumbers.regularize!
— Methodregularize!(::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.
QuantumLattices.QuantumNumbers.regularize
— Methodregularize(::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.
QuantumLattices.decompose
— Methoddecompose(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
.
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.
QuantumLattices.dimension
— Methoddimension(::Type{<:QuantumNumber}) -> Int
dimension(::QuantumNumber) -> Int
The dimension of the Hilbert space an QuantumNumber
represents. Apparently, this is always 1.
QuantumLattices.expand
— Methodexpand(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.
QuantumLattices.permute
— Methodpermute(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
.