Skip to content

Add warning when converting global phase operator to OpenQASM 2.0 #6476

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 29, 2024
7 changes: 6 additions & 1 deletion cirq-core/cirq/circuits/qasm_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,12 @@ 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 not (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the condition so that it works for the when the circuit has multiple global phases

if all(isinstance(op, ops.GlobalPhaseGate) for op in self.operations):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I overlooked that pattern. I've addressed it now.
Thank you for pointing it out!

len(self.operations) == 1 and isinstance(self.operations[0].gate, ops.GlobalPhaseGate)
):
output_line_gap(2)

# Operations
self._write_operations(self.operations, output, output_line_gap)
Expand Down
13 changes: 13 additions & 0 deletions cirq-core/cirq/circuits/qasm_output_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 10 additions & 1 deletion cirq-core/cirq/ops/gate_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""Basic types defining qubits, gates, and operations."""

import re
import warnings
from typing import (
AbstractSet,
Any,
Expand All @@ -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

Expand Down Expand Up @@ -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_(
Expand Down
6 changes: 6 additions & 0 deletions cirq-core/cirq/testing/consistent_qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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:
Expand Down