-
Notifications
You must be signed in to change notification settings - Fork 57
Add a Pauli frame tracking dialect #2188
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
base: main
Are you sure you want to change the base?
Conversation
multiphaseCFD
left a comment
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 @joeycarter for the nice work! Looks good to me. Just left a few minor comments/question.
dime10
left a comment
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.
Love it! 😍
The one thing I wonder is whether the pauli frame ops should generate new qubits 🤔 After all, they don't write to the qubits (they read/write from pauli frame which is a hidden state (no value for it in the ir)?), the only exception is the flush op so there it makes sense.
Thanks!
I was wondering this as well when I was building the interface. The reason I opted for this design was to easily replace Pauli gates with calls to the Pauli frame tracker. For example, given then program, %0 = quantum.alloc( 1) : !quantum.reg
%1 = quantum.extract %0[ 0] : !quantum.reg -> !quantum.bit
%2 = quantum.custom "Hadamard"() %1 : !quantum.bit
%3 = quantum.custom "PauliX"() %2 : !quantum.bit
%4 = quantum.custom "Hadamard"() %3 : !quantum.bitwe will eventually want to have a pass that replaces the PauliX gate with a %0 = quantum.alloc( 1) : !quantum.reg
%1 = quantum.extract %0[ 0] : !quantum.reg -> !quantum.bit
%2 = quantum.custom "Hadamard"() %1 : !quantum.bit
%3 = pauli_frame.update [true, false] %2 : !quantum.bit
%4 = quantum.custom "Hadamard"() %3 : !quantum.bitThis way it's easy to replace ops without extra management of the qubit SSA values. We'll also need to consider commutation relations at some point, so returning an updated qubit value helps keep track of the operation order (although we're still working out the mechanics of how this will work). Do you see an alternative design that might work here instead? |
Replacing (or erasing) a quantum gate is actually quite easy, you would just call reaplaceAllUses on the output qubits with the input qubits.
That's a good point, if the pauli frame op consumes the same qubit value as another gate, there is no defined ordering between the two (at least on the SSA graph), the ordering would only be defined when considering the absolute ordering in the block's op list. MLIR passes won't mess with this ordering if the op is effectful, but our transforms might if we don't pay attention. In this case your current design might be safer then 👍 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2188 +/- ##
==========================================
+ Coverage 97.40% 97.48% +0.07%
==========================================
Files 93 93
Lines 10684 10690 +6
Branches 1027 1027
==========================================
+ Hits 10407 10421 +14
+ Misses 216 209 -7
+ Partials 61 60 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Yes I agree, it might not be strictly necessary to return the qubit, but it's safer for the time being, given our current knowledge of the system. In that case I propose we leave it as. |
multiphaseCFD
left a comment
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 @joeycarter ! LGTM
|
How does it handle updates like "commute current record past Hadamard"? |
That is an excellent point @lillian542 , this feature seems to be currently missing. I believe we could change the signature of |
|
Moving this PR back to draft while we discuss design choices. |
Context: A Pauli frame tracker [1] is a system that tracks gates from the Pauli group in classical electronics instead of physically applying them to qubits on the device. Doing so reduces the number of quantum operations applied to the system, thus reducing the probability of errors. This PR adds a Pauli frame tracking dialect to Catalyst and includes a set of abstractions and operations for interacting with an external Pauli frame tracking library.
[1] Knill, E. Quantum computing with realistically noisy devices. Nature 434, 39-44 (2005). https://doi.org/10.1038/nature03350.
Description of the Change: The
PauliFramedialect includes the following operations:pauli_frame.init, which initializes the Pauli record of the target qubit(s) to I.pauli_frame.init_qreg, same aspauli_frame.initexcept it initializes theh Pauli records of all the qubits in a quantum register.pauli_frame.update, which updates the Pauli record of the target qubit(s) given a new Pauli record.pauli_frame.read, which reads the Pauli record of the target qubit.pauli_frame.correct_measurement, which corrects a measurement result given a Pauli record.pauli_frame.flush, which flush the Pauli record(s) of the target qubit(s) (flushing means physically applying the Pauli gates in the record and re-initializing).pauli_frame.set, an extra op which sets the Pauli record of the target qubit(s).Note that this PR only adds the dialect itself. Future PRs will add compilation passes to insert these ops into the quantum program IR and to lower them to runtime stubs that call into a (thus far) mocked out Pauli frame tracking runtime library.
[sc-103530]