{ "cells": [ { "attachments": {}, "cell_type": "markdown", "id": "a477c993", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# How to run Qiskit on Amazon Braket" ] }, { "cell_type": "code", "execution_count": 1, "id": "3a9504c9", "metadata": {}, "outputs": [], "source": [ "# Use Braket SDK Cost Tracking to estimate the cost to run this example\n", "from braket.tracking import Tracker\n", "t = Tracker().start()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "c885d164", "metadata": {}, "source": [ "If you're like many people who learned quantum computing in the past several years, you might have learned how to program quantum circuits with [Qiskit](https://qiskit.org): the open-source quantum Software Development Kit (SDK) first released in 2017. With the [Qiskit-Braket provider](https://github.com/qiskit-community/qiskit-braket-provider/blob/main/docs/tutorials/0_tutorial_qiskit-braket-provider_overview.ipynb), you can run your Qiskit code across any of the gate-based devices on the [Amazon Braket](https://aws.amazon.com/braket/) quantum computing service.\n", "\n", "**Note**: if you're running this in your local development environment (i.e. not from the Braket console), you'll need to make sure you've got your AWS account configured properly first to access Braket devices. Check out [this tutorial](https://aws.amazon.com/blogs/quantum-computing/setting-up-your-local-development-environment-in-amazon-braket/) for a walkthrough." ] }, { "attachments": {}, "cell_type": "markdown", "id": "b23c5287", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Access Braket devices from Qiskit \n", "\n", " There are quite a few different backend devices on Amazon Braket, so we'll walk through them one by one and give an example of recommended use cases for each." ] }, { "attachments": {}, "cell_type": "markdown", "id": "a94feb7b", "metadata": {}, "source": [ "### Quantum simulators\n", "Let's start with the ***local simulator***. This is a quantum full state vector simulator which runs *locally* -- that means wherever you're running this Jupyter notebook (e.g. your local development environment or a notebook instance on the Braket console).\n", "\n", "**Recommended use case:** Noiseless circuits up to ~12 qubits" ] }, { "cell_type": "code", "execution_count": 2, "id": "f162ba69", "metadata": {}, "outputs": [], "source": [ "from qiskit_braket_provider import BraketLocalBackend\n", "\n", "local_simulator = BraketLocalBackend()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "17e2ab4d", "metadata": {}, "source": [ "Next, we have the ***local density matrix simulator***. This simulator also runs on your local machine, but allows you to simulate the effects of *noise* on your quantum circuit. Because density matrices are twice the size of state vectors, the number of qubits you can effectively simulate is half the size as the local state vector simulator.\n", "\n", "**Recommended use case:** Noisy circuits up to ~6 qubits" ] }, { "cell_type": "code", "execution_count": 3, "id": "2bfe0170", "metadata": {}, "outputs": [], "source": [ "local_dm_simulator = BraketLocalBackend(name='braket_dm')" ] }, { "attachments": {}, "cell_type": "markdown", "id": "de912d0e", "metadata": {}, "source": [ "Now let's look at Braket's *on-demand* simulators: these run on AWS computing resources and have some expanded features in addition to those of the local simulator. We can list all the available Braket simulators with the following code:" ] }, { "cell_type": "code", "execution_count": 4, "id": "70a24c64", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[BraketBackend[SV1], BraketBackend[TN1], BraketBackend[dm1]]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from qiskit_braket_provider import AWSBraketProvider\n", "\n", "provider = AWSBraketProvider()\n", "\n", "provider.backends(statuses=[\"ONLINE\"], types=[\"SIMULATOR\"])" ] }, { "attachments": {}, "cell_type": "markdown", "id": "d846e7f2", "metadata": {}, "source": [ "First up for on-demand simulators is ***SV1***. This is a full state vector simulator which allows you to simulate larger circuits than the local simulator, along with the ability to [batch tasks](https://docs.aws.amazon.com/braket/latest/developerguide/braket-batching-tasks.html) and run them in parallel, as well as use advanced techniques like [adjoint gradient calculations](https://pennylane.ai/blog/2022/12/computing-adjoint-gradients-with-amazon-braket-sv1/) for variational quantum algorithms. \n", "\n", "**Recommended use case:** Noiseless variational algorithms on up to 34 qubits" ] }, { "cell_type": "code", "execution_count": 5, "id": "19024712", "metadata": {}, "outputs": [], "source": [ "aws_sv1 = provider.get_backend(\"SV1\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "41c66765", "metadata": {}, "source": [ "The next on-demand simulator is ***DM1***. This is a density matrix simulator which, like SV1, allows you to simulate a larger number of qubits, as well as take advantage of batch execution. \n", "\n", "**Recommended use case:** Noisy variational algorithms on up to 17 qubits" ] }, { "cell_type": "code", "execution_count": 6, "id": "54e855a5", "metadata": {}, "outputs": [], "source": [ "aws_dm1 = provider.get_backend(\"dm1\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "ae97b1a1", "metadata": {}, "source": [ "Lastly for on-demand simulators, we have ***TN1***. This is a tensor-network simulator, which represents each gate in a circuit as a tensor. TN1 can simulate a larger number of qubits for circuits with local gates or other special structure, but will typically be slower than SV1 or DM1 for circuits with long-range or all-to-all gate structure.\n", "\n", "**Recommended use case:** Noiseless quantum circuits with local connectivity and up to 50 qubits" ] }, { "attachments": {}, "cell_type": "markdown", "id": "ad54a536", "metadata": {}, "source": [ "**Note**: Each AWS resource, (like a file or CPU or QPU) lives in a specific region and may only be accessible from that region. For example, TN1 is only available in the `eu-west-2`, `us-east-1`, and `us-west-2` regions. \n", "\n", "To change your AWS region if you're running in a managed notebook, you'll need to use the GUI in the top right hand corner of the AWS console to select your new region, then relaunch or create your notebook from the Braket console.\n", "\n", "To change your AWS region if you're running in your local development environment, you run the following code snippet:\n", "```\n", "import os\n", "os.environ[\"AWS_REGION\"] = \"your-desired-region\"\n", "```" ] }, { "cell_type": "code", "execution_count": 7, "id": "cd711dcb", "metadata": {}, "outputs": [], "source": [ "# If you've switched to one of the regions where TN1 is accessible, feel free to uncomment the following code\n", "# aws_tn1 = provider.get_backend(\"TN1\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "dc6910f0", "metadata": {}, "source": [ "### Quantum Processing Units (QPUs)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "8bfc8706", "metadata": {}, "source": [ "Amazon Braket also provides access to a number of third-party quantum hardware devices. The following code shows how to view the supported QPUs which are currently online:" ] }, { "cell_type": "code", "execution_count": null, "id": "f5329bca", "metadata": {}, "outputs": [], "source": [ "provider.backends(statuses=[\"ONLINE\"], types=[\"QPU\"])" ] }, { "attachments": {}, "cell_type": "markdown", "id": "4c7a21d4", "metadata": {}, "source": [ "For a closer look at each quantum computer, you can peruse the [Providers Overview](https://aws.amazon.com/braket/quantum-computers/) on the Braket homepage, or the Devices tab on the left side of the Braket console. \n", "Currently only gate-based QPUs (IonQ, OQC, Rigetti) are supported with the Qiskit-Braket provider. " ] }, { "attachments": {}, "cell_type": "markdown", "id": "0800b99f", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Running circuits on Braket devices\n", "\n" ] }, { "attachments": {}, "cell_type": "markdown", "id": "6bf048f4", "metadata": {}, "source": [ "Now that we've walked through each of the quantum devices available through the Qiskit-Braket provider, let's take them for a spin! For this example, we'll create a 3-GHZ state on the Rigetti device, but feel free to choose a different QPU from the commented out devices below." ] }, { "cell_type": "code", "execution_count": null, "id": "a5beeb7b", "metadata": {}, "outputs": [], "source": [ "qpu_backend = provider.get_backend(\"Aspen-M-3\")\n", "# qpu_backend = provider.get_backend(\"Lucy\")\n", "# qpu_backend = provider.get_backend(\"Aria\")\n", "\n", "print(qpu_backend)" ] }, { "cell_type": "code", "execution_count": 18, "id": "e9d90ed2", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
     ┌───┐          \n",
       "q_0: ┤ H ├──■────■──\n",
       "     └───┘┌─┴─┐  │  \n",
       "q_1: ─────┤ X ├──┼──\n",
       "          └───┘┌─┴─┐\n",
       "q_2: ──────────┤ X ├\n",
       "               └───┘
" ], "text/plain": [ " ┌───┐ \n", "q_0: ┤ H ├──■────■──\n", " └───┘┌─┴─┐ │ \n", "q_1: ─────┤ X ├──┼──\n", " └───┘┌─┴─┐\n", "q_2: ──────────┤ X ├\n", " └───┘" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from qiskit import QuantumCircuit\n", "\n", "circuit = QuantumCircuit(3)\n", "circuit.h(0)\n", "circuit.cx(0, 1)\n", "circuit.cx(0, 2)\n", "circuit.draw()" ] }, { "cell_type": "code", "execution_count": 19, "id": "32fd1f51", "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [], "source": [ "# run circuit\n", "qpu_task = qpu_backend.run(circuit, shots=10)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "9515c95b", "metadata": {}, "source": [ "Each task you run is assigned a unique ARN (Amazon Resource Name), which you can save and use to retrieve the data for your task after its run, even if you close your notebook." ] }, { "cell_type": "code", "execution_count": 20, "id": "d6f5d0da", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'arn:aws:braket:eu-west-2:567402972798:quantum-task/51449f9f-5b0b-476e-98e8-231fb90af30e'" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "task_id = qpu_task.job_id()\n", "task_id" ] }, { "attachments": {}, "cell_type": "markdown", "id": "3b7ee5ac", "metadata": {}, "source": [ "**Note**: Qiskit uses the name \\\"job\\\" to refer to what is called a \\\"task\\\" in Amazon Braket. This is why you access the ARN for the task by calling `.job_id()`. \n", "\n", "Now, Braket has a separate feature called \\\"Hybrid *Jobs*\\\", which is beyond the scope of this notebook, but which you can read about in the [developer guide](https://docs.aws.amazon.com/braket/latest/developerguide/braket-jobs.html)." ] }, { "cell_type": "code", "execution_count": 21, "id": "dec44bb5", "metadata": {}, "outputs": [], "source": [ "# Retrieve task data\n", "retrieved_task = qpu_backend.retrieve_job(job_id=task_id)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "355472d4", "metadata": {}, "source": [ "Then you can check the status of the task to see if it's finished:" ] }, { "cell_type": "code", "execution_count": 22, "id": "bb84627d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "retrieved_task.status()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "7c2d97be", "metadata": {}, "source": [ "**Note:** different devices may have different availability windows, so while your task may not run right away, rest assured it will be added to the queue to be run when the device is back online." ] }, { "attachments": {}, "cell_type": "markdown", "id": "d6f54cb5", "metadata": {}, "source": [ "When your task is finished, you can retrieve the data:" ] }, { "cell_type": "code", "execution_count": null, "id": "c510eb22", "metadata": {}, "outputs": [], "source": [ "data = retrieved_task.result()" ] }, { "cell_type": "code", "execution_count": null, "id": "90660ecd", "metadata": {}, "outputs": [], "source": [ "from qiskit.visualization import plot_histogram\n", "plot_histogram(data.get_counts())" ] }, { "attachments": {}, "cell_type": "markdown", "id": "1819e1f8", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Running algorithms on Braket devices" ] }, { "attachments": {}, "cell_type": "markdown", "id": "41520df9", "metadata": {}, "source": [ "You can also use the Qiskit-Braket provider to run built-in Qiskit algorithms on Braket backends. For example, we can run the VQE algorithm to find the ground state of hydrogen. We'll use the local simulator since the problem can be expressed in a basis that only requires a few qubits and will run quickly." ] }, { "cell_type": "code", "execution_count": null, "id": "1e7de04f", "metadata": {}, "outputs": [], "source": [ "from qiskit.opflow import (\n", " I,\n", " X,\n", " Z,\n", ")\n", "\n", "# Define the Hamiltonian operator for H2 in terms of Pauli spin operators\n", "H2_op = (\n", " (-1.052373245772859 * I ^ I)\n", " + (0.39793742484318045 * I ^ Z)\n", " + (-0.39793742484318045 * Z ^ I)\n", " + (-0.01128010425623538 * Z ^ Z)\n", " + (0.18093119978423156 * X ^ X)\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "9c5cbca8", "metadata": {}, "outputs": [], "source": [ "# Import some utilities\n", "from qiskit.utils import QuantumInstance\n", "from qiskit.circuit.library import TwoLocal\n", "from qiskit.algorithms.optimizers import SLSQP\n", "from qiskit.algorithms import VQE\n", "\n", "# Define a `QuantumInstance` with a Braket backend\n", "qi = QuantumInstance(local_simulator, seed_transpiler=42, seed_simulator=42)\n", "\n", "# Specify VQE configuration\n", "ansatz = TwoLocal(rotation_blocks=\"ry\", entanglement_blocks=\"cz\")\n", "slsqp = SLSQP(maxiter=1)\n", "vqe = VQE(ansatz, optimizer=slsqp, quantum_instance=qi)\n", "\n", "# Find the ground state\n", "result = vqe.compute_minimum_eigenvalue(H2_op)\n", "print(result)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "a5ce5134", "metadata": {}, "source": [ "## What now?" ] }, { "attachments": {}, "cell_type": "markdown", "id": "a497c6ef", "metadata": {}, "source": [ "The sky is the limit! Keep in mind, the Qiskit-Braket provider is still new and experimental, so if you run into a bug or want a new feature supported, consider [submitting a GitHub issue](https://github.com/qiskit-community/qiskit-braket-provider/issues) and opening a feature branch to join in on the development effort yourself!" ] }, { "cell_type": "code", "execution_count": null, "id": "480d8040", "metadata": {}, "outputs": [], "source": [ "print(\"Task Summary\")\n", "print(t.quantum_tasks_statistics())\n", "print('Note: Charges shown are estimates based on your Amazon Braket simulator and quantum processing unit (QPU) task usage. Estimated charges shown may differ from your actual charges. Estimated charges do not factor in any discounts or credits, and you may experience additional charges based on your use of other services such as Amazon Elastic Compute Cloud (Amazon EC2).')\n", "print(f\"Estimated cost to run this example: {t.qpu_tasks_cost() + t.simulator_tasks_cost():.2f} USD\")" ] }, { "cell_type": "code", "execution_count": null, "id": "61350edd", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.10" } }, "nbformat": 4, "nbformat_minor": 5 }