Criar um gerenciador de passes para desacoplamento dinâmico
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.5.1 qiskit-ibm-runtime~=0.47.0
Esta página demonstra como usar o PadDynamicalDecoupling para adicionar uma técnica de supressão de erros chamada desacoplamento dinâmico ao circuito.
O desacoplamento dinâmico funciona adicionando sequências de pulso (conhecidas como sequências de desacoplamento dinâmico ) a qubits ociosos para girá-los em torno da esfera de Bloch, o que cancela o efeito dos canais de ruído, suprimindo assim a decoerência. Essas sequências de pulsos são semelhantes aos pulsos de reorientação usados na ressonância magnética nuclear. Para obter uma descrição completa, consulte A Quantum Engineer's Guide to Superconducting Qubits (Guia do engenheiro quântico para Qubits supercondutores ).
Como a passagem PadDynamicalDecoupling opera somente em circuitos programados e envolve portas que não são necessariamente portas de base do nosso alvo, você precisará dos parâmetros ALAPScheduleAnalysis e BasisTranslator também.
Obtenha as target informações do backend e salve os nomes das operações como, basis_gates pois o target precisará ser modificado para adicionar informações de temporização para as portas utilizadas no desacoplamento dinâmico.
Nestes exemplos, é utilizado o backend FakeSherbrooke``qiskit_ibm_runtime simulado do, mas você pode testá-lo em qualquer backend real ou simulado compatível com o Qiskit. Seus resultados podem ser diferentes.
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
target = backend.target
basis_gates = list(target.operation_names)Crie um circuito efficient_su2 como exemplo. Primeiro, transpile o circuito para o backend porque os pulsos de desacoplamento dinâmico precisam ser adicionados depois que o circuito tiver sido transpilado e programado. A dissociação dinâmica geralmente funciona melhor quando há muito tempo ocioso nos circuitos quânticos, ou seja, há qubits que não estão sendo usados enquanto outros estão ativos. Esse é o caso desse circuito porque as portas de dois qubits ecr são aplicadas sequencialmente nesse ansatz.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit.library import efficient_su2
qc = efficient_su2(12, entanglement="circular", reps=1)
pm = generate_preset_pass_manager(1, target=target, seed_transpiler=12345)
qc_t = pm.run(qc)
qc_t.draw("mpl", fold=-1, idle_wires=False)Output:
Uma sequência de desacoplamento dinâmico é uma série de portas que compõem a identidade e são espaçadas regularmente no tempo. Por exemplo, comece criando uma sequência simples chamada XY4 que consiste em quatro portas.
from qiskit.circuit.library import XGate, YGate
X = XGate()
Y = YGate()
dd_sequence = [X, Y, X, Y]Devido ao tempo regular das sequências de desacoplamento dinâmico, as informações sobre o YGate devem ser adicionadas ao target porque ele não é um portão básico, ao passo que o XGate é. Sabemos a priori que o YGate tem a mesma duração e erro que o XGate, portanto, podemos simplesmente recuperar essas propriedades do target e adicioná-las de volta aos YGate objetos. É também por isso que os basis_gates foram salvos separadamente, já que estamos adicionando a YGate instrução ao, target embora não seja um portão base real do ibm_fez.
from qiskit.transpiler import InstructionProperties
y_gate_properties = {}
for qubit in range(target.num_qubits):
y_gate_properties.update(
{
(qubit,): InstructionProperties(
duration=target["x"][(qubit,)].duration,
error=target["x"][(qubit,)].error,
)
}
)
target.add_instruction(YGate(), y_gate_properties)Os circuitos Ansatz, como o efficient_su2 , são parametrizados, portanto, devem ter um valor vinculado a eles antes de serem enviados ao backend. Aqui, atribua parâmetros aleatórios.
import numpy as np
rng = np.random.default_rng(1234)
qc_t.assign_parameters(
rng.uniform(-np.pi, np.pi, qc_t.num_parameters), inplace=True
)Em seguida, execute os passes personalizados. Instanciar o PassManager com ALAPScheduleAnalysis e PadDynamicalDecoupling. Execute ALAPScheduleAnalysis primeiro para adicionar informações de tempo sobre o circuito quântico antes que as sequências de desacoplamento dinâmico com espaçamento regular possam ser adicionadas. Esses passes são executados no circuito com .run().
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes.scheduling import (
ALAPScheduleAnalysis,
PadDynamicalDecoupling,
)
dd_pm = PassManager(
[
ALAPScheduleAnalysis(target=target),
PadDynamicalDecoupling(target=target, dd_sequence=dd_sequence),
]
)
qc_dd = dd_pm.run(qc_t)Use a ferramenta de timeline_drawer visualização para ver o tempo do circuito e confirmar que uma sequência regularmente espaçada de XGate objetos e YGate objetos aparece no circuito.
from qiskit.visualization import timeline_drawer
timeline_drawer(qc_dd, idle_wires=False, target=target)Output:
Por fim, como o YGate não é um portão de base real do nosso backend, aplique manualmente a passagem BasisTranslator (essa é uma passagem padrão, mas é executada antes do agendamento, portanto, precisa ser aplicada novamente). A biblioteca de equivalência de sessão é uma biblioteca de equivalências de circuitos que permite que o transpilador decomponha os circuitos em portas de base, conforme também especificado como um argumento.
from qiskit.circuit.equivalence_library import (
SessionEquivalenceLibrary as sel,
)
from qiskit.transpiler.passes import BasisTranslator
qc_dd = BasisTranslator(sel, basis_gates)(qc_dd)
qc_dd.draw("mpl", fold=-1, idle_wires=False)Output:
Agora, YGate os objetos estão ausentes do nosso circuito e há informações explícitas de temporização na forma de Delay portas. Este circuito transposto com desacoplamento dinâmico está agora pronto para ser enviado para o backend.
Próximas etapas
- Para saber como usar a função
generate_preset_passmanagerem vez de escrever seus próprios passes, comece pelo tópico Definições padrão de transpilação e opções de configuração. - Experimente o guia Comparar configurações do transpiler.
- Consulte a documentação da API Transpile.