qiskit-documentation/docs/guides/serverless-first-program.ipynb

426 lines
14 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"id": "e17b430a-ec17-4a88-9a71-9ce365059bea",
"metadata": {},
"source": [
"# Write your first Qiskit Serverless program"
]
},
{
"cell_type": "markdown",
"id": "90e824fb-dcf6-4a8b-9808-d66aa9bfb3b5",
"metadata": {
"tags": [
"version-info"
]
},
"source": [
"<details>\n",
"<summary><b>Package versions</b></summary>\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-aer~=0.15.1\n",
"qiskit-ibm-runtime~=0.31.0\n",
"qiskit-serverless~=0.17.1\n",
"qiskit-ibm-catalog~=0.1\n",
"```\n",
"</details>"
]
},
{
"cell_type": "markdown",
"id": "b32bff85-1760-4296-8f5b-ea6e5c942bbe",
"metadata": {},
"source": [
"This example demonstrates how to use `qiskit-serverless` tools to create a parallel transpilation program, and then implement `qiskit-ibm-catalog` to deploy your program to IBM Quantum&trade; Platform to use as a reusable remote service."
]
},
{
"cell_type": "markdown",
"id": "e3603a5c-78f4-40ec-9568-7a45664acfc7",
"metadata": {},
"source": [
"## Example: remote transpilation with Qiskit Serverless\n",
"\n",
"Start with the following example that transpiles a `circuit` against a given `backend` and target `optimization_level`, and gradually add more elements to deploy your workload to Qiskit Serverless.\n",
"\n",
"Put the following code cell in the file `./source_files/transpile_remote.py`. This file is the program we'll upload to Qiskit Serverless."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "21ea3269-1946-40b4-9c0f-9431003c2d0b",
"metadata": {
"editable": true,
"slideshow": {
"slide_type": ""
},
"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": 2,
"id": "4b550093-1d73-4c15-905a-0caa12f7dcbe",
"metadata": {
"editable": true,
"slideshow": {
"slide_type": ""
},
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Writing ./source_files/transpile_remote.py\n"
]
}
],
"source": [
"%%writefile ./source_files/transpile_remote.py\n",
"\n",
"from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
"\n",
"def transpile_remote(circuit, optimization_level, backend):\n",
" \"\"\"Transpiles an abstract circuit into an ISA circuit for a given backend.\"\"\"\n",
" pass_manager = generate_preset_pass_manager(\n",
" optimization_level=optimization_level,\n",
"\t\tbackend=backend\n",
" )\n",
" isa_circuit = pass_manager.run(circuit)\n",
" return isa_circuit"
]
},
{
"cell_type": "markdown",
"id": "ea182474-7566-4a13-96d8-cfcc8f16dd8f",
"metadata": {},
"source": [
"## Set up your files\n",
"\n",
"Qiskit Serverless requires setting up your workloads `.py` files into a dedicated directory. The following structure is an example of good practice:\n",
"\n",
"```text\n",
"serverless_program\n",
"├── program_uploader.ipynb\n",
"└── source_files\n",
" ├── transpile_remote.py\n",
" └── *.py\n",
"```\n",
"\n",
"Serverless uploads the contents of `source_files` to run remotely. Once these are set up, you can adjust `transpile_remote.py` to fetch inputs and return outputs.\n",
"\n",
"### Get program arguments\n",
"\n",
"Your initial `transpile_remote.py` has three inputs: `circuits`, `backend_name`, and `optimization_level`. Serverless is currently limited to only accept serializable inputs and outputs. For this reason, you cannot pass in `backend` directly, so use `backend_name` as a string instead."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "54a8d2c6-a3f4-4169-9210-dd213e2273d2",
"metadata": {},
"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",
"from qiskit_serverless import get_arguments, save_result, distribute_task, get\n",
"\n",
"# Get program arguments\n",
"arguments = get_arguments()\n",
"circuits = arguments.get(\"circuits\")\n",
"backend_name = arguments.get(\"backend_name\")\n",
"optimization_level = arguments.get(\"optimization_level\")"
]
},
{
"cell_type": "markdown",
"id": "bf57e8a8-4f64-4933-978d-c16bda4e0c0c",
"metadata": {},
"source": [
"At this point, you can get your backend with `QiskitRuntimeService`, and add your existing program:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "7077ba00-1571-4f99-8c53-b1a9ac280987",
"metadata": {},
"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",
"from qiskit_ibm_runtime import QiskitRuntimeService\n",
"\n",
"service = QiskitRuntimeService(channel=\"ibm_quantum\")\n",
"backend = service.get_backend(backend_name)"
]
},
{
"cell_type": "markdown",
"id": "8bd63bfc-0da5-46de-ace5-8463b5ad92f3",
"metadata": {},
"source": [
"Finally, you can run `transpile_remote()` across all `circuits` passed in, and return the `transpiled_circuits` as a result:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "afdb6896-93b8-4006-b27b-49ebb16e7c1c",
"metadata": {},
"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",
"results = [\n",
" transpile_remote(circuit, backend)\n",
" for circuit in circuits\n",
"]\n",
"\n",
"save_result({\n",
" \"transpiled_circuits\": results\n",
"})"
]
},
{
"cell_type": "markdown",
"id": "a05fa201-aabb-43a5-8a6a-f53c5c664fc4",
"metadata": {},
"source": [
"## Deploy to IBM Quantum Platform\n",
"\n",
"The previous section created a program to be run remotely. The code cells in this section upload that program to Qiskit Serverless.\n",
"\n",
"Use `qiskit-ibm-catalog` to authenticate to `QiskitServerless` with your API token, which you can find in your [IBM Quantum account](https://quantum.ibm.com/account), and upload the program.\n",
"\n",
"You can use `save_account()` to save your credentials (See the \"Authenticate to the service\" step in the [Set up to use IBM Quantum Platform](./setup-channel#set-up-to-use-ibm-quantum-platform) section). Note that this writes your credentials to the same file as [`QiskitRuntimeService.save_account()`](/api/qiskit-ibm-runtime/qiskit_ibm_runtime.QiskitRuntimeService#save_account)."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "cc9d5267-8019-4543-ab6a-679583d26340",
"metadata": {},
"outputs": [],
"source": [
"from qiskit_ibm_catalog import QiskitServerless, QiskitFunction\n",
"\n",
"# Authenticate to the remote cluster and submit the pattern for remote execution\n",
"serverless = QiskitServerless()"
]
},
{
"cell_type": "markdown",
"id": "7e8327dc-9105-4fb0-9cf0-c6e13ca32674",
"metadata": {},
"source": [
"Qiskit Serverless compresses the contents of `working_dir` (in this case, `source_files`) into a `tar`, which is uploaded and cleaned up after. The `entrypoint` identifies the main program executable for Qiskit Serverless to run. Additionally, if your program has custom `pip` dependencies, you can add them to a `dependencies` array:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "62738969-b19c-484e-8591-4f89c99990ed",
"metadata": {},
"outputs": [],
"source": [
"transpile_remote_demo = QiskitFunction(\n",
" title=\"transpile_remote_serverless\",\n",
" entrypoint=\"transpile_remote.py\",\n",
" working_dir=\"./source_files/\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "ed72ee48-a643-4d2e-b245-6e9ab3673ddb",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"QiskitFunction(transpile_remote_serverless)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"serverless.upload(transpile_remote_demo)"
]
},
{
"cell_type": "markdown",
"id": "9a22d507-2489-4f2f-af78-c9249ed3fc3d",
"metadata": {},
"source": [
"To check if it successfully uploaded, use `serverless.list()`:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "ff7d8283-ee72-4167-8a8a-1f07367ba6ef",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[QiskitFunction(transpile_remote_serverless_test_7b71d607),\n",
" QiskitFunction(transpile_remote_serverless_test_6169e40a),\n",
" QiskitFunction(transpile_remote_serverless_test_3e28580a),\n",
" QiskitFunction(transpile_remote_serverless_test_7e16ef16),\n",
" QiskitFunction(transpile_remote_serverless_test_47c755bf),\n",
" QiskitFunction(transpile_remote_serverless),\n",
" QiskitFunction(transpile_remote_serverless_test_579ed35c-3f56-484c-8a64-58dc953ed845),\n",
" QiskitFunction(transpile_remote_serverless_test_47c79b69),\n",
" QiskitFunction(transpile_remote_serverless_test_53c0786c),\n",
" QiskitFunction(transpile_remote_serverless_test_094ae798-88f7-46ab-8997-5a0bf503d908),\n",
" QiskitFunction(transpile_remote_serverless_test_35fb8da4-0fa3-4596-85c4-3a13d67f8c6a),\n",
" QiskitFunction(transpile_remote_serverless_test_426d1904),\n",
" QiskitFunction(transpile_remote_serverless_test_ebd79361),\n",
" QiskitFunction(transpile_remote_serverless_test_a966c167),\n",
" QiskitFunction(transpile_remote_serverless_test_d19e6f7e-3de0-4dde-b978-bdd03fba9845),\n",
" QiskitFunction(transpile_remote_serverless_test_b4d7a503),\n",
" QiskitFunction(transpile_remote_serverless_test_ceb9a116),\n",
" QiskitFunction(transpile_remote_serverless_test_355478eb),\n",
" QiskitFunction(transpile_remote_serverless_test),\n",
" QiskitFunction(transpile_remote_serverless_test_8e84c5f0-962d-4cd0-bca8-ebe1e227552f),\n",
" QiskitFunction(transpile_remote_serverless_test_4532e330),\n",
" QiskitFunction(transpile_remote_serverless_test_7659964c),\n",
" QiskitFunction(transpile_remote_serverless_test_5d216ee7),\n",
" QiskitFunction(transpile_remote_serverless_test_d0757405),\n",
" QiskitFunction(transpile_remote_serverless_test_0f048273),\n",
" QiskitFunction(transpile_remote_serverless_test_6a68a773),\n",
" QiskitFunction(transpile_remote_serverless_test_f9b5609f),\n",
" QiskitFunction(transpile_remote_serverless_test_701468af-437d-4737-8a00-843f0431a09c),\n",
" QiskitFunction(transpile_remote_serverless_test_e81ddca0),\n",
" QiskitFunction(transpile_remote_serverless_test_c1de9270),\n",
" QiskitFunction(transpile_remote_serverless_test_3826f696),\n",
" QiskitFunction(transpile_remote_serverless_test_2da7da19),\n",
" QiskitFunction(transpile_remote_serverless_test_74c54154),\n",
" QiskitFunction(transpile_remote_serverless_test_e51063a5),\n",
" QiskitFunction(transpile_remote_serverless_test_69c1b2c6),\n",
" QiskitFunction(transpile_remote_serverless_test_abb21121),\n",
" QiskitFunction(transpile_remote_serverless_test_0990ad64),\n",
" QiskitFunction(transpile_remote_serverless_test_65db9226),\n",
" QiskitFunction(transpile_remote_serverless_test_f7057422),\n",
" QiskitFunction(transpile_remote_serverless_test_9fad0bc6)]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"serverless.list()"
]
},
{
"cell_type": "markdown",
"id": "f8940b98-33f7-4029-ac77-60058c4aee78",
"metadata": {},
"source": [
"## Next steps\n",
"\n",
"<Admonition type=\"info\" title=\"Recommendations\">\n",
"\n",
"- Learn how to pass inputs and run your program remotely in the [Run your first Qiskit Serverless workload remotely](./serverless-run-first-workload) topic.\n",
"\n",
"</Admonition>"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "2992c8d5-f8f5-4602-8705-db1e20383459",
"metadata": {
"editable": true,
"slideshow": {
"slide_type": ""
},
"tags": [
"remove-cell"
]
},
"outputs": [],
"source": [
"# This cell is hidden from users, it just deletes the working folder we created\n",
"import shutil\n",
"\n",
"shutil.rmtree(\"./source_files/\")"
]
}
],
"metadata": {
"description": "How to create a parallel transpilation program and deploy it to IBM Quantum Platform to use as a reusable remote service.",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3"
},
"title": "Write your first Qiskit Serverless program"
},
"nbformat": 4,
"nbformat_minor": 2
}