{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Displaying information through the execution stack\n", "\n", "Plugins are very powerful and versatile objects that can be used for various applications.\n", "\n", "In this notebook we present a simple way to live-plot optimization processes via some Plugin.\n", "\n", "To demonstrate this, we will run a simple QAOA-MAXCUT algorithm using the QLM libraries and plot the trace during the optimization\n", "\n", "## Writing a widget plugin\n", "\n", "Lets write a simple widget plugin" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2022-11-05T19:42:42.156084Z", "iopub.status.busy": "2022-11-05T19:42:42.155661Z", "iopub.status.idle": "2022-11-05T19:42:42.556169Z", "shell.execute_reply": "2022-11-05T19:42:42.555282Z" } }, "outputs": [], "source": [ "%matplotlib notebook\n", "import matplotlib.pyplot as plt\n", "import hashlib # To hash incoming jobs\n", "from qat.core.plugins import AbstractPlugin\n", "\n", "\n", "class WidgetPlugin(AbstractPlugin):\n", " def __init__(self):\n", " super(WidgetPlugin, self).__init__()\n", " # Widget\n", " self.line = None\n", " self.fig = None\n", " self.ax = None\n", " # Data being drawn\n", " self.x, self.y = None, None\n", " \n", " def reset(self):\n", " \"\"\" Initializing a widget \"\"\"\n", " self.x = []\n", " self.y = []\n", " fig = plt.figure()\n", " ax = fig.add_subplot(1, 1, 1)\n", " line, = ax.plot(self.x, self.y)\n", " self.widget = line\n", " self.fig = fig\n", " self.ax = ax\n", " self.fig.show()\n", "\n", " def update_plot(self, value):\n", " \"\"\" Updating the current plot\"\"\"\n", " # Updating data\n", " self.x.append(len(self.x))\n", " self.y.append(value)\n", " # Updating widget\n", " self.widget.set_data(self.x, self.y)\n", " # Updating axes limits\n", " self.ax.set_xlim(( 0, len(self.x)))\n", " self.ax.set_ylim((min(self.y) - 1e-1, max(self.y)+1e-1))\n", " # Redrawing widget\n", " self.fig.canvas.draw()\n", "\n", " def compile(self, batch, _):\n", " return batch\n", "\n", " def post_process(self, batch_result):\n", " self.update_plot(batch_result.results[0].value)\n", " return batch_result" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Importing the tools we need from the QLM" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2022-11-05T19:42:42.559782Z", "iopub.status.busy": "2022-11-05T19:42:42.559414Z", "iopub.status.idle": "2022-11-05T19:42:43.014807Z", "shell.execute_reply": "2022-11-05T19:42:43.014078Z" } }, "outputs": [], "source": [ "import networkx as nx\n", "from qat.plugins import ScipyMinimizePlugin\n", "from qat.vsolve.qaoa import MaxCut\n", "from qat.qpus import get_default_qpu" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Generating a random instance of Max Cut (graph of size 6), Ansatz of depth 2." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2022-11-05T19:42:43.018412Z", "iopub.status.busy": "2022-11-05T19:42:43.018087Z", "iopub.status.idle": "2022-11-05T19:42:43.045241Z", "shell.execute_reply": "2022-11-05T19:42:43.044680Z" } }, "outputs": [], "source": [ "graph = nx.random_graphs.erdos_renyi_graph(6, 0.5)\n", "problem = MaxCut(graph)\n", "job = problem.to_job(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Defining our execution stack: \n", "* an optimizer\n", "* our widget plugin (to catch and plot the energy)\n", "* LinAlg\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2022-11-05T19:42:43.048339Z", "iopub.status.busy": "2022-11-05T19:42:43.047829Z", "iopub.status.idle": "2022-11-05T19:42:43.051495Z", "shell.execute_reply": "2022-11-05T19:42:43.050975Z" } }, "outputs": [], "source": [ "display = WidgetPlugin()\n", "stack = ScipyMinimizePlugin(method=\"COBYLA\", tol=1e-3, options={\"maxiter\": 50}) | display | get_default_qpu()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calling the reset method sets up a plot, submitting a job will start plotting the energy." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2022-11-05T19:42:43.054408Z", "iopub.status.busy": "2022-11-05T19:42:43.053960Z", "iopub.status.idle": "2022-11-05T19:42:43.096415Z", "shell.execute_reply": "2022-11-05T19:42:43.095882Z" } }, "outputs": [], "source": [ "display.reset()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": { "iopub.execute_input": "2022-11-05T19:42:43.112380Z", "iopub.status.busy": "2022-11-05T19:42:43.111957Z", "iopub.status.idle": "2022-11-05T19:42:45.343781Z", "shell.execute_reply": "2022-11-05T19:42:45.343231Z" } }, "outputs": [], "source": [ "result = stack.submit(job)" ] } ], "metadata": { "authors": [ "Simon Martiel" ], "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.10.4" }, "tags": [ "variational" ] }, "nbformat": 4, "nbformat_minor": 2 }