Přeskočit na hlavní obsah

Odložené rozlišení časování pomocí stretch

Specifikace jazyka OpenQASM 3 obsahuje typ stretch, pomocí kterého můžeš určovat relativní časování operací místo absolutního. Podpora stretch jako dob trvání pro instrukce Delay byla přidána v Qiskit v2.0.0. Konkrétní hodnota doby trvání stretch se rozlišuje v době kompilace, poté co jsou známy přesné doby trvání kalibrovaných Gate. Kompilátor se snaží minimalizovat dobu trvání stretch při splnění časových omezení na jednom nebo více Qubitech. Pak můžeš vyjádřit návrhy Gate jako rovnoměrné rozmísťování Gate (například pro implementaci echo decoupling sekvence vyššího řádu), zarovnání sekvence Gate doleva nebo aplikování Gate po dobu trvání nějakého dílčího Circuit, aniž bys znal přesné časování.

Příklady

Dynamické decoupling

Běžným případem použití stretch je aplikování dynamického decouplingového na nečinný Qubit, zatímco jiný Qubit prochází podmíněnými operacemi.

Pomocí stretch můžeme například aplikovat XX dynamický decoupling na Qubit 1 po dobu trvání podmíněného bloku aplikovaného na Qubit 0, jak ilustruje následující diagram:

Obrázek ilustrující následující Circuit

Odpovídající Circuit by vypadal takto. Všimni si, že k definování hranic tohoto relativního časování je potřeba dvojice bariér.

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

Zarovnání plánování

Tento příklad používá stretch k zajištění toho, aby byla sekvence Gate mezi dvěma bariérami zarovnána doleva, bez ohledu na jejich skutečné doby trvání:

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()
poznámka

Při použití stretch s Qiskit Runtime se jakýkoli zbytek vzniklý rozlišením stretch přičte k prvnímu delay, které stretch používá.

Příklad:

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)

Výše uvedený kód se rozlišuje na hodnotu 25 se zbytkem 1. K prvnímu delay[a] bude přičten zbytek.

Rovnice pro rozlišení stretch: a+8+a+8+a+8=100=3a+24a + 8 + a + 8 + a + 8 = 100 = 3*a + 24

Zobrazení hodnot stretch v Qiskit Runtime

Skutečná hodnota doby trvání stretch se rozlišuje v době kompilace, poté co je Circuit naplánován. Při spuštění úlohy Sampler v Qiskit Runtime můžeš zobrazit rozlišené hodnoty stretch v metadatech výsledku úlohy. Podpora stretch v Qiskit Runtime je momentálně experimentální, takže nejprve musíš nastavit experimentální možnost pro povolení jejího načítání, pak přistupuj k datům přímo z metadat takto:

# 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'])
poznámka

Ačkoli je celková doba Circuit vrácena v metadatech „compilation", NENÍ to čas používaný pro fakturaci (kvantový čas).

Pochopení výstupu metadat

Metadata stretch_values vracejí následující informace:

  • Název: Název aplikovaného stretch.
  • Hodnota: Požadovaná cílová hodnota.
  • Zbytek: Zbytek z rozlišení stretch, který se přičte k prvnímu delay, které stretch používá.
  • Rozvinuté hodnoty: Sady hodnot, které specifikují začátek stretch a jeho dobu trvání.

Příklad

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

Výstup metadat

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

Hodnoty vrácené pro dobu trvání závisí na cílové hodnotě a vypočítaném zbytku. Například pro foo jsou vráceny tyto doby trvání:

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

Pro pochopení a ověření časování můžeš použít vizualizaci.

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

Na následujícím obrázku, na základě ukázkového výstupu, odpovídá foo stretchům na Qubitu 2. První stretch delay, které používá foo, začíná na konci init_play (1365). Doba trvání stretch je 10, takže toto delay končí, když začíná Gate x (1365+10=1375). Druhý a třetí stretch lze interpretovat podobně.

Výstup příkazu draw_circuit_schedule_timing je zobrazen.

Použij posuvníky dole, ovládací prvky nahoře (najetím myší na výstupní obrázek je zobrazíš) a legendu na straně výstupu pro přizpůsobení zobrazení. Najeď myší na obrázek pro zobrazení přesných dat.

Úplné podrobnosti najdeš v tématu Vizualizace časování Circuit.

Omezení Qiskit Runtime

Podpora stretch v Qiskit Runtime je momentálně experimentální a má tato omezení:

  • Nejvýše jedna proměnná stretch na sadu Qubitů mezi bariérami (implicitními i explicitními). Sada Qubitů je jeden nebo více Qubitů; tyto sady musí být navzájem disjunktní.

    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
  • Oblast ohraničená sadou bariér se nazývá oblast bariéry. Proměnnou stretch nelze použít ve více oblastech bariér.

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

    Ilustrace výstupu předchozího kódu

  • Výrazy stretch jsou omezeny na tvar X*stretch + Y, kde X a Y jsou konstanty s plovoucí desetinnou čárkou nebo celá čísla.

    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)
  • Výrazy stretch mohou obsahovat pouze jednu proměnnou stretch.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(expr.add(a, b), 0)
  • Výrazy stretch nesmí vést k záporným hodnotám delay. Aktuální řešič neodvozuje omezení nezápornosti.

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