diff --git a/qiskit/extensions/unitary.py b/qiskit/extensions/unitary.py index 6a36e630dd3f..5d9364805ded 100644 --- a/qiskit/extensions/unitary.py +++ b/qiskit/extensions/unitary.py @@ -191,22 +191,13 @@ def qasm(self): _qasm_escape_gate_name(self.label) if self.label else "unitary" + str(id(self)) ) - # map from gates in the definition to params in the method - bit_to_qasm = OrderedDict() - current_bit = 0 - + qubit_to_qasm = {bit: f"p{i}" for i, bit in enumerate(self.definition.qubits)} gates_def = "" for instruction in self.definition.data: - # add bits from this gate to the overall set of params - for bit in instruction.qubits + instruction.clbits: - if bit not in bit_to_qasm: - bit_to_qasm[bit] = "p" + str(current_bit) - current_bit += 1 - curr_gate = "\t{} {};\n".format( instruction.operation.qasm(), - ",".join([bit_to_qasm[j] for j in instruction.qubits + instruction.clbits]), + ",".join(qubit_to_qasm[qubit] for qubit in instruction.qubits), ) gates_def += curr_gate @@ -215,7 +206,7 @@ def qasm(self): "gate " + self._qasm_name + " " - + ",".join(bit_to_qasm.values()) + + ",".join(qubit_to_qasm[qubit] for qubit in self.definition.qubits) + " {\n" + gates_def + "}" diff --git a/releasenotes/notes/fix-qasm2-identity-as-unitary-aa2feeb05707a597.yaml b/releasenotes/notes/fix-qasm2-identity-as-unitary-aa2feeb05707a597.yaml new file mode 100644 index 000000000000..7cbd2a5cdfcc --- /dev/null +++ b/releasenotes/notes/fix-qasm2-identity-as-unitary-aa2feeb05707a597.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + The OpenQASM 2 exporter (:meth:`.QuantumCircuit.qasm`) will now correctly + define the qubit parameters for :class:`.UnitaryGate` operations that do + not affect all the qubits they are defined over. + Fixed `#8224 `__. diff --git a/test/python/circuit/test_unitary.py b/test/python/circuit/test_unitary.py index d124188565b2..935b63897ec9 100644 --- a/test/python/circuit/test_unitary.py +++ b/test/python/circuit/test_unitary.py @@ -281,6 +281,20 @@ def test_qasm_2q_unitary(self): ) self.assertEqual(expected_qasm, qc.qasm()) + def test_qasm_unitary_noop(self): + """Test that an identifier unitary can be converted to OpenQASM 2""" + qc = QuantumCircuit(QuantumRegister(3, "q0")) + qc.unitary(numpy.eye(8), qc.qubits, label="unitary_identity") + expected_qasm = ( + "OPENQASM 2.0;\n" + 'include "qelib1.inc";\n' + "gate unitary_identity p0,p1,p2 {\n" + "}\n" + "qreg q0[3];\n" + "unitary_identity q0[0],q0[1],q0[2];\n" + ) + self.assertEqual(expected_qasm, qc.qasm()) + def test_unitary_decomposition(self): """Test decomposition for unitary gates over 2 qubits.""" qc = QuantumCircuit(3)