Skip to content

Commit

Permalink
Detect duplicates in QuantumCircuit.compose
Browse files Browse the repository at this point in the history
Previously, `QuantumCircuit.compose` would silently attempt to compose
multiple qubits onto the same state, which would fail in weird ways if
any multi-qubit instructions were acting on these collapsed qubits.
  • Loading branch information
jakelishman committed Dec 21, 2023
1 parent 70901b2 commit 98f7ebb
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 0 deletions.
8 changes: 8 additions & 0 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,10 @@ def compose(
f"Number of items in qubits parameter ({len(mapped_qubits)}) does not"
f" match number of qubits in the circuit ({len(other.qubits)})."
)
if len(set(mapped_qubits)) != len(mapped_qubits):
raise CircuitError(
f"Duplicate qubits referenced in 'qubits' parameter: '{mapped_qubits}'"
)
edge_map.update(zip(other.qubits, mapped_qubits))

if clbits is None:
Expand All @@ -1019,6 +1023,10 @@ def compose(
f"Number of items in clbits parameter ({len(mapped_clbits)}) does not"
f" match number of clbits in the circuit ({len(other.clbits)})."
)
if len(set(mapped_clbits)) != len(mapped_clbits):
raise CircuitError(
f"Duplicate clbits referenced in 'clbits' parameter: '{mapped_clbits}'"
)
edge_map.update(zip(other.clbits, dest.cbit_argument_conversion(clbits)))

variable_mapper = _classical_resource_map.VariableMapper(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fixes:
- |
:meth:`.QuantumCircuit.compose` will now correctly raise a :exc:`.CircuitError` when there are
duplicates in the ``qubits`` or ``clbits`` arguments.
11 changes: 11 additions & 0 deletions test/python/circuit/test_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
Instruction,
CASE_DEFAULT,
SwitchCaseOp,
CircuitError,
)
from qiskit.circuit.library import HGate, RZGate, CXGate, CCXGate, TwoLocal
from qiskit.circuit.classical import expr
Expand Down Expand Up @@ -880,6 +881,16 @@ def test_expr_target_is_mapped(self):

self.assertEqual(dest, expected)

def test_rejects_duplicate_bits(self):
"""Test that compose rejects duplicates in either qubits or clbits."""
base = QuantumCircuit(5, 5)

attempt = QuantumCircuit(2, 2)
with self.assertRaisesRegex(CircuitError, "Duplicate qubits"):
base.compose(attempt, [1, 1], [0, 1])
with self.assertRaisesRegex(CircuitError, "Duplicate clbits"):
base.compose(attempt, [0, 1], [1, 1])


if __name__ == "__main__":
unittest.main()

0 comments on commit 98f7ebb

Please sign in to comment.