Skip to content

Commit

Permalink
Improve reverse_bits to support registerless bits (Qiskit#7423)
Browse files Browse the repository at this point in the history
* Improve reverse_bits to support registerless bits

* Change the algorithm of reverse_bits

* Reimplement reverse_bits with reversed bits

Also add more test cases.

* Simplify bit lookups

Co-authored-by: Jake Lishman <[email protected]>
  • Loading branch information
2 people authored and ajavadia committed May 31, 2022
1 parent 8b5babe commit 6873b43
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 18 deletions.
50 changes: 32 additions & 18 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,37 +475,51 @@ def reverse_bits(self) -> "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

Expand Down
Original file line number Diff line number Diff line change
@@ -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()
74 changes: 74 additions & 0 deletions test/python/circuit/test_circuit_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,80 @@ def test_reverse_bits_with_registers(self):

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)
Expand Down

0 comments on commit 6873b43

Please sign in to comment.