diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index 7951277be2..fcc24beed0 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -475,37 +475,51 @@ class QuantumCircuit: .. parsed-literal:: ┌───┐ - q_0: ┤ H ├─────■────── - └───┘┌────┴─────┐ - q_1: ─────┤ RX(1.57) ├ - └──────────┘ + a_0: ┤ H ├──■───────────────── + └───┘┌─┴─┐ + a_1: ─────┤ X ├──■──────────── + └───┘┌─┴─┐ + a_2: ──────────┤ X ├──■─────── + └───┘┌─┴─┐ + b_0: ───────────────┤ X ├──■── + └───┘┌─┴─┐ + b_1: ────────────────────┤ X ├ + └───┘ output: .. parsed-literal:: - ┌──────────┐ - q_0: ─────┤ RX(1.57) ├ - ┌───┐└────┬─────┘ - q_1: ┤ H ├─────■────── + ┌───┐ + b_0: ────────────────────┤ X ├ + ┌───┐└─┬─┘ + b_1: ───────────────┤ X ├──■── + ┌───┐└─┬─┘ + a_0: ──────────┤ X ├──■─────── + ┌───┐└─┬─┘ + a_1: ─────┤ X ├──■──────────── + ┌───┐└─┬─┘ + a_2: ┤ H ├──■───────────────── └───┘ """ circ = QuantumCircuit( - *reversed(self.qregs), - *reversed(self.cregs), + list(reversed(self.qubits)), + list(reversed(self.clbits)), name=self.name, global_phase=self.global_phase, ) - num_qubits = self.num_qubits - num_clbits = self.num_clbits - old_qubits = self.qubits - old_clbits = self.clbits - new_qubits = circ.qubits - new_clbits = circ.clbits + new_qubit_map = circ.qubits[::-1] + new_clbit_map = circ.clbits[::-1] + for reg in reversed(self.qregs): + bits = [new_qubit_map[self.find_bit(qubit).index] for qubit in reversed(reg)] + circ.add_register(QuantumRegister(bits=bits, name=reg.name)) + for reg in reversed(self.cregs): + bits = [new_clbit_map[self.find_bit(clbit).index] for clbit in reversed(reg)] + circ.add_register(ClassicalRegister(bits=bits, name=reg.name)) for inst, qargs, cargs in self.data: - new_qargs = [new_qubits[num_qubits - old_qubits.index(q) - 1] for q in qargs] - new_cargs = [new_clbits[num_clbits - old_clbits.index(c) - 1] for c in cargs] + new_qargs = [new_qubit_map[self.find_bit(qubit).index] for qubit in qargs] + new_cargs = [new_clbit_map[self.find_bit(clbit).index] for clbit in cargs] circ._append(inst, new_qargs, new_cargs) return circ diff --git a/releasenotes/notes/fix-reverse_bits-with-registerless-bits-6d17597b99640fb0.yaml b/releasenotes/notes/fix-reverse_bits-with-registerless-bits-6d17597b99640fb0.yaml new file mode 100644 index 0000000000..6fa9789cfd --- /dev/null +++ b/releasenotes/notes/fix-reverse_bits-with-registerless-bits-6d17597b99640fb0.yaml @@ -0,0 +1,11 @@ +--- +fixes: + - | + Fixed :meth:`.QuantumCircuit.reverse_bits` with circuits containing registerless + :class:`.Qubit` and :class:`.Clbit`. For example, the following will now work:: + + from qiskit.circuit import QuantumCircuit, Qubit, Clbit + + qc = QuantumCircuit([Qubit(), Clbit()]) + qc.h(0).c_if(qc.clbits[0], 0) + qc.reverse_bits() diff --git a/test/python/circuit/test_circuit_operations.py b/test/python/circuit/test_circuit_operations.py index 148ae91ad0..4fe6194029 100644 --- a/test/python/circuit/test_circuit_operations.py +++ b/test/python/circuit/test_circuit_operations.py @@ -1008,6 +1008,80 @@ class TestCircuitOperations(QiskitTestCase): self.assertEqual(qc.reverse_bits(), expected) + def test_reverse_bits_with_overlapped_registers(self): + """Test reversing order of bits when registers are overlapped.""" + qr1 = QuantumRegister(2, "a") + qr2 = QuantumRegister(bits=[qr1[0], qr1[1], Qubit()], name="b") + qc = QuantumCircuit(qr1, qr2) + qc.h(qr1[0]) + qc.cx(qr1[0], qr1[1]) + qc.cx(qr1[1], qr2[2]) + + qr2 = QuantumRegister(bits=[Qubit(), qr1[0], qr1[1]], name="b") + expected = QuantumCircuit(qr2, qr1) + expected.h(qr1[1]) + expected.cx(qr1[1], qr1[0]) + expected.cx(qr1[0], qr2[0]) + + self.assertEqual(qc.reverse_bits(), expected) + + def test_reverse_bits_with_registerless_bits(self): + """Test reversing order of registerless bits.""" + q0 = Qubit() + q1 = Qubit() + c0 = Clbit() + c1 = Clbit() + qc = QuantumCircuit([q0, q1], [c0, c1]) + qc.h(0) + qc.cx(0, 1) + qc.x(0).c_if(1, True) + qc.measure(0, 0) + + expected = QuantumCircuit([c1, c0], [q1, q0]) + expected.h(1) + expected.cx(1, 0) + expected.x(1).c_if(0, True) + expected.measure(1, 1) + + self.assertEqual(qc.reverse_bits(), expected) + + def test_reverse_bits_with_registers_and_bits(self): + """Test reversing order of bits with registers and registerless bits.""" + qr = QuantumRegister(2, "a") + q = Qubit() + qc = QuantumCircuit(qr, [q]) + qc.h(qr[0]) + qc.cx(qr[0], qr[1]) + qc.cx(qr[1], q) + + expected = QuantumCircuit([q], qr) + expected.h(qr[1]) + expected.cx(qr[1], qr[0]) + expected.cx(qr[0], q) + + self.assertEqual(qc.reverse_bits(), expected) + + def test_reverse_bits_with_mixed_overlapped_registers(self): + """Test reversing order of bits with overlapped registers and registerless bits.""" + q = Qubit() + qr1 = QuantumRegister(bits=[q, Qubit()], name="qr1") + qr2 = QuantumRegister(bits=[qr1[1], Qubit()], name="qr2") + qc = QuantumCircuit(qr1, qr2, [Qubit()]) + qc.h(q) + qc.cx(qr1[0], qr1[1]) + qc.cx(qr1[1], qr2[1]) + qc.cx(2, 3) + + qr2 = QuantumRegister(2, "qr2") + qr1 = QuantumRegister(bits=[qr2[1], q], name="qr1") + expected = QuantumCircuit([Qubit()], qr2, qr1) + expected.h(qr1[1]) + expected.cx(qr1[1], qr1[0]) + expected.cx(qr1[0], qr2[0]) + expected.cx(1, 0) + + self.assertEqual(qc.reverse_bits(), expected) + def test_cnot_alias(self): """Test that the cnot method alias adds a cx gate.""" qc = QuantumCircuit(2)