{ "cells": [ { "attachments": {}, "cell_type": "markdown", "id": "dfb19657", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Getting started with the Qiskit-Braket provider" ] }, { "attachments": {}, "cell_type": "markdown", "id": "a95fc7c5", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Qiskit to Braket mapping" ] }, { "attachments": {}, "cell_type": "markdown", "id": "447c275b", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "![qiskit-to-braket-diagram](./data/qiskit-braket-mapping.png)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "04160f91", "metadata": {}, "source": [ "We first start by importing all required classes and functions for this notebook. We also start the cost tracker to print the costs at the end of this notebook." ] }, { "cell_type": "code", "execution_count": 1, "id": "445cc5d9", "metadata": { "ExecuteTime": { "end_time": "2024-03-06T06:26:03.828647Z", "start_time": "2024-03-06T06:26:02.319740Z" } }, "outputs": [], "source": [ "from qiskit import QuantumCircuit\n", "from qiskit.circuit.random import random_circuit\n", "from qiskit.visualization import plot_histogram\n", "\n", "from braket.tracking import Tracker\n", "\n", "from qiskit_braket_provider import BraketLocalBackend, BraketProvider, to_braket\n", "\n", "# Use Braket SDK Cost Tracking to estimate the cost to run this example\n", "t = Tracker().start()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "6fea9c62", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Access Braket devices from Qiskit \n", "\n", "`BraketProvider` class gives you a method `backends` to access backends that are available through Braket SDK." ] }, { "attachments": {}, "cell_type": "markdown", "id": "a59c288b", "metadata": {}, "source": [ "Let's get available devices to use by Qiskit" ] }, { "cell_type": "code", "execution_count": 2, "id": "2b47da63", "metadata": { "slideshow": { "slide_type": "-" }, "ExecuteTime": { "end_time": "2024-03-06T06:26:13.290746Z", "start_time": "2024-03-06T06:26:08.276905Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[BraketBackend[Aria 1], BraketBackend[Aria 2], BraketBackend[Aspen-M-3], BraketBackend[Forte 1], BraketBackend[Harmony], BraketBackend[Lucy], BraketBackend[SV1], BraketBackend[TN1], BraketBackend[dm1]]\n" ] } ], "source": [ "provider = BraketProvider()\n", "print(provider.backends())" ] }, { "attachments": {}, "cell_type": "markdown", "id": "cf366038", "metadata": {}, "source": [ "If you want to explore what is available by specific contraints, you can specify query arguments to `backends` method of provider.\n", "Arguments are fully compatible with Braket's `get_device` method. See the documentation at [braket.aws.aws_device.AwsDevice.get_devices](https://amazon-braket-sdk-python.readthedocs.io/en/stable/_apidoc/braket.aws.aws_device.html#braket.aws.aws_device.AwsDevice.get_devices). For example, you can retrieve the list of online simulators via:" ] }, { "cell_type": "code", "execution_count": 3, "id": "e182e1a4", "metadata": { "ExecuteTime": { "end_time": "2024-03-06T06:26:22.044814Z", "start_time": "2024-03-06T06:26:21.478978Z" } }, "outputs": [ { "data": { "text/plain": "[BraketBackend[SV1], BraketBackend[TN1], BraketBackend[dm1]]" }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "online_simulators_backends = provider.backends(statuses=[\"ONLINE\"], types=[\"SIMULATOR\"])\n", "online_simulators_backends" ] }, { "attachments": {}, "cell_type": "markdown", "id": "edbae0ee", "metadata": {}, "source": [ "For prototyping it is usually a good practice to use simulators \n", "to set up workflow of your program and then change it to real device.\n", "We can access local simulator by creating instance of class `BraketLocalBackend`" ] }, { "cell_type": "code", "execution_count": 4, "id": "2517f020", "metadata": { "slideshow": { "slide_type": "slide" }, "ExecuteTime": { "end_time": "2024-03-06T06:26:28.655697Z", "start_time": "2024-03-06T06:26:28.541800Z" } }, "outputs": [ { "data": { "text/plain": "BraketBackend[default]" }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "local_simulator = BraketLocalBackend()\n", "local_simulator" ] }, { "attachments": {}, "cell_type": "markdown", "id": "390c3a64", "metadata": {}, "source": [ "Any backend can be instantiated via the `get_backend` method of the provider. Here is an example where we create a Backend object for the IonQ `Aria 1` device." ] }, { "cell_type": "code", "execution_count": 5, "id": "64a9cb24", "metadata": { "ExecuteTime": { "end_time": "2024-03-06T06:26:38.862397Z", "start_time": "2024-03-06T06:26:36.334650Z" } }, "outputs": [], "source": [ "Aria_1 = provider.get_backend(\"Aria 1\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "e91eeeee", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Running circuits on Braket devices" ] }, { "attachments": {}, "cell_type": "markdown", "id": "137ae345", "metadata": {}, "source": [ "Let's first create Qiskit circuit. We will start with a Bell circuit." ] }, { "cell_type": "code", "execution_count": 6, "id": "22d4a07a", "metadata": { "ExecuteTime": { "end_time": "2024-03-06T06:26:46.139190Z", "start_time": "2024-03-06T06:26:46.133439Z" } }, "outputs": [ { "data": { "text/plain": " ┌───┐ \nq_0: ┤ H ├──■──\n └───┘┌─┴─┐\nq_1: ─────┤ X ├\n └───┘", "text/html": "
┌───┐ \nq_0: ┤ H ├──■──\n └───┘┌─┴─┐\nq_1: ─────┤ X ├\n └───┘" }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "qc = QuantumCircuit(2)\n", "qc.h(0)\n", "qc.cx(0, 1)\n", "qc.draw()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "512cfd00", "metadata": {}, "source": [ "This circuit can be used to submit a task to the local simulator. In the [tutorials](https://github.com/qiskit-community/qiskit-braket-provider/tree/main/docs/tutorials) associated to the Qiskit-Braket provider, we will use the Braket taxonomy:\n", "- a task is an atomic request to a device or a simulator. \n", "- an hybrid job is a mean to run hybrid quantum-classical algorithms requiring both classical AWS resources and quantum processing units (QPUs). See [What is a Hybrid Job](https://docs.aws.amazon.com/braket/latest/developerguide/braket-what-is-hybrid-job.html) for more details.\n", "\n", "Here, quantum tasks are analogous to Qiskit jobs, which is why tasks have a `job_id` property. If a task has been submitted to Braket managed device, `job_id` will return a Task ARN (Amazon Resource number) which identifies the task and allows to retrieve it in the Braket Console and in your notebooks. " ] }, { "cell_type": "code", "execution_count": 7, "id": "d00d454c", "metadata": { "ExecuteTime": { "end_time": "2024-03-06T06:26:49.681208Z", "start_time": "2024-03-06T06:26:49.656719Z" } }, "outputs": [], "source": [ "task = local_simulator.run(qc, shots=10)" ] }, { "cell_type": "markdown", "id": "0d22adcd", "metadata": {}, "source": [ "Results are returned via a `Result` object, from which you can extract counts and plot them in a histogram." ] }, { "cell_type": "code", "execution_count": 8, "id": "b653ca31", "metadata": { "ExecuteTime": { "end_time": "2024-03-06T06:26:55.379878Z", "start_time": "2024-03-06T06:26:55.035869Z" } }, "outputs": [ { "data": { "text/plain": "