-
-
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
Two stage ZNE #2452
Two stage ZNE #2452
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2452 +/- ##
=======================================
Coverage 98.70% 98.70%
=======================================
Files 88 88
Lines 4083 4091 +8
=======================================
+ Hits 4030 4038 +8
Misses 53 53 ☔ View full report in Codecov by Sentry. |
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 work Farrokh! Needs a little bit of flushing out, but also there's not a whole lot to flush out! Nice that it's so simple.
I think a few small updates should get this merged, and then we can keep iterating once it's merged.
mitiq/zne/tests/test_zne.py
Outdated
@pytest.mark.parametrize( | ||
"extrapolation_factory", [RichardsonFactory, LinearFactory] | ||
) | ||
def test_two_stage_zne(noise_scaling_method, extrapolation_factory): |
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.
This test does a good job of testing the combined functionality, but it would be good to have individual unit tests for each of the functions separately. WDYT? Would it be redundant?
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 for now the combined test is good enough. As we iterate in future PRs and the functions get more complicated, it might be better to separate them then.
remove comment in test_zne.py Co-authored-by: nate stemen <[email protected]>
use Sequence instead of list in typehinting for scale_factors Co-authored-by: nate stemen <[email protected]>
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! Just two minor asks.
mitiq/zne/tests/test_zne.py
Outdated
if to_frontend == to_braket: | ||
assert all(isinstance(circ, braket.circuits.Circuit) for circ in circs) | ||
elif to_frontend == to_qiskit: | ||
assert all(isinstance(circ, qiskit.QuantumCircuit) for circ in circs) | ||
elif to_frontend == to_pennylane: | ||
assert all( | ||
isinstance(circ, pennylane.tape.QuantumTape) for circ in circs | ||
) | ||
elif to_frontend == to_pyquil: | ||
assert all(isinstance(circ, pyquil.quil.Program) for circ in circs) | ||
elif to_frontend == to_qibo: | ||
assert all(isinstance(circ, qibo.Circuit) for circ in circs) | ||
else: | ||
assert all(isinstance(circ, cirq.Circuit) for circ in circs) |
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.
These tests are redundant since we already know our scaling method functions preserve input type. E.g. fold_global
never converts a qibo.Circuit
to anything but a qibo.Circuit
. Since those tests cover this, let's leave it out from here for readability.
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 see, that makes sense. I'll remove these tests!
) | ||
@pytest.mark.parametrize( | ||
"to_frontend", | ||
[None, to_qiskit, to_braket, to_pennylane, to_pyquil, to_qibo], |
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.
[None, to_qiskit, to_braket, to_pennylane, to_pyquil, to_qibo], | |
[convert_to_mitiq, to_qiskit, to_braket, to_pennylane, to_pyquil, to_qibo], |
I think we can use this instead to leave the circuit as a cirq.Circuit
object instead of doing the check below.
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.
That makes it a bit cleaner indeed!
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.
Actually, convert_to_mitiq() returns a tuple (the circuit and a string). So you still need one check right (if to_frontend = convert_to_mitiq)?
mitiq/zne/zne.py
Outdated
def combine_results( | ||
scale_factors: Sequence[float], | ||
results: list[float], | ||
extrapolation_method: Callable[[list[float], list[float]], float], |
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.
Might want to generalize these to Sequence[float]
to make mypy happy.
Well done on having this in @FarLab. Later on it could be nice to have very short docs on the added functionality for modularization, maybe once we have more in other techniques, but we can also start with ZNE only. |
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.
Sorry for the delayed (and at this point posthumous) review. I added some comments to improve on it.
It would have been also nice to ship an example (perahps in a tutorial) where we use the new workflow, along with the code changes.
circuits = [] | ||
for scale_factor in scale_factors: | ||
circuits.append(scale_method(circuit, scale_factor)) | ||
|
||
return circuits |
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.
this should be a list comprehension fo sho
return [scale_method(circuit, s) for s in scale_factors]
res = extrapolation_method(scale_factors, results) | ||
|
||
return res |
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.
unnecessary variable
return extrapolation_method(scale_factors, results)
"to_frontend", | ||
[None, to_qiskit, to_braket, to_pennylane, to_pyquil, to_qibo], | ||
) | ||
def test_two_stage_zne( |
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.
There should be two separete unit tests for the two new functions you implemented. This is an integration test, and one bad symptom is that this test is violating the AAA pattern.
This PR modularizes ZNE using the design described in #2439.