Skip to content
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

Fix an error in qasm3 exporter when operating on unitary gates #13633

Merged
merged 3 commits into from
Jan 14, 2025
Merged
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
2 changes: 1 addition & 1 deletion qiskit/circuit/library/generalized_gates/permutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def inverse(self, annotated: bool = False) -> PermutationGate:

return PermutationGate(pattern=_inverse_pattern(self.pattern))

def _qasm2_decomposition(self):
def _qasm_decomposition(self):
# pylint: disable=cyclic-import
from qiskit.synthesis.permutation import synth_permutation_basic

Expand Down
2 changes: 1 addition & 1 deletion qiskit/circuit/library/generalized_gates/unitary.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def control(
)
return gate

def _qasm2_decomposition(self):
def _qasm_decomposition(self):
"""Return an unparameterized version of ourselves, so the OQ2 exporter doesn't choke on the
non-standard things in our `params` field."""
out = self.definition.to_gate()
Expand Down
4 changes: 2 additions & 2 deletions qiskit/qasm2/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,8 @@ def _define_custom_operation(operation, gates_to_define):
# definition, but still continue to return the given object as the call-site object.
if operation.base_class in known_good_parameterized:
parameterized_operation = type(operation)(*_FIXED_PARAMETERS[: len(operation.params)])
elif hasattr(operation, "_qasm2_decomposition"):
new_op = operation._qasm2_decomposition()
elif hasattr(operation, "_qasm_decomposition"):
new_op = operation._qasm_decomposition()
parameterized_operation = operation = new_op.copy(name=_escape_name(new_op.name, "gate_"))
else:
parameterized_operation = operation
Expand Down
9 changes: 6 additions & 3 deletions qiskit/qasm3/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1180,13 +1180,16 @@ def build_gate_call(self, instruction: CircuitInstruction):

This will also push the gate into the symbol table (if required), including recursively
defining the gate blocks."""
ident = self.symbols.get_gate(instruction.operation)
operation = instruction.operation
if hasattr(operation, "_qasm_decomposition"):
operation = operation._qasm_decomposition()
ident = self.symbols.get_gate(operation)
if ident is None:
ident = self.define_gate(instruction.operation)
ident = self.define_gate(operation)
qubits = [self._lookup_bit(qubit) for qubit in instruction.qubits]
parameters = [
ast.StringifyAndPray(self._rebind_scoped_parameters(param))
for param in instruction.operation.params
for param in operation.params
]
if not self.disable_constants:
for parameter in parameters:
Expand Down
5 changes: 5 additions & 0 deletions releasenotes/notes/fix-qasm-3-unitary-2da190be6ba25bbd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fixes:
- |
Fix a bug in :class:`.qasm3.Exporter` that caused the exporter to crash when
handling a unitary gate due to incorrect processing of its ``params`` field.
17 changes: 17 additions & 0 deletions test/python/qasm3/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -2665,6 +2665,23 @@ def test_switch_v1_expr_target(self):
test = dumps(qc, experimental=ExperimentalFeatures.SWITCH_CASE_V1)
self.assertEqual(test, expected)

def test_circuit_with_unitary(self):
"""Test that circuits with `unitary` gate are correctly handled"""
matrix = [[0, 1], [1, 0]]
qc = QuantumCircuit(1)
qc.unitary(matrix, [0])
expected = """\
OPENQASM 3.0;
include "stdgates.inc";
gate unitary _gate_q_0 {
U(pi, -pi, 0) _gate_q_0;
}
qubit[1] q;
unitary q[0];
"""
test = dumps(qc)
self.assertEqual(test, expected)


@ddt
class TestQASM3ExporterFailurePaths(QiskitTestCase):
Expand Down
Loading