Skip to main content
IBM Quantum Platform

MultiStagePassManager

class qiskit.passmanager.MultiStagePassManager(**stages)

GitHub

Bases : Generic[IR, IR_OUT]

Un gestionnaire de passes par étapes prenant en charge plusieurs IR.

Ce gestionnaire de passes exécute des étapes séquentielles et nommées sur le programme d'entrée. Une étape peut être définie comme Task, un itérable de celle-ci, ou comme un BasePassManager. Si un BasePassManager est défini comme étape, seules les tâches qu’il contient sont exécutées; les conversions d’entrée et de sortie définies par ses _passmanager_backend méthodes et _passmanager_frontend ne sont _pas_ appliquées.

Les étapes permettent de :

  • conserver l'IR, par exemple s'il est défini sur BasePassManager[IR] ou Task[IR, IR], ou
  • réduire l'IR, par exemple à Task[IR1, IR2].

Il incombe à l'utilisateur de configurer les étages de manière compatible, de sorte que la réponse en impulsion (IR) de sortie de l'étage actuel corresponde à la réponse en impulsion (IR) d'entrée de l'étage suivant. Les noms des étapes et l'ordre dans lequel elles s'exécutent sont définis lors de la création du gestionnaire de passes. L'implémentation d'une étape peut être modifiée en attribuant une nouvelle implémentation à l'attribut correspondant de l'objet.

Si une fonction de rappel est fournie à la run() méthode, elle doit être capable de gérer le fait que son entrée IR puisse correspondre à n'importe quel type de sortie généré par les tâches du gestionnaire de passes.

La fonction de rappel est appelée avec la signature suivante :

def callback(
    task: Task,  # the executed task
    passmanager_ir: Any,  # the IR after the task execution
    property_set: PropertySet,  # the property set after execution
    running_time: float,  # the time the task ran
    count: int  # the number of executed tasks so far
):
    ...

Tous les arguments sont transmis sous forme d'arguments par mot-clé.

Remarque

Alors que l'objet Task définit l'interface de la tâche, les passes personnalisées ne doivent dériver que de la classe de base GenericPass. La base Task est une interface interne, et les prochaines versions de Qiskit pourraient imposer davantage de restrictions quant aux types disponibles Task.

Voici un exemple de flux de travail :

from qiskit.circuit import QuantumCircuit
from qiskit.dagcircuit import DAGCircuit
from qiskit.passmanager import GenericPass, MultiStagePassManager
from qiskit.transpiler import generate_preset_pass_manager, Target, CouplingMap

class CustomPauliIR:
    # A custom IR of global Pauli strings
    def __init__(self, num_qubits):
        self.num_qubits = num_qubits
        self.paulis = []

    def apply(self, pauli: str):
        assert len(pauli) == self.num_qubits
        self.paulis.append(pauli)

class CustomPauliOptimization(GenericPass[CustomPauliIR, CustomPauliIR]):
    # A pass run on the custom Pauli IR
    def run(self, passmanager_ir: CustomPauliIR) -> CustomPauliIR:
        to_remove = []
        for i, pauli in enumerate(passmanager_ir.paulis):
            if all(p == "I" for p in pauli):
                to_remove.append(i)

        for i in reversed(to_remove):
            del passmanager_ir.paulis[i]

        return passmanager_ir

class PauliToDAG(GenericPass[CustomPauliIR, DAGCircuit]):
    # A pass converting CustomPauliIR to DAGCircuit
    def run(self, passmanager_ir: CustomPauliIR) -> DAGCircuit:
        circuit = QuantumCircuit(passmanager_ir.num_qubits)
        for pauli in passmanager_ir.paulis:
            circuit.pauli(pauli, circuit.qubits)
        return circuit.to_dag()

def callback(task, passmanager_ir, property_set, running_time, count):
    if isinstance(passmanager_ir, CustomPauliIR):
        print("PauliIR:", task.__class__.__name__, passmanager_ir.paulis)
    else:
        print("DAGCircuit:", task.__class__.__name__, passmanager_ir.count_ops())

target = Target.from_configuration(
    basis_gates=["u", "cx"], coupling_map=CouplingMap.from_line(3)
)
multi_pm = MultiStagePassManager(
    pauli_opt=CustomPauliOptimization(),
    pauli_to_dag=PauliToDAG(),
    dag_opt=generate_preset_pass_manager(target=target),
)

program = CustomPauliIR(3)
program.apply("XYZ")
program.apply("III")
program.apply("ZZI")

out = multi_pm.run(program, callback=callback)
print(out.count_ops())

Cette classe est apparentée à StagedPassManager dans la mesure où toutes deux présentent un modèle d'exécution par étapes. Le StagedPassManager, cependant, n'autorise DAGCircuit que comme IR, dispose de conversions implicites depuis et vers un QuantumCircuit aux niveaux d'entrée et de sortie, et comporte des hooks implicites pre_* de stade et post_* dans lesquels il est possible d'écrire.

La logique d'exécution d'un StagedPassManager est à peu près équivalente à :

from qiskit.circuit import QuantumCircuit
from qiskit.dagcircuit import DAGCircuit
from qiskit.passmanager import GenericPass, MultiStagePassManager
from qiskit.transpiler import TranspileLayout

class CircuitToDAG(GenericPass[QuantumCircuit, DAGCircuit]):
    def run(self, passmanager_ir: QuantumCircuit) -> DAGCircuit:
        self.property_set["original_qubit_indices"] = {
            bit: i for i, bit in enumerate(passmanager_ir.qubits)
        }
        self.property_set["num_input_qubits"] = passmanager_ir.num_qubits
        return passmanager_ir.to_dag()

class DAGToCircuit(GenericPass[DAGCircuit, QuantumCircuit]):
    def run(self, passmanager_ir: DAGCircuit) -> QuantumCircuit:
        qc = passmanager_ir.to_circuit(copy_operations=False)
        qc._layout = TranspileLayout.from_property_set(passmanager_ir, self.property_set)
        return qc

multi_pm = MultiStagePassManager(
    input=CircuitToDAG(),
    # ... stages of StagedPassManager ...
    output=DAGToCircuit()
)

input_circuit = QuantumCircuit(1)
output_circuit = multi_pm.run(input_circuit)
Avertissement

Le modèle d'exécution actuel linéarise le passage en un FlowControllerLinear afin d'exécuter les tâches. Ce modèle sous-jacent est susceptible d'évoluer et il n'est pas prudent de se baser sur cette hypothèse. Les interfaces publiques de cette classe sont toutefois stables.

Paramètres

stages (BasePassManager[Any] | Task[Any, Any] | Iterable[Task[Any, Any]]) –

Les étapes en tant que gestionnaires de passes. Celles-ci seront exécutées dans l'ordre indiqué et doivent avoir des IR compatibles.

Les noms des étapes sont définis par le constructeur; vous ne pouvez pas ajouter de nouvelles étapes par la suite, mais vous pouvez remplacer l'implémentation de chaque étape en réaffectant son attribut.


Attributs

stages

Les noms de scène. Ceux-ci sont immuables.

Les étapes elles-mêmes peuvent être modifiées en écrivant dans l'attribut portant le même nom que l'étape.


Méthodes

run

run(in_programs, callback=None, *, property_set=None)

GitHub

Exécutez le gestionnaire de passes sur un ensemble de programmes d'entrée.

Paramètres

  • in_programs (IR | list[IR] | tuple[IR]) – Les programmes sur lesquels le gestionnaire de mots de passe doit s'exécuter.
  • callback (Callable[[Task, Any, PropertySet, float, int], None] | None) – Une fonction de rappel transmise à chaque tâche individuelle.
  • property_set (PropertySet | None) – Une propriété facultative à transmettre au gestionnaire de passes. Si cette valeur est fournie, elle sera modifiée directement. Cette fonctionnalité ne peut pas être utilisée avec plusieurs programmes.

Retours

Les programmes de sortie.

Type de retour

IR_OUT | Iterable [ IR_OUT ]

to_flow_controller

to_flow_controller()

GitHub

Convertissez ce gestionnaire de passages à plusieurs étapes en un régulateur de débit linéaire.

Cette conversion normalise ce gestionnaire de passes en un Task[IR, IR_OUT] et permet de l'imbriquer à l'intérieur d'un MultiStagePassManager lui-même ou d'autres flux d'exécution.

Type de retour

Flow[* ControllerLinearIR*, IR_OUT]

Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.