common.title

Docs
Quantum Circuit
TYTAN CLOUD

QUANTUM GAMING


Overview
Terms of service

Privacy policy

Contact
Research

Sign in
Sign up
common.title

New circuit drawing backend for blueqat

Yuichiro Minato

2022/04/17 00:29

Hi, I am developing an app for a quantum computer and would like to check the quantum circuit. one of the weak points of blueqat is that it does not have a drawing system.

By the way, you can use drawing using Qiskit at

.run_with_ibmq(returns='draw', output='mpl')

To use a new blueqat drawing tool, please copy and paste the following.

  1. Load the tool
  2. Drawing simulator body
  3. Register as a backend. This time, we registered a backend called draw.

In the future, we will register it as an official backend of blueqat and update it for easy installation.

import numpy as np
from blueqat.backends.backendbase import Backend
from blueqat import BlueqatGlobalSetting
from blueqat import Circuit
import networkx as nx
import matplotlib.pyplot as plt
import math

class DrawCircuit(Backend):
    """Backend for draw output."""
    
    def _preprocess_run(self, gates, n_qubits, args, kwargs):
        qlist = {}
        flg = 0
        time = 0
        add_edge = []
        remove_edge = []

        for i in range(n_qubits):
            qlist[i] = [{'num': flg, 'gate': 'q'+str(i), 'angle': '', 'xpos': 0, 'ypos': i, 'type': 'qubit'}]
            flg += 1
        
        time += 1
        return gates, (qlist, n_qubits, [flg], [time], add_edge, remove_edge)

    def _postprocess_run(self, ctx):
        #color_code
        color_gate = {}
        color_gate['X'] = color_gate['Y'] = color_gate['Z'] = '#0BB0E2'
        color_gate['RX'] = color_gate['RY'] = color_gate['RZ'] = '#FCD000'
        color_gate['H'] = color_gate['T'] = color_gate['S'] = '#E6000A'
        color_gate['M'] = 'white'
        
        qlist = ctx[0]
        n_qubits = ctx[1]
        flg = ctx[2][-1]
        time = ctx[3][-1]
        
        #measurement
        for i in range(n_qubits):
            qlist[i].append({'num': flg, 'gate': 'M', 'angle': '', 'xpos': 30, 'ypos': i + math.floor((time-1)/30)*(n_qubits+1), 'type': 'measurement'})
            flg += 1
        
        G = nx.Graph()

        for i in range(n_qubits):
            for j in range(len(qlist[i])-1):
                G.add_edge(qlist[i][j]['num'], qlist[i][j+1]['num'])
        
        #twoqubit connections
        for item in ctx[4]:
            G.add_edge(item[0], item[1])

        for item in ctx[5]:
            G.remove_edge(item[0], item[1])

        #image size
        plt.figure(1, figsize=(30, (n_qubits+1)*(math.floor(time/30)+1)), dpi=60)

        labels = {}
        colors = {}
        angles = {}
        sizes = {}

        for i in range(n_qubits):
            for j in range(len(qlist[i])):
                angles[qlist[i][j]['num']] = qlist[i][j]['angle']
                labels[qlist[i][j]['num']] = qlist[i][j]['gate']
                sizes[qlist[i][j]['num']] = 1200
                if qlist[i][j]['type'] == 'dummy':
                    colors[qlist[i][j]['num']] = 'white'
                    sizes[qlist[i][j]['num']] = 0
                elif qlist[i][j]['gate'] == '' or qlist[i][j]['gate'] == 'CZ':
                    colors[qlist[i][j]['num']] = 'black'
                    sizes[qlist[i][j]['num']] = 100
                elif qlist[i][j]['type'] == 'qubit':
                    colors[qlist[i][j]['num']] = 'white'
                else:
                    colors[qlist[i][j]['num']] = color_gate[qlist[i][j]['gate']]

        
        #position
        pos = {}
        for i in range(n_qubits):
            for j in range(len(qlist[i])):
                pos[qlist[i][j]['num']] = (qlist[i][j]['xpos'], (n_qubits+1)*(math.floor(time/30)+1) - qlist[i][j]['ypos'])

        #dummy qubit just for top and bottom margin
        labels[flg]= ''
        colors[flg] = 'black'
        sizes[flg] = 0
        pos[flg] = (0, (n_qubits+1)*(math.floor(time/30)+1)+1)
        G.add_node(flg)
        labels[flg+1]= ''
        colors[flg+1] = 'black'
        sizes[flg+1] = 0
        pos[flg+1] = (0, 1)
        G.add_node(flg+1)
       
        nx.set_node_attributes(G, labels, 'label')
        nx.set_node_attributes(G, colors, 'color')
        nx.set_node_attributes(G, angles, 'angle')
        nx.set_node_attributes(G, sizes, 'size')

        options = {
            "font_size": 12,
            "edgecolors": "black",
            "linewidths": 2,
            "width": 2,
        }

        node_labels = nx.get_node_attributes(G, 'label')
        node_colors = [colors[i] for i in nx.get_node_attributes(G, 'color')]
        node_sizes = [sizes[i] for i in nx.get_node_attributes(G, 'size')]
        nx.draw_networkx(G, pos, labels = node_labels, node_color = node_colors, node_size = node_sizes, **options)

        #label positions for angles
        pos_attrs = pos.copy()
        for i in pos_attrs:
            pos_attrs[i] = (pos_attrs[i][0]+0.4, pos_attrs[i][1]-0.4)
    
        node_attrs = nx.get_node_attributes(G, 'angle')
        custom_node_attrs = {}

        for node, attr in node_attrs.items():
            custom_node_attrs[node] = attr

        nx.draw_networkx_labels(G, pos_attrs, labels = custom_node_attrs, font_size=9)
        #plt.axis('off')
        plt.show()
        
        return 

    def _one_qubit_gate_noargs(self, gate, ctx):
        flg = ctx[2][-1]
        time = ctx[3][-1]
        qlist = ctx[0]
        
        time_adjust = time%30
        if time_adjust == 0:
            for i in range(ctx[1]):
                ypos_adjust = i + (math.floor(time/30)-1)*(ctx[1]+1)
                qlist[i].append({'num': flg, 'gate': '', 'angle': '', 'xpos': 30, 'ypos': ypos_adjust, 'type': 'dummy'})
                flg += 1
            time += 1
            
            for i in range(ctx[1]):
                ypos_adjust = i + math.floor(time/30)*(ctx[1]+1)
                qlist[i].append({'num': flg, 'gate': '', 'angle': '', 'xpos': 0, 'ypos': ypos_adjust, 'type': 'dummy'})
                flg += 1
                ctx[5].append((flg-1, flg-1-ctx[1]))
        
        time_adjust = time%30
        for idx in gate.target_iter(ctx[1]):
            ypos_adjust = idx + math.floor(time/30)*(ctx[1]+1)
            qlist[idx].append({'num': flg, 'gate': gate.lowername.upper(), 'angle': '', 'xpos': time_adjust, 'ypos': ypos_adjust, 'type': 'gate'})
            flg += 1
        ctx[2].append(flg)
        ctx[3].append(time+1)
        return ctx

    gate_x = _one_qubit_gate_noargs
    gate_y = _one_qubit_gate_noargs
    gate_z = _one_qubit_gate_noargs
    gate_h = _one_qubit_gate_noargs
    gate_t = _one_qubit_gate_noargs
    gate_s = _one_qubit_gate_noargs
    
    def _one_qubit_gate_args_theta(self, gate, ctx):
        flg = ctx[2][-1]
        time = ctx[3][-1]
        qlist = ctx[0]
        
        time_adjust = time%30
        if time_adjust == 0:
            for i in range(ctx[1]):
                ypos_adjust = i + (math.floor(time/30)-1)*(ctx[1]+1)
                qlist[i].append({'num': flg, 'gate': '', 'angle': '', 'xpos': 30, 'ypos': ypos_adjust, 'type': 'dummy'})
                flg += 1
            time += 1
            
            for i in range(ctx[1]):
                ypos_adjust = i + math.floor(time/30)*(ctx[1]+1)
                qlist[i].append({'num': flg, 'gate': '', 'angle': '', 'xpos': 0, 'ypos': ypos_adjust, 'type': 'dummy'})
                flg += 1
                ctx[5].append((flg-1, flg-1-ctx[1]))
        
        time_adjust = time%30
        for idx in gate.target_iter(ctx[1]):
            ypos_adjust = idx + math.floor(time/30)*(ctx[1]+1)
            qlist[idx].append({'num': flg, 'gate': gate.lowername.upper(), 'angle': round(gate.theta, 2), 'xpos': time_adjust, 'ypos': ypos_adjust, 'type': 'gate'})
            flg += 1
        ctx[2].append(flg)
        ctx[3].append(time+1)
        return ctx

    gate_rx = _one_qubit_gate_args_theta
    gate_ry = _one_qubit_gate_args_theta
    gate_rz = _one_qubit_gate_args_theta
    gate_phase = _one_qubit_gate_args_theta

    def gate_i(self, gate, ctx):
        time = ctx[3][-1]
        ctx[3].append(time+1)
        return ctx
    
    def _two_qubit_gate_noargs(self, gate, ctx):
        flg = ctx[2][-1]
        time = ctx[3][-1]
        qlist = ctx[0]
        
        tg = ''
        if gate.lowername == 'cx':
            tg = 'x'
        elif gate.lowername == 'cy':
            tg = 'y'
        elif gate.lowername == 'cz':
            tg = 'z'

        time_adjust = time%30
        if time_adjust == 0:
            for i in range(ctx[1]):
                ypos_adjust = i + (math.floor(time/30)-1)*(ctx[1]+1)
                qlist[i].append({'num': flg, 'gate': '', 'angle': '', 'xpos': 30, 'ypos': ypos_adjust, 'type': 'dummy'})
                flg += 1
            time += 1
            
            for i in range(ctx[1]):
                ypos_adjust = i + math.floor(time/30)*(ctx[1]+1)
                qlist[i].append({'num': flg, 'gate': '', 'angle': '', 'xpos': 0, 'ypos': ypos_adjust, 'type': 'dummy'})
                flg += 1
                ctx[5].append((flg-1, flg-1-ctx[1]))

        time_adjust = time%30        
        for control, target in gate.control_target_iter(ctx[1]):
            qlist[target].append({'num': flg, 'gate': tg.upper(), 'angle': '', 'xpos': time_adjust, 'ypos': target + math.floor(time/30)*(ctx[1]+1), 'type': 'gate'})
            flg += 1
            qlist[control].append({'num': flg, 'gate': '', 'angle': '', 'xpos': time_adjust, 'ypos': control + math.floor(time/30)*(ctx[1]+1), 'type': 'gate'})
            flg += 1
            ctx[4].append((flg-2, flg-1))
        ctx[2].append(flg)
        ctx[3].append(time+1)
        return ctx
    
    gate_cx = gate_cy = gate_cz = _two_qubit_gate_noargs

    def _three_qubit_gate_noargs(self, gate, ctx):
        return ctx

    gate_ccx = _three_qubit_gate_noargs
    gate_cswap = _three_qubit_gate_noargs

    def gate_measure(self, gate, ctx):
        return ctx

    gate_reset = _one_qubit_gate_noargs
    
BlueqatGlobalSetting.register_backend('draw', DrawCircuit)

for a moment you can use this function as

Circuit().h[0].cx[0,1].run(backend="draw")

if you want to calcurate and draw,

a = Circuit().h[0].cx[0,1]
a.run(backend="draw")
a.m[:].run(shots=1000)

Let's try some tutorials

Circuit(7).i[:].x[:5].x[2,4].x[2:5].i[:].x[:5].i[:].x[1:5].x[4].x[1:5].i[:].rx(0)[2:4].rx(0)[1,2,4].rx(0)[1,2,4].rx(0)[2,4].i[:].x[2:4].x[1,4].x[1,4].x[2:7].i[:].x[2:4].x[1,4].x[1,4].x[2:5].x[1].x[0:5].x[1,4].run(backend="draw")
<Figure size 1800x480 with 1 Axes>

image

a = Circuit().x[0]
for i in range(28):
    a.x[0]
a.run(backend="draw")
<Figure size 1800x240 with 1 Axes>

image

You can get the circuit from QAOA as result.circuit

from blueqat import vqe
from blueqat.pauli import *
from blueqat.pauli import qubo_bit as q

#hamiltonian = q(0)-3*q(1)+2*q(0)*q(1)+3*q(2)*q(3)+q(4)*q(7)
hamiltonian = Z[0]-3*Z[1]+2*Z[0]*Z[1]+3*Z[2]*Z[3]+Z[4]
step = 8

result = vqe.Vqe(vqe.QaoaAnsatz(hamiltonian, step)).run()
result.circuit.run(backend='draw')
<Figure size 1800x1080 with 1 Axes>

image

It may convenient for machine learning also. Please try it!

© 2025, blueqat Inc. All rights reserved