Skip to main content
IBM Quantum Platform

Portas fracionárias

  • O código desta página foi desenvolvido usando os seguintes requisitos. Recomendamos o uso dessas versões ou de versões mais recentes.

    qiskit[all]~=2.3.1
    qiskit-ibm-runtime~=0.45.1
    

Esta página apresenta dois novos tipos de portas compatíveis com a frota de QPUs IBM Quantum®. Essas portas fracionárias são compatíveis com as QPUs Heron na forma de:

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

Esta página discute os casos de uso em que a implementação de portas fracionárias pode melhorar a eficiência de seus fluxos de trabalho, bem como a forma de usar essas portas em IBM Quantum QPUs.


Como usar portas fracionárias

Internamente, esses portões fracionários funcionam executando diretamente uma rotação RZZ(θ)R_{ZZ}(\theta) e RX(θ)R_X(\theta) para um ângulo arbitrário. O uso do portão RX(θ)R_X(\theta) pode reduzir a duração e o erro para rotações de qubit único de ângulo arbitrário em até um fator de dois. A execução direta da rotação do portão RZZ(θ)R_{ZZ}(\theta) evita a decomposição em múltiplos CZGate objetos, reduzindo de forma semelhante a duração e o erro de um circuito. Isso é especialmente útil para circuitos que contêm muitas rotações de um e dois qubits, como ao simular a dinâmica de um sistema quântico ou ao usar uma abordagem variacional com muitos parâmetros.

Embora esses tipos de portas façam parte do conjunto padrão de portas que um QuantumCircuit pode possuir, elas só podem ser usadas em QPUs específicas do IBM Quantum, e devem ser carregadas com o sinalizador use_fractional_gates definido como True (conforme mostrado abaixo). Este sinalizador garantirá que os portões fracionários sejam incluídos no backend Target do transpilador.

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

Esse exemplo de código demonstra como usar portas fracionárias no contexto de um fluxo de trabalho que simula a dinâmica de uma cadeia de Ising usando portas fracionárias. A duração do circuito é então comparada com um backend que não usa portas fracionárias.

Observação sobre as taxas de erro relatadas

O valor do erro informado no site Target de um backend com portas fracionárias ativadas é apenas uma cópia da contraparte da porta não fracionária (que pode não ser a mesma). Isso ocorre porque ainda não há suporte para o relatório de taxas de erro nas portas fracionárias.

No entanto, como o tempo de porta de portas fracionárias e não fracionárias é o mesmo, é razoável supor que suas taxas de erro sejam comparáveis, especialmente quando a fonte dominante de erro em um circuito se deve ao relaxamento.

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 dois objetos de backend: um com portas fracionárias ativadas e outro com elas desativadas e, em seguida, transpile os dois.

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)

Exiba a linha do tempo do circuito usando os dois tipos de portas.

# 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

Restrições de ângulo

Para a porta RZZ(θ)R_{ZZ}(\theta) de dois qubits, somente os ângulos entre 00 e π/2\pi/2 podem ser executados no hardware IBM Quantum. Se um circuito contiver qualquer porta RZZ(θ)R_{ZZ}(\theta) com um ângulo fora desse intervalo, o pipeline de transpilação padrão geralmente corrigirá isso com uma transformação de circuito apropriada (por meio da FoldRzzAngle passagem). Entretanto, para qualquer porta RZZ(θ)R_{ZZ}(\theta) que contenha um ou mais Parameters, o transpilador assumirá que esses parâmetros receberão ângulos dentro desse intervalo no tempo de execução. O trabalho falhará se algum dos valores de parâmetro especificados no PUB enviado para Qiskit Runtime estiver fora desse intervalo.


Onde usar portas fracionárias

Historicamente, as portas de base disponíveis em IBM Quantum QPUs têm sido CZ, X, RZ, SX, e IDπ/2\pi / 2 por exemplo, uma porta RX(θ)R_X(\theta), quando transpilada, deve se decompor em uma série de portas RZRZ e X\sqrt{X}, o que cria um circuito com duas portas de duração finita em vez de uma.

Da mesma forma, quando as rotações de dois qubits, como uma porta RZZ(θ)R_{ZZ}(\theta), são transpiladas, a decomposição requer duas portas e várias portas de um qubit, o que aumenta a profundidade do circuito CZ portas e várias portas de um único qubit, o que aumenta a profundidade do circuito. Essas decomposições são mostradas no código a seguir.

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 fluxos de trabalho que exigem muitas rotações de um único qubit RX(θ)R_X(\theta) ou de dois qubits (como em um ansatz variacional ou ao simular a evolução temporal de sistemas quânticos), essa restrição faz com que a profundidade do circuito aumente rapidamente. Entretanto, as portas fracionárias eliminam esse requisito, pois as rotações de um e dois qubits são executadas diretamente e criam um circuito quântico mais eficiente (e, portanto, com supressão de erros).


Quando não usar portas fracionárias

É importante observar que as portas fracionárias são um recurso experimental e o comportamento do sinalizador use_fractional_gates pode mudar no futuro. Consulte as notas de versão das novas versões do site Qiskit Runtime para obter mais informações. Consulte também a documentação de referência da API para QiskitRuntimeService.backend, que descreve use_fractional_gates.

Além disso, o transpilador do Qiskit tem capacidade limitada para usar o RZZ(θ)R_{ZZ}(\theta) em suas passagens de otimização. Isso exige que você tenha mais cuidado ao criar e otimizar os circuitos que contêm essas instruções.

Por fim, não há suporte para o uso de portas fracionárias:

Leia o guia sobre opções primitivas para saber mais sobre como personalizar as técnicas de atenuação e supressão de erros para uma determinada carga de trabalho quântica.


Quais backends suportam portas fracionárias?

Nem todos os back-ends oferecem suporte a portas fracionárias. Corra service.backends(use_fractional_gates=True) para encontrar aqueles que o fazem. Um backend falso só suporta portas fracionárias se o backend “real” correspondente também as suportar.

Observe que os backends falsos não oferecem suporte a portas fracionárias por padrão, uma vez que essas portas estão desativadas por padrão. Para habilitar portas fracionárias em um backend simulado que as suporte, atualize sua configuração.

Exemplo:

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

Próximas etapas

Recomendações
Esta página foi útil?
Relate um bug, erro de digitação ou solicite conteúdo no GitHub.