Skip to main content
IBM Quantum Platform

Risoluzione dei tempi differita con l'uso di stretch

La specifica linguistica 3 dell' OpenQASM contiene un stretch tipo con cui è possibile specificare la temporizzazione relativa delle operazioni invece della temporizzazione assoluta. Il supporto per stretch come durate per Delay istruzioni è stato aggiunto in Qiskit v2.0.0. Il valore concreto di una durata di estensione viene risolto in fase di compilazione, dopo che è nota la durata esatta dei gate calibrati. Il compilatore cerca di ridurre al minimo la durata dell'estensione, tenendo conto dei vincoli temporali su uno o più qubit. È quindi possibile esprimere progetti di gate quali gate con spaziatura uniforme (ad esempio, per implementare una sequenza di disaccoppiamento dell'eco di ordine superiore), allineamento a sinistra di una sequenza di gate o applicazione di un gate per la durata di alcuni sottocircuiti, senza conoscere la temporizzazione esatta.


Esempi

Disaccoppiamento dinamico

Un caso d'uso comune di stretch è quello di applicare il disaccoppiamento dinamico a un qubit inattivo mentre un altro qubit è sottoposto a operazioni condizionali.

Ad esempio, possiamo utilizzare stretch per applicare una sequenza di disaccoppiamento dinamico XX al qubit 1, per la durata del blocco condizionale applicato al qubit 0, come illustrato dal diagramma seguente:

Immagine che illustra il seguente circuito

Il circuito corrispondente è il seguente. Si noti che è necessaria una coppia di barriere per definire i confini di questa temporizzazione relativa.

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()

Allineamento della pianificazione

Questo esempio utilizza stretch per garantire che una sequenza di porte tra due barriere sia allineata a sinistra, indipendentemente dalla loro durata effettiva:

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

Quando si utilizza il servizio Compute di IBM Quantumstretch , eventuali frazioni risultanti da una risoluzione dello stretch vengono aggiunte al primo ritardo che utilizza lo stretch.

Esempio:

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)

Il codice di cui sopra risolve con un valore di 25 e un resto di 1. Al primo ritardo[a] verrà aggiunto il resto.

Equazione di risoluzione dello stiramento: a+8+a+8+a+8=100=3a+24a + 8 + a + 8 + a + 8 = 100 = 3*a + 24


Visualizza i valori di estensione nel servizio di calcolo " IBM Quantum "

Il valore effettivo della durata di uno stretch viene determinato in fase di compilazione, dopo la pianificazione del circuito. Quando si esegue un processo Sampler in un servizio di elaborazion IBM Quantum, è possibile visualizzare i valori di estensione risolti nei metadati dei risultati del processo. Il supporto per stretch in Quantum Compute è attualmente in fase sperimentale, pertanto è necessario innanzitutto impostare un'opzione sperimentale per abilitarne il recupero, quindi accedere ai dati direttamente dai metadati come segue:

# 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

Sebbene il tempo totale di esecuzione del circuito sia riportato nei metadati "compilation", NON si tratta del tempo utilizzato ai fini della fatturazione (tempo QPU).

Comprendere l'output dei metadati

I stretch_values metadati restituiscono le seguenti informazioni:

  • Nome: Il nome dell'estensione applicata.
  • Valore: il valore dell'obiettivo richiesto.
  • Resto: il resto risultante dalla risoluzione dell'allungamento, che viene aggiunto al primo ritardo che utilizza l'allungamento.
  • Valori espansi: insiemi di valori che specificano l'inizio dell'allungamento e la sua durata.

Esempio

# 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()

Output dei metadati

 [{'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]]}
  ]

I valori restituiti per la durata dipendono dal valore dell'obiettivo e dal resto calcolato. Ad esempio, queste sono le durate restituite per foo:

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

È possibile utilizzare una visualizzazione per comprendere e verificare la tempistica.

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

Nell'immagine seguente, basata sull'output di esempio, foo corrisponde agli allungamenti su Qubit 2. Il primo ritardo di allungamento che utilizza foo inizia alla fine del init_play (1365). La durata dell'estensione è 10, quindi il ritardo termina quando inizia il x gate (1365+10=1375). È possibile interpretare il secondo e il terzo tratto in modo simile.

Viene visualizzato il risultato del comando draw_circuit_schedule_timing.

Utilizza i cursori nella parte inferiore, i controlli nella parte superiore (passa con il mouse sull'immagine di output per visualizzarli) e la legenda sul lato dell'output per personalizzare la visualizzazione. Passa il mouse sull'immagine per visualizzare i dati esatti.

Per ulteriori dettagli, consultare la sezione "Visualizzazione dei tempi dei circuiti ".


Limiti del calcolo quantistico

Il supporto per in stretch Quantum Compute è attualmente in fase sperimentale e presenta i seguenti limiti:

  • Al massimo una variabile di tratto per ogni qubit impostato tra le barriere (implicite ed esplicite). Un insieme di qubit è uno o più qubit; questi insiemi devono essere mutuamente esclusivi.

    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
  • L'area circondata da un insieme di barriere è chiamata regione barriera. Una variabile di tipo stretch non può essere utilizzata in più regioni barriera.

    # 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))
    Illustrazione del risultato del codice precedente
    : uso non corretto della funzione stretch nelle regioni di barriera
  • Le espressioni stretch sono limitate a quelle della forma X*stretch + Y dove X e Y sono costanti in virgola mobile o interi.

    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)
  • Le espressioni di stiramento possono includere una sola variabile di stiramento.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(expr.add(a, b), 0)
  • Le espressioni stretch non possono risolvere con valori di ritardo negativi. Il solutore attuale non deduce i vincoli di non negatività.

    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))
Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.