Skip to content

Commit

Permalink
Merge branch 'main' of github.com:Qiskit/qiskit-terra into integratio…
Browse files Browse the repository at this point in the history
…n/cf-opt-2-3
  • Loading branch information
kevinhartman committed Jul 6, 2023
2 parents b2e303e + 163875e commit 45dc1e2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 27 deletions.
50 changes: 23 additions & 27 deletions qiskit/transpiler/passes/utils/check_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from qiskit.transpiler.basepasses import AnalysisPass
from qiskit.transpiler.target import Target
from qiskit.circuit.controlflow import ControlFlowOp
from qiskit.converters import circuit_to_dag


class CheckMap(AnalysisPass):
Expand Down Expand Up @@ -64,35 +65,30 @@ def run(self, dag):
Args:
dag (DAGCircuit): DAG to map.
"""
from qiskit.converters import circuit_to_dag

self.property_set[self.property_set_field] = True

if not self.qargs:
self.property_set[self.property_set_field] = True
return
wire_map = {bit: index for index, bit in enumerate(dag.qubits)}
self.property_set[self.property_set_field] = self._recurse(dag, wire_map)

qubit_indices = {bit: index for index, bit in enumerate(dag.qubits)}
def _recurse(self, dag, wire_map) -> bool:
for node in dag.op_nodes(include_directives=False):
is_controlflow_op = isinstance(node.op, ControlFlowOp)
if len(node.qargs) == 2 and not is_controlflow_op:
if dag.has_calibration_for(node):
continue
physical_q0 = qubit_indices[node.qargs[0]]
physical_q1 = qubit_indices[node.qargs[1]]
if (physical_q0, physical_q1) not in self.qargs:
self.property_set["check_map_msg"] = "{}({}, {}) failed".format(
node.name,
physical_q0,
physical_q1,
)
self.property_set[self.property_set_field] = False
return
elif is_controlflow_op:
order = [qubit_indices[bit] for bit in node.qargs]
if isinstance(node.op, ControlFlowOp):
for block in node.op.blocks:
dag_block = circuit_to_dag(block)
mapped_dag = dag.copy_empty_like()
mapped_dag.compose(dag_block, qubits=order)
self.run(mapped_dag)
if not self.property_set[self.property_set_field]:
return
inner_wire_map = {
inner: wire_map[outer] for inner, outer in zip(block.qubits, node.qargs)
}
if not self._recurse(circuit_to_dag(block), inner_wire_map):
return False
elif (
len(node.qargs) == 2
and not dag.has_calibration_for(node)
and (wire_map[node.qargs[0]], wire_map[node.qargs[1]]) not in self.qargs
):
self.property_set["check_map_msg"] = "{}({}, {}) failed".format(
node.name,
wire_map[node.qargs[0]],
wire_map[node.qargs[1]],
)
return False
return True
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
The :class:`.CheckMap` transpiler pass will no longer spuriously error when dealing with nested
conditional structures created by the control-flow builder interface. See `#10394
<https://github.com/Qiskit/qiskit-terra/issues/10394>`__.
22 changes: 22 additions & 0 deletions test/python/transpiler/test_check_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,28 @@ def test_nested_controlflow_false(self):
pass_.run(dag)
self.assertFalse(pass_.property_set["is_swap_mapped"])

def test_nested_conditional_unusual_bit_order(self):
"""Test that `CheckMap` succeeds when inner conditional blocks have clbits that are involved
in their own (nested conditionals), and the binding order is not the same as the
bit-definition order. See gh-10394."""
qr = QuantumRegister(2, "q")
cr1 = ClassicalRegister(2, "c1")
cr2 = ClassicalRegister(2, "c2")

# Note that the bits here are not in the same order as in the outer circuit object, but they
# are the same as the binding order in the `if_test`, so everything maps `{x: x}` and it
# should all be fine. This kind of thing is a staple of the control-flow builders.
inner_order = [cr2[0], cr1[0], cr2[1], cr1[1]]
inner = QuantumCircuit(qr, inner_order, cr1, cr2)
inner.cx(0, 1).c_if(cr2, 3)

outer = QuantumCircuit(qr, cr1, cr2)
outer.if_test((cr1, 3), inner, outer.qubits, inner_order)

pass_ = CheckMap(CouplingMap.from_line(2))
pass_(outer)
self.assertTrue(pass_.property_set["is_swap_mapped"])


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

0 comments on commit 45dc1e2

Please sign in to comment.