Skip to content
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

Retrieve old jobs #1099

Merged
merged 11 commits into from
Nov 13, 2024
18 changes: 9 additions & 9 deletions docs/source/get_started/access_info/access_info_qss.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
]
},
{
"cell_type": "markdown",
"id": "domestic-bryan",
"metadata": {},
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Infleqtion/client-superstaq/blob/main/docs/source/get_started/access_info/access_info_qss.ipynb) [![Launch Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/Infleqtion/client-superstaq/HEAD?labpath=docs/source/get_started/access_info/access_info_qss.ipynb)"
]
},
"cell_type": "markdown",
"id": "domestic-bryan",
"metadata": {},
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Infleqtion/client-superstaq/blob/main/docs/source/get_started/access_info/access_info_qss.ipynb) [![Launch Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/Infleqtion/client-superstaq/HEAD?labpath=docs/source/get_started/access_info/access_info_qss.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "70537a94",
Expand Down Expand Up @@ -679,7 +679,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"id": "16bdcfff",
"metadata": {},
"outputs": [
Expand All @@ -698,7 +698,7 @@
"source": [
"backend = provider.get_backend(\"ibmq_brisbane_qpu\")\n",
"job_id = job.job_id() # Here we use the job ID from above, but this can be any old job ID\n",
"job_old = backend.retrieve_job(job_id)\n",
"job_old = provider.get_job(job_id)\n",
"job_old.input_circuits(index=0).draw(output=\"mpl\")"
]
}
Expand Down
10 changes: 7 additions & 3 deletions qiskit-superstaq/qiskit_superstaq/superstaq_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,17 +172,21 @@ def run(

def retrieve_job(self, job_id: str) -> qss.SuperstaqJob:
"""Gets a job that has been created on the Superstaq API.

Args:
job_id: The UUID of the job. Jobs are assigned these numbers by the server during the
creation of the job.

Returns:
A `qss.SuperstaqJob` which can be queried for status or results.

Raises:
~gss.SuperstaqServerException: If there was an error accessing the API.
"""
warnings.warn(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Cirq's deprecation infrastructure. Here's an example

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth having our own deprecation warning decorator in gss?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What version should we say is the deadline for deprecation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do 0.5.40. I made it up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double checking. This is the warning body we will have

f'{qualname} was used but is deprecated.\n' f'It will be removed in cirq {deadline}.\n' f'{fix}\n'.
Given that the message will state that the function will be deprecated for a certain cirq version, should we use it for qss?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see. What we have now is fine then.

"The `.retrieve_job()` method of `SuperstaqBackend` has been deprecated, and will be "
"removed in a future version of qiskit-superstaq. Instead, use the `.get_job()`"
"method of `SuperstaqProvider`.",
DeprecationWarning,
stacklevel=2,
)
return qss.SuperstaqJob(self, job_id)

def compile(
Expand Down
24 changes: 24 additions & 0 deletions qiskit-superstaq/qiskit_superstaq/superstaq_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,30 @@ def backends(
superstaq_backends.append(self.get_backend(backend.target))
return superstaq_backends

def get_job(self, job_id: str) -> qss.SuperstaqJob:
"""Gets a job that has been created on the Superstaq API.

Args:
job_id: The UUID of the job. Jobs are assigned these numbers by the server during the
creation of the job.

Returns:
A `qss.SuperstaqJob` which can be queried for status or results.

Raises:
~gss.SuperstaqServerException: If there was an error accessing the API.
~gss.SuperstaqException: If retrived jobs are from different targets.
"""
job_ids = job_id.split(",")
jobs = self._client.fetch_jobs(job_ids)

target = jobs[job_ids[0]]["target"]

if all(target == val["target"] for val in jobs.values()):
return qss.SuperstaqJob(self.get_backend(target), job_id)
else:
raise gss.SuperstaqException("Job ids belong to jobs at different targets.")

def resource_estimate(
self, circuits: qiskit.QuantumCircuit | Sequence[qiskit.QuantumCircuit], target: str
) -> gss.ResourceEstimate | list[gss.ResourceEstimate]:
Expand Down
63 changes: 63 additions & 0 deletions qiskit-superstaq/qiskit_superstaq/superstaq_provider_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,69 @@ def test_get_balance() -> None:
assert ss_provider.get_balance(pretty_output=False) == 12345.6789


@patch("requests.Session.post")
def test_get_job(mock_post: MagicMock, fake_superstaq_provider: MockSuperstaqProvider) -> None:
qc = qiskit.QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 0], [1, 1])
backend = fake_superstaq_provider.get_backend("ibmq_brisbane_qpu")

with patch(
"general_superstaq.superstaq_client._SuperstaqClient.create_job",
return_value={"job_ids": ["job_id"], "status": "ready"},
):
job = backend.run(qc, method="dry-run", shots=100)

mock_post.return_value.json = lambda: {
"job_id": {
"status": "ready",
"target": "ibmq_brisbane_qpu",
}
}

assert job == fake_superstaq_provider.get_job("job_id")

# multi circuit job with a comma separated job_id
with patch(
"general_superstaq.superstaq_client._SuperstaqClient.create_job",
return_value={"job_ids": ["job_id1,job_id2"], "status": "ready"},
):
job = backend.run([qc, qc], method="dry-run", shots=100)

mock_post.return_value.json = lambda: {
"job_id1": {
"status": "ready",
"target": "ibmq_brisbane_qpu",
},
"job_id2": {
"status": "ready",
"target": "ibmq_brisbane_qpu",
},
}
assert job == fake_superstaq_provider.get_job("job_id1,job_id2")

# job ids belonging to different targets
with patch(
"general_superstaq.superstaq_client._SuperstaqClient.create_job",
return_value={"job_ids": ["job_id1,job_id2"], "status": "ready"},
):
job = backend.run([qc, qc], method="dry-run", shots=100)

mock_post.return_value.json = lambda: {
"job_id1": {
"status": "ready",
"target": "ibmq_brisbane_qpu",
},
"job_id2": {
"status": "ready",
"target": "ibmq_fez_qpu",
},
}
with pytest.raises(gss.SuperstaqException, match="Job ids belong to jobs at different targets"):
fake_superstaq_provider.get_job("job_id1,job_id2")


@patch("requests.Session.post")
def test_aqt_compile(mock_post: MagicMock, fake_superstaq_provider: MockSuperstaqProvider) -> None:
qc = qiskit.QuantumCircuit(8)
Expand Down