Skip to content

Commit 962aaa9

Browse files
committed
Fix permute issue?
1 parent f545a1e commit 962aaa9

File tree

4 files changed

+105
-18
lines changed

4 files changed

+105
-18
lines changed

python/quantum-pecos/src/pecos/slr/gen_codes/gen_qasm.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,12 @@ def block_op_loop(self, block) -> None:
125125
if len(block.ops) == 0:
126126
self.write("")
127127
else:
128-
# Save the current permutation map
129-
saved_permutation_map = self.permutation_map.copy()
128+
# Check if this block contains a Permute operation
129+
# If so, we don't want to restore the permutation map
130+
contains_permute = any(type(op).__name__ == "Permute" for op in block.ops if hasattr(op, '__class__'))
131+
132+
# Save the current permutation map if needed
133+
saved_permutation_map = None if contains_permute else self.permutation_map.copy()
130134

131135
for op in block.ops:
132136
# TODO: figure out how to identify Block types without using isinstance
@@ -135,8 +139,9 @@ def block_op_loop(self, block) -> None:
135139
else:
136140
self.write(self.generate_op(op))
137141

138-
# Restore the permutation map
139-
self.permutation_map = saved_permutation_map
142+
# Restore the permutation map if we saved it
143+
if saved_permutation_map is not None:
144+
self.permutation_map = saved_permutation_map
140145

141146
def generate_op(self, op):
142147
op_name = type(op).__name__
@@ -145,12 +150,28 @@ def generate_op(self, op):
145150

146151
if op_name == "Barrier":
147152
stat = True
148-
qubits = (
149-
", ".join(str(q) for q in op.qregs)
150-
if isinstance(op.qregs, list | tuple | set)
151-
else op.qregs
152-
)
153-
153+
# Process barrier operands
154+
barrier_parts = []
155+
for qreg in op.qregs:
156+
if hasattr(qreg, 'sym') and hasattr(qreg, 'elems'): # It's a register
157+
# Check if we need to apply permutation to any qubit in this register
158+
has_permutation = any(
159+
(qreg.sym, i) in self.permutation_map
160+
for i in range(len(qreg.elems))
161+
)
162+
if not has_permutation:
163+
# No permutation, use compact register notation
164+
barrier_parts.append(qreg.sym)
165+
else:
166+
# Has permutation, list individual qubits
167+
for qubit in qreg.elems:
168+
barrier_parts.append(self.apply_permutation(qubit))
169+
elif hasattr(qreg, 'reg') and hasattr(qreg, 'index'): # It's a single qubit
170+
barrier_parts.append(self.apply_permutation(qreg))
171+
else:
172+
barrier_parts.append(str(qreg))
173+
174+
qubits = ", ".join(barrier_parts)
154175
op_str = f"barrier {qubits};"
155176
elif op_name == "Comment":
156177
txt = op.txt.split("\n")
@@ -595,8 +616,10 @@ def qgate_sq_qasm(self, op, repr_str: str | None = None):
595616

596617
for q in op.qargs:
597618
if type(q).__name__ == "QReg":
598-
lines = [f"{repr_str} {qubit};" for qubit in q]
599-
str_list.extend(lines)
619+
# Apply permutation to each qubit in the register
620+
for qubit in q:
621+
q_str = self.apply_permutation(qubit)
622+
str_list.append(f"{repr_str} {q_str};")
600623

601624
elif isinstance(q, tuple):
602625
if len(q) != op.qsize:

python/quantum-pecos/src/pecos/slr/slr_converter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def generate(
3333
add_versions: bool = False,
3434
) -> str:
3535
if target == Language.QASM:
36-
generator = QASMGenerator(skip_headers=skip_headers)
36+
generator = QASMGenerator(skip_headers=skip_headers, add_versions=add_versions)
3737
elif target in [Language.QIR, Language.QIRBC]:
3838
self._check_qir_imported()
3939
generator = QIRGenerator()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Copyright 2025 The PECOS Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
4+
# the License.You may obtain a copy of the License at
5+
#
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
9+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
# specific language governing permissions and limitations under the License.
11+
12+
"""Testing SLR->QASM permute cases."""
13+
14+
from pecos.qeclib import qubit as p
15+
from pecos.slr import Bit, Block, Comment, CReg, If, Main, Permute, QReg, Qubit, Repeat, SlrConverter
16+
17+
from pecos.qeclib.steane.steane_class import Steane
18+
19+
def test_permute1():
20+
prog = Main(
21+
a := Steane("a"),
22+
b := Steane("b"),
23+
meas := CReg("meas", 2),
24+
Permute(a.d,
25+
b.d),
26+
Permute(a.a,
27+
b.a),
28+
a.mx(meas[0]),
29+
b.my(meas[1]),
30+
)
31+
32+
qasm = SlrConverter(prog).qasm()
33+
34+
print(qasm)
35+
36+
# Check that permutation was applied correctly
37+
assert "ry(-pi/2) b_d[0];" in qasm.lower()
38+
assert "measure b_d[0] -> a_raw_meas[0];" in qasm.lower()
39+
assert "rx(-pi/2) a_d[0];" in qasm.lower()
40+
assert "measure a_d[0] -> b_raw_meas[0];" in qasm.lower()
41+
42+
def test_permute2():
43+
def my_permute(a: Steane, b: Steane):
44+
block = Block(
45+
Permute(a.d,b.d),
46+
Permute(a.a, b.a),
47+
)
48+
return block
49+
50+
prog = Main(
51+
a := Steane("a"),
52+
b := Steane("b"),
53+
meas := CReg("meas", 2),
54+
my_permute(a, b),
55+
a.mx(meas[0]),
56+
b.my(meas[1]),
57+
)
58+
59+
qasm = SlrConverter(prog).qasm()
60+
61+
print(qasm)
62+
63+
# Check that permutation was applied correctly
64+
assert "ry(-pi/2) b_d[0];" in qasm.lower()
65+
assert "measure b_d[0] -> a_raw_meas[0];" in qasm.lower()
66+
assert "rx(-pi/2) a_d[0];" in qasm.lower()
67+
assert "measure a_d[0] -> b_raw_meas[0];" in qasm.lower()

python/tests/pecos/regression/test_qasm/random_cases/test_slr_phys.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ def test_bell():
7979
qasm = (
8080
"OPENQASM 2.0;\n"
8181
'include "hqslib1.inc";\n'
82-
f"// Generated using: PECOS version {__version__}\n"
8382
"qreg q[2];\n"
8483
"creg m[2];\n"
8584
"h q[0];\n"
@@ -145,7 +144,6 @@ def __init__(self, q0: Qubit, q1: Qubit, m0: Bit, m1: Bit) -> None:
145144
qasm = (
146145
"OPENQASM 2.0;\n"
147146
'include "hqslib1.inc";\n'
148-
f"// Generated using: PECOS version {__version__}\n"
149147
"qreg q[2];\n"
150148
"creg m[2];\n"
151149
"creg c[4];\n"
@@ -178,7 +176,6 @@ def test_strange_program() -> None:
178176
qasm = (
179177
"OPENQASM 2.0;\n"
180178
'include "hqslib1.inc";\n'
181-
f"// Generated using: PECOS version {__version__}\n"
182179
"qreg q[2];\n"
183180
"creg c[4];\n"
184181
"creg b[4];\n"
@@ -187,7 +184,7 @@ def test_strange_program() -> None:
187184
"c = 3;\n"
188185
"// Here is some injected QASM:\n"
189186
"c = b & 1;\n"
190-
"// Permuting: q[1] -> q[0], q[0] -> q[1]\n"
187+
"// Permutation: q[0] -> q[1], q[1] -> q[0]\n"
191188
"h q[1];"
192189
)
193190

@@ -223,7 +220,7 @@ def test_control_flow_qir():
223220
),
224221
Barrier(q[0], q[1]),
225222
p.F4dg(q[1]),
226-
p.Sdg(q[0]),
223+
p.SZdg(q[0]),
227224
p.CX(q[0], q[1]),
228225
Barrier(q[1], q[0]),
229226
p.RX[0.3](q[0]),

0 commit comments

Comments
 (0)