Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions qiskit/qasm3/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,13 @@ def dump(self, circuit, stream):
"U": _CANONICAL_STANDARD_GATES[StandardGate.U],
}

# Some downstream consumers, notably qiskit-aer, interpret "unitary" as a special instruction name
# rather than a user-defined gate. Exported gate definitions that use the bare symbol can then be
# misclassified, so we rename those declarations while preserving the circuit semantics.
_DECLARED_GATE_NAME_RENAMES = {
"unitary": "unitary_gate",
}


@dataclasses.dataclass
class GateInfo:
Expand Down Expand Up @@ -557,6 +564,7 @@ def register_gate(
) -> ast.Identifier:
"""Register the given gate in the symbol table, using the given components to build up the
full AST definition."""
name = _DECLARED_GATE_NAME_RENAMES.get(name, name)
name = self.escaped_declarable_name(name, allow_rename=True, unique=False)
ident = ast.Identifier(name)
self.gates[name] = GateInfo(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
fixes:
- |
The OpenQASM 3 exporter (:func:`.qasm3.dumps` and :func:`~.qasm3.dump`) will no longer emit a
declared gate called ``unitary`` when exporting circuit definitions built from
:class:`.UnitaryGate` instances. This avoids collisions with downstream consumers such as
:mod:`qiskit_aer` that interpret ``unitary`` as a special instruction name.

upgrade_qasm:
- |
OpenQASM 3 output for circuits containing exported :class:`.UnitaryGate` definitions now uses
gate names beginning with ``unitary_gate`` instead of the bare symbol ``unitary``.
20 changes: 18 additions & 2 deletions test/python/qasm3/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -2757,15 +2757,31 @@ def test_circuit_with_unitary(self):
expected = """\
OPENQASM 3.0;
include "stdgates.inc";
gate unitary _gate_q_0 {
gate unitary_gate _gate_q_0 {
U(pi, -pi, 0) _gate_q_0;
}
qubit[1] q;
unitary q[0];
unitary_gate q[0];
"""
test = dumps(qc)
self.assertEqual(test, expected)

def test_nested_unitary_definitions_do_not_use_bare_unitary_name(self):
"""Test synthesized subcircuits avoid exporting a declared gate called ``unitary``."""
from qiskit.circuit.library import Initialize

raw_state = [1, 2, 3, 4, 5, 6, 7, 8]
norm = sum(value * value for value in raw_state) ** 0.5

qc = QuantumCircuit(3)
qc.compose(
Initialize([value / norm for value in raw_state]).definition, range(3), inplace=True
)

test = dumps(qc)
self.assertNotIn("gate unitary ", test)
self.assertNotIn("\nunitary ", test)


@ddt
class TestQASM3ExporterFailurePaths(QiskitTestCase):
Expand Down