Skip to main content
IBM Quantum Platform

Resolução de tempo diferida usando alongamento

A especificação da linguagem 3 do OpenQASM contém um stretch tipo com o qual você pode especificar o tempo relativo das operações em vez do tempo absoluto. O suporte para durações stretch como instruções Delay foi adicionado no Qiskit v2.0.0. O valor concreto de uma duração de trecho é resolvido em tempo de compilação, após a duração exata dos portões calibrados ser conhecida. O compilador tenta minimizar a duração do alongamento, sujeito a restrições de tempo em um ou mais qubits. Você pode então expressar projetos de portas, como portas com espaçamento uniforme (por exemplo, para implementar uma sequência de desacoplamento de eco de ordem superior), alinhar à esquerda uma sequência de portas ou aplicar uma porta durante a duração de algum subcircuito, sem saber o tempo exato.


Exemplos

Desacoplamento dinâmico

Um caso de uso comum do stretch é aplicar o desacoplamento dinâmico a um qubit ocioso enquanto outro qubit está sendo submetido a operações condicionais.

Por exemplo, podemos usar o site stretch para aplicar uma sequência de desacoplamento dinâmico XX ao qubit 1, durante a duração do bloco condicional aplicado ao qubit 0, conforme ilustrado no diagrama a seguir:

Imagem que ilustra o circuito a seguir

O circuito correspondente seria parecido com o seguinte. Observe que é necessário um par de barreiras para definir os limites desse tempo relativo.

from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit.classical import expr

qubits = QuantumRegister(2)
clbits = ClassicalRegister(2)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1) = qubits
(c0, c1) = clbits

# Add barriers to define the boundaries
circuit.barrier()
circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)) as else_:
    circuit.h(q0)
with else_:
    circuit.x(q0)

# Apply an XX DD sequence with stretch on qubit 1
s = circuit.add_stretch("s")
circuit.delay(s, q1)
circuit.x(q1)
circuit.delay(expr.mul(s, 2), q1)
circuit.x(q1)
circuit.delay(s, q1)
circuit.barrier()

Alinhamento de programação

Este exemplo usa o site stretch para garantir que uma sequência de portas entre duas barreiras seja alinhada à esquerda, independentemente de suas durações reais:

from qiskit import QuantumCircuit
from numpy import pi

qc = QuantumCircuit(5)
qc.barrier()
qc.cx(0, 1)
qc.u(pi/4, 0, pi/2, 2)
qc.cx(3, 4)

a = qc.add_stretch("a")
b = qc.add_stretch("b")
c = qc.add_stretch("c")

# Use the stretches as Delay duration.
qc.delay(a, [0, 1])
qc.delay(b, 2)
qc.delay(c, [3, 4])
qc.barrier()
Note

Ao usar stretch com Qiskit Runtime, qualquer resto resultante de uma resolução de alongamento é adicionado ao primeiro atraso que usa o alongamento.

Exemplo:

a = circuit.add_stretch("a")
circuit.barrier(q0, q1)
circuit.delay(100, q0)
circuit.delay(a, q1)  # resolve to 26
circuit.x(q1)  # duration: 8
circuit.delay(a, q1)  # resolve to 25
circuit.x(q1)  # duration: 8
circuit.delay(a, q1)  # resolve to 25
circuit.x(q1)  # duration: 8
circuit.barrier(q0, q1)

O código acima resulta em um valor de 25 com um resto de 1. O primeiro atraso[a] terá o restante adicionado.

Equação de resolução de estiramento: a+8+a+8+a+8=100=3a+24a + 8 + a + 8 + a + 8 = 100 = 3*a + 24


Visualizar valores de extensão em Qiskit Runtime

O valor real de uma duração de estiramento é resolvido no momento da compilação, após o circuito ser programado. Ao executar uma tarefa do Sampler em Qiskit Runtime, você pode visualizar os valores de extensão resolvidos nos metadados do resultado da tarefa. O suporte para stretch em Qiskit Runtime é atualmente experimental, portanto, você precisa primeiro definir uma opção experimental para habilitar sua recuperação e, em seguida, acessar os dados diretamente dos metadados da seguinte maneira:

# Enable stretch value retrieval.
sampler.options.experimental = {
    "execution": {
        "stretch_values": True,
        "scheduler_timing": True,
    },
}

# Access the stretch values from the metadata.
job_result = job.result()
circuit_stretch_values = (
    job_result[0].metadata["compilation"]["stretch_values"]
    )

# Visualize the timing.
# Use the sliders at the bottom, the controls at the top, and the 
# legend on the side of the output to customize the view.
draw_circuit_schedule_timing(ob.result()[0].metadata['compilation']
    ['scheduler_timing']['timing'])
Note

Embora o tempo total de execução do circuito seja informado nos metadados de "compilação", esse NÃO é o tempo utilizado para fins de cobrança (tempo de QPU).

Entenda a saída de metadados

Os stretch_values metadados retornam as seguintes informações:

  • Nome: O nome do alongamento aplicado.
  • Valor: O valor da meta solicitada.
  • Remanesecente: O remanescente da resolução do alongamento, que é adicionado ao primeiro atraso que utiliza o alongamento.
  • Valores expandidos: conjuntos de valores que especificam o início do alongamento e sua duração.

Exemplo

# Define the circuit
circuit = QuantumCircuit(4)
foo = circuit.add_stretch("foo")
bar = circuit.add_stretch("bar")
circuit.barrier()
circuit.cz(0, 1)
circuit.cz(0, 1)
circuit.cz(0, 1)
circuit.cz(0, 1)

circuit.delay(foo, 2)
circuit.x(2)
# 3*foo
circuit.delay(expr.mul(3, foo), 2)
circuit.x(2)
# 2*foo
circuit.delay(expr.mul(2, foo), 2)

circuit.delay(bar, 3)
circuit.x(3)
circuit.delay(bar, 3)

circuit.measure_all()

Saída de metadados

 [{'name': 'bar',
  'value': 29,
  'remainder': 1,
  'expanded_values': [[1365, 30], [1404, 29]]},
 {'name': 'foo',
  'value': 8,
  'remainder': 2,
  'expanded_values': [[1365, 10], [1384, 24], [1417, 16]]}
  ]

Os valores retornados para a duração dependem do valor da meta e do restante calculado. Por exemplo, estas são as durações retornadas para foo:

  • foo value + remainder (8+2 = 10)
  • foo value * 3 (8 x 3 = 24)
  • foo value * 2 (8 x 2 = 16)

Você pode usar uma visualização para ajudar a entender e verificar o tempo.

draw_circuit_schedule_timing(job.result()[0].metadata
    ['compilation']['scheduler_timing']['timing'])

Na imagem a seguir, com base no exemplo de saída, foo corresponde aos trechos no Qubit 2. O primeiro atraso de alongamento que usa foo começa no final do init_play (1365). A duração do intervalo é 10, de modo que o atraso termina quando o x portão é acionado (1365+10=1375). Você pode interpretar o segundo e o terceiro trechos de forma semelhante.

A saída do comando draw_circuit_schedule_timing é exibida.

Use os controles deslizantes na parte inferior, os controles na parte superior (passe o mouse sobre a imagem de saída para revelá-los) e a legenda ao lado da saída para personalizar a visualização. Passe o cursor sobre a imagem para visualizar os dados exatos.

Para obter mais detalhes, consulte o tópico “Visualização do tempo de resposta do circuito ”.


Qiskit Runtime limitações

O suporte para stretch em Qiskit Runtime é atualmente experimental e tem as seguintes restrições:

  • No máximo uma variável de extensão por qubit definido entre barreiras (implícitas e explícitas). Um conjunto de qubits é um ou mais qubits; esses conjuntos devem ser mutuamente exclusivos.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(a, (q0, q1))
    circuit.delay(b, q0)  # Invalid because 2 stretches are applied on q0
  • A área cercada por um conjunto de barreiras é chamada de região de barreira. Uma variável de extensão não pode ser usada em várias regiões de barreira.

    # Stretch a is used in two barrier regions
    a = circuit.add_stretch("a")
    circuit.barrier((q0, q1))
    circuit.delay(a, q0)
    circuit.barrier((q0, q1))
    circuit.delay(a, q0)
    circuit.barrier((q0, q1))
    Ilustração do resultado
    do código anterior: uso inválido da função stretch em regiões de barreira
  • As expressões de alongamento são limitadas àquelas do formato X*stretch + Y em que X e Y são constantes de ponto flutuante ou inteiras.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    c = circuit.add_stretch("c")
    
    # (a /  b) * c is not supported
    circuit.delay(expr.mul(expr.div(a, b), c), q1)
  • As expressões de alongamento só podem incluir uma única variável de alongamento.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(expr.add(a, b), 0)
  • As expressões de alongamento não podem ser resolvidas para valores de atraso negativos. O solucionador atual não infere restrições de não negatividade.

    from qiskit.circuit import Duration
    
    circuit.barrier((q0, q1))
    circuit.delay(20, q1)
    # The length of this barrier region is 20dt, meaning the
    # equation for solving stretch 'a' is a + 40dt = 20dt, giving a = -20dt.
    circuit.delay(expr.add(a, Duration.dt(40)), q0)
    circuit.barrier((q0, q1))
Esta página foi útil?
Relate um bug, erro de digitação ou solicite conteúdo no GitHub.