Skip to content

Commit

Permalink
raise an exception with a custom gate with clbits or no qubits (#10438)
Browse files Browse the repository at this point in the history
* raise an exception with a custom gate with no qubits or with one-or-more clbits

* QASM2ExportError

* test_circuit_raises_invalid_custom_gate_1

* test_circuit_raises_invalid_custom_gate_2

* reno

* Split error messages to be more specific

* Fix testing bug

* Fixup release note

---------

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
  • Loading branch information
1ucian0 and jakelishman authored Jul 24, 2023
1 parent cab90ca commit 208c29a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 1 deletion.
15 changes: 14 additions & 1 deletion qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -5025,7 +5025,9 @@ def _qasm2_define_custom_operation(operation, existing_gate_names, gates_to_defi
Returns a potentially new :class:`.Instruction`, which should be used for the
:meth:`~.Instruction.qasm` call (it may have been renamed)."""
from qiskit.circuit import library as lib # pylint: disable=cyclic-import
# pylint: disable=cyclic-import
from qiskit.circuit import library as lib
from qiskit.qasm2 import QASM2ExportError

if operation.name in existing_gate_names:
return operation
Expand Down Expand Up @@ -5086,6 +5088,17 @@ def _qasm2_define_custom_operation(operation, existing_gate_names, gates_to_defi
)
else:
parameters_qasm = ""

if operation.num_qubits == 0:
raise QASM2ExportError(
f"OpenQASM 2 cannot represent '{operation.name}, which acts on zero qubits."
)
if operation.num_clbits != 0:
raise QASM2ExportError(
f"OpenQASM 2 cannot represent '{operation.name}', which acts on {operation.num_clbits}"
" classical bits."
)

qubits_qasm = ",".join(f"q{i}" for i in range(parameterized_operation.num_qubits))
parameterized_definition = getattr(parameterized_operation, "definition", None)
if parameterized_definition is None:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fixes:
- |
Qiskit can represent custom instructions that act on zero qubits, or on a non-zero number of
classical bits. These cannot be exported to OpenQASM 2, but previously :meth:`.QuantumCircuit.qasm`
would try, and output invalid OpenQASM 2. Instead, a :exc:`.QASM2ExportError` will now correctly
be raised. See `#7351 <https://github.com/Qiskit/qiskit-terra/issues/7351>`__ and
`#10435 <https://github.com/Qiskit/qiskit-terra/issues/10435>`__.
24 changes: 24 additions & 0 deletions test/python/circuit/test_circuit_qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,30 @@ def test_circuit_raises_on_single_bit_condition(self):
with self.assertRaisesRegex(QasmError, "OpenQASM 2 can only condition on registers"):
qc.qasm()

def test_circuit_raises_invalid_custom_gate_no_qubits(self):
"""OpenQASM 2 exporter of custom gates with no qubits.
See: https://github.com/Qiskit/qiskit-terra/issues/10435"""
legit_circuit = QuantumCircuit(5, name="legit_circuit")
empty_circuit = QuantumCircuit(name="empty_circuit")
legit_circuit.append(empty_circuit)

with self.assertRaisesRegex(QasmError, "acts on zero qubits"):
legit_circuit.qasm()

def test_circuit_raises_invalid_custom_gate_clbits(self):
"""OpenQASM 2 exporter of custom instruction.
See: https://github.com/Qiskit/qiskit-terra/issues/7351"""
instruction = QuantumCircuit(2, 2, name="inst")
instruction.cx(0, 1)
instruction.measure([0, 1], [0, 1])
custom_instruction = instruction.to_instruction()

qc = QuantumCircuit(2, 2)
qc.append(custom_instruction, [0, 1], [0, 1])

with self.assertRaisesRegex(QasmError, "acts on 2 classical bits"):
qc.qasm()

def test_circuit_qasm_with_permutations(self):
"""Test circuit qasm() method with Permutation gates."""

Expand Down

0 comments on commit 208c29a

Please sign in to comment.