Establecer el nivel de optimización del transpilador
El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos. Recomendamos utilizar estas versiones o versiones más recientes.
qiskit[all]~=2.5.0 qiskit-ibm-runtime~=0.47.0
Los dispositivos cuánticos reales están sujetos a ruido y errores de puerta, por lo que optimizar los circuitos para reducir su profundidad y el número de puertas puede mejorar significativamente los resultados obtenidos al ejecutar esos circuitos.
La función generate_preset_pass_manager tiene un argumento posicional obligatorio, optimization_level, que controla cuánto esfuerzo dedica el transpilador a optimizar los circuitos. Este argumento puede ser un número entero con uno de los valores 0, 1, 2 ó 3.
Los niveles de optimización más altos generan circuitos más optimizados a costa de tiempos de compilación más largos.
En la tabla siguiente se explican las optimizaciones realizadas con cada ajuste.
Nivel de optimización | Descripción |
|---|---|
| 0 | Sin optimización: se utiliza normalmente para la caracterización del hardware
|
| 1 | Optimización de la luz:
|
| 2 | Optimización media:
|
| 3 | Alta optimización:
|
Nivel de optimización en acción
Dado que las puertas de dos qubits suelen ser la fuente más importante de errores, podemos cuantificar aproximadamente la "eficiencia de hardware" de la transpilación contando el número de puertas de dos qubits en el circuito resultante. Aquí probaremos los distintos niveles de optimización en un circuito de entrada formado por un unitario aleatorio seguido de una puerta SWAP.
from qiskit import QuantumCircuit
from qiskit.circuit.library import UnitaryGate
from qiskit.quantum_info import Operator, random_unitary
UU = random_unitary(4, seed=12345)
rand_U = UnitaryGate(UU)
qc = QuantumCircuit(2)
qc.append(rand_U, range(2))
qc.swap(0, 1)
qc.draw("mpl", style="iqp")Output:
En estos ejemplos se utiliza el backend FakeSherbrooke``qiskit_ibm_runtime simulado de, pero puedes probarlo con cualquier backend real o simulado compatible con Qiskit. Tus resultados pueden ser diferentes.
En primer lugar, vamos a transpilar utilizando el nivel de optimización 0.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
pass_manager = generate_preset_pass_manager(
optimization_level=0, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)Output:
El circuito transpilado tiene seis de las puertas ECR de dos qubits.
Repita la operación para el nivel de optimización 1:
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
pass_manager = generate_preset_pass_manager(
optimization_level=1, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)Output:
El circuito transpilado sigue teniendo seis puertas ECR, pero el número de puertas single-qubit se ha reducido.
Repita la operación para el nivel de optimización 2:
pass_manager = generate_preset_pass_manager(
optimization_level=2, backend=backend, seed_transpiler=12345
)
qc_t2_exact = pass_manager.run(qc)
qc_t2_exact.draw("mpl", idle_wires=False)Output:
Se obtienen los mismos resultados que en el nivel de optimización 1. Tenga en cuenta que aumentar el nivel de optimización no siempre marca la diferencia.
Repita de nuevo, con el nivel de optimización 3:
pass_manager = generate_preset_pass_manager(
optimization_level=3, backend=backend, seed_transpiler=12345
)
qc_t3_exact = pass_manager.run(qc)
qc_t3_exact.draw("mpl", idle_wires=False)Output:
Ahora, sólo hay tres puertas ECR. Obtenemos este resultado porque en el nivel de optimización 3, Qiskit intenta resintetizar bloques de puertas de dos qubits, y cualquier puerta de dos qubits puede implementarse utilizando como máximo tres puertas ECR. Podemos obtener incluso menos compuertas ECR si establecemos approximation_degree en un valor inferior a 1, permitiendo al transpilador realizar aproximaciones que pueden introducir algún error en la descomposición de la compuerta (véase Parámetros de uso común para la transpilación ):
pass_manager = generate_preset_pass_manager(
optimization_level=3,
approximation_degree=0.99,
backend=backend,
seed_transpiler=12345,
)
qc_t3_approx = pass_manager.run(qc)
qc_t3_approx.draw("mpl", idle_wires=False)Output:
Este circuito sólo tiene dos puertas ECR, pero es un circuito aproximado. Para entender en qué difiere su efecto del circuito exacto, podemos calcular la fidelidad entre el operador unitario que implementa este circuito y el unitario exacto. Antes de realizar el cálculo, primero reducimos el circuito transpilado, que contiene 127 qubits, a un circuito que sólo contiene los qubits activos, que son dos.
import numpy as np
def trace_to_fidelity_2q(trace: float) -> float:
return (4.0 + trace * trace.conjugate()) / 20.0
# Reduce circuits down to 2 qubits so they are easy to simulate
qc_t3_exact_small = QuantumCircuit.from_instructions(qc_t3_exact)
qc_t3_approx_small = QuantumCircuit.from_instructions(qc_t3_approx)
# Compute the fidelity
exact_fid = trace_to_fidelity_2q(
np.trace(np.dot(Operator(qc_t3_exact_small).adjoint().data, UU))
)
approx_fid = trace_to_fidelity_2q(
np.trace(np.dot(Operator(qc_t3_approx_small).adjoint().data, UU))
)
print(
f"Synthesis fidelity\nExact: {exact_fid:.3f}\nApproximate: {approx_fid:.3f}"
)Output:
Synthesis fidelity
Exact: 1.000+0.000j
Approximate: 0.992+0.000j
Ajustar el nivel de optimización puede modificar también otros aspectos del circuito, no solo el número de puertas ECR. Para ver ejemplos de cómo la configuración del nivel de optimización modifica la disposición, consulta «Representación de ordenadores cuánticos ».
Próximos pasos
- Para saber más sobre la función
generate_preset_passmanager, empiece por el tema Ajustes por defecto y opciones de configuración de la transpilación. - Continúe aprendiendo sobre la transpilación con el tema Etapas del transpilador.
- Prueba la guía de configuración del transpilador Compare.
- Prueba el tutorial Construir códigos de repetición.
- Consulte la documentación de la API de Transpile.