-
Notifications
You must be signed in to change notification settings - Fork 7
Description
The problem with the current AbstractHamiltonian
interface
The interface for AbstractHamiltonian
and AbstractObservable
require amongst other things
- given an
address
be able to calculate the number of non-zero offdiagonals in the column withnum_offdiagonals
, and - deterministically generate one of these offdiagonals (address and value) with
get_offdiagonal
, which essentially indexes each one with an integer.
This information is conveniently used for uniformly sampling the offdiagonals, or for generating the full column for deterministic matrix-vector products. A problem arises for operators where it is costly to calculate the number of non-zero off-diagonals ahead of time. For example this is the case if the operator is defined as the product of two operators A*B
, where calculating num-offdiagonals
accurately would require to first generate all offdiagonals from B
and then calling num_offdiagonals
on the resulting addresses with A
. Similarly, for fermionic Hamiltonians it is often complicated and impractical to accurately determine the number of offdiagonals and algorithmically access them.
Avoiding the problem
Let us consider what is really required for Rimu's functionality:
- For deterministic matrix-vector products is is necessary to generate an exhaustive sequence of offdiagonals (address and value) in addition to the diagonal matrix element to define the operator column defined by a given address.
- For QMC or stochastic matrix-vector products is is necessary to generate offdiagonal address-value pairs with a known probability (in a
WithReplacement
fashion). - For the
DynamicSemiStochastic
spawning strategy it would be good to know the length of the column, i.e.num_offdiagonals
- but a reasonable estimate may be sufficient.
These requirements are less than what is currently required. The first two requirements could be easily met for product or fermionic hamiltonians without calculating the number of offdiagonals ahead of time. Moreover, if num_offdiagonals
is replaced by a cheaply available estimate then this could also be cheap to calculate for products of operators.
Suggested solution: An OperatorColumn
type and constructor
OperatorColumn
could both be an abstract type and constructor for a type instance (with potentially a custom type suitable for the type of Hamiltonian). Before computing any of the information in points 1-3 one would instantiate a struct
column = OperatorColumn(hamiltonian, address)
that could precompute and store the diagonal element (because that is needed in any scenario), the estimated column length, and other potentially relevant information (e.g. convert the address
into an OccupiedModeMap
for efficient generation of excitations). Then iterating over column
would generate all address, value pairs (e.g. with the diagonal element as the first one) and offdiagonals can be sampled from the column:
addr, diagonal_matrix_element = first(column) # first element from iteration
column_dvec = DVec(column) # fill a DVec by iterating `column`
new_address, probability, value = random_offdiagonal(column) # similar to the existing function but now acting on the `column` struct
estimated_length = num_offdiagonals(column) # now just an estimate that could be the same for every column
This suggests changing the interface for AbstractHamiltonian
and AbstractOperator
to require them to provide a method for OperatorColumn
that instantiates a struct with the properties mentioned above. In this case, the Hamiltonian would "own" the excitation generator, i.e. the algorithm that provides the random selection of offdiagonals.
For existing Hamiltonians that already implement get_offdiagonal
and the rest of the existing interface, default implementations for OperatorColumn
can be provided. For new Hamiltonians, implementing get_offdiagonal
would no longer be required.
In order to facilitate easy-to-compute estimates for num_offdiagonals
, operator traits like OneBodyOperator
and TwoBodyOperator
could be introduced. Setting the trait would then result in a value of N*M
, and N(N-1)*M^2
for BoseFS
addresses, respectively, where N
is the particle number and M
the number of modes. Corresponding pre-computed values (possibly even computed at compile time) for other types of Fock addresses can be provided.
Required changes to existing code
Code related to spawning and for matrix-operator products and three-way dot products would have to be adapted to make use of OperatorColumn
and be cleaned of the old interface functions. The SpawningStrategy
s WithoutReplacement
and Bernoulli
would either be completely deprecated, or the strategy could be passed as an additional argument into the random_offdiagonal
function. In this case the sampler would have to take care of this.
Checklist
- New
AbstractOperator
interface:operator_column
function andAbstractOperatorColumn
type.diagonal_element
,starting_address
,random_offdiagonal
, andoffdiagonals
operate on acolumn
. Operator Column #317 - Implement
OperatorProduct
. - Implement
OperatorSum
. - Operator traits control the availability of
random_offdiagonal
and theoffdiagonals
iterator. - Move the responsibility for
StochasticStyle
,SpawningStrategy
, andCompressionStrategy
out of theAbstractDVec
and into thePMCAlgorithm
. -
DynamicSemistochastic
type memoizes column elements.