MultiStagePassManager
class qiskit.passmanager.MultiStagePassManager(**stages)
Bases: Generic[IR, IR_OUT]
Un gestor de pases por etapas compatible con múltiples IR.
Este gestor de pasadas ejecuta etapas secuenciales y con nombre en el programa de entrada. Una etapa puede definirse como Task, un iterable de la misma o como un BasePassManager. Si BasePassManager se establece un como etapa, solo se ejecutan las tareas que contiene; las conversiones de entrada y salida definidas por sus _passmanager_backend métodos _passmanager_frontend y _no_ se aplican.
Las etapas pueden:
- mantener el IR, por ejemplo, si se establece como
BasePassManager[IR]oTask[IR, IR], o - reducir el IR, por ejemplo, a
Task[IR1, IR2].
Es responsabilidad del usuario configurar las etapas de forma que sean compatibles entre sí, de modo que la respuesta en frecuencia (IR) de salida de la etapa actual coincida con la respuesta en frecuencia (IR) de entrada de la etapa siguiente. Los nombres de las etapas y el orden en que se ejecutan se establecen al crear el gestor de pases. La implementación de una etapa se puede modificar asignando una nueva implementación al atributo correspondiente del objeto.
Si se proporciona una función de devolución de llamada al run() método, esta debe ser capaz de gestionar que su entrada IR sea de cualquier tipo de salida generado por las tareas del gestor de pasadas.
La función de devolución de llamada se invoca con la siguiente 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
):
...Todos los argumentos se pasan como argumentos de palabra clave.
Si bien el objeto Task define la interfaz de la tarea, las pasadas personalizadas solo deben derivarse de la clase base GenericPass. La base Task es una interfaz interna, y es posible que en futuras versiones de Qiskit se impongan más restricciones sobre los tipos disponibles de Task.
Un ejemplo de flujo de trabajo es:
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())Esta clase guarda relación con StagedPassManager en el sentido de que ambas tienen un modelo de ejecución por etapas. Sin StagedPassManager embargo, solo admite DAGCircuit como IR, cuenta con conversiones implícitas desde y hacia un QuantumCircuit en los niveles de entrada y salida, y dispone de ganchos implícitos pre_* de las etapas y post_* en los que se puede escribir.
La lógica de ejecución de un StagedPassManager es, a grandes rasgos, 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)El modelo de ejecución actual linealiza el paso en un FlowControllerLinear para ejecutar las tareas. Este modelo subyacente está sujeto a cambios y no es seguro basarse en esta suposición. Sin embargo, las interfaces públicas de esta clase son estables.
Parámetros
stages (BasePassManager[Any] | Task[Any, Any] | Iterable[Task[Any, Any]]) –
Las etapas como gestores de pasos. Se ejecutarán en el orden indicado y deben tener IR compatibles.
Los nombres de las etapas los establece el constructor; no se pueden añadir nuevas etapas posteriormente, pero sí se puede sustituir la implementación de cada etapa reasignando su atributo.
Atributos
stages
Los nombres artísticos. Son inmutables.
Las etapas en sí mismas se pueden modificar escribiendo en el atributo que lleva el mismo nombre que la etapa.
Métodos
run
run(in_programs, callback=None, *, property_set=None)
Ejecuta el gestor de pases en un conjunto de programas de entrada.
Parámetros
- in_programs (IR | list[IR] | tuple[IR]) – Los programas en los que se ejecutará el gestor de contraseñas.
- callback (Callable[[Task, Any, PropertySet, float, int], None] | None) – Una función de devolución de llamada que se pasa a cada tarea individual.
- property_set (PropertySet | None) – Una propiedad opcional que se va a pasar al gestor de pases. Si se proporciona, se modificará in situ. Esto no se puede utilizar con múltiples programas.
Devuelve
Los programas de salida.
Tipo de retorno
IR_OUT | Iterable [ IR_OUT ]
to_flow_controller
to_flow_controller()
Convierte este gestor de pasos de varias etapas en un controlador de flujo lineal.
Esta conversión normaliza este gestor de pasadas en un Task[IR, IR_OUT] y permite anidarlo dentro de MultiStagePassManager un o de otros flujos de ejecución.
Tipo de retorno
Flow[* ControllerLinearIR*, IR_OUT]