-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
More conservative caching in the CommutationChecker
#13600
Conversation
One or more of the following people are relevant to this code:
|
Pull Request Test Coverage Report for Build 12652621375Warning: This coverage report may be inaccurate.This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.
Details
💛 - Coveralls |
Thanks @Cryoris, I agree that it's better to not cache a commutation relationship rather than to cache a wrong one. Nevertheless, I thought we had a way both to check and to store that |
Yes, we cover the parametric We can also discuss this with the team, whether this is the right approach or we should rather make the assumption that gate instances do only differ by their |
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.
I think that caching/checking commutation relations for standard gates only makes a lot of sense. I had a few in-line questions (probably showing that I have not fully followed the recent updates to commutation checking). One other question, if I remember correctly, at some point @brandhsn has generated a database of commutation relations, are we still using it, and if so, should it be regenerated for standard gates only?
I agree that a more long-term plan might be to rethink the role of params
when defining custom gates, but let's leave this as a possible followup.
self.assertTrue(scc.commute(NewGateCX(), [0, 2], [], CXGate(), [0, 1], [])) | ||
self.assertFalse(scc.commute(NewGateCX(), [0, 1], [], CXGate(), [1, 2], [])) | ||
self.assertTrue(scc.commute(NewGateCX(), [1, 4], [], CXGate(), [1, 6], [])) | ||
self.assertFalse(scc.commute(NewGateCX(), [5, 3], [], CXGate(), [3, 1], [])) | ||
cx_like = CUGate(np.pi, 0, np.pi, 0) | ||
self.assertTrue(scc.commute(cx_like, [0, 2], [], CXGate(), [0, 1], [])) | ||
self.assertFalse(scc.commute(cx_like, [0, 1], [], CXGate(), [1, 2], [])) | ||
self.assertTrue(scc.commute(cx_like, [1, 4], [], CXGate(), [1, 6], [])) | ||
self.assertFalse(scc.commute(cx_like, [5, 3], [], CXGate(), [3, 1], [])) |
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.
Please tell me if I understand correctly. NewGateCX
is not a standard gate, so with this PR we will no longer cache its commutation relations. And cx_like
is a standard gate (a CUGate
). This is why it makes sense to update the tests to reason about cx_like
instead of NewGateCX
, correct? However, the scc.commute
method should still be able to handle NewGateCX
. So maybe it makes sense to leave a test that deals with custom gates. Do we still have such a test?
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.
Correct to all of the above 👍🏻
We don't have a test using NewGateCX
concretely, only with the EvilRXGate
, which should test the same thing. I can add a test with NewGateCX
though just to be safe.
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, having an additional test for a benign custom gate makes sense.
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.
Added in 44457f7 👍🏻
def __init__(self, evil_input_not_in_param: float): | ||
""" | ||
Args: | ||
evil_input_not_in_param: The RX rotation angle. | ||
""" | ||
self.value = evil_input_not_in_param | ||
super().__init__("<evil laugh here>", 1, []) |
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.
I love this. This is what I meant earlier by saying that you are taking the art of writing tests to a whole new level 😄.
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.
LGTM, thanks for the fix and updating the tests.
@Mergifyio backport stable/1.3 |
✅ Backports have been created
|
* conservative commutation check * tests and reno * reno in the right location * more tests for custom gates (cherry picked from commit 93d796f)
) * conservative commutation check * tests and reno * reno in the right location * more tests for custom gates (cherry picked from commit 93d796f) Co-authored-by: Julien Gacon <jules.gacon@googlemail.com>
Summary
Fixes #13570.
This PR might require some discussion on what assumptions we have on custom
Instruction
s. However, if we cannot assume that an instruction's definition is fully specified by it'sparams
, then we cannot use theparams
as key in the commutation library. (We also sometimes put additional information outside ofparams
.)This PR makes the commutation cache more conservative, by only additionally caching standard gate relations, where we know the instructions are defined by it's
params
.Details and comments
The commutation checker currently caches commutations of any instruction with float-only
params
(with some hardcoded exceptions). This leads to problems if the instruction's definition depends on more than just theparams
, e.g. we could have a custom gate defined asCalling the commutation checker with an instance of this gate will then cache the first commutation, under the key
[]
(since theparams
are empty) and subsequent queries of the cache return the first commutation, regardless of the evil rotation angle. For exampleAnother solution could be to explicitly state the assumption that the gate must be fully specified by the
params
attribute, and we'd have to update some gates in the library.I ran the
test/benchmarks/utility_scale.py
benchmarks and could not see a regression on my laptop.