-
Notifications
You must be signed in to change notification settings - Fork 54
Error Generator Propagation Module #538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Moved some files around, integrated stim translations into pyGSTi, Added a tutorial notebook to examples
This is the initial commit for the addition of functionality in pygsti for modeling systems with LFH noise present. This adds a new lfh module to extras (for now) which includes a special type of LindbladErrorgen that can have gaussianly fluctuating hamiltonian parameters. Additionally this adds a special LFH aware explicit model class, and a number of specialized forward simulators.
…into feature-LFH-noise
…yGSTio/pyGSTi into feature-Propagatable-ErrorGens
…into feature-LFH-noise
…into feature-LFH-noise
Start refactoring variable names and begin work on making the error generator propagator into a class.
Added Analytic Propagation
…into feature-LFH-noise
Relocate the error generator propagation code from extras into a proper pyGSTi submodule.
…s' into feature-errorgen-propagation-refactors
First real commit updating the implementation of the error generator propagation code. Still a big mess at the moment, but there are enough folks wanting to use it even as it currently is that it makes sense to make this available while still partially broken and in development flux.
I hadn't yet updated that codepath after adding in the 'include_spam' kwarg so needed to patch this in.
Fixes an error in the first order BCH logic that meant that when including SPAM the final measurement layer's error generator wasn't getting combined in.
My initial (complete) attempt at updating the implementation of the error generator commutator psuedocode to get it working. Next up is testing.
Generalize the implementation of CompleteElementaryErrorgenBasis to add support for local error generator label types. This enables constructing bases with element matrices that are given on the full space, rather than restricted to the nontrivial subspace, which is useful for some applications. Also add a new casting method for LocalStimErrorgenLabel to allow conversion from other label types/label-like objects.
First pass at trying to resolve the fact that we typically only store have the C and A generators due to symmetry, meaning there is a preferred basis label ordering.
This fixes a bunch of issues with the error generator commutators. Particularly tracking down some missing factors of 2 and -1 and i.
Fix some errors in the commutator code that meant some of the S terms were not being calculated properly for the C/A and A/A commutators.
This adds a stab at functionality for random CP constrained error generators. In addition to enforcing the CP constraint, this also allows features like: specifying a target error rate, fixing particular error generator rates (while selecting the rest randomly), setting weights for the H and S sectors, and specifying error generator type/weight/sslbl overlap constraints.
Add in support for higher-order BCH up to fourth order.
Add in support for implicit models. The main change here is a switch to using the model's circuit_layer_operator method to grab the requisite error generators for each circuit layer, rather than grabbing these from the model's member dictionaries directly as works for explicit models.
Patch an issue in the random error generator construction code which had previously meant that we were getting non-CP maps when we didn't have both C and A present. It looks like with this new construction scheme we're getting CP error generators even when only using one or the other (and also when having mismatched weights).
Fix an error that occurred when not all maximum weights were specified and/or specifiable.
Add the ECR gate to the stim conversion dictionary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks as always for the very thorough work @coreyostrove! I have a few questions/comments to discuss, but nothing super critical. Having this with docstrings/unit tests/Jupyter notebook working for me locally + your PR explanation goes a long way in making this go smoothly :)
jupyter_notebooks/Tutorials/algorithms/ErrorGeneratorPropagation.ipynb
Outdated
Show resolved
Hide resolved
pygsti/tools/errgenproptools.py
Outdated
# http://www.apache.org/licenses/LICENSE-2.0 or in the LICENSE file in the root pyGSTi directory. | ||
#*************************************************************************************************** | ||
|
||
import stim |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noting another unguarded STIM.
Add a number of changes to address feedback on PR. Adds some try-excepts around stim imports, fixes a few bugs and renames a function.
Quick note. Took a look to see why the unit tests failed and this looks like an innocuous (but interestingly platform dependent) false-postive due to some comparison logic:
TLDR: The test didn't like that 2e-17 wasn't exactly zero. That level of difference isn't actually meaningful though so I'll rework this test to use different comparison logic that doesn't trigger for something like this. |
Addendum: I was kind of confused by the fact that this triggered at all. The numpy
Where the default value of atol is 1e-8. But it turns out that the function |
Minor change to test tolerance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After discussion in dev meeting, we will keep this in its own submodule for now and will revisit that as it integrates in/stuff gets built on top of it.
This PR introduces version 1.0 of a new pyGSTi module for the efficient approximate simulation of noisy Clifford circuits using a technique based on the analytic propagation of elementary error generators. This is a rather major update and will likely be challenging to review just due to the sheer amount of code that has been added or touched, so I will do my best to summarize notable changes and additions below. Where relevant I'll also discuss any notable architectural/design considerations that may be relevant for reviewers.
Overview of Changes
Error Generator Propagator Class
The central new class for the error generator propagation module is
ErrorGeneratorPropagator
. This class houses the main methods responsible for performing/orchestrating the propagation of elementary error generators to the end of a circuit, and managing any post-propagation processing related to producing effective end-or-circuit error generators (e.g. iterative application of the BCH approximation). This class wraps/contains a reference to a corresponding model, and responsibility for generating sparse representations of the per-circuit layer error generators (i.e. error generator coefficient dictionaries) needed to instantiate the propagation computation is delegated to this model. As such, all of the functionality described in this PR should be compatible with any error-generator parameterized model, or otherwise any model able to return per-circuit-layer error generator coefficient dictionaries).Stim is a dependency now
The functionality of this module is inextricably built on top of stim as a backend for fast stabilizer tableau related computations, so with this module is now added to the requirements list for pyGSTi.
LocalStimErrorgenLabel Class
To help manage metadata and other functionality which is helpful in the context of error generator propagation we've introduced a new
ElementaryErrorgenLabel
subclass calledLocalStimErrorgenLabel
. In many ways this class is similar to the existingLocalElementaryErrorgenLabel
class, both store their basis element subscript labels in a 'local' format for example. I.e. as full n-qubit pauli strings, but for LocalStimErrorgenLabel these are now instances ofstim.PauliString
objects instead of python strings (heavily reducing the overhead of conversion back and forth throughout the propagation code). This class is also responsible for one of the core subroutines in propagation, being delegated the responsibility of mapping its basis element labels to their new value under conjugation by a Clifford operation. To simplify interoperability between this new class and other existing parts of pyGSTi which don't presently natively support these new labels (perhaps at some point we'll change that) this class has built-in methods for casting itself to instances ofLocalElementaryErrorgenLabel
orGlobalElementaryErrogenLabel
, as well as for casting from instances of these classes.New
errgenproptools
moduleTo support the functionality of the
ErrorGeneratorPropagator
class, as well as extend those capabilities in other directions, there is a new module inpygsti.tools
with a large number of related utilities. Here is an overview:Lots of supporting backend changes
In no particular order (I'm just going to go top to bottom through the diff summary and may skip any de minimis or obvious ones). This section will probably be the longest of this write up, mostly because backend changes touch a lot of pyGSTi code and are the hardest to understand without context.
Basis
performance improvements. Previously certain frequently accessed basis properties corresponding to properties that should be static were recomputed on the fly (e.g. the dimension, or the component bases). This slowed down certain subroutines (particularly hashing). We now precompute these quantities at initialization time (the actual computations are cheap, the slow part was redoing them thousands of times) and cache their values internally. There is also some rudimentary caching added for the basis transformation matrix construction (just a fairly small LRU cache) which significantly reduces the overhead of converting multiple matrices from one matrix to another. (It looks like I must have also found an edge case in the original hashing function but I don't recall the details on that anymore.)CompleteElementaryErrorgenBasis
andExplcitElementaryErrorgenBasis
have been notably extended. This includes:CompleteElementaryErrorgenBasis
. Users can now specify separate maximum weights for all 4 sectors (previously you could only separately control the weights of the H block and the SCA block as a whole). There is also now an option for controlling the format of the elementary error generators used by the basis (either local or global style).LocalElementaryErrorgenLabel
andGlobalElementaryErrorgenLabel
:StateSpace
is now effectively static. Certain attributes that were previous exposed as part of the public API and potentially mutable are now protected as properties. This change was made for two reasons: 1. We were pretty much already treating state spaces as immutable in practice, I didn't find any instance in pyGSTi where we do inplace state space manipulation and all of the state space methods that involve mutation already returned new objects and avoided inplace manipulation. 2. Enforcing this means we can start caching hashes to improve performance, which in-turn improves the performance of certain operations involving theBasis
class.Circuit
class now has two new methods for conversion from a pyGSTi circuit (clifford only) to either a list ofstim.Tableau
objects (one per circuit layer), or a single
stim.Tableau
corresponding to the combined clifford operation for the overall circuit. There have also been requests for conversion in the other direction (stim to pyGSTi), so that is on the roadmap for a future version.LocalElementaryErrorgenLabel
. Previously most functions which involved working with elementary error generator labels assumed that these labels were instances ofGlobalElementaryErrorgenLabel
and these were the labels used internally in many/most error generator related model members, for example. The exception to this is the code which actually constructs elementary error generator matrices which requires basis element labels which are in the local-style and so casted the error generator coefficients toLocalElementaryErrorgenLabel
. Anyhow, rather than go on and on, all of this conversion back and forth in different contexts and doing lots of casting (sometimes multiple casts for a single operation) was a real performance bottleneck when instantiating error generator dictionaries for a circuit layer when instantiating propagation. To address this I've rewritten these code paths to allow working interchangeably with both label types, and all of the relevant methods now have the option of specifying which type of label you'd like returned. I've also added some caching to reduce the overhead of switching back and forth between the requested label types in different contexts.-
LindbladErrorgen
andLindbladCoefficientBlock
:LindbladCoefficientBlock
the performance of constructing error generator coefficient dictionaries was improved, and caching was added for these so that the dictionaries are only reconstructed when block data has been changed. Previously it would reconstruct this from scratch each time it was requested which was a big bottleneck..LindbladErrorgen
aside from changes related to adding first-class support for local labels as described in the previous point, we now finally have nearly completely coverage and up-to-date documentation for this module! (GPT helped me out a bit).lindbladtools
: Faster dense elementary error generator construction. This is achieved two ways.Miscellaneous
lindbladtools
called forrandom_error_generator_rates
for generating random (CP-constrained) error generators. This has been a frequently requested utility and includes a number of requested features from end-users:Unit tests and Tutorial
Finally, the new error generator propagation module is backed up by a relatively complete suite of unit tests. I've also written brand new test modules for the new/existing error generator basis code and the error generator label code which we previously didn't have any coverage for.
In addition there is a new tutorial covering the main features and usage of this module located in the tutorials sub-folder on algorithms.
Final comment
When you're reviewing this you'll notice some commented out code in a module related to low-frequency Hamiltonian models. When I originally started writing this I thought that these two modules would be inextricably linked and worked on their development in parallel. But that turned out not to be true and rewriting the git history to extricate these changes from the rest would be very hard as far as I can tell. Expect a separate PR related to this LFH code in the next month or two (I'm willing to commit to cleaning this up in advance of the next major release), but for now I'd ask you to pretend it isn't there.
Special thanks go out to @ashenmill for getting the ball rolling and for consultation throughout the development of this module. Thanks also go out to @tjproct, @jordanh6 and @kevincyoung for their help working out theory, and to @sserita and @enielse for their help with debugging and design advice.