{ "cells": [ { "cell_type": "markdown", "id": "26c21ec5", "metadata": {}, "source": [ "# Example for execution of multiple circuits in QPUs" ] }, { "cell_type": "markdown", "id": "df8dc942", "metadata": {}, "source": [ "In this notebook, some examples of simple execution without communications will be shown. The scheme followed is going to be the similar in every case, even for the most complex ones. First, the `cunqa` module imports will be done." ] }, { "cell_type": "markdown", "id": "82e8596c", "metadata": {}, "source": [ "
\n", "Warning: The path to the cunqa module has to be added if cunqa is not in the PYTHONPATH list of directories. This is specially important for the ones that built CUNQA from source and are not using it as a LMOD module (in which case, if the installation was done correctly, cunqa module will be inside PYTHONPATH). As a default example, the path added is the $HOME path, but it should be adapted.\n", "
" ] }, { "cell_type": "code", "execution_count": 8, "id": "c532632a", "metadata": {}, "outputs": [], "source": [ "import os, sys\n", "\n", "# If this is not done before the cunqa module imports, it will fail to find them\n", "sys.path.append(os.getenv(\"HOME\"))\n", "\n", "from cunqa import get_QPUs, qraise, gather, qdrop\n", "from cunqa.qpu import run" ] }, { "cell_type": "markdown", "id": "368e94bf", "metadata": {}, "source": [ "## Small circuit example\n", "### Turning ON the vQPUs\n", "\n", "After the imports, we begin with the body of the program. First of all, the virtual QPUs (vQPUs) must be deployed. To achieve this there are two options:\n", "\n", "1. **Using the `qraise` command**.\n", "2. **Using the `qraise()` Python function**.\n", " \n", "Both achieve the same: turning on the vQPUs. In fact, the `qraise()` Python function employs the `qraise` bash command to achieve this. The difference lies in the fact that the `qraise()` Python function integrates the resource management into the Python API worflow, while the `qraise` bash command needs to be executed before the workflow starts in order to have the QPUs raised beforehand.\n", "\n", "In order to make this example self-contained the `qraise` Python function will be employed." ] }, { "cell_type": "code", "execution_count": 9, "id": "c2d0c54e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requested QPUs with command:\n", "\tqraise -n 2 -t 00:10:00 --simulator=Aer --co-located\n", "QPUs ready to work ✅\n", "\n", "QPUs properties:\n", "QPU 377618_294450, backend: SimpleBackend, simulator: AerSimulator, version: 0.0.1.\n", "QPU 377618_294451, backend: SimpleBackend, simulator: AerSimulator, version: 0.0.1.\n" ] } ], "source": [ "family = qraise(2, \"00:10:00\", simulator = \"Aer\", co_located = True)\n", "# bash equivalent: qraise -n 2 -t 00:10:00 --sim Aer --co-located\n", "\n", "qpus = get_QPUs(co_located=True, family=family)\n", "\n", "print(\"\\nQPUs properties:\")\n", "for q in qpus:\n", " print(f\"QPU {q.id}, backend: {q.backend['name']}, simulator: {q.backend['simulator']}, version: {q.backend['version']}.\")" ] }, { "cell_type": "markdown", "id": "0b312b18", "metadata": {}, "source": [ "Two vQPUs were raised for ten minutes, without communications and employing the Aer simulator to execute the circuits. Moreover, the flag `co_located` was set to true, meaning that these vQPUs will run in a co-located scheme, i.e, they will be accesible from every node of the cluster. \n", "\n", "
\n", "Warrning: If the co_located flag was not set to true, then the vQPUs will be available only if the user is inside the node they are deployed on (similar to how it works with actual GPUs).\n", "
\n", "\n", "On the oher hand, the method `get_QPUs()` accesses the information of the raised vQPUs and instantiates one `QPU` object for each. This `QPU` instance possesses the information of its related vQPU and, also, a connection to it. This way, this object is the one responsible of sending the circuit to get it executed. " ] }, { "cell_type": "markdown", "id": "29555d4b", "metadata": {}, "source": [ "### Designing the circuit \n", "\n", "There are three options for designing the circuit:\n", "\n", "- **`CunqaCircuit`**.\n", "- **`QuantumCircuit`** (from Qiskit).\n", "- **`json`**.\n", "\n", "`CunqaCircuit` is designed to be similar to the `QuantumCircuit` but allowing communication instructions. This is done to reduce the learning curve, recognizing the fact that `QuantumCircuit` is a well stablished API inside quantum computation programmers.\n", "\n", "The `json` format is used as an intermediate representation (IR). It is a much less human-understandable format employed to send the information to the vQPUs, but it can be directly used (as the complex example will show).\n", "\n", "But because in this example communication directives are not employed, the `QuantumCircuit` class from Qiskit is employed." ] }, { "cell_type": "code", "execution_count": 10, "id": "c5350387", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
        ┌───┐┌──────┐┌───────┐ ░ ┌─┐            \n",
       "   q_0: ┤ X ├┤0     ├┤0      ├─░─┤M├────────────\n",
       "        └───┘│      ││       │ ░ └╥┘┌─┐         \n",
       "   q_1: ─────┤1     ├┤1      ├─░──╫─┤M├─────────\n",
       "             │      ││       │ ░  ║ └╥┘┌─┐      \n",
       "   q_2: ─────┤2 QFT ├┤2 IQFT ├─░──╫──╫─┤M├──────\n",
       "        ┌───┐│      ││       │ ░  ║  ║ └╥┘┌─┐   \n",
       "   q_3: ┤ X ├┤3     ├┤3      ├─░──╫──╫──╫─┤M├───\n",
       "        ├───┤│      ││       │ ░  ║  ║  ║ └╥┘┌─┐\n",
       "   q_4: ┤ X ├┤4     ├┤4      ├─░──╫──╫──╫──╫─┤M├\n",
       "        └───┘└──────┘└───────┘ ░  ║  ║  ║  ║ └╥┘\n",
       "meas: 5/══════════════════════════╩══╩══╩══╩══╩═\n",
       "                                  0  1  2  3  4 
" ], "text/plain": [ " ┌───┐┌──────┐┌───────┐ ░ ┌─┐ \n", " q_0: ┤ X ├┤0 ├┤0 ├─░─┤M├────────────\n", " └───┘│ ││ │ ░ └╥┘┌─┐ \n", " q_1: ─────┤1 ├┤1 ├─░──╫─┤M├─────────\n", " │ ││ │ ░ ║ └╥┘┌─┐ \n", " q_2: ─────┤2 QFT ├┤2 IQFT ├─░──╫──╫─┤M├──────\n", " ┌───┐│ ││ │ ░ ║ ║ └╥┘┌─┐ \n", " q_3: ┤ X ├┤3 ├┤3 ├─░──╫──╫──╫─┤M├───\n", " ├───┤│ ││ │ ░ ║ ║ ║ └╥┘┌─┐\n", " q_4: ┤ X ├┤4 ├┤4 ├─░──╫──╫──╫──╫─┤M├\n", " └───┘└──────┘└───────┘ ░ ║ ║ ║ ║ └╥┘\n", "meas: 5/══════════════════════════╩══╩══╩══╩══╩═\n", " 0 1 2 3 4 " ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from qiskit import QuantumCircuit\n", "from qiskit.circuit.library import QFT\n", "\n", "n = 5 # number of qubits\n", "\n", "qc = QuantumCircuit(n)\n", "\n", "qc.x(0); qc.x(n-1); qc.x(n-2)\n", "qc.append(QFT(n), range(n))\n", "qc.append(QFT(n).inverse(), range(n))\n", "qc.measure_all()\n", "\n", "display(qc.draw())" ] }, { "cell_type": "markdown", "id": "bf2f0f88", "metadata": {}, "source": [ "### Executing the circuit in the vQPUs\n", "It is time to execute and display the results by following these steps:\n", "\n", "1. Calling the `run` function with: the circuit, the QPU and the run parameters. This method will return a `qjob.QJob` object.\n", "
\n", "Note: The `run()` function is asynchronous.\n", "
\n", "\n", "2. To get the results of the simulation, the property `QJob.result` is called, returning a `Result` object that stores the execution information. Depending on the simulator, there will be more or less information.\n", "3.
\n", "Note: This is a synchronous method, blocking the execution until the vQPU retrieves the results obtained.\n", "
\n", "\n", "4. From the `Result` object obtained, the counts dictionary can be obtained by accessing the `Result.counts` property. Another property independent from the simulator is `Result.time_taken`, that stores the time spent in the simulation in seconds." ] }, { "cell_type": "code", "execution_count": 11, "id": "c5c6682c", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAArYAAAFGCAYAAACfedxoAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAAsTAAALEwEAmpwYAAAbzElEQVR4nO3df7BfdX3n8df75mJUCAiBRAIJMRh+JRAqd6hbMy3K0qJWhLXTVWYKI6XpFNnGSrvFrTOltdiy1u0W6MhahdplV0trpYLuumjJpEyxNYlGgsUKCgk/En4nKFC83s/+cb9pLzE/7g335pucPB4zmdz7Oef7/b5vxnGec/jcc6q1FgAA2NcN9HsAAACYDMIWAIBOELYAAHSCsAUAoBOELQAAnSBsAQDohMF+D7AnHH744W3+/Pn9HgMAYJdWr179eGvtiO2szxocHPx4ksXZfy9OjiRZNzw8fPFpp5326LYH94uwnT9/flatWtXvMQAAdqmqHtje+uDg4Mdf/epXn3jEEUc8NTAwsF8+iGBkZKQee+yxkzZu3PjxJOdse3x/rX0AgH3N4iOOOGLL/hq1STIwMNCOOOKIzRm9av2jx/fwPAAA7J6B/Tlqt+r9G2y3YYUtAADjct999x1w5plnHnvMMccsPvroo0++4IIL5j333HOVJLfeeuuMGTNmnHrCCSectGDBgkWXXXbZkUly9dVXz7zgggvmjX2f008//fiVK1e+ctv3v+eee152yimnnDBv3rzFb33rWxc8//zzNZH59os9tgAAXTP/8s+fNpnvd/8fvHX1zo6PjIzk3HPPfe3FF1/86PLly+8bHh7O+eeff8wll1xy9A033LAhSYaGhr53++2337tly5aBk08++aTzzjtv80RmeN/73nf0pZdeumnZsmVPnX/++fP++I//+PDf/M3ffGy8r3fFFgCAXbrllltmTJ8+fWT58uVPJMng4GCuu+66DZ/5zGdmbt68+UVNefDBB4+cfPLJz95zzz3Tx/v+IyMjufPOO2e8+93vfipJLrrooiduueWWV01kRmELAMAu3XXXXa9YsmTJs2PXDjvssJGjjjrqhbvvvvtFAbtx48ZpX/va1w489dRTnxvv+2/atGlwxowZPzzggAOSJPPnz39h06ZNL5vIjLYiAAAwKVatWnXQiSeeeNLAwEBbvnz5xqGhoefvvPPOA7d3btWEts+Oi7AFAGCXFi9e/NzNN9986Ni1J598cuDxxx8fPOWUU55fsWLFQVv32I495/DDDx9++umnp41de/rpp6fNnj17eOza7Nmzh5955plpP/jBD3LAAQfk/vvvf9ns2bNfmMiMtiIAALBL55xzzjPPP//8wLXXXjszSYaHh3PJJZfMveiiix496KCDdngbsqVLl35/9erVB61fv34wSVauXPnKF154YeDYY499UbQODAzk9a9//TM33HDDoUly/fXXz/zZn/3Zpycyo7AFAGCXBgYGcvPNN9/713/914cec8wxiw899NBTBwYGctVVV23c2evmzp07fNVVV204++yzF55wwgkn/dqv/drcG2+88TvTpk37kXM/8pGPPHjNNde8et68eYufeuqpweXLlz8+kRmrte7f53doaKh5pC4AsC+oqtWttaFt19euXXv/kiVLJhR6U+m222478MILL1xw00033bd06dJnd/2KybN27drDlyxZMn/bdXtsAQCYsLPOOuv7Dz/88F39nmMsWxEAAOgEYQsAQCcIWwAAOkHYAgDQCcIWAIBOELYAAIzLfffdd8CZZ5557DHHHLP46KOPPvmCCy6Y99xzz1WS3HrrrTNmzJhx6gknnHDSggULFl122WVHJsnVV18984ILLpg39n1OP/3041euXPnKbd//Qx/60BHz5s1bXFWnPfLIIxO+e5fbfQEA7IuuOOS0yX2/zat3dnhkZCTnnnvuay+++OJHly9fft/w8HDOP//8Yy655JKjb7jhhg1JsvWRulu2bBk4+eSTTzrvvPM2T2SEn/qpn/reO97xjs1vetObjt+dH2GPXbGtquur6tGqWjdm7bCquq2qvt37+9DeelXV1VV1b1V9o6peN+Y1F/bO/3ZVXbin5gcA2J/dcsstM6ZPnz6yfPnyJ5JkcHAw11133YbPfOYzMzdv3vyipjz44INHTj755Gfvueee6RP5jDe84Q3PHX/88S/s+szt25NbEf4sydnbrF2e5MuttYVJvtz7PknenGRh78+yJB9NRkM4yW8n+fEkpyf57a0xDADA1LnrrrtesWTJkhc9Yeywww4bOeqoo164++67XxSwGzdunPa1r33twFNPPfW5PTnjHgvb1trKJE9us/z2JJ/sff3JJOeOWf/zNuorSV5VVUcm+Zkkt7XWnmytPZXktvxo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\n", "text/plain": [ "
" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "counts = []\n", "for i, qpu in enumerate(qpus):\n", " \n", " # 1)\n", " qjob = run(qc.decompose().decompose(), qpu, shots = 1000) # non-blocking call\n", "\n", " # 2)\n", " result = qjob.result # bloking call\n", "\n", " # 3)\n", " time = result.time_taken\n", " counts.append(result.counts)\n", "\n", "%matplotlib inline\n", "from qiskit.visualization import plot_histogram\n", "import matplotlib.pyplot as plt\n", "\n", "plot_histogram(counts, figsize = (10, 5), bar_labels=False, legend = [f\"QPU {i}\" for i in range(len(qpus))])" ] }, { "cell_type": "markdown", "id": "74236b95", "metadata": {}, "source": [ "## Complex circuit example\n", "\n", "The following circuit is more complex than the previous one: it has 15 qubits and 10 intermediate measurements. The execution of this circuit is far more expensive than the previous one, as all its shots are executed in only one QPU, i.e., sequentially. " ] }, { "cell_type": "code", "execution_count": 12, "id": "d38536e0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[33m\twarning: [ir.py] Circuit is already in IR format, returning it as is.\n", "\u001b[0m\n", "Result: Time taken: 20.09280778 s.\n" ] } ], "source": [ "import json\n", "\n", "# impoting from examples/circuits/\n", "with open(\"circuits/circuit_15qubits_10layers.json\", \"r\") as file:\n", " circuit = json.load(file)\n", "\n", "qjob = run(circuit, qpus[0], shots = 1000)\n", "\n", "result = qjob.result # bloking call\n", "time = result.time_taken\n", "counts.append(result.counts)\n", "\n", "print(f\"Result: Time taken: {time} s.\")" ] }, { "cell_type": "markdown", "id": "3a29ee22", "metadata": {}, "source": [ "This cost that this circuit has allows us to really display how CUNQA parallelizes the execution of the circuits when sending to the different vQPUs available. So, just as in the previous example, the circuit is executed in every vQPU available." ] }, { "cell_type": "code", "execution_count": 13, "id": "7d72f869", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[33m\twarning: [ir.py] Circuit is already in IR format, returning it as is.\n", "\u001b[0m\n", "\u001b[33m\twarning: [ir.py] Circuit is already in IR format, returning it as is.\n", "\u001b[0m\n", "Time taken to run 2 circuits in parallel: 20.766820907592773 s.\n", "\n", "Time of each execution:\n", "For QJob 0, time taken: 20.749891593 s.\n", "For QJob 1, time taken: 20.213398957 s.\n", "\n", "Removed job(s) with ID(s): \u001b[1;32m377618 \u001b[0m\n" ] } ], "source": [ "import time\n", "\n", "qjobs = []\n", "n = len(qpus)\n", "\n", "tick = time.time()\n", "\n", "for qpu in qpus:\n", " qjobs.append(run(circuit, qpu, shots = 1000))\n", " \n", "results = gather(qjobs) # this is a bloking call\n", "tack = time.time()\n", "\n", "print(f\"Time taken to run {n} circuits in parallel: {tack - tick} s.\")\n", "print(\"\\nTime of each execution:\")\n", "for i, result in enumerate(results):\n", " print(f\"For QJob {i}, time taken: {result.time_taken} s.\")\n", "print()\n", "\n", "qdrop(family)" ] }, { "cell_type": "markdown", "id": "ce72b755", "metadata": {}, "source": [ "The results show how the time taken is (approximately) the same as the previous execution even though the number of the shots executed has been multiplied by the number of the vQPUs available (in this case, duplicated).\n", "\n", "So it can be confirmed that **the circuits were run in parallel**.\n", "\n", "Moreover, the `qdrop()` Python function is called at the end of the program to drop the vQPUs, as they will not be used further. This relinquishes the classical resources employed in the execution of the vQPUs. Just as with the `qraise()`, `qdrop()` possesses a bash command counterpart that performs the same functionality." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.10" } }, "nbformat": 4, "nbformat_minor": 5 }