diff --git a/cirq-core/cirq/circuits/qasm_output.py b/cirq-core/cirq/circuits/qasm_output.py index 2d19138f47e..2539799540c 100644 --- a/cirq-core/cirq/circuits/qasm_output.py +++ b/cirq-core/cirq/circuits/qasm_output.py @@ -293,7 +293,11 @@ def output(text): output(f'creg {meas_id}[{len(meas.qubits)}];\n') else: output(f'creg {meas_id}[{len(meas.qubits)}]; // Measurement: {comment}\n') - output_line_gap(2) + # In OpenQASM 2.0, the transformation of global phase gates is ignored. + # Therefore, no newline is created when the operations contained in + # a circuit consist only of global phase gates. + if any(not isinstance(op.gate, ops.GlobalPhaseGate) for op in self.operations): + output_line_gap(2) # Operations self._write_operations(self.operations, output, output_line_gap) diff --git a/cirq-core/cirq/circuits/qasm_output_test.py b/cirq-core/cirq/circuits/qasm_output_test.py index 7f421018324..d9083ee183a 100644 --- a/cirq-core/cirq/circuits/qasm_output_test.py +++ b/cirq-core/cirq/circuits/qasm_output_test.py @@ -191,6 +191,19 @@ def test_h_gate_with_parameter(): ) +def test_qasm_global_pahse(): + output = cirq.QasmOutput((cirq.global_phase_operation(np.exp(1j * 5))), ()) + assert ( + str(output) + == """OPENQASM 2.0; +include "qelib1.inc"; + + +// Qubits: [] +""" + ) + + def test_precision(): (q0,) = _make_qubits(1) output = cirq.QasmOutput((cirq.X(q0) ** 0.1234567,), (q0,), precision=3) diff --git a/cirq-core/cirq/ops/gate_operation.py b/cirq-core/cirq/ops/gate_operation.py index abf238eb04e..db5be010923 100644 --- a/cirq-core/cirq/ops/gate_operation.py +++ b/cirq-core/cirq/ops/gate_operation.py @@ -15,6 +15,7 @@ """Basic types defining qubits, gates, and operations.""" import re +import warnings from typing import ( AbstractSet, Any, @@ -35,7 +36,7 @@ import numpy as np -from cirq import protocols, value +from cirq import ops, protocols, value from cirq.ops import raw_types, gate_features, control_values as cv from cirq.type_workarounds import NotImplementedType @@ -348,6 +349,14 @@ def __rmul__(self, other: Any) -> Any: return self.gate._rmul_with_qubits(self._qubits, other) def _qasm_(self, args: 'protocols.QasmArgs') -> Optional[str]: + if isinstance(self.gate, ops.GlobalPhaseGate): + warnings.warn( + "OpenQASM 2.0 does not support global phase." + "Since the global phase does not affect the measurement results, " + "the conversion to QASM is disregarded." + ) + return "" + return protocols.qasm(self.gate, args=args, qubits=self.qubits, default=None) def _equal_up_to_global_phase_( diff --git a/cirq-core/cirq/testing/consistent_qasm.py b/cirq-core/cirq/testing/consistent_qasm.py index e61095e9053..9d24eaa9698 100644 --- a/cirq-core/cirq/testing/consistent_qasm.py +++ b/cirq-core/cirq/testing/consistent_qasm.py @@ -42,6 +42,7 @@ def assert_qasm_is_consistent_with_unitary(val: Any): if isinstance(val, ops.Operation): qubits: Sequence[ops.Qid] = val.qubits op = val + gate = val.gate elif isinstance(val, ops.Gate): qid_shape = protocols.qid_shape(val) remaining_shape = list(qid_shape) @@ -52,9 +53,14 @@ def assert_qasm_is_consistent_with_unitary(val: Any): remaining_shape.pop(i) qubits = devices.LineQid.for_qid_shape(remaining_shape) op = val.on(*qubits) + gate = val else: raise NotImplementedError(f"Don't know how to test {val!r}") + if isinstance(gate, ops.GlobalPhaseGate): + # OpenQASM 2.0 does not support global phase gates. + return + args = protocols.QasmArgs(qubit_id_map={q: f'q[{i}]' for i, q in enumerate(qubits)}) qasm = protocols.qasm(op, args=args, default=None) if qasm is None: