Skip to content

Commit a6552cc

Browse files
feat: added function to give quirk url from a qualtran's bloq
1 parent af8592b commit a6552cc

2 files changed

Lines changed: 120 additions & 0 deletions

File tree

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import subprocess
2+
3+
from qualtran import Bloq, DecomposeTypeError
4+
from qualtran.bloqs.bookkeeping import Join, Split
5+
from qualtran.drawing import (
6+
ModPlus,
7+
Circle,
8+
LarrowTextBox,
9+
RarrowTextBox,
10+
LineManager,
11+
get_musical_score_data,
12+
)
13+
14+
15+
class SparseLineManager(LineManager):
16+
"""
17+
LineManager which keeps partitioned line slots reserved for them until they need it again
18+
"""
19+
20+
# DIDN'TDO: only handles partition patterns of the type (QAny(n)/QUInt(n)/... -> QBit((n,)) or QBit((n,)) -> QAny(n))
21+
22+
def maybe_reserve(self, binst, reg, idx):
23+
if binst.bloq_is(Join) and reg.shape:
24+
25+
def _keep_split_lines(binst_to_check, reg_to_check):
26+
binst_cond = binst_to_check.bloq == binst.bloq.adjoint()
27+
reg_cond = reg_to_check == reg.adjoint()
28+
return binst_cond and reg_cond
29+
30+
self.reserve_n(1, _keep_split_lines)
31+
32+
if binst.bloq_is(Split) and not reg.shape:
33+
34+
def _keep_joined_line(binst_to_check, reg_to_check):
35+
binst_cond = binst_to_check.bloq == binst.bloq.adjoint()
36+
reg_cond = reg_to_check == reg.adjoint()
37+
return binst_cond and reg_cond
38+
39+
self.reserve_n(1, _keep_joined_line)
40+
41+
42+
handled_operations = {
43+
ModPlus(): '"X"',
44+
Circle(filled=True): '"•"',
45+
Circle(filled=False): '"◦"',
46+
LarrowTextBox(text='∧'): '"X"',
47+
RarrowTextBox(text='∧'): '"X"',
48+
}
49+
50+
51+
def bloq_to_quirk(
52+
bloq: Bloq,
53+
line_manager: LineManager = SparseLineManager().__init__(), # type: ignore[misc]
54+
open_quirk=False,
55+
) -> str:
56+
"""Convert a Bloq into a Quirk circuit URL.
57+
58+
The input bloq is decomposed and flattened before conversion. Only a limited set
59+
of operations is currently supported: control, anti-control, and NOT.
60+
61+
Args:
62+
bloq: The bloq to export to Quirk.
63+
line_manager: Line manager used to assign and order circuit lines.
64+
open_quirk: If True, opens the generated URL in Firefox.
65+
66+
Returns:
67+
A URL encoding the corresponding Quirk circuit.
68+
"""
69+
try:
70+
flat_bloq = bloq.decompose_bloq().flatten()
71+
except DecomposeTypeError: # no need to flatten the bloq if it is atomic
72+
flat_bloq = bloq.as_composite_bloq()
73+
msd = get_musical_score_data(flat_bloq, manager=line_manager)
74+
75+
sparse_circuit = [(['1'] * (msd.max_y + 1)).copy() for _ in range(msd.max_x)]
76+
for soq in msd.json_dict()['soqs']:
77+
try:
78+
gate = handled_operations[soq.symb]
79+
sparse_circuit[soq.rpos.seq_x][soq.rpos.y] = gate
80+
except KeyError:
81+
None
82+
83+
circuit = list(filter((['1'] * (msd.max_y + 1)).__ne__, sparse_circuit))
84+
nb_deleted_lines = 0
85+
for i in range(
86+
msd.max_y + 1
87+
): # deleting lines of the circuit which are not used (happens with partition)
88+
ind = i - nb_deleted_lines
89+
for col in circuit:
90+
line_is_useless = col[ind] == '1'
91+
if not line_is_useless:
92+
break
93+
if line_is_useless:
94+
for col in circuit:
95+
col.pop(ind)
96+
nb_deleted_lines += 1
97+
98+
quirk_url = "https://algassert.com/quirk"
99+
start = '#circuit={"cols":['
100+
end = ']}'
101+
url = quirk_url + start + ','.join('[' + ','.join(col) + ']' for col in circuit) + end
102+
103+
if open_quirk:
104+
subprocess.run(["firefox", url], check=False)
105+
106+
return url
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from qualtran import QUInt
2+
from qualtran.bloqs.basic_gates import Toffoli
3+
from qualtran.bloqs.mcmt import MultiTargetCNOT
4+
from qualtran.bloqs.arithmetic.addition import Add
5+
from qualtran.quirk_interop.bloq_to_quirk import bloq_to_quirk
6+
7+
8+
def test_bloq_to_quirk():
9+
bloq_to_quirk(Add(QUInt(5)))
10+
bloq_to_quirk(MultiTargetCNOT(5))
11+
12+
13+
def test_bloq_to_quirk_on_atomic():
14+
bloq_to_quirk(Toffoli())

0 commit comments

Comments
 (0)