-
-
Notifications
You must be signed in to change notification settings - Fork 166
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
New QEM benchmarking method: "rotated" RB circuits #2028
New QEM benchmarking method: "rotated" RB circuits #2028
Conversation
3da2973
to
f8f1677
Compare
f8f1677
to
5b1d7aa
Compare
Codecov ReportAll modified lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #2028 +/- ##
==========================================
+ Coverage 98.28% 98.32% +0.03%
==========================================
Files 86 87 +1
Lines 4084 4118 +34
==========================================
+ Hits 4014 4049 +35
+ Misses 70 69 -1
☔ View full report in Codecov by Sentry. |
cab74c6
to
e261073
Compare
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.
Nice, quick, work! Looking forward to using this to do some more testing! I've got a few higher level comments before diving into the details.
Math
The math from the docstring isn't being displayed properly. You can either use double backslashes in place of the existings \
s, or you can use the following syntax.
:math:`equation`
for inline math, and
..math::
equation
for display math. An example of these in use can be found here:
Lines 94 to 104 in b6cb5c1
r"""Maps a set of Kraus operators into a single superoperator | |
matrix acting by matrix multiplication on vectorized | |
density matrices. | |
The returned matrix :math:`S` is obtained with the formula: | |
.. math:: | |
S = \sum_j K_j \otimes K_j^*, | |
where :math:`\{K_j\}` are the Kraus operators. | |
The mapping is based on the following isomorphism: |
API
The other thing that I could imagine we might want to use this function for is testing EM methods as a function of this \theta
, falling back on random value when it's not passed. That would allow us to write code such as
for theta in np.linspace(0, 2*np.pi, 50):
circuit = generate_rotated_rb_circuits(...) # passing theta in here
# calculate circuits noisy, ideal, and mitigated expval
# plot the error as a function of theta
Does this seem like something that would be interesting?
Combining this with generate_rb_circuits
Did you consider merging this function with the existing function? I could imagine we could allow that function to take a parameter theta
that would rotate the circuit midway through if it was passed in. Otherwise, returning the "standard" RB circuit. We probably want to avoid overloading functions with too many options, but this may be okay? Not suggesting we have to go this route, just curious if you considered it.
Benchmarking utilities consistency
This PR made me realize that our utilities to generate benchmarking circuits all return a single QPROGRAM
except for RB circuits (and now rotated RB circuits) where we return List[QPROGRAM]
. @andreamari is there a reason for this? I feel like we should try to be consistent here. This is not necessarily something we should address in this PR, but maybe it's something we want to open an issue for if we want to address it?
Thanks @natestemen! All good points to consider. I've fixed the math rendering. That's on me for looking too quickly at the math italics and centering in the API doc. As for combining the functions, I thought about it, but decided against it because when we insert the rotation, it's no longer really an RB circuit anymore, but rather a linear combination of Clifford groups whose ideal expectation values can vary in the interval
Changed my mind on the last point above because |
As for |
Allow user to set `theta` instead of randomly selecting in the function.
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 @Misty-W for the clean and simple solution!
I have only one doubt: are you sure about adding a layer many rotations (one for each qubit)?
Initially I was thinking of a single rotation gate applied to just one qubit, possibly a qubit approximately in the middle of the quantum register. If I am not wrong, this should also work and should produce (with very high probability) an expectation value which is exactly given by
With a layer of many rotations, if I am not wrong, the expectation value will contain a product of many sinusoidal functions. So
Mine are just untested guesses. So, a practical strategy is probably to just plot
Great work @Misty-W! @Misty-W @andreamari what do you think of adding this functionality to the main RB function, e.g., as a |
thanks for the suggestions @andreamari ! I've changed the function to only insert an Here are some plots of the output- seems to be what we want in terms of the rotation, but any idea why they are so "spiky"?
or alternatively,
|
About different plots with different simulation methods: About the spikes:
At the moment it's not easy to increase the number of qubits of RB circuits (this could be a new interesting issue), so my suggestions to avoid strange effects are:
You may have better solutions. I think anything is fine as long as the user is aware of the expected behavior and doesn't get surprised by unexpected results (as we did! 😃 ). |
Add check for pathological circuit Remove unused `seed` argument Wordsmith the docstring
@andreamari, since the Cirq random Clifford functions don't accept a random seed, I went with [Alternative A]:
|
RTD problem is unrelated to this PR- seems GitHub automatically shows a failure when RTD takes longer than 1 hour to finish building, even though it built successfully. |
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.
Hi Misty,
could you test if the new function produces a smooth Cos(theta) plot?
As you tried in this message.
I see some problems with the current code:
- Main problem: it seems that we replace a pathological circuit, i.e. the case with E(theta)=1, with a new random RB circuit but without the intermediate RZ gate. We should instead add the RZ gate otherwise E(theta) would still be = to 1, so still pathological.
- Second problem: the current code doesn't check if the second attempt is pathological as well.
Maybe a good pseudo-workflow is the following:
- Generate a RB circuit (
rb_circuit
) and save a copy of it (rb_copy
). - Insert a Z gate (equivalent to RZ(\pi) ) in the middle of the circuit.
- If the expectation value is close to 1, we have a pathological circuit, and we restart from step 1. Else, the case is not pathological, and we can go to next step.
- Insert the R_Z(theta) rotation in
rb_copy
and return it.
Whatever solution you decide to take, the final goal is having a smooth cos(theta) plot for the expectation value.
hi @andreamari,
Yes, I'll regenerate the plots with the new code.
I'm using |
Ah, I missed the "rotated" word. Now I see! Note also that you may enter an infinite recursion when theta is a multiple of 2pi. |
Add Cirq `qubit_characterization` author names Fix formatting
Add optional seed for rb circuits in `generate_rotated_rb_circuits`
In the end, I decided to use a seed. It lets the user generate a set of rotated RB circuits with different values of theta but otherwise the same circuit, which is useful for testing and troubleshooting. Once the user's workflow is set up, then they can randomly choose or sweep over To do this efficiently I used some code from the Cirq functions |
Plotting the expectation values as a function of theta at three seed values:
|
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.
Cool! Very nice to have the seed
option.
This LGTM, once the comments below are addressed.
Co-authored-by: Andrea Mari <[email protected]>
Define local random state from optional seed in `generate_rb_circuits`
thanks for the helpful comments @andreamari, @natestemen, and @nathanshammah! I think I've addressed everything, so once the tests pass here I'll merge this. |
Co-authored-by: nate stemen <[email protected]>
Description
Fixes #2005.
Add a function$R_z$ rotation inserted in the middle.
generate_rotated_rb_circuits
which generates a list of randomized benchmarking circuits, each with a randomThis benchmarking method enables testing QEM techniques in more general scenarios, closer to real-world applications in which expectation values can take arbitrary values.
Rotated randomized bencmarking circuits are randomized benchmarking circuits in which an$R_z(\theta)$ rotation is inserted in the middle, such that:
where$G_j$ are Clifford elements or Clifford gates.
The circuits generate expectation values which are sinusoidal functions of$\theta$ , which in the ideal (noiseless) case vary in a continuous interval of $E_{\rm ideal} \in [-1, 1]$ .
Since (up to factors of 2) we have$R_z(\theta) =cos(\theta) I + i \ sin(\theta) Z$ , the rotated Clifford circuit $C(\theta)$ can be written as a linear combination of just two Clifford circuits and, therefore, it is still easy to classically simulate.
License
Before opening the PR, please ensure you have completed the following where appropriate.