# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2018.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""Check if the gates follow the right direction with respect to the coupling map."""
from qiskit.circuit import ControlFlowOp
from qiskit.converters import circuit_to_dag
from qiskit.transpiler.basepasses import AnalysisPass
[documentos]class CheckGateDirection(AnalysisPass):
"""Check if the two-qubit gates follow the right direction with
respect to the coupling map.
"""
def __init__(self, coupling_map, target=None):
"""CheckGateDirection initializer.
Args:
coupling_map (CouplingMap): Directed graph representing a coupling map.
target (Target): The backend target to use for this pass. If this is specified
it will be used instead of the coupling map
"""
super().__init__()
self.coupling_map = coupling_map
self.target = target
def _coupling_map_visit(self, dag, wire_map, edges=None):
if edges is None:
edges = self.coupling_map.get_edges()
# Don't include directives to avoid things like barrier, which are assumed always supported.
for node in dag.op_nodes(include_directives=False):
if isinstance(node.op, ControlFlowOp):
for block in node.op.blocks:
inner_wire_map = {
inner: wire_map[outer] for outer, inner in zip(node.qargs, block.qubits)
}
if not self._coupling_map_visit(circuit_to_dag(block), inner_wire_map, edges):
return False
elif (
len(node.qargs) == 2
and (wire_map[node.qargs[0]], wire_map[node.qargs[1]]) not in edges
):
return False
return True
def _target_visit(self, dag, wire_map):
# Don't include directives to avoid things like barrier, which are assumed always supported.
for node in dag.op_nodes(include_directives=False):
if isinstance(node.op, ControlFlowOp):
for block in node.op.blocks:
inner_wire_map = {
inner: wire_map[outer] for outer, inner in zip(node.qargs, block.qubits)
}
if not self._target_visit(circuit_to_dag(block), inner_wire_map):
return False
elif len(node.qargs) == 2 and not self.target.instruction_supported(
node.op.name, (wire_map[node.qargs[0]], wire_map[node.qargs[1]])
):
return False
return True
[documentos] def run(self, dag):
"""Run the CheckGateDirection pass on `dag`.
If `dag` is mapped and the direction is correct the property
`is_direction_mapped` is set to True (or to False otherwise).
Args:
dag (DAGCircuit): DAG to check.
"""
wire_map = {bit: i for i, bit in enumerate(dag.qubits)}
self.property_set["is_direction_mapped"] = (
self._coupling_map_visit(dag, wire_map)
if self.target is None
else self._target_visit(dag, wire_map)
)