diff --git a/docs/getting_started/basic/01_running_program.ipynb b/docs/getting_started/basic/01_running_program.ipynb
index add3e60e6..81594d96b 100644
--- a/docs/getting_started/basic/01_running_program.ipynb
+++ b/docs/getting_started/basic/01_running_program.ipynb
@@ -2,43 +2,85 @@
"cells": [
{
"cell_type": "markdown",
- "id": "66030e20-b384-4dcf-9c5f-7664f7ad1693",
+ "id": "0544343d-7181-4016-a4f4-fb9df39c4bad",
"metadata": {},
"source": [
"# Running a Qiskit Function as a function\n",
"\n",
- "In this tutorial, we will write a basic Qiskit Function using Qiskit Serverless. We will show how to run the function remotely and retrieve the results from the serverless client.\n",
+ "In this tutorial, you’ll learn how to create and run a Qiskit Function using Qiskit Serverless. A Qiskit Function is a self-contained Python script that can execute quantum workloads remotely on serverless infrastructure.\n",
+ "We’ll start by writing a simple function that:\n",
+ "\n",
+ " - Builds a two-qubit quantum circuit to create a Bell state.\n",
+ " - Transpiles the circuit for a target backend.\n",
+ " - Runs the circuit using the Sampler primitive.\n",
+ " - Saves the results so they can be retrieved later.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "77472550-b841-4546-b475-032eb4b62f99",
+ "metadata": {},
+ "source": [
+ "#### Install dependencies\n",
+ "\n",
+ "Before we begin, make sure the required packages are installed in your notebook environment:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "aa3aa259-e7c9-48c0-baa8-fe958280b0ad",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%pip install qiskit qiskit-ibm-runtime qiskit-serverless"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "66030e20-b384-4dcf-9c5f-7664f7ad1693",
+ "metadata": {},
+ "source": [
+ "\n",
+ "## Prep Work\n",
"\n",
"### Writing the Qiskit Function\n",
"\n",
- "First, we need to write the function code and save it to a file called [function.py](./source_files/function.py). This function creates a two-qubit quantum circuit that prepares a Bell state, measures the result, and saves the measured probability distribution.\n",
+ "First, we need to write the function code and save it to a file called [function.py](./source_files/function.py). This function will contain the logic for our Qiskit Function. For this example, we will creates a two-qubit quantum circuit that prepares a Bell state, measures the result, and saves the measured probability distribution.\n",
"\n",
"The code for the function is shown below:\n",
"\n",
"```python\n",
"from qiskit import QuantumCircuit\n",
- "from qiskit.primitives import Sampler\n",
- "\n",
+ "from qiskit.transpiler import generate_preset_pass_manager\n",
+ "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
+ "from qiskit_ibm_runtime.fake_provider import FakeVigoV2\n",
"from qiskit_serverless import save_result\n",
"\n",
"# all print statement will be available in job logs\n",
"print(\"Running function...\")\n",
"\n",
- "# creating circuit\n",
+ "# Step 1: Create a Bell-state circuit\n",
"circuit = QuantumCircuit(2)\n",
"circuit.h(0)\n",
"circuit.cx(0, 1)\n",
"circuit.measure_all()\n",
"\n",
- "# running Sampler primitive\n",
- "sampler = Sampler()\n",
- "quasi_dists = sampler.run(circuit).result().quasi_dists\n",
+ "# Step 2: Transpile for a fake backend (for demonstration)\n",
+ "backend = FakeVigoV2()\n",
+ "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
+ "isa_circuit = pm.run(circuit)\n",
"\n",
- "# save results of function execution, \n",
- "# which will be accessible by calling `.result()`\n",
+ "# Step 3: Run the Sampler primitive\n",
+ "sampler = Sampler(backend)\n",
+ "quasi_dists = sampler.run([isa_circuit]).result()[0].data.meas.get_counts()\n",
+ "\n",
+ "\n",
+ "# Step 4: Save results so they can be retrieved later by calling `.result()`\n",
"save_result(quasi_dists)\n",
"print(\"Completed running function.\")\n",
"```\n",
+ "Now that we’ve written our Qiskit Function, the next step is to deploy it to the serverless environment so it can run remotely.\n",
"\n",
"### Deploying the function\n",
"\n",
@@ -86,6 +128,7 @@
"source": [
"client = ServerlessClient(\n",
" token=os.environ.get(\"GATEWAY_TOKEN\", \"awesome_token\"),\n",
+ " instance=os.environ.get(\"GATEWAY_INSTANCE\", \"an_awesome_crn\"),\n",
" host=os.environ.get(\"GATEWAY_HOST\", \"http://localhost:8000\"),\n",
" # If you are using the kubernetes approach the URL must be http://localhost\n",
")\n",
@@ -98,17 +141,17 @@
"id": "4dd85621-9ab0-4f34-9ab4-07ad773c5e00",
"metadata": {},
"source": [
+ "### Create a Qiskit Function object\n",
"\n",
- "\n",
- "`QiskitFunction` accepts couple of required parameters:\n",
+ "A `QiskitFunction` represents the function you want to run. It includes:\n",
"\n",
"- title - name of the Qiskit Function\n",
- "- entrypoint - name of python file you want to execute\n",
- "- working_dir - directory where your script is located (directory size must be less than 50MB). This is optional parameter and will be current folder by default.\n",
+ "- entrypoint - the name of the python file that will be executed.\n",
+ "- working_dir - directory where your script is located (directory size must be less than 50MB). This is optional parameter and will be current folder by default.\n",
"\n",
- "> Warning! All content of `working_dir` will be shipped to cluster for execution\n",
+ "This tells the serverless system what code to run and what supporting files to include. Everything in working_dir will be packaged and shipped to the compute node.\n",
"\n",
- "> Warning! Execution of `upload` function ships All content of `working_dir`. When the contents of `working_dir` is changed, the `upload` function must be called again to update the shipped directory contents."
+ "> Warning! All content of `working_dir` will be shipped to cluster for execution\n"
]
},
{
@@ -132,9 +175,30 @@
"from qiskit_serverless import QiskitFunction\n",
"\n",
"function = QiskitFunction(\n",
- " title=\"my-first-function\", entrypoint=\"function.py\", working_dir=\"./source_files/\"\n",
- ")\n",
+ " title=\"my-first-function\",\n",
+ " entrypoint=\"function.py\",\n",
+ " working_dir=\"./source_files/\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a23d9f80-6634-48ca-9cc0-5c2146101848",
+ "metadata": {},
+ "source": [
+ "### Upload the function\n",
+ "Once the function object is created, upload it to the gateway so it can be executed later:\n",
"\n",
+ "> Warning! Execution of `upload` function ships All content of `working_dir`. When the contents of `working_dir` is changed, the `upload` function must be called again to update the shipped directory contents."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "f2a17837-e4b8-4ea4-a9ed-97358a06f705",
+ "metadata": {},
+ "outputs": [],
+ "source": [
"client.upload(function)"
]
},
@@ -143,9 +207,9 @@
"id": "3e5326e2-9ff8-48e8-a8a9-18716633fd01",
"metadata": {},
"source": [
- "### Running the QiskitFunction\n",
+ "## Running the QiskitFunction\n",
"\n",
- "After deploying the QiskitFunction, we can see our function in a `list` of availiable functions."
+ "After deploying the QiskitFunction, we can he function by its title:"
]
},
{
@@ -175,7 +239,7 @@
"id": "135eda5f",
"metadata": {},
"source": [
- "We can run any function by calling `run` method on function object."
+ "We can run any function by calling `run` method on function object. This will make the job run on the gateway:"
]
},
{
@@ -187,7 +251,7 @@
{
"data": {
"text/plain": [
- ""
+ ""
]
},
"execution_count": 5,
@@ -205,22 +269,22 @@
"id": "39ee31d2-3553-4e19-bcb9-4cccd0df0e4c",
"metadata": {},
"source": [
- "[Job](https://qiskit.github.io/qiskit-serverless/stubs/qiskit_serverless.core.Job.html#qiskit_serverless.core.Job) instances have a `status()` method to check status of the function execution."
+ "A [Job](https://qiskit.github.io/qiskit-serverless/stubs/qiskit_serverless.core.Job.html#qiskit_serverless.core.Job) instances have a `status()` method to check status of the function execution. It will help us monitor the status of our job:"
]
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 6,
"id": "cc7ccea6-bbae-4184-ba7f-67b6c20a0b0b",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "'DONE'"
+ "'QUEUED'"
]
},
- "execution_count": 15,
+ "execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
@@ -234,22 +298,22 @@
"id": "f496adbe-3d82-4aad-b86b-6adb3b9d287d",
"metadata": {},
"source": [
- "`Job` instances also have a `result()` method for retrieving results. The `result()` method will not return until the job is done running the function."
+ "We can retrieve the result by calling the `result()` method of an instanced `Job` object. The `result()` method will not return until the job is done running the function."
]
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 7,
"id": "ca05d063",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "{'00': 539, '11': 485}"
+ "{'11': 535, '00': 489}"
]
},
- "execution_count": 16,
+ "execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
@@ -263,12 +327,12 @@
"id": "719d3572",
"metadata": {},
"source": [
- "To inspect the logs from a function, access them from the ``Job`` instance."
+ "To inspect the logs from a function for debugging or analysis, you can access them from the ``Job`` instance."
]
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 8,
"id": "eb5ec85f",
"metadata": {},
"outputs": [
@@ -276,7 +340,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "2024-12-05 17:26:40,785\tINFO job_manager.py:531 -- Runtime env is setting up.\n",
+ "2025-11-03 10:03:01,072\tINFO job_manager.py:531 -- Runtime env is setting up.\n",
"Running function...\n",
"Completed running function.\n",
"\n"
@@ -308,9 +372,9 @@
],
"metadata": {
"kernelspec": {
- "display_name": ".venv",
+ "display_name": "Python (qiskit_serverless test venv)",
"language": "python",
- "name": "python3"
+ "name": "qiskit_serverless_test_venv"
},
"language_info": {
"codemirror_mode": {
@@ -322,7 +386,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.9"
+ "version": "3.13.7"
}
},
"nbformat": 4,
diff --git a/docs/getting_started/basic/02_arguments_and_results.ipynb b/docs/getting_started/basic/02_arguments_and_results.ipynb
index e0ed65e07..2fe9699e4 100644
--- a/docs/getting_started/basic/02_arguments_and_results.ipynb
+++ b/docs/getting_started/basic/02_arguments_and_results.ipynb
@@ -10,30 +10,58 @@
"\n",
"Let's create another file with our function [./source_files/function_with_arguments.py](./source_files/function_with_arguments.py). \n",
"\n",
- "Instead of having the circuit defined inside the function (like we did in the first example), we will pass it as an argument. We will also save the results, so we can access them later by calling [save_result](https://qiskit.github.io/qiskit-serverless/stubs/qiskit_serverless.core.save_result.html#qiskit_serverless.core.save_result).\n",
+ "Instead of having the circuit defined inside the function (like we did in the first example), we will pass it as an argument. To make this case more realistic, we will also pass a backend argument for the transpilation and the Sampler. This use case is for transpiling a circuit in the cloud. We will also save the results, so we can access them later by calling [save_result](https://qiskit.github.io/qiskit-serverless/stubs/qiskit_serverless.core.save_result.html#qiskit_serverless.core.save_result).\n",
"\n",
"Here is the function:\n",
"\n",
"```python\n",
+ "\"\"\"function with arguments for jupyter notebook.\"\"\"\n",
+ "from qiskit import QuantumCircuit\n",
+ "from qiskit.providers.exceptions import QiskitBackendNotFoundError\n",
+ "from qiskit.transpiler import generate_preset_pass_manager\n",
"from qiskit_serverless import get_arguments, save_result\n",
- "from qiskit.primitives import Sampler\n",
+ "from qiskit_ibm_runtime import QiskitRuntimeService\n",
+ "from qiskit_ibm_runtime.fake_provider import FakeProviderForBackendV2\n",
+ "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
+ "\n",
"\n",
"# get all arguments passed to this function\n",
"arguments = get_arguments()\n",
"\n",
"# get specific argument that we are interested in\n",
"circuit = arguments.get(\"circuit\")\n",
+ "backend_name = arguments.get(\"backend_name\")\n",
+ "service = arguments.get(\"service\")\n",
"\n",
- "sampler = Sampler()\n",
+ "# verifying arguments types\n",
+ "if not isinstance(circuit, QuantumCircuit):\n",
+ " raise ValueError(\"circuit must be QuantumCircuit.\")\n",
+ "if not isinstance(backend_name, str):\n",
+ " raise ValueError(\"backend_name must be str.\")\n",
"\n",
- "quasi_dists = sampler.run(circuit).result().quasi_dists\n",
+ "if \"fake\" in backend_name.lower():\n",
+ " service = FakeProviderForBackendV2()\n",
+ "if isinstance(service, (FakeProviderForBackendV2, QiskitRuntimeService)):\n",
+ " try:\n",
+ " backend = service.backend(backend_name)\n",
+ " except QiskitBackendNotFoundError as e:\n",
+ " raise ValueError(f\"Error retrieving backend {backend_name}: {e}\") from e\n",
+ "else:\n",
+ " raise ValueError(f\"A service of type `QiskitRuntimeService` is required for using the backend named {backend_name}.\")\n",
"\n",
- "print(f\"Quasi distribution: {quasi_dists[0]}\")\n",
+ "# matching our run to the backend argument\n",
+ "sampler = Sampler(backend)\n",
+ "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
+ "isa_circuit = pm.run(circuit)\n",
+ "\n",
+ "# running the circuit\n",
+ "quasi_dists = sampler.run([isa_circuit]).result()[0].data.meas.get_counts()\n",
"\n",
"# saving results of the execution\n",
"save_result({\n",
- " \"quasi_dists\": quasi_dists[0]\n",
+ " \"quasi_dists\": quasi_dists\n",
"})\n",
+ "\n",
"```\n",
"\n",
"As you can see, the circuit construction is not inside the function anymore. Instead, we parse the arguments by calling the [get_arguments](https://qiskit.github.io/qiskit-serverless/stubs/qiskit_serverless.serializers.get_arguments.html#qiskit_serverless.serializers.get_arguments) function."
@@ -49,7 +77,9 @@
{
"cell_type": "code",
"execution_count": 1,
- "metadata": {},
+ "metadata": {
+ "scrolled": true
+ },
"outputs": [
{
"data": {
@@ -87,6 +117,55 @@
"circuit.draw()"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Our Function can run on either simulator or a real hardware. For real hardware usage, a service object is needed to connect and send the data to the IQP. Here is how we can do it"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "management.get:WARNING:2025-10-30 12:34:31,507: Loading default saved account\n"
+ ]
+ }
+ ],
+ "source": [
+ "from qiskit_ibm_runtime import QiskitRuntimeService\n",
+ " \n",
+ "service = QiskitRuntimeService(\n",
+ " # channel=\"ibm_quantum_platform\",\n",
+ " # token=\"API_KEY\",\n",
+ " # instance=\"CRN\"\n",
+ ")\n",
+ "backend_name = service.least_busy(simulator=False, operational=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We decide to use a simulator as this is an example. Because of that we will write oer our backend name and service so our function will run over a simulator.In this ecample, we chose `FakeVigoV2` to be our backend:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from qiskit_ibm_runtime.fake_provider import FakeVigoV2\n",
+ "\n",
+ "backend_name = FakeVigoV2().name"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -103,7 +182,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 4,
"metadata": {},
"outputs": [
{
@@ -112,7 +191,7 @@
""
]
},
- "execution_count": 2,
+ "execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -123,6 +202,7 @@
"\n",
"client = ServerlessClient(\n",
" token=os.environ.get(\"GATEWAY_TOKEN\", \"awesome_token\"),\n",
+ " instance=os.environ.get(\"GATEWAY_INSTANCE\", \"an_awesome_crn\"),\n",
" host=os.environ.get(\"GATEWAY_HOST\", \"http://localhost:8000\"),\n",
" # If you are using the kubernetes approach the URL must be http://localhost\n",
")\n",
@@ -131,7 +211,7 @@
},
{
"cell_type": "code",
- "execution_count": 3,
+ "execution_count": 5,
"metadata": {},
"outputs": [
{
@@ -140,7 +220,7 @@
"QiskitFunction(function-with-arguments)"
]
},
- "execution_count": 3,
+ "execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
@@ -166,7 +246,7 @@
},
{
"cell_type": "code",
- "execution_count": 4,
+ "execution_count": 6,
"metadata": {},
"outputs": [
{
@@ -175,7 +255,7 @@
"QiskitFunction(function-with-arguments)"
]
},
- "execution_count": 4,
+ "execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
@@ -187,22 +267,22 @@
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
- "execution_count": 5,
+ "execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
- "job = my_function.run(circuit=circuit)\n",
+ "job = my_function.run(circuit=circuit, backend_name=backend_name, service=service)\n",
"job"
]
},
@@ -215,16 +295,16 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- "{'quasi_dists': {'11': 524, '00': 500}}"
+ "{'quasi_dists': {'11': 504, '00': 520}}"
]
},
- "execution_count": 6,
+ "execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
@@ -232,13 +312,31 @@
"source": [
"job.result()"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2025-10-30 09:42:40,698\tINFO job_manager.py:531 -- Runtime env is setting up.\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(job.logs())"
+ ]
}
],
"metadata": {
"kernelspec": {
- "display_name": ".venv",
+ "display_name": "Python (qiskit_serverless test venv)",
"language": "python",
- "name": "python3"
+ "name": "qiskit_serverless_test_venv"
},
"language_info": {
"codemirror_mode": {
@@ -250,7 +348,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.9"
+ "version": "3.13.7"
}
},
"nbformat": 4,
diff --git a/docs/getting_started/basic/04_distributed_workloads.ipynb b/docs/getting_started/basic/04_distributed_workloads.ipynb
index becbc8831..368ab4c51 100644
--- a/docs/getting_started/basic/04_distributed_workloads.ipynb
+++ b/docs/getting_started/basic/04_distributed_workloads.ipynb
@@ -14,32 +14,45 @@
"from qiskit_serverless import get_arguments, save_result, distribute_task, get\n",
"\n",
"from qiskit import QuantumCircuit\n",
- "from qiskit.primitives import Sampler\n",
+ "from qiskit.providers import BackendV2\n",
+ "from qiskit.providers.exceptions import QiskitBackendNotFoundError\n",
+ "from qiskit.transpiler import generate_preset_pass_manager\n",
+ "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
+ "from qiskit_ibm_runtime.fake_provider import FakeVigoV2\n",
"\n",
"\n",
"@distribute_task()\n",
- "def distributed_sample(circuit: QuantumCircuit):\n",
+ "def distributed_sample(circuit: QuantumCircuit, backend: BackendV2):\n",
" \"\"\"Distributed task that returns quasi distribution for given circuit.\"\"\"\n",
- " return Sampler().run(circuit).result().quasi_dists[0]\n",
+ " pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
+ " isa_circuit = pm.run(circuit)\n",
+ " return Sampler(backend).run([isa_circuit]).result()[0].data.meas.get_counts()\n",
"\n",
"\n",
"arguments = get_arguments()\n",
"circuits = arguments.get(\"circuits\")\n",
+ "backend_name = arguments.get(\"backend_name\")\n",
+ "service = arguments.get(\"service\")\n",
"\n",
+ "if \"fake\" not in backend_name.lower():\n",
+ " if service is not None:\n",
+ " try:\n",
+ " backend = service.backend(backend_name)\n",
+ " except QiskitBackendNotFoundError as e:\n",
+ " raise ValueError(f\"Error retrieving backend {backend_name}: {e}\") from e\n",
+ " else:\n",
+ " raise ValueError(f\"A service is required for using the backend named {backend_name}.\")\n",
+ "else:\n",
+ " backend = FakeVigoV2()\n",
"\n",
"# run distributed tasks as async function\n",
"# we get task references as a return type\n",
- "sample_task_references = [\n",
- " distributed_sample(circuit)\n",
- " for circuit in circuits\n",
- "]\n",
+ "sample_task_references = [distributed_sample(circuit, backend) for circuit in circuits]\n",
"\n",
"# now we need to collect results from task references\n",
"results = get(sample_task_references)\n",
"\n",
- "save_result({\n",
- " \"results\": results\n",
- "})\n",
+ "save_result({\"results\": results})\n",
"```\n",
"\n",
"There are a lot of new concepts introduced in this Qiskit Function, so let's go over them in more detail:\n",
@@ -70,7 +83,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 1,
"metadata": {},
"outputs": [
{
@@ -90,6 +103,7 @@
"\n",
"client = ServerlessClient(\n",
" token=os.environ.get(\"GATEWAY_TOKEN\", \"awesome_token\"),\n",
+ " instance=os.environ.get(\"GATEWAY_INSTANCE\", \"an_awesome_crn\"),\n",
" host=os.environ.get(\"GATEWAY_HOST\", \"http://localhost:8000\"),\n",
" # If you are using the kubernetes approach the URL must be http://localhost\n",
")\n",
@@ -112,9 +126,9 @@
{
"data": {
"text/plain": [
- "[,\n",
- " ,\n",
- " ]"
+ "[,\n",
+ " ,\n",
+ " ]"
]
},
"execution_count": 2,
@@ -130,6 +144,47 @@
"circuits"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Our function can run on either simulator or a real hardware. For real hardware usage, a service object is needed to connect and send the data to the IQP. Here is how we can do it:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from qiskit_ibm_runtime import QiskitRuntimeService\n",
+ " \n",
+ "service = QiskitRuntimeService(\n",
+ " # channel=\"ibm_quantum_platform\",\n",
+ " # token=\"API_KEY\",\n",
+ " # instance=\"CRN\"\n",
+ ")\n",
+ "backend_name = service.least_busy(simulator=False, operational=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We also need to pass a name of backend as an argument. In this example, let's send the name of `FakeVigoV2` to our function:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from qiskit_ibm_runtime.fake_provider import FakeVigoV2\n",
+ "\n",
+ "backend_name = FakeVigoV2().name"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -139,7 +194,7 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 4,
"metadata": {},
"outputs": [
{
@@ -148,7 +203,7 @@
"QiskitFunction(function-with-parallel-workflow)"
]
},
- "execution_count": 10,
+ "execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
@@ -167,23 +222,23 @@
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
- ""
+ ""
]
},
- "execution_count": 11,
+ "execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"parallel_function = client.get(\"function-with-parallel-workflow\")\n",
- "job = parallel_function.run(circuits=circuits)\n",
+ "job = parallel_function.run(circuits=circuits, backend_name=backend_name)\n",
"job"
]
},
@@ -230,7 +285,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": ".venv",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -244,7 +299,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.9"
+ "version": "3.13.7"
}
},
"nbformat": 4,
diff --git a/docs/getting_started/basic/05_retrieving_past_results.ipynb b/docs/getting_started/basic/05_retrieving_past_results.ipynb
index 21c2c31a8..95f85f801 100644
--- a/docs/getting_started/basic/05_retrieving_past_results.ipynb
+++ b/docs/getting_started/basic/05_retrieving_past_results.ipynb
@@ -250,7 +250,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": ".venv",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -264,7 +264,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.11.9"
+ "version": "3.13.7"
}
},
"nbformat": 4,
diff --git a/docs/getting_started/basic/source_files/function.py b/docs/getting_started/basic/source_files/function.py
index 93e86818a..fa735a13d 100644
--- a/docs/getting_started/basic/source_files/function.py
+++ b/docs/getting_started/basic/source_files/function.py
@@ -1,22 +1,29 @@
+"""function for jupyter notebook."""
from qiskit import QuantumCircuit
-from qiskit.primitives import StatevectorSampler as Sampler
-
+from qiskit.transpiler import generate_preset_pass_manager
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+from qiskit_ibm_runtime.fake_provider import FakeVigoV2
from qiskit_serverless import save_result
# all print statement will be available in job logs
print("Running function...")
-# creating circuit
+# Step 1: Create a Bell-state circuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
-# running Sampler primitive
-sampler = Sampler()
-quasi_dists = sampler.run([(circuit)]).result()[0].data.meas.get_counts()
+# Step 2: Transpile for a fake backend (for demonstration)
+backend = FakeVigoV2()
+pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
+isa_circuit = pm.run(circuit)
+
+# Step 3: Run the Sampler primitive
+sampler = Sampler(backend)
+quasi_dists = sampler.run([isa_circuit]).result()[0].data.meas.get_counts()
+
-# saves results of function execution,
-# which will be accessible by calling `.result()`
+# Step 4: Save results so they can be retrieved later by calling `.result()`
save_result(quasi_dists)
print("Completed running function.")
diff --git a/docs/getting_started/basic/source_files/function_with_arguments.py b/docs/getting_started/basic/source_files/function_with_arguments.py
index 5aede3762..2ade75225 100644
--- a/docs/getting_started/basic/source_files/function_with_arguments.py
+++ b/docs/getting_started/basic/source_files/function_with_arguments.py
@@ -1,17 +1,46 @@
+"""function with arguments for jupyter notebook."""
+from qiskit import QuantumCircuit
+from qiskit.providers.exceptions import QiskitBackendNotFoundError
+from qiskit.transpiler import generate_preset_pass_manager
from qiskit_serverless import get_arguments, save_result
-from qiskit.primitives import StatevectorSampler as Sampler
+from qiskit_ibm_runtime import QiskitRuntimeService
+from qiskit_ibm_runtime.fake_provider import FakeProviderForBackendV2
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+
# get all arguments passed to this function
arguments = get_arguments()
# get specific argument that we are interested in
circuit = arguments.get("circuit")
+backend_name = arguments.get("backend_name")
+service = arguments.get("service")
+
+# verifying arguments types
+if not isinstance(circuit, QuantumCircuit):
+ raise ValueError("circuit must be QuantumCircuit.")
+if not isinstance(backend_name, str):
+ raise ValueError("backend_name must be str.")
-sampler = Sampler()
+if "fake" in backend_name.lower():
+ service = FakeProviderForBackendV2()
+if isinstance(service, (FakeProviderForBackendV2, QiskitRuntimeService)):
+ try:
+ backend = service.backend(backend_name)
+ except QiskitBackendNotFoundError as e:
+ raise ValueError(f"Error retrieving backend {backend_name}: {e}") from e
+else:
+ raise ValueError(f"A service of type `QiskitRuntimeService` is required for using the backend named {backend_name}.")
-quasi_dists = sampler.run([(circuit)]).result()[0].data.meas.get_counts()
+# matching our run to the backend argument
+sampler = Sampler(backend)
+pm = generate_preset_pass_manager(backend=backend, optimization_level=3)
+isa_circuit = pm.run(circuit)
-print(f"Quasi distribution: {quasi_dists}")
+# running the circuit
+quasi_dists = sampler.run([isa_circuit]).result()[0].data.meas.get_counts()
# saving results of the execution
-save_result({"quasi_dists": quasi_dists})
+save_result({
+ "quasi_dists": quasi_dists
+})
diff --git a/docs/getting_started/basic/source_files/function_with_dependencies.py b/docs/getting_started/basic/source_files/function_with_dependencies.py
index 85f3ffb0f..5e85622b1 100644
--- a/docs/getting_started/basic/source_files/function_with_dependencies.py
+++ b/docs/getting_started/basic/source_files/function_with_dependencies.py
@@ -1,3 +1,4 @@
+"""function with dependencies for jupyter notebook."""
from qiskit_serverless import save_result
import pendulum
@@ -5,7 +6,7 @@
dt_toronto = pendulum.datetime(2012, 1, 1, tz='America/Toronto')
dt_vancouver = pendulum.datetime(2012, 1, 1, tz='America/Vancouver')
-diff = dt_vancouver.diff(dt_toronto).in_hours()
+diff = dt_vancouver.diff(dt_toronto).in_hours()
print(diff)
save_result({"hours": diff})
diff --git a/docs/getting_started/basic/source_files/function_with_parallel_workflow.py b/docs/getting_started/basic/source_files/function_with_parallel_workflow.py
index 01af48986..e36d42f7a 100644
--- a/docs/getting_started/basic/source_files/function_with_parallel_workflow.py
+++ b/docs/getting_started/basic/source_files/function_with_parallel_workflow.py
@@ -1,21 +1,51 @@
+"""function with parallel workflow for jupyter notebook."""
from qiskit_serverless import get_arguments, save_result, distribute_task, get
from qiskit import QuantumCircuit
-from qiskit.primitives import StatevectorSampler as Sampler
+from qiskit.providers import BackendV2
+from qiskit.providers.exceptions import QiskitBackendNotFoundError
+from qiskit.transpiler import generate_preset_pass_manager
+from qiskit_ibm_runtime import SamplerV2 as Sampler
+from qiskit_ibm_runtime.fake_provider import FakeProviderForBackendV2
@distribute_task()
-def distributed_sample(circuit: QuantumCircuit):
+def distributed_sample(circuit: QuantumCircuit, backend: BackendV2):
"""Distributed task that returns quasi distribution for given circuit."""
- return Sampler().run([(circuit)]).result()[0].data.meas.get_counts()
+ pm = generate_preset_pass_manager(backend=backend, optimization_level=3)
+ isa_circuit = pm.run(circuit)
+ return Sampler(backend).run([isa_circuit]).result()[0].data.meas.get_counts()
arguments = get_arguments()
circuits = arguments.get("circuits")
+backend_name = arguments.get("backend_name")
+service = arguments.get("service")
+
+# verifying arguments types
+if not isinstance(circuits, List):
+ circuits = [circuits]
+
+for circuit in circuits:
+ if not isinstance(circuit, QuantumCircuit):
+ raise ValueError("Each circuit in circuits must be QuantumCircuit.")
+if not isinstance(backend_name, str):
+ raise ValueError("backend_name must be str.")
+
+
+if "fake" in backend_name.lower():
+ service = FakeProviderForBackendV2()
+if isinstance(service, (FakeProviderForBackendV2, QiskitRuntimeService)):
+ try:
+ backend = service.backend(backend_name)
+ except QiskitBackendNotFoundError as e:
+ raise ValueError(f"Error retrieving backend {backend_name}: {e}") from e
+else:
+ raise ValueError(f"A service of type `QiskitRuntimeService` is required for using the backend named {backend_name}.")
# run distributed tasks as async function
# we get task references as a return type
-sample_task_references = [distributed_sample(circuit) for circuit in circuits]
+sample_task_references = [distributed_sample(circuit, backend) for circuit in circuits]
# now we need to collect results from task references
results = get(sample_task_references)