Skip to content

Support efficient products of AbstractHamiltonians and non-uniform excitation generation #312

@joachimbrand

Description

@joachimbrand

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 with num_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:

  1. 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.
  2. For QMC or stochastic matrix-vector products is is necessary to generate offdiagonal address-value pairs with a known probability (in a WithReplacement fashion).
  3. 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 SpawningStrategys 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 and AbstractOperatorColumn type. diagonal_element, starting_address, random_offdiagonal, and offdiagonals operate on a column. Operator Column #317
  • Implement OperatorProduct.
  • Implement OperatorSum.
  • Operator traits control the availability of random_offdiagonal and the offdiagonals iterator.
  • Move the responsibility for StochasticStyle, SpawningStrategy, and CompressionStrategy out of the AbstractDVec and into the PMCAlgorithm.
  • DynamicSemistochastic type memoizes column elements.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions