Source code for qiskit.transpiler.passes.basis.unroll_3q_or_more

# 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.

"""Recursively expands 3q+ gates until the circuit only contains 2q or 1q gates."""

from qiskit.transpiler.basepasses import TransformationPass
from qiskit.transpiler.passes.utils import control_flow
from qiskit.exceptions import QiskitError
from qiskit.circuit import ControlFlowOp
from qiskit.converters.circuit_to_dag import circuit_to_dag


[docs]class Unroll3qOrMore(TransformationPass): """Recursively expands 3q+ gates until the circuit only contains 2q or 1q gates.""" def __init__(self, target=None, basis_gates=None): """Initialize the Unroll3qOrMore pass Args: target (Target): The target object representing the compilation target. If specified any multi-qubit instructions in the circuit when the pass is run that are supported by the target device will be left in place. If both this and ``basis_gates`` are specified only the target will be checked. basis_gates (list): A list of basis gate names that the target device supports. If specified any gate names in the circuit which are present in this list will not be unrolled. If both this and ``target`` are specified only the target will be used for checking which gates are supported. """ super().__init__() self.target = target self.basis_gates = None if basis_gates is not None: self.basis_gates = set(basis_gates)
[docs] def run(self, dag): """Run the Unroll3qOrMore pass on `dag`. Args: dag(DAGCircuit): input dag Returns: DAGCircuit: output dag with maximum node degrees of 2 Raises: QiskitError: if a 3q+ gate is not decomposable """ for node in dag.multi_qubit_ops(): if dag.has_calibration_for(node): continue if isinstance(node.op, ControlFlowOp): node.op = control_flow.map_blocks(self.run, node.op) continue if self.target is not None: # Treat target instructions as global since this pass can be run # prior to layout and routing we don't have phsyical qubits from # the circuit yet if node.name in self.target: continue elif self.basis_gates is not None and node.name in self.basis_gates: continue # TODO: allow choosing other possible decompositions rule = node.op.definition.data if not rule: if rule == []: # empty node dag.remove_op_node(node) continue raise QiskitError( "Cannot unroll all 3q or more gates. " "No rule to expand instruction %s." % node.op.name ) decomposition = circuit_to_dag(node.op.definition, copy_operations=False) decomposition = self.run(decomposition) # recursively unroll dag.substitute_node_with_dag(node, decomposition) return dag