Module BitStringAddresses
This module contains the implementations of BitString and various Fock addresses. The addresses serve as a basis for a Hamiltonian.
While there are not restrictions on the type of address a Hamiltonian uses, Rimu provides implementations for Bosonic, Fermionic, and mixed Fock States.
When implementing a new address type, care must be taken to make them space-efficient and stack-allocated - avoid using (heap-allocated) arrays to represent your addresses at all costs!
Fock addresses
Rimu provides a variety of address implementations that should make it straightforward to implement efficient Hamiltonians. Examples are:
BoseFSSingle-component bosonic Fock state with fixed particle and mode number.FermiFSSingle-component fermionic Fock state with fixed particle and mode number.CompositeFSMulti-component Fock state composed of the above types.OccupationNumberFSSingle-component bosonic Fock state with a fixed number of modes. The number of particles is not part of the type and can be changed by operators.
Fock address API
Rimu.BitStringAddresses.AbstractFockAddress — TypeAbstractFockAddress{N,M}Abstract type representing a Fock state with N particles and M modes.
See also SingleComponentFockAddress, CompositeFS, BoseFS, FermiFS.
Rimu.BitStringAddresses.BoseFSIndex — TypeBoseFSIndexStruct used for indexing and performing excitations on a BoseFS.
Fields:
occnum: the occupation number.mode: the index of the mode.offset: the position of the mode in the address. This is the bit offset of the mode when
the address is represented by a bitstring, and the position in the list when it is represented by SortedParticleList.
Rimu.BitStringAddresses.FermiFSIndex — TypeFermiFSIndexStruct used for indexing and performing excitations on a FermiFS.
Fields:
occnum: the occupation number.mode: the index of the mode.offset: the position of the mode in the address. This ismode - 1when the address is represented by a bitstring, and the position in the list when usingSortedParticleList.
Rimu.BitStringAddresses.OccupiedModeMap — TypeOccupiedModeMap(addr) <: AbstractVectorGet a map of occupied modes in address as an AbstractVector of indices compatible with excitation - BoseFSIndex or FermiFSIndex.
OccupiedModeMap(addr)[i] contains the index for the i-th occupied mode. This is useful because repeatedly looking for occupied modes with find_occupied_mode can be time-consuming. OccupiedModeMap(addr) is an eager version of the iterator returned by occupied_modes. It is similar to onr but contains more information.
Example
julia> b = BoseFS(10, 0, 0, 0, 2, 0, 1)
BoseFS{13,7}(10, 0, 0, 0, 2, 0, 1)
julia> mb = OccupiedModeMap(b)
3-element OccupiedModeMap{7, BoseFSIndex}:
BoseFSIndex(occnum=10, mode=1, offset=0)
BoseFSIndex(occnum=2, mode=5, offset=14)
BoseFSIndex(occnum=1, mode=7, offset=18)
julia> f = FermiFS(1,1,1,1,0,0,1,0,0)
FermiFS{5,9}(1, 1, 1, 1, 0, 0, 1, 0, 0)
julia> mf = OccupiedModeMap(f)
5-element OccupiedModeMap{5, FermiFSIndex}:
FermiFSIndex(occnum=1, mode=1, offset=0)
FermiFSIndex(occnum=1, mode=2, offset=1)
FermiFSIndex(occnum=1, mode=3, offset=2)
FermiFSIndex(occnum=1, mode=4, offset=3)
FermiFSIndex(occnum=1, mode=7, offset=6)
julia> mf == collect(occupied_modes(f))
true
julia> dot(mf, mb)
11
julia> dot(mf, 1:20)
17See also dot, SingleComponentFockAddress.
Rimu.BitStringAddresses.OccupiedPairsMap — TypeOccupiedPairsMap(addr::SingleComponentFockAddress) <: AbstractVectorGet a map of all distinct pairs of indices in addr. Pairs involving multiply-occupied modes are counted once, (including self-pairing). This is useful for cases where identifying pairs of particles for eg. interactions is not well-defined or efficient to do on the fly. This is an eager iterator whose elements are a tuple of particle indices that can be given to excitation
Example
julia> addr = BoseFS(10, 0, 0, 0, 2, 0, 1)
BoseFS{13,7}(10, 0, 0, 0, 2, 0, 1)
julia> pairs = OccupiedPairsMap(addr)
5-element OccupiedPairsMap{78, Tuple{BoseFSIndex, BoseFSIndex}}:
(BoseFSIndex(occnum=10, mode=1, offset=0), BoseFSIndex(occnum=10, mode=1, offset=0))
(BoseFSIndex(occnum=2, mode=5, offset=14), BoseFSIndex(occnum=2, mode=5, offset=14))
(BoseFSIndex(occnum=2, mode=5, offset=14), BoseFSIndex(occnum=10, mode=1, offset=0))
(BoseFSIndex(occnum=1, mode=7, offset=18), BoseFSIndex(occnum=10, mode=1, offset=0))
(BoseFSIndex(occnum=1, mode=7, offset=18), BoseFSIndex(occnum=2, mode=5, offset=14))
julia> excitation(addr, pairs[2], pairs[4])
(BoseFS{13,7}(9, 0, 0, 0, 4, 0, 0), 10.954451150103322)See also OccupiedModeMap.
Rimu.BitStringAddresses.SingleComponentFockAddress — TypeSingleComponentFockAddress{N,M} <: AbstractFockAddress{N,M}A type representing a single component Fock state with N particles and M modes.
Implemented subtypes: BoseFS, FermiFS.
Supported functionality
find_modefind_occupied_modenum_occupied_modesoccupied_modes: Lazy iterator.OccupiedModeMap:AbstractVectorwith eager construction.excitation: Create a new address.BoseFSIndexandFermiFSIndexfor indexing.
See also CompositeFS, AbstractFockAddress.
Rimu.BitStringAddresses.excitation — Functionexcitation(addr::SingleComponentFockAddress, creations::NTuple, destructions::NTuple)Generate an excitation on address addr by applying creations and destructions, which are tuples of the appropriate address indices (i.e. BoseFSIndex for bosons, or FermiFSIndex for fermions).
\[a^†_{c_1} a^†_{c_2} \ldots a_{d_1} a_{d_2} \ldots |\mathrm{addr}\rangle \to α|\mathrm{naddr}\rangle\]
Returns the new address naddr and the factor α. The value of α is given by the square root of the product of mode occupations before destruction and after creation. If the excitation is illegal, returns an arbitrary address and the value 0.0.
Example
julia> f = FermiFS(1,1,0,0,1,1,1,1)
FermiFS{6,8}(1, 1, 0, 0, 1, 1, 1, 1)
julia> i, j, k, l = find_mode(f, (3,4,2,5))
(FermiFSIndex(occnum=0, mode=3, offset=2), FermiFSIndex(occnum=0, mode=4, offset=3), FermiFSIndex(occnum=1, mode=2, offset=1), FermiFSIndex(occnum=1, mode=5, offset=4))
julia> excitation(f, (i,j), (k,l))
(FermiFS{6,8}(1, 0, 1, 1, 0, 1, 1, 1), -1.0)Rimu.BitStringAddresses.find_mode — Functionfind_mode(::SingleComponentFockAddress, i)Find the i-th mode in address. Returns BoseFSIndex for BoseFS, and FermiFSIndex for FermiFS. Can work on a tuple of modes. Does not check bounds.
julia> find_mode(BoseFS(1, 0, 2), 2)
BoseFSIndex(occnum=0, mode=2, offset=2)
julia> find_mode(FermiFS(1, 1, 1, 0), (2,3))
(FermiFSIndex(occnum=1, mode=2, offset=1), FermiFSIndex(occnum=1, mode=3, offset=2))Rimu.BitStringAddresses.find_occupied_mode — Functionfind_occupied_mode(::SingleComponentFockAddress, k)
find_occupied_mode(::BoseFS, k, [n])Find the k-th occupied mode in address (with at least n particles). Returns BoseFSIndex for BoseFS, and FermiFSIndex for FermiFS. When unsuccessful it returns a zero index.
Example
julia> find_occupied_mode(FermiFS(1, 1, 1, 0), 2)
FermiFSIndex(occnum=1, mode=2, offset=1)
julia> find_occupied_mode(BoseFS(1, 0, 2), 1)
BoseFSIndex(occnum=1, mode=1, offset=0)
julia> find_occupied_mode(BoseFS(1, 0, 2), 1, 2)
BoseFSIndex(occnum=2, mode=3, offset=3)See also occupied_modes, OccupiedModeMap, SingleComponentFockAddress.
Rimu.BitStringAddresses.num_components — Methodnum_components(::Type{<:AbstractFockAddress})
num_components(::AbstractFockAddress)Number of components in address.
Rimu.BitStringAddresses.num_modes — Methodnum_modes(::Type{<:AbstractFockAddress})
num_modes(::AbstractFockAddress)Number of modes represented by address.
Rimu.BitStringAddresses.num_occupied_modes — Functionnum_occupied_modes(::SingleComponentFockAddress)Get the number of occupied modes in address. Equivalent to length(occupied_modes(address)), or the number of non-zeros in its ONR representation.
Example
julia> num_occupied_modes(BoseFS((1, 0, 2)))
2
julia> num_occupied_modes(FermiFS((1, 1, 1, 0)))
3Rimu.BitStringAddresses.num_particles — Methodnum_particles(::Type{<:AbstractFockAddress})
num_particles(::AbstractFockAddress)Number of particles represented by address.
Rimu.BitStringAddresses.occupied_modes — Functionoccupied_modes(::SingleComponentFockAddress)Return a lazy iterator over all occupied modes in an address. Iterates over BoseFSIndexs for BoseFS, and over FermiFSIndexs for FermiFS. See OccupiedModeMap for an eager version.
Example
julia> b = BoseFS((1,5,0,4));
julia> foreach(println, occupied_modes(b))
BoseFSIndex(occnum=1, mode=1, offset=0)
BoseFSIndex(occnum=5, mode=2, offset=2)
BoseFSIndex(occnum=4, mode=4, offset=9)julia> f = FermiFS((1,1,0,1,0,0,1));
julia> foreach(println, occupied_modes(f))
FermiFSIndex(occnum=1, mode=1, offset=0)
FermiFSIndex(occnum=1, mode=2, offset=1)
FermiFSIndex(occnum=1, mode=4, offset=3)
FermiFSIndex(occnum=1, mode=7, offset=6)See also find_occupied_mode, SingleComponentFockAddress.
Rimu.BitStringAddresses.onr — Functionoccupation_number_representation(fs::SingleComponentFockAddress)
onr(fs::SingleComponentFockAddress)Compute and return the occupation number representation of the Fock state fs as an SVector{M}, where M is the number of modes.
Rimu.BitStringAddresses.@fs_str — Macrofs"$(string)"Parse the compact representation of a Fock state. Useful for copying the printout from a vector to the REPL.
Example
julia> DVec(BoseFS{3,4}(0, 1, 2, 0) => 1)
DVec{BoseFS{3, 4, BitString{6, 1, UInt8}},Int64} with 1 entry, style = IsStochasticInteger{Int64}()
fs"|0 1 2 0⟩" => 1
julia> fs"|0 1 2 0⟩" => 1 # Copied from above printout
BoseFS{3,4}(0, 1, 2, 0) => 1
julia> fs"|1 2 3⟩⊗|0 1 0⟩" # composite bosonic Fock state
CompositeFS(
BoseFS{6,3}(1, 2, 3),
BoseFS{1,3}(0, 1, 0),
)
julia> fs"|↑↓↑⟩" # construct a fermionic Fock state
CompositeFS(
FermiFS{2,3}(1, 0, 1),
FermiFS{1,3}(0, 1, 0),
)
julia> s = fs"|0 1 2 0⟩{}" # constructing OccupationNumberFS with default UInt8 container
OccupationNumberFS{4, UInt8}(0, 1, 2, 0)
julia> [s] # prints out with the signifcant number of bits specified in braces
1-element Vector{OccupationNumberFS{4, UInt8}}:
fs"|0 1 2 0⟩{8}"See also FermiFS, BoseFS, CompositeFS, FermiFS2C, OccupationNumberFS.
Rimu.BitStringAddresses.BoseFS — TypeBoseFS{N,M,S} <: SingleComponentFockAddressAddress type that represents a Fock state of N spinless bosons in M modes by wrapping a BitString, or a SortedParticleList. Which is wrapped is chosen automatically based on the properties of the address.
Constructors
BoseFS{[N,M]}(val::Integer...): CreateBoseFS{N,M}from occupation numbers. This is type-stable if the number of modesMand the number of particlesNare provided. Otherwise,MandNare inferred from the arguments.BoseFS{[N,M]}(onr): CreateBoseFS{N,M}from occupation number representation, seeonr. This is efficient ifNandMare provided, andonris a statically-sized collection, such as aTupleorSVector.BoseFS{[N,M]}([M, ]pairs...): Provide the number of modesMandmode => occupation_numberpairs. IfMis provided as a type parameter, it should not be provided as the first argument. Useful for creating sparse addresses.pairscan be multiple arguments or an iterator of pairs.BoseFS{N,M,S}(bs::S): Unsafe constructor. Does not check whether the number of particles inbsis equal toN.@fs_str: Addresses are sometimes printed in a compact manner. This representation can also be used as a constructor. See the last example below.
Examples
julia> BoseFS{6,5}(0, 1, 2, 3, 0)
BoseFS{6,5}(0, 1, 2, 3, 0)
julia> BoseFS([abs(i - 3) ≤ 1 ? i - 1 : 0 for i in 1:5])
BoseFS{6,5}(0, 1, 2, 3, 0)
julia> BoseFS(5, 2 => 1, 3 => 2, 4 => 3)
BoseFS{6,5}(0, 1, 2, 3, 0)
julia> BoseFS{6,5}(i => i - 1 for i in 2:4)
BoseFS{6,5}(0, 1, 2, 3, 0)
julia> fs"|0 1 2 3 0⟩"
BoseFS{6,5}(0, 1, 2, 3, 0)
julia> fs"|b 5: 2 3 3 4 4 4⟩"
BoseFS{6,5}(0, 1, 2, 3, 0)See also: SingleComponentFockAddress, OccupationNumberFS, FermiFS, CompositeFS, FermiFS2C.
Rimu.BitStringAddresses.bose_hubbard_interaction — Methodbose_hubbard_interaction(address)Return $Σ_i n_i (n_i-1)$ for computing the Bose-Hubbard on-site interaction (without the $U$ prefactor.)
Example
julia> Hamiltonians.bose_hubbard_interaction(BoseFS{4,4}((2,1,1,0)))
2
julia> Hamiltonians.bose_hubbard_interaction(BoseFS{4,4}((3,0,1,0)))
6Rimu.BitStringAddresses.hopnextneighbour — Methodnew_address, product = hopnextneighbour(add, chosen)Compute the new address of a hopping event for the Bose-Hubbard model. Returns the new address and the square root of product of occupation numbers of the involved modes.
The off-diagonals are indexed as follows:
(chosen + 1) ÷ 2selects the hopping site.- Even
chosenindicates a hop to the left. - Odd
chosenindicates a hop to the right. - Boundary conditions are periodic.
Example
julia> using Rimu.Hamiltonians: hopnextneighbour
julia> hopnextneighbour(BoseFS(1, 0, 1), 3)
(BoseFS{2,3}(2, 0, 0), 1.4142135623730951)
julia> hopnextneighbour(BoseFS(1, 0, 1), 4)
(BoseFS{2,3}(1, 1, 0), 1.0)Rimu.BitStringAddresses.near_uniform — Methodnear_uniform(BoseFS{N,M}) -> BoseFS{N,M}Create bosonic Fock state with near uniform occupation number of M modes with a total of N particles.
Examples
julia> near_uniform(BoseFS{7,5})
BoseFS{7,5}(2, 2, 1, 1, 1)
julia> near_uniform(FermiFS{3,5})
FermiFS{3,5}(1, 1, 1, 0, 0)Rimu.BitStringAddresses.FermiFS — TypeFermiFS{N,M,S} <: SingleComponentFockAddressAddress type that represents a Fock state of N fermions of the same spin in M modes by wrapping a BitString, or a SortedParticleList. Which is wrapped is chosen automatically based on the properties of the address.
Constructors
FermiFS{[N,M]}(val::Integer...): CreateFermiFS{N,M}from occupation numbers. This is type-stable if the number of modesMand the number of particlesNare provided. Otherwise,MandNare inferred from the arguments.FermiFS{[N,M]}(onr): CreateFermiFS{N,M}from occupation number representation, seeonr. This is efficient ifNandMare provided, andonris a statically-sized collection, such as aTuple{M}orSVector{M}.FermiFS{[N,M]}([M, ]pairs...): Provide the number of modesMand pairs of the formmode => 1. IfMis provided as a type parameter, it should not be provided as the first argument. Useful for creating sparse addresses.pairscan be multiple arguments or an iterator of pairs.FermiFS{N,M,S}(bs::S): Unsafe constructor. Does not check whether the number of particles inbsis equal toN, or whether each mode only contains one particle.@fs_str: Addresses are sometimes printed in a compact manner. This representation can also be used as a constructor. See the last example below.
Examples
julia> FermiFS{3,5}(0, 1, 1, 1, 0)
FermiFS{3,5}(0, 1, 1, 1, 0)
julia> FermiFS([abs(i - 3) ≤ 1 for i in 1:5])
FermiFS{3,5}(0, 1, 1, 1, 0)
julia> FermiFS(5, 2 => 1, 3 => 1, 4 => 1)
FermiFS{3,5}(0, 1, 1, 1, 0)
julia> FermiFS{3,5}(i => 1 for i in 2:4)
FermiFS{3,5}(0, 1, 1, 1, 0)
julia> fs"|⋅↑↑↑⋅⟩"
FermiFS{3,5}(0, 1, 1, 1, 0)
julia> fs"|f 5: 2 3 4⟩"
FermiFS{3,5}(0, 1, 1, 1, 0)See also: SingleComponentFockAddress, BoseFS, CompositeFS, FermiFS2C, BitString, OccupationNumberFS.
Rimu.BitStringAddresses.BoseFS2C — TypeBoseFS2C{NA,NB,M,AA,AB} <: AbstractFockAddress
BoseFS2C(onr_a, onr_b)Address type that constructed with two BoseFS{N,M,S}. It represents a Fock state with two components, e.g. two different species of bosons with particle number NA from species S and particle number NB from species B. The number of modes M is expected to be the same for both components.
Rimu.BitStringAddresses.CompositeFS — TypeCompositeFS(addresses::SingleComponentFockAddress...) <: AbstractFockAddressUsed to encode addresses for multi-component models. All component addresses are expected have the same number of modes.
See also: BoseFS, FermiFS, SingleComponentFockAddress, num_modes, FermiFS2C, AbstractFockAddress.
Rimu.BitStringAddresses.FermiFS2C — TypeFermiFS2C <: AbstractFockAddress
FermiFS2C(onr_a, onr_b)Fock state address with two fermionic (spin) components. Alias for CompositeFS with two FermiFS components. Construct by specifying either two compatible FermiFSs, two onrs, or the number of modes followed by mode => occupation_number pairs, where occupation_number=1 will put a particle in the first component and occupation_number=-1 will put a particle in the second component. See examples below.
Examples
julia> FermiFS2C(FermiFS(1,0,0), FermiFS(0,1,1))
CompositeFS(
FermiFS{1,3}(1, 0, 0),
FermiFS{2,3}(0, 1, 1),
)
julia> FermiFS2C((1,0,0), (0,1,1))
CompositeFS(
FermiFS{1,3}(1, 0, 0),
FermiFS{2,3}(0, 1, 1),
)
julia> FermiFS2C(3, 1 => 1, 2 => -1, 3 => -1)
CompositeFS(
FermiFS{1,3}(1, 0, 0),
FermiFS{2,3}(0, 1, 1),
)
julia> fs"|↑↓↓⟩"
CompositeFS(
FermiFS{1,3}(1, 0, 0),
FermiFS{2,3}(0, 1, 1),
)Rimu.BitStringAddresses.time_reverse — Methodtime_reverse(addr)Apply the time-reversal operation on a two-component Fock address that flips all the spins.
Requires each component address to have the same type.
Rimu.BitStringAddresses.OccupationNumberFS — TypeOccupationNumberFS{M,T} <: SingleComponentFockAddressAddress type that stores the occupation numbers of a single component bosonic Fock state with M modes. The occupation numbers must fit into the type T <: Unsigned. The number of particles is runtime data, and can be retrieved with num_particles(address).
Constructors
OccupationNumberFS(val::Integer...): Construct from occupation numbers. Must be < 256 to fit intoUInt8.OccupationNumberFS{[M,T]}(onr): Construct from collectiononrwithMoccupation numbers with typeT. If unspecified, the typeTof the occupation numbers is inferred from the type of the arguments.OccupationNumberFS(fs::BoseFS): Construct fromBoseFS.- With shortform macro
@fs_str. Specify the number of significant bits in braces. See example below.
Examples
julia> ofs = OccupationNumberFS(1,2,3)
OccupationNumberFS{3, UInt8}(1, 2, 3)
julia> ofs == fs"|1 2 3⟩{8}"
true
julia> num_particles(ofs)
6Rimu.BitStringAddresses.excitation — Methodexcitation(addr::OccupationNumberFS, c::NTuple, d::NTuple)
→ (nadd, α)Generate an excitation on an OccupationNumberFS by applying the creation and destruction operators specified by the tuples of mode numbers c and d to the Fock state addr. The modes are indexed by integers (starting at 1), or by indices of type BoseFSIndex. The value of α is given by the square root of the product of mode occupations before destruction and after creation.
The number of particles may change by this type of excitation.
Example
julia> s = fs"|1 2 3⟩{8}"
OccupationNumberFS{3, UInt8}(1, 2, 3)
julia> num_particles(s)
6
julia> es, α = excitation(s, (1,1), (3,))
(OccupationNumberFS{3, UInt8}(3, 2, 2), 4.242640687119285)
julia> num_particles(es)
7Internal representations
The atomic addresses, BoseFS and FermiFS, are implemented as either bitstrings or sorted lists of particles. Using these approaches over an occupation number representation makes the addresses much more space-efficient.
Therewhile OccupationNumberFS internally uses the occupation number representation, which allows it to handle excitation operations that change the particle number. This is fast but requires more storage space.
Internal APIs
Rimu.BitStringAddresses.BitString — TypeBitString{B,N,T<:Unsigned}Type for storing bitstrings of static size. Holds B bits in N chunks, where each chunk is of type T.
N is chosen automatically to accommodate B bits as efficiently as possible.
Constructors
BitString{B,N,T}(::SVector{N,T}): unsafe constructor. Does not check for ghost bits.BitString{B,N,T}(i::T): as above, but setsias the rightmost chunk.BitString{B}(::Integer): Convert integer toBitString. Integer is truncated to the correct number of bits.
Rimu.BitStringAddresses.SortedParticleList — TypeSortedParticleList{N,M,T<:Unsigned}Type for storing sparse fock states. Stores the mode number of each particle as an entry with only its mode stored. The entries are always kept sorted.
Iterating over SortedParticleLists yields occupied modes as a tuple of occupation number, mode number, and position in list.
Constructors
SortedParticleList{N,M,T}(::SVector{N,T}): unsafe constructor. Does not sort input.SortedParticleList(arr::AbstractVector): convert ONR toSortedParticleList
Index
Rimu.BitStringAddresses.AbstractFockAddressRimu.BitStringAddresses.BitStringRimu.BitStringAddresses.BoseFSRimu.BitStringAddresses.BoseFS2CRimu.BitStringAddresses.BoseFSIndexRimu.BitStringAddresses.CompositeFSRimu.BitStringAddresses.FermiFSRimu.BitStringAddresses.FermiFS2CRimu.BitStringAddresses.FermiFSIndexRimu.BitStringAddresses.OccupationNumberFSRimu.BitStringAddresses.OccupiedModeMapRimu.BitStringAddresses.OccupiedPairsMapRimu.BitStringAddresses.SingleComponentFockAddressRimu.BitStringAddresses.SortedParticleListRimu.BitStringAddresses.bose_hubbard_interactionRimu.BitStringAddresses.excitationRimu.BitStringAddresses.excitationRimu.BitStringAddresses.find_modeRimu.BitStringAddresses.find_occupied_modeRimu.BitStringAddresses.hopnextneighbourRimu.BitStringAddresses.near_uniformRimu.BitStringAddresses.num_componentsRimu.BitStringAddresses.num_modesRimu.BitStringAddresses.num_occupied_modesRimu.BitStringAddresses.num_particlesRimu.BitStringAddresses.occupied_modesRimu.BitStringAddresses.onrRimu.BitStringAddresses.time_reverseRimu.BitStringAddresses.@fs_str