Displaying information through the execution stack¶

Plugins are very powerful and versatile objects that can be used for various applications.

In this notebook we present a simple way to live-plot optimization processes via some Plugin.

To demonstrate this, we will run a simple QAOA-MAXCUT algorithm using the QLM libraries and plot the trace during the optimization

Writing a widget plugin¶

Lets write a simple widget plugin

In [1]:
%matplotlib notebook
import matplotlib.pyplot as plt
import hashlib  # To hash incoming jobs
from qat.core.plugins import AbstractPlugin


class WidgetPlugin(AbstractPlugin):
    def __init__(self):
        super(WidgetPlugin, self).__init__()
        # Widget
        self.line = None
        self.fig = None
        self.ax = None
        # Data being drawn
        self.x, self.y = None, None
        
    def reset(self):
        """ Initializing a widget """
        self.x = []
        self.y = []
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        line, = ax.plot(self.x, self.y)
        self.widget = line
        self.fig = fig
        self.ax = ax
        self.fig.show()

    def update_plot(self, value):
        """ Updating the current plot"""
        # Updating data
        self.x.append(len(self.x))
        self.y.append(value)
        # Updating widget
        self.widget.set_data(self.x, self.y)
        # Updating axes limits
        self.ax.set_xlim(( 0, len(self.x)))
        self.ax.set_ylim((min(self.y) - 1e-1, max(self.y)+1e-1))
        # Redrawing widget
        self.fig.canvas.draw()

    def compile(self, batch, _):
        return batch

    def post_process(self, batch_result):
        self.update_plot(batch_result.results[0].value)
        return batch_result

Importing the tools we need from the QLM

In [2]:
import networkx as nx
from qat.plugins import ScipyMinimizePlugin
from qat.opt import MaxCut
from qat.qpus import get_default_qpu

Generating a random instance of Max Cut (graph of size 6), Ansatz of depth 2.

In [3]:
graph = nx.random_graphs.erdos_renyi_graph(6, 0.5)
problem = MaxCut(graph)
job = problem.to_job("qaoa", 2)  # '2' is the depth

Defining our execution stack:

  • an optimizer
  • our widget plugin (to catch and plot the energy)
  • LinAlg
In [4]:
display = WidgetPlugin()
stack = ScipyMinimizePlugin(method="COBYLA", tol=1e-3, options={"maxiter": 50}) | display | get_default_qpu()

Calling the reset method sets up a plot, submitting a job will start plotting the energy.

In [5]:
display.reset()
In [6]:
result = stack.submit(job)