Lumaktaw sa pangunahing nilalaman

Classical feedforward at control flow

Mga bersyon ng package

Ang code sa pahinang ito ay ginawa gamit ang mga sumusunod na kinakailangan. Inirerekomenda naming gamitin ang mga bersyong ito o mas bago pa.

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
Ang Dynamic circuits ay available na sa lahat ng backend

Ang bagong bersyon ng dynamic circuits ay available na ngayon sa lahat ng user sa lahat ng backend. Maaari ka na ngayong mag-run ng dynamic circuits sa utility scale. Tingnan ang announcement para sa karagdagang detalye.

Ang dynamic circuits ay makapangyarihang mga tool na maaari mong gamitin para sukatin ang mga qubit sa gitna ng pagpapatakbo ng quantum circuit at pagkatapos ay magsagawa ng mga classical logic operation sa loob ng circuit, batay sa resulta ng mga mid-circuit na pagsukat. Ang prosesong ito ay kilala rin bilang classical feedforward. Bagama't maaga pa lamang ang pag-unawa kung paano pinakamabuti na mapagsamantalahan ang dynamic circuits, ang komunidad ng quantum research ay nakakilala na ng ilang mga use case, tulad ng mga sumusunod:

Ang mga pagpapabuting hatid ng dynamic circuits, gayunpaman, ay may kasamang mga trade-off. Ang mga mid-circuit na pagsukat at classical operations ay karaniwang mas matagal ang oras ng pagpapatupad kaysa sa mga two-qubit gate, at ang pagtaas ng oras na ito ay maaaring mapawalang-bisa ang mga benepisyo ng pinaikling circuit depth. Kaya naman, ang pagpapababa ng haba ng mid-circuit measurement ay isang lugar ng pagpapabuti habang inilalabas ng IBM Quantum® ang bagong bersyon ng dynamic circuits.

Tinutukoy ng OpenQASM 3 specification ang ilang mga control-flow structure, ngunit ang Qiskit Runtime ay kasalukuyang sumusuporta lamang sa conditional na if statement. Sa Qiskit SDK, ito ay tumutugma sa pamamaraang if_test sa QuantumCircuit. Ang pamamaraang ito ay nagbabalik ng isang context manager at karaniwang ginagamit sa isang with statement. Inilalarawan ng gabay na ito kung paano gamitin ang conditional statement na ito.

tala

Ang mga halimbawa ng code sa gabay na ito ay gumagamit ng standard na measure instruction para sa mid-circuit measurements. Gayunpaman, inirerekomenda na gamitin ang MidCircuitMeasure instruction sa halip, kung sinusuportahan ng backend. Tingnan ang dokumentasyon ng Mid-circuit measurements para sa mga detalye.

if statement​

Ginagamit ang if statement para magsagawa ng mga operasyon nang kondisyonal batay sa halaga ng isang classical bit o register.

Sa halimbawa sa ibaba, nag-aaplay kami ng Hadamard gate sa isang qubit at sinusukat ito. Kung ang resulta ay 1, nag-aaplay kami ng X gate sa qubit, na may epektong ibabalik ito sa estado na 0. Pagkatapos ay sinusukat namin ang qubit muli. Ang nagreresultang kinalabasan ng pagsukat ay dapat na 0 na may 100% na posibilidad.

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

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

circuit.h(q0)
# Use MidCircuitMeasure() if it's supported by the backend.
# circuit.append(MidCircuitMeasure(), [q0], [c0])
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

Ang with statement ay maaaring bigyan ng assignment target na isa ring context manager na maaaring i-store at pagkatapos ay gamitin para lumikha ng else block, na isinasagawa tuwing ang mga nilalaman ng if block ay hindi isinasagawa.

Sa halimbawa sa ibaba, nagpapasimula kami ng mga register na may dalawang qubit at dalawang classical bit. Nag-aaplay kami ng Hadamard gate sa unang qubit at sinusukat ito. Kung ang resulta ay 1, nag-aaplay kami ng Hadamard gate sa pangalawang qubit; kung hindi, nag-aaplay kami ng X gate sa pangalawang qubit. Sa wakas, sinusukat namin ang pangalawang qubit din.

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

Bukod sa pag-condition sa isang classical bit, posible rin ang pag-condition sa halaga ng isang classical register na binubuo ng maraming bit.

Sa halimbawa sa ibaba, nag-aaplay kami ng Hadamard gate sa dalawang qubit at sinusukat ang mga ito. Kung ang resulta ay 01, iyon ay, ang unang qubit ay 1 at ang pangalawang qubit ay 0, nag-aaplay kami ng X gate sa ikatlong qubit. Sa wakas, sinusukat namin ang ikatlong qubit. Tandaan na para sa kalinawan, pinili naming tukuyin ang estado ng ikatlong classical bit, na 0, sa kondisyon ng if. Sa drawing ng circuit, ang kondisyon ay ipinahiwatig ng mga bilog sa mga classical bit na kina-condition. Ang isang itim na bilog ay nagpapahiwatig ng pag-condition sa 1, habang ang isang puting bilog ay nagpapahiwatig ng pag-condition sa 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

Mga classical expression​

Ang Qiskit classical expression module na qiskit.circuit.classical ay naglalaman ng eksplorasyon na representasyon ng mga runtime operation sa mga classical value sa panahon ng pagpapatakbo ng circuit. Dahil sa mga limitasyon ng hardware, ang mga kondisyon ng QuantumCircuit.if_test() lamang ang kasalukuyang sinusuportahan.

Ang sumusunod na halimbawa ay nagpapakita na maaari mong gamitin ang pagkalkula ng parity para lumikha ng n-qubit GHZ state gamit ang dynamic circuits. Una, gumawa ng n/2n/2 Bell pairs sa mga katabing qubit. Pagkatapos, idikit ang mga pares na ito gamit ang isang layer ng CNOT gate sa pagitan ng mga pares. Pagkatapos ay susukat ng mga target qubit ng lahat ng naunang CNOT gate at iri-reset ang bawat nasukat na qubit sa estado ∣0⟩\vert 0 \rangle. Mag-aaplay ka ng XX sa bawat hindi nasukat na site kung saan ang parity ng lahat ng naunang bit ay kakaiba. Sa wakas, mga CNOT gate ang ilalapat sa mga nasukat na qubit para muling maitatag ang entanglement na nawala sa pagsukat.

Sa pagkalkula ng parity, ang unang elemento ng nabuong expression ay kinabibilangan ng pag-lift ng Python object na mr[0] sa isang Value node (lift ay ginagamit para gawing mga classical expression ang mga arbitrary na object). Hindi ito kinakailangan para sa mr[1] at sa posibleng susunod na classical register, dahil sila ay mga input sa expr.bit_xor, at ang anumang kinakailangang pag-lift ay awtomatikong ginagawa sa mga kasong ito. Ang mga ganitong expression ay maaaring itayo sa mga loop at iba pang mga construct.

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

Hanapin ang mga backend na sumusuporta sa dynamic circuits​

Para mahanap ang lahat ng backend na maa-access ng iyong account at sumusuporta sa dynamic circuits, patakbuhin ang code tulad ng sumusunod. Ang halimbawang ito ay ipinapalagay na na-save mo ang iyong mga login credentials. Maaari mo ring tahasang tukuyin ang mga credentials kapag sinisimulan ang iyong Qiskit Runtime service account. Papayagan ka nitong tingnan ang mga backend na available sa isang partikular na instance o uri ng plano, halimbawa.

Mga Tala
  • Ang mga backend na available sa account ay depende sa instance na tinukoy sa mga credentials.
  • Ang bagong bersyon ng dynamic circuits ay available na ngayon sa lahat ng user sa lahat ng backend. Tingnan ang announcement para sa karagdagang detalye.
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
dc_backends = service.backends(dynamic_circuits=True)
print(dc_backends)
[<IBMBackend('ibm_pittsburgh')>, <IBMBackend('ibm_boston')>, <IBMBackend('ibm_fez')>, <IBMBackend('ibm_miami')>, <IBMBackend('ibm_marrakesh')>, <IBMBackend('ibm_torino')>, <IBMBackend('ibm_kingston')>]

Mga limitasyon ng Qiskit Runtime​

Alamin ang mga sumusunod na hadlang kapag nagpapatakbo ng dynamic circuits sa Qiskit Runtime.

  • Dahil sa limitadong pisikal na memorya sa control electronics, mayroon ding limitasyon sa bilang ng mga if statement at sukat ng kanilang mga operand. Ang limitasyong ito ay isang function ng bilang ng mga broadcast at bilang ng mga broadcasted na bit sa isang job (hindi isang circuit).

    Kapag nagpoproseso ng kondisyon ng if, ang measurement data ay kailangang ilipat sa control logic para magsagawa ng pagtatasa. Ang isang broadcast ay isang paglipat ng natatanging classical data, at ang broadcasted bits ay ang bilang ng mga classical bit na inililipat. Isaalang-alang ang sumusunod:

    c0 = ClassicalRegister(3)
    c1 = ClassicalRegister(5)
    ...
    with circuit.if_test((c0, 1)) ...
    with circuit.if_test((c0, 3)) ...
    with circuit.if_test((c1[2], 1)) ...

    Sa nakaraang halimbawa ng code, ang unang dalawang if_test object sa c0 ay itinuturing na isang broadcast dahil ang nilalaman ng c0 ay hindi nagbago, kaya hindi na kailangang i-broadcast muli. Ang if_test sa c1 ay isang pangalawang broadcast. Ang una ay nag-broadcast ng lahat ng tatlong bit sa c0 at ang pangalawa ay nag-broadcast ng isang bit lamang, na nagbibigay ng kabuuang apat na broadcasted na bit.

    Sa kasalukuyan, kung mag-broadcast ka ng 60 bit sa bawat pagkakataon, ang job ay maaaring magkaroon ng humigit-kumulang 300 broadcast. Kung mag-broadcast ka ng isang bit lamang sa bawat pagkakataon, gayunpaman, ang job ay maaaring magkaroon ng 2400 broadcast.

  • Ang operand na ginagamit sa isang if_test statement ay dapat na 32 o mas kaunti pang bit. Kaya, kung ikukumpara mo ang buong ClassicalRegister, ang sukat ng ClassicalRegister na iyon ay dapat na 32 o mas kaunti pang bit. Kung ikukumpara mo lamang ang isang bit mula sa isang ClassicalRegister, gayunpaman, ang ClassicalRegister na iyon ay maaaring magkaroon ng anumang sukat (dahil ang operand ay isang bit lamang).

    Halimbawa, ang code block na "Hindi valid" ay hindi gumagana dahil ang cr ay higit sa 32 bit. Maaari mo, gayunpaman, gumamit ng classical register na mas malawak sa 32 bit kung sinusubukan mo lamang ang isang bit, tulad ng ipinakita sa code block na "Valid".

       cr = ClassicalRegister(50)
    qr = QuantumRegister(50)
    circuit = QuantumCircuit(qr, cr)
    ...
    circ.measure(qr, cr)
    with circ.if_test((cr, 15)):
    ...
  • Hindi pinapayagan ang mga nested conditional. Halimbawa, ang sumusunod na code block ay hindi gagana dahil mayroon itong if_test sa loob ng isa pang if_test:

       c1 = ClassicalRegister(1, "c1")
    c2 = ClassicalRegister(2, "c2")
    ...
    with circ.if_test((c1, 1)):
    with circ.if_test(c2, 1)):
    ...
  • Ang pagkakaroon ng reset o mga pagsukat sa loob ng mga conditional ay hindi sinusuportahan.

  • Hindi sinusuportahan ang mga arithmetic operation.

  • Tingnan ang OpenQASM 3 feature table para malaman kung aling mga feature ng OpenQASM 3 ang sinusuportahan sa Qiskit at Qiskit Runtime.

  • Kapag ang OpenQASM 3 (sa halip na QuantumCircuit) ay ginagamit bilang input format para maipasa ang mga circuit sa mga Qiskit Runtime primitive, ang mga instruksyon lamang na maaaring i-load sa Qiskit ang sinusuportahan. Hindi sinusuportahan ang mga classical operation, halimbawa, dahil hindi sila maaaring i-load sa Qiskit. Tingnan ang I-import ang isang OpenQASM 3 program sa Qiskit para sa karagdagang impormasyon.

  • Hindi sinusuportahan ang mga instruksyon na for, while, at switch.

Gamitin ang dynamic circuits kasama ang Estimator​

Dahil hindi sinusuportahan ng Estimator ang dynamic circuits, maaari kang gumamit ng Sampler at bumuo ng iyong sariling mga measurement circuit sa halip. Bilang alternatibo, maaari mong gamitin ang Executor primitive, na sumusuporta sa dynamic circuits.

Para gayahin ang gawi ng Estimator, sundin ang prosesong ito:

  1. I-grupo ang mga termino ng lahat ng observable sa isang partition. Maaari itong gawin sa pamamagitan ng paggamit ng PauliList API, halimbawa.
    tala

    Maaari mong gamitin ang BitArray primitive attribute para kalkulahin ang mga expectation value ng ibinigay na mga observable.

  2. Mag-execute ng isang basis change circuit bawat partition (anumang pagbabago ng basis ang kailangang gawin para sa bawat partition). Tingnan ang Measurement bases addon utility na measurement_bases module para sa karagdagang impormasyon. Magsimula sa mga utility.
  3. Pagsamahin muli ang mga resulta para sa bawat partition.

Mga susunod na hakbang​

Mga Rekomendasyon