From e3ebf05a0731524c03be533028648381499d841f Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 29 Oct 2024 15:17:00 +0100 Subject: [PATCH 1/2] Improve QASM parser to handle multi-character register names --- pyzx/circuit/qasmparser.py | 18 ++++++++++++++++-- tests/test_qasm.py | 17 +++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/pyzx/circuit/qasmparser.py b/pyzx/circuit/qasmparser.py index a92341ea..25f2fa44 100644 --- a/pyzx/circuit/qasmparser.py +++ b/pyzx/circuit/qasmparser.py @@ -140,7 +140,18 @@ def extract_command_parts(self, c: str) -> Tuple[str,List[Fraction],List[str]]: def parse_command(self, c: str, registers: Dict[str,Tuple[int,int]]) -> List[Gate]: gates: List[Gate] = [] name, phases, args = self.extract_command_parts(c) - if name in ("barrier","creg","measure", "id"): return gates + if name in ("barrier","creg", "id"): return gates + if name == "measure": + target, result_bit = args[0].split(' -> ') + # Extract the register name and index separately for both target and result + target_reg, target_idx = target.split('[') + result_reg, result_idx = result_bit.split('[') + # Remove the trailing ']' and convert to int + target_qbit = int(target_idx[:-1]) + result_bit = int(result_idx[:-1]) + gate = Measurement(target_qbit, result_bit) + gates.append(gate) + return gates if name in ("opaque", "if"): raise TypeError("Unsupported operation {}".format(c)) if name == "qreg": @@ -154,9 +165,12 @@ def parse_command(self, c: str, registers: Dict[str,Tuple[int,int]]) -> List[Gat dim = 1 for a in args: if "[" in a: + # Split at the first '[' to handle multi-character register names regname, valp = a.split("[",1) + # Remove the trailing ']' before converting to int val = int(valp[:-1]) - if regname not in registers: raise TypeError("Invalid register {}".format(regname)) + if regname not in registers: + raise TypeError("Invalid register {}".format(regname)) qubit_values.append([registers[regname][0]+val]) else: if is_range: diff --git a/tests/test_qasm.py b/tests/test_qasm.py index 128569f5..eb0639f4 100644 --- a/tests/test_qasm.py +++ b/tests/test_qasm.py @@ -80,6 +80,23 @@ def test_parse_qasm3(self): self.assertEqual(c.qubits, qasm3.qubits) self.assertListEqual(c.gates, qasm3.gates) + + def test_parse_qasm3_long_creg(self): + qasm3 = Circuit.from_qasm(""" + OPENQASM 3; + include "stdgates.inc"; + qubit[3] q1; + cx q1[0], q1[1]; + s q1[2]; + cx q1[2], q1[1]; + """) + c = Circuit(3) + c.add_gate("CNOT", 0, 1) + c.add_gate("S", 2) + c.add_gate("CNOT", 2, 1) + self.assertEqual(c.qubits, qasm3.qubits) + self.assertListEqual(c.gates, qasm3.gates) + def test_load_qasm_from_file(self): c = Circuit(1) c.add_gate("YPhase", 0, Fraction(1, 4)) From 48c8f5f74b471f6f901c3a705779ea026050b8b7 Mon Sep 17 00:00:00 2001 From: Liam Hurwitz Date: Thu, 19 Dec 2024 17:11:13 +0100 Subject: [PATCH 2/2] Fix mypy error by creating a new variable. Add Measurement import --- pyzx/circuit/qasmparser.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyzx/circuit/qasmparser.py b/pyzx/circuit/qasmparser.py index 25f2fa44..2f9ca90a 100644 --- a/pyzx/circuit/qasmparser.py +++ b/pyzx/circuit/qasmparser.py @@ -21,7 +21,7 @@ from typing import List, Dict, Tuple, Optional from . import Circuit -from .gates import Gate, qasm_gate_table +from .gates import Gate, qasm_gate_table, Measurement from ..utils import settings @@ -144,12 +144,12 @@ def parse_command(self, c: str, registers: Dict[str,Tuple[int,int]]) -> List[Gat if name == "measure": target, result_bit = args[0].split(' -> ') # Extract the register name and index separately for both target and result - target_reg, target_idx = target.split('[') - result_reg, result_idx = result_bit.split('[') + _, target_idx = target.split('[') + _, result_idx = result_bit.split('[') # Remove the trailing ']' and convert to int target_qbit = int(target_idx[:-1]) - result_bit = int(result_idx[:-1]) - gate = Measurement(target_qbit, result_bit) + result_register = int(result_idx[:-1]) + gate = Measurement(target_qbit, result_register) gates.append(gate) return gates if name in ("opaque", "if"):