Skip to content

Commit

Permalink
Fix replace_block_with_op on operations with wrong number of qubits (
Browse files Browse the repository at this point in the history
…#12637)

* fix illegal op insertion

* rm dangling print

* fix PauliEvolution

* Update qiskit/dagcircuit/dagcircuit.py

Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>

---------

Co-authored-by: John Lapeyre <jlapeyre@users.noreply.github.com>
  • Loading branch information
Cryoris and jlapeyre authored Jul 1, 2024
1 parent 5deed7a commit 67fd35a
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 1 deletion.
7 changes: 7 additions & 0 deletions qiskit/dagcircuit/dagcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,13 @@ def replace_block_with_op(
block_cargs.sort(key=wire_pos_map.get)
new_node = DAGOpNode(op, block_qargs, block_cargs, dag=self)

# check the op to insert matches the number of qubits we put it on
if op.num_qubits != len(block_qargs):
raise DAGCircuitError(
f"Number of qubits in the replacement operation ({op.num_qubits}) is not equal to "
f"the number of qubits in the block ({len(block_qargs)})!"
)

try:
new_node._node_id = self._multi_graph.contract_nodes(
block_ids, new_node, check_cycle=cycle_check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ def run(self, dag: DAGCircuit) -> DAGCircuit:
sub_dag = self._decompose_to_2q(dag, node.op)

block_op = Commuting2qBlock(set(sub_dag.op_nodes()))
wire_order = {wire: idx for idx, wire in enumerate(dag.qubits)}
wire_order = {
wire: idx
for idx, wire in enumerate(sub_dag.qubits)
if wire not in sub_dag.idle_wires()
}
dag.replace_block_with_op([node], block_op, wire_order)

return dag
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fixes:
- |
Previously, :meth:`.DAGCircuit.replace_block_with_op` allowed to place an
``n``-qubit operation onto a block of ``m`` qubits, leaving the DAG in an
invalid state. This behavior has been fixed, and the attempt will raise
a :class:`.DAGCircuitError`.
16 changes: 16 additions & 0 deletions test/python/dagcircuit/test_dagcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2903,6 +2903,22 @@ def test_single_node_block(self):
self.assertEqual(expected_dag.count_ops(), dag.count_ops())
self.assertIsInstance(new_node.op, XGate)

def test_invalid_replacement_size(self):
"""Test inserting an operation on a wrong number of qubits raises."""

# two X gates, normal circuit
qc = QuantumCircuit(2)
qc.x(range(2))

# mutilate the DAG
dag = circuit_to_dag(qc)
to_replace = list(dag.op_nodes())
new_node = XGate()
idx_map = {node.qargs[0]: i for i, node in enumerate(to_replace)}

with self.assertRaises(DAGCircuitError):
dag.replace_block_with_op(to_replace, new_node, idx_map)

def test_replace_control_flow_block(self):
"""Test that we can replace a block of control-flow nodes with a single one."""
body = QuantumCircuit(1)
Expand Down

0 comments on commit 67fd35a

Please sign in to comment.