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

Para la puerta de dos qubits RZZ(θ)R_{ZZ}(\theta), sólo los ángulos entre 00 y π/2\pi/2 pueden ejecutarse en el hardware IBM Quantum. Si un circuito contiene alguna compuerta RZZ(θ)R_{ZZ}(\theta) con un ángulo fuera de este rango, entonces el pipeline de transpilación estándar generalmente lo corregirá con una transformación de circuito apropiada (a través del FoldRzzAngle pass). Sin embargo, para cualquier puerta RZZ(θ)R_{ZZ}(\theta) que contenga una o más Parameters, el transpilador asumirá que a estos parámetros se les asignarán ángulos dentro de este rango en tiempo de ejecución. El trabajo fallará si alguno de los valores de los parámetros especificados en PUB enviados a Qiskit Runtime están fuera de este rango.


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 señalar que las puertas fraccionales son una característica experimental y el comportamiento de la bandera use_fractional_gates puede cambiar en el futuro. Para más información, consulte las notas de la nueva versión de Qiskit Runtime. Consulte también la documentación de referencia de la API para QiskitRuntimeService.backend, que 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. 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.