-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Update AQT Backend #6441
Update AQT Backend #6441
Conversation
…irq into update-aqt
Update AQT Backend
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
cirq-aqt/cirq_aqt/aqt_device.py
Outdated
if len(operation.qubits) == 1: | ||
for idx in xtlk_arr.nonzero()[0]: | ||
exponent = operation.gate.exponent # type:ignore | ||
exponent = exponent * xtlk_arr[idx] | ||
xtlk_op = gate.on(system_qubits[idx]) ** exponent | ||
xtlk_op = operation.gate.on(system_qubits[idx]) ** exponent |
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 there needs to be a check here and on 138 to exclude the case when operation.gate is None.
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! Fixed.
cirq-aqt/cirq_aqt/aqt_sampler.py
Outdated
@@ -40,16 +41,68 @@ class AQTSampler(cirq.Sampler): | |||
runs a single circuit or an entire sweep remotely | |||
""" | |||
|
|||
def __init__(self, remote_host: str, access_token: str): | |||
def __init__(self, workspace: str, resource: str, access_token: str, remote_host: str = "https://arnica.aqt.eu/api/v1/"): |
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.
Is there a reason to reorder the arguments? Is it because of the default argument?
If we keep the order the same, it would be more backwards compatible. This is doubly important since all the arguments are strings, so if people are passing them by position, they could get out of order.
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.
Yes, it was because of the default argument. We preferred the definition of workspace and resource than requiring the user to piece together a URL, but this does require breaking backwards-compatibility. We figured that by requiring two arguments now, it would be clear enough that the "old way" is not the right way any more.
cirq-aqt/cirq_aqt/aqt_sampler.py
Outdated
@@ -40,16 +41,68 @@ class AQTSampler(cirq.Sampler): | |||
runs a single circuit or an entire sweep remotely | |||
""" | |||
|
|||
def __init__(self, remote_host: str, access_token: str): | |||
def __init__(self, workspace: str, resource: str, access_token: str, remote_host: str = "https://arnica.aqt.eu/api/v1/"): |
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.
Recommend putting "https://arnica.aqt.eu/api/v1/" into a constant at the top, such as
_DEFAULT_HOST = "https://arnica.aqt.eu/api/v1/"
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.
Yes, agreed. Fixed.
cirq-aqt/cirq_aqt/aqt_sampler.py
Outdated
self.remote_host = remote_host | ||
self.access_token = access_token | ||
|
||
@staticmethod | ||
def fetch_resources(access_token: str, remote_host: str = "https://arnica.aqt.eu/api/v1/") -> None: |
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.
Same here, put remote_host default as a constant.
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.
Fixed.
cirq-aqt/cirq_aqt/aqt_sampler.py
Outdated
raise RuntimeError('Got unexpected return data from server: \n' + str(response.json())) | ||
|
||
workspaces = cast(list, response.json()) | ||
col_widths = [19, 21, 20, 3] |
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.
What's with these random width numbers? It can't be 20, 20, 20?
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 are completely arbitrary and just literally the current longest possible strings. Happy to change.
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.
Maybe we should make it a constant. Or better yet, make it part of a different class rather than hardcode it in a sampler class. Also a line comment explaining that these are the current longest strings may be helpful.
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 was no real reason to initialise the values like that, so have adjusted this slightly.
cirq-aqt/cirq_aqt/aqt_sampler.py
Outdated
col_widths[1] = max(col_widths[1], len(resource['name'])) | ||
col_widths[2] = max(col_widths[2], len(resource['id'])) | ||
|
||
print("+-" + col_widths[0]*"-"+ "-+-" + col_widths[1]*"-" + "-+-" + col_widths[2]*"-" + "-+-" + col_widths[3]*"-" + "-+") |
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 would recommend creating a data structure here. Perhaps a dataclass or attrs that has workspace_id, resource_name, resource_id as member variables. Then, the function can return that. This will be more programmatically useful.
Optionally, you could then have print_resources somewhere that prints this out in this fixed width format.
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.
We considered this, but we currently need the user to manually choose the workspace and resource they want to use. By allowing these to be chosen programmatically somehow, it could introduce errors that might lead to confusion. There is also limited information currently provided by the API with which one would programmatically choose - it is literally just a list of acceptable workspace/resource IDs.
This is intended purely as a helper function to allow users to look up the ID of resources that they already have access to, in case they forgot to write them down or something.
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 still don't think this is good design. Having a Workspace class that contains names and ids of resources would be a natural way to encapsulate this information returned from the API, provide a good place to document what is returned, be more testable, and be more testable. You could then have a print() (or just put it in str) function on this class to print the information as it is here. It also would not take too much work to move this into a class.
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 certainly agree it's not good design. Have adapted slightly to expose a fetch as well as a print static method.
Used TypedDict instead of classes to stay consistent with what was already there. Note sure in hindsight that that was the best idea.
def _parse_legacy_circuit_json(self, json_str: str) -> list: | ||
"""Converts a legacy JSON circuit representation. | ||
|
||
Converts a JSON created for the legacy API into one that will work |
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.
Do these APIs have versions? "Converts a JSON created for the API v0.3 ..." would be more precise and less prone to misinterpretation when the newer than new API comes out next year (or whenever)
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.
Yes, now they do. Updated. Thanks!
cirq-aqt/cirq_aqt/aqt_sampler.py
Outdated
@@ -99,28 +152,78 @@ def _generate_json( | |||
raise RuntimeError('Cannot send an empty circuit') | |||
json_str = json.dumps(seq_list) | |||
return json_str | |||
|
|||
def _parse_legacy_circuit_json(self, json_str: str) -> list: |
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.
better typing would be "-> list[dict[str,str]]
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.
It's not quite so simple, but I've improved this return type anyway with better definitions for the operations.
cirq-aqt/cirq_aqt/aqt_sampler.py
Outdated
@@ -223,10 +341,12 @@ class AQTSamplerLocalSimulator(AQTSampler): | |||
sampler.simulate_ideal=True | |||
""" | |||
|
|||
def __init__(self, remote_host: str = '', access_token: str = '', simulate_ideal: bool = False): | |||
def __init__(self, workspace: str = "", resource: str = "", access_token: str = "", remote_host: str = "", simulate_ideal: bool = False): |
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.
Same here, it would be nice to preserve backwards compatibility.
Also, you can fix the formatting by running |
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 with a few last nits. Thanks for addressing comments.
@@ -36,11 +37,18 @@ | |||
gate_dict = {'X': cirq.X, 'Y': cirq.Y, 'Z': cirq.Z, 'MS': cirq.XX, 'R': cirq.PhasedXPowGate} | |||
|
|||
|
|||
class OperationString(Enum): |
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.
We should add a short docstring for this enum.
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 - fixed.
cirq-aqt/cirq_aqt/aqt_device.py
Outdated
'Y': cirq.depolarize(1e-3), | ||
'Z': cirq.depolarize(1e-3), | ||
'R': cirq.depolarize(1e-3), | ||
'Z': cirq.depolarize(0), |
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.
Should this use the enum 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.
Yes! Fixed. Thanks
It looks like there are some integration test failures. Once these are resolved, this should be good to merge! |
Sent you an invite to be a collaborator, which should allow you to run CI on your own. |
Thanks. Have a weird mismatch between formatting locally and on CI. Was missing some test coverage too, but let's pretend that didn't happen..! Looks like everything's passing now finally... |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #6441 +/- ##
========================================
Coverage 97.78% 97.79%
========================================
Files 1124 1124
Lines 95493 95680 +187
========================================
+ Hits 93380 93570 +190
+ Misses 2113 2110 -3 ☔ View full report in Codecov by Sentry. |
Adjusted the AQT backend so that it works with the new AQT Arnica API. We also updated the gateset to reflect what we support. As we made an extension to the API, we were able to add a feature that lists the workspaces and resources that are available to a user. We also updated tests and documentation accordingly. Fixes quantumlib#6379
Adjusted the AQT backend so that it works with the new AQT Arnica API. We also updated the gateset to reflect what we support.
As we made an extension to the API, we were able to add a feature that lists the workspaces and resources that are available to a user. We also updated tests and documentation accordingly.
Fixes #6379