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.
- Load the tool
- Drawing simulator body
- 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>
a = Circuit().x[0]
for i in range(28):
a.x[0]
a.run(backend="draw")
<Figure size 1800x240 with 1 Axes>
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>
It may convenient for machine learning also. Please try it!