Skip to content

Commit

Permalink
Fix an error in qasm3 exporter when operating on unitary gates (#13633)
Browse files Browse the repository at this point in the history
* Fix error in qasm3 exporter when operating on unitary gates

* Update test/python/qasm3/test_export.py

Co-authored-by: Jake Lishman <[email protected]>

* Update releasenotes/notes/fix-qasm-3-unitary-2da190be6ba25bbd.yaml

Co-authored-by: Jake Lishman <[email protected]>

---------

Co-authored-by: Jake Lishman <[email protected]>
  • Loading branch information
gadial and jakelishman authored Jan 14, 2025
1 parent b98e0d0 commit 087e393
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 7 deletions.
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 @@ -186,7 +186,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

0 comments on commit 087e393

Please sign in to comment.