Skip to main content
IBM Quantum Platform

MultiStagePassManager

class qiskit.passmanager.MultiStagePassManager(**stages)

GitHub

Basi: Generic[IR, IR_OUT]

Un gestore di passaggi a tappe che supporta più IR.

Questo gestore di passaggi esegue fasi sequenziali e denominate sul programma di input. Uno stadio può essere definito come Task, un suo iterabile oppure come un BasePassManager. Se a BasePassManager viene impostato come stage, vengono eseguite solo le attività in esso contenute; le conversioni di input e output definite dai suoi _passmanager_backend metodi e _passmanager_frontend non vengono applicate.

Le fasi possono:

  • mantenere l'IR, ad esempio se impostato su BasePassManager[IR] o Task[IR, IR], oppure
  • ridurre l'IR, ad esempio a Task[IR1, IR2].

È responsabilità dell'utente configurare gli stadi in modo compatibile, in modo che la risposta in frequenza (IR) in uscita dello stadio corrente corrisponda alla risposta in frequenza (IR) in ingresso dello stadio successivo. I nomi delle fasi e l'ordine in cui vengono eseguite vengono definiti al momento della creazione del gestore dei passaggi. L'implementazione di una fase può essere modificata assegnando una nuova implementazione all'attributo dell'oggetto corrispondente.

Se al run() metodo viene fornita una callback, questa deve essere in grado di gestire un input IR di qualsiasi tipo generato dalle attività presenti nel gestore dei passaggi.

La funzione di callback viene chiamata con la seguente firma:

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
):
    ...

Tutti gli argomenti vengono passati come argomenti chiave.

Nota

Mentre l'oggetto Task definisce l'interfaccia dell'attività, i passaggi personalizzati dovrebbero derivare esclusivamente dalla classe base GenericPass. La base Task è un'interfaccia interna e le versioni successive di Qiskit potrebbero imporre ulteriori restrizioni sui tipi disponibili di Task.

Ecco un esempio di flusso di lavoro:

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())

Questa classe è correlata a StagedPassManager in quanto entrambe presentano un modello di esecuzione per fasi. Il StagedPassManager, tuttavia, ammette DAGCircuit solo come IR, prevede conversioni implicite da e verso un QuantumCircuit a livello di input e output, e dispone di hook impliciti pre_* per gli stadi e post_* in cui è possibile scrivere.

La logica di esecuzione di un StagedPassManager è sostanzialmente equivalente a:

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)
Avvertenza

L'attuale modello di esecuzione linearizza il passaggio in un FlowControllerLinear per eseguire le attività. Questo modello di base è soggetto a modifiche e non è sicuro basarsi su tale presupposto. Le interfacce pubbliche di questa classe, tuttavia, sono stabili.

Parametri

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

Le fasi in qualità di responsabili dei pass. Questi verranno eseguiti nell'ordine indicato e devono avere IR compatibili.

I nomi delle fasi sono fissati dal costruttore; non è possibile aggiungere nuove fasi in un secondo momento, ma è possibile sostituire l'implementazione di ciascuna fase riassegnando il relativo attributo.


Attributi

stages

I nomi d'arte. Questi sono immutabili.

Le fasi stesse possono essere modificate scrivendo nell'attributo che porta lo stesso nome della fase.


Metodi

run

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

GitHub

Eseguire il gestore dei passaggi su una serie di programmi di input.

Parametri

  • in_programs (IR | list[IR] | tuple[IR]) – I programmi su cui eseguire il gestore dei pass.
  • callback (Callable[[Task, Any, PropertySet, float, int], None] | None) – Una funzione di callback passata a ogni singola attività.
  • property_set (PropertySet | None) – Una proprietà facoltativa da passare al gestore dei pass. Se specificato, verrà modificato in loco. Non è possibile utilizzarlo con più programmi contemporaneamente.

Risultati

I programmi di output.

Tipo di restituzione

IR_OUT | Iterable [ IR_OUT ]

to_flow_controller

to_flow_controller()

GitHub

Converti questo gestore di passaggi a più stadi in un regolatore di flusso lineare.

Questa conversione normalizza questo gestore di passaggi in un Task[IR, IR_OUT] e ne consente l'annidamento all'interno di un MultiStagePassManager stesso o di altri flussi di esecuzione.

Tipo di restituzione

Flow[* ControllerLinearIR*, IR_OUT]

Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.