From cbb1552197d1b2e358f9d42d24bedd413259e843 Mon Sep 17 00:00:00 2001 From: Nathnael Bekele <135308096+natibek@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:14:40 -0600 Subject: [PATCH] Retrieve old jobs (#1099) --- .../access_info/access_info_qss.ipynb | 18 +++--- .../qiskit_superstaq/superstaq_backend.py | 10 ++- .../qiskit_superstaq/superstaq_provider.py | 24 +++++++ .../superstaq_provider_test.py | 63 +++++++++++++++++++ 4 files changed, 103 insertions(+), 12 deletions(-) diff --git a/docs/source/get_started/access_info/access_info_qss.ipynb b/docs/source/get_started/access_info/access_info_qss.ipynb index 7ab1518b4..82eb3cbed 100644 --- a/docs/source/get_started/access_info/access_info_qss.ipynb +++ b/docs/source/get_started/access_info/access_info_qss.ipynb @@ -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", @@ -679,7 +679,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "16bdcfff", "metadata": {}, "outputs": [ @@ -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\")" ] } diff --git a/qiskit-superstaq/qiskit_superstaq/superstaq_backend.py b/qiskit-superstaq/qiskit_superstaq/superstaq_backend.py index 6dd8aa44a..4e8ad8a85 100644 --- a/qiskit-superstaq/qiskit_superstaq/superstaq_backend.py +++ b/qiskit-superstaq/qiskit_superstaq/superstaq_backend.py @@ -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( + "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( diff --git a/qiskit-superstaq/qiskit_superstaq/superstaq_provider.py b/qiskit-superstaq/qiskit_superstaq/superstaq_provider.py index 555b6ebc4..521bc49ff 100644 --- a/qiskit-superstaq/qiskit_superstaq/superstaq_provider.py +++ b/qiskit-superstaq/qiskit_superstaq/superstaq_provider.py @@ -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]: diff --git a/qiskit-superstaq/qiskit_superstaq/superstaq_provider_test.py b/qiskit-superstaq/qiskit_superstaq/superstaq_provider_test.py index a705f4193..75930ef27 100644 --- a/qiskit-superstaq/qiskit_superstaq/superstaq_provider_test.py +++ b/qiskit-superstaq/qiskit_superstaq/superstaq_provider_test.py @@ -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)