Skip to content

Commit

Permalink
Merge pull request #146 from minatoyuichiro/master
Browse files Browse the repository at this point in the history
update backend
  • Loading branch information
minatoyuichiro authored Apr 17, 2022
2 parents d66d65d + 97e0ba9 commit b492ed4
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 3 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,22 @@ minimizer = vqe.get_scipy_minimizer(method="COBYLA")
result = vqe.Vqe(vqe.QaoaAnsatz(hamiltonian, step), minimizer=minimizer).run()
```

### Circuit Drawing Backend
```python
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')
```

![draw](https://raw.githubusercontent.com/Blueqat/Blueqat/master/draw.png)

### Cloud System Connection (API Key is required)
```python
from bqcloud import register_api
Expand Down
2 changes: 1 addition & 1 deletion blueqat/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@

"""The version of blueqat."""

__version__ = "0.4.10-dev"
__version__ = "0.5.0-dev"
4 changes: 2 additions & 2 deletions blueqat/backends/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
from .qasm_output_backend import QasmOutputBackend
from .ibmq_backend import ibmq_backend
from .sympy_backend import SympyBackend
from .qgate_backend import QgateBackend
from .onequbitgate_transpiler import OneQubitGateCompactionTranspiler
from .twoqubitgate_transpiler import TwoQubitGateDecomposingTranspiler
from .draw_backend import DrawCircuit

BACKENDS = {
"numpy": NumPyBackend,
"numba": numba_backend_lazy,
"qasm_output": QasmOutputBackend,
"ibmq": ibmq_backend,
"sympy_unitary": SympyBackend,
"qgate": QgateBackend,
"2q_decomposition": TwoQubitGateDecomposingTranspiler,
"1q_compaction": OneQubitGateCompactionTranspiler,
"draw": DrawCircuit,
}
DEFAULT_BACKEND_NAME = "numpy"
257 changes: 257 additions & 0 deletions blueqat/backends/draw_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
from .backendbase import Backend
from ..circuit import Circuit
from ..gate import *

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
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
Binary file added draw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b492ed4

Please sign in to comment.