Lewati ke konten utama

Classical feedforward dan control flow (dynamic circuits)

Versi paket

Kode di halaman ini dikembangkan menggunakan persyaratan berikut. Kami merekomendasikan menggunakan versi ini atau yang lebih baru.

qiskit[all]~=2.4.0

Dynamic circuits adalah alat yang powerful yang memungkinkan kamu mengukur qubit di tengah eksekusi quantum circuit, lalu melakukan operasi logika klasik di dalam circuit berdasarkan hasil pengukuran mid-circuit tersebut. Proses ini juga dikenal sebagai classical feedforward. Meskipun masih tahap awal dalam memahami cara terbaik memanfaatkan dynamic circuits, komunitas riset kuantum sudah mengidentifikasi sejumlah kasus penggunaan, seperti berikut:

Qiskit mendukung empat konstruk control flow untuk classical feedforward, masing-masing diimplementasikan sebagai metode pada QuantumCircuit. Konstruk dan metode yang sesuai adalah:

Setiap metode ini mengembalikan sebuah context manager dan biasanya digunakan dalam pernyataan with. Sisa panduan ini menjelaskan masing-masing konstruk dan cara menggunakannya.

perhatian

Ada beberapa batasan operasi classical feedforward dan control flow pada hardware kuantum yang mungkin memengaruhi program kamu. Untuk informasi lebih lanjut, lihat Jalankan dynamic circuits.

Pernyataan if

Pernyataan if digunakan untuk melakukan operasi secara kondisional berdasarkan nilai sebuah classical bit atau register.

Pada contoh di bawah, kita menerapkan Hadamard gate pada sebuah qubit dan mengukurnya. Jika hasilnya adalah 1, maka kita menerapkan X gate pada qubit tersebut, yang efeknya adalah membaliknya kembali ke state 0. Kita kemudian mengukur qubit itu lagi. Hasil pengukuran yang dihasilkan seharusnya 0 dengan probabilitas 100%.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
circuit = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)):
circuit.x(q0)
circuit.measure(q0, c0)
circuit.draw("mpl")

# example output counts: {'0': 1024}

Output of the previous code cell

Pernyataan with bisa diberi target penugasan yang berupa context manager itu sendiri, yang bisa disimpan dan kemudian digunakan untuk membuat blok else, yang dieksekusi setiap kali isi blok if tidak dieksekusi.

Pada contoh di bawah, kita menginisialisasi register dengan dua qubit dan dua classical bit. Kita menerapkan Hadamard gate pada qubit pertama dan mengukurnya. Jika hasilnya adalah 1, maka kita menerapkan Hadamard gate pada qubit kedua; jika tidak, kita menerapkan X gate pada qubit kedua. Terakhir, kita juga mengukur qubit kedua.

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

circuit.h(q0)
circuit.measure(q0, c0)
with circuit.if_test((c0, 1)) as else_:
circuit.h(q1)
with else_:
circuit.x(q1)
circuit.measure(q1, c1)

circuit.draw("mpl")

# example output counts: {'01': 260, '11': 272, '10': 492}

Output of the previous code cell

Selain mengondisikan pada satu classical bit, kamu juga bisa mengondisikan pada nilai sebuah classical register yang terdiri dari beberapa bit.

Pada contoh di bawah, kita menerapkan Hadamard gates pada dua qubit dan mengukurnya. Jika hasilnya adalah 01, yaitu qubit pertama adalah 1 dan qubit kedua adalah 0, maka kita menerapkan X gate pada qubit ketiga. Terakhir, kita mengukur qubit ketiga. Perlu dicatat bahwa demi kejelasan, kita memilih untuk menentukan state classical bit ketiga, yaitu 0, dalam kondisi if. Dalam gambar circuit, kondisi ditunjukkan oleh lingkaran pada classical bit yang dijadikan kondisi. Lingkaran solid menunjukkan pengondisian pada 1, sedangkan lingkaran bergaris menunjukkan pengondisian pada 0.

qubits = QuantumRegister(3)
clbits = ClassicalRegister(3)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1, q2) = qubits
(c0, c1, c2) = clbits

circuit.h([q0, q1])
circuit.measure(q0, c0)
circuit.measure(q1, c1)
with circuit.if_test((clbits, 0b001)):
circuit.x(q2)
circuit.measure(q2, c2)

circuit.draw("mpl")

# example output counts: {'101': 269, '011': 260, '000': 252, '010': 243}

Output of the previous code cell

Switch statement

Pernyataan switch digunakan untuk memilih tindakan berdasarkan nilai sebuah classical bit atau register. Ini serupa dengan pernyataan if, namun kamu bisa menentukan lebih banyak case untuk logika percabangan. Contoh di bawah menerapkan Hadamard gate pada sebuah qubit dan mengukurnya. Jika hasilnya adalah 0, terapkan X gate pada qubit tersebut, dan jika hasilnya adalah 1, terapkan Z gate. Hasil pengukuran yang dihasilkan seharusnya 1 dengan probabilitas 100%.

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
circuit = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

circuit.h(q0)
circuit.measure(q0, c0)
with circuit.switch(c0) as case:
with case(0):
circuit.x(q0)
with case(1):
circuit.z(q0)
circuit.measure(q0, c0)

circuit.draw("mpl")

# example output counts: {'1': 1024}

Output of the previous code cell

Karena contoh di atas menggunakan satu classical bit, hanya ada dua kemungkinan case, sehingga kamu bisa mendapatkan hasil yang sama menggunakan pernyataan if-else. Switch case terutama berguna saat melakukan percabangan berdasarkan nilai classical register yang terdiri dari beberapa bit. Contoh berikut menunjukkan cara membuat default case, yang dieksekusi jika tidak ada case sebelumnya yang cocok. Perlu dicatat bahwa dalam pernyataan switch, hanya satu blok yang akan dieksekusi. Tidak ada fallthrough.

Contoh di bawah menerapkan Hadamard gates pada dua qubit dan mengukurnya. Jika hasilnya adalah 00 atau 11, terapkan Z gate pada qubit ketiga. Jika hasilnya adalah 01, terapkan Y gate. Jika tidak ada case sebelumnya yang cocok, terapkan X gate. Terakhir, ukur qubit ketiga.

qubits = QuantumRegister(3)
clbits = ClassicalRegister(3)
circuit = QuantumCircuit(qubits, clbits)
(q0, q1, q2) = qubits
(c0, c1, c2) = clbits

circuit.h([q0, q1])
circuit.measure(q0, c0)
circuit.measure(q1, c1)
with circuit.switch(clbits) as case:
with case(0b000, 0b011):
circuit.z(q2)
with case(0b001):
circuit.y(q2)
with case(case.DEFAULT):
circuit.x(q2)
circuit.measure(q2, c2)

circuit.draw("mpl")

# example output counts: {'101': 267, '110': 249, '011': 265, '000': 243}

Output of the previous code cell

For loop

For loop digunakan untuk mengiterasi sekumpulan nilai klasik dan melakukan beberapa operasi pada setiap iterasi.

Contoh berikut menggunakan for loop untuk menerapkan 5 X gate pada sebuah qubit dan kemudian mengukurnya. Karena dilakukan dalam jumlah ganjil X gate, efek keseluruhannya adalah membalik qubit dari state 0 ke state 1.

qubits = QuantumRegister(1)
clbits = ClassicalRegister(1)
circuit = QuantumCircuit(qubits, clbits)
(q0,) = qubits
(c0,) = clbits

with circuit.for_loop(range(5)) as _:
circuit.x(q0)
circuit.measure(q0, c0)

circuit.draw("mpl")

# example output counts: {'1': 1024}

Output of the previous code cell

While loop

While loop digunakan untuk mengulang instruksi selama suatu kondisi terpenuhi.

Contoh di bawah menerapkan Hadamard gates pada dua qubit dan mengukurnya. Kemudian membuat while loop yang mengulang prosedur ini selama hasil pengukuran adalah 11. Akibatnya, pengukuran akhir seharusnya tidak pernah 11, dengan kemungkinan yang tersisa muncul dengan frekuensi yang kira-kira sama.

qubits = QuantumRegister(2)
clbits = ClassicalRegister(2)
circuit = QuantumCircuit(qubits, clbits)

q0, q1 = qubits
c0, c1 = clbits

circuit.h([q0, q1])
circuit.measure(q0, c0)
circuit.measure(q1, c1)
with circuit.while_loop((clbits, 0b11)):
circuit.h([q0, q1])
circuit.measure(q0, c0)
circuit.measure(q1, c1)

circuit.draw("mpl")

# example output counts: {'01': 334, '10': 368, '00': 322}

Output of the previous code cell

Ekspresi klasik

Modul ekspresi klasik Qiskit qiskit.circuit.classical berisi representasi eksploratif dari operasi runtime pada nilai klasik selama eksekusi circuit.

Contoh berikut menunjukkan bahwa kamu bisa menggunakan perhitungan paritas untuk membuat n-qubit GHZ state menggunakan dynamic circuits. Pertama, buat n/2n/2 pasangan Bell pada qubit yang berdekatan. Kemudian, gabungkan pasangan-pasangan ini menggunakan satu lapisan CNOT gates di antara pasangan. Kamu kemudian mengukur target qubit dari semua CNOT gates sebelumnya dan me-reset setiap qubit yang diukur ke state 0\vert 0 \rangle. Kamu menerapkan XX ke setiap situs yang tidak diukur di mana paritas dari semua bit sebelumnya adalah ganjil. Terakhir, CNOT gates diterapkan pada qubit yang diukur untuk memulihkan entanglement yang hilang saat pengukuran.

Dalam perhitungan paritas, elemen pertama dari ekspresi yang dibangun melibatkan pengangkatan objek Python mr[0] ke sebuah node Value (lift digunakan untuk mengubah objek sembarang menjadi ekspresi klasik). Ini tidak diperlukan untuk mr[1] dan kemungkinan classical register berikutnya, karena keduanya adalah input untuk expr.bit_xor, dan pengangkatan yang diperlukan dilakukan secara otomatis dalam kasus tersebut. Ekspresi semacam itu bisa dibangun dalam loop dan konstruk lainnya.

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

num_qubits = 8
if num_qubits % 2 or num_qubits < 4:
raise ValueError("num_qubits must be an even integer ≥ 4")
meas_qubits = list(range(2, num_qubits, 2)) # qubits to measure and reset

qr = QuantumRegister(num_qubits, "qr")
mr = ClassicalRegister(len(meas_qubits), "m")
qc = QuantumCircuit(qr, mr)

# Create local Bell pairs
qc.reset(qr)
qc.h(qr[::2])
for ctrl in range(0, num_qubits, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])

# Glue neighboring pairs
for ctrl in range(1, num_qubits - 1, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])

# Measure boundary qubits between pairs,reset to 0
for k, q in enumerate(meas_qubits):
qc.measure(qr[q], mr[k])
qc.reset(qr[q])

# Parity-conditioned X corrections
# Each non-measured qubit gets flipped iff the parity (XOR) of all
# preceding measurement bits is 1
for tgt in range(num_qubits):
if tgt in meas_qubits: # skip measured qubits
continue
# all measurement registers whose physical qubit index < tgt
left_bits = [k for k, q in enumerate(meas_qubits) if q < tgt]
if not left_bits: # skip if list empty
continue

# build XOR-parity expression
parity = expr.lift(
mr[left_bits[0]]
) # lift the first bit to Value so it will be treated like a boolean.
for k in left_bits[1:]:
parity = expr.bit_xor(
mr[k], parity
) # calculate parity with all other bits
with qc.if_test(parity): # Add X if parity is 1
qc.x(qr[tgt])

# Re-entangle measured qubits
for ctrl in range(1, num_qubits - 1, 2):
qc.cx(qr[ctrl], qr[ctrl + 1])
qc.draw(output="mpl", style="iqp", idle_wires=False, fold=-1)

Output of the previous code cell

Store

Anda dapat menggunakan instruksi store untuk menyimpan hasil ekspresi klasik, jika ekspresi tersebut akan digunakan berulang kali. Operasi secara otomatis diparalelkan, sehingga kode Anda menjadi jauh lebih efisien saat runtime.

Misalnya, lebih alami dan lebih efisien saat runtime untuk menulis B[0]B[1]B[2]B[0] \oplus B[1] \oplus B[2] \ldots, di mana B=¬AB = \neg A, daripada (¬A[0])(¬A[1])(¬A[2])(\neg A[0]) \oplus (\neg A[1]) \oplus (\neg A[2]) \ldots. Yang pertama menghitung negasi dalam satu langkah paralel sebelum rantai XOR, alih-alih mengevaluasi setiap negasi secara berurutan di dalam ekspresi.

Contoh lengkap:

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

qregs = QuantumRegister(4, "q")
creg = ClassicalRegister(3, "c")
# temp is a plain ClassicalRegister used as the store target
temp = ClassicalRegister(3, "temp")
qc = QuantumCircuit(qregs, creg, temp)

qc.h([0, 1, 2])
qc.measure([0, 1, 2], creg)

# Store bit-NOT of the full 3-bit register into temp
qc.store(temp, expr.bit_not(creg))

# Compute parity of temp using bit-indexed XOR
parity = expr.bit_xor(
expr.bit_xor(expr.index(temp, 0), expr.index(temp, 1)),
expr.index(temp, 2),
)

# Flip q3 if parity of ~creg is 1
with qc.if_test(parity):
qc.x(3)

qc.measure([0, 1, 2], creg)

qc.draw("mpl")

Output of the previous code cell

Langkah selanjutnya

Rekomendasi