diff --git a/docs/guides/functions.ipynb b/docs/guides/functions.ipynb index 83af1f341de..d9d3a58b2c4 100644 --- a/docs/guides/functions.ipynb +++ b/docs/guides/functions.ipynb @@ -262,7 +262,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "9b9a7a3c-cc98-4c19-93cd-f59793515c70", "metadata": {}, "outputs": [ @@ -281,7 +281,7 @@ "job = ibm_cf.run(\n", " pubs=[(circuit, observable)],\n", " instance=instance,\n", - " backend_name=backend_name, # E.g. \"ibm_kyiv\"\n", + " backend_name=backend_name, # E.g. \"ibm_fez\"\n", ")\n", "\n", "job.job_id" diff --git a/docs/guides/get-qpu-information.ipynb b/docs/guides/get-qpu-information.ipynb index c11a86376e0..51086fc62b2 100644 --- a/docs/guides/get-qpu-information.ipynb +++ b/docs/guides/get-qpu-information.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "cb8aed01-2218-4524-b769-94e3f481b25f", + "id": "b58546f5-fe44-488d-b402-b723a5eff5f4", "metadata": {}, "source": [ "# Get backend information with Qiskit\n", @@ -21,7 +21,7 @@ }, { "cell_type": "markdown", - "id": "3eccac60-3e0f-4f55-ad2d-f19620105ad3", + "id": "8e0f7648-b359-4492-b88d-26566ca78af6", "metadata": { "tags": [ "version-info" @@ -42,7 +42,7 @@ }, { "cell_type": "markdown", - "id": "fb232c67-5b12-4125-b786-aca54bd734c2", + "id": "d3be18e3-d1b5-49c4-a82e-c3e5ecbd5491", "metadata": {}, "source": [ "This page explains how to use Qiskit to find information about your available backends." @@ -50,7 +50,7 @@ }, { "cell_type": "markdown", - "id": "915e21a1-edd8-40a8-a230-2105a024b81c", + "id": "76d675eb-ad62-4436-9649-7cb6837e16f0", "metadata": {}, "source": [ "## List backends\n", @@ -64,7 +64,7 @@ }, { "cell_type": "markdown", - "id": "5a858078-ac19-4ee8-9642-d8d08c8ee58c", + "id": "8a169a1d-0a02-41cd-89b0-5d606114866d", "metadata": {}, "source": [ "\n", @@ -78,7 +78,7 @@ { "cell_type": "code", "execution_count": 1, - "id": "1dfa3af8-686d-420c-8b58-b8e687816fec", + "id": "ad5d41fc-2bb5-4a32-b8bb-8dbc48ef2337", "metadata": {}, "outputs": [ { @@ -86,9 +86,7 @@ "text/plain": [ "[,\n", " ,\n", - " ,\n", - " ,\n", - " ]" + " ]" ] }, "execution_count": 1, @@ -107,7 +105,7 @@ }, { "cell_type": "markdown", - "id": "2e3a18e2-1130-4fb6-a57d-d7226b4268b7", + "id": "88565803-2450-45e1-9075-720d9c57681e", "metadata": {}, "source": [ "The [`QiskitRuntimeService.backend()`](../api/qiskit-ibm-runtime/qiskit-runtime-service#backend) method (note that this is singular: *backend*) takes the name of the backend as the input parameter and returns an [`IBMBackend`](../api/qiskit-ibm-runtime/ibm-backend) instance representing that particular backend:" @@ -116,7 +114,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "25a40e79-a494-40e6-9558-17f4418a0efc", + "id": "cd1fd069-fe00-4865-8ee5-ba788fa405ba", "metadata": {}, "outputs": [ { @@ -136,7 +134,7 @@ }, { "cell_type": "markdown", - "id": "3ba97c22-330f-4eed-8e44-e538f94c2974", + "id": "4bcbb09a-30c0-4b7e-af9f-71a501fc1c47", "metadata": {}, "source": [ "## Filter backends\n", @@ -152,8 +150,8 @@ }, { "cell_type": "code", - "execution_count": 3, - "id": "dbadd7dd-1272-4973-9ad8-5fd5a40ea008", + "execution_count": 2, + "id": "f9611008-cae5-451b-98a8-a59ae281b33e", "metadata": {}, "outputs": [ { @@ -161,12 +159,10 @@ "text/plain": [ "[,\n", " ,\n", - " ,\n", - " ,\n", - " ]" + " ]" ] }, - "execution_count": 3, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -177,7 +173,7 @@ }, { "cell_type": "markdown", - "id": "b2d15581-56d8-4719-8e35-a8cbf0abd0c3", + "id": "89f7fe95-5fcd-4838-a26a-0ca4aa0882e4", "metadata": {}, "source": [ "Use these keyword arguments to filter by any attribute in backend configuration ([JSON schema](https://github.com/Qiskit/ibm-quantum-schemas/blob/main/schemas/backend_configuration_schema.json)) or status ([JSON schema](https://github.com/Qiskit/ibm-quantum-schemas/blob/main/schemas/backend_status_schema.json)). A similar method is [`QiskitRuntimeService.least_busy()`](../api/qiskit-ibm-runtime/qiskit-runtime-service#least_busy), which takes the same filters as `backends()` but returns the backend that matches the filters and has the least number of jobs pending in the queue:" @@ -185,17 +181,17 @@ }, { "cell_type": "code", - "execution_count": 4, - "id": "061ef5dc-cd72-4f7a-b4a0-c7cbaffd4169", + "execution_count": 3, + "id": "89d7a8c6-05e8-4ef8-8e50-bc5ead67a436", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 4, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -206,7 +202,7 @@ }, { "cell_type": "markdown", - "id": "4dc42491-6a03-4e49-bd26-905187edd45b", + "id": "9ab8d5ff-b8ce-4562-8226-95f88bae9438", "metadata": {}, "source": [ "## Static backend information\n", @@ -219,7 +215,7 @@ { "cell_type": "code", "execution_count": 5, - "id": "7c963d4f-9792-4d76-97c8-93aa95c6f791", + "id": "a42c128e-6559-498b-a313-8f1be787ab23", "metadata": {}, "outputs": [ { @@ -245,7 +241,7 @@ }, { "cell_type": "markdown", - "id": "cf5b994a-2434-43df-8e37-c063f1fbe3ce", + "id": "48237011-bd39-4481-8df7-5264620aa6f3", "metadata": {}, "source": [ "For a full list of attributes, see the [`IBMBackend` API documentation](/docs/api/qiskit-ibm-runtime/ibm-backend)." @@ -253,7 +249,7 @@ }, { "cell_type": "markdown", - "id": "fe84b143-8a73-4bd9-b6a4-b3a023e72964", + "id": "c7c38144-478e-4c31-b050-82078de0f505", "metadata": {}, "source": [ "## Dynamic backend information\n", @@ -269,7 +265,7 @@ { "cell_type": "code", "execution_count": 6, - "id": "f1a82580-cd98-4654-94d2-eec8ccc9f7ad", + "id": "94da1ff9-d491-4d78-8720-29141ab1dddf", "metadata": {}, "outputs": [ { @@ -289,7 +285,7 @@ }, { "cell_type": "markdown", - "id": "f96efd0b-3d35-4ab5-b7b1-ef182c6eed31", + "id": "1d3002ef-e196-4d02-b0d7-b84d1a75ce30", "metadata": {}, "source": [ "### Instruction properties\n", @@ -300,7 +296,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "582de91f-62b4-464c-b9c8-f84af948a06a", + "id": "dc15db13-bf2a-4934-8ef6-cacfb953fde6", "metadata": {}, "outputs": [ { @@ -320,7 +316,7 @@ }, { "cell_type": "markdown", - "id": "d5da7085-163f-4cdc-930a-4fc00832480a", + "id": "2d304e9f-6e76-4876-bbb2-b6b768f3f9e3", "metadata": {}, "source": [ "The following cell shows the properties for a measurement operation (including the readout error) on qubit 0." @@ -329,7 +325,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "f6b9e34e-2ef7-4340-8e33-828dd18c8e9d", + "id": "810d55d0-2f60-4bce-a1c2-254e2b989b90", "metadata": {}, "outputs": [ { @@ -349,7 +345,7 @@ }, { "cell_type": "markdown", - "id": "2385a454-d097-4f63-925f-8609433f3bd7", + "id": "4ba1c604-b4b9-498d-ac29-9cb3a9644e09", "metadata": {}, "source": [ "## Next steps\n", diff --git a/docs/guides/instances.mdx b/docs/guides/instances.mdx index 1afdd4af897..6cb0f6926f0 100644 --- a/docs/guides/instances.mdx +++ b/docs/guides/instances.mdx @@ -111,10 +111,10 @@ print(service.instances()) # Optional: Specify it at service level. # This becomes the default unless overwritten. service = QiskitRuntimeService(channel='ibm_quantum', instance="hub1/group1/project1") -backend1 = service.backend("ibm_kyiv") +backend1 = service.backend("ibm_fez") # Optional: Specify it at the backend level, which overwrites the service-level specification when this backend is used. -backend2 = service.backend("ibm_kyiv", instance="hub2/group2/project2") +backend2 = service.backend("ibm_fez", instance="hub2/group2/project2") sampler1 = SamplerV2(mode=backend1) # this will use hub1/group1/project1 sampler2 = SamplerV2(mode=backend2) # this will use hub2/group2/project2 diff --git a/docs/guides/q-ctrl-optimization-solver.ipynb b/docs/guides/q-ctrl-optimization-solver.ipynb index a6a427efe8e..458d941ac34 100644 --- a/docs/guides/q-ctrl-optimization-solver.ipynb +++ b/docs/guides/q-ctrl-optimization-solver.ipynb @@ -305,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "16c66d64", "metadata": {}, "outputs": [], @@ -315,7 +315,7 @@ " problem=problem_as_str,\n", " problem_type=\"maxcut\",\n", " instance=instance,\n", - " backend_name=backend_name, # E.g. \"ibm_kyiv\"\n", + " backend_name=backend_name, # E.g. \"ibm_fez\"\n", ")" ] }, @@ -540,7 +540,7 @@ "mvc_job = solver.run(\n", " problem=srepr(cost_function),\n", " instance=instance,\n", - " backend_name=backend_name, # E.g. \"ibm_kyiv\"\n", + " backend_name=backend_name, # E.g. \"ibm_fez\"\n", ")" ] }, diff --git a/docs/guides/q-ctrl-performance-management.ipynb b/docs/guides/q-ctrl-performance-management.ipynb index ab100fc261f..3b7ebedb279 100644 --- a/docs/guides/q-ctrl-performance-management.ipynb +++ b/docs/guides/q-ctrl-performance-management.ipynb @@ -245,7 +245,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "26952e1f", "metadata": {}, "outputs": [], @@ -255,7 +255,7 @@ " primitive=\"estimator\",\n", " pubs=estimator_pubs,\n", " instance=instance,\n", - " backend_name=backend_name, # E.g. \"ibm_kyiv\", or omit to default to the least busy device\n", + " backend_name=backend_name,\n", ")" ] }, @@ -397,11 +397,9 @@ "- ibm_cleveland\n", "- ibm_fez\n", "- ibm_kawasaki\n", - "- ibm_kyiv\n", "- ibm_nazca\n", "- ibm_quebec\n", "- ibm_rensselaer\n", - "- ibm_sherbrooke\n", "- ibm_strasbourg\n", "- ibm_torino\n", "\n", @@ -488,7 +486,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "2595df84", "metadata": {}, "outputs": [], @@ -498,7 +496,7 @@ " primitive=\"sampler\",\n", " pubs=sampler_pubs,\n", " instance=instance,\n", - " backend_name=backend_name, # Such as \"ibm_kyiv\", or omit to default to the least busy device\n", + " backend_name=backend_name,\n", ")" ] }, diff --git a/docs/guides/serverless-run-first-workload.ipynb b/docs/guides/serverless-run-first-workload.ipynb index e1793480fcd..1fc47277555 100644 --- a/docs/guides/serverless-run-first-workload.ipynb +++ b/docs/guides/serverless-run-first-workload.ipynb @@ -141,18 +141,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "ebefb5ac-c8a8-4350-b16f-0677f0e412e5", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ibm_kyiv\n" - ] - } - ], + "outputs": [], "source": [ "from qiskit_ibm_runtime import QiskitRuntimeService\n", "\n", diff --git a/docs/tutorials/advanced-techniques-for-qaoa.ipynb b/docs/tutorials/advanced-techniques-for-qaoa.ipynb index 3b17937dd09..418b0ee9655 100644 --- a/docs/tutorials/advanced-techniques-for-qaoa.ipynb +++ b/docs/tutorials/advanced-techniques-for-qaoa.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "8f563e71-f031-43a7-9e71-1f3bf50cf673", + "id": "9f81f6b2-d7f3-4cc2-b09b-cf3a627c7b0f", "metadata": { "tags": [ "remove-cell" @@ -14,7 +14,7 @@ }, { "cell_type": "markdown", - "id": "689402c9-cb97-41a8-8587-416c346feb03", + "id": "1a869c2d-ae51-47d3-8a41-bfcf5e505f59", "metadata": {}, "source": [ "# Advanced Techniques for QAOA\n", @@ -23,7 +23,7 @@ }, { "cell_type": "markdown", - "id": "e1fdfd3c-ea42-44f9-8e04-fe013c26c8f9", + "id": "ea97567d-810f-4cca-8edf-a47d70ea870a", "metadata": {}, "source": [ "## Background\n", @@ -35,26 +35,26 @@ "\n", "- **SWAP strategy with SAT initial mapping**: This is a specifically designed transpiler pass for QAOA that uses a SWAP strategy and a SAT solver together to improve the selection of which physical qubits on the QPU to use. The SWAP strategy exploits the commutativity of the QAOA operators to reorder gates so that layers of SWAP gates can be simultaneously executed, thus reducing the depth of the circuit [\\[1\\]](#references). The SAT solver is used to find an initial mapping that minimizes the number of SWAP operations needed to map the qubits in the circuit to the physical qubits on the device [\\[2\\]](#references) .\n", "- **CVaR cost function**: Typically the expected value of the cost Hamiltonian is used as the cost function for QAOA, but as was shown in [\\[3\\]](#references) , focusing on the tail of the distribution, rather than the expected value, can improve the performance of QAOA for combinatorial optimization problems. The CVaR accomplishes this. For a given set of shots with corresponding objective values of the considered optimization problem, the Conditional Value at Risk (CVaR) with confidence level $\\alpha \\in [0, 1]$ is defined as the average of the $\\alpha$ best shots [\\[3\\]](#references).\n", - "Thus, $\\alpha = 1$ corresponds to the standard expected value, while $\\alpha=0$ corresponds to the minimum of the given shots, and $\\alpha \\in (0, 1)$ is a tradeoff between focusing on better shots, but still applying some averaging to smoothen the optimization landscape. Additionally, the CVaR can be used as error mitigation technique to improve the quality of the objective value estimation [\\[4\\]](#references)." + "Thus, $\\alpha = 1$ corresponds to the standard expected value, while $\\alpha=0$ corresponds to the minimum of the given shots, and $\\alpha \\in (0, 1)$ is a tradeoff between focusing on better shots, while still applying some averaging to smooth out the optimization landscape. Additionally, the CVaR can be used as an error mitigation technique to improve the quality of the objective value estimation [\\[4\\]](#references)." ] }, { "cell_type": "markdown", - "id": "637cc0b1-354b-4c91-abd6-ce0d37eea3f2", + "id": "40fb546e-85e0-450b-a5ea-5d08950d129f", "metadata": {}, "source": [ "## Requirements\n", "\n", "Before starting this tutorial, be sure you have the following installed:\n", "- Qiskit SDK v1.0 or later, with visualization support ( `pip install 'qiskit[visualization]'` )\n", - "- Qiskit Runtime 0.22 or later (`pip install qiskit-ibm-runtime`)\n", + "- Qiskit Runtime v0.22 or later (`pip install qiskit-ibm-runtime`)\n", "- Rustworkx graph library (`pip install rustworkx`)\n", "- Python SAT (`pip install python-sat`)" ] }, { "cell_type": "markdown", - "id": "2e64680d-42ef-4d01-bc42-3e4bf08cea4c", + "id": "50285e5f-1a7b-471c-a223-1ae0af19d9ed", "metadata": {}, "source": [ "## Setup" @@ -63,7 +63,7 @@ { "cell_type": "code", "execution_count": null, - "id": "90e8ddc0-b27a-4243-a2ea-6465988fec53", + "id": "d019ea68-61e0-4341-84c7-e612ca10dde7", "metadata": {}, "outputs": [], "source": [ @@ -99,7 +99,7 @@ }, { "cell_type": "markdown", - "id": "a7b390ce-6a6e-4cce-b586-2980d0e94507", + "id": "8b77b0c9-f5a6-476e-86b8-069ba14f9ab3", "metadata": {}, "source": [ "## Step 1: Map classical inputs to a quantum problem\n", @@ -107,36 +107,27 @@ "### Max-Cut Problem\n", "Let's consider solving the **Max-Cut** problem on a graph with 100 nodes using QAOA.\n", "The Max-Cut problem is a combinatorial optimization problem that is defined on a graph $G = (V, E)$, where $V$ is the set of vertices and $E$ is the set of edges. The goal is to partition the vertices into two sets, $S$ and $V \\setminus S$, such that the number of edges between the two sets is maximized.\n", - "In this example, we will use a graph with 100 nodes that is based on a hardware coupling map.\n", + "In this example, we use a graph with 100 nodes that is based on a hardware coupling map.\n", "\n", "\n", - "### Graph -> Hamiltonian\n", + "### Graph → Hamiltonian\n", "\n", - "First, convert the graph into a Hamiltonian that is suited for the QAOA. Details on this process can be found in the introductory QAOA tutorial, linked above." + "First, convert the graph into a Hamiltonian that is suited for the QAOA. Details on this process can be found in the [introductory QAOA tutorial.](/docs/tutorials/quantum-approximate-optimization-algorithm)" ] }, { "cell_type": "code", "execution_count": null, - "id": "179077e5-50d5-4db2-8b55-591aeca1a35b", + "id": "d19a5086-a858-45e1-b60b-f31db350e9d9", "metadata": { "collapsed": true, "jupyter": { "outputs_hidden": true } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], + "outputs": [], "source": [ - "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"\", overwrite=True, set_as_default=True)\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(operational=True, simulator=False)\n", "print(backend)" ] @@ -144,7 +135,7 @@ { "cell_type": "code", "execution_count": null, - "id": "056a7cc3-7c8e-41ea-a17b-ef048e8e61d9", + "id": "c989c08a-1e79-4059-b9d7-12651909b3bb", "metadata": {}, "outputs": [ { @@ -173,7 +164,7 @@ { "cell_type": "code", "execution_count": null, - "id": "cdd5c74f-f894-4a80-98bf-27af3f112598", + "id": "e39c4e42-ce97-4a04-8879-da4d33a684bc", "metadata": {}, "outputs": [ { @@ -223,7 +214,7 @@ }, { "cell_type": "markdown", - "id": "1b61cc7b-37ec-4c1e-ae62-ca59a030a590", + "id": "cf94748d-25b2-47bc-8e65-8504dee843b6", "metadata": {}, "source": [ "### Hamiltonian → quantum circuit" @@ -232,7 +223,7 @@ { "cell_type": "code", "execution_count": null, - "id": "99f216ff-e94b-4daf-bc1b-278f9bd1d9f6", + "id": "8ff1859a-7487-4113-b8d7-1342cd6bf527", "metadata": {}, "outputs": [ { @@ -256,20 +247,20 @@ }, { "cell_type": "markdown", - "id": "4604b82d-2003-4842-bbef-6b9ce5caf782", + "id": "4e576068-53e7-4a06-a83b-87e95de141e9", "metadata": {}, "source": [ "## Step 2: Optimize problem for quantum hardware execution\n", "### SWAP strategy with the SAT initial mapping\n", "We will demonstrate how to build and optimize QAOA circuits using the **SWAP strategy with SAT initial mapping**, a specifically designed transpiler pass for QAOA applied to quadratic problems.\n", "\n", - "In this example, we choose a SWAP insertion strategy for blocks of commuting two-qubit gates which applies layers of SWAP gates simultaneously executable on the coupling map. This strategy is presented in [\\[1\\]](#references) and exposed as a standardized Qiskit transpiler pass (see [here](/docs/api/qiskit/qiskit.transpiler.passes.Commuting2qGateRouter)), where we can choose different qubit configurations. We use a line swap strategy in this example." + "In this example, we choose a SWAP insertion strategy for blocks of commuting two-qubit gates, which applies layers of SWAP gates that are simultaneously executable on the coupling map. This strategy is presented in [\\[1\\]](#references) and is exposed as a standardized Qiskit transpiler pass (see [`Commuting2qGateRouter`](/docs/api/qiskit/qiskit.transpiler.passes.Commuting2qGateRouter)), where we can choose different qubit configurations. We use a line swap strategy in this example." ] }, { "cell_type": "code", "execution_count": null, - "id": "a10620d5-e70b-4d08-badd-ec5103b000e9", + "id": "7c54402a-7696-4b0e-826a-6e0ac4c54395", "metadata": {}, "outputs": [], "source": [ @@ -297,22 +288,22 @@ }, { "cell_type": "markdown", - "id": "038dc48a-7dbc-4fcc-9296-440181177d4a", + "id": "ba53fd1d-0d68-43e3-9102-4c6e64f04de7", "metadata": {}, "source": [ "#### Remap the graph using a SAT mapper\n", "\n", - "Even when a circuit consists of commuting gates (this is the case for the QAOA circuit, but also for trotterized simulations of Ising Hamiltonians), finding a good initial mapping is a challenging task. The SAT-based approach presented in [\\[2\\]](#references) enables the discovery of effective initial mappings for circuits with commuting gates, resulting in a significant reduction in the number of required SWAP layers. This approach has been demonstrated to scale to up to *500 qubits*, as illustrated in the paper.\n", + "Even when a circuit consists of commuting gates (this is the case for the QAOA circuit, but also for Trotterized simulations of Ising Hamiltonians), finding a good initial mapping is a challenging task. The SAT-based approach presented in [\\[2\\]](#references) enables the discovery of effective initial mappings for circuits with commuting gates, resulting in a significant reduction in the number of required SWAP layers. This approach has been demonstrated to scale to up to *500 qubits*, as illustrated in the paper.\n", "\n", "The following code demonstrates how to use the `SATMapper` from Matsuo et al. to remap the graph. This process allows the problem to be mapped to a more optimal initial state for a specified SWAP strategy, resulting in a significant reduction in the number of SWAP layers required to execute the circuit.\n", "\n", - "In `SATMapper`, the problem of finding a good initial mapping is formulated as a SAT problem. A SAT solver is used to find such an initial mapping for the QAOA circuit. `python-sat` (`pysat` in short) is a Python library for a SAT solver, and we will use it to solve the SAT problem in this example." + "In `SATMapper`, the problem of finding a good initial mapping is formulated as a SAT problem. A SAT solver is used to find such an initial mapping for the QAOA circuit. `python-sat` (`pysat` for short) is a Python library for a SAT solver, and we will use it to solve the SAT problem in this example." ] }, { "cell_type": "code", "execution_count": null, - "id": "204be7cb-33c0-49dc-bb47-40d93027e940", + "id": "df9d861a-64e8-49ee-aed1-c41f437fa743", "metadata": {}, "outputs": [], "source": [ @@ -325,9 +316,11 @@ "class SATResult:\n", " \"\"\"A data class to hold the result of a SAT solver.\"\"\"\n", "\n", - " satisfiable: bool # Satisfiable is True if the SAT model could be solved in a given time.\n", + " satisfiable: bool # Satisfiable is True if the SAT model could be solved\n", + " # in a given time.\n", " solution: dict # The solution to the SAT problem if it is satisfiable.\n", - " mapping: list # The mapping of nodes in the pattern graph to nodes in the target graph.\n", + " mapping: list # The mapping of nodes in the pattern graph to nodes in the\n", + " # target graph.\n", " elapsed_time: float # The time it took to solve the SAT model.\n", "\n", "\n", @@ -336,24 +329,26 @@ " the initial mapping problem in SWAP gate insertion for commuting gates.\n", "\n", " When this pass is run on a DAG it will look for the first instance of\n", - " :class:`.Commuting2qBlock` and use the program graph :math:`P` of this block of gates to\n", - " find a layout for a given swap strategy. This layout is found with a\n", - " binary search over the layers :math:`l` of the swap strategy. At each considered layer\n", - " a subgraph isomorphism problem formulated as a SAT is solved by a SAT solver. Each instance\n", - " is whether it is possible to embed the program graph :math:`P` into the effective\n", - " connectivity graph :math:`C_l` that is achieved by applying :math:`l` layers of the\n", - " swap strategy to the coupling map :math:`C_0` of the backend. Since solving SAT problems\n", - " can be hard, a ``time_out`` fixes the maximum time allotted to the SAT solver for each\n", - " instance. If this time is exceeded the considered problem is deemed unsatisfiable and\n", - " the binary search proceeds to the next number of swap layers :math:``l``.\n", + " :class:`.Commuting2qBlock` and use the program graph :math:`P` of this block\n", + " of gates to find a layout for a given swap strategy. This layout is found\n", + " with a binary search over the layers :math:`l` of the swap strategy. At each\n", + " considered layer a subgraph isomorphism problem formulated as a SAT is solved\n", + " by a SAT solver. Each instance is whether it is possible to embed the program\n", + " graph :math:`P` into the effective connectivity graph :math:`C_l` that is\n", + " achieved by applying :math:`l` layers of the swap strategy to the coupling map\n", + " :math:`C_0` of the backend. Since solving SAT problems can be hard, a\n", + " ``time_out`` fixes the maximum time allotted to the SAT solver for each\n", + " instance. If this time is exceeded the considered problem is deemed\n", + " unsatisfiable and the binary search proceeds to the next number of swap\n", + " layers :math:``l``.\n", " \"\"\"\n", "\n", " def __init__(self, timeout: int = 60):\n", " \"\"\"Initialize the SATMapping.\n", "\n", " Args:\n", - " timeout: The allowed time in seconds for each iteration of the SAT solver. This\n", - " variable defaults to 60 seconds.\n", + " timeout: The allowed time in seconds for each iteration of the SAT\n", + " solver. This variable defaults to 60 seconds.\n", " \"\"\"\n", " self.timeout = timeout\n", "\n", @@ -364,29 +359,34 @@ " min_layers: int | None = None,\n", " max_layers: int | None = None,\n", " ) -> dict[int, SATResult]:\n", - " r\"\"\"Find an initial mapping for a given swap strategy. Perform a binary search\n", - " over the number of swap layers, and for each number of swap layers solve a\n", - " subgraph isomorphism problem formulated as a SAT problem.\n", + " r\"\"\"Find an initial mapping for a given swap strategy. Perform a\n", + " binary search over the number of swap layers, and for each number\n", + " of swap layers solve a subgraph isomorphism problem formulated as\n", + " a SAT problem.\n", "\n", " Args:\n", " program_graph (rx.Graph): The program graph with commuting gates, where\n", " each edge represents a two-qubit gate.\n", - " swap_strategy (SwapStrategy): The swap strategy to use to find the initial mapping.\n", - " min_layers (int): The minimum number of swap layers to consider. Defaults to\n", - " the maximum degree of the program graph - 2.\n", - " max_layers (int): The maximum number of swap layers to consider. Defaults to\n", - " the number of qubits in the swap strategy - 2.\n", + " swap_strategy (SwapStrategy): The swap strategy to use to find the\n", + " initial mapping.\n", + " min_layers (int): The minimum number of swap layers to consider.\n", + " Defaults to the maximum degree of the\n", + " program graph - 2.\n", + " max_layers (int): The maximum number of swap layers to consider.\n", + " Defaults to the number of qubits in the\n", + " swap strategy - 2.\n", "\n", " Returns:\n", - " dict[int, SATResult]: A dictionary containing the results of the SAT solver for\n", - " each number of swap layers.\n", + " dict[int, SATResult]: A dictionary containing the results of the SAT\n", + " solver for each number of swap layers.\n", " \"\"\"\n", " num_nodes_g1 = len(program_graph.nodes())\n", " num_nodes_g2 = swap_strategy.distance_matrix.shape[0]\n", " if num_nodes_g1 > num_nodes_g2:\n", " return SATResult(False, [], [], 0)\n", " if min_layers is None:\n", - " # use the maximum degree of the program graph - 2 as the lower bound.\n", + " # use the maximum degree of the program graph - 2\n", + " # as the lower bound.\n", " min_layers = max((d for _, d in program_graph.degree)) - 2\n", " if max_layers is None:\n", " max_layers = num_nodes_g2 - 1\n", @@ -403,10 +403,12 @@ " binary_search_results = {}\n", "\n", " def interrupt(solver):\n", - " # This function is called to interrupt the solver when the timeout is reached.\n", + " # This function is called to interrupt the solver when the\n", + " # timeout is reached.\n", " solver.interrupt()\n", "\n", - " # Make a cnf (conjunctive normal form) for the one-to-one mapping constraint\n", + " # Make a cnf (conjunctive normal form) for the one-to-one\n", + " # mapping constraint\n", " cnf1 = []\n", " for i in range(num_nodes_g1):\n", " clause = variables[i, :].tolist()\n", @@ -418,14 +420,15 @@ " for k, m in combinations(clause, 2):\n", " cnf1.append([-1 * k, -1 * m])\n", "\n", - " # Perform a binary search over the number of swap layers to find the minimum\n", - " # number of swap layers that satisfies the subgraph isomorphism problem.\n", + " # Perform a binary search over the number of swap layers to find the\n", + " # minimum number of swap layers that satisfies the subgraph isomorphism\n", + " # problem.\n", " while min_layers < max_layers:\n", " num_layers = (min_layers + max_layers) // 2\n", "\n", - " # Create the connectivity matrix. Note that if the swap strategy cannot reach\n", - " # full connectivity then its distance matrix will have entries with -1. These\n", - " # entries must be treated as False.\n", + " # Create the connectivity matrix. Note that if the swap strategy\n", + " # cannot reach full connectivity then its distance matrix will have\n", + " # entries with -1. These entries must be treated as False.\n", " d_matrix = swap_strategy.distance_matrix\n", " connectivity_matrix = (\n", " (-1 < d_matrix) & (d_matrix <= num_layers)\n", @@ -450,7 +453,8 @@ "\n", " with Solver(bootstrap_with=cnf, use_timer=True) as solver:\n", " # Solve the SAT problem with a timeout.\n", - " # Timer is used to interrupt the solver when the timeout is reached.\n", + " # Timer is used to interrupt the solver when the\n", + " # timeout is reached.\n", " timer = Timer(self.timeout, interrupt, [solver])\n", " timer.start()\n", " status = solver.solve_limited(expect_interrupt=True)\n", @@ -463,14 +467,16 @@ " f\"Layers: {num_layers}, Status: {status}, Time: {e_time}\"\n", " )\n", " if status:\n", - " # If the SAT problem is satisfiable, convert the solution to a mapping.\n", + " # If the SAT problem is satisfiable, convert the solution\n", + " # to a mapping.\n", " mapping = [vid2mapping[idx] for idx in sol if idx > 0]\n", " binary_search_results[num_layers] = SATResult(\n", " status, sol, mapping, e_time\n", " )\n", " max_layers = num_layers\n", " else:\n", - " # If the SAT problem is unsatisfiable, return the last satisfiable solution.\n", + " # If the SAT problem is unsatisfiable, return the last\n", + " # satisfiable solution.\n", " binary_search_results[num_layers] = SATResult(\n", " status, sol, [], e_time\n", " )\n", @@ -485,14 +491,16 @@ "\n", " Args:\n", " graph (nx.Graph): The graph to remap.\n", - " swap_strategy (SwapStrategy): The swap strategy to use to find the initial mapping.\n", + " swap_strategy (SwapStrategy): The swap strategy to use\n", + " to find the initial mapping.\n", "\n", " Returns:\n", - " tuple: A tuple containing the remapped graph, the edge map, and the number of layers of\n", - " the swap strategy that was used to find the initial mapping. If no solution is found\n", - " then the tuple contains None for each element.\n", - " Note the returned edge map `{k: v}` means that node `k` in the original\n", - " graph gets mapped to node `v` in the Pauli strings.\n", + " tuple: A tuple containing the remapped graph, the edge map, and the\n", + " number of layers of the swap strategy that was used to find the\n", + " initial mapping. If no solution is found then the tuple contains\n", + " None for each element. Note the returned edge map `{k: v}` means that\n", + " node `k` in the original graph gets mapped to node `v` in the\n", + " Pauli strings.\n", " \"\"\"\n", " num_nodes = len(graph.nodes())\n", " results = self.find_initial_mappings(\n", @@ -518,7 +526,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "0a98c9b9-9b80-47e2-b0e8-33766a109e25", + "id": "e689e09e-6ca7-4154-8602-d1d954ebe80b", "metadata": {}, "outputs": [ { @@ -554,7 +562,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "7b505f06-10c9-4245-8836-4dfefece08de", + "id": "ecf6e8c3-65c2-4430-8dd3-d67b8842045d", "metadata": {}, "outputs": [ { @@ -587,28 +595,28 @@ }, { "cell_type": "markdown", - "id": "657c6785-9129-4c66-b144-b34a76d22333", + "id": "5ae531be-80eb-4acd-b84a-7d466fd872e7", "metadata": {}, "source": [ "#### Build a QAOA circuit with the SWAP strategy and the SAT mapping\n", - "We only want to apply the SWAP strategies to the cost operator layer, so we will start by creating the isolated block that we will later transform and append to the final QAOA circuit.\n", + "We only want to apply the SWAP strategies to the cost operator layer, so we start by creating the isolated block that we will later transform and append to the final QAOA circuit.\n", "\n", - "For this, we can use the [`QAOAAnsatz`](/docs/api/qiskit/qiskit.circuit.library.QAOAAnsatz) class from Qiskit. We will input an empty circuit to the `initial_state` and `mixer_operator` fields to make sure we are building an isolated cost operator layer.\n", - "We also define the edge_coloring map so that RZZGates are positioned next to SWAP gates. This strategic placement allows us to exploit CX cancellations, optimizing the circuit for better performance.\n", + "For this, we can use the [`QAOAAnsatz`](/docs/api/qiskit/qiskit.circuit.library.QAOAAnsatz) class from Qiskit. We input an empty circuit to the `initial_state` and `mixer_operator` fields to make sure we are building an isolated cost operator layer.\n", + "We also define the edge_coloring map so that RZZ gates are positioned next to SWAP gates. This strategic placement allows us to exploit CX cancellations, optimizing the circuit for better performance.\n", "This process is executed within the `create_qaoa_swap_circuit` function." ] }, { "cell_type": "code", "execution_count": null, - "id": "3bde29ab-1f16-4fc8-81b1-dac467f5ecc1", + "id": "57d5eb53-9cda-4c38-a00b-26ed4b533bcd", "metadata": {}, "outputs": [], "source": [ "def make_meas_map(circuit: QuantumCircuit) -> dict:\n", " \"\"\"Return a mapping from qubit index (the key) to classical bit (the value).\n", "\n", - " This allows us to account for the swapping order introduced by the SwapStrategy.\n", + " This allows us to account for the swapping order introduced by the SWAP strategy.\n", " \"\"\"\n", " creg = circuit.cregs[0]\n", " qreg = circuit.qregs[0]\n", @@ -655,7 +663,7 @@ "):\n", " \"\"\"Applies QAOA layers to construct circuit.\n", "\n", - " First, the initial state is applied. If `initial_state` is None we begin in the\n", + " First, the initial state is applied. If `initial_state` is None, we begin in the\n", " initial superposition state. Next, we alternate between layers of the cost operator\n", " and the mixer. The cost operator is alternatively applied in order and in reverse\n", " instruction order. This allows us to apply the swap strategy on odd `p` layers\n", @@ -728,8 +736,8 @@ " gates. This allows us to choose an ordering such that `Rzz` gates will\n", " immediately precede SWAP gates to leverage CNOT cancellation.\n", " theta: The QAOA angles.\n", - " qaoa_layers: The number of layers of the cost-operator and the mixer operator.\n", - " initial_state: The initial state on which we apply layers of cost-operator\n", + " qaoa_layers: The number of layers of the cost operator and the mixer operator.\n", + " initial_state: The initial state on which we apply layers of cost operator\n", " and mixer.\n", " mixer: The QAOA mixer. It will be applied as is onto the QAOA circuit. Therefore,\n", " its output must have the same ordering of qubits as its input.\n", @@ -755,11 +763,11 @@ " # This will allow us to recover the permutation of the measurements that the swap introduce.\n", " cost_layer.measure_all()\n", "\n", - " # Now, apply the swap strategy for commuting pauli evolution gates\n", + " # Now, apply the swap strategy for commuting Pauli evolution gates\n", " cost_layer = apply_swap_strategy(cost_layer, swap_strategy, edge_coloring)\n", "\n", " # Compute the measurement map (qubit to classical bit).\n", - " # we will apply this for qaoa_layers % 2 == 1.\n", + " # We will apply this for qaoa_layers % 2 == 1.\n", " if qaoa_layers % 2 == 1:\n", " meas_map = make_meas_map(cost_layer)\n", " else:\n", @@ -778,7 +786,7 @@ { "cell_type": "code", "execution_count": 10, - "id": "0402a1eb-c450-49ba-b7f0-887e6c28ff04", + "id": "25db3ad8-0666-42f9-8569-544f89d99391", "metadata": {}, "outputs": [ { @@ -798,13 +806,13 @@ }, { "cell_type": "code", - "execution_count": 11, - "id": "d6e71480-33fe-4843-b27d-04e55259e4d5", + "execution_count": null, + "id": "7793ef92-ce59-4fd7-b43f-48d4e3427e3a", "metadata": {}, "outputs": [], "source": [ - "# We can define the edge_coloring map so that RZZGates are positioned next to SWAP gates to exploit CX cancellations\n", - "# We use greedy edge coloring to color the edges of the graph in the rustworkx. This coloring is used to order the Rzz gates in the circuit.\n", + "# We can define the edge_coloring map so that RZZ gates are positioned next to SWAP gates to exploit CX cancellations\n", + "# We use greedy edge coloring to color the edges of the graph in the rustworkx. This coloring is used to order the RZZ gates in the circuit.\n", "\n", "edge_coloring_idx = rx.graph_greedy_edge_color(graph_100)\n", "edge_coloring = {\n", @@ -817,7 +825,7 @@ { "cell_type": "code", "execution_count": 12, - "id": "b3c19d0d-41f6-48e1-8e56-c7e54287a69a", + "id": "82ae28b3-85eb-4487-8100-1e622e93cccf", "metadata": {}, "outputs": [ { @@ -844,7 +852,7 @@ }, { "cell_type": "markdown", - "id": "bfc9c09b-3c1a-4f2b-87e9-085d1c2a937c", + "id": "e2afd1a7-0980-433b-a3a8-303d7e7718b1", "metadata": {}, "source": [ "## Step 3: Execute using Qiskit primitives\n", @@ -859,17 +867,9 @@ { "cell_type": "code", "execution_count": null, - "id": "ba981a4c-5f1a-48a5-b577-07f0cd3a9d44", + "id": "5e4745d4-df78-4ec6-b390-549ee91bba20", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], + "outputs": [], "source": [ "pass_manager = generate_preset_pass_manager(\n", " backend=backend,\n", @@ -882,7 +882,7 @@ { "cell_type": "code", "execution_count": 14, - "id": "5d0cede0-cab2-4598-9a9c-9bbd5a03b986", + "id": "e6794cf3-7fbe-46a5-bdc0-5faad1235365", "metadata": {}, "outputs": [], "source": [ @@ -918,7 +918,7 @@ { "cell_type": "code", "execution_count": null, - "id": "cf3d1f9d-fedc-43ce-8957-3d613bb1c476", + "id": "c5e5f7a4-01f6-4a02-9114-3bb0e24be1a2", "metadata": {}, "outputs": [], "source": [ @@ -1022,7 +1022,7 @@ }, { "cell_type": "markdown", - "id": "6006dd68-db46-4ed1-ae16-f1ea166067c2", + "id": "63fa2ab4-5354-4022-ab46-e9bbf73870de", "metadata": {}, "source": [ "The CVaR can be used as an error mitigation technique as previously discussed [\\[4\\]](#references). In this example, we determine $\\alpha$ and the number of shots according to the circuit's error rate." @@ -1031,7 +1031,7 @@ { "cell_type": "code", "execution_count": 16, - "id": "c01f0762-d603-4dc8-bdf5-9694bf751817", + "id": "032bf312-4bf4-40f4-81f0-2ae8a719b98b", "metadata": {}, "outputs": [ { @@ -1068,7 +1068,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d4cec8e2-f896-46c3-80c4-8cf4a6d063e9", + "id": "4e608d54-60ee-4a63-91f7-aace7c036694", "metadata": {}, "outputs": [ { @@ -1142,7 +1142,7 @@ }, { "cell_type": "markdown", - "id": "1f691aa7-e53a-4d04-80e1-33fa901e7a6b", + "id": "1d190fa4-3bbe-412a-b296-6dddd3ad2b12", "metadata": {}, "source": [ "## Step 4: Post-process and return result in desired classical format" @@ -1151,7 +1151,7 @@ { "cell_type": "code", "execution_count": null, - "id": "b4f377c5-5501-4568-801d-5599c9315efa", + "id": "761821cb-9a0c-4efb-806b-75513302d34a", "metadata": {}, "outputs": [ { @@ -1183,16 +1183,16 @@ }, { "cell_type": "markdown", - "id": "99e70f6e-f794-4dcf-b991-5da71496ba53", + "id": "38aadfcb-aec9-4dbb-a9d3-319239eae196", "metadata": {}, "source": [ - "The following graph is the results of the standard expectation value." + "The following cost is the result of the standard expectation value." ] }, { "cell_type": "code", "execution_count": 36, - "id": "2e04c7ae-1eb9-4a66-950b-4c9f4b7c0ed1", + "id": "7e8af29e-c99b-41f2-b6dd-2be471e1af21", "metadata": {}, "outputs": [ { @@ -1220,7 +1220,7 @@ { "cell_type": "code", "execution_count": null, - "id": "f0962c7a-464b-4cd6-ad5b-36df07eb7691", + "id": "5ea9e6aa-4297-4687-b484-1695d415bad5", "metadata": {}, "outputs": [ { @@ -1260,19 +1260,19 @@ }, { "cell_type": "markdown", - "id": "c5707795-b521-4d33-b361-e75fa924d463", + "id": "c5879546-35ab-4876-bed9-262b85f130cc", "metadata": {}, "source": [ "Finally, let's draw a graph based on the CVaR result.\n", "We split the graph nodes into two sets based on the CVaR result.\n", - "The nodes in the first set are colored in grey, and the nodes in the second set are colored in purple.\n", + "The nodes in the first set are colored in gray, and the nodes in the second set are colored in purple.\n", "The edges between the two sets are the edges that are cut by the partitioning." ] }, { "cell_type": "code", "execution_count": 46, - "id": "91d3560b-a688-41a4-a4d6-37ab218541f6", + "id": "852dfeed-2871-4ca1-9754-15c95293198e", "metadata": {}, "outputs": [ { @@ -1300,7 +1300,7 @@ }, { "cell_type": "markdown", - "id": "213b262e-cb95-47cb-b3b6-e44505e2bcf1", + "id": "82f5c13b-a141-4657-adfd-bb18e88ad9f2", "metadata": {}, "source": [ "## References\n", @@ -1316,7 +1316,7 @@ }, { "cell_type": "markdown", - "id": "993f61f9-4fb0-4f69-8734-f108c4287552", + "id": "c048cd84-d6e8-4b8a-926e-a7f7724a86e2", "metadata": {}, "source": [ "## Tutorial survey\n", @@ -1328,10 +1328,10 @@ }, { "cell_type": "markdown", - "id": "600bde6b-5d07-475d-8720-0031007f3cf2", + "id": "d325feb7-b9c5-4e6a-b1ee-93e5f96213cb", "metadata": {}, "source": [ - "© IBM Corp. 2024" + "© IBM Corp. 2025" ] } ], diff --git a/docs/tutorials/ai-transpiler-introduction.ipynb b/docs/tutorials/ai-transpiler-introduction.ipynb index 17e252012fd..e1b27fa7f9d 100644 --- a/docs/tutorials/ai-transpiler-introduction.ipynb +++ b/docs/tutorials/ai-transpiler-introduction.ipynb @@ -3,55 +3,56 @@ { "attachments": {}, "cell_type": "markdown", - "id": "aed5a4ec-3fb1-46d3-85eb-65f2d80d8279", + "id": "f59032f0-f29a-4e52-9cab-855ed6f86b00", "metadata": {}, "source": [ "{/* cspell:ignore fontsize */}\n", "\n", - "# AI Transpiler Introduction\n", + "# Qiskit AI-powered transpiler service introduction\n", "*Estimated QPU usage: None (NOTE: no execution was done in this notebook as notebook is focused on the transpilation process)*\n", "\n", "## Background\n", "\n", - "The **Qiskit AI-powered transpiler service (QTS)** introduces machine learning-based optimizations in both **routing** and **synthesis** passes. These AI modes have been designed to tackle the limitations of traditional transpilation, particularly for **large-scale circuits** and **complex hardware topologies**.\n", + "The **Qiskit AI-powered transpiler service (QTS)** introduces machine learning-based optimizations in both routing and synthesis passes. These AI modes have been designed to tackle the limitations of traditional transpilation, particularly for large-scale circuits and complex hardware topologies.\n", "\n", - "**Key Features of the AI-Powered Transpiler**:\n", - "- **Routing Passes**: AI-powered routing can dynamically adjust qubit paths based on the specific circuit and backend, reducing the need for excessive SWAP gates.\n", + "### Key features of QTS\n", + "\n", + "- Routing passes: AI-powered routing can dynamically adjust qubit paths based on the specific circuit and backend, reducing the need for excessive SWAP gates.\n", " - `AIRouting`: Layout selection and circuit routing\n", "\n", - "- **Synthesis Passes**: AI techniques optimize the decomposition of multi-qubit gates, minimizing the number of 2-qubit gates, which are typically more error-prone.\n", + "- Synthesis passes: AI techniques optimize the decomposition of multi-qubit gates, minimizing the number of two-qubit gates, which are typically more error-prone.\n", " - `AICliffordSynthesis`: Clifford gate synthesis\n", " - `AILinearFunctionSynthesis`: Linear function circuit synthesis\n", " - `AIPermutationSynthesis`: Permutation circuit synthesis\n", " - `AIPauliNetworkSynthesis`: Pauli Network circuit synthesis (only available in the Qiskit Transpiler Service, not in local environment)\n", "\n", - "**Comparison with Traditional Transpilation**: The standard Qiskit transpiler is a robust tool that can handle a broad spectrum of quantum circuits effectively. However, when circuits grow larger in scale or hardware configurations become more complex, the **Qiskit AI-powered transpiler service (QTS)** can deliver additional optimization gains. By leveraging **learned models** for routing and synthesis, QTS further refines circuit layouts and reduces overhead for challenging or large-scale quantum tasks.\n", + "- Comparison with traditional transpilation: The standard Qiskit transpiler is a robust tool that can handle a broad spectrum of quantum circuits effectively. However, when circuits grow larger in scale or hardware configurations become more complex, QTS can deliver additional optimization gains. By using learned models for routing and synthesis, QTS further refines circuit layouts and reduces overhead for challenging or large-scale quantum tasks.\n", "\n", "\n", - "In this tutorial, we will evaluate the AI modes using **both routing and synthesis** passes, comparing the results to traditional transpilation to highlight where AI offers performance gains.\n", + "In this tutorial, we will evaluate the AI modes using both routing and synthesis passes, comparing the results to traditional transpilation to highlight where AI offers performance gains.\n", "\n", - "For more information on the details of QTS, please refer to the [documentation](https://docs.quantum.ibm.com/guides/ai-transpiler-passes).\n", + "For more details on QTS, please refer to the [documentation](/docs/guides/ai-transpiler-passes).\n", "\n", "\n", - "### Why Use AI for Quantum Circuit Transpilation?\n", + "### Why use AI for quantum circuit transpilation?\n", "\n", "As quantum circuits grow in size and complexity, traditional transpilation methods struggle to optimize layouts and reduce gate counts efficiently. Larger circuits, particularly those involving hundreds of qubits, impose significant challenges on routing and synthesis due to device constraints, limited connectivity, and qubit error rates.\n", "\n", - "This is where **AI-powered transpilation** offers a potential solution. By leveraging machine learning techniques, the AI-powered transpiler in Qiskit can make smarter decisions about **qubit routing** and **gate synthesis**, leading to better optimization of large-scale quantum circuits.\n", + "This is where AI-powered transpilation offers a potential solution. By leveraging machine learning techniques, the AI-powered transpiler in Qiskit can make smarter decisions about qubit routing and gate synthesis, leading to better optimization of large-scale quantum circuits.\n", "\n", - "### Brief Benchmarking Results\n", + "### Brief benchmarking results\n", "![Graph showing AI transpiler performance against Qiskit](/docs/images/tutorials/ai-transpiler-introduction/ai-transpiler-benchmarks.avif)\n", "\n", "\n", - "In benchmarking tests, the **Qiskit AI-powered transpiler service (QTS)** consistently produced **shallower, higher-quality circuits** compared to the standard Qiskit transpiler. For these tests, we used **Qiskit’s default pass manager strategy**—configured via the [`generate_preset_passmanager`](https://docs.quantum.ibm.com/api/qiskit/transpiler_preset). While this default strategy is often effective, it can struggle with larger or more complex circuits. By contrast, QTS’s AI-powered passes achieved an **average 24% reduction** in 2-qubit gate counts and a **36% reduction** in circuit depth for large circuits (100+ qubits) when transpiling to the **heavy hex topology** of IBM Quantum hardware. For more information on these benchmarks, please refer to the following blog post [\\[1\\]](#references).\n", + "In benchmarking tests, QTS consistently produced shallower, higher-quality circuits compared to the standard Qiskit transpiler. For these tests, we used Qiskit’s default pass manager strategy, configured with [`generate_preset_passmanager`](/docs/api/qiskit/transpiler_preset). While this default strategy is often effective, it can struggle with larger or more complex circuits. By contrast, QTS’s AI-powered passes achieved an average 24% reduction in two-qubit gate counts and a 36% reduction in circuit depth for large circuits (100+ qubits) when transpiling to the heavy-hex topology of IBM Quantum® hardware. For more information on these benchmarks, please refer to the [blog.](https://www.ibm.com/quantum/blog/qiskit-performance)\n", "\n", - "In this notebook, we will explore the **key benefits** of Qiskit AI-powered transpiler service and how it compares to traditional methods." + "In this notebook, we will explore the key benefits of QTS and how it compares to traditional methods." ] }, { "cell_type": "code", - "execution_count": null, - "id": "0d8375e2-081b-49a6-9147-b5bab1e90e13", + "execution_count": 3, + "id": "2aa75e36-471f-49aa-8478-134f13e3630b", "metadata": { "tags": [ "remove-cell" @@ -66,14 +67,14 @@ }, { "cell_type": "markdown", - "id": "67893eb6-4260-4aef-b9af-cde3ad2440ed", + "id": "4a781d15-0953-4af6-b581-ea6cb3a74228", "metadata": {}, "source": [ "## Requirements\n", "\n", "Before starting this tutorial, ensure that you have the following installed:\n", "\n", - "* Qiskit SDK 1.0 or later, with visualization support (`pip install 'qiskit[visualization]'`)\n", + "* Qiskit SDK v1.0 or later, with visualization support (`pip install 'qiskit[visualization]'`)\n", "* Qiskit Runtime (`pip install qiskit-ibm-runtime`) 0.22 or later\n", "* Qiskit IBM Transpiler (`pip install qiskit-ibm-transpiler`)\n", "* Qiskit IBM AI Local Transpiler (`pip install qiskit_ibm_ai_local_transpiler`)" @@ -81,7 +82,7 @@ }, { "cell_type": "markdown", - "id": "3686c322-632a-4c27-949b-c192ba63c7ea", + "id": "c7c26e24-329b-4283-9cc0-67a241807049", "metadata": {}, "source": [ "## Setup" @@ -89,8 +90,8 @@ }, { "cell_type": "code", - "execution_count": 1, - "id": "229ddedf-d9d9-415e-b421-6d8160ae1c3e", + "execution_count": 4, + "id": "2c462d48-ae45-4528-9b09-cebc869a6812", "metadata": {}, "outputs": [], "source": [ @@ -243,40 +244,40 @@ }, { "cell_type": "markdown", - "id": "b4ec9de1-5b6c-4f32-ad12-41dc674075e1", + "id": "ba7568f8-50c9-47b4-acc0-33ea34f5fca0", "metadata": {}, "source": [ - "# Part I. Qiskit Patterns\n", + "# Part I. Qiskit patterns\n", "\n", - "Let's now see how to use the **AI transpiler service** with a simple quantum circuit and using Qiskit patterns. The key is creating a **TranspilerService instance** and specifying the use of AI modes during transpilation." + "Let's now see how to use the AI transpiler service with a simple quantum circuit, using Qiskit patterns. The key is creating a `TranspilerService` instance and specifying the use of AI modes during transpilation." ] }, { "cell_type": "markdown", - "id": "72976be5-bc85-47bf-a3f4-c7a453350f9f", + "id": "5ba1bb22-272f-4f8f-ae78-7c3d1cdaacc6", "metadata": {}, "source": [ "## Step 1: Map classical inputs to a quantum problem\n", "\n", - "In this section, we will test the AI transpiler on the `EfficientSU2` circuit, a widely used hardware-efficient ansatz. This circuit is particularly relevant for variational quantum algorithms (e.g., VQE) and quantum machine learning tasks, making it an ideal test case for assessing transpilation performance.\n", + "In this section, we will test the AI transpiler on the `EfficientSU2` circuit, a widely used hardware-efficient ansatz. This circuit is particularly relevant for variational quantum algorithms (for example, VQE) and quantum machine-learning tasks, making it an ideal test case for assessing transpilation performance.\n", "\n", - "The `EfficientSU2` circuit consists of alternating layers of single-qubit rotations and entangling gates like CNOTs. These layers enable flexible exploration of the quantum state space while keeping the gate depth manageable, which is crucial for NISQ devices. By optimizing this circuit, we aim to reduce gate count, improve fidelity, and minimize noise. This makes it a strong candidate for testing the AI transpiler’s efficiency." + "The `EfficientSU2` circuit consists of alternating layers of single-qubit rotations and entangling gates like CNOTs. These layers enable flexible exploration of the quantum state space while keeping the gate depth manageable. By optimizing this circuit, we aim to reduce gate count, improve fidelity, and minimize noise. This makes it a strong candidate for testing the AI transpiler’s efficiency." ] }, { "cell_type": "code", - "execution_count": 2, - "id": "e6daecfb-1cd9-4489-99b6-91fddbbe90c1", + "execution_count": 5, + "id": "c6e9c2c0-e02c-4276-bae8-d5692e60b6b8", "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAArQAAAFvCAYAAAC7L1irAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAXwlJREFUeJzt3Ql4TNf/P/B3Jvsu+yIIElusjb0oLa2lVLWKovh+W1VUF6WLlmq/tVVrLdVF+9OqUrTWLtZK0RJrRAiRIBuySSLrJPN/zvUX0kRkYpKZc+f9ep55kpm5987R5p7PZ84993MsdDqdDkREREREktIYuwFERERERPeDCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUmNCS0RERERSY0JLRERERFJjQktEREREUnNytgNoPLpdDpoc/MhCyt7W1hYWBjseDodkFcEqdhZAgb8T0BmTrY+wND9APsAItIHE1oTJQLZ6oYjIIvhMd/D2sHOYMcTgazrdkglrC9gzzOKzLQPMHQ/wD6AiPTBKQdEREREJDUmtEREREQkNSa0RERERCQ1JrREREREJDVOXycykzvmk1NykZ6ZD22RDnY2lqjr5wg7W3YBREQkP0YzIpVKTsnBt5vOIexoMo6cTsWV1NxS71tZWaB5kBtCm3piUM9APNa5NiwtedGGiIjkw4SWSGWOnE7BvG9OYuOuOGi1urtuJ947fiZNeXz9czTq13bGS880wcRhzWBvx66BiIjkwailIr6dQtB748xSrxXeyEXmhSTErN+HqK+3Q1dUDLXKitiL6Hd7lHpNY+cIW/9G8Og+Et6PvwwLS/X+yefla/H+8mP4+NsIFBffPZG9m9iELExdcFhJbr/5sCs6tfKplnZS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NcRFJrQqcu3YOewY9r+S50NPfV1mG0t7G3Sc8zz2Pv8J1MYxuAOCZ/5e8vzEyPIXFgh85f8Q/81kpQOw8aoHl5aPwMKSpwIRycvO1gobPn0EX244i8nzDyE75/7KeT3YxgfffNBVipvAKhP7KiJ7XKxs7KuIGuKiXK2lu8q+eAWOtW+v3mLtZA8rBzvkJKeV2s65ni+canui94abN7rZuDgCGgvYuDrhr1eWQla2Pg1QkHJ74YuinEwU5d2AjUfZy3C2PoFo+NaGkudiEr1Lm0drrK1ERNU1/WDs003wWOfaeGthONbvjIVWq9PrGHV8HTFldAulooGlpUY1sa8iMsdFfWJfRdQQF5nQqoSYP1RcWAS/bi2RtO8kmox+DLGb9qO4QFtqu4wzl/Bj8/+WPBeXVmxcHXBo+reQmZg/ZGFpjczjO+DSuheubV+mTHC3sLIps21hxhVYuXgp84iuH/0duZdPo2E5k+SJiGRUz98Za+b1wKfXOuCrjWfx0x+xOH0hA0VF5Se3tZxtlBHZF55qjH5d68DKyvQTWX1jX0Vkjov6xL6KqCEuMqFVkX0TFqHLwgmwmfMCsuKSsW/iYrg1Ns7yiMZQ//XViFs8BpeWvwRbvyDUf/175F48VWa764e2IHnDHEBjCWt3fwRP3w6Nrb1R2kxEVF38vBzw3ottlEdOrhYnolNx/lImcvOLYGWpURLZ1k3cUb+2szK6q/bYF/RMd7R5cxhsajmibu/2CBk3ALtGzUHaqViYQ+xL2fUtEle/i6LsdGT88wuu/DIfQe9ugUODNqqIi0xoVUR8y9za+0299jn+yTqohX1gCzT9NPye23k++rzyICIyF2K52k6tfJSHuca+8+v2Kg+1xcVKx75HRisPtcZFea4rUJUUFWph6+Zc7sIK5REFpMXk+Ly0LKiBuOyizUwtVVy6IqKA9KXPx8PK+facLCIiUnfsU1tctNAz9qkhLlroRFFWMjmFOXlY3XAEZDE85ntYO9gZ7Hi5WqDrdkglrC9gz2seRERmGQcFc4+FYUaMgxyhJSIiIiKpMaElIiIiIqlxyoGJEv9btLn5kIVYmcWQd8mKv8q8IkjFzlLUgTR2K4iI1EG2OCiYeyy0M2IcZEJLRERERFLjlAMiIiIikhoTWiIiIiKSGhNaIiIiIpIaE1oiIiIikhoTWiIiIiKSGhNaIiIiIpIaE1oiIiIikhoTWiIiIiKSGhNaIiIiIpIaE1oiIiIikhoTWiIiIiKSGhNaIiIiIpIaE1oiIiIikhoTWiIiIiKSGhNaIiIiIpIaE1oiIiIikhoTWiIiIiKSGhNaIiIiIpIaE1oiIiIikhoTWiIiIiKSGhNaIiIiIpIaE1oiIiIikhoTWiIiIiKSGhNaIiIiIpIaE1oiIiIigsz+H3gQWh+AO5uQAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, - "execution_count": 2, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -292,16 +293,16 @@ }, { "cell_type": "markdown", - "id": "9b4f574a-eaa8-41e4-8f41-addb02e6cc86", + "id": "6c7c76f7-c376-47e9-bc9c-dbe32b2c89b7", "metadata": {}, "source": [ "## Step 2: Optimize problem for quantum hardware execution\n", "\n", - "**Choose a backend**\n", + "### Choose a backend\n", "\n", - "For this example, we will use the `ibm_brisbane` backend. This backend features a heavy hexagonal topology with 127 qubits, making it a suitable target for large-scale circuit demonstrations, especially when assessing performance on modern quantum hardware.\n", + "For this example, we will use the `ibm_brisbane` backend. This backend features a heavy-hexagonal topology with 127 qubits, making it a suitable target for large-scale circuit demonstrations, especially when assessing performance on modern quantum hardware.\n", "\n", - "**Create TranspilerService Instances**\n", + "### Create TranspilerService Instances\n", "\n", "To evaluate the effectiveness of the AI transpiler, we will perform two transpilation runs. First, we will transpile the circuit using the AI transpiler. Then, we will run a comparison by transpiling the same circuit without the AI transpiler, using traditional methods. Both transpilation processes will use the following configuration:\n", "\n", @@ -311,10 +312,11 @@ "\n", "By comparing the results from these two runs, we will be able to assess how much optimization is gained by using the AI transpiler in terms of circuit depth, gate count, and runtime efficiency.\n", "\n", - "Notes:\n", - "- For best results, user can use `ai=auto` as it will run both the standard Qiskit heuristic passes and the AI-powered passes and return the best result. For our example, we will run the AI-powered passes explicitly to show the difference in results.\n", + "\n", + "For the best results, you can use `ai=auto`, as it will run both the standard Qiskit heuristic passes and the AI-powered passes, and return the best result. For our example, we will run the AI-powered passes explicitly to show the difference in results.\n", + "\n", "\n", - "- Similar to `generate_preset_passmanager`, the `generate_ai_passmanager` function can be used for a hybrid AI-powered transpilation, example usage shown below.\n", + "Similar to `generate_preset_passmanager`, the `generate_ai_passmanager` function can be used for a hybrid AI-powered transpilation, as demonstrated in the following example.\n", "\n", "```python\n", " from qiskit.circuit.library import EfficientSU2\n", @@ -336,8 +338,8 @@ }, { "cell_type": "code", - "execution_count": 3, - "id": "d6989a85-96e0-4453-a28b-a504ca69750d", + "execution_count": 6, + "id": "a1aa25dd-41a9-4416-a959-44f28af613c8", "metadata": {}, "outputs": [], "source": [ @@ -356,7 +358,7 @@ }, { "cell_type": "markdown", - "id": "32cfb7eb-6209-4ec6-b8bc-d00b6559a237", + "id": "a06d6144-3445-4446-a3e1-18ca78a1173c", "metadata": {}, "source": [ "Transpile the circuits and record the times." @@ -364,24 +366,16 @@ }, { "cell_type": "code", - "execution_count": 4, - "id": "f60cfd26-bbcc-4519-98a9-8d4123f3150e", + "execution_count": 7, + "id": "fb5167bd-35f0-432f-af6d-023c70783d20", "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/henryzou/.venvs/ibm-learning-sabre/lib/python3.11/site-packages/qiskit/qpy/interface.py:305: UserWarning: The qiskit version used to generate the provided QPY file, 1.2.4, is newer than the current qiskit version 1.2.0. This may result in an error if the QPY file uses instructions not present in this current qiskit version\n", - " warnings.warn(\n" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ - "Standard transpilation: 43.817320108413696 seconds\n", - "AI transpilation : 21.043448209762573 seconds\n" + "Standard transpilation: 47.36643695831299 seconds\n", + "AI transpilation : 30.494643211364746 seconds\n" ] } ], @@ -401,16 +395,16 @@ }, { "cell_type": "code", - "execution_count": 5, - "id": "d96b9e88-bfe1-4426-b9c1-1b00cbd784d3", + "execution_count": 8, + "id": "db2e66df-917b-4eed-8993-41c845259aa1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Standard transpilation: Depth 482, Gate count 4467, Time 43.817320108413696\n", - "AI transpilation : Depth 131, Gate count 2358, Time 21.043448209762573\n" + "Standard transpilation: Depth 221, Gate count 2519, Time 47.36643695831299\n", + "AI transpilation : Depth 134, Gate count 1903, Time 30.494643211364746\n" ] } ], @@ -431,33 +425,33 @@ }, { "cell_type": "markdown", - "id": "e3b05b65-7583-4514-83bc-4d99ba4864db", + "id": "d934ebd2-e594-4076-8b21-822087df01ea", "metadata": {}, "source": [ "In this test, we compare the performance of the AI transpiler and the standard transpilation method on the EfficientSU2 circuit using the `ibm_brisbane` backend. The results show a significant improvement in the circuit's depth, gate count, and transpilation time when using the AI transpiler:\n", "\n", - "- **Circuit Depth**: This reduction in depth is substantial (over 50%), as it means the AI transpiler has found a more efficient arrangement of qubit interactions, which can directly impact the overall fidelity of the circuit on quantum hardware. A shallower circuit helps mitigate qubit decoherence and reduces the likelihood of noise affecting the outcome.\n", + "- Circuit depth: This reduction in depth is substantial (over 50%), as it means the AI transpiler has found a more efficient arrangement of qubit interactions, which can directly impact the overall fidelity of the circuit on quantum hardware. A shallower circuit helps mitigate qubit decoherence and reduces the likelihood of noise affecting the outcome.\n", "\n", - "- **Gate Count**: The AI transpiler also reduced the gate count by nearly 50%. Since each gate has an associated error rate, fewer gates directly lower the overall chance of error, which is critical for maintaining coherence and improving the reliability of results in practical quantum computing tasks.\n", + "- Gate count: The AI transpiler also reduced the gate count by nearly 50%. Since each gate has an associated error rate, fewer gates directly lower the overall chance of error, which is critical for maintaining coherence and improving the reliability of results in practical quantum computing tasks.\n", "\n", "\n", - "- **Transpilation Time Efficiency**: While the time varies for the device, the time it took to transpile the circuit was drastically reduced, over a 50% improvement. This shows that the AI-powered transpiler not only optimizes the resulting circuit but also improves the efficiency of the transpilation process itself, making it faster to generate optimized circuits.\n", + "- Transpilation time efficiency: While the time varies for the device, the time it took to transpile the circuit was drastically reduced, over a 50% improvement. This shows that the AI-powered transpiler not only optimizes the resulting circuit but also improves the efficiency of the transpilation process itself, making it faster to generate optimized circuits.\n", "\n", - "It is important to note that these results are based on just one circuit. To obtain a comprehensive understanding of how the AI transpiler compares to traditional methods, it is necessary to test a variety of circuits. The performance of QTS can vary greatly depending on the type of circuit being optimized. For a broader comparison, refer to the benchmarks above or visit the following IBM Blog Post[\\[1\\]](#references)" + "It is important to note that these results are based on just one circuit. To obtain a comprehensive understanding of how the AI transpiler compares to traditional methods, it is necessary to test a variety of circuits. The performance of QTS can vary greatly depending on the type of circuit being optimized. For a broader comparison, refer to the benchmarks above or visit the [blog.](https://www.ibm.com/quantum/blog/qiskit-performance)" ] }, { "cell_type": "markdown", - "id": "36556b22-258b-4c6f-b14a-33ef759f54ed", + "id": "c8a55587-abf6-4096-85fd-2702a077ae75", "metadata": {}, "source": [ "## Step 3: Execute using Qiskit primitives\n", - "As this tutorial focuses on transpilation, no experiments will be executed on the quantum device. The goal is to leverage the optimizations from Step 2 to obtain a transpiled circuit with reduced depth and/or gate count." + "As this tutorial focuses on transpilation, no experiments will be executed on the quantum device. The goal is to leverage the optimizations from Step 2 to obtain a transpiled circuit with reduced depth or gate count." ] }, { "cell_type": "markdown", - "id": "86398ce2-beb4-4944-8961-57cadf03096a", + "id": "8d0cfca9-be4e-40ab-ab98-d7899bb8b3fa", "metadata": {}, "source": [ "## Step 4: Post-process and return result in desired classical format\n", @@ -466,28 +460,20 @@ }, { "cell_type": "markdown", - "id": "c546005f-1a73-4906-8804-f925846fe380", + "id": "c82277b2-22e9-44fe-886e-e8ceb2178278", "metadata": {}, "source": [ - "# Part II. Analyzing and benchmarking the transpiled circuits\n", + "# Part II. Analyze and benchmark the transpiled circuits\n", "\n", "In this section, we will demonstrate how to analyze the transpiled circuit and benchmark it against the original version in more detail. We will focus on metrics such as circuit depth, gate count, and transpilation time to assess the effectiveness of the optimization. Additionally, we will discuss how the results may differ across various circuit types, offering insights into the broader performance of the transpiler across different scenarios." ] }, { "cell_type": "code", - "execution_count": 6, - "id": "11499cdb-b2f4-4ca3-8546-9c354f772088", + "execution_count": 9, + "id": "ee24725b-64c9-4d6a-aa97-5a3502b0982a", "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/henryzou/.venvs/ibm-learning-sabre/lib/python3.11/site-packages/qiskit/qpy/interface.py:305: UserWarning: The qiskit version used to generate the provided QPY file, 1.2.4, is newer than the current qiskit version 1.2.0. This may result in an error if the QPY file uses instructions not present in this current qiskit version\n", - " warnings.warn(\n" - ] - }, { "name": "stdout", "output_type": "stream", @@ -498,18 +484,18 @@ "Completed transpilation for BV\n", "Completed transpilation for QV\n", " Circuit Depth (No AI) Gate Count (No AI) Time (No AI) Depth (AI) \\\n", - "0 Random 345 7842 3.944334 298 \n", - "1 Clifford 84 2284 2.354044 67 \n", - "2 QFT 328 4847 3.657239 217 \n", - "3 BV 135 1116 2.536958 103 \n", - "4 QV 198 5075 2.670678 174 \n", + "0 Random 324 7756 8.575865 293 \n", + "1 Clifford 92 2179 4.253957 72 \n", + "2 QFT 351 4809 3.260779 241 \n", + "3 BV 108 821 1.898376 103 \n", + "4 QV 183 5047 4.165533 168 \n", "\n", " Gate Count (AI) Time (AI) \n", - "0 8738 34.042681 \n", - "1 2173 18.066975 \n", - "2 4602 25.296369 \n", - "3 791 21.240081 \n", - "4 5613 26.749141 \n" + "0 8305 32.752996 \n", + "1 2360 20.725153 \n", + "2 5009 24.736278 \n", + "3 723 21.294635 \n", + "4 5220 24.647348 \n" ] } ], @@ -558,7 +544,7 @@ }, { "cell_type": "markdown", - "id": "f4aae7f9-3a73-4798-992a-55f2bea3dcc2", + "id": "061d85cf-3841-4ed3-bd0d-cd950564efb7", "metadata": {}, "source": [ "Average percentage reduction for each metric. Positive are improvements, negative are degradations." @@ -567,7 +553,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "5d3aad52-a63d-458e-b048-afd546f40a1e", + "id": "70cf9c05-62a3-4049-9712-319902107ba6", "metadata": {}, "outputs": [ { @@ -606,7 +592,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "541960d9-4c2a-4149-bd44-6077553c699b", + "id": "79b8d5d9-0f9d-42ca-9583-8bec17430014", "metadata": {}, "outputs": [ { @@ -652,7 +638,7 @@ }, { "cell_type": "markdown", - "id": "ee11b216-4966-467f-9fa3-1eeada3703a1", + "id": "345022d3-e302-47e6-9453-9261136923a7", "metadata": {}, "source": [ "The AI transpiler's performance varies significantly based on the type of circuit being optimized. In some cases, it achieves notable reductions in circuit depth and gate count compared to the standard transpiler. However, these improvements often come with a substantial increase in runtime.\n", @@ -662,28 +648,28 @@ }, { "cell_type": "markdown", - "id": "ac7b9f26-97e6-443a-b7c6-e23f6126303f", + "id": "9e496e7a-64a8-46fd-b240-c494e7825bd2", "metadata": {}, "source": [ "## When should users choose AI-powered transpilation?\n", "\n", - "The AI-powered transpiler in Qiskit excels in scenarios where traditional transpilation methods struggle—particularly with large-scale and complex quantum circuits. For circuits involving hundreds of qubits or those targeting hardware with intricate coupling maps, the AI transpiler offers superior optimization in terms of circuit depth, gate count, and runtime efficiency. In benchmarking tests, it has consistently outperformed traditional methods, delivering significantly shallower circuits and reducing gate counts, which are critical for enhancing performance and mitigating noise on real quantum hardware.\n", + "The AI-powered transpiler in Qiskit excels in scenarios where traditional transpilation methods struggle, particularly with large-scale and complex quantum circuits. For circuits involving hundreds of qubits or those targeting hardware with intricate coupling maps, the AI transpiler offers superior optimization in terms of circuit depth, gate count, and runtime efficiency. In benchmarking tests, it has consistently outperformed traditional methods, delivering significantly shallower circuits and reducing gate counts, which are critical for enhancing performance and mitigating noise on real quantum hardware.\n", "\n", "Users should consider AI-powered transpilation when working with:\n", "- Large circuits where traditional methods fail to efficiently handle the scale.\n", "- Complex hardware topologies where device connectivity and routing challenges arise.\n", "- Performance-sensitive applications where reducing circuit depth and improving fidelity are paramount.\n", "\n", - "#### Getting the Best Results: Using `ai=\"auto\"`\n", - "For optimal results, users can set ai=\"auto\" in the Qiskit Transpiler Service. This automatically selects the best AI-based optimizations based on the circuit and target hardware, ensuring that the transpiler delivers the highest performance without manual configuration. This mode is ideal for users who want the convenience of automatic optimization while still benefiting from the powerful AI-driven enhancements to circuit routing and synthesis." + "## Get the best results using `ai=\"auto\"`\n", + "For optimal results, users can set `ai=\"auto\"` in QTS, which automatically selects the best AI-based optimizations based on the circuit and target hardware, ensuring that the transpiler delivers the highest performance without manual configuration. This mode is ideal for users who want the convenience of automatic optimization while still benefiting from the powerful AI-driven enhancements to circuit routing and synthesis." ] }, { "cell_type": "markdown", - "id": "b02c6498-4f7b-43df-9008-4602089d1fec", + "id": "c345cb54-a838-427f-898f-51fb607da493", "metadata": {}, "source": [ - "# Part III. Exploring AI-powered permutation network synthesis\n", + "# Part III. Explore AI-powered permutation network synthesis\n", "\n", "Permutation networks are foundational in quantum computing, particularly for systems constrained by restricted topologies. These networks facilitate long-range interactions by dynamically swapping qubits to mimic all-to-all connectivity on hardware with limited connectivity. Such transformations are essential for implementing complex quantum algorithms on near-term devices, where interactions often span beyond nearest neighbors.\n", "\n", @@ -691,25 +677,25 @@ "\n", "We will walk through a Qiskit patterns example showcasing the synthesis of a permutation network to achieve all-to-all connectivity for a set of qubits. We will compare the performance of `AIPermutationSynthesis` against the standard synthesis methods in Qiskit. This example will demonstrate how the AI transpiler optimizes for lower circuit depth and gate count, highlighting its advantages in practical quantum workflows.\n", "\n", - "For more details about the AI-powered permutation synthesis in QTS, please refer to the [Qiskit API documentation](https://docs.quantum.ibm.com/api/qiskit-ibm-transpiler/qiskit_ibm_transpiler.ai.AIPermutationSynthesis)." + "For more details about the AI-powered permutation synthesis in QTS, please refer to the [Qiskit API documentation](/docs/api/qiskit-ibm-transpiler/ai-ai-permutation-synthesis)." ] }, { "cell_type": "markdown", - "id": "22ef1d50-3221-44b3-bbc9-221f8f473d0b", + "id": "76de0959-1eca-43d9-b8fe-f9aea9a122d8", "metadata": {}, "source": [ "## Step 1: Map classical inputs to a quantum problem\n", "\n", "To represent a classical permutation problem on a quantum computer, we start by defining the structure of the quantum circuits. For this example:\n", "\n", - "1. **Quantum Circuit Initialization**:\n", + "1. Quantum circuit initialization:\n", " We allocate 27 qubits to match the backend we will use, which has 27 qubits.\n", "\n", - "2. **Applying Permutations**:\n", + "2. Apply permutations:\n", " We generate five random permutation patterns (`pattern_1` through `pattern_5`) using a fixed seed (42) for reproducibility. Each permutation pattern is applied to a separate quantum circuit (`qc_1` through `qc_5`).\n", "\n", - "3. **Circuit Decomposition**:\n", + "3. Circuit decomposition:\n", " Each permutation operation is decomposed into native gate sets compatible with the target quantum hardware. We analyze the depth and the number of two-qubit gates (nonlocal gates) for each decomposed circuit.\n", "\n", "The results provide insight into the complexity of representing classical permutation problems on a quantum device, demonstrating the resource requirements for different permutation patterns." @@ -718,7 +704,7 @@ { "cell_type": "code", "execution_count": 9, - "id": "4d0259c1-9de4-4371-a9d7-0ace6fd7391d", + "id": "76a3e847-0808-4413-bd0c-c760cd2df3f4", "metadata": {}, "outputs": [ { @@ -768,39 +754,39 @@ }, { "cell_type": "markdown", - "id": "3de10fba-9321-4d74-ab54-644bc3204a1c", + "id": "a8b79798-fa80-44d8-8a52-2d2a50e0c280", "metadata": {}, "source": [ "## Step 2: Optimize problem for quantum hardware execution\n", "In this step, we proceed with optimization using the AI synthesis passes.\n", "\n", - "For the AI synthesis passes, the `PassManager` requires only the coupling map of the backend. However, it is important to note that not all coupling maps are compatible; only those that the `AIPermutationSynthesis` pass has been trained on will work. Currently, the `AIPermutationSynthesis` pass supports blocks of sizes 65, 33, and 27 qubits. Thus we will select `ibm_cario` as the backend for this example, as it has 27 qubits.\n", + "For the AI synthesis passes, the `PassManager` requires only the coupling map of the backend. However, it is important to note that not all coupling maps are compatible; only those that the `AIPermutationSynthesis` pass has been trained on will work. Currently, the `AIPermutationSynthesis` pass supports blocks of sizes 65, 33, and 27 qubits. For this example we use a 27-qubit QPU.\n", "\n", "For comparison, we will evaluate the performance of AI synthesis against generic permutation synthesis methods in Qiskit, including:\n", "\n", - "- **`synth_permutation_depth_lnn_kms`:** This method synthesizes a permutation circuit for a linear nearest-neighbor (LNN) architecture using the Kutin, Moulton, and Smithline (KMS) algorithm. It guarantees a circuit with a depth of at most $ n $ and a size of at most $ n(n-1)/2 $, where both depth and size are measured in terms of SWAP gates.\n", + "- `synth_permutation_depth_lnn_kms`: This method synthesizes a permutation circuit for a linear nearest-neighbor (LNN) architecture using the Kutin, Moulton, and Smithline (KMS) algorithm. It guarantees a circuit with a depth of at most $ n $ and a size of at most $ n(n-1)/2 $, where both depth and size are measured in terms of SWAP gates.\n", "\n", - "- **`synth_permutation_acg`:** This method synthesizes a permutation circuit for a fully-connected architecture using the Alon, Chung, and Graham (ACG) algorithm. It produces a circuit with a depth of exactly 2 (in terms of the number of SWAP gates).\n", + "- `synth_permutation_acg`: This method synthesizes a permutation circuit for a fully-connected architecture using the Alon, Chung, and Graham (ACG) algorithm. It produces a circuit with a depth of exactly 2 (in terms of the number of SWAP gates).\n", "\n", - "- **`synth_permutation_basic`:** This is a straightforward implementation that synthesizes permutation circuits without imposing constraints on connectivity or optimization for specific architectures. It serves as a baseline for comparing performance with more advanced methods.\n", + "- `synth_permutation_basic`: This is a straightforward implementation that synthesizes permutation circuits without imposing constraints on connectivity or optimization for specific architectures. It serves as a baseline for comparing performance with more advanced methods.\n", "\n", "Each of these methods represents a distinct approach to synthesizing permutation networks, providing a comprehensive benchmark against the AI-powered methods.\n", "\n", - "For more details about synthesis methods in Qiskit, refer to the [Qiskit API documentation](https://docs.quantum.ibm.com/api/qiskit/synthesis)." + "For more details about synthesis methods in Qiskit, refer to the [Qiskit API documentation](/docs/api/qiskit/synthesis)." ] }, { "cell_type": "markdown", - "id": "240196a2-0382-4f67-9dc7-9184d69c134f", + "id": "b1733a10-c285-444e-af47-4a32329c5f7a", "metadata": {}, "source": [ - "Define the coupling map representing `ibm_cario`, a 27-qubit device." + "Define the coupling map representing the 27-qubit QPU." ] }, { "cell_type": "code", "execution_count": 10, - "id": "172ad2e3-5703-44d2-a2a1-567f64630c94", + "id": "84dff2c2-a496-4828-bb8e-08d373816a36", "metadata": {}, "outputs": [ { @@ -852,7 +838,7 @@ }, { "cell_type": "markdown", - "id": "aa6db33d-8407-4bd2-a6fc-a9a9aea8cfeb", + "id": "47bdb1f5-1fc6-46c4-8fc9-98d16a4d2529", "metadata": {}, "source": [ "Create the pass managers and transpile each of the permutation circuits using the AI synthesis passes and generic synthesis methods." @@ -861,7 +847,7 @@ { "cell_type": "code", "execution_count": 11, - "id": "f3112a62-1ce0-4586-8e89-423b34974838", + "id": "128cc285-094a-4b07-a37d-8424a4003b2c", "metadata": {}, "outputs": [], "source": [ @@ -876,7 +862,7 @@ }, { "cell_type": "markdown", - "id": "e67e64b1-54ac-4df6-932d-f8dec72290ff", + "id": "42f80e32-60fd-46a8-a6b5-4bcadb15810a", "metadata": {}, "source": [ "Record the metrics (depth, gate count, time) for each circuit after transpilation." @@ -885,7 +871,7 @@ { "cell_type": "code", "execution_count": 12, - "id": "fd90b81b-970d-4f5b-9d1a-f0760589ab6e", + "id": "72ee8474-eea6-421a-9d7d-070587eaff71", "metadata": {}, "outputs": [ { @@ -959,21 +945,21 @@ }, { "cell_type": "markdown", - "id": "1464ba6b-ce1b-412e-b179-6ad690356053", + "id": "e1ba3767-5ce1-4663-803b-73ccfc22f03b", "metadata": {}, "source": [ "The results demonstrate that the AI transpiler outperforms all other Qiskit synthesis methods for this set of random permutation circuits. Key findings include:\n", "\n", - "1. **Depth**: The AI transpiler achieves the lowest average depth, indicating superior optimization of circuit layouts.\n", - "2. **Gate Count**: It significantly reduces the number of two-qubit gates compared to other methods, improving execution fidelity and efficiency.\n", - "3. **Transpilation Time**: All methods, including the AI transpiler, run very quickly at this scale, making them practical for use. However, the AI transpiler provides additional optimization benefits without added runtime cost.\n", + "1. Depth: The AI transpiler achieves the lowest average depth, indicating superior optimization of circuit layouts.\n", + "2. Gate count: It significantly reduces the number of two-qubit gates compared to other methods, improving execution fidelity and efficiency.\n", + "3. Transpilation time: All methods, including the AI transpiler, run very quickly at this scale, making them practical for use. However, the AI transpiler provides additional optimization benefits without added runtime cost.\n", "\n", "These results establish the AI transpiler as the most effective approach for this benchmark, particularly for depth and gate count optimization." ] }, { "cell_type": "markdown", - "id": "059bf36f-33cb-4438-a73f-07f9a724cd52", + "id": "dbaab943-5fd7-4720-98bf-8602b2ab4473", "metadata": {}, "source": [ "Plot the results to compare the performance of the AI synthesis passes against the generic synthesis methods." @@ -982,7 +968,7 @@ { "cell_type": "code", "execution_count": 13, - "id": "37e6bd25-abb9-474a-9366-0af31c44c0dc", + "id": "a326f268-0115-442c-8563-968676b66670", "metadata": {}, "outputs": [ { @@ -1041,37 +1027,37 @@ }, { "cell_type": "markdown", - "id": "c6f34546-0b99-4a8f-8294-e6cdc327e2f5", + "id": "03a9af42-42a7-4344-b834-0d2b506d4d78", "metadata": {}, "source": [ "This graph highlights the individual results for each circuit (`qc_1` to `qc_5`) across different synthesis methods:\n", "\n", - "1. **Circuit Depth**:\n", - " The AI transpiler often achieves **comparable or better depth optimizations** than other methods, highlighting its ability to optimize depth efficiently for these permutation circuits.\n", + "1. Circuit depth:\n", + " The AI transpiler often achieves comparable or better depth optimizations than other methods, highlighting its ability to optimize depth efficiently for these permutation circuits.\n", "\n", - "2. **2Q Gate Count**:\n", + "2. Two-qubit gate count:\n", " The AI transpiler also shows a substantial reduction in the number of two-qubit gates compared to other methods, indicating more efficient resource usage and improved circuit quality.\n", "\n", - "3. **Transpilation Time**:\n", + "3. Transpilation time:\n", " All methods, including the AI transpiler, run quickly at this scale. However, the AI method achieves its optimizations without introducing additional runtime overhead, making it highly practical.\n", "\n", - "While these results underscore the AI transpiler’s effectiveness for permutation circuits, it is important to note its **limitations**. The AI synthesis method is currently only available for certain coupling maps, which may restrict its broader applicability. This constraint should be considered when evaluating its usage in different scenarios.\n", + "While these results underscore the AI transpiler’s effectiveness for permutation circuits, it is important to note its limitations. The AI synthesis method is currently only available for certain coupling maps, which may restrict its broader applicability. This constraint should be considered when evaluating its usage in different scenarios.\n", "\n", - "Overall, the AI transpiler **demonstrates promising improvements** in depth and gate count optimization for these specific circuits while maintaining comparable transpilation times." + "Overall, the AI transpiler demonstrates promising improvements in depth and gate count optimization for these specific circuits while maintaining comparable transpilation times." ] }, { "cell_type": "markdown", - "id": "099bab43-5ede-4a9d-869a-158c049089f1", + "id": "41b1405d-fa90-48b6-9ce2-933f05358778", "metadata": {}, "source": [ "## Step 3: Execute using Qiskit primitives\n", - "As this tutorial focuses on transpilation, no experiments will be executed on the quantum device. The goal is to leverage the optimizations from Step 2 to obtain a transpiled circuit with reduced depth and/or gate count." + "As this tutorial focuses on transpilation, no experiments will be executed on the quantum device. The goal is to leverage the optimizations from Step 2 to obtain a transpiled circuit with reduced depth or gate count." ] }, { "cell_type": "markdown", - "id": "96381451-cffe-4517-8a45-8fd9720407c5", + "id": "3d942ee4-e4d7-4e87-8c8a-17c662d5379f", "metadata": {}, "source": [ "## Step 4: Post-process and return result in desired classical format\n", @@ -1080,42 +1066,32 @@ }, { "cell_type": "markdown", - "id": "385a261f-9db9-46cf-9d50-d079de23e790", + "id": "3c165627-415b-44fd-87e6-b7117d4abc74", "metadata": {}, "source": [ "## Limitations of QTS\n", "\n", - "While the **Qiskit AI-powered Transpiler Service (QTS)** can offer significant performance benefits for large and complex quantum circuits, there are several service-level constraints and AI pass–specific considerations to be aware of.\n", + "While QTS can offer significant performance benefits for large and complex quantum circuits, there are several service-level constraints and AI pass–specific considerations to be aware of.\n", "\n", - "- **Maximum 2Q Gates per Circuit**\n", - " Each circuit can include up to **1 million two-qubit gates** in any AI mode.\n", - "- **Transpilation Run Time**\n", - " Each transpilation process can run for up to **30 minutes**. If it exceeds this limit, the job will be canceled.\n", - "- **Retrieving Results**\n", - " You must retrieve the transpilation result within **20 minutes** after the process finishes. After that, the result is discarded.\n", - "- **Job Queue Time**\n", - " A set of circuits can remain in the internal queue for up to **120 minutes** while waiting to be transpiled. If the process doesn’t start within this window, the job is canceled.\n", - "- **Qubit Limit**\n", - " Currently, there is no strictly defined maximum number of qubits. However, the service has been tested successfully with circuits of **900+ qubits**.\n", + "- Maximum two-qubit gates per circuit\n", + " Each circuit can include up to one million two-qubit gates in any AI mode.\n", + "- Transpilation run time\n", + " Each transpilation process can run for up to 30 minutes. If it exceeds this limit, the job will be canceled.\n", + "- Retrieve results\n", + " You must retrieve the transpilation result within 20 minutes after the process finishes. After that, the result is discarded.\n", + "- Job queue time\n", + " A set of circuits can remain in the internal queue for up to 120 minutes while waiting to be transpiled. If the process doesn’t start within this window, the job is canceled.\n", + "- Qubit limit\n", + " Currently, there is no strictly defined maximum number of qubits. However, the service has been tested successfully with circuits of 900+ qubits.\n", "\n", "While QTS often delivers significant improvements in gate count and circuit depth, overall transpilation performance can vary based on circuit size, connectivity, and runtime constraints. Larger or more complex circuits may still incur additional transpilation time or require specialized configurations.\n", "\n", - "For the latest and most detailed information about QTS constraints, please refer to the [QTS Limitations documentation](https://docs.quantum.ibm.com/guides/qiskit-transpiler-service#limits-of-the-qiskit-transpiler-service)." - ] - }, - { - "cell_type": "markdown", - "id": "7e9a5978-c8c7-479d-9d49-9a6d5f99a6e0", - "metadata": {}, - "source": [ - "## References\n", - "\n", - "[1] IBM Quantum. \"Qiskit Performance and Scaling: A Closer Look.\" IBM Quantum Blog, https://www.ibm.com/quantum/blog/qiskit-performance." + "For the latest and most detailed information about QTS constraints, please refer to the [QTS Limitations documentation](/docs/guides/qiskit-transpiler-service#limits-of-the-qiskit-transpiler-service)." ] }, { "cell_type": "markdown", - "id": "337b200e-fb7c-4dad-9e8a-4c96099287ba", + "id": "3b21bb06-7a2b-4181-af59-734c89435d45", "metadata": {}, "source": [ "## Tutorial survey\n", @@ -1127,7 +1103,7 @@ }, { "cell_type": "markdown", - "id": "58960bec-b596-468c-85bb-5b05135aa89f", + "id": "a76ce81d-7d92-42be-a2fc-bf4ef98c1ac2", "metadata": {}, "source": [ "© IBM Corp. 2025" diff --git a/docs/tutorials/improved-trotterized-time-evolution-with-approximate-quantum-compilation.ipynb b/docs/tutorials/approximate-quantum-compilation-for-time-evolution.ipynb similarity index 99% rename from docs/tutorials/improved-trotterized-time-evolution-with-approximate-quantum-compilation.ipynb rename to docs/tutorials/approximate-quantum-compilation-for-time-evolution.ipynb index d251aa85857..ffe4e22e5d7 100644 --- a/docs/tutorials/improved-trotterized-time-evolution-with-approximate-quantum-compilation.ipynb +++ b/docs/tutorials/approximate-quantum-compilation-for-time-evolution.ipynb @@ -2,45 +2,45 @@ "cells": [ { "cell_type": "markdown", - "id": "f7bef3b0-a8f1-4ef2-9c0a-744fe7154cfe", + "id": "2c991cef-110a-455a-8741-52d5e20d3196", "metadata": {}, "source": [ - "# Improved Trotterized Time Evolution with Approximate Quantum Compilation (AQC-Tensor)\n", + "# Approximate quantum compilation for time evolution circuits\n", "*Usage estimate: 5 minutes on IBM Brisbane (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, { "cell_type": "markdown", - "id": "d29ee564-cfdb-408d-b7c2-647491e9d2bf", + "id": "93895788-7d38-4cc7-a7e9-ba97c34966af", "metadata": {}, "source": [ "## Background\n", "\n", - "This tutorial demonstrates how to implement **Approximate Quantum Compilation** using tensor networks (AQC-Tensor) with Qiskit to enhance quantum circuit performance. We apply AQC-Tensor within the context of a Trotterized time evolution to reduce circuit depth while maintaining simulation accuracy, following Qiskit’s framework for state preparation and optimization. In this notebook, you'll learn how to create a low-depth ansatz circuit from an initial Trotter circuit, optimize it with tensor networks, and prepare it for quantum hardware execution.\n", + "This tutorial demonstrates how to implement **Approximate Quantum Compilation** using tensor networks (AQC-Tensor) with Qiskit to enhance quantum circuit performance. We apply AQC-Tensor within the context of a Trotterized time evolution to reduce circuit depth while maintaining simulation accuracy, following the Qiskit framework for state preparation and optimization. In this notebook, you'll learn how to create a low-depth ansatz circuit from an initial Trotter circuit, optimize it with tensor networks, and prepare it for quantum hardware execution.\n", "\n", - "The primary objective is to simulate time evolution for a model Hamiltonian with a reduced circuit depth. This is achieved using the **AQC-Tensor** Qiskit addon, [qiskit-addon-aqc-tensor](https://github.com/Qiskit/qiskit-addon-aqc-tensor), which leverages tensor networks, specifically matrix product states (MPS), to compress and optimize the initial circuit. Through iterative adjustments, the compressed ansatz circuit maintains fidelity to the original circuit while staying feasible for near-term quantum hardware. More details can be found in the corresponding [docs](https://docs.quantum.ibm.com/guides/qiskit-addons-aqc) with a [simple example](https://docs.quantum.ibm.com/guides/qiskit-addons-aqc-get-started) to get started.\n", + "The primary objective is to simulate time evolution for a model Hamiltonian with a reduced circuit depth. This is achieved using the **AQC-Tensor** Qiskit addon, [qiskit-addon-aqc-tensor](https://github.com/Qiskit/qiskit-addon-aqc-tensor), which leverages tensor networks, specifically matrix product states (MPS), to compress and optimize the initial circuit. Through iterative adjustments, the compressed ansatz circuit maintains fidelity to the original circuit while staying feasible for near-term quantum hardware. More details can be found in the corresponding [docs](/docs/guides/qiskit-addons-aqc) with a [simple example](/docs/guides/qiskit-addons-aqc-get-started) to get started.\n", "\n", "Approximate Quantum Compilation is particularly advantageous in quantum simulations that exceed hardware coherence times, as it allows complex simulations to be performed more efficiently. This tutorial will guide you through the AQC-Tensor workflow setup in Qiskit, covering initialization of a Hamiltonian, generation of Trotter circuits, and transpilation of the final optimized circuit for a target device." ] }, { "cell_type": "markdown", - "id": "93730c6d-567e-4039-82f8-02f087b521e9", + "id": "b1b8f238-0dab-42c5-b658-779f3ff178a0", "metadata": {}, "source": [ "## Requirements\n", "\n", "Before starting this tutorial, ensure that you have the following installed:\n", "\n", - "* Qiskit SDK 1.0 or later, with visualization support (`pip install 'qiskit[visualization]'`)\n", - "* Qiskit Runtime 0.22 or later (`pip install qiskit-ibm-runtime`)\n", + "* Qiskit SDK v1.0 or later, with visualization support (`pip install 'qiskit[visualization]'`)\n", + "* Qiskit Runtime v0.22 or later (`pip install qiskit-ibm-runtime`)\n", "* AQC-Tensor Qiskit addon (`pip install 'qiskit-addon-aqc-tensor[aer,quimb-jax]'`)\n", - "* rustworkx 0.15 or later (`pip install rustworkx`)" + "* rustworkx v0.15 or later (`pip install rustworkx`)" ] }, { "cell_type": "markdown", - "id": "e6b08e9e-edf6-4332-9629-1d6d82cf300a", + "id": "f0723f2d-e0ba-4fe9-a742-1891b7b45459", "metadata": {}, "source": [ "## Setup" @@ -49,7 +49,7 @@ { "cell_type": "code", "execution_count": 28, - "id": "07d7ecc7-2b37-4a94-a7c9-78ec919e2240", + "id": "ccdcdca2-4e77-4696-b0ff-45d13dbc6ac3", "metadata": {}, "outputs": [], "source": [ @@ -85,10 +85,10 @@ }, { "cell_type": "markdown", - "id": "09bbe795-9439-4f41-851c-eed55f9897df", + "id": "39bc4470-f7f8-4550-83a7-a22167024000", "metadata": {}, "source": [ - "## Part I. Small scale example\n", + "## Part I. Small-scale example\n", "\n", "The first part of this tutorial uses a small-scale example with 10 sites to illustrate the process of mapping a quantum simulation problem to an executable quantum circuit. Here, we’ll explore the dynamics of a 10-site XXZ model, allowing us to build and optimize a manageable quantum circuit before scaling to larger systems.\n", "\n", @@ -101,25 +101,25 @@ "\\hat{\\mathcal{H}}_{XXZ} = \\sum_{i=1}^{L-1} J_{i,(i+1)}\\left(X_i X_{(i+1)}+Y_i Y_{(i+1)}+ 2\\cdot Z_i Z_{(i+1)} \\right) \\, ,\n", "$$\n", "\n", - "where $J_{i,(i+1)}$ is a random coefficient corresponding to edge $(i, i+1)$ and $L=10$ is the number of sites.\n", + "where $J_{i,(i+1)}$ is a random coefficient corresponding to edge $(i, i+1)$, and $L=10$ is the number of sites.\n", "\n", "By simulating the evolution of this system with reduced circuit depth, we can gain insights into using AQC-Tensor to compress and optimize circuits." ] }, { "cell_type": "markdown", - "id": "4f5d0d9e-9afd-4d67-8864-fa2684e749dc", + "id": "89f22428-d4d8-49e7-a1c5-39197dc58330", "metadata": {}, "source": [ - "#### Set up the Hamiltonian and Observable\n", + "#### Set up the Hamiltonian and observable\n", "\n", - "Before, we map our problem, we will need to set up the coupling map, Hamiltonian, and observable for the 10-site XXZ model." + "Before we map our problem, we need to set up the coupling map, Hamiltonian, and observable for the 10-site XXZ model." ] }, { "cell_type": "code", "execution_count": 2, - "id": "e9e70402-fa3a-40e2-8601-ca30e13374e9", + "id": "1ea0e102-23d5-4e6e-8ef8-e82843452b19", "metadata": {}, "outputs": [ { @@ -187,7 +187,7 @@ }, { "cell_type": "markdown", - "id": "ed31b52d-1608-466d-9d96-3ac232401aeb", + "id": "e6cd54e3-6a9c-4cdc-8493-d612e930dcee", "metadata": {}, "source": [ "With the Hamiltonian defined, we can proceed to construct the initial state." @@ -196,7 +196,7 @@ { "cell_type": "code", "execution_count": 3, - "id": "623f8932-6989-4c01-8331-449cd5a216f2", + "id": "71252a74-e7bf-4003-a1fd-8f7659195f9a", "metadata": {}, "outputs": [], "source": [ @@ -209,7 +209,7 @@ }, { "cell_type": "markdown", - "id": "9cad44ff-e90b-40dc-8383-d27d527a20a1", + "id": "5fb34a14-d197-4ac4-a224-5be2cec06a2e", "metadata": {}, "source": [ "### Step 1: Map classical inputs to a quantum problem\n", @@ -225,10 +225,10 @@ }, { "cell_type": "markdown", - "id": "abb82376-06d0-48c0-af36-4e56fec0e1e9", + "id": "7c5f2a2e-179c-4e62-a32f-5bc202f89701", "metadata": {}, "source": [ - "#### Determine the Portion of Time Evolution to Simulate Classically\n", + "#### Determine the portion of time evolution to simulate classically\n", "\n", "Our goal is to simulate the time evolution of the model Hamiltonian defined earlier using Trotter evolution. To make this process efficient for quantum hardware, we split the evolution into two segments:\n", "\n", @@ -237,8 +237,8 @@ "- **Subsequent Segment**: This remaining portion of the evolution, from $ t = 0.2 $ to $ t = 0.4 $, will be executed on quantum hardware, referred to as the `subsequent_circuit`. Given hardware limitations, we aim to use as few Trotter layers as possible to maintain a manageable circuit depth. For this segment, we use `subsequent_num_trotter_steps = 3`.\n", "\n", "\n", - "#### Choosing the split time\n", - "We choose $ t = 0.2 $ as the split time to balance classical simulability with hardware feasibility. Early in the evolution, entanglement in the XXZ model remains low enough for classical methods like MPS to approximate accurately.\n", + "#### Choose the split time\n", + "We choose $t = 0.2$ as the split time to balance classical simulability with hardware feasibility. Early in the evolution, entanglement in the XXZ model remains low enough for classical methods like MPS to approximate accurately.\n", "\n", "When choosing a split time, a good guideline is to select a point where entanglement is still manageable classically but captures enough of the evolution to simplify the hardware-executed portion. Trial and error may be needed to find the best balance for different Hamiltonians." ] @@ -246,7 +246,7 @@ { "cell_type": "code", "execution_count": 4, - "id": "5a4fd748-336e-43d8-93bc-e04af68d55a5", + "id": "199d4e7e-02b2-4da8-b567-8195fb9de536", "metadata": {}, "outputs": [], "source": [ @@ -268,7 +268,7 @@ { "cell_type": "code", "execution_count": 5, - "id": "6a1956b3-335f-4570-bad6-0ed9767b2859", + "id": "83039f82-97cb-4613-86c9-a8faf0839a02", "metadata": {}, "outputs": [ { @@ -298,20 +298,20 @@ }, { "cell_type": "markdown", - "id": "7f649ca7-cf2b-4f4f-8702-9b79694bdfd8", + "id": "064a17af-4af8-4ff5-899c-750147d269df", "metadata": {}, "source": [ "To enable a meaningful comparison, we will generate two additional circuits:\n", "\n", - "- **AQC Comparison Circuit**: This circuit evolves up to `aqc_evolution_time` but uses the same Trotter step duration as the `subsequent_circuit`. It serves as a comparison to the `aqc_target_circuit`, showing the evolution we would observe without using an increased number of Trotter steps. We will refer to this circuit as the `aqc_comparison_circuit`.\n", + "- **AQC comparison circuit**: This circuit evolves up to `aqc_evolution_time` but uses the same Trotter step duration as the `subsequent_circuit`. It serves as a comparison to the `aqc_target_circuit`, showing the evolution we would observe without using an increased number of Trotter steps. We will refer to this circuit as the `aqc_comparison_circuit`.\n", "\n", - "- **Reference Circuit**: This circuit is used as a baseline to obtain the exact result. It simulates the full evolution using tensor networks to calculate the exact outcome, providing a reference for evaluating the effectiveness of AQC-Tensor. We will refer to this circuit as the `reference_circuit`." + "- **Reference circuit**: This circuit is used as a baseline to obtain the exact result. It simulates the full evolution using tensor networks to calculate the exact outcome, providing a reference for evaluating the effectiveness of AQC-Tensor. We will refer to this circuit as the `reference_circuit`." ] }, { "cell_type": "code", "execution_count": 6, - "id": "6d1a0f3e-ea4b-4862-8193-9b1d3adb4e4c", + "id": "33b2ad93-7ae4-4250-bf38-9adc3bc2970d", "metadata": {}, "outputs": [ { @@ -344,7 +344,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "e40fcb2f-24eb-48d0-b8f6-6b663eb83284", + "id": "1bfa67a2-ac51-4158-b539-2c33f4c5ecf3", "metadata": {}, "outputs": [], "source": [ @@ -365,7 +365,7 @@ }, { "cell_type": "markdown", - "id": "3c938497-6de8-4653-bc43-e8fce9c63684", + "id": "2051f622-5b71-4be5-aab9-e9eb5d315a6f", "metadata": {}, "source": [ "#### Generate an ansatz and initial parameters from a Trotter circuit with fewer steps\n", @@ -383,7 +383,7 @@ { "cell_type": "code", "execution_count": 8, - "id": "3b64a36a-aa21-4673-bcbb-f175cea72660", + "id": "b9e81c51-dc6f-4237-9aca-e1384f1897bc", "metadata": {}, "outputs": [ { @@ -420,7 +420,7 @@ { "cell_type": "code", "execution_count": 9, - "id": "e45e0ccb-b3db-4307-ae31-af3eedc36d85", + "id": "bd9e9bf2-9ee5-445d-aa4a-c7f412c488f8", "metadata": {}, "outputs": [ { @@ -443,18 +443,18 @@ }, { "cell_type": "markdown", - "id": "9bb1dc12-2324-4829-8e24-d311fea399df", + "id": "3c8663b9-d513-4a2a-9911-03f3500ad486", "metadata": {}, "source": [ - "#### Choose Settings for Tensor Network Simulation\n", + "#### Choose settings for tensor network simulation\n", "\n", - "Here, we use Quimb's matrix-product state circuit simulator, along with jax for providing the gradient." + "Here, we use Quimb's matrix-product state circuit simulator, along with jax to provide the gradient." ] }, { "cell_type": "code", "execution_count": 10, - "id": "6dbeb6f2-6271-4cd2-96f0-2f5fca5f8429", + "id": "e5b9471f-fc7a-45c9-ab11-295cfff620bf", "metadata": {}, "outputs": [], "source": [ @@ -465,7 +465,7 @@ }, { "cell_type": "markdown", - "id": "1949039f-1a8a-4c8d-9a2b-fe2f90ba13d8", + "id": "5030d11d-54e3-4f29-acb2-6f7dd3ff05cb", "metadata": {}, "source": [ "Next, we build a MPS representation of the target state that will be approximated using AQC-Tensor. This representation enables efficient handling of entanglement, providing a compact description of the quantum state for further optimization." @@ -474,7 +474,7 @@ { "cell_type": "code", "execution_count": 11, - "id": "792b5ceb-9670-41f0-9ad0-e3b7528470b9", + "id": "1f050059-a281-41f1-a277-d7450e8b3ee3", "metadata": {}, "outputs": [ { @@ -504,7 +504,7 @@ }, { "cell_type": "markdown", - "id": "95f11d03-ae68-4261-9b50-62e0ee48aa52", + "id": "5ffbdd20-c9bf-4265-8a8d-8135abb2b8f7", "metadata": {}, "source": [ "Note that, by choosing a larger number of Trotter steps for the target state, we have effectively reduced its Trotter error compared to the initial circuit. We can evaluate the fidelity ($ |\\langle \\psi_1 | \\psi_2 \\rangle|^2 $) between the state prepared by the initial circuit and the target state to quantify this difference." @@ -513,7 +513,7 @@ { "cell_type": "code", "execution_count": 12, - "id": "e3854a2e-53d1-456d-aff5-6ed98171da75", + "id": "51d7d623-3e7c-44e7-80f1-94fd555a2c9e", "metadata": {}, "outputs": [ { @@ -532,17 +532,17 @@ }, { "cell_type": "markdown", - "id": "2c9d1797-092f-47c1-b97e-b35539d20c30", + "id": "01234b5b-f4db-4e22-993a-c8673621ab7f", "metadata": {}, "source": [ - "#### Optimize the parameters of the Ansatz using MPS calculations\n", - "In this step, we optimize the ansatz parameters by minimizing a simple cost function, `MaximizeStateFidelity`, using the L-BFGS optimizer from SciPy. We select a stopping criterion for the fidelity that ensures it surpasses the fidelity of the initial circuit without AQC-Tensor. Once this threshold is reached, the compressed circuit will exhibit both lower Trotter error and reduced depth compared to the original circuit. With additional CPU time, further optimization can continue to increase fidelity." + "#### Optimize the parameters of the ansatz using MPS calculations\n", + "In this step, we optimize the ansatz parameters by minimizing a simple cost function, `MaximizeStateFidelity`, using the L-BFGS optimizer from SciPy. We select a stopping criterion for the fidelity that ensures it surpasses the fidelity of the initial circuit without AQC-Tensor. Once this threshold is reached, the compressed circuit will exhibit both lower Trotter error and reduced depth compared to the original circuit. By using additional CPU time, further optimization can continue to increase fidelity." ] }, { "cell_type": "code", "execution_count": 29, - "id": "444519db-5bb1-415a-bf7e-c71357dc0b12", + "id": "ad2265cb-19a6-4402-8b0d-24239c930c90", "metadata": {}, "outputs": [ { @@ -651,7 +651,7 @@ { "cell_type": "code", "execution_count": 14, - "id": "c13cf527-93d8-4c91-9d82-f1a4a43e8267", + "id": "c95ccea0-be99-4db9-838d-2327851e6761", "metadata": {}, "outputs": [ { @@ -669,7 +669,7 @@ }, { "cell_type": "markdown", - "id": "66124b2b-a13c-4e38-8e57-ba64a4374e3e", + "id": "ca32c1ef-f7d5-4489-83b3-17972bf94700", "metadata": {}, "source": [ "At this point, it is only necessary to find the final parameters to the ansatz circuit. We can then merge the optimized AQC circuit with the remaining evolution circuit to create a complete time-evolution circuit for execution on quantum hardware." @@ -678,7 +678,7 @@ { "cell_type": "code", "execution_count": 15, - "id": "eb14c290-9069-46a4-8522-7458fdb43eba", + "id": "813c9ced-6a2e-4345-bffc-7dae938e2015", "metadata": {}, "outputs": [ { @@ -701,16 +701,16 @@ }, { "cell_type": "markdown", - "id": "05abd1c6-4eb5-4715-826f-99cb02f48afd", + "id": "46a93127-5443-40b7-a81a-dfd70df42ba2", "metadata": {}, "source": [ - "For our `aqc_comparison_circuit`, we will also need to merge it with the remaining evolution circuit. This circuit will be used to compare the performance of the AQC-Tensor-optimized circuit with the original circuit." + "We also need to merge our `aqc_comparison_circuit` with the remaining evolution circuit. This circuit will be used to compare the performance of the AQC-Tensor-optimized circuit with the original circuit." ] }, { "cell_type": "code", "execution_count": 16, - "id": "1f7ed210-992b-488e-aae7-79eb83f25aac", + "id": "86ba26ff-0bfa-47d0-b5ee-8944a8ddf274", "metadata": {}, "outputs": [ { @@ -732,7 +732,7 @@ }, { "cell_type": "markdown", - "id": "29086476-90ef-4355-9d0e-4a678740c81b", + "id": "982c5067-9a74-42a0-bd31-aaff72cf79df", "metadata": {}, "source": [ "### Step 2: Optimize problem for quantum hardware execution" @@ -740,45 +740,36 @@ }, { "cell_type": "markdown", - "id": "76e96f8c-662f-4c24-af92-9bc6ca370d66", + "id": "2121c40c-a9a7-4c36-a20a-04ee9f6637db", "metadata": {}, "source": [ - "Select the hardware, here we will use any of the IBM Quantum devices available that has at least 127 qubits." + "Select the hardware. Here we will use any of the IBM Quantum® devices available that have at least 127 qubits." ] }, { "cell_type": "code", - "execution_count": 17, - "id": "66dd568a-a86e-47fe-b467-a01b963d02c3", + "execution_count": null, + "id": "88715b59-4516-4b75-b041-c978944dd14a", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], + "outputs": [], "source": [ - "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"\", overwrite=True, set_as_default=True)\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(min_num_qubits=127)\n", "print(backend)" ] }, { "cell_type": "markdown", - "id": "9b1f3f3b-ac86-46bb-9aeb-4e6fda0cf6f8", + "id": "3f477394-5eac-4c12-b36b-e94c800fa889", "metadata": {}, "source": [ - "We transpile PUBs (circuit and observables) to match the backend ISA (Instruction Set Architecture). By setting `optimization_level=3`, the transpiler optimizes the circuit to fit a 1D chain of qubits, reducing the noise that impacts circuit fidelity. Once the circuits are transformed into a format compatible with the backend, we apply a corresponding transformation to the observables to ensure they align with the modified qubit layout." + "We transpile PUBs (circuit and observables) to match the backend ISA (Instruction Set Architecture). By setting `optimization_level=3`, the transpiler optimizes the circuit to fit a one-dimensional chain of qubits, reducing the noise that impacts circuit fidelity. Once the circuits are transformed into a format compatible with the backend, we apply a corresponding transformation to the observables to ensure they align with the modified qubit layout." ] }, { "cell_type": "code", "execution_count": 18, - "id": "b744cf08-a74f-4f76-b848-3c8e817f8cf5", + "id": "087fff8d-98b9-4f9a-8004-01a3b0166e12", "metadata": {}, "outputs": [ { @@ -815,16 +806,16 @@ }, { "cell_type": "markdown", - "id": "3959db03-da3c-4bc3-b5d9-f883a711f82b", + "id": "58e8e840-94a8-4414-81f7-01bbf1b73810", "metadata": {}, "source": [ - "Performing transpilation for the comparison circuit." + "Perform transpilation for the comparison circuit." ] }, { "cell_type": "code", "execution_count": 19, - "id": "a6508417-c922-451d-9acb-5a8695b965e4", + "id": "7c2e5fe7-21ce-461d-adaa-776f8d882163", "metadata": {}, "outputs": [ { @@ -860,7 +851,7 @@ }, { "cell_type": "markdown", - "id": "9b62bc2d-55b7-4c97-9666-886759a3f297", + "id": "1f832aaa-c2a9-42b7-95b6-bd920cdc17b0", "metadata": {}, "source": [ "### Step 3: Execute using Qiskit primitives\n", @@ -871,7 +862,7 @@ { "cell_type": "code", "execution_count": 20, - "id": "acf89871-9162-4c31-841b-e33d27ccc148", + "id": "3aabf36b-4587-43b7-be99-9376fc7f47c1", "metadata": {}, "outputs": [ { @@ -901,16 +892,16 @@ }, { "cell_type": "markdown", - "id": "51c79a36-70db-4cf1-b4d8-2eb964dec46a", + "id": "4ec6669b-2b76-41df-9634-3c073998b1d7", "metadata": {}, "source": [ - "Performing the execution for the comparison circuit." + "Perform the execution for the comparison circuit." ] }, { "cell_type": "code", "execution_count": 21, - "id": "fe1c0816-5816-454f-bd8f-14eea3e5ae6b", + "id": "91f16fff-da28-42b4-a32a-fa2f0945f8fd", "metadata": {}, "outputs": [ { @@ -939,7 +930,7 @@ }, { "cell_type": "markdown", - "id": "fc68dd8c-61cb-48c8-988e-60c300afb123", + "id": "3c6d16d4-3118-49b6-9594-3d7ddb02701c", "metadata": {}, "source": [ "### Step 4: Post-process and return result in desired classical format\n", @@ -950,7 +941,7 @@ { "cell_type": "code", "execution_count": 22, - "id": "36b83fe2-6b3b-4cdc-b3db-fd030ef070ec", + "id": "7247e56f-0ab8-4aa9-834c-ba95965a0b3f", "metadata": {}, "outputs": [ { @@ -994,7 +985,7 @@ }, { "cell_type": "markdown", - "id": "30badebe-9840-45e7-9ac3-8b019d674be5", + "id": "1c8b65e6-df72-45b3-8f31-a6aed44cb867", "metadata": {}, "source": [ "Bar plot to compare the results of the AQC, comparison, and exact circuits." @@ -1003,7 +994,7 @@ { "cell_type": "code", "execution_count": 23, - "id": "38c4f75d-27fe-4342-99c4-e1568f1e9343", + "id": "5f7b36a6-3666-4223-9c5d-d92bca741ad2", "metadata": {}, "outputs": [ { @@ -1045,10 +1036,10 @@ }, { "cell_type": "markdown", - "id": "a540fd4e-5fae-4af0-8b56-fd94f7ff5838", + "id": "ff81fb19-d175-42b0-8ef3-025712a7630d", "metadata": {}, "source": [ - "## Part II: scale it up!\n", + "## Part II: scale it up\n", "\n", "\n", "The second part of this tutorial builds on the previous example by scaling up to a larger system with 50 sites, illustrating how to map more complex quantum simulation problems to executable quantum circuits. Here, we explore the dynamics of a 50-site XXZ model, allowing us to build and optimize a substantial quantum circuit that reflects more realistic system sizes.\n", @@ -1058,12 +1049,12 @@ "\\hat{\\mathcal{H}}_{XXZ} = \\sum_{i=1}^{L-1} J_{i,(i+1)}\\left(X_i X_{(i+1)}+Y_i Y_{(i+1)}+ 2\\cdot Z_i Z_{(i+1)} \\right) \\, ,\n", "$$\n", "\n", - "where $J_{i,(i+1)}$ is a random coefficient corresponding to edge $(i, i+1)$ and $L=50$ is the number of sites." + "where $J_{i,(i+1)}$ is a random coefficient corresponding to edge $(i, i+1)$, and $L=50$ is the number of sites." ] }, { "cell_type": "markdown", - "id": "6925d295-f28c-457b-88f9-5279e29ace90", + "id": "f6d11e17-b4be-44fa-bc09-465e5e66a6af", "metadata": {}, "source": [ "Define the coupling map and edges for the Hamiltonian." @@ -1072,7 +1063,7 @@ { "cell_type": "code", "execution_count": 30, - "id": "a6cd46d8-b821-4860-8d2d-289462848042", + "id": "d0dec1ee-85fe-4c40-9595-b7764e9cfcca", "metadata": {}, "outputs": [], "source": [ @@ -1116,7 +1107,7 @@ }, { "cell_type": "markdown", - "id": "000ec763-d9fd-4c3b-8e98-7d1c08594e92", + "id": "65009d89-4752-40ac-b3ab-8e88425851b2", "metadata": {}, "source": [ "### Step 1: Map classical inputs to a quantum problem\n", @@ -1130,16 +1121,16 @@ }, { "cell_type": "markdown", - "id": "97b3ad88-a81a-47a2-9452-562335fd4c77", + "id": "41f5186a-e54e-4913-8a52-1c90611991c7", "metadata": {}, "source": [ - "Generate the AQC target circuit (The initial sgement)." + "Generate the AQC target circuit (the initial segment)." ] }, { "cell_type": "code", "execution_count": 31, - "id": "d3b73831-e047-4d24-9a3f-5407a3149175", + "id": "86735d08-49b3-47e4-abcd-631a77f50a02", "metadata": {}, "outputs": [], "source": [ @@ -1159,16 +1150,16 @@ }, { "cell_type": "markdown", - "id": "2e7af326-a62a-4f0f-9654-8aae91a7170c", + "id": "c5e79369-19ae-4b17-a9fc-9502a8a1254c", "metadata": {}, "source": [ - "Generate the subsequent circuit (The remaining segment)." + "Generate the subsequent circuit (the remaining segment)." ] }, { "cell_type": "code", "execution_count": 32, - "id": "0483ccf1-554c-4f18-8145-2569792d14c8", + "id": "35c6469c-3be7-4e89-a065-0e4957305b59", "metadata": {}, "outputs": [], "source": [ @@ -1184,16 +1175,16 @@ }, { "cell_type": "markdown", - "id": "150251ee-aee0-4eac-9f8e-d5239f6bc751", + "id": "0e13fbc5-0c00-4f21-9925-8d1230854dc5", "metadata": {}, "source": [ - "Generate the AQC comparison circuit (The initial segment, but with the same number of Trotter steps as the subsequent circuit)." + "Generate the AQC comparison circuit (the initial segment, but with the same number of Trotter steps as the subsequent circuit)." ] }, { "cell_type": "code", "execution_count": 33, - "id": "90237c0e-43d8-43bc-88e0-2bb037bc3167", + "id": "922fb467-81b0-40d7-b21b-ef781ad043a1", "metadata": {}, "outputs": [ { @@ -1225,7 +1216,7 @@ }, { "cell_type": "markdown", - "id": "06879425-2245-440f-922d-e05213a45bf9", + "id": "21228ca8-3fa6-4efe-9e53-8d3f824b7729", "metadata": {}, "source": [ "Generate the reference circuit." @@ -1234,7 +1225,7 @@ { "cell_type": "code", "execution_count": 34, - "id": "a0b14a35-bf0c-44ab-997c-d6505ad2aa2d", + "id": "3525fe02-25cf-4254-b2c4-717f27bc29d8", "metadata": {}, "outputs": [], "source": [ @@ -1254,7 +1245,7 @@ }, { "cell_type": "markdown", - "id": "cd4982ee-b3ae-4a11-9ed1-0a35ad7769b8", + "id": "a15b40ac-0259-4229-b76b-502ff7068499", "metadata": {}, "source": [ "Generate an ansatz and initial parameters from a Trotter circuit with fewer steps." @@ -1263,7 +1254,7 @@ { "cell_type": "code", "execution_count": 35, - "id": "63efe288-79c2-4ae5-9db1-9c457d332920", + "id": "ddbc3549-3171-4a29-b046-2a52b5e7065a", "metadata": {}, "outputs": [], "source": [ @@ -1287,7 +1278,7 @@ { "cell_type": "code", "execution_count": 36, - "id": "bf1e0ded-7d7a-4ac7-a121-46dc085da6ac", + "id": "8e596d77-5954-4756-b765-48855cd38659", "metadata": {}, "outputs": [ { @@ -1310,16 +1301,16 @@ }, { "cell_type": "markdown", - "id": "a205104f-c76d-484b-a091-999f73f5c168", + "id": "4d07d63a-8572-4116-9fd5-c070f62043a7", "metadata": {}, "source": [ - "Set settings for tensor network simulation and then construct a Matrix Product State representation of the target state for optimization. Then, evaluate the fidelity between the initial circuit and the target state to quantify the difference in Trotter error." + "Set settings for tensor network simulation and then construct a matrix product state representation of the target state for optimization. Then, evaluate the fidelity between the initial circuit and the target state to quantify the difference in Trotter error." ] }, { "cell_type": "code", "execution_count": 37, - "id": "2385cc75-07a6-4505-a610-833cce65f681", + "id": "6030706e-1451-47d9-9e47-bcccf4cb5d9c", "metadata": {}, "outputs": [ { @@ -1358,7 +1349,7 @@ }, { "cell_type": "markdown", - "id": "a9708bed-9f81-42a2-a633-b1d29cc91bd9", + "id": "56dfc4e4-6b28-4ed1-81da-8b0f4bc99425", "metadata": {}, "source": [ "To optimize the ansatz parameters, we minimize the `MaximizeStateFidelity` cost function using the L-BFGS optimizer from SciPy, with a stopping criterion set to surpass the fidelity of the initial circuit without AQC-Tensor. This ensures that the compressed circuit has both lower Trotter error and reduced depth." @@ -1367,7 +1358,7 @@ { "cell_type": "code", "execution_count": 38, - "id": "5796af5c-3103-425d-89bd-3f48e25db6b6", + "id": "af10ef7f-e57d-49a3-abb0-3d51e856c4b0", "metadata": {}, "outputs": [ { @@ -1476,7 +1467,7 @@ { "cell_type": "code", "execution_count": 39, - "id": "7f8e3574-fa91-48d4-b8dc-ec1991017a93", + "id": "0e711fcc-7767-411e-bb73-fd9c8408a22b", "metadata": {}, "outputs": [], "source": [ @@ -1485,7 +1476,7 @@ }, { "cell_type": "markdown", - "id": "44ba6b6d-2b8b-4836-a3d6-24319353bd41", + "id": "b1838b8e-81d4-4897-8cbd-dd7daa8bb220", "metadata": {}, "source": [ "Construct the final circuit for transpilation by assembling the optimized ansatz with the remaining time evolution circuit." @@ -1494,7 +1485,7 @@ { "cell_type": "code", "execution_count": 40, - "id": "2160be5d-138a-4250-925d-52e9a4634979", + "id": "f96b1ab0-f0ed-485f-a763-4ab57d36f410", "metadata": {}, "outputs": [], "source": [ @@ -1505,7 +1496,7 @@ { "cell_type": "code", "execution_count": 41, - "id": "fa39e8e8-a04a-48fb-9e63-51490db5dbc5", + "id": "579cbef1-a3a8-4916-b840-ab3fcc5c4b33", "metadata": {}, "outputs": [], "source": [ @@ -1514,7 +1505,7 @@ }, { "cell_type": "markdown", - "id": "bb11c7b2-974c-4818-9d01-57f6415c0fdd", + "id": "bb111fb1-07e4-4f0c-ad71-933b04492a23", "metadata": {}, "source": [ "### Step 2: Optimize problem for quantum hardware execution" @@ -1522,7 +1513,7 @@ }, { "cell_type": "markdown", - "id": "005b7339-a650-4973-96d1-65ba17b45355", + "id": "627dd426-730d-4554-b631-1e9949f46c26", "metadata": {}, "source": [ "Select the backend." @@ -1530,28 +1521,19 @@ }, { "cell_type": "code", - "execution_count": 42, - "id": "da94a1aa-48a3-4704-a18a-516f8b75116d", + "execution_count": null, + "id": "771a44a6-b5ba-4b9d-8c64-9a79f6d4ed77", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], + "outputs": [], "source": [ - "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"\", overwrite=True, set_as_default=True)\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(min_num_qubits=127)\n", "print(backend)" ] }, { "cell_type": "markdown", - "id": "f5384a41-c404-45ad-9cad-baad6c302a80", + "id": "cbc5d688-9acf-4fe2-8d58-fea74edb09e8", "metadata": {}, "source": [ "Transpile the completed circuit on the target hardware, preparing it for execution. The resulting ISA circuit can then be sent for execution on the backend." @@ -1560,7 +1542,7 @@ { "cell_type": "code", "execution_count": 43, - "id": "a642d9f9-606a-417e-97a8-f921717a003e", + "id": "85b4acc0-7121-416d-9bf5-b6d3135ae805", "metadata": {}, "outputs": [ { @@ -1598,7 +1580,7 @@ { "cell_type": "code", "execution_count": 44, - "id": "0af8500f-3c7c-41d6-be50-c90b07531cfe", + "id": "b0d295c7-c816-4683-bb2a-0ce9898e5d88", "metadata": {}, "outputs": [ { @@ -1634,7 +1616,7 @@ }, { "cell_type": "markdown", - "id": "5d94c26b-cd5c-4c34-9f36-f0056a2dd2c3", + "id": "f9431bec-66d1-44e3-a77d-01ca9e03e523", "metadata": {}, "source": [ "### Step 3: Execute using Qiskit primitives\n", @@ -1643,13 +1625,13 @@ "\n", "For this larger-scale example, we will explore how to utilize `EstimatorOptions` to better manage and control the parameters of our hardware experiment. While these settings are optional, they are useful for tracking experiment parameters and refining execution options for optimal results.\n", "\n", - "For a complete list of available execution options, refer to the [qiskit-ibm-runtime documentation](https://docs.quantum.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.EstimatorOptions)." + "For a complete list of available execution options, refer to the [qiskit-ibm-runtime documentation](/docs/api/qiskit-ibm-runtime/options-estimator-options)." ] }, { "cell_type": "code", "execution_count": 45, - "id": "aa6935e9-902f-4905-91d2-bc96001bd884", + "id": "cf449353-f392-4248-b6ad-5af9107c1fff", "metadata": {}, "outputs": [], "source": [ @@ -1691,7 +1673,7 @@ { "cell_type": "code", "execution_count": 46, - "id": "04258c28-ac1d-4090-856e-c14c06855d7d", + "id": "ea2a1425-a49b-4b31-b019-abbee4fdf690", "metadata": {}, "outputs": [ { @@ -1721,7 +1703,7 @@ { "cell_type": "code", "execution_count": 47, - "id": "07d8452b-228e-462c-a1eb-8c2ee348caa5", + "id": "4f7d9e7d-9da1-4cc3-ae09-0e3613c5479a", "metadata": {}, "outputs": [ { @@ -1750,7 +1732,7 @@ }, { "cell_type": "markdown", - "id": "9ed2d509-d8bd-47f0-a0d9-44e8042de207", + "id": "17ced13b-a3d3-4ded-92a6-b978508dd27a", "metadata": {}, "source": [ "### Step 4: Post-process and return result in desired classical format\n", @@ -1760,7 +1742,7 @@ { "cell_type": "code", "execution_count": 48, - "id": "8ad1a28e-f095-4540-a47b-dde1f3857cd6", + "id": "5b2e2d3e-bebb-44a4-bbdb-881ffc2749e5", "metadata": {}, "outputs": [ { @@ -1804,16 +1786,16 @@ }, { "cell_type": "markdown", - "id": "33647b44-abd6-454c-a71d-527756d54214", + "id": "f5ba5634-1689-457a-b7c7-adf3ca8e1d41", "metadata": {}, "source": [ - "Plotting the results of the AQC, comparison, and exact circuits for the 50-site XXZ model." + "Plot the results of the AQC, comparison, and exact circuits for the 50-site XXZ model." ] }, { "cell_type": "code", "execution_count": 49, - "id": "bfd0a870-1f61-42f1-b701-972680c0eed6", + "id": "01889c4d-16a4-458a-9211-08be8bcae1e4", "metadata": {}, "outputs": [ { @@ -1854,12 +1836,12 @@ }, { "cell_type": "markdown", - "id": "880db537-07d6-4ec8-9bc6-94f2d0acc327", + "id": "45f512f7-9233-4f1f-8f24-cb3524567135", "metadata": {}, "source": [ "## Conclusion\n", "\n", - "This tutorial demonstrated how to use Approximate Quantum Compilation with tensor networks (AQC-Tensor) to compress and optimize circuits for simulating quantum dynamics at scale. Utilizing both a small and large Heisenberg models, we applied AQC-Tensor to reduce the circuit depth required for Trotterized time evolution. By generating a parametrized ansatz from a simplified Trotter circuit and optimizing it with matrix product state (MPS) techniques, we achieved a low-depth approximation of the target evolution that is both accurate and efficient.\n", + "This tutorial demonstrated how to use Approximate Quantum Compilation with tensor networks (AQC-Tensor) to compress and optimize circuits for simulating quantum dynamics at scale. Utilizing both small and large Heisenberg models, we applied AQC-Tensor to reduce the circuit depth required for Trotterized time evolution. By generating a parametrized ansatz from a simplified Trotter circuit and optimizing it with matrix product state (MPS) techniques, we achieved a low-depth approximation of the target evolution that is both accurate and efficient.\n", "\n", "The workflow here highlights the key advantages of AQC-Tensor for scaling quantum simulations:\n", "\n", @@ -1872,7 +1854,7 @@ }, { "cell_type": "markdown", - "id": "d93b8a8b-318d-44eb-99ed-3921241edace", + "id": "3cc40a5a-4b55-45e8-a4f1-df45b9e37abd", "metadata": {}, "source": [ "## Tutorial survey\n", @@ -1884,10 +1866,10 @@ }, { "cell_type": "markdown", - "id": "2c64edb2-e820-4f7c-be37-fc919adc68fa", + "id": "07d2d65e-d1cf-433a-a1a4-31976c5733d1", "metadata": {}, "source": [ - "© IBM Corp. 2024" + "© IBM Corp. 2025" ] } ], @@ -1911,7 +1893,7 @@ "version": "3" }, "platform": "cloud", - "title": "Improved Trotterized Time Evolution with Approximate Quantum Compilation (AQC-Tensor)" + "title": "Approximate quantum compilation for time evolution circuits" }, "nbformat": 4, "nbformat_minor": 4 diff --git a/docs/tutorials/chsh-inequality.ipynb b/docs/tutorials/chsh-inequality.ipynb index 01fbe2cb1aa..a14e9319503 100644 --- a/docs/tutorials/chsh-inequality.ipynb +++ b/docs/tutorials/chsh-inequality.ipynb @@ -54,7 +54,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "3938d4a6", "metadata": {}, "outputs": [], @@ -152,24 +152,24 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "id": "16f323fb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'ibm_kyoto'" + "'ibm_torino'" ] }, - "execution_count": 2, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# To run on hardware, select the backend with the fewest number of jobs in the queue\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")\n", diff --git a/docs/tutorials/circuit-transpilation-settings.ipynb b/docs/tutorials/circuit-transpilation-settings.ipynb index d9265ba1526..fbe607869b2 100644 --- a/docs/tutorials/circuit-transpilation-settings.ipynb +++ b/docs/tutorials/circuit-transpilation-settings.ipynb @@ -103,7 +103,7 @@ ], "source": [ "# To run on hardware, select the backend with the fewest number of jobs in the queue\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")\n", diff --git a/docs/tutorials/combine-error-mitigation-options-with-the-estimator-primitive.ipynb b/docs/tutorials/combine-error-mitigation-techniques.ipynb similarity index 99% rename from docs/tutorials/combine-error-mitigation-options-with-the-estimator-primitive.ipynb rename to docs/tutorials/combine-error-mitigation-techniques.ipynb index 3174834401d..bec12b65d02 100644 --- a/docs/tutorials/combine-error-mitigation-options-with-the-estimator-primitive.ipynb +++ b/docs/tutorials/combine-error-mitigation-techniques.ipynb @@ -200,7 +200,7 @@ "metadata": {}, "outputs": [], "source": [ - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" diff --git a/docs/tutorials/reduce-transpiled-circuit-depth-with-circuit-cutting.ipynb b/docs/tutorials/depth-reduction-with-circuit-cutting.ipynb similarity index 99% rename from docs/tutorials/reduce-transpiled-circuit-depth-with-circuit-cutting.ipynb rename to docs/tutorials/depth-reduction-with-circuit-cutting.ipynb index 9ab779c3821..0833f8c6c27 100644 --- a/docs/tutorials/reduce-transpiled-circuit-depth-with-circuit-cutting.ipynb +++ b/docs/tutorials/depth-reduction-with-circuit-cutting.ipynb @@ -5,7 +5,7 @@ "id": "7ed4867f", "metadata": {}, "source": [ - "# Reduce transpiled circuit depth with circuit cutting\n", + "# Circuit cutting for depth reduction\n", "*Usage estimate: 8 minutes on IBM Brisbane (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -116,13 +116,12 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "b394da7a", "metadata": {}, "outputs": [], "source": [ - "# Remember to insert your token in the QiskitRuntimeService constructor\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, min_num_qubits=circuit.num_qubits, simulator=False\n", ")\n", @@ -471,7 +470,7 @@ "version": "3" }, "platform": "cloud", - "title": "Reduce transpiled circuit depth with circuit cutting" + "title": "Circuit cutting for depth reduction" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/building-workflows-with-the-ibm-circuit-function.ipynb b/docs/tutorials/error-mitigation-with-qiskit-functions.ipynb similarity index 99% rename from docs/tutorials/building-workflows-with-the-ibm-circuit-function.ipynb rename to docs/tutorials/error-mitigation-with-qiskit-functions.ipynb index 2005239cf0c..f07831e871e 100644 --- a/docs/tutorials/building-workflows-with-the-ibm-circuit-function.ipynb +++ b/docs/tutorials/error-mitigation-with-qiskit-functions.ipynb @@ -5,7 +5,7 @@ "id": "bb523f27-586e-4c9c-b641-1f1db71396ef", "metadata": {}, "source": [ - "# Building workflows with the IBM Circuit function\n", + "# Error mitigation with the IBM Circuit function\n", "*Usage estimate: 26 minutes on IBM Brisbane (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -109,7 +109,7 @@ "metadata": {}, "outputs": [], "source": [ - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" @@ -492,7 +492,7 @@ "version": "3" }, "platform": "cloud", - "title": "Building workflows with the IBM Circuit function\n" + "title": "Error mitigation with the IBM Circuit function\n" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/grovers-algorithm.ipynb b/docs/tutorials/grovers-algorithm.ipynb index 73226208ed9..2190ea7a4ca 100644 --- a/docs/tutorials/grovers-algorithm.ipynb +++ b/docs/tutorials/grovers-algorithm.ipynb @@ -129,7 +129,7 @@ ], "source": [ "# To run on hardware, select the backend with the fewest number of jobs in the queue\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")\n", @@ -166,7 +166,7 @@ ], "source": [ "# To run on hardware, select the backend with the fewest number of jobs in the queue\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")\n", diff --git a/docs/tutorials/krylov-subspace-expansion.ipynb b/docs/tutorials/krylov-quantum-diagonalization.ipynb similarity index 99% rename from docs/tutorials/krylov-subspace-expansion.ipynb rename to docs/tutorials/krylov-quantum-diagonalization.ipynb index c21d08f09c0..1d46b845233 100644 --- a/docs/tutorials/krylov-subspace-expansion.ipynb +++ b/docs/tutorials/krylov-quantum-diagonalization.ipynb @@ -7,7 +7,7 @@ "source": [ "{/* cspell:ignore prefactors */}\n", "\n", - "# Diagonalization of large many-body Hamiltonians on a quantum processor\n", + "# Krylov quantum diagonalization of lattice Hamiltonians\n", "*Usage estimate: 20 minutes on IBM Fez (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -875,7 +875,7 @@ "metadata": {}, "outputs": [], "source": [ - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" @@ -1638,7 +1638,7 @@ "version": "3" }, "platform": "cloud", - "title": "Diagonalization of large many-body Hamiltonians on a quantum processor\n" + "title": "Krylov quantum diagonalization of lattice Hamiltonians\n" }, "nbformat": 4, "nbformat_minor": 4 diff --git a/docs/tutorials/long-range-entanglement-with-limited-qubit-connectivity.ipynb b/docs/tutorials/long-range-entanglement.ipynb similarity index 99% rename from docs/tutorials/long-range-entanglement-with-limited-qubit-connectivity.ipynb rename to docs/tutorials/long-range-entanglement.ipynb index 952ed032dd6..99e18d1f9a9 100644 --- a/docs/tutorials/long-range-entanglement-with-limited-qubit-connectivity.ipynb +++ b/docs/tutorials/long-range-entanglement.ipynb @@ -12,7 +12,7 @@ "source": [ "{/* cspell:ignore XIXI, IZIZ, XZXZ, YZYI, ZZZI, YIYZ, ZIZZ, IXXX, XYIY, IYXY, ZYYX, YYZX, ZXYY, YXZY, quasidistillation */}\n", "\n", - "# Long-range entanglement with limited qubit connectivity\n", + "# Long-range entanglement with dynamic circuits\n", "*Usage estimate: 90 minutes on IBM Sherbrooke (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -235,7 +235,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "4fc13eba-bc50-4607-88f9-8ada04b69794", "metadata": {}, "outputs": [ @@ -271,7 +271,7 @@ "\n", "\n", "# Set up access to IBM Quantum devices\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")\n", @@ -2369,7 +2369,7 @@ "version": "3" }, "platform": "cloud", - "title": "Long-range entanglement with limited qubit connectivity" + "title": "Long-range entanglement with dynamic circuits" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/generating-long-range-entanglement-with-measurements.ipynb b/docs/tutorials/nishimori-phase-transition.ipynb similarity index 99% rename from docs/tutorials/generating-long-range-entanglement-with-measurements.ipynb rename to docs/tutorials/nishimori-phase-transition.ipynb index a4dfc478769..6ea97c7e387 100644 --- a/docs/tutorials/generating-long-range-entanglement-with-measurements.ipynb +++ b/docs/tutorials/nishimori-phase-transition.ipynb @@ -5,7 +5,7 @@ "id": "a10c2a41-ab48-4da5-bbe1-a16fd47906fe", "metadata": {}, "source": [ - "# Generating long-range entanglement with measurements\n", + "# Nishimori phase transition\n", "*Usage estimate: 3 minutes on IBM Torino (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -725,7 +725,7 @@ "version": "3" }, "platform": "cloud", - "title": "Generating long-range entanglement with measurements" + "title": "Nishimori phase transition" }, "nbformat": 4, "nbformat_minor": 4 diff --git a/docs/tutorials/improving-estimation-of-expectation-values-with-operator-backpropagation.ipynb b/docs/tutorials/operator-back-propagation.ipynb similarity index 99% rename from docs/tutorials/improving-estimation-of-expectation-values-with-operator-backpropagation.ipynb rename to docs/tutorials/operator-back-propagation.ipynb index 0413e1cee14..c69b4399b3d 100644 --- a/docs/tutorials/improving-estimation-of-expectation-values-with-operator-backpropagation.ipynb +++ b/docs/tutorials/operator-back-propagation.ipynb @@ -7,7 +7,7 @@ "source": [ "{/* cspell:ignore simeq // This in an equation and isn't being ignored correctly */}\n", "\n", - "# Improving estimation of expectation values with Operator Backpropagation (OBP)\n", + "# Operator backpropagation (OBP) for estimation of expectation values\n", "*Usage estimate: 16 minutes on IBM Nazca (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -507,12 +507,12 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "10a660c2-bf9e-4f81-aab4-d9ef294180a2", "metadata": {}, "outputs": [], "source": [ - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" @@ -1339,7 +1339,7 @@ "version": "3" }, "platform": "cloud", - "title": "Improving estimation of expectation values with Operator Backpropagation (OBP)" + "title": "Operator backpropagation (OBP) for estimation of expectation values" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/solving-maxcut-with-reduced-qubit-requirements-using-pauli-correlation-encoding.ipynb b/docs/tutorials/pauli-correlation-encoding-for-qaoa.ipynb similarity index 99% rename from docs/tutorials/solving-maxcut-with-reduced-qubit-requirements-using-pauli-correlation-encoding.ipynb rename to docs/tutorials/pauli-correlation-encoding-for-qaoa.ipynb index 989bb3c7eea..2d39176182b 100644 --- a/docs/tutorials/solving-maxcut-with-reduced-qubit-requirements-using-pauli-correlation-encoding.ipynb +++ b/docs/tutorials/pauli-correlation-encoding-for-qaoa.ipynb @@ -7,7 +7,7 @@ "source": [ "{/* cspell:ignore setminus coloneqq rbrack // latex that isn't being ignored for some reason */}\n", "\n", - "# Solving Maxcut with Reduced Qubit Requirements Using Pauli Correlation Encoding\n", + "# Pauli Correlation Encoding to reduce Maxcut requirements\n", "\n", "*Usage estimate: 30 minutes on IBM Sherbrooke (NOTE: This is an estimate only. Your runtime may vary.)*" ] @@ -93,9 +93,7 @@ "from qiskit_ibm_runtime import Session\n", "from rustworkx.visualization import mpl_draw\n", "\n", - "# If you didn't previously save your account, follow the instructions here:\n", - "# https://docs.quantum.ibm.com/guides/setup-channel\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" @@ -731,7 +729,7 @@ "version": "3" }, "platform": "cloud", - "title": "Solving Maxcut with Reduced Qubit Requirements Using Pauli Correlation Encoding" + "title": "Pauli Correlation Encoding to reduce Maxcut requirements" }, "nbformat": 4, "nbformat_minor": 4 diff --git a/docs/tutorials/scaling-periodic-boundary-problems-with-circuit-cutting.ipynb b/docs/tutorials/periodic-boundary-conditions-with-circuit-cutting.ipynb similarity index 99% rename from docs/tutorials/scaling-periodic-boundary-problems-with-circuit-cutting.ipynb rename to docs/tutorials/periodic-boundary-conditions-with-circuit-cutting.ipynb index e919ab24183..b77ba0ab770 100644 --- a/docs/tutorials/scaling-periodic-boundary-problems-with-circuit-cutting.ipynb +++ b/docs/tutorials/periodic-boundary-conditions-with-circuit-cutting.ipynb @@ -5,9 +5,9 @@ "id": "eb16d89d-f6fc-417f-9ce5-19251d039df7", "metadata": {}, "source": [ - "{/* cspell:ignore edgecolor */}", + "{/* cspell:ignore edgecolor */}\n", "\n", - "# Scaling Periodic Boundary Problems with Circuit Cutting\n", + "# Circuit cutting for periodic boundary conditions\n", "*Usage estimate: 2 minutes on IBM Brisbane (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -123,7 +123,7 @@ "metadata": {}, "outputs": [], "source": [ - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" @@ -996,7 +996,7 @@ "version": "3" }, "platform": "cloud", - "title": "Scaling Periodic Boundary Problems with Circuit Cutting\n" + "title": "Circuit cutting for periodic boundary conditions\n" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/utility-scale-error-mitigation-with-probabilistic-error-amplification.ipynb b/docs/tutorials/probabilistic-error-amplification.ipynb similarity index 99% rename from docs/tutorials/utility-scale-error-mitigation-with-probabilistic-error-amplification.ipynb rename to docs/tutorials/probabilistic-error-amplification.ipynb index 9ac41c356e9..56ba462064c 100644 --- a/docs/tutorials/utility-scale-error-mitigation-with-probabilistic-error-amplification.ipynb +++ b/docs/tutorials/probabilistic-error-amplification.ipynb @@ -215,12 +215,12 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "50c0b07c-b43a-4d48-8d06-d141469fd0e6", "metadata": {}, "outputs": [], "source": [ - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" diff --git a/docs/tutorials/quantum-approximate-optimization-algorithm.ipynb b/docs/tutorials/quantum-approximate-optimization-algorithm.ipynb index bfad23e45d1..7a514370c22 100644 --- a/docs/tutorials/quantum-approximate-optimization-algorithm.ipynb +++ b/docs/tutorials/quantum-approximate-optimization-algorithm.ipynb @@ -17,7 +17,7 @@ "id": "bc51e7bf-e582-49ba-93f8-035624d56ccf", "metadata": {}, "source": [ - "# Solve utility-scale quantum optimization problems\n", + "# Quantum approximate optimization algorithm\n", "*Usage estimate: 8 minutes on IBM Sherbrooke (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -407,7 +407,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "3f28a422-805c-4d3d-b5f6-62539e9133bd", "metadata": {}, "outputs": [ @@ -431,8 +431,7 @@ } ], "source": [ - "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"\", overwrite=True, set_as_default=True)\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")\n", @@ -1422,7 +1421,7 @@ "version": "3" }, "platform": "cloud", - "title": "Solve utility-scale quantum optimization problems" + "title": "Quantum approximate optimization algorithm" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/quantum-kernel-training.ipynb b/docs/tutorials/quantum-kernel-training.ipynb index 7768a99b7a5..fb984a827d5 100644 --- a/docs/tutorials/quantum-kernel-training.ipynb +++ b/docs/tutorials/quantum-kernel-training.ipynb @@ -193,7 +193,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "49607b34-9723-493d-85da-bd97c1351104", "metadata": {}, "outputs": [ @@ -210,8 +210,7 @@ } ], "source": [ - "# Remember to insert your token in the QiskitRuntimeService constructor\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=overlap_circ.num_qubits\n", ")\n", diff --git a/docs/tutorials/qunova-hivqe.ipynb b/docs/tutorials/qunova-hivqe.ipynb index 1e6ae973b38..3cccff1d5c6 100644 --- a/docs/tutorials/qunova-hivqe.ipynb +++ b/docs/tutorials/qunova-hivqe.ipynb @@ -7,7 +7,7 @@ "source": [ "{/* cspell:ignore hivqe mcscf CASCI */}\n", "\n", - "# Compute Dissociation PES curve for Li2S (20Q) and FeP-NO (44Q) with Qunova HiVQE" + "# Dissociation PES curves with Qunova HiVQE" ] }, { @@ -1121,7 +1121,7 @@ "version": "3" }, "platform": "cloud", - "title": "Compute Dissociation PES curve for Li2S (20Q) and FeP-NO (44Q) with Qunova HiVQE" + "title": "Dissociation PES curves with Qunova HiVQE" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/real-time-benchmarking-for-qubit-selection.ipynb b/docs/tutorials/real-time-benchmarking-for-qubit-selection.ipynb index 3baeff7a8c9..07abd7b3a80 100644 --- a/docs/tutorials/real-time-benchmarking-for-qubit-selection.ipynb +++ b/docs/tutorials/real-time-benchmarking-for-qubit-selection.ipynb @@ -109,13 +109,13 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "f968acca-9131-4f5d-aa74-70befcdda4f5", "metadata": {}, "outputs": [], "source": [ "# To run on hardware, select the backend with the fewest number of jobs in the queue\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")\n", diff --git a/docs/tutorials/build-repetition-codes.ipynb b/docs/tutorials/repetition-codes.ipynb similarity index 99% rename from docs/tutorials/build-repetition-codes.ipynb rename to docs/tutorials/repetition-codes.ipynb index d1cf4457694..b219d86612b 100644 --- a/docs/tutorials/build-repetition-codes.ipynb +++ b/docs/tutorials/repetition-codes.ipynb @@ -10,7 +10,7 @@ } }, "source": [ - "# Build repetition codes\n", + "# Repetition codes\n", "*Estimated QPU usage: 4 seconds (tested on IBM Sherbrooke)*\n", "\n", "## Background\n", @@ -518,7 +518,7 @@ "version": "3" }, "platform": "cloud", - "title": "Build repetition codes" + "title": "Repetition codes" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/improving-energy-estimation-of-a-fermionic-hamiltonian-with-sqd.ipynb b/docs/tutorials/sample-based-quantum-diagonalization.ipynb similarity index 99% rename from docs/tutorials/improving-energy-estimation-of-a-fermionic-hamiltonian-with-sqd.ipynb rename to docs/tutorials/sample-based-quantum-diagonalization.ipynb index d415a6a36f3..a3dc9e87c34 100644 --- a/docs/tutorials/improving-energy-estimation-of-a-fermionic-hamiltonian-with-sqd.ipynb +++ b/docs/tutorials/sample-based-quantum-diagonalization.ipynb @@ -7,7 +7,7 @@ "source": [ "{/* cspell:ignore LUCJ CCSD ccsd hcore */}\n", "\n", - "# Improving energy estimation of a Fermionic Hamiltonian with SQD\n", + "# Sample-based quantum diagonalization of a chemistry Hamiltonian\n", "*Usage estimate: under 1 minute on IBM Sherbrooke (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -338,7 +338,7 @@ "metadata": {}, "outputs": [], "source": [ - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" diff --git a/docs/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver.ipynb b/docs/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver.ipynb index e073e829d05..572b1467045 100644 --- a/docs/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver.ipynb +++ b/docs/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver.ipynb @@ -7,7 +7,7 @@ "source": [ "{/* cspell:ignore lambdify ILOG histtype stepfilled */}\n", "\n", - "# Solve higher-order binary optimization problems with Q-CTRL's Optimization Solver" + "# Higher-order binary optimization with Q-CTRL's Optimization Solver" ] }, { @@ -847,7 +847,7 @@ "version": "3" }, "platform": "cloud", - "title": "Solve higher-order binary optimization problems with Q-CTRL's Optimization Solver" + "title": "Higher-order binary optimization with Q-CTRL's Optimization Solver" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/heisenberg-chain.ipynb b/docs/tutorials/spin-chain-vqe.ipynb similarity index 99% rename from docs/tutorials/heisenberg-chain.ipynb rename to docs/tutorials/spin-chain-vqe.ipynb index 2c2a398da8d..825346b2afc 100644 --- a/docs/tutorials/heisenberg-chain.ipynb +++ b/docs/tutorials/spin-chain-vqe.ipynb @@ -7,7 +7,7 @@ "tags": [] }, "source": [ - "# Heisenberg chain\n", + "# Ground state energy estimation of the Heisenberg chain with VQE\n", "*Usage estimate: 2 minutes on IBM Cusco (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -428,7 +428,7 @@ "version": "3" }, "platform": "cloud", - "title": "Heisenberg chain" + "title": "Ground state energy estimation of the Heisenberg chain with VQE" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/docs/tutorials/transpilation-optimizations-with-sabre.ipynb b/docs/tutorials/transpilation-optimizations-with-sabre.ipynb index 6a373ab533b..d32e22e3d92 100644 --- a/docs/tutorials/transpilation-optimizations-with-sabre.ipynb +++ b/docs/tutorials/transpilation-optimizations-with-sabre.ipynb @@ -211,7 +211,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "c426faa1-6656-4ac4-8c41-b37720f7bdc4", "metadata": {}, "outputs": [ @@ -224,8 +224,7 @@ } ], "source": [ - "# QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"\", overwrite=True, set_as_default=True)\n", - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")\n", @@ -806,7 +805,7 @@ "heuristic = arguments.get(\"heuristic\")\n", "\n", "# Get the backend\n", - "service = QiskitRuntimeService(channel='ibm_quantum')\n", + "service = QiskitRuntimeService()\n", "backend = service.backend(backend_name)\n", "print(backend)\n", "\n", diff --git a/docs/tutorials/wire-cutting-to-improve-performance.ipynb b/docs/tutorials/wire-cutting.ipynb similarity index 99% rename from docs/tutorials/wire-cutting-to-improve-performance.ipynb rename to docs/tutorials/wire-cutting.ipynb index 4a7e75241f6..0b0d3101f1b 100644 --- a/docs/tutorials/wire-cutting-to-improve-performance.ipynb +++ b/docs/tutorials/wire-cutting.ipynb @@ -5,7 +5,7 @@ "id": "57a88d32-f7b1-4bd9-9677-d172af205376", "metadata": {}, "source": [ - "# Improving estimation of expectation values using wire cutting\n", + "# Wire cutting for expectation values estimation\n", "*Usage estimate: 1 minute on IBM Brisbane (NOTE: This is an estimate only. Your runtime may vary.)*" ] }, @@ -600,7 +600,7 @@ "metadata": {}, "outputs": [], "source": [ - "service = QiskitRuntimeService(channel=\"ibm_quantum\")\n", + "service = QiskitRuntimeService()\n", "backend = service.least_busy(\n", " operational=True, simulator=False, min_num_qubits=127\n", ")" @@ -1295,7 +1295,7 @@ "version": "3" }, "platform": "cloud", - "title": "Improving estimation of expectation values using wire cutting" + "title": "Wire cutting for expectation values estimation" }, "nbformat": 4, "nbformat_minor": 5 diff --git a/qiskit_bot.yaml b/qiskit_bot.yaml index 44a9b32dcbe..0de585664cb 100644 --- a/qiskit_bot.yaml +++ b/qiskit_bot.yaml @@ -512,25 +512,25 @@ notifications: "docs/tutorials/ai-transpiler-introduction": - "@miamico" - "@henryzou50" - "docs/tutorials/build-repetition-codes": + "docs/tutorials/repetition-codes": - "@miamico" - "@henryzou50" - "docs/tutorials/combine-error-mitigation-options-with-the-estimator-primitive": + "docs/tutorials/combine-error-mitigation-techniques": - "@miamico" - "@RitajitMajumdar" - "docs/tutorials/generating-long-range-entanglement-with-measurements": + "docs/tutorials/nishimori-phase-transition": - "@miamico" - "@kevinsung" - "docs/tutorials/heisenberg-chain": + "docs/tutorials/spin-chain-vqe": - "@miamico" - "@MeltemTolunay" - "docs/tutorials/improved-trotterized-time-evolution-with-approximate-quantum-compilation": + "docs/tutorials/approximate-quantum-compilation-for-time-evolution": - "@miamico" - "@henryzou50" - "docs/tutorials/improving-estimation-of-expectation-values-with-operator-backpropagation": + "docs/tutorials/operator-back-propagation": - "@miamico" - "@RitajitMajumdar" - "docs/tutorials/long-range-entanglement-with-limited-qubit-connectivity": + "docs/tutorials/long-range-entanglement": - "@miamico" "docs/tutorials/advanced-techniques-for-qaoa": - "@miamico" @@ -546,26 +546,26 @@ notifications: - "@a-matsuo" "docs/tutorials/quantum-kernel-training": - "@miamico" - "docs/tutorials/reduce-transpiled-circuit-depth-with-circuit-cutting": + "docs/tutorials/depth-reduction-with-circuit-cutting": - "@miamico" - "@RitajitMajumdar" "docs/tutorials/repeat-until-success": - "@miamico" - "docs/tutorials/solving-maxcut-with-reduced-qubit-requirements-using-pauli-correlation-encoding": + "docs/tutorials/probabilistic-error-amplification": + - "@miamico" + "docs/tutorials/pauli-correlation-encoding-for-qaoa": - "@miamico" - "@a-matsuo" "docs/tutorials/transpilation-optimizations-with-sabre": - "@miamico" - "@henryzou50" - "docs/tutorials/utility-scale-error-mitigation-with-probabilistic-error-amplification": - - "@miamico" "docs/tutorials/variational-quantum-eigensolver": - "@miamico" - "@MeltemTolunay" - "docs/tutorials/wire-cutting-to-improve-performance": + "docs/tutorials/wire-cutting": - "@miamico" - "@RitajitMajumdar" - "docs/tutorials/building-workflows-with-the-ibm-circuit-function": + "docs/tutorials/error-mitigation-with-qiskit-functions": - "@miamico" - "@RitajitMajumdar" "docs/tutorials/qunova-hivqe": @@ -581,13 +581,13 @@ notifications: - "@abbycross" "docs/tutorials/real-time-benchmarking-for-qubit-selection": - "@miamico" - "docs/tutorials/scaling-periodic-boundary-problems-with-circuit-cutting": + "docs/tutorials/periodic-boundary-conditions-with-circuit-cutting": - "@miamico" - "@RitajitMajumdar" - "docs/tutorials/improving-energy-estimation-of-a-fermionic-hamiltonian-with-sqd": + "docs/tutorials/sample-based-quantum-diagonalization": - "@miamico" - "@kevinsung" - "docs/tutorials/krylov-subspace-expansion": + "docs/tutorials/krylov-quantum-diagonalization": - "@miamico" "docs/tutorials/compute-dissociation-curves-for-strong-coupling-systems-with-quna-sys-qsci": - "@miamico" diff --git a/scripts/config/notebook-testing.toml b/scripts/config/notebook-testing.toml index 2c5d3d9211a..aa1cef90d4a 100644 --- a/scripts/config/notebook-testing.toml +++ b/scripts/config/notebook-testing.toml @@ -136,31 +136,31 @@ notebooks = [ # We never run tutorials notebooks "docs/tutorials/advanced-techniques-for-qaoa.ipynb", "docs/tutorials/ai-transpiler-introduction.ipynb", - "docs/tutorials/build-repetition-codes.ipynb", "docs/tutorials/circuit-transpilation-settings.ipynb", - "docs/tutorials/combine-error-mitigation-options-with-the-estimator-primitive.ipynb", - "docs/tutorials/generating-long-range-entanglement-with-measurements.ipynb", "docs/tutorials/grovers-algorithm.ipynb", - "docs/tutorials/heisenberg-chain.ipynb", - "docs/tutorials/improved-trotterized-time-evolution-with-approximate-quantum-compilation.ipynb", - "docs/tutorials/improving-estimation-of-expectation-values-with-operator-backpropagation.ipynb", - "docs/tutorials/long-range-entanglement-with-limited-qubit-connectivity.ipynb", + "docs/tutorials/spin-chain-vqe.ipynb", "docs/tutorials/quantum-approximate-optimization-algorithm.ipynb", "docs/tutorials/quantum-kernel-training.ipynb", - "docs/tutorials/reduce-transpiled-circuit-depth-with-circuit-cutting.ipynb", "docs/tutorials/repeat-until-success.ipynb", - "docs/tutorials/solving-maxcut-with-reduced-qubit-requirements-using-pauli-correlation-encoding.ipynb", "docs/tutorials/transpilation-optimizations-with-sabre.ipynb", - "docs/tutorials/utility-scale-error-mitigation-with-probabilistic-error-amplification.ipynb", "docs/tutorials/variational-quantum-eigensolver.ipynb", - "docs/tutorials/wire-cutting-to-improve-performance.ipynb", - "docs/tutorials/building-workflows-with-the-ibm-circuit-function.ipynb", "docs/tutorials/qunova-hivqe.ipynb", "docs/tutorials/real-time-benchmarking-for-qubit-selection.ipynb", - "docs/tutorials/scaling-periodic-boundary-problems-with-circuit-cutting.ipynb", - "docs/tutorials/improving-energy-estimation-of-a-fermionic-hamiltonian-with-sqd.ipynb", - "docs/tutorials/krylov-subspace-expansion.ipynb", "docs/tutorials/compute-dissociation-curves-for-strong-coupling-systems-with-quna-sys-qsci.ipynb", "docs/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver.ipynb", "docs/tutorials/chsh-inequality.ipynb", + "docs/tutorials/approximate-quantum-compilation-for-time-evolution.ipynb", + "docs/tutorials/combine-error-mitigation-techniques.ipynb", + "docs/tutorials/periodic-boundary-conditions-with-circuit-cutting.ipynb", + "docs/tutorials/repetition-codes.ipynb", + "docs/tutorials/error-mitigation-with-qiskit-functions.ipynb", + "docs/tutorials/operator-back-propagation.ipynb", + "docs/tutorials/depth-reduction-with-circuit-cutting.ipynb", + "docs/tutorials/long-range-entanglement.ipynb", + "docs/tutorials/wire-cutting.ipynb", + "docs/tutorials/krylov-quantum-diagonalization.ipynb", + "docs/tutorials/probabilistic-error-amplification.ipynb", + "docs/tutorials/sample-based-quantum-diagonalization.ipynb", + "docs/tutorials/pauli-correlation-encoding-for-qaoa.ipynb", + "docs/tutorials/nishimori-phase-transition.ipynb", ]