-
Notifications
You must be signed in to change notification settings - Fork 61
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
Minor improvement to quantum_info.random_clifford
#1259
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1259 +/- ##
==========================================
- Coverage 99.85% 99.84% -0.01%
==========================================
Files 73 73
Lines 10638 10645 +7
==========================================
+ Hits 10623 10629 +6
- Misses 15 16 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Ok this is ready @renatomello |
@@ -204,7 +204,8 @@ def _find_repeated(qubits: Sequence[int]) -> int: | |||
def _check_control_target_overlap(self): | |||
"""Checks that there are no qubits that are both target and | |||
controls.""" | |||
common = set(self._target_qubits) & self._control_qubits | |||
control_target = self._target_qubits + self._control_qubits | |||
common = len(set(control_target)) != len(control_target) | |||
if common: | |||
raise_error( | |||
ValueError, |
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.
common
used to be a set
but now it is a bool
, therefore the error message defined under this line (GitHub does not let me comment there because it is not changed in this PR) will stop making sense. It will probably read:
ValueError("True qubits are both targets and controls for gate ...")
which doesn't make much sense. It should be modified accordingly.
Other than that, what is the motivation of switching _control_qubits
from set
to tuple
? Just symmetry with _target_qubits
? (not intending to say that the current code is the best, I am sure it can be simplified in many ways)
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.
Other than that, what is the motivation of switching
_control_qubits
fromset
totuple
? Just symmetry with_target_qubits
? (not intending to say that the current code is the best, I am sure it can be simplified in many ways)
In [1]: %timeit set()
63.8 ns ± 4.93 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
In [2]: %timeit set()
55.9 ns ± 2.81 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
In [3]: %timeit list()
61.4 ns ± 3.49 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
In [4]: %timeit tuple()
28.8 ns ± 0.179 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
In [5]: %timeit []
23 ns ± 2.33 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)
In [6]: %timeit ()
7.33 ns ± 0.0883 ns per loop (mean ± std. dev. of 7 runs, 100,000,000 loops each)
It's 7x faster. Even though it's in the ns
scale, it makes a difference when creating tens or even hundreds of thousands of gates e.g. random_clifford
for 1000+ qubits.
Another thing that we noted is that every single qubit gate is inheriting a control_qubits attribute from the abstract Gate class. This means that every single qubit gate carries an empty tuple with it, unless the method controlled_by is used and the tuple is filled. It may be worth for single qubit gates to move the initialization of control_qubits to inside the control_qubits method. That would make the creating of gates slightly faster and the objects slightly lighter. |
Co-authored-by: Renato Mello <[email protected]>
for more information, see https://pre-commit.ci
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 @renatomello for the explanation regarding the set
. I was not aware about this overhead. This PR looks good to me.
Another thing that we noted is that every single qubit gate is inheriting a control_qubits attribute from the abstract Gate class. This means that every single qubit gate carries an empty tuple with it, unless the method controlled_by is used and the tuple is filled. It may be worth for single qubit gates to move the initialization of control_qubits to inside the control_qubits method. That would make the creating of gates slightly faster and the objects slightly lighter.
I wouldn't expect that this adds that big of an overhead. If it does, I am fine with dropping it for single qubit gates, however, we should be a bit careful with .controlled_by
because it is not good practice to add new attributes to objects outside __init__
(pylint
may even complain if you do this). Then I guess .controlled_by
would have to create a different gate instance for the controlled version of the gate (which has control_qubits
), but I am also not sure if it's a good solution because we'd have to replicate every non-controlled gate to support that.
In any case, I would postpone to another PR, but feel free to open an issue if you think control_qubits
should be dropped.
Minor improvement to
quantum_info.random_clifford
.Checklist: