-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fixed commutation checking between two Pauli product measurements #16023
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
Changes from 2 commits
19ab6ba
2b4b48e
6323efa
8ef7b5b
027aeb4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -496,6 +496,24 @@ impl CommutationChecker { | |
| _ => (), | ||
| }; | ||
|
|
||
| // Special handling for commutativity of two pauli product measurements | ||
| if let ( | ||
| OperationRef::PauliProductMeasurement(ppm1), | ||
| OperationRef::PauliProductMeasurement(ppm2), | ||
| ) = (op1, op2) | ||
| { | ||
| if cargs1 == cargs2 { | ||
| // If both PPMs write to the same classical bit, it's generally incorrect to interchange them. | ||
| // So we return true only if both PPMs are identical. | ||
| return Ok(qargs1 == qargs2 && ppm1 == ppm2); | ||
| } else { | ||
| // PPMs write to different classical bits, and they commute if and only if their pauli generators do. | ||
| let size = qargs1.iter().chain(qargs2.iter()).max().unwrap().0 + 1; | ||
| let pauli1 = try_pauli_generator(op1, qargs1, size).expect("extracting sparse observable generator from pauli product measurement in infallible"); | ||
| let pauli2 = try_pauli_generator(op2, qargs2, size).expect("extracting sparse observable generator from pauli product measurement in infallible"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not necessarily for this PR, but these observable_generator_from_ppm(ppm: &PauliProductMeasurement, qubits: &[Qubit], num_qubits: u32) -> SparseObservable {}that you can call here. (and It's generally not a great idea to go from a specific type (
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I was thinking about this, especially after reviewing your PRs :smiling. I have implemented this suggestion in 6323efa, mostly because I also needed to return the phase of the pauli in addition to the sparse observable.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This if num_cargs1 > 0 && num_cargs2 > 0 && cargs1 == cargs2 {
return Ok(op1 == op2);
}and avoid all the rest of the extra code?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, I have removed the |
||
| return Ok(pauli1.commutes(&pauli2, tol)); | ||
| } | ||
| } | ||
| // Handle commutations between Pauli-based gates among themselves, and with standard gates | ||
| // TODO Support trivial commutations of standard gates with identities in the Paulis | ||
| let size = qargs1.iter().chain(qargs2.iter()).max().unwrap().0 + 1; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| --- | ||
| fixes: | ||
| - | | ||
| Fixed commutativity check between two :class:`.PauliProductMeasurement` instructions | ||
| in the case that both instructions measure to the same classical bit. In this case, | ||
| the later measurement overwrites the result of the earlier measurement, and consequently, | ||
| interchanging the two measurement instructions inside the quantum circuit is generally | ||
| invalid. |
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.
From your PR comment, you were worried about the case$\mathcal O(n \lg n)$ for $n$ qubits.
(ZX, [0, 1])and(XZ, [1, 0]). The simplest algorithm would be to "canonicalise" both PPMs into sorted order in terms of theqargsand then do an elementwise comparison. That's (naively, at least)I wouldn't say you have to do that in this PR, though.
Fwiw, if the two PPMs are identical, then any optimisation that applies to one necessarily applies to the other too, so on the face of it, it doesn't really matter whether you report them as commuting or not, but it would matter if you're then intending to group things into mutually commuting terms; if you report them as falsely non-commuting then you might fail to commute another rotation through both measures and to cancel with something on the other side.
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.
Great point on collecting mutually commuting sets of gates - I have not thought of that.
I have fixed the canonicalization problem in 6323efa in the spirit of the existing code: constructing
SparseObservablegenerators and checking whether they are equal. In the process I realized thattry_pauli_generatorignores the phase of a pauli product measurement instruction, which is probably fine in general, but not in this particular case -- as this would lead to incorrectly commutingPPM("XYZ")andPPM("-XYZ").Note that constructing a
SparseObservableinstead of just retrieving the Pauli is an overkill, and I have a follow-up PR #15815 that significantly improves upon commuting PPRs/PPMs among themselves (including canonicalization, but temporary having the same problems that are being fixed here).