Multidimensional Angular Model (RGB visualization)

For this notebook, the Pillow python package is required.

[1]:
from qrobot.models import AngularModel

In this notebook we present a 3-dimensional (\(n=3\)) demo for the AngularModel class. For simplicity’s sake, we consider \(\tau = 1\)

[2]:
n = 3
tau = 1

Plotting utils

Before starting, we define some plotting utils for the notebook:

[3]:
from PIL import Image


def data2img(data):
    """Converts normalized input data to a 10x10 color image representation"""
    rgb = [round(d * 255) for d in data]
    return Image.new("RGB", (10, 10), tuple(rgb))
[4]:
import matplotlib.pyplot as plt


class Plotter:
    def __init__(self):

        self.color_list = (
            (0, 0, 0),  # Black
            (255, 0, 0),  # Red
            (0, 255, 0),  # Green
            (255, 255, 0),  # Yellow
            (0, 0, 255),  # Blue
            (255, 0, 255),  # Violet
            (0, 255, 255),  # Cyan
            (255, 255, 255),  # White
        )

        self.states_dict = {
            1: "000",
            2: "001",
            3: "010",
            4: "011",
            5: "100",
            6: "101",
            7: "110",
            8: "111",
        }

    def plot_data(self, data):
        """Plots normalized data in 3d space with the correspondant color representation"""
        fig = plt.figure(figsize=(17, 3))

        # Plot the input color in the RGB space
        ax1 = fig.add_subplot(1, 5, 2, projection="3d")
        # Plot the 3d point
        ax1.scatter(data[0], data[1], data[2], marker="o")
        # Set the axis labels
        ax1.set_xlabel("Dim_1")
        ax1.set_ylabel("Dim_2")
        ax1.set_zlabel("Dim_3")
        # Set the fixed bounds of the axis
        ax1.set_xlim([0, 1])
        ax1.set_ylim([0, 1])
        ax1.set_zlim([0, 1])

        # Plot the actual input color
        ax2 = plt.subplot(1, 5, 4)
        ax2.set_title("Data = {}\n".format(data))
        plt.imshow(data2img(data))

    def plot_result(self, data, counts, shots):
        """Plots the % obtained from the simulation for each basis states"""
        plt.figure(figsize=(15, 1), dpi=150)

        # Plot the input
        axis = plt.subplot(1, 10, 1)
        axis.tick_params(
            axis="both",
            which="both",
            bottom=False,
            top=False,
            left=False,
            right=False,
            labelbottom=False,
            labeltop=False,
            labelleft=False,
            labelright=False,
        )
        axis.set_title("Input")
        axis.set_xlabel("{}".format(data))
        plt.imshow(data2img(data))

        # Plot all the probabilities
        for i in range(0, 8):
            axis = plt.subplot(1, 10, i + 2)
            axis.set_title("{}".format(self.states_dict[i + 1]))
            axis.tick_params(
                axis="both",
                which="both",
                bottom=False,
                top=False,
                left=False,
                right=False,
                labelbottom=False,
                labeltop=False,
                labelleft=False,
                labelright=False,
            )
            try:
                axis.set_xlabel(f"{counts[self.states_dict[i+1]]/shots:%}")
            except KeyError:
                axis.set_xlabel(f"{0:%}")
            img = Image.new("RGB", (10, 10), self.color_list[i])
            plt.imshow(img)
[5]:
plotter = Plotter()

Input definition

We start by defining an arbirary input:

[6]:
input_data = [0.1, 0.5, 0.9]
plotter.plot_data(input_data)
../_images/notebooks_03_multidimensional_angular_model_9_0.png

Encode the input in the model

We initialize the model by instantiating an object with \(n\) and \(\tau\)

[7]:
model = AngularModel(n, tau)

Using the encode method, we encode the event’s tridimensional data in the model. Since we have a multidimensional inputs, two loops are needed -in general- in order to loop through the \(n\) dimensions of the input and then through time. Despite this, we considered \(\tau = 1\), hence only one loop is needed:

[8]:
model.clear()  # to re-initialize the model (allows re-runing this cell without double the encoding)

for dim in range(model.n):
    model.encode(input_data[dim], dim)

The model is implemented by a Qiskit quantum circuit:

[9]:
model.print_circuit()
      ┌──────────┐
q_0: ─┤ Ry(π/10) ├
      ├─────────┬┘
q_1: ─┤ Ry(π/2) ├─
     ┌┴─────────┴┐
q_2: ┤ Ry(9π/10) ├
     └───────────┘
c: 3/═════════════

Given the input we defined above, the model is in the following state:

[10]:
model.plot_state_mat()
../_images/notebooks_03_multidimensional_angular_model_17_0.png

Measurement simulation

We simulate shots measurements, and then we extract the relative frequencies for the \(2^n\) possible basis state outcomes:

[11]:
shots = 1000000
counts = model.measure(shots)

Raw counts for each possible outcome:

[12]:
import json

print("Aggregated binary outcomes of the circuit:")
print(json.dumps(counts, sort_keys=True, indent=4))
Aggregated binary outcomes of the circuit:
{
    "000": 11844,
    "001": 326,
    "010": 11802,
    "011": 299,
    "100": 475907,
    "101": 11986,
    "110": 475766,
    "111": 12070
}

From the raw counts we can obtain the relative frequencies (aka the probabilities) and compare them with the input sequence. Since we have not operated any change of basis (with the model.query(target) method), the canonical basis is maintained, and it is possible to visualize it still with our RGB representation:

[13]:
plotter.plot_result(input_data, counts, shots)
../_images/notebooks_03_multidimensional_angular_model_23_0.png
[ ]: