diff --git a/qiskit_aer/backends/aer_compiler.py b/qiskit_aer/backends/aer_compiler.py index a0c75247cc..846eb10052 100644 --- a/qiskit_aer/backends/aer_compiler.py +++ b/qiskit_aer/backends/aer_compiler.py @@ -259,6 +259,9 @@ def _inline_for_loop_op(self, instruction, parent, bit_map): """inline for_loop body while iterating its indexset""" qargs = [bit_map[q] for q in instruction.qubits] cargs = [bit_map[c] for c in instruction.clbits] + # to avoid wrong topological sorting of command with "empty" block + if len(qargs) == 0: + qargs = parent.qubits indexset, loop_parameter, body = instruction.operation.params inner_bit_map = { inner: bit_map[outer] @@ -320,6 +323,9 @@ def _inline_while_loop_op(self, instruction, parent, bit_map): ) qargs = [bit_map[q] for q in instruction.qubits] cargs = [bit_map[c] for c in instruction.clbits] + # to avoid wrong topological sorting of command with "empty" block + if len(qargs) == 0: + qargs = parent.qubits if isinstance(condition_tuple, Expr): mark_cargs = self._list_clbit_from_expr(bit_map, condition_tuple) @@ -371,6 +377,13 @@ def _inline_if_else_op(self, instruction, continue_label, break_label, parent, b qargs = [bit_map[q] for q in instruction.qubits] cargs = [bit_map[c] for c in instruction.clbits] + # to avoid wrong topological sorting of command with "empty" block + if len(qargs) == 0: + qargs = parent.qubits + + # to avoid wrong topological sorting of command with "empty" block + if len(qargs) == 0: + qargs = parent.qubits if isinstance(condition_tuple, Expr): mark_cargs = self._list_clbit_from_expr(bit_map, condition_tuple) @@ -439,6 +452,9 @@ def _inline_switch_case_op(self, instruction, continue_label, break_label, paren qargs = [bit_map[q] for q in instruction.qubits] cargs = [bit_map[c] for c in instruction.clbits] + # to avoid wrong topological sorting of command with "empty" block + if len(qargs) == 0: + qargs = parent.qubits if isinstance(instruction.operation.target, Clbit): target_clbits = {bit_map[instruction.operation.target]} diff --git a/releasenotes/notes/fix_infinite_run_on_empty_conditional-d9e6d31ffa1c3bc3.yaml b/releasenotes/notes/fix_infinite_run_on_empty_conditional-d9e6d31ffa1c3bc3.yaml new file mode 100644 index 0000000000..10bcad90b8 --- /dev/null +++ b/releasenotes/notes/fix_infinite_run_on_empty_conditional-d9e6d31ffa1c3bc3.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + Using a conditional with empty body caused the transpile run to + mix the order of gates in the circuit, leading sometimes to infinite + simulations. + This fix ensures that the order of gates is preserved. diff --git a/test/terra/backends/aer_simulator/test_conditional.py b/test/terra/backends/aer_simulator/test_conditional.py index ec33fd404b..56dc936781 100644 --- a/test/terra/backends/aer_simulator/test_conditional.py +++ b/test/terra/backends/aer_simulator/test_conditional.py @@ -16,7 +16,7 @@ from test.terra.reference import ref_conditionals from test.terra.backends.simulator_test_case import SimulatorTestCase, supported_methods -from qiskit import QuantumCircuit +from qiskit import QuantumCircuit, ClassicalRegister from qiskit.circuit.library import DiagonalGate @@ -380,3 +380,23 @@ def test_conditional_diagonal(self): self.assertNotEqual(result.data(circuit)["base"], result.data(circuit0)["diff"]) self.assertEqual(result.data(circuit)["base"], result.data(circuit1)["equal"]) + + +class TestConditionalErrors(SimulatorTestCase): + def test_infinite_run_error(self): + backend = self.backend(method="statevector", device="CPU") + backend.set_options(max_parallel_experiments=0) + + main_circ = QuantumCircuit(1) + creg_0 = ClassicalRegister(1) + main_circ.add_register(creg_0) + main_circ.measure(0, creg_0[0]) + main_circ.x(0) + with main_circ.if_test((creg_0[0], 0)) as else_1: + pass + with else_1: + pass + main_circ.measure_active() + + result = backend.run(main_circ, shots=1).result() + self.assertSuccess(result)