Skip to main content
IBM Quantum Platform

Puertas fraccionarias

  • 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.3.1
    qiskit-ibm-runtime~=0.45.1
    

En esta página se presentan dos nuevos tipos de puertas compatibles con la flota de QPUs Quantum® de IBM. Estas puertas fraccionarias se admiten en las QPU Heron en forma de:

  • RZZ(θ)R_{ZZ}(\theta) para 0<θπ/20 \lt \theta \leq \pi/2
  • RX(θ)R_X(\theta) para cualquier θ\theta

Esta página analiza los casos de uso en los que la implementación de puertas fraccionarias puede mejorar la eficiencia de sus flujos de trabajo, así como la forma de utilizar estas puertas en IBM Quantum QPUs.


Cómo utilizar las puertas fraccionarias

Internamente, estas puertas fraccionarias funcionan ejecutando directamente una rotación RZZ(θ)R_{ZZ}(\theta) y RX(θ)R_X(\theta) para un ángulo arbitrario. El uso de la puerta « RX(θ)R_X(\theta) » puede reducir la duración y el error de las rotaciones de un solo qubit de ángulo arbitrario hasta en un factor de dos. La ejecución directa de la rotación de puertas « RZZ(θ)R_{ZZ}(\theta) » evita la descomposición en múltiples CZGate objetos, lo que reduce de forma similar la duración y el error de un circuito. Esto resulta especialmente útil para circuitos que contienen muchas rotaciones de uno y dos qubits, como cuando se simula la dinámica de un sistema cuántico o cuando se utiliza un ansatz variacional con muchos parámetros.

Aunque este tipo de puertas forman parte de la biblioteca de puertas estándar de las que QuantumCircuit puede disponer un usuario, solo pueden utilizarse en determinadas QPU de IBM Quantum, y deben cargarse con el indicador use_fractional_gates activado True (como se muestra a continuación). Esta opción garantizará que las puertas fraccionarias se incluyan en el backend Target del transpilador.

service = QiskitRuntimeService()
backend = service.backend('ibm_torino', use_fractional_gates=True)

Este ejemplo de código demuestra cómo utilizar puertas fraccionarias en el contexto de un flujo de trabajo que simula la dinámica de una cadena de Ising utilizando puertas fraccionarias. A continuación, se compara la duración del circuito con un backend que no utiliza puertas fraccionarias.

Nota sobre los porcentajes de error notificados

El valor de error notificado en Target de un backend con puertas fraccionarias activadas es sólo una copia del homólogo de la puerta no fraccionaria (que puede no ser el mismo). Esto se debe a que aún no se admite la notificación de porcentajes de error en las puertas fraccionarias.

Sin embargo, dado que el tiempo de compuerta de las compuertas fraccionarias y no fraccionarias es el mismo, es razonable suponer que sus tasas de error son comparables, especialmente cuando la fuente dominante de error en un circuito se debe a la relajación.

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.visualization.timeline import draw as draw_timeline, IQXSimple

from qiskit_ibm_runtime import QiskitRuntimeService


num_qubits = 5
num_time_steps = 3
rx_angle = 0.1
rzz_angle = 0.1

ising_circuit = QuantumCircuit(num_qubits)
for i in range(num_time_steps):
    # rx layer
    for q in range(num_qubits):
        ising_circuit.rx(rx_angle, q)
    for q in range(1, num_qubits - 1, 2):
        ising_circuit.rzz(rzz_angle, q, q + 1)
    # 2nd rzz layer
    for q in range(0, num_qubits - 1, 2):
        ising_circuit.rzz(rzz_angle, q, q + 1)
    ising_circuit.barrier()
ising_circuit.draw("mpl")

Output:

Output of the previous code cell

Especifique dos objetos backend: uno con las puertas fraccionarias activadas y otro con ellas desactivadas, y transpile ambos.

service = QiskitRuntimeService()
backend_fractional = service.backend("ibm_torino", use_fractional_gates=True)
backend_conventional = service.backend(
    "ibm_torino", use_fractional_gates=False
)

pm_fractional = generate_preset_pass_manager(
    optimization_level=3, backend=backend_fractional, scheduling_method="alap"
)
pm_conventional = generate_preset_pass_manager(
    optimization_level=3,
    backend=backend_conventional,
    scheduling_method="alap",
)

ising_circuit_fractional = pm_fractional.run(ising_circuit)
ising_circuit_conventional = pm_conventional.run(ising_circuit)

Visualiza la cronología del circuito utilizando los dos tipos de compuertas.

# Draw timeline of circuit with conventional gates
draw_timeline(
    ising_circuit_conventional,
    idle_wires=False,
    target=backend_conventional.target,
    time_range=(0, 500),
    style=IQXSimple(),
)

Output:

Output of the previous code cell
# Draw timeline of circuit with fractional gates
draw_timeline(
    ising_circuit_fractional,
    idle_wires=False,
    target=backend_fractional.target,
    time_range=(0, 500),
    style=IQXSimple(),
)

Output:

Output of the previous code cell

Restricciones angulares

En el caso de la puerta « RZZ(θ)R_{ZZ}(\theta) » de dos qubits, en el hardware de IBM Quantum solo se pueden ejecutar los ángulos comprendidos entre 00 y π/2\pi/2. Si un circuito contiene alguna puerta « RZZ(θ)R_{ZZ}(\theta) » con un ángulo fuera de este rango, el proceso estándar de transpilación lo corregirá, por lo general, mediante una transformación adecuada del circuito (a través de la pasada FoldRzzAngle ). Sin embargo, para cualquier puerta « RZZ(θ)R_{ZZ}(\theta) » que contenga una o más Parameter«s», el transpilador asumirá que a estos parámetros se les asignarán ángulos dentro de este rango en tiempo de ejecución. La tarea fallará si alguno de los valores de los parámetros especificados en el archivo « PUB » enviado al servicio de computación de IBM Quantum se encuentra fuera de este intervalo.


Dónde utilizar puertas fraccionarias

Históricamente, las puertas base disponibles en IBM Quantum QPUs han sido CZ, X, RZ, **SX**y **ID**que no pueden representar eficientemente circuitos con rotaciones de uno y dos qubits que no sean múltiplos de π/2\pi / 2. Por ejemplo, una puerta RX(θ)R_X(\theta), cuando se transpila, debe descomponerse en una serie de puertas RZRZ y X\sqrt{X}, lo que crea un circuito con dos puertas de duración finita en lugar de una.

Del mismo modo, cuando se transpilan rotaciones de dos qubits como una puerta RZZ(θ)R_{ZZ}(\theta), la descomposición requiere dos CZ puertas y varias puertas de un solo qubit, lo que aumenta la profundidad del circuito. Estas descomposiciones se muestran en el siguiente código.

qc = QuantumCircuit(1)
param = Parameter("θ")
qc.rx(param, 0)
qc.draw("mpl")

Output:

Output of the previous code cell
# Decomposition of an RX(θ) gate using the IBM Quantum QPU basis
service = QiskitRuntimeService()
backend = service.backend("ibm_torino")
optimization_level = 3
pm = generate_preset_pass_manager(optimization_level, backend=backend)
transpiled_circuit = pm.run(qc)
transpiled_circuit.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.transpiler import generate_preset_pass_manager

from qiskit_ibm_runtime import QiskitRuntimeService

qc = QuantumCircuit(2)
param = Parameter("θ")
qc.rzz(param, 0, 1)
qc.draw("mpl")

Output:

Output of the previous code cell
# Decomposition of an RZZ(θ) gate using the IBM Quantum QPU basis
service = QiskitRuntimeService()
backend = service.backend("ibm_torino")
optimization_level = 3
pm = generate_preset_pass_manager(optimization_level, backend=backend)
transpiled_circuit = pm.run(qc)
transpiled_circuit.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Para los flujos de trabajo que requieren muchas rotaciones de un solo qubit RX(θ)R_X(\theta) o de dos qubits (como en un ansatz variacional o al simular la evolución temporal de sistemas cuánticos), esta restricción hace que la profundidad del circuito crezca rápidamente. Sin embargo, las puertas fraccionarias eliminan este requisito, ya que las rotaciones de uno y dos qubits se ejecutan directamente, y crean un circuito cuántico más eficiente (y, por tanto, con supresión de errores).


Cuándo no utilizar puertas fraccionarias

Es importante tener en cuenta que las puertas fraccionarias son una función experimental y que el comportamiento de este use_fractional_gates indicador podría cambiar en el futuro. Consulta las notas de la versión de las nuevas versiones de qiskit-ibm-runtime para obtener más información. Consulta también la documentación de referencia de la API de QiskitRuntimeService.backend, donde se describe use_fractional_gates...

Además, el transpilador Qiskit tiene una capacidad limitada para utilizar RZZ(θ)R_{ZZ}(\theta) en sus pases de optimización. Esto obliga a tener más cuidado a la hora de elaborar y optimizar los circuitos que contienen estas instrucciones.

Por último, no se admite el uso de puertas fraccionarias para:

Lea la guía sobre opciones primitivas para obtener más información sobre la personalización de las técnicas de mitigación y supresión de errores para una carga de trabajo cuántica determinada.


¿Qué backends admiten puertas fraccionarias?

No todos los backends admiten puertas fraccionarias. Corre service.backends(use_fractional_gates=True) para encontrar a los que sí lo hacen. Con el lanzamiento de v0.48qiskit-ibm-runtime , también puedes ejecutar la orden para service.least_busy(fractional_gates=True) encontrar el backend menos ocupado que admita puertas fraccionarias. Un backend falso solo admite puertas fraccionarias si el backend «real» correspondiente las admite.

Ten en cuenta que los backends falsos no admiten puertas fraccionarias de forma predeterminada, ya que estas están desactivadas por defecto. Para habilitar las puertas fraccionarias en un backend simulado que las admita, actualiza su configuración.

Ejemplo:

service = QiskitRuntimeService()
fake_backend = FakeBoston()
fake_backend.refresh(service=service, use_fractional_gates=True)

Próximos pasos

Recomendaciones
¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.