Improve performance of PauliLindbladMap sampling
The PauliLindbladMap.sample and PauliLindbladMap.signed_sample will be involved in randomized parameter generation in template circuits, and it is important that there is a high-performance way of calling them (or related functions).
While this isn't exposed in the existing interface, performance is currently achieved by always pre-computing quantities derived from the rates that are needed for sampling:
probabilitiesnon_negative_rates(whether or not each rate is non-negative, which is necessary for sign propagation)gamma(the over-all gamma of the map)
The benefit of this pre-computation is when sample (signed_sample) is called, these computations don't need to be done, however this also means that these computations may be being done prematurely in other workflows. E.g. in the process of building a map before sampling, there may be intermediate maps for which the derived quantities are never used.
Another performance issue arises in a workflow like PEA, which requires scaling the rates of a single model with different scale factors. This can be achieved in the current implementation by calling the scale_rates method, which returns a new model with the scaled rates and a copy of the corresponding QubitSparsePauliList. Here, the performance concern is that the QubitSparsePauliList is being unnecessarily copied: the same list of operators is required for sampling regardless of the scale factor being used. Note that a similar issue exists in workflows requiring application of different opacity filters to a single model.
@jakelishman proposed the following solution to these issues:
- Introduce a class representing
ratesthat pre-computes the derived quantities, and a function (or method) for sampling that takes a class and aQubitSparsePauliListof the same length as input. - Drop the internal precomputation in
PauliLindbladMap.
The sampling methods attached to PauliLindbladMap will still remain, though will become slightly less performant. Other direct uses of PauliLindbladMap will become more performant (as the precomputations will no longer be being done). A user who requires high performance sampling will use the new class and function to perform the pre-computation only when needed, and can sample using scaled/modified rates by referencing a single QubitSparsePauliList without needing to create new copies.
I'd like to work on this issue and try to design a solution as Jake suggested. Would you please assign me this issue: @jakelishman / @eliarbel ?