From d99cf516fe5d12d67b632b08e653c1eea7fe1d33 Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Tue, 26 Nov 2024 14:42:55 +0000 Subject: [PATCH 1/4] Fix folder not existing --- docs/guides/serverless-manage-resources.ipynb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/guides/serverless-manage-resources.ipynb b/docs/guides/serverless-manage-resources.ipynb index 33813a01eb4..c83eb61d56e 100644 --- a/docs/guides/serverless-manage-resources.ipynb +++ b/docs/guides/serverless-manage-resources.ipynb @@ -36,6 +36,23 @@ "For classical tasks that can be parallelized, use the `@distribute_task` decorater to define compute requirements needed to perform a task. Start by recalling the `transpile_parallel.py` example from the [Write your first Qiskit Serverless program](./serverless-first-program) topic:" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e41cd2f-bce6-4c8a-8e44-537c18b3023c", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# This cell is hidden from users, it just creates a new folder\n", + "from pathlib import Path\n", + "\n", + "Path(\"./source_files\").mkdir(exist_ok=True)" + ] + }, { "cell_type": "code", "execution_count": null, From 54328a6e1d52d6dee12ffbb86d709236220c1dde Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Tue, 26 Nov 2024 16:12:37 +0000 Subject: [PATCH 2/4] Add tests and remove broken functionality --- docs/guides/serverless-manage-resources.ipynb | 188 ++++++++---------- scripts/config/notebook-testing.toml | 2 +- 2 files changed, 81 insertions(+), 109 deletions(-) diff --git a/docs/guides/serverless-manage-resources.ipynb b/docs/guides/serverless-manage-resources.ipynb index c83eb61d56e..eb6a45b7f31 100644 --- a/docs/guides/serverless-manage-resources.ipynb +++ b/docs/guides/serverless-manage-resources.ipynb @@ -33,7 +33,7 @@ "id": "b2d40a63-3359-46e9-8f1b-4746b449b407", "metadata": {}, "source": [ - "For classical tasks that can be parallelized, use the `@distribute_task` decorater to define compute requirements needed to perform a task. Start by recalling the `transpile_parallel.py` example from the [Write your first Qiskit Serverless program](./serverless-first-program) topic:" + "For classical tasks that can be parallelized, use the `@distribute_task` decorater to define compute requirements needed to perform a task. Start by recalling the `transpile_remote.py` example from the [Write your first Qiskit Serverless program](./serverless-first-program) topic:" ] }, { @@ -138,6 +138,75 @@ "save_result(results) # Overwrites any previously saved results" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "757f81e9-3981-4358-a1a2-d3262c7cddcd", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "%%writefile --append ./source_files/transpile_remote.py\n", + "# This cell is hidden from users. It checks the transpilation ran correctly.\n", + "from qiskit import QuantumCircuit\n", + "assert all(isinstance(result, QuantumCircuit) for result in results)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df28a92c-3585-49f0-a2ea-828a34638684", + "metadata": {}, + "outputs": [], + "source": [ + "# This cell is hidden from users.\n", + "# It uploads the serverless program and checks it runs.\n", + "\n", + "\n", + "def test_serverless_job(title, entrypoint):\n", + " # Import in function to stop them interfering with user-facing code\n", + " from qiskit.circuit.random import random_circuit\n", + " from qiskit_serverless import IBMServerlessClient, QiskitFunction\n", + " import time\n", + " import uuid\n", + "\n", + " title += \"_\" + uuid.uuid4().hex[:8]\n", + " serverless = IBMServerlessClient()\n", + " transpile_remote_demo = QiskitFunction(\n", + " title=title,\n", + " entrypoint=entrypoint,\n", + " working_dir=\"./source_files/\",\n", + " )\n", + " serverless.upload(transpile_remote_demo)\n", + " job = serverless.get(title).run(\n", + " circuit=random_circuit(3, 3),\n", + " circuit_list=[random_circuit(3, 3) for _ in range(3)],\n", + " backend=\"ibm_kyiv\",\n", + " optimization_level=1,\n", + " )\n", + " for retry in range(25):\n", + " time.sleep(5)\n", + " status = job.status()\n", + " if status == \"DONE\":\n", + " print(\"Job completed successfully\")\n", + " return\n", + " if status not in [\"QUEUED\", \"INITIALIZING\", \"RUNNING\", \"DONE\"]:\n", + " raise Exception(\n", + " f\"Unexpected job status '{status}'.\\nHere's the logs:\\n\"\n", + " + job.logs()\n", + " )\n", + " print(f\"Waiting for job (status '{status}')\")\n", + " raise Exception(\"Job did not complete in time\")\n", + "\n", + "\n", + "test_serverless_job(\n", + " title=\"transpile_remote_serverless_test\", entrypoint=\"transpile_remote.py\"\n", + ")" + ] + }, { "cell_type": "markdown", "id": "611fe030-4494-46b5-9ea1-9678ac513210", @@ -169,118 +238,21 @@ " return None" ] }, - { - "cell_type": "markdown", - "id": "6bc45489-56d0-4f46-8659-9df4d1555516", - "metadata": {}, - "source": [ - "## Manage data across your program\n", - "\n", - "Qiskit Serverless allows you to manage files in the `/data` directory across all your programs. This includes several limitations:\n", - "\n", - "- Only `tar` and `h5` files are supported today\n", - "- This is only a flat `/data` storage, and cannot have `/data/folder/` subdirectories\n", - "\n", - "The following shows how to upload files. Be sure you have authenticated to Qiskit Serverless with your [IBM Quantum account](https://quantum.ibm.com/account) (see [Deploy to IBM Quantum Platform](./serverless-first-program#deploy-to-ibm-quantum-platform) for instructions)." - ] - }, { "cell_type": "code", - "execution_count": 8, - "id": "0183278f-8ce3-4466-9255-097b2d211052", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'{\"message\":\"/usr/src/app/media/5f37582aa306c50013fac285/transpile_demo.tar\"}'" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import tarfile\n", - "from qiskit_serverless import IBMServerlessClient\n", - "\n", - "# Create a tar\n", - "filename = \"transpile_demo.tar\"\n", - "file = tarfile.open(filename, \"w\")\n", - "file.add(\"./source_files/transpile_remote.py\")\n", - "file.close()\n", - "\n", - "# Upload the tar to Serverless data directory\n", - "serverless = IBMServerlessClient()\n", - "serverless.file_upload(filename)" - ] - }, - { - "cell_type": "markdown", - "id": "4f762470-945f-48d5-a65b-c60d3b2dae3f", - "metadata": {}, - "source": [ - "Next, you can list all the files in your `data` directory. This data is accessible to all programs." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "14241fc4-d0cb-4803-8752-a460e1f48708", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['transpile_demo.tar']" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "serverless.files()" - ] - }, - { - "cell_type": "markdown", - "id": "a97bd83e-8250-43bb-b1c4-d40d822c7ba2", - "metadata": {}, - "source": [ - "This can be done from a program by using `file_download()` to download the file to the program environment, and uncompressing the `tar`." - ] - }, - { - "cell_type": "code", - "id": "ef649b2a-ed95-4dd2-89d9-61438faa7c1e", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [ + "remove-cell" + ] + }, "outputs": [], "source": [ - "%%writefile ./source_files/extract_tarfile.py\n", - "\n", - "import tarfile\n", - "from qiskit_serverless import IBMServerlessClient\n", - "\n", - "serverless = IBMServerlessClient(token=\"\")\n", - "files = serverless.files()\n", - "demo_file = files[0]\n", - "downloaded_tar = serverless.file_download(demo_file)\n", - "\n", - "\n", - "with tarfile.open(downloaded_tar, 'r') as tar:\n", - " tar.extractall()" - ] - }, - { - "cell_type": "markdown", - "id": "5b93dbdb-2060-468b-8496-ba98142a780b", - "metadata": {}, - "source": [ - "At this point, your program can interact with the files, as you would a local experiment. `file_upload()` , `file_download()`, and `file_delete()` can be called from your local experiment, or your uploaded program, for consistent and flexible data management." + "# This cell is hidden from users.\n", + "# It checks the distributed program works.\n", + "test_serverless_job(\n", + " title=\"transpile_remote_serverless_test\", entrypoint=\"transpile_remote.py\"\n", + ")" ] }, { diff --git a/scripts/config/notebook-testing.toml b/scripts/config/notebook-testing.toml index 6af53638592..a97b354d5eb 100644 --- a/scripts/config/notebook-testing.toml +++ b/scripts/config/notebook-testing.toml @@ -30,6 +30,7 @@ notebooks_normal_test = [ "docs/guides/operator-class.ipynb", "docs/guides/error-mitigation-and-suppression-techniques.ipynb", "docs/guides/serverless-first-program.ipynb", + "docs/guides/serverless-manage-resources.ipynb", "docs/guides/serverless-run-first-workload.ipynb", "docs/guides/specify-observables-pauli.ipynb", "docs/guides/qiskit-addons-aqc-get-started.ipynb", @@ -62,7 +63,6 @@ notebooks_that_submit_jobs = [ notebooks_no_mock = [ "docs/guides/get-started-with-primitives.ipynb", "docs/guides/hello-world.ipynb", - "docs/guides/serverless-manage-resources.ipynb", "docs/guides/noise-learning.ipynb", "docs/guides/qiskit-addons-obp-get-started.ipynb", ] From a4ab786659621a7e4ff1119b0fe5f582332deb89 Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Tue, 26 Nov 2024 16:12:47 +0000 Subject: [PATCH 3/4] Re-run notebook --- docs/guides/serverless-manage-resources.ipynb | 261 ++++++++++++++++-- 1 file changed, 243 insertions(+), 18 deletions(-) diff --git a/docs/guides/serverless-manage-resources.ipynb b/docs/guides/serverless-manage-resources.ipynb index eb6a45b7f31..f45ce1d4c5c 100644 --- a/docs/guides/serverless-manage-resources.ipynb +++ b/docs/guides/serverless-manage-resources.ipynb @@ -16,7 +16,28 @@ "version-info" ] }, - "source": [] + "source": [ + "
\n", + "Package versions\n", + "\n", + "The code on this page was developed using the following requirements.\n", + "We recommend using these versions or newer.\n", + "\n", + "```\n", + "qiskit[all]~=1.2.4\n", + "qiskit-ibm-runtime~=0.33.2\n", + "qiskit-aer~=0.15.1\n", + "qiskit-serverless~=0.18.0\n", + "qiskit-ibm-catalog~=0.2\n", + "qiskit-addon-sqd~=0.8.1\n", + "qiskit-addon-utils~=0.1.0\n", + "qiskit-addon-aqc-tensor~=0.1.2\n", + "qiskit-addon-obp~=0.1.0\n", + "scipy~=1.14.1\n", + "pyscf~=2.7.0\n", + "```\n", + "
" + ] }, { "cell_type": "markdown", @@ -38,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "9e41cd2f-bce6-4c8a-8e44-537c18b3023c", "metadata": { "tags": [ @@ -55,10 +76,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "475d82f0-15cc-4db3-b3b0-54b07822b2a0", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing ./source_files/transpile_remote.py\n" + ] + } + ], "source": [ "%%writefile ./source_files/transpile_remote.py\n", "\n", @@ -88,11 +117,19 @@ ] }, { - "id": "74fdcd4a-01cd-46ca-aa24-2a8a3605346f", "cell_type": "code", - "execution_count": null, + "execution_count": 3, + "id": "74fdcd4a-01cd-46ca-aa24-2a8a3605346f", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Appending to ./source_files/transpile_remote.py\n" + ] + } + ], "source": [ "%%writefile --append ./source_files/transpile_remote.py\n", "\n", @@ -121,11 +158,19 @@ ] }, { - "id": "ac99b4a0-4a42-4c43-869d-265344b70359", "cell_type": "code", - "execution_count": null, + "execution_count": 4, + "id": "ac99b4a0-4a42-4c43-869d-265344b70359", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Appending to ./source_files/transpile_remote.py\n" + ] + } + ], "source": [ "%%writefile --append ./source_files/transpile_remote.py\n", "\n", @@ -140,14 +185,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "757f81e9-3981-4358-a1a2-d3262c7cddcd", "metadata": { "tags": [ "remove-cell" ] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Appending to ./source_files/transpile_remote.py\n" + ] + } + ], "source": [ "%%writefile --append ./source_files/transpile_remote.py\n", "# This cell is hidden from users. It checks the transpilation ran correctly.\n", @@ -157,10 +210,95 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "df28a92c-3585-49f0-a2ea-828a34638684", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'QUEUED')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'QUEUED')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'QUEUED')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'QUEUED')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'INITIALIZING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'INITIALIZING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Job completed successfully\n" + ] + } + ], "source": [ "# This cell is hidden from users.\n", "# It uploads the serverless program and checks it runs.\n", @@ -223,10 +361,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "cea90969-cfbf-4181-9ffa-524f3709dc69", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Appending to ./source_files/transpile_remote.py\n" + ] + } + ], "source": [ "%%writefile --append ./source_files/transpile_remote.py\n", "\n", @@ -240,13 +386,92 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, + "id": "55163053-2cd8-4e5d-8470-d08055a6f401", "metadata": { "tags": [ "remove-cell" ] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'QUEUED')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'QUEUED')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'INITIALIZING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'INITIALIZING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Waiting for job (status 'RUNNING')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Job completed successfully\n" + ] + } + ], "source": [ "# This cell is hidden from users.\n", "# It checks the distributed program works.\n", From ca071552dea60a410cbf4e08fdd88f13b01f22b2 Mon Sep 17 00:00:00 2001 From: Frank Harkins Date: Tue, 26 Nov 2024 16:46:05 +0000 Subject: [PATCH 4/4] Hide cell --- docs/guides/serverless-manage-resources.ipynb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/guides/serverless-manage-resources.ipynb b/docs/guides/serverless-manage-resources.ipynb index f45ce1d4c5c..d00a6870c69 100644 --- a/docs/guides/serverless-manage-resources.ipynb +++ b/docs/guides/serverless-manage-resources.ipynb @@ -212,7 +212,11 @@ "cell_type": "code", "execution_count": 6, "id": "df28a92c-3585-49f0-a2ea-828a34638684", - "metadata": {}, + "metadata": { + "tags": [ + "remove-cell" + ] + }, "outputs": [ { "name": "stdout",