Lewati ke konten utama

Resolusi timing yang ditangguhkan menggunakan stretch

Spesifikasi bahasa OpenQASM 3 mengandung tipe stretch yang memungkinkan kamu menentukan timing relatif operasi alih-alih timing absolut. Dukungan untuk stretch sebagai durasi bagi instruksi Delay ditambahkan di Qiskit v2.0.0. Nilai konkret dari durasi stretch diselesaikan pada saat kompilasi, setelah durasi tepat dari gate yang dikalibrasi diketahui. Compiler berusaha meminimalkan durasi stretch, dengan memperhatikan constraint timing pada satu atau lebih Qubit. Dengan ini kamu bisa mengekspresikan desain gate seperti penempatan gate secara merata (misalnya untuk mengimplementasikan urutan echo decoupling tingkat tinggi), left-aligning urutan gate, atau menerapkan gate selama durasi sub-circuit tertentu, tanpa perlu mengetahui timing pastinya.

Contoh​

Dynamical decoupling​

Salah satu kasus penggunaan umum stretch adalah menerapkan dynamical decoupling pada Qubit yang sedang idle sementara Qubit lain menjalani operasi kondisional.

Misalnya, kita bisa menggunakan stretch untuk menerapkan urutan dynamical decoupling XX pada Qubit 1, selama durasi blok kondisional yang diterapkan pada Qubit 0, seperti yang digambarkan diagram berikut:

Gambar yang mengilustrasikan circuit berikut

Circuit yang bersangkutan akan terlihat seperti berikut. Perhatikan bahwa sepasang barrier diperlukan untuk mendefinisikan batas-batas timing relatif ini.

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

Penyelarasan penjadwalan​

Contoh ini menggunakan stretch untuk memastikan urutan gate di antara dua barrier disejajarkan ke kiri, apapun durasi aktualnya:

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

Saat menggunakan stretch dengan Qiskit Runtime, sisa apapun yang dihasilkan dari resolusi stretch ditambahkan ke delay pertama yang menggunakan stretch tersebut.

Contoh:

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)

Kode di atas diselesaikan ke nilai 25 dengan sisa 1. Delay pertama [a] akan mendapat tambahan sisa tersebut.

Persamaan resolusi stretch: a+8+a+8+a+8=100=3βˆ—a+24a + 8 + a + 8 + a + 8 = 100 = 3*a + 24

Lihat nilai stretch di Qiskit Runtime​

Nilai aktual dari durasi stretch diselesaikan pada saat kompilasi, setelah circuit dijadwalkan. Saat menjalankan job Sampler di Qiskit Runtime, kamu bisa melihat nilai stretch yang telah diselesaikan dalam metadata hasil job. Dukungan untuk stretch di Qiskit Runtime saat ini masih eksperimental, jadi kamu perlu mengatur opsi eksperimental terlebih dahulu untuk mengaktifkan pengambilan datanya, lalu mengakses data langsung dari metadata seperti berikut:

# 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'])
catatan

Meskipun total waktu circuit dikembalikan dalam metadata "compilation", ini BUKAN waktu yang digunakan untuk penagihan (quantum time).

Memahami output metadata​

Metadata stretch_values mengembalikan informasi berikut:

  • Name: Nama stretch yang diterapkan.
  • Value: Nilai tujuan yang diminta.
  • Remainder: Sisa dari penyelesaian stretch, yang ditambahkan ke delay pertama yang menggunakan stretch tersebut.
  • Expanded values: Kumpulan nilai yang menentukan awal stretch dan durasinya.

Contoh​

# 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 metadata​

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

Nilai yang dikembalikan untuk durasi bergantung pada nilai tujuan dan sisa yang dihitung. Misalnya, berikut adalah durasi yang dikembalikan untuk foo:

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

Kamu bisa menggunakan visualisasi untuk membantu memahami dan memverifikasi timing.

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

Pada gambar berikut, berdasarkan contoh output, foo berhubungan dengan stretch pada Qubit 2. Delay stretch pertama yang menggunakan foo dimulai di akhir init_play (1365). Durasi stretch adalah 10, sehingga delay tersebut berakhir saat gate x dimulai (1365+10=1375). Kamu bisa menginterpretasikan stretch kedua dan ketiga dengan cara yang sama.

Output dari perintah draw_circuit_schedule_timing ditampilkan.

Gunakan slider di bagian bawah, kontrol di bagian atas (arahkan kursor ke gambar output untuk menampilkannya), dan legenda di samping output untuk menyesuaikan tampilan. Arahkan kursor ke gambar untuk melihat data yang tepat.

Untuk detail lengkap, lihat topik Visualize circuit timing.

Keterbatasan Qiskit Runtime​

Dukungan untuk stretch di Qiskit Runtime saat ini masih eksperimental dan memiliki constraint berikut:

  • Maksimal satu variabel stretch per qubit set di antara barrier (implisit dan eksplisit). Qubit set adalah satu atau lebih Qubit; set-set ini harus saling eksklusif.

    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
  • Area yang dikelilingi oleh sekumpulan barrier disebut barrier region. Variabel stretch tidak bisa digunakan di beberapa barrier region.

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

    Ilustrasi output kode sebelumnya

  • Ekspresi stretch dibatasi pada bentuk X*stretch + Y di mana X dan Y adalah konstanta floating point atau integer.

    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)
  • Ekspresi stretch hanya boleh mengandung satu variabel stretch.

    a = circuit.add_stretch("a")
    b = circuit.add_stretch("b")
    circuit.delay(expr.add(a, b), 0)
  • Ekspresi stretch tidak boleh menghasilkan nilai delay negatif. Solver saat ini tidak menyimpulkan constraint non-negativitas.

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