426 lines
14 KiB
Plaintext
426 lines
14 KiB
Plaintext
{
|
||
"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™ 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 workload’s `.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
|
||
}
|