Langkau ke kandungan utama

Suapan balik klasik dan aliran kawalan (litar dinamik)

Versi pakej

Kod pada halaman ini dibangunkan menggunakan keperluan berikut. Kami mengesyorkan penggunaan versi ini atau yang lebih baharu.

qiskit[all]~=2.4.0

Litar dinamik ialah alat yang berkuasa yang membolehkan anda mengukur qubit di tengah-tengah pelaksanaan Circuit kuantum dan kemudian melakukan operasi logik klasik dalam Circuit, berdasarkan keputusan pengukuran mid-Circuit tersebut. Proses ini juga dikenali sebagai suapan balik klasik. Walaupun ini masih peringkat awal dalam memahami cara terbaik memanfaatkan litar dinamik, komuniti penyelidikan kuantum telah mengenal pasti beberapa kes penggunaan, seperti berikut:

Qiskit menyokong empat konstruk aliran kawalan untuk suapan balik klasik, setiap satu dilaksanakan sebagai kaedah pada QuantumCircuit. Konstruk dan kaedah yang bersesuaian ialah:

Setiap kaedah ini mengembalikan pengurus konteks dan biasanya digunakan dalam pernyataan with. Selebihnya panduan ini menerangkan setiap konstruk ini dan cara menggunakannya.

awas

Terdapat beberapa batasan operasi suapan balik klasik dan aliran kawalan pada perkakasan kuantum yang mungkin memberi kesan kepada program anda. Untuk maklumat lanjut, lihat Laksanakan litar dinamik.

Pernyataan if

Pernyataan if digunakan untuk melaksanakan operasi secara bersyarat berdasarkan nilai bit atau daftar klasik.

Dalam contoh di bawah, kami menggunakan gate Hadamard pada sebuah qubit dan mengukurnya. Jika hasilnya ialah 1, maka kami menggunakan gate X pada qubit tersebut, yang berkesan membalikkannya semula ke keadaan 0. Kemudian kami mengukur qubit itu sekali lagi. Hasil pengukuran seharusnya ialah 0 dengan kebarangkalian 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 boleh diberi sasaran tugasan yang itu sendiri merupakan pengurus konteks yang boleh disimpan dan kemudiannya digunakan untuk mencipta blok else, yang dilaksanakan apabila kandungan blok if tidak dilaksanakan.

Dalam contoh di bawah, kami memulakan daftar dengan dua qubit dan dua bit klasik. Kami menggunakan gate Hadamard pada qubit pertama dan mengukurnya. Jika hasilnya ialah 1, maka kami menggunakan gate Hadamard pada qubit kedua; jika tidak, kami menggunakan gate X pada qubit kedua. Akhirnya, kami mengukur qubit kedua juga.

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 daripada bersyarat pada satu bit klasik, adalah juga boleh bersyarat pada nilai daftar klasik yang terdiri daripada beberapa bit.

Dalam contoh di bawah, kami menggunakan gate Hadamard pada dua qubit dan mengukurnya. Jika hasilnya ialah 01, iaitu qubit pertama ialah 1 dan qubit kedua ialah 0, maka kami menggunakan gate X pada qubit ketiga. Akhirnya, kami mengukur qubit ketiga. Perhatikan bahawa untuk kejelasan, kami memilih untuk menentukan keadaan bit klasik ketiga, iaitu 0, dalam syarat if. Dalam lukisan Circuit, syarat ditunjukkan oleh bulatan pada bit klasik yang dijadikan syarat. Bulatan pepejal menunjukkan syarat pada 1, manakala bulatan bergarisan luar menunjukkan syarat 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

Pernyataan Switch

Pernyataan switch digunakan untuk memilih tindakan berdasarkan nilai bit atau daftar klasik. Ia serupa dengan pernyataan if, tetapi anda boleh menentukan lebih banyak kes untuk logik percabangan. Contoh di bawah menggunakan gate Hadamard pada sebuah qubit dan mengukurnya. Jika hasilnya ialah 0, gunakan gate X pada qubit, dan jika hasilnya ialah 1, gunakan gate Z. Hasil pengukuran seharusnya ialah 1 dengan kebarangkalian 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

Kerana contoh di atas menggunakan satu bit klasik, hanya terdapat dua kes yang mungkin, jadi anda boleh mencapai hasil yang sama menggunakan pernyataan if-else. Kes switch terutamanya berguna apabila percabangan pada nilai daftar klasik yang terdiri daripada beberapa bit. Contoh berikut menunjukkan cara membina kes lalai, yang dilaksanakan jika tiada kes sebelumnya yang sepadan. Perhatikan bahawa dalam pernyataan switch, hanya satu blok yang dilaksanakan. Tiada fallthrough.

Contoh di bawah menggunakan gate Hadamard pada dua qubit dan mengukurnya. Jika hasilnya ialah 00 atau 11, gunakan gate Z pada qubit ketiga. Jika hasilnya ialah 01, gunakan gate Y. Jika tiada kes sebelumnya yang sepadan, gunakan gate X. Akhirnya, 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

Gelung For

Gelung for digunakan untuk melakukan iterasi ke atas urutan nilai klasik dan melakukan beberapa operasi semasa setiap iterasi.

Contoh berikut menggunakan gelung for untuk menggunakan 5 gate X pada sebuah qubit dan kemudian mengukurnya. Kerana ia melakukan bilangan gate X yang ganjil, kesan keseluruhannya ialah membalikkan qubit dari keadaan 0 ke keadaan 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

Gelung While

Gelung while digunakan untuk mengulang arahan selagi sesuatu syarat dipenuhi.

Contoh di bawah menggunakan gate Hadamard pada dua qubit dan mengukurnya. Kemudian ia mencipta gelung while yang mengulang prosedur ini selagi hasil pengukuran ialah 11. Akibatnya, pengukuran akhir tidak seharusnya menjadi 11, dengan kemungkinan yang tinggal muncul dengan kekerapan yang lebih kurang 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

Ungkapan klasik

Modul ungkapan klasik Qiskit qiskit.circuit.classical mengandungi representasi eksperimentasi operasi masa larian pada nilai klasik semasa pelaksanaan Circuit.

Contoh berikut menunjukkan bahawa anda boleh menggunakan pengiraan pariti untuk mencipta keadaan GHZ n-Qubit menggunakan litar dinamik. Pertama, jana n/2n/2 pasangan Bell pada qubit bersebelahan. Kemudian, sambungkan pasangan-pasangan ini menggunakan lapisan gate CNOT di antara pasangan. Anda kemudian mengukur qubit sasaran semua gate CNOT sebelumnya dan menetapkan semula setiap qubit yang diukur ke keadaan 0\vert 0 \rangle. Anda menggunakan XX pada setiap tapak yang tidak diukur di mana pariti semua bit sebelumnya adalah ganjil. Akhirnya, gate CNOT digunakan pada qubit yang diukur untuk memulihkan keterikatan yang hilang dalam pengukuran.

Dalam pengiraan pariti, elemen pertama ungkapan yang dibina melibatkan pengangkatan objek Python mr[0] ke nod Value (lift digunakan untuk menukar objek arbitrari kepada ungkapan klasik). Ini tidak diperlukan untuk mr[1] dan daftar klasik yang mungkin berikutnya, kerana ia adalah input kepada expr.bit_xor, dan sebarang pengangkatan yang diperlukan dilakukan secara automatik dalam kes-kes ini. Ungkapan sedemikian boleh dibina dalam gelung dan konstruk lain.

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 boleh menggunakan arahan store untuk menyimpan hasil ungkapan klasik, jika ungkapan tersebut akan digunakan berulang kali. Operasi diparalelkan secara automatik, menjadikan kod anda jauh lebih cekap semasa masa larian.

Sebagai contoh, adalah lebih semula jadi dan lebih cekap semasa masa larian untuk menulis B[0]B[1]B[2]B[0] \oplus B[1] \oplus B[2] \ldots, di mana B=¬AB = \neg A, berbanding (¬A[0])(¬A[1])(¬A[2])(\neg A[0]) \oplus (\neg A[1]) \oplus (\neg A[2]) \ldots. Yang pertama mengira penafian dalam satu langkah selari sebelum rantaian XOR, bukannya menilai setiap penafian secara berturutan di dalam ungkapan.

Contoh penuh:

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 seterusnya

Cadangan