Skip to content

1. HTML Visualization

The visualization module includes 3 parts: - A web app that can handle visualization info. - Painter class that helps in building positions, coordinates mapping, and visualization info to send to the app. - OpenQASMParser class, a parser that helps extract useful information from the OpenQASM 2.0 string

Drawing

1.1 Web app (Built with Flask):

The web app is used to handle the visualization info and draw the svg figure on the html

1.1.1 How to start the app

  1. Install Flask: If you haven't install Flask, run: pip install Flask or pip install -r requirements.txt since the Flask package is included in the requirements.txt file

  2. In the html_visualization directory, you can see a file called app.py. Simply run python app.py or run the app.py file on PyCharm IDE.

  3. Open a new tab on Google Chrome, and type in 127.0.0.1:5000 and you will see the app open

Here is how the app looks like at first. Don't worry if you see the page is empty, that's how the web app is initialized. We will get to the part where we send visualization info to the app and it will draw on the svg element.

Drawing

1.2 Painter class:

This class provides useful tools to create positions, mapping, and visualization info that will send to the web app.

1.2.1 Columns class:

  • The Painter class use the Columns class to keep track of the position of operations, registers, and the width of each column.
  • The Columns class is a 2d array with an array columns, and each column is an array has a size equal to the number of registers.
  • When an operation is added, the Columns class will fill with value 1 where the operation is on. Drawing

  • For special case like barriers, every columns before the barrier is filled with -1. This will help to add next operation after the barrier when the Columns find the empty space to add new operation Drawing

  • Columns width: Each column will have a width of the column. This is helpful because sometimes we will want to draw gates that has bigger width than normal gate. The Columns will update the width accordingly when encounter a new width. Drawing

1.3 Draw tutorial

In order to draw, you will need to import the Painter class, the class constructor take no arguement to initialize. Each time you add something new to draw remember to called the function draw(), it's the main function that send visualization info to the web app.

1.3.1 Add register

  1. Fisrt we initialize the Painter class.
  2. Then we called the add_register function, the function takes 3 arguements: reg_name, size, and reg-type. The reg_type default value is 'qreg'. but when we specify 'creg' it will draw classical register instead.
  3. And then called the draw() function, which will send the visualization info to the web app
from graphiq.utils.draw import Painter

painter = Painter()
painter.add_register(reg_name="p", size=4)
painter.add_register(reg_name="c", size=4, reg_type="creg")

"""
The register label positions is stored in the registers_position variable.
The variable store the y coordinates of the label. 
"""
print(painter.registers_position)
painter.draw()
{'qreg': {'p[0]': 50, 'p[1]': 100, 'p[2]': 150, 'p[3]': 200}, 'creg': {'c[4]': 250}}

<Response [200]>

Drawing

1.3.2 Add operations

1.3.2.1 Add gates

Here are some examples, on how to draw gates using the Painter. 1. First, we initialize the Painter, and draw some registers on there. 2. Next, we add some gates using the add_gate function, The function takes 4 arguments: gate_name, qargs, params, and controls.

Note 1. The qargs is a list of label which the gate acts on and however right now multi qargs is not supported, so the function will throw error.

"""Add gates"""
painter = Painter()
painter.add_register(reg_name="p", size=4, reg_type="qreg")
painter.add_register(reg_name="e", size=1, reg_type="qreg")
painter.add_register(reg_name="c", size=4, reg_type="creg")


painter.add_gate(gate_name="H", qargs=["p[0]"])
painter.add_gate(gate_name="CX", qargs=["p[1]"], controls=["e[0]"])
painter.add_gate(gate_name="RX", qargs=["p[0]"], params={"theta": "pi/2"})
painter.add_gate(
    gate_name="RZ", qargs=["p[1]"], params={"theta": "pi/8"}, controls=["e[0]"]
)
painter.draw()
<Response [200]>

Drawing

1.3.2.2 Add measurement

For draw measures, we call the add_measurement to draw it to the web app. The function takes 2 arguments: 1. qreg which is the qreg label that the function will draw on 2. creg which is the creg label that the function will draw to

Here is some example of the how to draw measurements

for i in range(4):
    painter.add_measurement(f"p[{i}]", "c[4]")

painter.draw()
<Response [200]>

Drawing

1.3.2.3 Add barriers

For draw barriers, we call the add_barriers function. The function only takes one argument: qreg, which is a list of qreg labels that the function will draw the barrier on

painter.add_barriers(["p[0]", "p[1]", "p[2]", "p[3]", "e[0]"])
painter.draw()
<Response [200]>

Drawing

1.3.2.4 Add resets

For draw reset, we call the add_reset function. The function only takes one argument qreg, which is a qreg label that the function will draw on

for i in ["e[0]", "p[0]", "p[1]", "p[2]", "p[3]"]:
    painter.add_reset(i)

painter.draw()
<Response [200]>

Drawing

1.3.3 Load OpenQASM example

To be able to draw from openqasm string, the Painter has a function called load_openqasm_str. The function takes an OpenQASM 2.0 string as an input, and will add all the drawing information that need to be draw on the web app.

Here an example, that we draw ghz3 circuit from our benchmarks.circuits

from benchmarks.circuits import *

circuit, state = ghz3_state_circuit()
openqasm = circuit.to_openqasm()

painter = Painter()
painter.load_openqasm_str(openqasm)
painter.draw()
D:\Jobs\Ki3\graph-compiler\graphiq\state.py:251: UserWarning: Stabilizer representation being set is not compared to previously existing representations. Make sure the newrepresentation is consistent with other object representations
  warnings.warn(

<Response [200]>

Drawing