MultiStagePassManager
class qiskit.passmanager.MultiStagePassManager(**stages)
Basen: Generic[IR, IR_OUT]
Ein Manager für gestaffelte Übergaben, der mehrere IRs unterstützt.
Dieser Pass-Manager führt nacheinander benannte Phasen für das Eingabeprogramm aus. Eine Stufe kann als Task, als eine iterierbare Menge davon oder als definiert werden BasePassManager. BasePassManager Wird a als Stufe festgelegt, werden nur die darin enthaltenen Aufgaben ausgeführt; die durch die _passmanager_backend Methoden und _passmanager_frontend definierten Eingabe- und Ausgabekonvertierungen werden _nicht_ angewendet.
Stufen können:
Task[IR, IR]die IR beibehalten, beispielsweise wenn sie aufBasePassManager[IR]oder gesetzt ist, oder- den IR senken, zum Beispiel auf
Task[IR1, IR2].
Es liegt in der Verantwortung des Anwenders, die Stufen so aufeinander abzustimmen, dass der Ausgangs-IR der aktuellen Stufe mit dem Eingangs-IR der nächsten Stufe übereinstimmt. Die Namen der Phasen und die Reihenfolge, in der sie ausgeführt werden, werden beim Erstellen des Pass-Managers festgelegt. Die Implementierung einer Phase kann geändert werden, indem dem entsprechenden Objektattribut eine neue Implementierung zugewiesen wird.
Wird der run() Methode ein Callback übergeben, muss dieser in der Lage sein, IR-Eingaben jeglichen Typs zu verarbeiten, die von den Aufgaben im Pass-Manager ausgegeben werden.
Der Callback wird mit folgender Signatur aufgerufen:
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
):
...Alle Argumente werden als Schlüsselwortargumente übergeben.
Während das Objekt Task die Aufgabenschnittstelle definiert, sollten benutzerdefinierte Durchläufe ausschließlich von der Basisklasse abgeleitet sein GenericPass. Die Basis Task ist eine interne Schnittstelle, und spätere Qiskit-Versionen könnten weitere Einschränkungen hinsichtlich der verfügbaren Typen vorsehen Task.
Ein Beispiel für einen Arbeitsablauf ist:
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())Diese Klasse steht insofern mit StagedPassManager in Zusammenhang, als beide über ein stufenweises Ausführungsmodell verfügen. Das StagedPassManager erlaubt DAGCircuit jedoch nur als IR, verfügt über implizite Konvertierungen von und zu einem QuantumCircuit auf der Eingangs- und Ausgangsebene und besitzt implizite pre_* - und post_* -Stufen-Hooks, in die geschrieben werden kann.
Die Ausführungslogik eines StagedPassManager entspricht in etwa:
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)Das derzeitige Ausführungsmodell linearisiert den Durchlauf in einen FlowControllerLinear , um die Aufgaben auszuführen. Dieses zugrunde liegende Modell kann sich ändern, und es ist unsicher, sich auf diese Annahme zu stützen. Die öffentlichen Schnittstellen dieser Klasse sind jedoch stabil.
Parameter
stages (BasePassManager[Any] | Task[Any, Any] | Iterable[Task[Any, Any]]) –
Die Etappen als Passmanager. Diese werden in der angegebenen Reihenfolge ausgeführt und müssen kompatible IRs aufweisen.
Die Namen der Phasen werden vom Konstruktor festgelegt; Sie können später keine neuen Phasen hinzufügen, aber Sie können die Implementierung jeder Phase ersetzen, indem Sie ihr Attribut neu zuweisen.
Attribute
stages
Die Künstlernamen. Diese sind unveränderlich.
Die Stufen selbst können geändert werden, indem man das Attribut mit dem gleichen Namen wie die Stufe überschreibt.
Methoden
run
run(in_programs, callback=None, *, property_set=None)
Führen Sie den Pass-Manager für eine Reihe von Eingabeprogrammen aus.
Parameter
- in_programs (IR | list[IR] | tuple[IR]) – Die Programme, in denen der Pass-Manager ausgeführt werden soll.
- callback (Callable[[Task, Any, PropertySet, float, int], None] | None) – Ein Callback, der an jede einzelne Aufgabe übergeben wird.
- property_set (PropertySet | None) – Eine optionale Eigenschaft, die an den Pass-Manager übergeben werden soll. Dies wird, sofern angegeben, an Ort und Stelle geändert. Dies kann nicht in mehreren Programmen gleichzeitig verwendet werden.
Rückgabe
Die Ausgabeprogramme.
Rückgabetyp
IR_OUT | Iterable [ IR_OUT ]
to_flow_controller
to_flow_controller()
Wandeln Sie diesen mehrstufigen Durchsatzregler in einen linearen Durchflussregler um.
Durch diese Konvertierung wird dieser Pass-Manager in ein Task[IR, IR_OUT] normalisiert und kann somit in ein MultiStagePassManager selbst oder in andere Ausführungsabläufe eingebettet werden.
Rückgabetyp
Flow[* ControllerLinearIR*, IR_OUT]