From 8bdef2067d55034b454de5c2ee814e6279998452 Mon Sep 17 00:00:00 2001 From: Emlyn Graham Date: Fri, 30 Jan 2026 14:27:31 +0100 Subject: [PATCH 1/3] fixed angles --- graphix_qasm_parser/parser.py | 45 ++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/graphix_qasm_parser/parser.py b/graphix_qasm_parser/parser.py index 16e1953..d7a996e 100644 --- a/graphix_qasm_parser/parser.py +++ b/graphix_qasm_parser/parser.py @@ -35,6 +35,7 @@ def rad_to_angle(angle: float) -> float: CZ = SWAP else: + ANGLE_PI = 1.0 try: from graphix.instruction import CZ except ImportError: @@ -49,6 +50,8 @@ def CZ(_q0: int, _q1: int) -> None: # noqa: N802 except ImportError: # Compatibility with graphix <= 0.3.3 # See https://github.com/TeamGraphix/graphix/pull/399 + ANGLE_PI = math.pi + def rad_to_angle(angle: float) -> float: """In older versions of graphix (<= 0.3.3), instruction angles were expressed in radians.""" return angle @@ -278,7 +281,9 @@ def __init__(self, parser: OpenQASMParser) -> None: } @override - def visitOldStyleDeclarationStatement(self, ctx: qasm3Parser.OldStyleDeclarationStatementContext) -> None: + def visitOldStyleDeclarationStatement( + self, ctx: qasm3Parser.OldStyleDeclarationStatementContext + ) -> None: decl_class: type[_Bit | _Qubit] kind = ctx.getChild(0) if kind.symbol.type == qasm3Parser.QREG: @@ -293,13 +298,17 @@ def visitOldStyleDeclarationStatement(self, ctx: qasm3Parser.OldStyleDeclaration self.declare_registers(ctx, decl_class, identifier, designator) @override - def visitQuantumDeclarationStatement(self, ctx: qasm3Parser.QuantumDeclarationStatementContext) -> None: + def visitQuantumDeclarationStatement( + self, ctx: qasm3Parser.QuantumDeclarationStatementContext + ) -> None: designator = ctx.qubitType().designator() # type: ignore[no-untyped-call] identifier = ctx.Identifier().getText() # type: ignore[no-untyped-call] self.declare_registers(ctx, _Qubit, identifier, designator) @override - def visitConstDeclarationStatement(self, ctx: qasm3Parser.ConstDeclarationStatementContext) -> None: + def visitConstDeclarationStatement( + self, ctx: qasm3Parser.ConstDeclarationStatementContext + ) -> None: identifier = ctx.Identifier().getText() # type: ignore[no-untyped-call] value = ctx.declarationExpression() # type: ignore[no-untyped-call] expr = self.evaluate_expression(value) @@ -310,11 +319,13 @@ def visitGateCallStatement(self, ctx: qasm3Parser.GateCallStatementContext) -> N gate = ctx.Identifier().getText() # type: ignore[no-untyped-call] operand_list = ctx.gateOperandList() # type: ignore[no-untyped-call] operands = [ - self.convert_qubit_index(operand_list.getChild(i)) for i in range(0, operand_list.getChildCount(), 2) + self.convert_qubit_index(operand_list.getChild(i)) + for i in range(0, operand_list.getChildCount(), 2) ] if expr_list := ctx.expressionList(): # type: ignore[no-untyped-call] exprs = [ - float(self.evaluate_expression(expr_list.getChild(i))) for i in range(0, expr_list.getChildCount(), 2) + float(self.evaluate_expression(expr_list.getChild(i))) + for i in range(0, expr_list.getChildCount(), 2) ] else: exprs = [] @@ -324,7 +335,9 @@ def visitGateCallStatement(self, ctx: qasm3Parser.GateCallStatementContext) -> N instruction = CCX(target=operands[2], controls=(operands[0], operands[1])) elif gate == "crz": # https://openqasm.com/language/standard_library.html#crz - instruction = RZZ(target=operands[1], control=operands[0], angle=rad_to_angle(exprs[0])) + instruction = RZZ( + target=operands[1], control=operands[0], angle=rad_to_angle(exprs[0]) + ) elif gate == "cx": # https://openqasm.com/language/standard_library.html#cx instruction = CNOT(target=operands[1], control=operands[0]) @@ -433,7 +446,9 @@ def parse(self, expr: qasm3Parser.ExpressionContext) -> _Value: return value @override - def visitParenthesisExpression(self, ctx: qasm3Parser.ParenthesisExpressionContext) -> _Value: + def visitParenthesisExpression( + self, ctx: qasm3Parser.ParenthesisExpressionContext + ) -> _Value: expr: qasm3Parser.ExpressionContext = ctx.expression() # type: ignore[no-untyped-call] return self.parse(expr) @@ -450,15 +465,21 @@ def visitUnaryExpression(self, ctx: qasm3Parser.UnaryExpressionContext) -> _Valu raise NotImplementedError(msg) @override - def visitAdditiveExpression(self, ctx: qasm3Parser.AdditiveExpressionContext) -> _Value: + def visitAdditiveExpression( + self, ctx: qasm3Parser.AdditiveExpressionContext + ) -> _Value: return self.parse_binary_operator(ctx) @override - def visitMultiplicativeExpression(self, ctx: qasm3Parser.MultiplicativeExpressionContext) -> _Value: + def visitMultiplicativeExpression( + self, ctx: qasm3Parser.MultiplicativeExpressionContext + ) -> _Value: return self.parse_binary_operator(ctx) @override - def visitLiteralExpression(self, ctx: qasm3Parser.LiteralExpressionContext) -> _Value: + def visitLiteralExpression( + self, ctx: qasm3Parser.LiteralExpressionContext + ) -> _Value: literal = ctx.getChild(0) if literal.symbol.type == qasm3Parser.DecimalIntegerLiteral: return _Int(ctx, int(literal.symbol.text)) @@ -472,7 +493,9 @@ def visitLiteralExpression(self, ctx: qasm3Parser.LiteralExpressionContext) -> _ raise NotImplementedError(msg) def parse_binary_operator( - self, ctx: qasm3Parser.AdditiveExpressionContext | qasm3Parser.MultiplicativeExpressionContext + self, + ctx: qasm3Parser.AdditiveExpressionContext + | qasm3Parser.MultiplicativeExpressionContext, ) -> _Value: lhs_expr: qasm3Parser.ExpressionContext = ctx.getChild(0) rhs_expr: qasm3Parser.ExpressionContext = ctx.getChild(2) From d83763bc5dbc0c44203bd475bf6ad3845ed6d96d Mon Sep 17 00:00:00 2001 From: Emlyn Graham Date: Fri, 30 Jan 2026 14:49:58 +0100 Subject: [PATCH 2/3] fixed CI for PR --- README.md | 3 ++- graphix_qasm_parser/parser.py | 41 ++++++++++------------------------- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index e5fd030..b5f331d 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,9 @@ circuit = parser.parse_file("my_circuit.qasm") |------------------------------------------------------------------|---------------------| | [ccx](https://openqasm.com/language/standard_library.html#ccx) | CCX | | [crz](https://openqasm.com/language/standard_library.html#crz) | RZZ | -| [cx](https://openqasm.com/language/standard_library.html#cx) | CX | +| [cx](https://openqasm.com/language/standard_library.html#cx) | CNOT | | [swap](https://openqasm.com/language/standard_library.html#swap) | SWAP | +| [swap](https://openqasm.com/language/standard_library.html#cz) | CZ | | [h](https://openqasm.com/language/standard_library.html#h) | H | | [s](https://openqasm.com/language/standard_library.html#s) | S | | [x](https://openqasm.com/language/standard_library.html#x) | X | diff --git a/graphix_qasm_parser/parser.py b/graphix_qasm_parser/parser.py index d7a996e..fe593f8 100644 --- a/graphix_qasm_parser/parser.py +++ b/graphix_qasm_parser/parser.py @@ -281,9 +281,7 @@ def __init__(self, parser: OpenQASMParser) -> None: } @override - def visitOldStyleDeclarationStatement( - self, ctx: qasm3Parser.OldStyleDeclarationStatementContext - ) -> None: + def visitOldStyleDeclarationStatement(self, ctx: qasm3Parser.OldStyleDeclarationStatementContext) -> None: decl_class: type[_Bit | _Qubit] kind = ctx.getChild(0) if kind.symbol.type == qasm3Parser.QREG: @@ -298,17 +296,13 @@ def visitOldStyleDeclarationStatement( self.declare_registers(ctx, decl_class, identifier, designator) @override - def visitQuantumDeclarationStatement( - self, ctx: qasm3Parser.QuantumDeclarationStatementContext - ) -> None: + def visitQuantumDeclarationStatement(self, ctx: qasm3Parser.QuantumDeclarationStatementContext) -> None: designator = ctx.qubitType().designator() # type: ignore[no-untyped-call] identifier = ctx.Identifier().getText() # type: ignore[no-untyped-call] self.declare_registers(ctx, _Qubit, identifier, designator) @override - def visitConstDeclarationStatement( - self, ctx: qasm3Parser.ConstDeclarationStatementContext - ) -> None: + def visitConstDeclarationStatement(self, ctx: qasm3Parser.ConstDeclarationStatementContext) -> None: identifier = ctx.Identifier().getText() # type: ignore[no-untyped-call] value = ctx.declarationExpression() # type: ignore[no-untyped-call] expr = self.evaluate_expression(value) @@ -319,13 +313,11 @@ def visitGateCallStatement(self, ctx: qasm3Parser.GateCallStatementContext) -> N gate = ctx.Identifier().getText() # type: ignore[no-untyped-call] operand_list = ctx.gateOperandList() # type: ignore[no-untyped-call] operands = [ - self.convert_qubit_index(operand_list.getChild(i)) - for i in range(0, operand_list.getChildCount(), 2) + self.convert_qubit_index(operand_list.getChild(i)) for i in range(0, operand_list.getChildCount(), 2) ] if expr_list := ctx.expressionList(): # type: ignore[no-untyped-call] exprs = [ - float(self.evaluate_expression(expr_list.getChild(i))) - for i in range(0, expr_list.getChildCount(), 2) + float(self.evaluate_expression(expr_list.getChild(i))) for i in range(0, expr_list.getChildCount(), 2) ] else: exprs = [] @@ -335,9 +327,7 @@ def visitGateCallStatement(self, ctx: qasm3Parser.GateCallStatementContext) -> N instruction = CCX(target=operands[2], controls=(operands[0], operands[1])) elif gate == "crz": # https://openqasm.com/language/standard_library.html#crz - instruction = RZZ( - target=operands[1], control=operands[0], angle=rad_to_angle(exprs[0]) - ) + instruction = RZZ(target=operands[1], control=operands[0], angle=rad_to_angle(exprs[0])) elif gate == "cx": # https://openqasm.com/language/standard_library.html#cx instruction = CNOT(target=operands[1], control=operands[0]) @@ -446,9 +436,7 @@ def parse(self, expr: qasm3Parser.ExpressionContext) -> _Value: return value @override - def visitParenthesisExpression( - self, ctx: qasm3Parser.ParenthesisExpressionContext - ) -> _Value: + def visitParenthesisExpression(self, ctx: qasm3Parser.ParenthesisExpressionContext) -> _Value: expr: qasm3Parser.ExpressionContext = ctx.expression() # type: ignore[no-untyped-call] return self.parse(expr) @@ -465,21 +453,15 @@ def visitUnaryExpression(self, ctx: qasm3Parser.UnaryExpressionContext) -> _Valu raise NotImplementedError(msg) @override - def visitAdditiveExpression( - self, ctx: qasm3Parser.AdditiveExpressionContext - ) -> _Value: + def visitAdditiveExpression(self, ctx: qasm3Parser.AdditiveExpressionContext) -> _Value: return self.parse_binary_operator(ctx) @override - def visitMultiplicativeExpression( - self, ctx: qasm3Parser.MultiplicativeExpressionContext - ) -> _Value: + def visitMultiplicativeExpression(self, ctx: qasm3Parser.MultiplicativeExpressionContext) -> _Value: return self.parse_binary_operator(ctx) @override - def visitLiteralExpression( - self, ctx: qasm3Parser.LiteralExpressionContext - ) -> _Value: + def visitLiteralExpression(self, ctx: qasm3Parser.LiteralExpressionContext) -> _Value: literal = ctx.getChild(0) if literal.symbol.type == qasm3Parser.DecimalIntegerLiteral: return _Int(ctx, int(literal.symbol.text)) @@ -494,8 +476,7 @@ def visitLiteralExpression( def parse_binary_operator( self, - ctx: qasm3Parser.AdditiveExpressionContext - | qasm3Parser.MultiplicativeExpressionContext, + ctx: qasm3Parser.AdditiveExpressionContext | qasm3Parser.MultiplicativeExpressionContext, ) -> _Value: lhs_expr: qasm3Parser.ExpressionContext = ctx.getChild(0) rhs_expr: qasm3Parser.ExpressionContext = ctx.getChild(2) From 4e22d1def806a7a48874f3ba5fb0f50ed23e7db8 Mon Sep 17 00:00:00 2001 From: Emlyn Graham Date: Tue, 3 Feb 2026 10:19:06 +0100 Subject: [PATCH 3/3] Thierry suggestions --- .github/workflows/typecheck.yml | 4 +--- graphix_qasm_parser/parser.py | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 122a678..b623f8c 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -29,6 +29,4 @@ jobs: python -m pip install --upgrade pip pip install .[dev] - - run: mypy - - - run: pyright + - run: mypy \ No newline at end of file diff --git a/graphix_qasm_parser/parser.py b/graphix_qasm_parser/parser.py index fe593f8..11cdbcf 100644 --- a/graphix_qasm_parser/parser.py +++ b/graphix_qasm_parser/parser.py @@ -35,7 +35,6 @@ def rad_to_angle(angle: float) -> float: CZ = SWAP else: - ANGLE_PI = 1.0 try: from graphix.instruction import CZ except ImportError: @@ -46,7 +45,7 @@ def CZ(_q0: int, _q1: int) -> None: # noqa: N802 raise NotImplementedError(msg) try: - from graphix.fundamentals import rad_to_angle + from graphix.fundamentals import ANGLE_PI, rad_to_angle except ImportError: # Compatibility with graphix <= 0.3.3 # See https://github.com/TeamGraphix/graphix/pull/399